From df891e0d9e1538373302df608504ed2e9213ab06 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Fri, 13 Jan 2017 21:04:13 -0500 Subject: [PATCH 0001/1534] Backport LLVM patches to fix X86 partial register stall Fix #19976 --- deps/llvm.mk | 7 +- deps/patches/llvm-PR276266.patch | 51 ++ deps/patches/llvm-PR277939.patch | 169 ++++ deps/patches/llvm-PR278088.patch | 224 +++++ deps/patches/llvm-PR278321.patch | 1409 ++++++++++++++++++++++++++++++ deps/patches/llvm-PR278923.patch | 69 ++ 6 files changed, 1928 insertions(+), 1 deletion(-) create mode 100644 deps/patches/llvm-PR276266.patch create mode 100644 deps/patches/llvm-PR277939.patch create mode 100644 deps/patches/llvm-PR278088.patch create mode 100644 deps/patches/llvm-PR278321.patch create mode 100644 deps/patches/llvm-PR278923.patch diff --git a/deps/llvm.mk b/deps/llvm.mk index d01ea5fc1d45f..387c4ba5f82ee 100644 --- a/deps/llvm.mk +++ b/deps/llvm.mk @@ -488,7 +488,7 @@ $(eval $(call LLVM_PATCH,llvm-r282182)) # Remove for 4.0 $(eval $(call LLVM_PATCH,llvm-3.9.0_cygwin)) # R283427, Remove for 4.0 endif $(eval $(call LLVM_PATCH,llvm-PR22923)) # Remove for 4.0 -$(eval $(call LLVM_PATCH,llvm-arm-fix-prel31)) +$(eval $(call LLVM_PATCH,llvm-arm-fix-prel31)) # Remove for 4.0 $(eval $(call LLVM_PATCH,llvm-D25865-cmakeshlib)) # Remove for 4.0 # Cygwin and openSUSE still use win32-threads mingw, https://llvm.org/bugs/show_bug.cgi?id=26365 $(eval $(call LLVM_PATCH,llvm-3.9.0_threads)) @@ -505,6 +505,11 @@ $(eval $(call LLVM_PATCH,llvm-D27397)) # Julia issue #19792, Remove for 4.0 $(eval $(call LLVM_PATCH,llvm-D28009)) # Julia issue #19792, Remove for 4.0 $(eval $(call LLVM_PATCH,llvm-D28215_FreeBSD_shlib)) $(eval $(call LLVM_PATCH,llvm-D28221-avx512)) # mentioned in issue #19797 +$(eval $(call LLVM_PATCH,llvm-PR276266)) # Issue #19976, Remove for 4.0 +$(eval $(call LLVM_PATCH,llvm-PR278088)) # Issue #19976, Remove for 4.0 +$(eval $(call LLVM_PATCH,llvm-PR277939)) # Issue #19976, Remove for 4.0 +$(eval $(call LLVM_PATCH,llvm-PR278321)) # Issue #19976, Remove for 4.0 +$(eval $(call LLVM_PATCH,llvm-PR278923)) # Issue #19976, Remove for 4.0 endif # LLVM_VER ifeq ($(LLVM_VER),3.7.1) diff --git a/deps/patches/llvm-PR276266.patch b/deps/patches/llvm-PR276266.patch new file mode 100644 index 0000000000000..576e96e5836d3 --- /dev/null +++ b/deps/patches/llvm-PR276266.patch @@ -0,0 +1,51 @@ +From 64d1e8b748bca22ce205eab7634cc5418c827f18 Mon Sep 17 00:00:00 2001 +From: Marina Yatsina +Date: Thu, 21 Jul 2016 12:37:07 +0000 +Subject: [PATCH 3/5] ExecutionDepsFix - Fix bug in clearance calculation + +The clearance calculation did not take into account registers defined as outputs or clobbers in inline assembly machine instructions because these register defs are implicit. + +Differential Revision: http://reviews.llvm.org/D22580 + + + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@276266 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + lib/CodeGen/ExecutionDepsFix.cpp | 2 -- + test/CodeGen/X86/break-false-dep.ll | 10 ++++++++++ + 2 files changed, 10 insertions(+), 2 deletions(-) + +diff --git a/lib/CodeGen/ExecutionDepsFix.cpp b/lib/CodeGen/ExecutionDepsFix.cpp +index 566b8d507b2..1fe5f459b69 100644 +--- a/lib/CodeGen/ExecutionDepsFix.cpp ++++ b/lib/CodeGen/ExecutionDepsFix.cpp +@@ -520,8 +520,6 @@ void ExeDepsFix::processDefs(MachineInstr *MI, bool Kill) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) + continue; +- if (MO.isImplicit()) +- break; + if (MO.isUse()) + continue; + for (int rx : regIndices(MO.getReg())) { +diff --git a/test/CodeGen/X86/break-false-dep.ll b/test/CodeGen/X86/break-false-dep.ll +index 74a0728f918..a7cda499dab 100644 +--- a/test/CodeGen/X86/break-false-dep.ll ++++ b/test/CodeGen/X86/break-false-dep.ll +@@ -199,3 +199,13 @@ for.end16: ; preds = %for.inc14 + ;AVX-NEXT: vmulsd {{.*}}, [[XMM0]], [[XMM0]] + ;AVX-NEXT: vmovsd [[XMM0]], + } ++ ++define double @inlineasmdep(i64 %arg) { ++top: ++ tail call void asm sideeffect "", "~{xmm0},~{dirflag},~{fpsr},~{flags}"() ++ %tmp1 = sitofp i64 %arg to double ++ ret double %tmp1 ++;AVX-LABEL:@inlineasmdep ++;AVX: vxorps [[XMM0:%xmm[0-9]+]], [[XMM0]], [[XMM0]] ++;AVX-NEXT: vcvtsi2sdq {{.*}}, [[XMM0]], {{%xmm[0-9]+}} ++} +-- +2.11.0 + diff --git a/deps/patches/llvm-PR277939.patch b/deps/patches/llvm-PR277939.patch new file mode 100644 index 0000000000000..65e46c32b4848 --- /dev/null +++ b/deps/patches/llvm-PR277939.patch @@ -0,0 +1,169 @@ +From 9790ab8bccdbc71dfcc166860ab6ce9c369bf686 Mon Sep 17 00:00:00 2001 +From: Simon Pilgrim +Date: Sat, 6 Aug 2016 21:21:12 +0000 +Subject: [PATCH 1/5] [X86][AVX2] Improve sign/zero extension on AVX2 targets + +Split extensions to large vectors into 256-bit chunks - the equivalent of what we do with pre-AVX2 into 128-bit chunks + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@277939 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + lib/Target/X86/X86ISelLowering.cpp | 22 +++++++++++++++------- + test/CodeGen/X86/vec_int_to_fp.ll | 24 ++++++++---------------- + test/CodeGen/X86/vector-sext.ll | 10 ++-------- + 3 files changed, 25 insertions(+), 31 deletions(-) + +diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp +index ca205335013..2bbedd4bd97 100644 +--- a/lib/Target/X86/X86ISelLowering.cpp ++++ b/lib/Target/X86/X86ISelLowering.cpp +@@ -30164,11 +30164,9 @@ static SDValue combineToExtendVectorInReg(SDNode *N, SelectionDAG &DAG, + : DAG.getZeroExtendVectorInReg(ExOp, DL, VT); + } + +- // On pre-AVX2 targets, split into 128-bit nodes of +- // ISD::*_EXTEND_VECTOR_INREG. +- if (!Subtarget.hasInt256() && !(VT.getSizeInBits() % 128)) { +- unsigned NumVecs = VT.getSizeInBits() / 128; +- unsigned NumSubElts = 128 / SVT.getSizeInBits(); ++ auto SplitAndExtendInReg = [&](unsigned SplitSize) { ++ unsigned NumVecs = VT.getSizeInBits() / SplitSize; ++ unsigned NumSubElts = SplitSize / SVT.getSizeInBits(); + EVT SubVT = EVT::getVectorVT(*DAG.getContext(), SVT, NumSubElts); + EVT InSubVT = EVT::getVectorVT(*DAG.getContext(), InSVT, NumSubElts); + +@@ -30176,14 +30174,24 @@ static SDValue combineToExtendVectorInReg(SDNode *N, SelectionDAG &DAG, + for (unsigned i = 0, Offset = 0; i != NumVecs; ++i, Offset += NumSubElts) { + SDValue SrcVec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, InSubVT, N0, + DAG.getIntPtrConstant(Offset, DL)); +- SrcVec = ExtendVecSize(DL, SrcVec, 128); ++ SrcVec = ExtendVecSize(DL, SrcVec, SplitSize); + SrcVec = Opcode == ISD::SIGN_EXTEND + ? DAG.getSignExtendVectorInReg(SrcVec, DL, SubVT) + : DAG.getZeroExtendVectorInReg(SrcVec, DL, SubVT); + Opnds.push_back(SrcVec); + } + return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, Opnds); +- } ++ }; ++ ++ // On pre-AVX2 targets, split into 128-bit nodes of ++ // ISD::*_EXTEND_VECTOR_INREG. ++ if (!Subtarget.hasInt256() && !(VT.getSizeInBits() % 128)) ++ return SplitAndExtendInReg(128); ++ ++ // On pre-AVX512 targets, split into 256-bit nodes of ++ // ISD::*_EXTEND_VECTOR_INREG. ++ if (!Subtarget.hasAVX512() && !(VT.getSizeInBits() % 256)) ++ return SplitAndExtendInReg(256); + + return SDValue(); + } +diff --git a/test/CodeGen/X86/vec_int_to_fp.ll b/test/CodeGen/X86/vec_int_to_fp.ll +index 43f5318a607..5d8f91385c7 100644 +--- a/test/CodeGen/X86/vec_int_to_fp.ll ++++ b/test/CodeGen/X86/vec_int_to_fp.ll +@@ -153,8 +153,7 @@ define <2 x double> @sitofp_16i8_to_2f64(<16 x i8> %a) { + ; + ; AVX2-LABEL: sitofp_16i8_to_2f64: + ; AVX2: # BB#0: +-; AVX2-NEXT: vpmovsxbw %xmm0, %ymm0 +-; AVX2-NEXT: vpmovsxwd %xmm0, %ymm0 ++; AVX2-NEXT: vpmovsxbd %xmm0, %ymm0 + ; AVX2-NEXT: vcvtdq2pd %xmm0, %ymm0 + ; AVX2-NEXT: # kill + ; AVX2-NEXT: vzeroupper +@@ -325,8 +324,7 @@ define <4 x double> @sitofp_16i8_to_4f64(<16 x i8> %a) { + ; + ; AVX2-LABEL: sitofp_16i8_to_4f64: + ; AVX2: # BB#0: +-; AVX2-NEXT: vpmovsxbw %xmm0, %ymm0 +-; AVX2-NEXT: vpmovsxwd %xmm0, %ymm0 ++; AVX2-NEXT: vpmovsxbd %xmm0, %ymm0 + ; AVX2-NEXT: vcvtdq2pd %xmm0, %ymm0 + ; AVX2-NEXT: retq + %cvt = sitofp <16 x i8> %a to <16 x double> +@@ -543,8 +541,7 @@ define <2 x double> @uitofp_16i8_to_2f64(<16 x i8> %a) { + ; + ; AVX2-LABEL: uitofp_16i8_to_2f64: + ; AVX2: # BB#0: +-; AVX2-NEXT: vpmovzxbw {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero,xmm0[8],zero,xmm0[9],zero,xmm0[10],zero,xmm0[11],zero,xmm0[12],zero,xmm0[13],zero,xmm0[14],zero,xmm0[15],zero +-; AVX2-NEXT: vpmovzxwd {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ++; AVX2-NEXT: vpmovzxbd {{.*#+}} ymm0 = xmm0[0],zero,zero,zero,xmm0[1],zero,zero,zero,xmm0[2],zero,zero,zero,xmm0[3],zero,zero,zero,xmm0[4],zero,zero,zero,xmm0[5],zero,zero,zero,xmm0[6],zero,zero,zero,xmm0[7],zero,zero,zero + ; AVX2-NEXT: vcvtdq2pd %xmm0, %ymm0 + ; AVX2-NEXT: # kill + ; AVX2-NEXT: vzeroupper +@@ -778,8 +775,7 @@ define <4 x double> @uitofp_16i8_to_4f64(<16 x i8> %a) { + ; + ; AVX2-LABEL: uitofp_16i8_to_4f64: + ; AVX2: # BB#0: +-; AVX2-NEXT: vpmovzxbw {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero,xmm0[8],zero,xmm0[9],zero,xmm0[10],zero,xmm0[11],zero,xmm0[12],zero,xmm0[13],zero,xmm0[14],zero,xmm0[15],zero +-; AVX2-NEXT: vpmovzxwd {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ++; AVX2-NEXT: vpmovzxbd {{.*#+}} ymm0 = xmm0[0],zero,zero,zero,xmm0[1],zero,zero,zero,xmm0[2],zero,zero,zero,xmm0[3],zero,zero,zero,xmm0[4],zero,zero,zero,xmm0[5],zero,zero,zero,xmm0[6],zero,zero,zero,xmm0[7],zero,zero,zero + ; AVX2-NEXT: vcvtdq2pd %xmm0, %ymm0 + ; AVX2-NEXT: retq + %cvt = uitofp <16 x i8> %a to <16 x double> +@@ -958,8 +954,7 @@ define <4 x float> @sitofp_16i8_to_4f32(<16 x i8> %a) { + ; + ; AVX2-LABEL: sitofp_16i8_to_4f32: + ; AVX2: # BB#0: +-; AVX2-NEXT: vpmovsxbw %xmm0, %ymm0 +-; AVX2-NEXT: vpmovsxwd %xmm0, %ymm0 ++; AVX2-NEXT: vpmovsxbd %xmm0, %ymm0 + ; AVX2-NEXT: vcvtdq2ps %ymm0, %ymm0 + ; AVX2-NEXT: # kill + ; AVX2-NEXT: vzeroupper +@@ -1134,8 +1129,7 @@ define <8 x float> @sitofp_16i8_to_8f32(<16 x i8> %a) { + ; + ; AVX2-LABEL: sitofp_16i8_to_8f32: + ; AVX2: # BB#0: +-; AVX2-NEXT: vpmovsxbw %xmm0, %ymm0 +-; AVX2-NEXT: vpmovsxwd %xmm0, %ymm0 ++; AVX2-NEXT: vpmovsxbd %xmm0, %ymm0 + ; AVX2-NEXT: vcvtdq2ps %ymm0, %ymm0 + ; AVX2-NEXT: retq + %cvt = sitofp <16 x i8> %a to <16 x float> +@@ -1456,8 +1450,7 @@ define <4 x float> @uitofp_16i8_to_4f32(<16 x i8> %a) { + ; + ; AVX2-LABEL: uitofp_16i8_to_4f32: + ; AVX2: # BB#0: +-; AVX2-NEXT: vpmovzxbw {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero,xmm0[8],zero,xmm0[9],zero,xmm0[10],zero,xmm0[11],zero,xmm0[12],zero,xmm0[13],zero,xmm0[14],zero,xmm0[15],zero +-; AVX2-NEXT: vpmovzxwd {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ++; AVX2-NEXT: vpmovzxbd {{.*#+}} ymm0 = xmm0[0],zero,zero,zero,xmm0[1],zero,zero,zero,xmm0[2],zero,zero,zero,xmm0[3],zero,zero,zero,xmm0[4],zero,zero,zero,xmm0[5],zero,zero,zero,xmm0[6],zero,zero,zero,xmm0[7],zero,zero,zero + ; AVX2-NEXT: vcvtdq2ps %ymm0, %ymm0 + ; AVX2-NEXT: # kill + ; AVX2-NEXT: vzeroupper +@@ -1813,8 +1806,7 @@ define <8 x float> @uitofp_16i8_to_8f32(<16 x i8> %a) { + ; + ; AVX2-LABEL: uitofp_16i8_to_8f32: + ; AVX2: # BB#0: +-; AVX2-NEXT: vpmovzxbw {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero,xmm0[8],zero,xmm0[9],zero,xmm0[10],zero,xmm0[11],zero,xmm0[12],zero,xmm0[13],zero,xmm0[14],zero,xmm0[15],zero +-; AVX2-NEXT: vpmovzxwd {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ++; AVX2-NEXT: vpmovzxbd {{.*#+}} ymm0 = xmm0[0],zero,zero,zero,xmm0[1],zero,zero,zero,xmm0[2],zero,zero,zero,xmm0[3],zero,zero,zero,xmm0[4],zero,zero,zero,xmm0[5],zero,zero,zero,xmm0[6],zero,zero,zero,xmm0[7],zero,zero,zero + ; AVX2-NEXT: vcvtdq2ps %ymm0, %ymm0 + ; AVX2-NEXT: retq + %cvt = uitofp <16 x i8> %a to <16 x float> +diff --git a/test/CodeGen/X86/vector-sext.ll b/test/CodeGen/X86/vector-sext.ll +index 018c5922a43..e29f3e5f91f 100644 +--- a/test/CodeGen/X86/vector-sext.ll ++++ b/test/CodeGen/X86/vector-sext.ll +@@ -407,15 +407,9 @@ define <8 x i64> @sext_16i8_to_8i64(<16 x i8> %A) nounwind uwtable readnone ssp + ; + ; AVX2-LABEL: sext_16i8_to_8i64: + ; AVX2: # BB#0: # %entry +-; AVX2-NEXT: vpmovzxbd {{.*#+}} xmm1 = xmm0[0],zero,zero,zero,xmm0[1],zero,zero,zero,xmm0[2],zero,zero,zero,xmm0[3],zero,zero,zero +-; AVX2-NEXT: vpslld $24, %xmm1, %xmm1 +-; AVX2-NEXT: vpsrad $24, %xmm1, %xmm1 +-; AVX2-NEXT: vpmovsxdq %xmm1, %ymm2 ++; AVX2-NEXT: vpmovsxbq %xmm0, %ymm2 + ; AVX2-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[1,1,2,3] +-; AVX2-NEXT: vpmovzxbd {{.*#+}} xmm0 = xmm0[0],zero,zero,zero,xmm0[1],zero,zero,zero,xmm0[2],zero,zero,zero,xmm0[3],zero,zero,zero +-; AVX2-NEXT: vpslld $24, %xmm0, %xmm0 +-; AVX2-NEXT: vpsrad $24, %xmm0, %xmm0 +-; AVX2-NEXT: vpmovsxdq %xmm0, %ymm1 ++; AVX2-NEXT: vpmovsxbq %xmm0, %ymm1 + ; AVX2-NEXT: vmovdqa %ymm2, %ymm0 + ; AVX2-NEXT: retq + ; +-- +2.11.0 + diff --git a/deps/patches/llvm-PR278088.patch b/deps/patches/llvm-PR278088.patch new file mode 100644 index 0000000000000..325069326b3ed --- /dev/null +++ b/deps/patches/llvm-PR278088.patch @@ -0,0 +1,224 @@ +From b01ff685400365f55c5333c29c2227842d61e984 Mon Sep 17 00:00:00 2001 +From: Craig Topper +Date: Tue, 9 Aug 2016 03:06:26 +0000 +Subject: [PATCH 2/5] [X86] Remove unnecessary bitcast from the front of + AVX1Only 256-bit logical operation patterns. + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@278088 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + lib/Target/X86/X86InstrSSE.td | 8 +++---- + test/CodeGen/X86/WidenArith.ll | 2 +- + test/CodeGen/X86/merge-consecutive-loads-256.ll | 26 ++++++--------------- + test/CodeGen/X86/v8i1-masks.ll | 4 ++-- + test/CodeGen/X86/vec_int_to_fp.ll | 30 ++++++++++++------------- + test/CodeGen/X86/vec_uint_to_fp-fastmath.ll | 26 ++++++++++----------- + 6 files changed, 42 insertions(+), 54 deletions(-) + +diff --git a/lib/Target/X86/X86InstrSSE.td b/lib/Target/X86/X86InstrSSE.td +index f91764a67d1..77da22de4d3 100644 +--- a/lib/Target/X86/X86InstrSSE.td ++++ b/lib/Target/X86/X86InstrSSE.td +@@ -2950,13 +2950,13 @@ let isCommutable = 0 in + // AVX1 requires type coercions in order to fold loads directly into logical + // operations. + let Predicates = [HasAVX1Only] in { +- def : Pat<(bc_v8f32 (and VR256:$src1, (loadv4i64 addr:$src2))), ++ def : Pat<(and VR256:$src1, (loadv4i64 addr:$src2)), + (VANDPSYrm VR256:$src1, addr:$src2)>; +- def : Pat<(bc_v8f32 (or VR256:$src1, (loadv4i64 addr:$src2))), ++ def : Pat<(or VR256:$src1, (loadv4i64 addr:$src2)), + (VORPSYrm VR256:$src1, addr:$src2)>; +- def : Pat<(bc_v8f32 (xor VR256:$src1, (loadv4i64 addr:$src2))), ++ def : Pat<(xor VR256:$src1, (loadv4i64 addr:$src2)), + (VXORPSYrm VR256:$src1, addr:$src2)>; +- def : Pat<(bc_v8f32 (X86andnp VR256:$src1, (loadv4i64 addr:$src2))), ++ def : Pat<(X86andnp VR256:$src1, (loadv4i64 addr:$src2)), + (VANDNPSYrm VR256:$src1, addr:$src2)>; + } + +diff --git a/test/CodeGen/X86/WidenArith.ll b/test/CodeGen/X86/WidenArith.ll +index cdd1a2818b2..cc5fcba6670 100644 +--- a/test/CodeGen/X86/WidenArith.ll ++++ b/test/CodeGen/X86/WidenArith.ll +@@ -9,8 +9,8 @@ define <8 x i32> @test(<8 x float> %a, <8 x float> %b) { + ; CHECK-NEXT: vsubps %ymm2, %ymm1, %ymm3 + ; CHECK-NEXT: vcmpltps %ymm1, %ymm0, %ymm0 + ; CHECK-NEXT: vcmpltps %ymm3, %ymm2, %ymm1 +-; CHECK-NEXT: vandps {{.*}}(%rip), %ymm1, %ymm1 + ; CHECK-NEXT: vandps %ymm1, %ymm0, %ymm0 ++; CHECK-NEXT: vandps {{.*}}(%rip), %ymm0, %ymm0 + ; CHECK-NEXT: retq + %c1 = fadd <8 x float> %a, %b + %b1 = fmul <8 x float> %b, %a +diff --git a/test/CodeGen/X86/merge-consecutive-loads-256.ll b/test/CodeGen/X86/merge-consecutive-loads-256.ll +index 8c2e9372900..dc268d9bdf8 100644 +--- a/test/CodeGen/X86/merge-consecutive-loads-256.ll ++++ b/test/CodeGen/X86/merge-consecutive-loads-256.ll +@@ -547,29 +547,17 @@ define <16 x i16> @merge_16i16_i16_0uu3uuuuuuuuCuEF(i16* %ptr) nounwind uwtable + } + + define <16 x i16> @merge_16i16_i16_0uu3zzuuuuuzCuEF(i16* %ptr) nounwind uwtable noinline ssp { +-; AVX1-LABEL: merge_16i16_i16_0uu3zzuuuuuzCuEF: +-; AVX1: # BB#0: +-; AVX1-NEXT: vmovaps {{.*#+}} ymm0 = [65535,0,0,65535,0,0,0,0,0,0,0,0,65535,0,65535,65535] +-; AVX1-NEXT: vandps (%rdi), %ymm0, %ymm0 +-; AVX1-NEXT: retq +-; +-; AVX2-LABEL: merge_16i16_i16_0uu3zzuuuuuzCuEF: +-; AVX2: # BB#0: +-; AVX2-NEXT: vmovups (%rdi), %ymm0 +-; AVX2-NEXT: vandps {{.*}}(%rip), %ymm0, %ymm0 +-; AVX2-NEXT: retq +-; +-; AVX512F-LABEL: merge_16i16_i16_0uu3zzuuuuuzCuEF: +-; AVX512F: # BB#0: +-; AVX512F-NEXT: vmovups (%rdi), %ymm0 +-; AVX512F-NEXT: vandps {{.*}}(%rip), %ymm0, %ymm0 +-; AVX512F-NEXT: retq ++; AVX-LABEL: merge_16i16_i16_0uu3zzuuuuuzCuEF: ++; AVX: # BB#0: ++; AVX-NEXT: vmovups (%rdi), %ymm0 ++; AVX-NEXT: vandps {{.*}}(%rip), %ymm0, %ymm0 ++; AVX-NEXT: retq + ; + ; X32-AVX-LABEL: merge_16i16_i16_0uu3zzuuuuuzCuEF: + ; X32-AVX: # BB#0: + ; X32-AVX-NEXT: movl {{[0-9]+}}(%esp), %eax +-; X32-AVX-NEXT: vmovaps {{.*#+}} ymm0 = [65535,0,0,65535,0,0,0,0,0,0,0,0,65535,0,65535,65535] +-; X32-AVX-NEXT: vandps (%eax), %ymm0, %ymm0 ++; X32-AVX-NEXT: vmovups (%eax), %ymm0 ++; X32-AVX-NEXT: vandps {{\.LCPI.*}}, %ymm0, %ymm0 + ; X32-AVX-NEXT: retl + %ptr0 = getelementptr inbounds i16, i16* %ptr, i64 0 + %ptr3 = getelementptr inbounds i16, i16* %ptr, i64 3 +diff --git a/test/CodeGen/X86/v8i1-masks.ll b/test/CodeGen/X86/v8i1-masks.ll +index 0135832ad92..d5c31506e98 100644 +--- a/test/CodeGen/X86/v8i1-masks.ll ++++ b/test/CodeGen/X86/v8i1-masks.ll +@@ -13,8 +13,8 @@ define void @and_masks(<8 x float>* %a, <8 x float>* %b, <8 x float>* %c) nounwi + ; X32-NEXT: vcmpltps %ymm0, %ymm1, %ymm1 + ; X32-NEXT: vmovups (%eax), %ymm2 + ; X32-NEXT: vcmpltps %ymm0, %ymm2, %ymm0 +-; X32-NEXT: vandps LCPI0_0, %ymm1, %ymm1 + ; X32-NEXT: vandps %ymm1, %ymm0, %ymm0 ++; X32-NEXT: vandps LCPI0_0, %ymm0, %ymm0 + ; X32-NEXT: vmovaps %ymm0, (%eax) + ; X32-NEXT: vzeroupper + ; X32-NEXT: retl +@@ -26,8 +26,8 @@ define void @and_masks(<8 x float>* %a, <8 x float>* %b, <8 x float>* %c) nounwi + ; X64-NEXT: vcmpltps %ymm0, %ymm1, %ymm1 + ; X64-NEXT: vmovups (%rdx), %ymm2 + ; X64-NEXT: vcmpltps %ymm0, %ymm2, %ymm0 +-; X64-NEXT: vandps {{.*}}(%rip), %ymm1, %ymm1 + ; X64-NEXT: vandps %ymm1, %ymm0, %ymm0 ++; X64-NEXT: vandps {{.*}}(%rip), %ymm0, %ymm0 + ; X64-NEXT: vmovaps %ymm0, (%rax) + ; X64-NEXT: vzeroupper + ; X64-NEXT: retq +diff --git a/test/CodeGen/X86/vec_int_to_fp.ll b/test/CodeGen/X86/vec_int_to_fp.ll +index 5d8f91385c7..8ea7243664a 100644 +--- a/test/CodeGen/X86/vec_int_to_fp.ll ++++ b/test/CodeGen/X86/vec_int_to_fp.ll +@@ -1694,15 +1694,15 @@ define <8 x float> @uitofp_8i32_to_8f32(<8 x i32> %a) { + ; + ; AVX1-LABEL: uitofp_8i32_to_8f32: + ; AVX1: # BB#0: +-; AVX1-NEXT: vandps {{.*}}(%rip), %ymm0, %ymm1 ++; AVX1-NEXT: vpsrld $16, %xmm0, %xmm1 ++; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm2 ++; AVX1-NEXT: vpsrld $16, %xmm2, %xmm2 ++; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm1, %ymm1 + ; AVX1-NEXT: vcvtdq2ps %ymm1, %ymm1 +-; AVX1-NEXT: vpsrld $16, %xmm0, %xmm2 +-; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +-; AVX1-NEXT: vpsrld $16, %xmm0, %xmm0 +-; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm2, %ymm0 ++; AVX1-NEXT: vmulps {{.*}}(%rip), %ymm1, %ymm1 ++; AVX1-NEXT: vandps {{.*}}(%rip), %ymm0, %ymm0 + ; AVX1-NEXT: vcvtdq2ps %ymm0, %ymm0 +-; AVX1-NEXT: vmulps {{.*}}(%rip), %ymm0, %ymm0 +-; AVX1-NEXT: vaddps %ymm1, %ymm0, %ymm0 ++; AVX1-NEXT: vaddps %ymm0, %ymm1, %ymm0 + ; AVX1-NEXT: retq + ; + ; AVX2-LABEL: uitofp_8i32_to_8f32: +@@ -3372,16 +3372,16 @@ define <8 x float> @uitofp_load_8i32_to_8f32(<8 x i32> *%a) { + ; + ; AVX1-LABEL: uitofp_load_8i32_to_8f32: + ; AVX1: # BB#0: +-; AVX1-NEXT: vmovaps (%rdi), %ymm0 +-; AVX1-NEXT: vandps {{.*}}(%rip), %ymm0, %ymm1 ++; AVX1-NEXT: vmovdqa (%rdi), %ymm0 ++; AVX1-NEXT: vpsrld $16, %xmm0, %xmm1 ++; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm2 ++; AVX1-NEXT: vpsrld $16, %xmm2, %xmm2 ++; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm1, %ymm1 + ; AVX1-NEXT: vcvtdq2ps %ymm1, %ymm1 +-; AVX1-NEXT: vpsrld $16, %xmm0, %xmm2 +-; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +-; AVX1-NEXT: vpsrld $16, %xmm0, %xmm0 +-; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm2, %ymm0 ++; AVX1-NEXT: vmulps {{.*}}(%rip), %ymm1, %ymm1 ++; AVX1-NEXT: vandps {{.*}}(%rip), %ymm0, %ymm0 + ; AVX1-NEXT: vcvtdq2ps %ymm0, %ymm0 +-; AVX1-NEXT: vmulps {{.*}}(%rip), %ymm0, %ymm0 +-; AVX1-NEXT: vaddps %ymm1, %ymm0, %ymm0 ++; AVX1-NEXT: vaddps %ymm0, %ymm1, %ymm0 + ; AVX1-NEXT: retq + ; + ; AVX2-LABEL: uitofp_load_8i32_to_8f32: +diff --git a/test/CodeGen/X86/vec_uint_to_fp-fastmath.ll b/test/CodeGen/X86/vec_uint_to_fp-fastmath.ll +index c0e02bd1599..cb8e2096585 100644 +--- a/test/CodeGen/X86/vec_uint_to_fp-fastmath.ll ++++ b/test/CodeGen/X86/vec_uint_to_fp-fastmath.ll +@@ -78,18 +78,18 @@ define <4 x float> @test_uitofp_v4i32_to_v4f32(<4 x i32> %arg) { + ret <4 x float> %tmp + } + +-; AVX: [[MASKCSTADDR_v8:.LCPI[0-9_]+]]: +-; AVX-NEXT: .long 65535 # 0xffff +-; AVX-NEXT: .long 65535 # 0xffff +-; AVX-NEXT: .long 65535 # 0xffff +-; AVX-NEXT: .long 65535 # 0xffff +- + ; AVX: [[FPMASKCSTADDR_v8:.LCPI[0-9_]+]]: + ; AVX-NEXT: .long 1199570944 # float 65536 + ; AVX-NEXT: .long 1199570944 # float 65536 + ; AVX-NEXT: .long 1199570944 # float 65536 + ; AVX-NEXT: .long 1199570944 # float 65536 + ++; AVX: [[MASKCSTADDR_v8:.LCPI[0-9_]+]]: ++; AVX-NEXT: .long 65535 # 0xffff ++; AVX-NEXT: .long 65535 # 0xffff ++; AVX-NEXT: .long 65535 # 0xffff ++; AVX-NEXT: .long 65535 # 0xffff ++ + ; AVX2: [[FPMASKCSTADDR_v8:.LCPI[0-9_]+]]: + ; AVX2-NEXT: .long 1199570944 # float 65536 + +@@ -119,15 +119,15 @@ define <8 x float> @test_uitofp_v8i32_to_v8f32(<8 x i32> %arg) { + ; + ; AVX-LABEL: test_uitofp_v8i32_to_v8f32: + ; AVX: # BB#0: +-; AVX-NEXT: vandps [[MASKCSTADDR_v8]](%rip), %ymm0, %ymm1 ++; AVX-NEXT: vpsrld $16, %xmm0, %xmm1 ++; AVX-NEXT: vextractf128 $1, %ymm0, %xmm2 ++; AVX-NEXT: vpsrld $16, %xmm2, %xmm2 ++; AVX-NEXT: vinsertf128 $1, %xmm2, %ymm1, %ymm1 + ; AVX-NEXT: vcvtdq2ps %ymm1, %ymm1 +-; AVX-NEXT: vpsrld $16, %xmm0, %xmm2 +-; AVX-NEXT: vextractf128 $1, %ymm0, %xmm0 +-; AVX-NEXT: vpsrld $16, %xmm0, %xmm0 +-; AVX-NEXT: vinsertf128 $1, %xmm0, %ymm2, %ymm0 ++; AVX-NEXT: vmulps [[FPMASKCSTADDR_v8]](%rip), %ymm1, %ymm1 ++; AVX-NEXT: vandps [[MASKCSTADDR_v8]](%rip), %ymm0, %ymm0 + ; AVX-NEXT: vcvtdq2ps %ymm0, %ymm0 +-; AVX-NEXT: vmulps [[FPMASKCSTADDR_v8]](%rip), %ymm0, %ymm0 +-; AVX-NEXT: vaddps %ymm1, %ymm0, %ymm0 ++; AVX-NEXT: vaddps %ymm0, %ymm1, %ymm0 + ; AVX-NEXT: retq + ; + ; AVX2-LABEL: test_uitofp_v8i32_to_v8f32: +-- +2.11.0 + diff --git a/deps/patches/llvm-PR278321.patch b/deps/patches/llvm-PR278321.patch new file mode 100644 index 0000000000000..709436536f01a --- /dev/null +++ b/deps/patches/llvm-PR278321.patch @@ -0,0 +1,1409 @@ +From a4ec9b3d6c2c53eb463284db0aa54158fad32701 Mon Sep 17 00:00:00 2001 +From: Marina Yatsina +Date: Thu, 11 Aug 2016 07:32:08 +0000 +Subject: [PATCH 4/5] Avoid false dependencies of undef machine operands + +This patch helps avoid false dependencies on undef registers by updating the machine instructions' undef operand to use a register that the instruction is truly dependent on, or use a register with clearance higher than Pref. + +Pseudo example: + +loop: +xmm0 = ... +xmm1 = vcvtsi2sdl eax, xmm0 +... = inst xmm0 +jmp loop + +In this example, selecting xmm0 as the undef register creates false dependency between loop iterations. +This false dependency cannot be solved by inserting an xor before vcvtsi2sdl because xmm0 is alive at the point of the vcvtsi2sdl instruction. +Selecting a different register instead of xmm0, especially a register that is not used in the loop, will eliminate this problem. + +Differential Revision: https://reviews.llvm.org/D22466 + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@278321 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + lib/CodeGen/ExecutionDepsFix.cpp | 53 ++++ + lib/Target/X86/X86InstrInfo.cpp | 2 +- + test/CodeGen/X86/break-false-dep.ll | 72 ++++- + test/CodeGen/X86/copy-propagation.ll | 3 +- + test/CodeGen/X86/half.ll | 2 +- + test/CodeGen/X86/vec_int_to_fp.ll | 579 ++++++++++++++++++++--------------- + 6 files changed, 467 insertions(+), 244 deletions(-) + +diff --git a/lib/CodeGen/ExecutionDepsFix.cpp b/lib/CodeGen/ExecutionDepsFix.cpp +index 1fe5f459b69..5f91db9251c 100644 +--- a/lib/CodeGen/ExecutionDepsFix.cpp ++++ b/lib/CodeGen/ExecutionDepsFix.cpp +@@ -203,6 +203,8 @@ private: + void processDefs(MachineInstr*, bool Kill); + void visitSoftInstr(MachineInstr*, unsigned mask); + void visitHardInstr(MachineInstr*, unsigned domain); ++ void pickBestRegisterForUndef(MachineInstr *MI, unsigned OpIdx, ++ unsigned Pref); + bool shouldBreakDependence(MachineInstr*, unsigned OpIdx, unsigned Pref); + void processUndefReads(MachineBasicBlock*); + }; +@@ -473,6 +475,56 @@ void ExeDepsFix::visitInstr(MachineInstr *MI) { + processDefs(MI, !DomP.first); + } + ++/// \brief Helps avoid false dependencies on undef registers by updating the ++/// machine instructions' undef operand to use a register that the instruction ++/// is truly dependent on, or use a register with clearance higher than Pref. ++void ExeDepsFix::pickBestRegisterForUndef(MachineInstr *MI, unsigned OpIdx, ++ unsigned Pref) { ++ MachineOperand &MO = MI->getOperand(OpIdx); ++ assert(MO.isUndef() && "Expected undef machine operand"); ++ ++ unsigned OriginalReg = MO.getReg(); ++ ++ // Update only undef operands that are mapped to one register. ++ if (AliasMap[OriginalReg].size() != 1) ++ return; ++ ++ // Get the undef operand's register class ++ const TargetRegisterClass *OpRC = ++ TII->getRegClass(MI->getDesc(), OpIdx, TRI, *MF); ++ ++ // If the instruction has a true dependency, we can hide the false depdency ++ // behind it. ++ for (MachineOperand &CurrMO : MI->operands()) { ++ if (!CurrMO.isReg() || CurrMO.isDef() || CurrMO.isUndef() || ++ !OpRC->contains(CurrMO.getReg())) ++ continue; ++ // We found a true dependency - replace the undef register with the true ++ // dependency. ++ MO.setReg(CurrMO.getReg()); ++ return; ++ } ++ ++ // Go over all registers in the register class and find the register with ++ // max clearance or clearance higher than Pref. ++ unsigned MaxClearance = 0; ++ unsigned MaxClearanceReg = OriginalReg; ++ for (unsigned rx = 0; rx < OpRC->getNumRegs(); ++rx) { ++ unsigned Clearance = CurInstr - LiveRegs[rx].Def; ++ if (Clearance <= MaxClearance) ++ continue; ++ MaxClearance = Clearance; ++ MaxClearanceReg = OpRC->getRegister(rx); ++ ++ if (MaxClearance > Pref) ++ break; ++ } ++ ++ // Update the operand if we found a register with better clearance. ++ if (MaxClearanceReg != OriginalReg) ++ MO.setReg(MaxClearanceReg); ++} ++ + /// \brief Return true to if it makes sense to break dependence on a partial def + /// or undef use. + bool ExeDepsFix::shouldBreakDependence(MachineInstr *MI, unsigned OpIdx, +@@ -510,6 +562,7 @@ void ExeDepsFix::processDefs(MachineInstr *MI, bool Kill) { + unsigned OpNum; + unsigned Pref = TII->getUndefRegClearance(*MI, OpNum, TRI); + if (Pref) { ++ pickBestRegisterForUndef(MI, OpNum, Pref); + if (shouldBreakDependence(MI, OpNum, Pref)) + UndefReads.push_back(std::make_pair(MI, OpNum)); + } +diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp +index 5f0aab9ddc6..9bfe25973ae 100644 +--- a/lib/Target/X86/X86InstrInfo.cpp ++++ b/lib/Target/X86/X86InstrInfo.cpp +@@ -68,7 +68,7 @@ static cl::opt + UndefRegClearance("undef-reg-clearance", + cl::desc("How many idle instructions we would like before " + "certain undef register reads"), +- cl::init(64), cl::Hidden); ++ cl::init(128), cl::Hidden); + + enum { + // Select which memory operand is being unfolded. +diff --git a/test/CodeGen/X86/break-false-dep.ll b/test/CodeGen/X86/break-false-dep.ll +index a7cda499dab..4c5e747f9ca 100644 +--- a/test/CodeGen/X86/break-false-dep.ll ++++ b/test/CodeGen/X86/break-false-dep.ll +@@ -126,6 +126,7 @@ loop: + %i = phi i64 [ 1, %entry ], [ %inc, %loop ] + %s1 = phi i64 [ %vx, %entry ], [ %s2, %loop ] + %fi = sitofp i64 %i to double ++ tail call void asm sideeffect "", "~{xmm0},~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{dirflag},~{fpsr},~{flags}"() + %vy = load double, double* %y + %fipy = fadd double %fi, %vy + %iipy = fptosi double %fipy to i64 +@@ -174,6 +175,7 @@ for.body3: + store double %mul11, double* %arrayidx13, align 8 + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + %exitcond = icmp eq i64 %indvars.iv.next, 1024 ++ tail call void asm sideeffect "", "~{xmm0},~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{dirflag},~{fpsr},~{flags}"() + br i1 %exitcond, label %for.inc14, label %for.body3 + + for.inc14: ; preds = %for.body3 +@@ -193,7 +195,7 @@ for.end16: ; preds = %for.inc14 + ;SSE-NEXT: movsd [[XMM0]], + ;AVX-LABEL:@loopdep3 + ;AVX: vxorps [[XMM0:%xmm[0-9]+]], [[XMM0]] +-;AVX-NEXT: vcvtsi2sdl {{.*}}, [[XMM0]], [[XMM0]] ++;AVX-NEXT: vcvtsi2sdl {{.*}}, [[XMM0]], {{%xmm[0-9]+}} + ;AVX-NEXT: vmulsd {{.*}}, [[XMM0]], [[XMM0]] + ;AVX-NEXT: vmulsd {{.*}}, [[XMM0]], [[XMM0]] + ;AVX-NEXT: vmulsd {{.*}}, [[XMM0]], [[XMM0]] +@@ -202,10 +204,76 @@ for.end16: ; preds = %for.inc14 + + define double @inlineasmdep(i64 %arg) { + top: +- tail call void asm sideeffect "", "~{xmm0},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm0},~{xmm1},~{xmm2},~{xmm3},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{dirflag},~{fpsr},~{flags}"() + %tmp1 = sitofp i64 %arg to double + ret double %tmp1 + ;AVX-LABEL:@inlineasmdep + ;AVX: vxorps [[XMM0:%xmm[0-9]+]], [[XMM0]], [[XMM0]] + ;AVX-NEXT: vcvtsi2sdq {{.*}}, [[XMM0]], {{%xmm[0-9]+}} + } ++ ++; Make sure we are making a smart choice regarding undef registers and ++; hiding the false dependency behind a true dependency ++define double @truedeps(float %arg) { ++top: ++ tail call void asm sideeffect "", "~{xmm6},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm0},~{xmm1},~{xmm2},~{xmm3},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm4},~{xmm5},~{xmm7},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{dirflag},~{fpsr},~{flags}"() ++ %tmp1 = fpext float %arg to double ++ ret double %tmp1 ++;AVX-LABEL:@truedeps ++;AVX-NOT: vxorps ++;AVX: vcvtss2sd [[XMM0:%xmm[0-9]+]], [[XMM0]], {{%xmm[0-9]+}} ++} ++ ++; Make sure we are making a smart choice regarding undef registers and ++; choosing the register with the highest clearence ++define double @clearence(i64 %arg) { ++top: ++ tail call void asm sideeffect "", "~{xmm6},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm0},~{xmm1},~{xmm2},~{xmm3},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm4},~{xmm5},~{xmm7},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{dirflag},~{fpsr},~{flags}"() ++ %tmp1 = sitofp i64 %arg to double ++ ret double %tmp1 ++;AVX-LABEL:@clearence ++;AVX: vxorps [[XMM6:%xmm6]], [[XMM6]], [[XMM6]] ++;AVX-NEXT: vcvtsi2sdq {{.*}}, [[XMM6]], {{%xmm[0-9]+}} ++} ++ ++; Make sure we are making a smart choice regarding undef registers in order to ++; avoid a cyclic dependence on a write to the same register in a previous ++; iteration, especially when we cannot zero out the undef register because it ++; is alive. ++define i64 @loopclearence(i64* nocapture %x, double* nocapture %y) nounwind { ++entry: ++ %vx = load i64, i64* %x ++ br label %loop ++loop: ++ %i = phi i64 [ 1, %entry ], [ %inc, %loop ] ++ %s1 = phi i64 [ %vx, %entry ], [ %s2, %loop ] ++ %fi = sitofp i64 %i to double ++ tail call void asm sideeffect "", "~{xmm0},~{xmm1},~{xmm2},~{xmm3},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{dirflag},~{fpsr},~{flags}"() ++ %vy = load double, double* %y ++ %fipy = fadd double %fi, %vy ++ %iipy = fptosi double %fipy to i64 ++ %s2 = add i64 %s1, %iipy ++ %inc = add nsw i64 %i, 1 ++ %exitcond = icmp eq i64 %inc, 156250000 ++ br i1 %exitcond, label %ret, label %loop ++ret: ++ ret i64 %s2 ++;AVX-LABEL:@loopclearence ++;Registers 4-7 are not used and therefore one of them should be chosen ++;AVX-NOT: {{%xmm[4-7]}} ++;AVX: vcvtsi2sdq {{.*}}, [[XMM4_7:%xmm[4-7]]], {{%xmm[0-9]+}} ++;AVX-NOT: [[XMM4_7]] ++} +diff --git a/test/CodeGen/X86/copy-propagation.ll b/test/CodeGen/X86/copy-propagation.ll +index 19421a06fa8..dac46c17382 100644 +--- a/test/CodeGen/X86/copy-propagation.ll ++++ b/test/CodeGen/X86/copy-propagation.ll +@@ -26,7 +26,7 @@ target triple = "x86_64-pc-win32-elf" + ; Copy the result in a temporary. + ; Note: Technically the regalloc could have been smarter and this move not required, + ; which would have hidden the bug. +-; CHECK-NEXT: vmovapd %xmm0, [[TMP:%xmm[0-9]+]] ++; CHECK: vmovapd %xmm0, [[TMP:%xmm[0-9]+]] + ; Crush xmm0. + ; CHECK-NEXT: vxorps %xmm0, %xmm0, %xmm0 + ; CHECK: movl $339772768, %e[[INDIRECT_CALL2:[a-z]+]] +@@ -37,6 +37,7 @@ target triple = "x86_64-pc-win32-elf" + define double @foo(i64 %arg) { + top: + %tmp = call double inttoptr (i64 339752784 to double (double, double)*)(double 1.000000e+00, double 0.000000e+00) ++ tail call void asm sideeffect "", "x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{dirflag},~{fpsr},~{flags}"(double %tmp) + %tmp1 = sitofp i64 %arg to double + call void inttoptr (i64 339772768 to void (double, double)*)(double %tmp, double %tmp1) + %tmp3 = fadd double %tmp1, %tmp +diff --git a/test/CodeGen/X86/half.ll b/test/CodeGen/X86/half.ll +index 717ddbfa6fd..739bb146e3a 100644 +--- a/test/CodeGen/X86/half.ll ++++ b/test/CodeGen/X86/half.ll +@@ -299,7 +299,7 @@ define half @test_f80trunc_nodagcombine() #0 { + ; CHECK-F16C-NEXT: movswl (%rsi), %eax + ; CHECK-F16C-NEXT: vmovd %eax, %xmm0 + ; CHECK-F16C-NEXT: vcvtph2ps %xmm0, %xmm0 +-; CHECK-F16C-NEXT: vcvtsi2ssl %edi, %xmm0, %xmm1 ++; CHECK-F16C-NEXT: vcvtsi2ssl %edi, %xmm1, %xmm1 + ; CHECK-F16C-NEXT: vcvtps2ph $4, %xmm1, %xmm1 + ; CHECK-F16C-NEXT: vcvtph2ps %xmm1, %xmm1 + ; CHECK-F16C-NEXT: vaddss %xmm1, %xmm0, %xmm0 +diff --git a/test/CodeGen/X86/vec_int_to_fp.ll b/test/CodeGen/X86/vec_int_to_fp.ll +index 8ea7243664a..bb0a93dc848 100644 +--- a/test/CodeGen/X86/vec_int_to_fp.ll ++++ b/test/CodeGen/X86/vec_int_to_fp.ll +@@ -27,10 +27,9 @@ define <2 x double> @sitofp_2i64_to_2f64(<2 x i64> %a) { + ; AVX-LABEL: sitofp_2i64_to_2f64: + ; AVX: # BB#0: + ; AVX-NEXT: vpextrq $1, %xmm0, %rax +-; AVX-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm1 ++; AVX-NEXT: vcvtsi2sdq %rax, %xmm1, %xmm1 + ; AVX-NEXT: vmovq %xmm0, %rax +-; AVX-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm0 ++; AVX-NEXT: vcvtsi2sdq %rax, %xmm2, %xmm0 + ; AVX-NEXT: vunpcklpd {{.*#+}} xmm0 = xmm0[0],xmm1[0] + ; AVX-NEXT: retq + %cvt = sitofp <2 x i64> %a to <2 x double> +@@ -188,15 +187,14 @@ define <4 x double> @sitofp_4i64_to_4f64(<4 x i64> %a) { + ; AVX1: # BB#0: + ; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm1 + ; AVX1-NEXT: vpextrq $1, %xmm1, %rax +-; AVX1-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2sdq %rax, %xmm2, %xmm2 + ; AVX1-NEXT: vmovq %xmm1, %rax +-; AVX1-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm1 ++; AVX1-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm1 + ; AVX1-NEXT: vunpcklpd {{.*#+}} xmm1 = xmm1[0],xmm2[0] + ; AVX1-NEXT: vpextrq $1, %xmm0, %rax +-; AVX1-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm2 + ; AVX1-NEXT: vmovq %xmm0, %rax +-; AVX1-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX1-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm0 ++; AVX1-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm0 + ; AVX1-NEXT: vunpcklpd {{.*#+}} xmm0 = xmm0[0],xmm2[0] + ; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 + ; AVX1-NEXT: retq +@@ -205,18 +203,33 @@ define <4 x double> @sitofp_4i64_to_4f64(<4 x i64> %a) { + ; AVX2: # BB#0: + ; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm1 + ; AVX2-NEXT: vpextrq $1, %xmm1, %rax +-; AVX2-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2sdq %rax, %xmm2, %xmm2 + ; AVX2-NEXT: vmovq %xmm1, %rax +-; AVX2-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm1 ++; AVX2-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm1 + ; AVX2-NEXT: vunpcklpd {{.*#+}} xmm1 = xmm1[0],xmm2[0] + ; AVX2-NEXT: vpextrq $1, %xmm0, %rax +-; AVX2-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm2 + ; AVX2-NEXT: vmovq %xmm0, %rax +-; AVX2-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX2-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm0 ++; AVX2-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm0 + ; AVX2-NEXT: vunpcklpd {{.*#+}} xmm0 = xmm0[0],xmm2[0] + ; AVX2-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 + ; AVX2-NEXT: retq ++; ++; AVX512-LABEL: sitofp_4i64_to_4f64: ++; AVX512: # BB#0: ++; AVX512-NEXT: vextracti32x4 $1, %ymm0, %xmm1 ++; AVX512-NEXT: vpextrq $1, %xmm1, %rax ++; AVX512-NEXT: vcvtsi2sdq %rax, %xmm2, %xmm2 ++; AVX512-NEXT: vmovq %xmm1, %rax ++; AVX512-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm1 ++; AVX512-NEXT: vunpcklpd {{.*#+}} xmm1 = xmm1[0],xmm2[0] ++; AVX512-NEXT: vpextrq $1, %xmm0, %rax ++; AVX512-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm2 ++; AVX512-NEXT: vmovq %xmm0, %rax ++; AVX512-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm0 ++; AVX512-NEXT: vunpcklpd {{.*#+}} xmm0 = xmm0[0],xmm2[0] ++; AVX512-NEXT: vinsertf32x4 $1, %xmm1, %ymm0, %ymm0 ++; AVX512-NEXT: retq + %cvt = sitofp <4 x i64> %a to <4 x double> + ret <4 x double> %cvt + } +@@ -803,12 +816,11 @@ define <4 x float> @sitofp_2i64_to_4f32(<2 x i64> %a) { + ; AVX-LABEL: sitofp_2i64_to_4f32: + ; AVX: # BB#0: + ; AVX-NEXT: vpextrq $1, %xmm0, %rax +-; AVX-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 + ; AVX-NEXT: vmovq %xmm0, %rax +-; AVX-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm0 ++; AVX-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm0 + ; AVX-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[2,3] +-; AVX-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm1 + ; AVX-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1],xmm1[0],xmm0[3] + ; AVX-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1,2],xmm1[0] + ; AVX-NEXT: retq +@@ -836,12 +848,11 @@ define <4 x float> @sitofp_4i64_to_4f32_undef(<2 x i64> %a) { + ; AVX-LABEL: sitofp_4i64_to_4f32_undef: + ; AVX: # BB#0: + ; AVX-NEXT: vpextrq $1, %xmm0, %rax +-; AVX-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 + ; AVX-NEXT: vmovq %xmm0, %rax +-; AVX-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm0 ++; AVX-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm0 + ; AVX-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[2,3] +-; AVX-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm1 + ; AVX-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1],xmm1[0],xmm0[3] + ; AVX-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1,2],xmm1[0] + ; AVX-NEXT: retq +@@ -988,17 +999,16 @@ define <4 x float> @sitofp_4i64_to_4f32(<4 x i64> %a) { + ; AVX1-LABEL: sitofp_4i64_to_4f32: + ; AVX1: # BB#0: + ; AVX1-NEXT: vpextrq $1, %xmm0, %rax +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 + ; AVX1-NEXT: vmovq %xmm0, %rax +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm2 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm1 = xmm2[0],xmm1[0],xmm2[2,3] + ; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 + ; AVX1-NEXT: vmovq %xmm0, %rax +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm2 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1],xmm2[0],xmm1[3] + ; AVX1-NEXT: vpextrq $1, %xmm0, %rax +-; AVX1-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm0 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm0 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm0[0] + ; AVX1-NEXT: vzeroupper + ; AVX1-NEXT: retq +@@ -1006,20 +1016,35 @@ define <4 x float> @sitofp_4i64_to_4f32(<4 x i64> %a) { + ; AVX2-LABEL: sitofp_4i64_to_4f32: + ; AVX2: # BB#0: + ; AVX2-NEXT: vpextrq $1, %xmm0, %rax +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 + ; AVX2-NEXT: vmovq %xmm0, %rax +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm2 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm1 = xmm2[0],xmm1[0],xmm2[2,3] + ; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm0 + ; AVX2-NEXT: vmovq %xmm0, %rax +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm2 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1],xmm2[0],xmm1[3] + ; AVX2-NEXT: vpextrq $1, %xmm0, %rax +-; AVX2-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm0 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm0 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm0[0] + ; AVX2-NEXT: vzeroupper + ; AVX2-NEXT: retq ++; ++; AVX512-LABEL: sitofp_4i64_to_4f32: ++; AVX512: # BB#0: ++; AVX512-NEXT: vpextrq $1, %xmm0, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 ++; AVX512-NEXT: vmovq %xmm0, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm2 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm1 = xmm2[0],xmm1[0],xmm2[2,3] ++; AVX512-NEXT: vextracti32x4 $1, %ymm0, %xmm0 ++; AVX512-NEXT: vmovq %xmm0, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm2 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1],xmm2[0],xmm1[3] ++; AVX512-NEXT: vpextrq $1, %xmm0, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm0 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm0[0] ++; AVX512-NEXT: retq + %cvt = sitofp <4 x i64> %a to <4 x float> + ret <4 x float> %cvt + } +@@ -1181,48 +1206,58 @@ define <4 x float> @uitofp_2i64_to_4f32(<2 x i64> %a) { + ; SSE-NEXT: unpcklps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1] + ; SSE-NEXT: retq + ; +-; AVX-LABEL: uitofp_2i64_to_4f32: +-; AVX: # BB#0: +-; AVX-NEXT: vpextrq $1, %xmm0, %rax +-; AVX-NEXT: movl %eax, %ecx +-; AVX-NEXT: andl $1, %ecx +-; AVX-NEXT: testq %rax, %rax +-; AVX-NEXT: js .LBB38_1 +-; AVX-NEXT: # BB#2: +-; AVX-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 +-; AVX-NEXT: jmp .LBB38_3 +-; AVX-NEXT: .LBB38_1: +-; AVX-NEXT: shrq %rax +-; AVX-NEXT: orq %rax, %rcx +-; AVX-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm1 +-; AVX-NEXT: vaddss %xmm1, %xmm1, %xmm1 +-; AVX-NEXT: .LBB38_3: +-; AVX-NEXT: vmovq %xmm0, %rax +-; AVX-NEXT: movl %eax, %ecx +-; AVX-NEXT: andl $1, %ecx +-; AVX-NEXT: testq %rax, %rax +-; AVX-NEXT: js .LBB38_4 +-; AVX-NEXT: # BB#5: +-; AVX-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm0 +-; AVX-NEXT: jmp .LBB38_6 +-; AVX-NEXT: .LBB38_4: +-; AVX-NEXT: shrq %rax +-; AVX-NEXT: orq %rax, %rcx +-; AVX-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm0 +-; AVX-NEXT: vaddss %xmm0, %xmm0, %xmm0 +-; AVX-NEXT: .LBB38_6: +-; AVX-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[2,3] +-; AVX-NEXT: vxorps %xmm1, %xmm1, %xmm1 +-; AVX-NEXT: testq %rax, %rax +-; AVX-NEXT: js .LBB38_8 +-; AVX-NEXT: # BB#7: +-; AVX-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 +-; AVX-NEXT: .LBB38_8: +-; AVX-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1],xmm1[0],xmm0[3] +-; AVX-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1,2],xmm1[0] +-; AVX-NEXT: retq ++; AVX1-LABEL: uitofp_2i64_to_4f32: ++; AVX1: # BB#0: ++; AVX1-NEXT: vpextrq $1, %xmm0, %rax ++; AVX1-NEXT: movl %eax, %ecx ++; AVX1-NEXT: andl $1, %ecx ++; AVX1-NEXT: testq %rax, %rax ++; AVX1-NEXT: js .LBB38_1 ++; AVX1-NEXT: # BB#2: ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 ++; AVX1-NEXT: jmp .LBB38_3 ++; AVX1-NEXT: .LBB38_1: ++; AVX1-NEXT: shrq %rax ++; AVX1-NEXT: orq %rax, %rcx ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm1, %xmm1 ++; AVX1-NEXT: vaddss %xmm1, %xmm1, %xmm1 ++; AVX1-NEXT: .LBB38_3: ++; AVX1-NEXT: vmovq %xmm0, %rax ++; AVX1-NEXT: movl %eax, %ecx ++; AVX1-NEXT: andl $1, %ecx ++; AVX1-NEXT: testq %rax, %rax ++; AVX1-NEXT: js .LBB38_4 ++; AVX1-NEXT: # BB#5: ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm0 ++; AVX1-NEXT: jmp .LBB38_6 ++; AVX1-NEXT: .LBB38_4: ++; AVX1-NEXT: shrq %rax ++; AVX1-NEXT: orq %rax, %rcx ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm2, %xmm0 ++; AVX1-NEXT: vaddss %xmm0, %xmm0, %xmm0 ++; AVX1-NEXT: .LBB38_6: ++; AVX1-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[2,3] ++; AVX1-NEXT: vxorps %xmm1, %xmm1, %xmm1 ++; AVX1-NEXT: testq %rax, %rax ++; AVX1-NEXT: js .LBB38_8 ++; AVX1-NEXT: # BB#7: ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm1 ++; AVX1-NEXT: .LBB38_8: ++; AVX1-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1],xmm1[0],xmm0[3] ++; AVX1-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1,2],xmm1[0] ++; AVX1-NEXT: retq ++; ++; AVX512-LABEL: uitofp_2i64_to_4f32: ++; AVX512: # BB#0: ++; AVX512-NEXT: vpextrq $1, %xmm0, %rax ++; AVX512-NEXT: vcvtusi2ssq %rax, %xmm0, %xmm1 ++; AVX512-NEXT: vmovq %xmm0, %rax ++; AVX512-NEXT: vcvtusi2ssq %rax, %xmm0, %xmm0 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[2,3] ++; AVX512-NEXT: vcvtusi2ssq %rax, %xmm0, %xmm1 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1],xmm1[0],xmm0[3] ++; AVX512-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1,2],xmm1[0] ++; AVX512-NEXT: retq + %cvt = uitofp <2 x i64> %a to <2 x float> + %ext = shufflevector <2 x float> %cvt, <2 x float> undef, <4 x i32> + ret <4 x float> %ext +@@ -1277,48 +1312,58 @@ define <4 x float> @uitofp_4i64_to_4f32_undef(<2 x i64> %a) { + ; SSE-NEXT: unpcklps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1] + ; SSE-NEXT: retq + ; +-; AVX-LABEL: uitofp_4i64_to_4f32_undef: +-; AVX: # BB#0: +-; AVX-NEXT: vpextrq $1, %xmm0, %rax +-; AVX-NEXT: movl %eax, %ecx +-; AVX-NEXT: andl $1, %ecx +-; AVX-NEXT: testq %rax, %rax +-; AVX-NEXT: js .LBB39_1 +-; AVX-NEXT: # BB#2: +-; AVX-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 +-; AVX-NEXT: jmp .LBB39_3 +-; AVX-NEXT: .LBB39_1: +-; AVX-NEXT: shrq %rax +-; AVX-NEXT: orq %rax, %rcx +-; AVX-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm1 +-; AVX-NEXT: vaddss %xmm1, %xmm1, %xmm1 +-; AVX-NEXT: .LBB39_3: +-; AVX-NEXT: vmovq %xmm0, %rax +-; AVX-NEXT: movl %eax, %ecx +-; AVX-NEXT: andl $1, %ecx +-; AVX-NEXT: testq %rax, %rax +-; AVX-NEXT: js .LBB39_4 +-; AVX-NEXT: # BB#5: +-; AVX-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm0 +-; AVX-NEXT: jmp .LBB39_6 +-; AVX-NEXT: .LBB39_4: +-; AVX-NEXT: shrq %rax +-; AVX-NEXT: orq %rax, %rcx +-; AVX-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm0 +-; AVX-NEXT: vaddss %xmm0, %xmm0, %xmm0 +-; AVX-NEXT: .LBB39_6: +-; AVX-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[2,3] +-; AVX-NEXT: vxorps %xmm1, %xmm1, %xmm1 +-; AVX-NEXT: testq %rax, %rax +-; AVX-NEXT: js .LBB39_8 +-; AVX-NEXT: # BB#7: +-; AVX-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 +-; AVX-NEXT: .LBB39_8: +-; AVX-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1],xmm1[0],xmm0[3] +-; AVX-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1,2],xmm1[0] +-; AVX-NEXT: retq ++; AVX1-LABEL: uitofp_4i64_to_4f32_undef: ++; AVX1: # BB#0: ++; AVX1-NEXT: vpextrq $1, %xmm0, %rax ++; AVX1-NEXT: movl %eax, %ecx ++; AVX1-NEXT: andl $1, %ecx ++; AVX1-NEXT: testq %rax, %rax ++; AVX1-NEXT: js .LBB39_1 ++; AVX1-NEXT: # BB#2: ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 ++; AVX1-NEXT: jmp .LBB39_3 ++; AVX1-NEXT: .LBB39_1: ++; AVX1-NEXT: shrq %rax ++; AVX1-NEXT: orq %rax, %rcx ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm1, %xmm1 ++; AVX1-NEXT: vaddss %xmm1, %xmm1, %xmm1 ++; AVX1-NEXT: .LBB39_3: ++; AVX1-NEXT: vmovq %xmm0, %rax ++; AVX1-NEXT: movl %eax, %ecx ++; AVX1-NEXT: andl $1, %ecx ++; AVX1-NEXT: testq %rax, %rax ++; AVX1-NEXT: js .LBB39_4 ++; AVX1-NEXT: # BB#5: ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm0 ++; AVX1-NEXT: jmp .LBB39_6 ++; AVX1-NEXT: .LBB39_4: ++; AVX1-NEXT: shrq %rax ++; AVX1-NEXT: orq %rax, %rcx ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm2, %xmm0 ++; AVX1-NEXT: vaddss %xmm0, %xmm0, %xmm0 ++; AVX1-NEXT: .LBB39_6: ++; AVX1-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[2,3] ++; AVX1-NEXT: vxorps %xmm1, %xmm1, %xmm1 ++; AVX1-NEXT: testq %rax, %rax ++; AVX1-NEXT: js .LBB39_8 ++; AVX1-NEXT: # BB#7: ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm1 ++; AVX1-NEXT: .LBB39_8: ++; AVX1-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1],xmm1[0],xmm0[3] ++; AVX1-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1,2],xmm1[0] ++; AVX1-NEXT: retq ++; ++; AVX512-LABEL: uitofp_4i64_to_4f32_undef: ++; AVX512: # BB#0: ++; AVX512-NEXT: vpextrq $1, %xmm0, %rax ++; AVX512-NEXT: vcvtusi2ssq %rax, %xmm0, %xmm1 ++; AVX512-NEXT: vmovq %xmm0, %rax ++; AVX512-NEXT: vcvtusi2ssq %rax, %xmm0, %xmm0 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[2,3] ++; AVX512-NEXT: vcvtusi2ssq %rax, %xmm0, %xmm1 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1],xmm1[0],xmm0[3] ++; AVX512-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0,1,2],xmm1[0] ++; AVX512-NEXT: retq + %ext = shufflevector <2 x i64> %a, <2 x i64> undef, <4 x i32> + %cvt = uitofp <4 x i64> %ext to <4 x float> + ret <4 x float> %cvt +@@ -1539,12 +1584,12 @@ define <4 x float> @uitofp_4i64_to_4f32(<4 x i64> %a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB45_1 + ; AVX1-NEXT: # BB#2: +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 + ; AVX1-NEXT: jmp .LBB45_3 + ; AVX1-NEXT: .LBB45_1: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm1 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm1, %xmm1 + ; AVX1-NEXT: vaddss %xmm1, %xmm1, %xmm1 + ; AVX1-NEXT: .LBB45_3: + ; AVX1-NEXT: vmovq %xmm0, %rax +@@ -1553,12 +1598,12 @@ define <4 x float> @uitofp_4i64_to_4f32(<4 x i64> %a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB45_4 + ; AVX1-NEXT: # BB#5: +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm2 + ; AVX1-NEXT: jmp .LBB45_6 + ; AVX1-NEXT: .LBB45_4: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm2, %xmm2 + ; AVX1-NEXT: vaddss %xmm2, %xmm2, %xmm2 + ; AVX1-NEXT: .LBB45_6: + ; AVX1-NEXT: vinsertps {{.*#+}} xmm1 = xmm2[0],xmm1[0],xmm2[2,3] +@@ -1569,12 +1614,12 @@ define <4 x float> @uitofp_4i64_to_4f32(<4 x i64> %a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB45_7 + ; AVX1-NEXT: # BB#8: +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm2 + ; AVX1-NEXT: jmp .LBB45_9 + ; AVX1-NEXT: .LBB45_7: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm3, %xmm2 + ; AVX1-NEXT: vaddss %xmm2, %xmm2, %xmm2 + ; AVX1-NEXT: .LBB45_9: + ; AVX1-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1],xmm2[0],xmm1[3] +@@ -1584,16 +1629,14 @@ define <4 x float> @uitofp_4i64_to_4f32(<4 x i64> %a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB45_10 + ; AVX1-NEXT: # BB#11: +-; AVX1-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm0 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm0 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm0[0] + ; AVX1-NEXT: vzeroupper + ; AVX1-NEXT: retq + ; AVX1-NEXT: .LBB45_10: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm0 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm3, %xmm0 + ; AVX1-NEXT: vaddss %xmm0, %xmm0, %xmm0 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm0[0] + ; AVX1-NEXT: vzeroupper +@@ -1607,12 +1650,12 @@ define <4 x float> @uitofp_4i64_to_4f32(<4 x i64> %a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB45_1 + ; AVX2-NEXT: # BB#2: +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 + ; AVX2-NEXT: jmp .LBB45_3 + ; AVX2-NEXT: .LBB45_1: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm1 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm1, %xmm1 + ; AVX2-NEXT: vaddss %xmm1, %xmm1, %xmm1 + ; AVX2-NEXT: .LBB45_3: + ; AVX2-NEXT: vmovq %xmm0, %rax +@@ -1621,12 +1664,12 @@ define <4 x float> @uitofp_4i64_to_4f32(<4 x i64> %a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB45_4 + ; AVX2-NEXT: # BB#5: +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm2 + ; AVX2-NEXT: jmp .LBB45_6 + ; AVX2-NEXT: .LBB45_4: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm2, %xmm2 + ; AVX2-NEXT: vaddss %xmm2, %xmm2, %xmm2 + ; AVX2-NEXT: .LBB45_6: + ; AVX2-NEXT: vinsertps {{.*#+}} xmm1 = xmm2[0],xmm1[0],xmm2[2,3] +@@ -1637,12 +1680,12 @@ define <4 x float> @uitofp_4i64_to_4f32(<4 x i64> %a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB45_7 + ; AVX2-NEXT: # BB#8: +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm2 + ; AVX2-NEXT: jmp .LBB45_9 + ; AVX2-NEXT: .LBB45_7: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm3, %xmm2 + ; AVX2-NEXT: vaddss %xmm2, %xmm2, %xmm2 + ; AVX2-NEXT: .LBB45_9: + ; AVX2-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1],xmm2[0],xmm1[3] +@@ -1652,16 +1695,14 @@ define <4 x float> @uitofp_4i64_to_4f32(<4 x i64> %a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB45_10 + ; AVX2-NEXT: # BB#11: +-; AVX2-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm0 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm0 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm0[0] + ; AVX2-NEXT: vzeroupper + ; AVX2-NEXT: retq + ; AVX2-NEXT: .LBB45_10: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm0 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm3, %xmm0 + ; AVX2-NEXT: vaddss %xmm0, %xmm0, %xmm0 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm0[0] + ; AVX2-NEXT: vzeroupper +@@ -1831,16 +1872,25 @@ define <2 x double> @sitofp_load_2i64_to_2f64(<2 x i64> *%a) { + ; SSE-NEXT: unpcklpd {{.*#+}} xmm0 = xmm0[0],xmm1[0] + ; SSE-NEXT: retq + ; +-; AVX-LABEL: sitofp_load_2i64_to_2f64: +-; AVX: # BB#0: +-; AVX-NEXT: vmovdqa (%rdi), %xmm0 +-; AVX-NEXT: vpextrq $1, %xmm0, %rax +-; AVX-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm1 +-; AVX-NEXT: vmovq %xmm0, %rax +-; AVX-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm0 +-; AVX-NEXT: vunpcklpd {{.*#+}} xmm0 = xmm0[0],xmm1[0] +-; AVX-NEXT: retq ++; AVX1-LABEL: sitofp_load_2i64_to_2f64: ++; AVX1: # BB#0: ++; AVX1-NEXT: vmovdqa (%rdi), %xmm0 ++; AVX1-NEXT: vpextrq $1, %xmm0, %rax ++; AVX1-NEXT: vcvtsi2sdq %rax, %xmm1, %xmm1 ++; AVX1-NEXT: vmovq %xmm0, %rax ++; AVX1-NEXT: vcvtsi2sdq %rax, %xmm2, %xmm0 ++; AVX1-NEXT: vunpcklpd {{.*#+}} xmm0 = xmm0[0],xmm1[0] ++; AVX1-NEXT: retq ++; ++; AVX512-LABEL: sitofp_load_2i64_to_2f64: ++; AVX512: # BB#0: ++; AVX512-NEXT: vmovdqa64 (%rdi), %xmm0 ++; AVX512-NEXT: vpextrq $1, %xmm0, %rax ++; AVX512-NEXT: vcvtsi2sdq %rax, %xmm1, %xmm1 ++; AVX512-NEXT: vmovq %xmm0, %rax ++; AVX512-NEXT: vcvtsi2sdq %rax, %xmm2, %xmm0 ++; AVX512-NEXT: vunpcklpd {{.*#+}} xmm0 = xmm0[0],xmm1[0] ++; AVX512-NEXT: retq + %ld = load <2 x i64>, <2 x i64> *%a + %cvt = sitofp <2 x i64> %ld to <2 x double> + ret <2 x double> %cvt +@@ -1930,15 +1980,14 @@ define <4 x double> @sitofp_load_4i64_to_4f64(<4 x i64> *%a) { + ; AVX1-NEXT: vmovaps (%rdi), %ymm0 + ; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm1 + ; AVX1-NEXT: vpextrq $1, %xmm1, %rax +-; AVX1-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2sdq %rax, %xmm2, %xmm2 + ; AVX1-NEXT: vmovq %xmm1, %rax +-; AVX1-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm1 ++; AVX1-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm1 + ; AVX1-NEXT: vunpcklpd {{.*#+}} xmm1 = xmm1[0],xmm2[0] + ; AVX1-NEXT: vpextrq $1, %xmm0, %rax +-; AVX1-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm2 + ; AVX1-NEXT: vmovq %xmm0, %rax +-; AVX1-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX1-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm0 ++; AVX1-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm0 + ; AVX1-NEXT: vunpcklpd {{.*#+}} xmm0 = xmm0[0],xmm2[0] + ; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 + ; AVX1-NEXT: retq +@@ -1948,18 +1997,34 @@ define <4 x double> @sitofp_load_4i64_to_4f64(<4 x i64> *%a) { + ; AVX2-NEXT: vmovdqa (%rdi), %ymm0 + ; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm1 + ; AVX2-NEXT: vpextrq $1, %xmm1, %rax +-; AVX2-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2sdq %rax, %xmm2, %xmm2 + ; AVX2-NEXT: vmovq %xmm1, %rax +-; AVX2-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm1 ++; AVX2-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm1 + ; AVX2-NEXT: vunpcklpd {{.*#+}} xmm1 = xmm1[0],xmm2[0] + ; AVX2-NEXT: vpextrq $1, %xmm0, %rax +-; AVX2-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm2 + ; AVX2-NEXT: vmovq %xmm0, %rax +-; AVX2-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX2-NEXT: vcvtsi2sdq %rax, %xmm0, %xmm0 ++; AVX2-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm0 + ; AVX2-NEXT: vunpcklpd {{.*#+}} xmm0 = xmm0[0],xmm2[0] + ; AVX2-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 + ; AVX2-NEXT: retq ++; ++; AVX512-LABEL: sitofp_load_4i64_to_4f64: ++; AVX512: # BB#0: ++; AVX512-NEXT: vmovdqa64 (%rdi), %ymm0 ++; AVX512-NEXT: vextracti32x4 $1, %ymm0, %xmm1 ++; AVX512-NEXT: vpextrq $1, %xmm1, %rax ++; AVX512-NEXT: vcvtsi2sdq %rax, %xmm2, %xmm2 ++; AVX512-NEXT: vmovq %xmm1, %rax ++; AVX512-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm1 ++; AVX512-NEXT: vunpcklpd {{.*#+}} xmm1 = xmm1[0],xmm2[0] ++; AVX512-NEXT: vpextrq $1, %xmm0, %rax ++; AVX512-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm2 ++; AVX512-NEXT: vmovq %xmm0, %rax ++; AVX512-NEXT: vcvtsi2sdq %rax, %xmm3, %xmm0 ++; AVX512-NEXT: vunpcklpd {{.*#+}} xmm0 = xmm0[0],xmm2[0] ++; AVX512-NEXT: vinsertf32x4 $1, %xmm1, %ymm0, %ymm0 ++; AVX512-NEXT: retq + %ld = load <4 x i64>, <4 x i64> *%a + %cvt = sitofp <4 x i64> %ld to <4 x double> + ret <4 x double> %cvt +@@ -2365,17 +2430,16 @@ define <4 x float> @sitofp_load_4i64_to_4f32(<4 x i64> *%a) { + ; AVX1: # BB#0: + ; AVX1-NEXT: vmovdqa (%rdi), %ymm0 + ; AVX1-NEXT: vpextrq $1, %xmm0, %rax +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 + ; AVX1-NEXT: vmovq %xmm0, %rax +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm2 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm1 = xmm2[0],xmm1[0],xmm2[2,3] + ; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 + ; AVX1-NEXT: vmovq %xmm0, %rax +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm2 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1],xmm2[0],xmm1[3] + ; AVX1-NEXT: vpextrq $1, %xmm0, %rax +-; AVX1-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm0 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm0 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm0[0] + ; AVX1-NEXT: vzeroupper + ; AVX1-NEXT: retq +@@ -2384,20 +2448,36 @@ define <4 x float> @sitofp_load_4i64_to_4f32(<4 x i64> *%a) { + ; AVX2: # BB#0: + ; AVX2-NEXT: vmovdqa (%rdi), %ymm0 + ; AVX2-NEXT: vpextrq $1, %xmm0, %rax +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 + ; AVX2-NEXT: vmovq %xmm0, %rax +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm2 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm1 = xmm2[0],xmm1[0],xmm2[2,3] + ; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm0 + ; AVX2-NEXT: vmovq %xmm0, %rax +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm2 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1],xmm2[0],xmm1[3] + ; AVX2-NEXT: vpextrq $1, %xmm0, %rax +-; AVX2-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm0 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm0 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm0[0] + ; AVX2-NEXT: vzeroupper + ; AVX2-NEXT: retq ++; ++; AVX512-LABEL: sitofp_load_4i64_to_4f32: ++; AVX512: # BB#0: ++; AVX512-NEXT: vmovdqa64 (%rdi), %ymm0 ++; AVX512-NEXT: vpextrq $1, %xmm0, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 ++; AVX512-NEXT: vmovq %xmm0, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm2 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm1 = xmm2[0],xmm1[0],xmm2[2,3] ++; AVX512-NEXT: vextracti32x4 $1, %ymm0, %xmm0 ++; AVX512-NEXT: vmovq %xmm0, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm2 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1],xmm2[0],xmm1[3] ++; AVX512-NEXT: vpextrq $1, %xmm0, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm0 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm0[0] ++; AVX512-NEXT: retq + %ld = load <4 x i64>, <4 x i64> *%a + %cvt = sitofp <4 x i64> %ld to <4 x float> + ret <4 x float> %cvt +@@ -2503,29 +2583,28 @@ define <8 x float> @sitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX1-NEXT: vmovdqa (%rdi), %ymm0 + ; AVX1-NEXT: vmovdqa 32(%rdi), %ymm1 + ; AVX1-NEXT: vpextrq $1, %xmm1, %rax +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm2 + ; AVX1-NEXT: vmovq %xmm1, %rax +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm3 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm3 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm2 = xmm3[0],xmm2[0],xmm3[2,3] + ; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm1 + ; AVX1-NEXT: vmovq %xmm1, %rax +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm3 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm3 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm2 = xmm2[0,1],xmm3[0],xmm2[3] + ; AVX1-NEXT: vpextrq $1, %xmm1, %rax +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm1 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm1 = xmm2[0,1,2],xmm1[0] + ; AVX1-NEXT: vpextrq $1, %xmm0, %rax +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm2 + ; AVX1-NEXT: vmovq %xmm0, %rax +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm3 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm3 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm2 = xmm3[0],xmm2[0],xmm3[2,3] + ; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 + ; AVX1-NEXT: vmovq %xmm0, %rax +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm3 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm3 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm2 = xmm2[0,1],xmm3[0],xmm2[3] + ; AVX1-NEXT: vpextrq $1, %xmm0, %rax +-; AVX1-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm0 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm0 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm0 = xmm2[0,1,2],xmm0[0] + ; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 + ; AVX1-NEXT: retq +@@ -2535,32 +2614,62 @@ define <8 x float> @sitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX2-NEXT: vmovdqa (%rdi), %ymm0 + ; AVX2-NEXT: vmovdqa 32(%rdi), %ymm1 + ; AVX2-NEXT: vpextrq $1, %xmm1, %rax +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm2 + ; AVX2-NEXT: vmovq %xmm1, %rax +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm3 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm3 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm2 = xmm3[0],xmm2[0],xmm3[2,3] + ; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm1 + ; AVX2-NEXT: vmovq %xmm1, %rax +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm3 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm3 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm2 = xmm2[0,1],xmm3[0],xmm2[3] + ; AVX2-NEXT: vpextrq $1, %xmm1, %rax +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm1 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm1 = xmm2[0,1,2],xmm1[0] + ; AVX2-NEXT: vpextrq $1, %xmm0, %rax +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm2 + ; AVX2-NEXT: vmovq %xmm0, %rax +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm3 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm3 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm2 = xmm3[0],xmm2[0],xmm3[2,3] + ; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm0 + ; AVX2-NEXT: vmovq %xmm0, %rax +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm3 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm3 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm2 = xmm2[0,1],xmm3[0],xmm2[3] + ; AVX2-NEXT: vpextrq $1, %xmm0, %rax +-; AVX2-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm0 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm0 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm0 = xmm2[0,1,2],xmm0[0] + ; AVX2-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 + ; AVX2-NEXT: retq ++; ++; AVX512-LABEL: sitofp_load_8i64_to_8f32: ++; AVX512: # BB#0: ++; AVX512-NEXT: vmovdqa64 (%rdi), %zmm0 ++; AVX512-NEXT: vextracti32x4 $2, %zmm0, %xmm1 ++; AVX512-NEXT: vpextrq $1, %xmm1, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm2 ++; AVX512-NEXT: vmovq %xmm1, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm1 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[2,3] ++; AVX512-NEXT: vextracti32x4 $3, %zmm0, %xmm2 ++; AVX512-NEXT: vmovq %xmm2, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm3 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1],xmm3[0],xmm1[3] ++; AVX512-NEXT: vpextrq $1, %xmm2, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm2 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1,2],xmm2[0] ++; AVX512-NEXT: vpextrq $1, %xmm0, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm2 ++; AVX512-NEXT: vmovq %xmm0, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm3 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm2 = xmm3[0],xmm2[0],xmm3[2,3] ++; AVX512-NEXT: vextracti32x4 $1, %zmm0, %xmm0 ++; AVX512-NEXT: vmovq %xmm0, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm3 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm2 = xmm2[0,1],xmm3[0],xmm2[3] ++; AVX512-NEXT: vpextrq $1, %xmm0, %rax ++; AVX512-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm0 ++; AVX512-NEXT: vinsertps {{.*#+}} xmm0 = xmm2[0,1,2],xmm0[0] ++; AVX512-NEXT: vinsertf32x4 $1, %xmm1, %ymm0, %ymm0 ++; AVX512-NEXT: retq + %ld = load <8 x i64>, <8 x i64> *%a + %cvt = sitofp <8 x i64> %ld to <8 x float> + ret <8 x float> %cvt +@@ -2733,12 +2842,12 @@ define <4 x float> @uitofp_load_4i64_to_4f32(<4 x i64> *%a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB74_1 + ; AVX1-NEXT: # BB#2: +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 + ; AVX1-NEXT: jmp .LBB74_3 + ; AVX1-NEXT: .LBB74_1: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm1 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm1, %xmm1 + ; AVX1-NEXT: vaddss %xmm1, %xmm1, %xmm1 + ; AVX1-NEXT: .LBB74_3: + ; AVX1-NEXT: vmovq %xmm0, %rax +@@ -2747,12 +2856,12 @@ define <4 x float> @uitofp_load_4i64_to_4f32(<4 x i64> *%a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB74_4 + ; AVX1-NEXT: # BB#5: +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm2 + ; AVX1-NEXT: jmp .LBB74_6 + ; AVX1-NEXT: .LBB74_4: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm2, %xmm2 + ; AVX1-NEXT: vaddss %xmm2, %xmm2, %xmm2 + ; AVX1-NEXT: .LBB74_6: + ; AVX1-NEXT: vinsertps {{.*#+}} xmm1 = xmm2[0],xmm1[0],xmm2[2,3] +@@ -2763,12 +2872,12 @@ define <4 x float> @uitofp_load_4i64_to_4f32(<4 x i64> *%a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB74_7 + ; AVX1-NEXT: # BB#8: +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm2 + ; AVX1-NEXT: jmp .LBB74_9 + ; AVX1-NEXT: .LBB74_7: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm3, %xmm2 + ; AVX1-NEXT: vaddss %xmm2, %xmm2, %xmm2 + ; AVX1-NEXT: .LBB74_9: + ; AVX1-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1],xmm2[0],xmm1[3] +@@ -2778,16 +2887,14 @@ define <4 x float> @uitofp_load_4i64_to_4f32(<4 x i64> *%a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB74_10 + ; AVX1-NEXT: # BB#11: +-; AVX1-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm0 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm0 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm0[0] + ; AVX1-NEXT: vzeroupper + ; AVX1-NEXT: retq + ; AVX1-NEXT: .LBB74_10: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm0 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm3, %xmm0 + ; AVX1-NEXT: vaddss %xmm0, %xmm0, %xmm0 + ; AVX1-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm0[0] + ; AVX1-NEXT: vzeroupper +@@ -2802,12 +2909,12 @@ define <4 x float> @uitofp_load_4i64_to_4f32(<4 x i64> *%a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB74_1 + ; AVX2-NEXT: # BB#2: +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 + ; AVX2-NEXT: jmp .LBB74_3 + ; AVX2-NEXT: .LBB74_1: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm1 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm1, %xmm1 + ; AVX2-NEXT: vaddss %xmm1, %xmm1, %xmm1 + ; AVX2-NEXT: .LBB74_3: + ; AVX2-NEXT: vmovq %xmm0, %rax +@@ -2816,12 +2923,12 @@ define <4 x float> @uitofp_load_4i64_to_4f32(<4 x i64> *%a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB74_4 + ; AVX2-NEXT: # BB#5: +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm2, %xmm2 + ; AVX2-NEXT: jmp .LBB74_6 + ; AVX2-NEXT: .LBB74_4: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm2, %xmm2 + ; AVX2-NEXT: vaddss %xmm2, %xmm2, %xmm2 + ; AVX2-NEXT: .LBB74_6: + ; AVX2-NEXT: vinsertps {{.*#+}} xmm1 = xmm2[0],xmm1[0],xmm2[2,3] +@@ -2832,12 +2939,12 @@ define <4 x float> @uitofp_load_4i64_to_4f32(<4 x i64> *%a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB74_7 + ; AVX2-NEXT: # BB#8: +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm2 + ; AVX2-NEXT: jmp .LBB74_9 + ; AVX2-NEXT: .LBB74_7: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm3, %xmm2 + ; AVX2-NEXT: vaddss %xmm2, %xmm2, %xmm2 + ; AVX2-NEXT: .LBB74_9: + ; AVX2-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1],xmm2[0],xmm1[3] +@@ -2847,16 +2954,14 @@ define <4 x float> @uitofp_load_4i64_to_4f32(<4 x i64> *%a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB74_10 + ; AVX2-NEXT: # BB#11: +-; AVX2-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm0 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm0 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm0[0] + ; AVX2-NEXT: vzeroupper + ; AVX2-NEXT: retq + ; AVX2-NEXT: .LBB74_10: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm0 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm3, %xmm0 + ; AVX2-NEXT: vaddss %xmm0, %xmm0, %xmm0 + ; AVX2-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm0[0] + ; AVX2-NEXT: vzeroupper +@@ -3094,12 +3199,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB78_1 + ; AVX1-NEXT: # BB#2: +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 + ; AVX1-NEXT: jmp .LBB78_3 + ; AVX1-NEXT: .LBB78_1: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm1 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm1, %xmm1 + ; AVX1-NEXT: vaddss %xmm1, %xmm1, %xmm1 + ; AVX1-NEXT: .LBB78_3: + ; AVX1-NEXT: vmovq %xmm2, %rax +@@ -3108,12 +3213,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB78_4 + ; AVX1-NEXT: # BB#5: +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm3 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm3 + ; AVX1-NEXT: jmp .LBB78_6 + ; AVX1-NEXT: .LBB78_4: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm3 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm3, %xmm3 + ; AVX1-NEXT: vaddss %xmm3, %xmm3, %xmm3 + ; AVX1-NEXT: .LBB78_6: + ; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm2 +@@ -3123,12 +3228,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB78_7 + ; AVX1-NEXT: # BB#8: +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm4 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm4 + ; AVX1-NEXT: jmp .LBB78_9 + ; AVX1-NEXT: .LBB78_7: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm4 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm4, %xmm4 + ; AVX1-NEXT: vaddss %xmm4, %xmm4, %xmm4 + ; AVX1-NEXT: .LBB78_9: + ; AVX1-NEXT: vpextrq $1, %xmm2, %rax +@@ -3137,12 +3242,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB78_10 + ; AVX1-NEXT: # BB#11: +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm5, %xmm2 + ; AVX1-NEXT: jmp .LBB78_12 + ; AVX1-NEXT: .LBB78_10: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm5, %xmm2 + ; AVX1-NEXT: vaddss %xmm2, %xmm2, %xmm2 + ; AVX1-NEXT: .LBB78_12: + ; AVX1-NEXT: vpextrq $1, %xmm0, %rax +@@ -3151,12 +3256,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB78_13 + ; AVX1-NEXT: # BB#14: +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm5 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm5, %xmm5 + ; AVX1-NEXT: jmp .LBB78_15 + ; AVX1-NEXT: .LBB78_13: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm5 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm5, %xmm5 + ; AVX1-NEXT: vaddss %xmm5, %xmm5, %xmm5 + ; AVX1-NEXT: .LBB78_15: + ; AVX1-NEXT: vinsertps {{.*#+}} xmm1 = xmm3[0],xmm1[0],xmm3[2,3] +@@ -3166,12 +3271,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB78_16 + ; AVX1-NEXT: # BB#17: +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm3 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm6, %xmm3 + ; AVX1-NEXT: jmp .LBB78_18 + ; AVX1-NEXT: .LBB78_16: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm3 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm6, %xmm3 + ; AVX1-NEXT: vaddss %xmm3, %xmm3, %xmm3 + ; AVX1-NEXT: .LBB78_18: + ; AVX1-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1],xmm4[0],xmm1[3] +@@ -3183,14 +3288,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB78_19 + ; AVX1-NEXT: # BB#20: +-; AVX1-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm5 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm6, %xmm5 + ; AVX1-NEXT: jmp .LBB78_21 + ; AVX1-NEXT: .LBB78_19: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm0 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm6, %xmm0 + ; AVX1-NEXT: vaddss %xmm0, %xmm0, %xmm5 + ; AVX1-NEXT: .LBB78_21: + ; AVX1-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm2[0] +@@ -3201,12 +3304,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX1-NEXT: testq %rax, %rax + ; AVX1-NEXT: js .LBB78_22 + ; AVX1-NEXT: # BB#23: +-; AVX1-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rax, %xmm6, %xmm2 + ; AVX1-NEXT: jmp .LBB78_24 + ; AVX1-NEXT: .LBB78_22: + ; AVX1-NEXT: shrq %rax + ; AVX1-NEXT: orq %rax, %rcx +-; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm2 ++; AVX1-NEXT: vcvtsi2ssq %rcx, %xmm6, %xmm2 + ; AVX1-NEXT: vaddss %xmm2, %xmm2, %xmm2 + ; AVX1-NEXT: .LBB78_24: + ; AVX1-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1,2],xmm2[0] +@@ -3223,12 +3326,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB78_1 + ; AVX2-NEXT: # BB#2: +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm1 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm1, %xmm1 + ; AVX2-NEXT: jmp .LBB78_3 + ; AVX2-NEXT: .LBB78_1: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm1 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm1, %xmm1 + ; AVX2-NEXT: vaddss %xmm1, %xmm1, %xmm1 + ; AVX2-NEXT: .LBB78_3: + ; AVX2-NEXT: vmovq %xmm2, %rax +@@ -3237,12 +3340,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB78_4 + ; AVX2-NEXT: # BB#5: +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm3 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm3, %xmm3 + ; AVX2-NEXT: jmp .LBB78_6 + ; AVX2-NEXT: .LBB78_4: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm3 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm3, %xmm3 + ; AVX2-NEXT: vaddss %xmm3, %xmm3, %xmm3 + ; AVX2-NEXT: .LBB78_6: + ; AVX2-NEXT: vextracti128 $1, %ymm2, %xmm2 +@@ -3252,12 +3355,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB78_7 + ; AVX2-NEXT: # BB#8: +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm4 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm4, %xmm4 + ; AVX2-NEXT: jmp .LBB78_9 + ; AVX2-NEXT: .LBB78_7: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm4 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm4, %xmm4 + ; AVX2-NEXT: vaddss %xmm4, %xmm4, %xmm4 + ; AVX2-NEXT: .LBB78_9: + ; AVX2-NEXT: vpextrq $1, %xmm2, %rax +@@ -3266,12 +3369,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB78_10 + ; AVX2-NEXT: # BB#11: +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm5, %xmm2 + ; AVX2-NEXT: jmp .LBB78_12 + ; AVX2-NEXT: .LBB78_10: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm5, %xmm2 + ; AVX2-NEXT: vaddss %xmm2, %xmm2, %xmm2 + ; AVX2-NEXT: .LBB78_12: + ; AVX2-NEXT: vpextrq $1, %xmm0, %rax +@@ -3280,12 +3383,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB78_13 + ; AVX2-NEXT: # BB#14: +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm5 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm5, %xmm5 + ; AVX2-NEXT: jmp .LBB78_15 + ; AVX2-NEXT: .LBB78_13: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm5 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm5, %xmm5 + ; AVX2-NEXT: vaddss %xmm5, %xmm5, %xmm5 + ; AVX2-NEXT: .LBB78_15: + ; AVX2-NEXT: vinsertps {{.*#+}} xmm1 = xmm3[0],xmm1[0],xmm3[2,3] +@@ -3295,12 +3398,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB78_16 + ; AVX2-NEXT: # BB#17: +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm3 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm6, %xmm3 + ; AVX2-NEXT: jmp .LBB78_18 + ; AVX2-NEXT: .LBB78_16: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm3 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm6, %xmm3 + ; AVX2-NEXT: vaddss %xmm3, %xmm3, %xmm3 + ; AVX2-NEXT: .LBB78_18: + ; AVX2-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1],xmm4[0],xmm1[3] +@@ -3312,14 +3415,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB78_19 + ; AVX2-NEXT: # BB#20: +-; AVX2-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm5 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm6, %xmm5 + ; AVX2-NEXT: jmp .LBB78_21 + ; AVX2-NEXT: .LBB78_19: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vxorps %xmm0, %xmm0, %xmm0 +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm0 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm6, %xmm0 + ; AVX2-NEXT: vaddss %xmm0, %xmm0, %xmm5 + ; AVX2-NEXT: .LBB78_21: + ; AVX2-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0,1,2],xmm2[0] +@@ -3330,12 +3431,12 @@ define <8 x float> @uitofp_load_8i64_to_8f32(<8 x i64> *%a) { + ; AVX2-NEXT: testq %rax, %rax + ; AVX2-NEXT: js .LBB78_22 + ; AVX2-NEXT: # BB#23: +-; AVX2-NEXT: vcvtsi2ssq %rax, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rax, %xmm6, %xmm2 + ; AVX2-NEXT: jmp .LBB78_24 + ; AVX2-NEXT: .LBB78_22: + ; AVX2-NEXT: shrq %rax + ; AVX2-NEXT: orq %rax, %rcx +-; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm0, %xmm2 ++; AVX2-NEXT: vcvtsi2ssq %rcx, %xmm6, %xmm2 + ; AVX2-NEXT: vaddss %xmm2, %xmm2, %xmm2 + ; AVX2-NEXT: .LBB78_24: + ; AVX2-NEXT: vinsertps {{.*#+}} xmm1 = xmm1[0,1,2],xmm2[0] +-- +2.11.0 + diff --git a/deps/patches/llvm-PR278923.patch b/deps/patches/llvm-PR278923.patch new file mode 100644 index 0000000000000..486777711193a --- /dev/null +++ b/deps/patches/llvm-PR278923.patch @@ -0,0 +1,69 @@ +From 77eee1c0f05c587e7fb8a9a2064908d7333dcfb9 Mon Sep 17 00:00:00 2001 +From: Marina Yatsina +Date: Wed, 17 Aug 2016 11:40:21 +0000 +Subject: [PATCH 5/5] Fixing bug committed in rev. 278321 + +In theory the indices of RC (and thus the index used for LiveRegs) may differ from the indices of OpRC. +Fixed the code to extract the correct RC index. +OpRC contains the first X consecutive elements of RC, and thus their indices are currently de facto the same, therefore a test cannot be added at this point. + +Differential Revision: https://reviews.llvm.org/D23491 + + + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@278923 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + include/llvm/Target/TargetRegisterInfo.h | 6 ++++++ + lib/CodeGen/ExecutionDepsFix.cpp | 9 ++++++--- + 2 files changed, 12 insertions(+), 3 deletions(-) + +diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h +index e5a6c8ed2f2..e5642493928 100644 +--- a/include/llvm/Target/TargetRegisterInfo.h ++++ b/include/llvm/Target/TargetRegisterInfo.h +@@ -17,6 +17,7 @@ + #define LLVM_TARGET_TARGETREGISTERINFO_H + + #include "llvm/ADT/ArrayRef.h" ++#include "llvm/ADT/iterator_range.h" + #include "llvm/CodeGen/MachineBasicBlock.h" + #include "llvm/CodeGen/MachineValueType.h" + #include "llvm/IR/CallingConv.h" +@@ -86,6 +87,11 @@ public: + + /// Return the number of registers in this class. + unsigned getNumRegs() const { return MC->getNumRegs(); } ++ ++ iterator_range::const_iterator> ++ getRegisters() const { ++ return make_range(MC->begin(), MC->end()); ++ } + + /// Return the specified register in the class. + unsigned getRegister(unsigned i) const { +diff --git a/lib/CodeGen/ExecutionDepsFix.cpp b/lib/CodeGen/ExecutionDepsFix.cpp +index 5f91db9251c..213dd58a31d 100644 +--- a/lib/CodeGen/ExecutionDepsFix.cpp ++++ b/lib/CodeGen/ExecutionDepsFix.cpp +@@ -509,12 +509,15 @@ void ExeDepsFix::pickBestRegisterForUndef(MachineInstr *MI, unsigned OpIdx, + // max clearance or clearance higher than Pref. + unsigned MaxClearance = 0; + unsigned MaxClearanceReg = OriginalReg; +- for (unsigned rx = 0; rx < OpRC->getNumRegs(); ++rx) { +- unsigned Clearance = CurInstr - LiveRegs[rx].Def; ++ for (auto Reg : OpRC->getRegisters()) { ++ assert(AliasMap[Reg].size() == 1 && ++ "Reg is expected to be mapped to a single index"); ++ int RCrx = *regIndices(Reg).begin(); ++ unsigned Clearance = CurInstr - LiveRegs[RCrx].Def; + if (Clearance <= MaxClearance) + continue; + MaxClearance = Clearance; +- MaxClearanceReg = OpRC->getRegister(rx); ++ MaxClearanceReg = Reg; + + if (MaxClearance > Pref) + break; +-- +2.11.0 + From e1f8faf172a32888c4583f34317fd9ab31927e0b Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Mon, 16 Jan 2017 00:38:00 -0500 Subject: [PATCH 0002/1534] Add LLVM Patch D28759 --- deps/llvm.mk | 1 + deps/patches/llvm-D28759-loopclearance.patch | 480 +++++++++++++++++++ 2 files changed, 481 insertions(+) create mode 100644 deps/patches/llvm-D28759-loopclearance.patch diff --git a/deps/llvm.mk b/deps/llvm.mk index 387c4ba5f82ee..62045da77e1a9 100644 --- a/deps/llvm.mk +++ b/deps/llvm.mk @@ -510,6 +510,7 @@ $(eval $(call LLVM_PATCH,llvm-PR278088)) # Issue #19976, Remove for 4.0 $(eval $(call LLVM_PATCH,llvm-PR277939)) # Issue #19976, Remove for 4.0 $(eval $(call LLVM_PATCH,llvm-PR278321)) # Issue #19976, Remove for 4.0 $(eval $(call LLVM_PATCH,llvm-PR278923)) # Issue #19976, Remove for 4.0 +$(eval $(call LLVM_PATCH,llvm-D28759-loopclearance)) endif # LLVM_VER ifeq ($(LLVM_VER),3.7.1) diff --git a/deps/patches/llvm-D28759-loopclearance.patch b/deps/patches/llvm-D28759-loopclearance.patch new file mode 100644 index 0000000000000..036ca4d83103c --- /dev/null +++ b/deps/patches/llvm-D28759-loopclearance.patch @@ -0,0 +1,480 @@ +From e3621af0115a851d0ed02f0b436deec62ec3e99c Mon Sep 17 00:00:00 2001 +From: Keno Fischer +Date: Sun, 15 Jan 2017 23:59:07 -0500 +Subject: [PATCH] [ExecutionDepsFix] Improve clearance calculation for loops + +In revision rL278321, ExecutionDepsFix learned how to pick a better +register for undef register reads, e.g. for instructions such as +`vcvtsi2sdq`. While this revision improved performance on a good number +of our benchmarks, it unfortunately also caused significant regressions +(up to 3x) on others. This regression turned out to be caused by loops +such as: + +PH -> A -> B (xmm -> xmm) -> C -> D -> EXIT + ^ | + +----------------------------------+ + +In the previous version of the clearance calculation, we would visit +the blocks in order, remembering for each whether there were any +incoming backedges from blocks that we hadn't processed yet and if +so queuing up the block to be re-processed. However, for loop structures +such as the above, this is clearly insufficient, since the block B +does not have any unknown backedges, so we do not see the false +dependency from the previous interation's Def of xmm registers in B. + +To fix this, we need to consider all blocks that are part of the loop +and reprocess them one the correct clearance values are known. As +an optimization, we also want to avoid reprocessing any later blocks +that are not part of the loop. + +In summary, the iteration order is as follows: +Before: PH A B C D A' +Corrected (Naive): PH A B C D A' B' C' D' +Corrected (w/ optimization): PH A B C A' B' C' D + +To facilitate this optimization we introduce two new counters for each +basic block. The first counts how many of it's predecssors have +completed primary processing. The second counts how many of its +predecessors have completed all processing (we will call such a block +*done*. Now, the criteria to reprocess a block is as follows: + - All Predecessors have completed primary processing + - For x the number of predecessors that have completed primary + processing *at the time of primary processing of this block*, + the number of predecessors that are done has reached x. + +The intuition behind this criterion is as follows: +We need to perform primary processing on all predecessors in order to +find out any direct defs in those predecessors. When predecessors are +done, we also know that we have information about indirect defs (e.g. +in block B though that were inherited through B->C->A->B). However, +we can't wait for all predecessors to be done, since that would +cause cyclic dependencies. However, it is guaranteed that all those +predecessors that are prior to us in reverse postorder will be done +before us. Since we iterate of the basic blocks in reverse postorder, +the number x above, is precisely the count of the number of predecessors +prior to us in reverse postorder. +--- + lib/CodeGen/ExecutionDepsFix.cpp | 223 ++++++++++++++++++++++-------------- + test/CodeGen/X86/break-false-dep.ll | 57 +++++++++ + 2 files changed, 197 insertions(+), 83 deletions(-) + +diff --git a/lib/CodeGen/ExecutionDepsFix.cpp b/lib/CodeGen/ExecutionDepsFix.cpp +index e7c6b03..6ac1db4 100644 +--- a/lib/CodeGen/ExecutionDepsFix.cpp ++++ b/lib/CodeGen/ExecutionDepsFix.cpp +@@ -142,8 +142,26 @@ class ExeDepsFix : public MachineFunctionPass { + std::vector> AliasMap; + const unsigned NumRegs; + LiveReg *LiveRegs; +- typedef DenseMap LiveOutMap; +- LiveOutMap LiveOuts; ++ struct MBBInfo { ++ // Keeps clearance and domain information for all registers. Not that this ++ // is different from the usual definition notion of liveness. The CPU ++ // doesn't care whether or not we consider a register killed. ++ LiveReg *OutRegs; ++ ++ // Whether we have gotten to this block in primary processing yet. ++ bool PrimaryCompleted; ++ ++ // The number of predecessors for which primary processing has completed ++ unsigned IncomingProcessed; ++ ++ // The value of `IncomingProcessed` at the start of primary processing ++ unsigned PrimaryIncoming; ++ ++ // The number of predecessors for which all processing steps are done. ++ unsigned IncomingCompleted; ++ }; ++ typedef DenseMap MBBInfoMap; ++ MBBInfoMap MBBInfos; + + /// List of undefined register reads in this block in forward order. + std::vector > UndefReads; +@@ -154,11 +172,6 @@ class ExeDepsFix : public MachineFunctionPass { + /// Current instruction number. + /// The first instruction in each basic block is 0. + int CurInstr; +- +- /// True when the current block has a predecessor that hasn't been visited +- /// yet. +- bool SeenUnknownBackEdge; +- + public: + ExeDepsFix(const TargetRegisterClass *rc) + : MachineFunctionPass(ID), RC(rc), NumRegs(RC->getNumRegs()) {} +@@ -180,7 +193,6 @@ public: + private: + iterator_range::const_iterator> + regIndices(unsigned Reg) const; +- + // DomainValue allocation. + DomainValue *alloc(int domain = -1); + DomainValue *retain(DomainValue *DV) { +@@ -199,8 +211,11 @@ private: + + void enterBasicBlock(MachineBasicBlock*); + void leaveBasicBlock(MachineBasicBlock*); +- void visitInstr(MachineInstr*); +- void processDefs(MachineInstr*, bool Kill); ++ bool isBlockDone(MachineBasicBlock *); ++ void processBasicBlock(MachineBasicBlock *MBB, bool PrimaryPass, bool Done); ++ void updateSuccessors(MachineBasicBlock *MBB, bool Primary, bool Done); ++ bool visitInstr(MachineInstr *); ++ void processDefs(MachineInstr *, bool BlockDone, bool Kill); + void visitSoftInstr(MachineInstr*, unsigned mask); + void visitHardInstr(MachineInstr*, unsigned domain); + void pickBestRegisterForUndef(MachineInstr *MI, unsigned OpIdx, +@@ -360,9 +375,6 @@ bool ExeDepsFix::merge(DomainValue *A, DomainValue *B) { + + /// Set up LiveRegs by merging predecessor live-out values. + void ExeDepsFix::enterBasicBlock(MachineBasicBlock *MBB) { +- // Detect back-edges from predecessors we haven't processed yet. +- SeenUnknownBackEdge = false; +- + // Reset instruction counter in each basic block. + CurInstr = 0; + +@@ -397,18 +409,18 @@ void ExeDepsFix::enterBasicBlock(MachineBasicBlock *MBB) { + // Try to coalesce live-out registers from predecessors. + for (MachineBasicBlock::const_pred_iterator pi = MBB->pred_begin(), + pe = MBB->pred_end(); pi != pe; ++pi) { +- LiveOutMap::const_iterator fi = LiveOuts.find(*pi); +- if (fi == LiveOuts.end()) { +- SeenUnknownBackEdge = true; ++ auto fi = MBBInfos.find(*pi); ++ assert(fi != MBBInfos.end()); ++ LiveReg *Incoming = fi->second.OutRegs; ++ if (Incoming == nullptr) { + continue; + } +- assert(fi->second && "Can't have NULL entries"); + + for (unsigned rx = 0; rx != NumRegs; ++rx) { + // Use the most recent predecessor def for each register. +- LiveRegs[rx].Def = std::max(LiveRegs[rx].Def, fi->second[rx].Def); ++ LiveRegs[rx].Def = std::max(LiveRegs[rx].Def, Incoming[rx].Def); + +- DomainValue *pdv = resolve(fi->second[rx].Value); ++ DomainValue *pdv = resolve(Incoming[rx].Value); + if (!pdv) + continue; + if (!LiveRegs[rx].Value) { +@@ -432,35 +444,33 @@ void ExeDepsFix::enterBasicBlock(MachineBasicBlock *MBB) { + force(rx, pdv->getFirstDomain()); + } + } +- DEBUG(dbgs() << "BB#" << MBB->getNumber() +- << (SeenUnknownBackEdge ? ": incomplete\n" : ": all preds known\n")); ++ DEBUG( ++ dbgs() << "BB#" << MBB->getNumber() ++ << (!isBlockDone(MBB) ? ": incomplete\n" : ": all preds known\n")); + } + + void ExeDepsFix::leaveBasicBlock(MachineBasicBlock *MBB) { + assert(LiveRegs && "Must enter basic block first."); ++ LiveReg *OldOutRegs = MBBInfos[MBB].OutRegs; + // Save live registers at end of MBB - used by enterBasicBlock(). + // Also use LiveOuts as a visited set to detect back-edges. +- bool First = LiveOuts.insert(std::make_pair(MBB, LiveRegs)).second; +- +- if (First) { +- // LiveRegs was inserted in LiveOuts. Adjust all defs to be relative to +- // the end of this block instead of the beginning. +- for (unsigned i = 0, e = NumRegs; i != e; ++i) +- LiveRegs[i].Def -= CurInstr; +- } else { +- // Insertion failed, this must be the second pass. ++ MBBInfos[MBB].OutRegs = LiveRegs; ++ ++ // LiveRegs was inserted in LiveOuts. Adjust all defs to be relative to ++ // the end of this block instead of the beginning. ++ for (unsigned i = 0, e = NumRegs; i != e; ++i) ++ LiveRegs[i].Def -= CurInstr; ++ if (OldOutRegs) { ++ // This must be the second pass. + // Release all the DomainValues instead of keeping them. + for (unsigned i = 0, e = NumRegs; i != e; ++i) +- release(LiveRegs[i].Value); +- delete[] LiveRegs; ++ release(OldOutRegs[i].Value); ++ delete[] OldOutRegs; + } + LiveRegs = nullptr; + } + +-void ExeDepsFix::visitInstr(MachineInstr *MI) { +- if (MI->isDebugValue()) +- return; +- ++bool ExeDepsFix::visitInstr(MachineInstr *MI) { + // Update instructions with explicit execution domains. + std::pair DomP = TII->getExecutionDomain(*MI); + if (DomP.first) { +@@ -470,9 +480,7 @@ void ExeDepsFix::visitInstr(MachineInstr *MI) { + visitHardInstr(MI, DomP.first); + } + +- // Process defs to track register ages, and kill values clobbered by generic +- // instructions. +- processDefs(MI, !DomP.first); ++ return !DomP.first; + } + + /// \brief Helps avoid false dependencies on undef registers by updating the +@@ -542,14 +550,7 @@ bool ExeDepsFix::shouldBreakDependence(MachineInstr *MI, unsigned OpIdx, + DEBUG(dbgs() << ": Break dependency.\n"); + continue; + } +- // The current clearance seems OK, but we may be ignoring a def from a +- // back-edge. +- if (!SeenUnknownBackEdge || Pref <= unsigned(CurInstr)) { +- DEBUG(dbgs() << ": OK .\n"); +- return false; +- } +- // A def from an unprocessed back-edge may make us break this dependency. +- DEBUG(dbgs() << ": Wait for back-edge to resolve.\n"); ++ DEBUG(dbgs() << ": OK .\n"); + return false; + } + return true; +@@ -559,16 +560,21 @@ bool ExeDepsFix::shouldBreakDependence(MachineInstr *MI, unsigned OpIdx, + // If Kill is set, also kill off DomainValues clobbered by the defs. + // + // Also break dependencies on partial defs and undef uses. +-void ExeDepsFix::processDefs(MachineInstr *MI, bool Kill) { ++void ExeDepsFix::processDefs(MachineInstr *MI, bool BlockDone, bool Kill) { + assert(!MI->isDebugValue() && "Won't process debug values"); + + // Break dependence on undef uses. Do this before updating LiveRegs below. + unsigned OpNum; +- unsigned Pref = TII->getUndefRegClearance(*MI, OpNum, TRI); +- if (Pref) { +- pickBestRegisterForUndef(MI, OpNum, Pref); +- if (shouldBreakDependence(MI, OpNum, Pref)) +- UndefReads.push_back(std::make_pair(MI, OpNum)); ++ // If this block is not done, it makes little sense to make any decisions ++ // based on clearance information. We need to make a second pass anyway, ++ // and by then we'll have better information, so we can avoid this work now. ++ if (BlockDone) { ++ unsigned Pref = TII->getUndefRegClearance(*MI, OpNum, TRI); ++ if (Pref) { ++ pickBestRegisterForUndef(MI, OpNum, Pref); ++ if (shouldBreakDependence(MI, OpNum, Pref)) ++ UndefReads.push_back(std::make_pair(MI, OpNum)); ++ } + } + const MCInstrDesc &MCID = MI->getDesc(); + for (unsigned i = 0, +@@ -584,11 +590,13 @@ void ExeDepsFix::processDefs(MachineInstr *MI, bool Kill) { + DEBUG(dbgs() << TRI->getName(RC->getRegister(rx)) << ":\t" << CurInstr + << '\t' << *MI); + +- // Check clearance before partial register updates. +- // Call breakDependence before setting LiveRegs[rx].Def. +- unsigned Pref = TII->getPartialRegUpdateClearance(*MI, i, TRI); +- if (Pref && shouldBreakDependence(MI, i, Pref)) +- TII->breakPartialRegDependency(*MI, i, TRI); ++ if (BlockDone) { ++ // Check clearance before partial register updates. ++ // Call breakDependence before setting LiveRegs[rx].Def. ++ unsigned Pref = TII->getPartialRegUpdateClearance(*MI, i, TRI); ++ if (Pref && shouldBreakDependence(MI, i, Pref)) ++ TII->breakPartialRegDependency(*MI, i, TRI); ++ } + + // How many instructions since rx was last written? + LiveRegs[rx].Def = CurInstr; +@@ -780,6 +788,45 @@ void ExeDepsFix::visitSoftInstr(MachineInstr *mi, unsigned mask) { + } + } + ++void ExeDepsFix::processBasicBlock(MachineBasicBlock *MBB, bool PrimaryPass, ++ bool Done) { ++ enterBasicBlock(MBB); ++ for (MachineInstr &MI : *MBB) { ++ if (!MI.isDebugValue()) { ++ bool Kill = false; ++ if (PrimaryPass) ++ Kill = visitInstr(&MI); ++ processDefs(&MI, isBlockDone(MBB), Kill); ++ } ++ } ++ processUndefReads(MBB); ++ leaveBasicBlock(MBB); ++} ++ ++bool ExeDepsFix::isBlockDone(MachineBasicBlock *MBB) { ++ return MBBInfos[MBB].PrimaryCompleted && ++ MBBInfos[MBB].IncomingCompleted == MBBInfos[MBB].PrimaryIncoming && ++ MBBInfos[MBB].IncomingProcessed == MBB->pred_size(); ++} ++ ++void ExeDepsFix::updateSuccessors(MachineBasicBlock *MBB, bool Primary, ++ bool Done) { ++ for (auto *Succ : MBB->successors()) { ++ if (!isBlockDone(Succ)) { ++ if (Primary) { ++ MBBInfos[Succ].IncomingProcessed++; ++ } ++ if (Done) { ++ MBBInfos[Succ].IncomingCompleted++; ++ } ++ if (isBlockDone(Succ)) { ++ processBasicBlock(Succ, false, true); ++ updateSuccessors(Succ, false, true); ++ } ++ } ++ } ++} ++ + bool ExeDepsFix::runOnMachineFunction(MachineFunction &mf) { + if (skipFunction(*mf.getFunction())) + return false; +@@ -816,44 +863,54 @@ bool ExeDepsFix::runOnMachineFunction(MachineFunction &mf) { + AliasMap[*AI].push_back(i); + } + ++ // Initialize the MMBInfos ++ for (auto &MBB : mf) { ++ MBBInfo InitialInfo{nullptr, false, 0, 0, 0}; ++ MBBInfos.insert(std::make_pair(&MBB, InitialInfo)); ++ } ++ + MachineBasicBlock *Entry = &*MF->begin(); + ReversePostOrderTraversal RPOT(Entry); +- SmallVector Loops; + for (ReversePostOrderTraversal::rpo_iterator + MBBI = RPOT.begin(), MBBE = RPOT.end(); MBBI != MBBE; ++MBBI) { + MachineBasicBlock *MBB = *MBBI; +- enterBasicBlock(MBB); +- if (SeenUnknownBackEdge) +- Loops.push_back(MBB); +- for (MachineInstr &MI : *MBB) +- visitInstr(&MI); +- processUndefReads(MBB); +- leaveBasicBlock(MBB); +- } +- +- // Visit all the loop blocks again in order to merge DomainValues from +- // back-edges. +- for (MachineBasicBlock *MBB : Loops) { +- enterBasicBlock(MBB); +- for (MachineInstr &MI : *MBB) +- if (!MI.isDebugValue()) +- processDefs(&MI, false); +- processUndefReads(MBB); +- leaveBasicBlock(MBB); ++ MBBInfos[MBB].PrimaryCompleted = true; ++ MBBInfos[MBB].PrimaryIncoming = MBBInfos[MBB].IncomingProcessed; ++ bool PrimaryDone = isBlockDone(MBB); ++ processBasicBlock(MBB, true, PrimaryDone); ++ updateSuccessors(MBB, true, PrimaryDone); ++ } ++ ++ // We need to go through again and finalize any blocks that are not done yet. ++ // This is possible if blocks have dead predecessors, so we didn't visit them ++ // above. N.B.: The reason we update succesors immidately above, rather than ++ // doing everything in one go here, is to avoid having to do two passes on ++ // basic block between loops (with the scheme above, the whole loop will be ++ // completed before moving on to the blocks after it). ++ for (ReversePostOrderTraversal::rpo_iterator ++ MBBI = RPOT.begin(), ++ MBBE = RPOT.end(); ++ MBBI != MBBE; ++MBBI) { ++ MachineBasicBlock *MBB = *MBBI; ++ if (!isBlockDone(MBB)) { ++ processBasicBlock(MBB, false, true); ++ // Don't update successors here. We'll get to them anyway through this ++ // loop. ++ } + } + + // Clear the LiveOuts vectors and collapse any remaining DomainValues. + for (ReversePostOrderTraversal::rpo_iterator + MBBI = RPOT.begin(), MBBE = RPOT.end(); MBBI != MBBE; ++MBBI) { +- LiveOutMap::const_iterator FI = LiveOuts.find(*MBBI); +- if (FI == LiveOuts.end() || !FI->second) ++ auto FI = MBBInfos.find(*MBBI); ++ if (FI == MBBInfos.end() || !FI->second.OutRegs) + continue; + for (unsigned i = 0, e = NumRegs; i != e; ++i) +- if (FI->second[i].Value) +- release(FI->second[i].Value); +- delete[] FI->second; ++ if (FI->second.OutRegs[i].Value) ++ release(FI->second.OutRegs[i].Value); ++ delete[] FI->second.OutRegs; + } +- LiveOuts.clear(); ++ MBBInfos.clear(); + UndefReads.clear(); + Avail.clear(); + Allocator.DestroyAll(); +diff --git a/test/CodeGen/X86/break-false-dep.ll b/test/CodeGen/X86/break-false-dep.ll +index 4c5e747..0ba1825 100644 +--- a/test/CodeGen/X86/break-false-dep.ll ++++ b/test/CodeGen/X86/break-false-dep.ll +@@ -277,3 +277,60 @@ ret: + ;AVX: vcvtsi2sdq {{.*}}, [[XMM4_7:%xmm[4-7]]], {{%xmm[0-9]+}} + ;AVX-NOT: [[XMM4_7]] + } ++ ++; Make sure we are making a smart choice regarding undef registers even for more ++; complicated loop structures. This example is the inner loop from ++; julia> a = falses(10000); a[1:4:end] = true ++; julia> linspace(1.0,2.0,10000)[a] ++define void @loopclearance2(double* nocapture %y, i64* %x, double %c1, double %c2, double %c3, double %c4, i64 %size) { ++entry: ++ tail call void asm sideeffect "", "~{xmm7},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{dirflag},~{fpsr},~{flags}"() ++ br label %loop ++ ++loop: ++ %phi_i = phi i64 [ 1, %entry ], [ %nexti, %loop_end ] ++ %phi_j = phi i64 [ 1, %entry ], [ %nextj, %loop_end ] ++ %phi_k = phi i64 [ 0, %entry ], [ %nextk, %loop_end ] ++ br label %inner_loop ++ ++inner_loop: ++ %phi = phi i64 [ %phi_k, %loop ], [ %nextk, %inner_loop ] ++ %idx = lshr i64 %phi, 6 ++ %inputptr = getelementptr i64, i64* %x, i64 %idx ++ %input = load i64, i64* %inputptr, align 8 ++ %masked = and i64 %phi, 63 ++ %shiftedmasked = shl i64 1, %masked ++ %maskedinput = and i64 %input, %shiftedmasked ++ %cmp = icmp eq i64 %maskedinput, 0 ++ %nextk = add i64 %phi, 1 ++ br i1 %cmp, label %inner_loop, label %loop_end ++ ++loop_end: ++ %nexti = add i64 %phi_i, 1 ++ %nextj = add i64 %phi_j, 1 ++ ; Register use, plus us clobbering 7-15 above, basically forces xmm7 here as ++ ; the only reasonable choice. The primary thing we care about is that it's ++ ; not one of the registers used in the loop (e.g. not the output reg here) ++;AVX-NOT: %xmm6 ++;AVX: vcvtsi2sdq {{.*}}, %xmm6, {{%xmm[0-9]+}} ++;AVX-NOT: %xmm6 ++ %nexti_f = sitofp i64 %nexti to double ++ %sub = fsub double %c1, %nexti_f ++ %mul = fmul double %sub, %c2 ++;AVX: vcvtsi2sdq {{.*}}, %xmm6, {{%xmm[0-9]+}} ++;AVX-NOT: %xmm6 ++ %phi_f = sitofp i64 %phi to double ++ %mul2 = fmul double %phi_f, %c3 ++ %add2 = fadd double %mul, %mul2 ++ %div = fdiv double %add2, %c4 ++ %prev_j = add i64 %phi_j, -1 ++ %outptr = getelementptr double, double* %y, i64 %prev_j ++ store double %div, double* %outptr, align 8 ++ %done = icmp slt i64 %size, %nexti ++ br i1 %done, label %loopdone, label %loop ++ ++loopdone: ++ ret void ++} +-- +2.9.3 From f4cbc403bcf38faac892967a2ba236f8523b2c26 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Mon, 16 Jan 2017 18:56:34 -0500 Subject: [PATCH 0003/1534] Add patch D28786 --- deps/llvm.mk | 1 + deps/patches/llvm-D28786-callclearance.patch | 344 +++++++++++++++++++ 2 files changed, 345 insertions(+) create mode 100644 deps/patches/llvm-D28786-callclearance.patch diff --git a/deps/llvm.mk b/deps/llvm.mk index 62045da77e1a9..18dece27bd08f 100644 --- a/deps/llvm.mk +++ b/deps/llvm.mk @@ -511,6 +511,7 @@ $(eval $(call LLVM_PATCH,llvm-PR277939)) # Issue #19976, Remove for 4.0 $(eval $(call LLVM_PATCH,llvm-PR278321)) # Issue #19976, Remove for 4.0 $(eval $(call LLVM_PATCH,llvm-PR278923)) # Issue #19976, Remove for 4.0 $(eval $(call LLVM_PATCH,llvm-D28759-loopclearance)) +$(eval $(call LLVM_PATCH,llvm-D28786-callclearance)) endif # LLVM_VER ifeq ($(LLVM_VER),3.7.1) diff --git a/deps/patches/llvm-D28786-callclearance.patch b/deps/patches/llvm-D28786-callclearance.patch new file mode 100644 index 0000000000000..fa7dfd3f22d38 --- /dev/null +++ b/deps/patches/llvm-D28786-callclearance.patch @@ -0,0 +1,344 @@ +diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h +index 83515bc..65b435a 100644 +--- a/include/llvm/Target/TargetInstrInfo.h ++++ b/include/llvm/Target/TargetInstrInfo.h +@@ -1440,6 +1440,17 @@ public: + virtual void breakPartialRegDependency(MachineInstr &MI, unsigned OpNum, + const TargetRegisterInfo *TRI) const {} + ++ /// May return true if the instruction in question is a dependency breaking ++ /// instruction. If so, the register number for which it is dependency ++ /// breaking should be returned in `OutReg`. It is prefereable to return ++ /// false if the result cannot be determined. This would at worst result ++ /// in the insertion of an unnecessary instruction, while the other ++ /// alternative could result in significant false-dependency penalties. ++ virtual bool isDependencyBreak(MachineInstr &MI, ++ unsigned *OutReg = nullptr) const { ++ return false; ++ } ++ + /// Create machine specific model for scheduling. + virtual DFAPacketizer * + CreateTargetScheduleState(const TargetSubtargetInfo &) const { +diff --git a/lib/CodeGen/ExecutionDepsFix.cpp b/lib/CodeGen/ExecutionDepsFix.cpp +index 6ac1db4..63065ea 100644 +--- a/lib/CodeGen/ExecutionDepsFix.cpp ++++ b/lib/CodeGen/ExecutionDepsFix.cpp +@@ -214,13 +214,18 @@ private: + bool isBlockDone(MachineBasicBlock *); + void processBasicBlock(MachineBasicBlock *MBB, bool PrimaryPass, bool Done); + void updateSuccessors(MachineBasicBlock *MBB, bool Primary, bool Done); +- bool visitInstr(MachineInstr *); ++ bool visitInstr(MachineInstr *, bool PrimaryPass); + void processDefs(MachineInstr *, bool BlockDone, bool Kill); + void visitSoftInstr(MachineInstr*, unsigned mask); + void visitHardInstr(MachineInstr*, unsigned domain); +- void pickBestRegisterForUndef(MachineInstr *MI, unsigned OpIdx, +- unsigned Pref); ++ void pickBestRegisterForUndef(MachineInstr *MI, unsigned OpIdx, unsigned Pref, ++ bool &TrueDependency); + bool shouldBreakDependence(MachineInstr*, unsigned OpIdx, unsigned Pref); ++ ++ // Undef Reads ++ void collapseUndefReads(unsigned from, unsigned to, unsigned Reg); ++ unsigned updateChooseableRegs(SparseSet &, ++ const TargetRegisterClass *, bool); + void processUndefReads(MachineBasicBlock*); + }; + } +@@ -394,11 +399,19 @@ void ExeDepsFix::enterBasicBlock(MachineBasicBlock *MBB) { + + // This is the entry block. + if (MBB->pred_empty()) { ++ // Treat all registers as being defined just before the first instruction. ++ // Howver, we want the logic later to prefer non live-ins over live-ins, ++ // so pretend the live-ins were defined slightly later. ++ // We used to only do this for live-ins, but that's a bit of a gamble. ++ // If our caller does arithmetic with these registers is is quite likely ++ // that it will have used registers beyond the ones that are live here. ++ // Given the immense penalty for getting this wrong, being conservative ++ // here seems worth it. ++ for (unsigned rx = 0; rx != NumRegs; ++rx) { ++ LiveRegs[rx].Def = -2; ++ } + for (const auto &LI : MBB->liveins()) { + for (int rx : regIndices(LI.PhysReg)) { +- // Treat function live-ins as if they were defined just before the first +- // instruction. Usually, function arguments are set up immediately +- // before the call. + LiveRegs[rx].Def = -1; + } + } +@@ -470,24 +483,36 @@ void ExeDepsFix::leaveBasicBlock(MachineBasicBlock *MBB) { + LiveRegs = nullptr; + } + +-bool ExeDepsFix::visitInstr(MachineInstr *MI) { +- // Update instructions with explicit execution domains. +- std::pair DomP = TII->getExecutionDomain(*MI); +- if (DomP.first) { +- if (DomP.second) +- visitSoftInstr(MI, DomP.second); +- else +- visitHardInstr(MI, DomP.first); ++bool ExeDepsFix::visitInstr(MachineInstr *MI, bool PrimaryPass) { ++ bool Kill = false; ++ ++ if (PrimaryPass) { ++ // Update instructions with explicit execution domains. ++ std::pair DomP = TII->getExecutionDomain(*MI); ++ if (DomP.first) { ++ if (DomP.second) ++ visitSoftInstr(MI, DomP.second); ++ else ++ visitHardInstr(MI, DomP.first); ++ } ++ Kill = !DomP.first; + } + +- return !DomP.first; ++ // If this is a call, pretend all registers we are considering are def'd here. ++ // We have no idea which registers the callee may use. ++ if (MI->isCall()) { ++ for (unsigned i = 0, e = NumRegs; i != e; ++i) ++ LiveRegs[i].Def = CurInstr; ++ } ++ ++ return Kill; + } + + /// \brief Helps avoid false dependencies on undef registers by updating the + /// machine instructions' undef operand to use a register that the instruction + /// is truly dependent on, or use a register with clearance higher than Pref. + void ExeDepsFix::pickBestRegisterForUndef(MachineInstr *MI, unsigned OpIdx, +- unsigned Pref) { ++ unsigned Pref, bool &TrueDependency) { + MachineOperand &MO = MI->getOperand(OpIdx); + assert(MO.isUndef() && "Expected undef machine operand"); + +@@ -510,6 +535,7 @@ void ExeDepsFix::pickBestRegisterForUndef(MachineInstr *MI, unsigned OpIdx, + // We found a true dependency - replace the undef register with the true + // dependency. + MO.setReg(CurrMO.getReg()); ++ TrueDependency = true; + return; + } + +@@ -571,9 +597,14 @@ void ExeDepsFix::processDefs(MachineInstr *MI, bool BlockDone, bool Kill) { + if (BlockDone) { + unsigned Pref = TII->getUndefRegClearance(*MI, OpNum, TRI); + if (Pref) { +- pickBestRegisterForUndef(MI, OpNum, Pref); +- if (shouldBreakDependence(MI, OpNum, Pref)) ++ bool TrueDependency = false; ++ pickBestRegisterForUndef(MI, OpNum, Pref, TrueDependency); ++ // Don't bother adding true dependencies to UndefReads. All we'd find out ++ // is that the register is live (since this very instruction depends on ++ // it), so we can't do anything. ++ if (!TrueDependency && shouldBreakDependence(MI, OpNum, Pref)) { + UndefReads.push_back(std::make_pair(MI, OpNum)); ++ } + } + } + const MCInstrDesc &MCID = MI->getDesc(); +@@ -606,9 +637,52 @@ void ExeDepsFix::processDefs(MachineInstr *MI, bool BlockDone, bool Kill) { + kill(rx); + } + } ++ unsigned DepReg = 0; ++ if (TII->isDependencyBreak(*MI, &DepReg)) { ++ for (int rx : regIndices(DepReg)) { ++ // This instruction is a dependency break, so there are no clearance ++ // issues, reset the counter. ++ LiveRegs[rx].Def = -(1 << 20); ++ } ++ } + ++CurInstr; + } + ++// Set the undef read register to `Reg` for all UndefReads in the range ++// [from,to). ++void ExeDepsFix::collapseUndefReads(unsigned from, unsigned to, unsigned Reg) { ++ if (from >= to) ++ return; ++ for (unsigned i = from; i < to; ++i) { ++ MachineInstr *MI = std::get<0>(UndefReads[i]); ++ unsigned OpIdx = std::get<1>(UndefReads[i]); ++ MachineOperand &MO = MI->getOperand(OpIdx); ++ MO.setReg(Reg); ++ } ++ TII->breakPartialRegDependency(*std::get<0>(UndefReads[from]), ++ std::get<1>(UndefReads[from]), TRI); ++} ++ ++unsigned ExeDepsFix::updateChooseableRegs(SparseSet &ChoosableRegs, ++ const TargetRegisterClass *OpRC, ++ bool add) { ++ unsigned LowestValid = (unsigned)-1; ++ ++ for (auto Reg : OpRC->getRegisters()) { ++ if (LiveRegSet.contains(Reg)) ++ ChoosableRegs.erase(Reg); ++ else if (add) { ++ ChoosableRegs.insert(Reg); ++ if (LowestValid == (unsigned)-1) ++ LowestValid = Reg; ++ } else if (ChoosableRegs.count(Reg) == 1) { ++ if (LowestValid == (unsigned)-1) ++ LowestValid = Reg; ++ } ++ } ++ return LowestValid; ++} ++ + /// \break Break false dependencies on undefined register reads. + /// + /// Walk the block backward computing precise liveness. This is expensive, so we +@@ -619,31 +693,87 @@ void ExeDepsFix::processUndefReads(MachineBasicBlock *MBB) { + if (UndefReads.empty()) + return; + ++ // We want to be slightly clever here, to avoid the following common pattern: ++ // Suppose we have some instruction `vrandom %in, %out` and the following code ++ // vrandom %xmm0, %xmm0 ++ // vrandom %xmm1, %xmm1 ++ // vrandom %xmm2, %xmm2 ++ // vrandom %xmm3, %xmm3 ++ // The earlier logic likes to produce these, because it picks the first ++ // register ++ // to break ties in clearance. However, most register allocators pick the dest ++ // register the same way. Naively, we'd have to insert a dependency break, ++ // before every instruction above. However, what we really want is ++ // vxorps %xmm3, %xmm3, %xmm3 ++ // vrandom %xmm3, %xmm0 ++ // vrandom %xmm3, %xmm1 ++ // vrandom %xmm3, %xmm2 ++ // vrandom %xmm3, %xmm3 ++ // To do so, we walk backwards and cumulatively keep track of which registers ++ // we can use to break the dependency. Then, once the set has collapsed, we ++ // reset the undef read register for all following instructions. ++ + // Collect this block's live out register units. + LiveRegSet.init(TRI); + // We do not need to care about pristine registers as they are just preserved + // but not actually used in the function. + LiveRegSet.addLiveOutsNoPristines(*MBB); + +- MachineInstr *UndefMI = UndefReads.back().first; +- unsigned OpIdx = UndefReads.back().second; ++ SparseSet ChoosableRegs; ++ ChoosableRegs.setUniverse(TRI->getNumRegs()); ++ ++ unsigned LastValid = (unsigned)-1; ++ const TargetRegisterClass *LastOpRC = nullptr; ++ size_t i, LastInit; ++ i = LastInit = UndefReads.size() - 1; ++ MachineInstr *UndefMI = std::get<0>(UndefReads[i]); + + for (MachineInstr &I : make_range(MBB->rbegin(), MBB->rend())) { + // Update liveness, including the current instruction's defs. + LiveRegSet.stepBackward(I); + ++ // This ensures that we don't accidentally pick a register whose live region ++ // lies entirely between two undef reads (since that would defeat the ++ // purpose of breaking the dependency). ++ for (auto LiveReg : LiveRegSet) ++ ChoosableRegs.erase(LiveReg); ++ + if (UndefMI == &I) { +- if (!LiveRegSet.contains(UndefMI->getOperand(OpIdx).getReg())) +- TII->breakPartialRegDependency(*UndefMI, OpIdx, TRI); ++ unsigned OpIdx = std::get<1>(UndefReads[i]); ++ // Get the undef operand's register class ++ const TargetRegisterClass *OpRC = ++ TII->getRegClass(UndefMI->getDesc(), OpIdx, TRI, *MF); ++ if (OpRC != LastOpRC || ChoosableRegs.size() == 0) { ++ if (LastInit != i) { ++ if (LastValid != (unsigned)-1) ++ collapseUndefReads(i + 1, LastInit + 1, LastValid); ++ ChoosableRegs.clear(); ++ LastInit = i; ++ } ++ } ++ ++ unsigned LowestValid = ++ updateChooseableRegs(ChoosableRegs, OpRC, LastInit == i); ++ ++ if (ChoosableRegs.size() == 0) { ++ if (LastInit != i) { ++ if (LastValid != (unsigned)-1) ++ collapseUndefReads(i + 1, LastInit + 1, LastValid); ++ LowestValid = updateChooseableRegs(ChoosableRegs, OpRC, true); ++ LastInit = i; ++ } ++ } ++ LastValid = LowestValid; ++ LastOpRC = OpRC; + +- UndefReads.pop_back(); +- if (UndefReads.empty()) +- return; ++ if (i == 0) ++ break; + +- UndefMI = UndefReads.back().first; +- OpIdx = UndefReads.back().second; ++ UndefMI = std::get<0>(UndefReads[--i]); + } + } ++ if (LastValid != (unsigned)-1) ++ collapseUndefReads(0, LastInit + 1, LastValid); + } + + // A hard instruction only works in one domain. All input registers will be +@@ -793,9 +923,7 @@ void ExeDepsFix::processBasicBlock(MachineBasicBlock *MBB, bool PrimaryPass, + enterBasicBlock(MBB); + for (MachineInstr &MI : *MBB) { + if (!MI.isDebugValue()) { +- bool Kill = false; +- if (PrimaryPass) +- Kill = visitInstr(&MI); ++ bool Kill = visitInstr(&MI, PrimaryPass); + processDefs(&MI, isBlockDone(MBB), Kill); + } + } +diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp +index 5793597..f31c97e 100644 +--- a/lib/Target/X86/X86InstrInfo.cpp ++++ b/lib/Target/X86/X86InstrInfo.cpp +@@ -7496,6 +7496,23 @@ void X86InstrInfo::breakPartialRegDependency( + } + } + ++bool X86InstrInfo::isDependencyBreak(MachineInstr &MI, unsigned *OutReg) const { ++ unsigned Opc = MI.getOpcode(); ++ if (!(Opc == X86::VXORPSrr || Opc == X86::VXORPDrr || Opc == X86::XORPSrr || ++ Opc == X86::XORPDrr)) ++ return false; ++ unsigned Reg = 0; ++ for (unsigned i = 0; i < MI.getNumOperands(); ++i) { ++ const MachineOperand &MO = MI.getOperand(i); ++ if (!MO.isReg() || (Reg != 0 && MO.getReg() != Reg)) ++ return false; ++ Reg = MO.getReg(); ++ } ++ if (OutReg) ++ *OutReg = Reg; ++ return true; ++} ++ + MachineInstr * + X86InstrInfo::foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, + ArrayRef Ops, +diff --git a/lib/Target/X86/X86InstrInfo.h b/lib/Target/X86/X86InstrInfo.h +index 8d74617..fa86882 100644 +--- a/lib/Target/X86/X86InstrInfo.h ++++ b/lib/Target/X86/X86InstrInfo.h +@@ -484,6 +484,7 @@ public: + const TargetRegisterInfo *TRI) const override; + void breakPartialRegDependency(MachineInstr &MI, unsigned OpNum, + const TargetRegisterInfo *TRI) const override; ++ bool isDependencyBreak(MachineInstr &MI, unsigned *OutReg) const override; + + MachineInstr *foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, + unsigned OpNum, From 723934ce6ac087e6550f8a03539634bf880a894f Mon Sep 17 00:00:00 2001 From: Iblis Lin Date: Sun, 19 Feb 2017 12:48:43 +0800 Subject: [PATCH 0004/1534] Fix FileMonitor test case on FreeBSD close #8078 On FreeBSD, the F_GETPATH is not available in fcntl. The path returned by libuv will be NULL. Ref: https://github.com/libuv/libuv/blob/309d603382159eacdf52cbf0fa936deb60552d32/src/unix/kqueue.c#L353-L361 And the test case in libuv: https://github.com/libuv/libuv/blob/309d603382159eacdf52cbf0fa936deb60552d32/test/test-fs-event.c#L315-L318 --- test/file.jl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/file.jl b/test/file.jl index 5fdcda60f1505..3db007556679a 100644 --- a/test/file.jl +++ b/test/file.jl @@ -236,7 +236,11 @@ function test_monitor_wait(tval) end fname, events = wait(fm) close(fm) - @test fname == basename(file) + if is_linux() || is_windows() || is_apple() + @test fname == basename(file) + else + @test fname == "" # platforms where F_GETPATH is not available + end @test events.changed end From 2142cc427ae288cffb83e49cabad2b1e235b0127 Mon Sep 17 00:00:00 2001 From: Iblis Lin Date: Sun, 19 Feb 2017 21:56:14 +0800 Subject: [PATCH 0005/1534] Fix Terminals.hascolor checking on FreeBSD --- base/Terminals.jl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/base/Terminals.jl b/base/Terminals.jl index f60f850616260..dfdc909f902fa 100644 --- a/base/Terminals.jl +++ b/base/Terminals.jl @@ -156,7 +156,11 @@ else function hascolor(t::TTYTerminal) startswith(t.term_type, "xterm") && return true try - return success(`tput setaf 0`) + @static if Sys.KERNEL == :FreeBSD + return success(`tput AF 0`) + else + return success(`tput setaf 0`) + end catch return false end From 3181500e361991b25a0ed8d63a821eb3c7a2e4bf Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Mon, 20 Feb 2017 17:31:37 -0500 Subject: [PATCH 0006/1534] Fix missing root across safe-point --- src/codegen.cpp | 255 ++++++++++++++++++++++++------------------------ 1 file changed, 128 insertions(+), 127 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 0207d89eda480..6961fb1a53abc 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -827,6 +827,7 @@ void jl_add_linfo_in_flight(StringRef name, jl_method_instance_t *linfo, const D extern "C" jl_llvm_functions_t jl_compile_linfo(jl_method_instance_t **pli, jl_code_info_t *src, size_t world, const jl_cgparams_t *params) { + // N.B.: `src` may have not been rooted by the caller. JL_TIMING(CODEGEN); jl_method_instance_t *li = *pli; assert(jl_is_method_instance(li)); @@ -836,148 +837,143 @@ jl_llvm_functions_t jl_compile_linfo(jl_method_instance_t **pli, jl_code_info_t !compare_cgparams(params, &jl_default_cgparams) && params->cached) jl_error("functions compiled with custom codegen params mustn't be cached"); - // Step 1. See if it is already compiled, - // Get the codegen lock, - // And get the source - if (li->def == NULL) { - JL_LOCK(&codegen_lock); - src = (jl_code_info_t*)li->inferred; - decls = li->functionObjectsDecls; - if (decls.functionObject != NULL || !src || !jl_is_code_info(src) || li->jlcall_api == 2) { - JL_UNLOCK(&codegen_lock); - return decls; - } - } - else if (!src) { - // Step 1a. If the caller didn't provide the source, - // try to infer it for ourself - // first see if it is already compiled + // Fast path for the already-compiled case + if (li->def != NULL) { decls = li->functionObjectsDecls; - if ((params->cached && decls.functionObject != NULL) || li->jlcall_api == 2) { - if (li->min_world <= world && li->max_world >= world) + bool already_compiled = params->cached && decls.functionObject != NULL; + if (!src) { + if ((already_compiled || li->jlcall_api == 2) && + (li->min_world <= world && li->max_world >= world)) { return decls; - } - JL_LOCK(&codegen_lock); - assert(li->min_world <= world && li->max_world >= world); - decls = li->functionObjectsDecls; - if ((params->cached && decls.functionObject != NULL) || li->jlcall_api == 2) { - JL_UNLOCK(&codegen_lock); + } + } else if (already_compiled) { return decls; } + } - // see if it is inferred - src = (jl_code_info_t*)li->inferred; - if (src) { - if (!jl_is_code_info(src)) { - src = jl_type_infer(pli, world, 0); - li = *pli; - } - if (!src || li->jlcall_api == 2) { - JL_UNLOCK(&codegen_lock); - return decls; + JL_GC_PUSH1(&src); + JL_LOCK(&codegen_lock); + decls = li->functionObjectsDecls; + + // Codegen lock held in this block + { + // Step 1: Re-check if this was already compiled (it may have been while + // we waited at the lock). + if (li->def == NULL) { + src = (jl_code_info_t*)li->inferred; + if (decls.functionObject != NULL || !src || !jl_is_code_info(src) || li->jlcall_api == 2) { + goto locked_out; } } - else { - // declare a failure to compile - JL_UNLOCK(&codegen_lock); - return decls; - } - } - else { - // similar to above, but never returns a NULL - // decl (unless compile fails), even if jlcall_api == 2 - decls = li->functionObjectsDecls; - if (params->cached && decls.functionObject != NULL) { - return decls; + else if (!src) { + // If the caller didn't provide the source, + // try to infer it for ourself, but first, re-check if it's already compiled. + assert(li->min_world <= world && li->max_world >= world); + if ((params->cached && decls.functionObject != NULL) || li->jlcall_api == 2) + goto locked_out; + + // see if it is inferred + src = (jl_code_info_t*)li->inferred; + if (src) { + if (!jl_is_code_info(src)) { + src = jl_type_infer(pli, world, 0); + li = *pli; + } + if (!src || li->jlcall_api == 2) + goto locked_out; + } + else { + // declare a failure to compile + goto locked_out; + } } - JL_LOCK(&codegen_lock); - decls = li->functionObjectsDecls; - if (params->cached && decls.functionObject != NULL) { - JL_UNLOCK(&codegen_lock); - return decls; + else if (params->cached && decls.functionObject != NULL) { + // similar to above, but never returns a NULL + // decl (unless compile fails), even if jlcall_api == 2 + goto locked_out; + } + assert(jl_is_code_info(src)); + + // Step 2: setup global state + IRBuilderBase::InsertPoint old = builder.saveAndClearIP(); + DebugLoc olddl = builder.getCurrentDebugLocation(); + bool last_n_c = nested_compile; + if (!nested_compile && dump_compiles_stream != NULL) + last_time = jl_hrtime(); + nested_compile = true; + + // Step 3. actually do the work of emitting the function + std::unique_ptr m; + JL_TRY { + jl_llvm_functions_t *pdecls; + if (!params->cached) + pdecls = &decls; + else if (li->min_world <= world && li->max_world >= world) + pdecls = &li->functionObjectsDecls; + else if (li->def == NULL) + pdecls = &li->functionObjectsDecls; + else + pdecls = &decls; + m = emit_function(li, src, world, pdecls, params); + if (params->cached && world) + decls = li->functionObjectsDecls; + //n_emit++; + } + JL_CATCH { + // something failed! this is very bad, since other WIP may be pointing to this function + // but there's not much we can do now. try to clear much of the WIP anyways. + li->functionObjectsDecls.functionObject = NULL; + li->functionObjectsDecls.specFunctionObject = NULL; + nested_compile = last_n_c; + builder.restoreIP(old); + builder.SetCurrentDebugLocation(olddl); + JL_UNLOCK(&codegen_lock); // Might GC + jl_rethrow_with_add("error compiling %s", jl_symbol_name(li->def ? li->def->name : anonymous_sym)); + } + Function *f = (Function*)decls.functionObject; + Function *specf = (Function*)decls.specFunctionObject; + + + if (JL_HOOK_TEST(params, module_activation)) { + JL_HOOK_CALL(params, module_activation, 1, jl_box_voidpointer(wrap(m.release()))); + } else { + // Step 4. Prepare debug info to receive this function + // record that this function name came from this linfo, + // so we can build a reverse mapping for debug-info. + bool toplevel = li->def == NULL; + if (!toplevel) { + const DataLayout &DL = + #if JL_LLVM_VERSION >= 30500 + m->getDataLayout(); + #else + *jl_data_layout; + #endif + // but don't remember toplevel thunks because + // they may not be rooted in the gc for the life of the program, + // and the runtime doesn't notify us when the code becomes unreachable :( + jl_add_linfo_in_flight((specf ? specf : f)->getName(), li, DL); + } + + // Step 5. Add the result to the execution engine now + jl_finalize_module(m.release(), !toplevel); } - } - JL_GC_PUSH1(&src); - assert(jl_is_code_info(src)); - // Step 2: setup global state - IRBuilderBase::InsertPoint old = builder.saveAndClearIP(); - DebugLoc olddl = builder.getCurrentDebugLocation(); - bool last_n_c = nested_compile; - if (!nested_compile && dump_compiles_stream != NULL) - last_time = jl_hrtime(); - nested_compile = true; + if (world && li->jlcall_api != 2) { + // if not inlineable, code won't be needed again + if (JL_DELETE_NON_INLINEABLE && jl_options.debug_level <= 1 && + li->def && li->inferred && jl_is_code_info(li->inferred) && + !((jl_code_info_t*)li->inferred)->inlineable && + li != li->def->unspecialized && !imaging_mode) { + li->inferred = jl_nothing; + } + } - // Step 3. actually do the work of emitting the function - std::unique_ptr m; - JL_TRY { - jl_llvm_functions_t *pdecls; - if (!params->cached) - pdecls = &decls; - else if (li->min_world <= world && li->max_world >= world) - pdecls = &li->functionObjectsDecls; - else if (li->def == NULL) - pdecls = &li->functionObjectsDecls; - else - pdecls = &decls; - m = emit_function(li, src, world, pdecls, params); - if (params->cached && world) - decls = li->functionObjectsDecls; - //n_emit++; - } - JL_CATCH { - // something failed! this is very bad, since other WIP may be pointing to this function - // but there's not much we can do now. try to clear much of the WIP anyways. - li->functionObjectsDecls.functionObject = NULL; - li->functionObjectsDecls.specFunctionObject = NULL; - nested_compile = last_n_c; + // Step 6: Done compiling: Restore global state builder.restoreIP(old); builder.SetCurrentDebugLocation(olddl); - JL_UNLOCK(&codegen_lock); // Might GC - jl_rethrow_with_add("error compiling %s", jl_symbol_name(li->def ? li->def->name : anonymous_sym)); - } - Function *f = (Function*)decls.functionObject; - Function *specf = (Function*)decls.specFunctionObject; - - - if (JL_HOOK_TEST(params, module_activation)) { - JL_HOOK_CALL(params, module_activation, 1, jl_box_voidpointer(wrap(m.release()))); - } else { - // Step 4. Prepare debug info to receive this function - // record that this function name came from this linfo, - // so we can build a reverse mapping for debug-info. - bool toplevel = li->def == NULL; - if (!toplevel) { - const DataLayout &DL = -#if JL_LLVM_VERSION >= 30500 - m->getDataLayout(); -#else - *jl_data_layout; -#endif - // but don't remember toplevel thunks because - // they may not be rooted in the gc for the life of the program, - // and the runtime doesn't notify us when the code becomes unreachable :( - jl_add_linfo_in_flight((specf ? specf : f)->getName(), li, DL); - } - - // Step 5. Add the result to the execution engine now - jl_finalize_module(m.release(), !toplevel); - } - - if (world && li->jlcall_api != 2) { - // if not inlineable, code won't be needed again - if (JL_DELETE_NON_INLINEABLE && jl_options.debug_level <= 1 && - li->def && li->inferred && jl_is_code_info(li->inferred) && - !((jl_code_info_t*)li->inferred)->inlineable && - li != li->def->unspecialized && !imaging_mode) { - li->inferred = jl_nothing; - } + nested_compile = last_n_c; } - // Step 6: Done compiling: Restore global state - builder.restoreIP(old); - builder.SetCurrentDebugLocation(olddl); - nested_compile = last_n_c; JL_UNLOCK(&codegen_lock); // Might GC if (dump_compiles_stream != NULL) { @@ -989,6 +985,11 @@ jl_llvm_functions_t jl_compile_linfo(jl_method_instance_t **pli, jl_code_info_t } JL_GC_POP(); return decls; + +locked_out: + JL_UNLOCK(&codegen_lock); + JL_GC_POP(); + return decls; } #if JL_LLVM_VERSION < 30700 From bb83c0e2f34a8713c43d53f508d569da4d4429fa Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 21 Feb 2017 01:18:00 -0500 Subject: [PATCH 0007/1534] fix specificity of Tuples with non-types in them --- src/subtype.c | 3 +++ test/core.jl | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/subtype.c b/src/subtype.c index 0a7b136ff2b81..fc6e2467fdf24 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -2051,6 +2051,9 @@ static int eq_msp(jl_value_t *a, jl_value_t *b, jl_typeenv_t *env) if ((a == (jl_value_t*)jl_any_type && b == jl_ANY_flag) || (b == (jl_value_t*)jl_any_type && a == jl_ANY_flag)) return 1; + if (!(jl_is_type(a) || jl_is_typevar(a)) || + !(jl_is_type(b) || jl_is_typevar(b))) + return jl_egal(a, b); JL_GC_PUSH2(&a, &b); jl_typeenv_t *e = env; while (e != NULL) { diff --git a/test/core.jl b/test/core.jl index 9fc29b36fcb29..dc777dbe03a4c 100644 --- a/test/core.jl +++ b/test/core.jl @@ -63,6 +63,8 @@ _z_z_z_(::Int, c...) = 3 @test args_morespecific(Tuple{Array{T} where T<:Union{Float32,Float64,Complex64,Complex128}, Any}, Tuple{Array{T} where T<:Real, Any}) +@test args_morespecific(Tuple{1,T} where T, Tuple{Any}) + # with bound varargs _bound_vararg_specificity_1{T,N}(::Type{Array{T,N}}, d::Vararg{Int, N}) = 0 From bb1f70425961470713208c9e9db7a77be3690c13 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Tue, 21 Feb 2017 06:02:15 -0600 Subject: [PATCH 0008/1534] Add docstrings for CartesianIndex and CartesianRange --- base/multidimensional.jl | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 283b4d6801bc5..21de678553872 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -12,7 +12,22 @@ module IteratorsMD export CartesianIndex, CartesianRange - # CartesianIndex + """ + CartesianIndex(i, j, k...) -> I + CartesianIndex((i, j, k...)) -> I + + Create a multidimensional index `I`, which can be used for + indexing a multidimensional array `A`. In particular, `A[I]` is + equivalent to `A[i,j,k...]`. One can freely mix integer and + `CartesianIndex` indices; for example, `A[Ipre, i, Ipost]` (where + `Ipre` and `Ipost` are `CartesianIndex` indices and `i` is an + `Int`) can be a useful expression when writing algorithms that + work along a single dimension of an array of arbitrary + dimensionality. + + A `CartesianIndex` is sometimes produced by [`eachindex`](@ref), and + always when iterating with an explicit [`CartesianRange`](@ref). + """ struct CartesianIndex{N} <: AbstractCartesianIndex{N} I::NTuple{N,Int} CartesianIndex{N}(index::NTuple{N,Integer}) where {N} = new(index) @@ -77,6 +92,25 @@ module IteratorsMD icmp(a, b) = ifelse(isless(a,b), 1, ifelse(a==b, 0, -1)) # Iteration + """ + CartesianRange(Istart::CartesianIndex, Istop::CartesianIndex) -> R + CartesianRange(sz::Dims) -> R + CartesianRange(istart:istop, jstart:jstop, ...) -> R + + Define a region `R` spanning a multidimensional rectangular range + of integer indices. These are most commonly encountered in the + context of iteration, where `for I in R ... end` will return + [`CartesianIndex`](@ref) indices `I` equivalent to the nested loops + + for j = jstart:jstop + for i = istart:istop + ... + end + end + + Consequently these can be useful for writing algorithms that + work in arbitrary dimensions. + """ struct CartesianRange{I<:CartesianIndex} start::I stop::I From 201737a4381af64ea962a27549019fbedfd018f3 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Tue, 21 Feb 2017 08:45:45 -0800 Subject: [PATCH 0009/1534] Add imports and module qualifiers for Distributed (#20710) * Add imports and module qualifiers for Distributed helps more of `JULIA_TESTFULL=1 make testall` pass * some more imports from Base into Distributed for use * fix rmprocs test to wait for removal of added workers --- base/distributed/Distributed.jl | 4 ++-- test/distributed_exec.jl | 5 +++-- test/topology.jl | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/base/distributed/Distributed.jl b/base/distributed/Distributed.jl index 17f680e0c5a7d..1405ab11867b5 100644 --- a/base/distributed/Distributed.jl +++ b/base/distributed/Distributed.jl @@ -4,13 +4,13 @@ module Distributed # imports for extension import Base: getindex, wait, put!, take!, fetch, isready, push!, length, - hash, ==, connect, kill, serialize, deserialize, close + hash, ==, connect, kill, serialize, deserialize, close, showerror # imports for use using Base: Process, Semaphore, JLOptions, AnyDict, buffer_writes, wait_connected, VERSION_STRING, sync_begin, sync_add, sync_end, async_run_thunk, binding_module, notify_error, atexit, julia_exename, julia_cmd, - AsyncGenerator, display_error + AsyncGenerator, display_error, acquire, release # NOTE: clusterserialize.jl imports additional symbols from Base.Serializer for use diff --git a/test/distributed_exec.jl b/test/distributed_exec.jl index 1b683c2ab9e20..0c6f0ee59d178 100644 --- a/test/distributed_exec.jl +++ b/test/distributed_exec.jl @@ -922,7 +922,7 @@ if DoFullTest # Test sending fake data to workers. The worker processes will print an # error message but should not terminate. for w in Base.Distributed.PGRP.workers - if isa(w, Base.Worker) + if isa(w, Base.Distributed.Worker) s = connect(get(w.config.host), get(w.config.port)) write(s, randstring(32)) end @@ -1269,6 +1269,7 @@ end if DoFullTest pids=addprocs(4); @test_throws ErrorException rmprocs(pids; waitfor=0.001); + rmprocs(pids) end # Auto serialization of globals from Main. @@ -1478,4 +1479,4 @@ catch ex @test isa(ex.captured.ex.exceptions[1].ex, ErrorException) @test contains(ex.captured.ex.exceptions[1].ex.msg, "BoundsError") @test ex.captured.ex.exceptions[2].ex == UndefVarError(:DontExistOn1) -end \ No newline at end of file +end diff --git a/test/topology.jl b/test/topology.jl index 52cdad0ffc8c1..66273149e25a0 100644 --- a/test/topology.jl +++ b/test/topology.jl @@ -43,7 +43,7 @@ function Base.launch(manager::TopoTestManager, params::Dict, launched::Array, c: for i in 1:manager.np io, pobj = open(pipeline(detach( - setenv(`$(Base.julia_cmd(exename)) $exeflags --bind-to $(Base.LPROC.bind_addr) --worker $(Base.cluster_cookie())`, dir=dir)); stderr=STDERR), "r") + setenv(`$(Base.julia_cmd(exename)) $exeflags --bind-to $(Base.Distributed.LPROC.bind_addr) --worker $(Base.cluster_cookie())`, dir=dir)); stderr=STDERR), "r") wconfig = WorkerConfig() wconfig.process = pobj wconfig.io = io From 9d960560833ec2cecff99045b1564f2ca08d3e0a Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Tue, 21 Feb 2017 08:59:08 -0800 Subject: [PATCH 0010/1534] Fix fetchheads callback and add tests (#20669) --- base/libgit2/callbacks.jl | 2 +- test/libgit2.jl | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/base/libgit2/callbacks.jl b/base/libgit2/callbacks.jl index a38c31460a335..06ead82ea578e 100644 --- a/base/libgit2/callbacks.jl +++ b/base/libgit2/callbacks.jl @@ -258,7 +258,7 @@ end function fetchhead_foreach_callback(ref_name::Cstring, remote_url::Cstring, oid::Ptr{GitHash}, is_merge::Cuint, payload::Ptr{Void}) fhead_vec = unsafe_pointer_to_objref(payload)::Vector{FetchHead} - push!(fhead_vec, FetchHead(unsafe_string(ref_name), unsafe_string(remote_url), GitHash(oid), is_merge == 1)) + push!(fhead_vec, FetchHead(unsafe_string(ref_name), unsafe_string(remote_url), unsafe_load(oid), is_merge == 1)) return Cint(0) end diff --git a/test/libgit2.jl b/test/libgit2.jl index 986ec9688570e..b54a2cd0303aa 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -563,6 +563,16 @@ mktempdir() do dir # Switch to the master branch LibGit2.branch!(repo, master_branch) + fetch_heads = LibGit2.fetchheads(repo) + @test fetch_heads[1].name == "refs/heads/master" + @test fetch_heads[1].ismerge == true #we just merged master + @test fetch_heads[2].name == "refs/heads/test_branch" + @test fetch_heads[2].ismerge == false + @test fetch_heads[3].name == "refs/tags/tag2" + @test fetch_heads[3].ismerge == false + for fh in fetch_heads + @test fh.url == cache_repo + end finally close(repo) end From 00b30a807601e2e0cbaec05142c4836557f89c00 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 23 Jan 2017 18:32:43 -0500 Subject: [PATCH 0011/1534] codegen: represent Union types via tagged unions this covers the code-generator support for representing types on the stack via a tagged type representation The function `remark_julia_type` now can transform between any two types. Instead of asserting when asked to drop type information, it'll instead cast the object to the requested representation. It'll make boxes, allocate stack copies, and compute tagged unions as needed to perform the request. This means that we can use `remark_julia_type` whenever we want type information to forcibly change. For example, storing to a slot requires dropping the intermediate type information and generating a representation suitable for copying into the memory location. Loading from a slot has the opposite requirement: it needs to be able to load the slot via it's declared type, then possibly to cast the result to add type information that may be used later (to emit optimizations of other intrinsic function calls). The primitive routines that need to be able to handle tagged unions are: - remark-type - load-local - store-local - isa - is - emit_typeof - emit_sizeof - boxed - unbox - specsig (not implemented here yet) Everything else should be possible to handle in inference by using these primitives to implement union-splitting. Additionally, the following will be supported once the type layout changes: - getfield / setfield The representation of the tagged-union is as a pair of < union*, selector > memory addresses. The selector is fixed as a byte, and will union-tag the first 126 isbits. It records the one-based depth-first count into the type-union of the isbits objects inside. An index of zero indicates that the union* is actually a tagged heap-allocated jl_value_t*, and needs to treated as normal for a boxed object rather than as a tagged union. The `union*` memory region may be allocated at *any* size. The only constraint is that it is big enough to contain the data currently specified by `selector`. It might not be big enough to contain the union of all types that could be stored there according to the associated Union type field. Use appropriate care when copying. this also includes improvements for codegen of isa with mixed types --- src/cgutils.cpp | 434 ++++++++++++++++++++++------ src/codegen.cpp | 685 +++++++++++++++++++++++++++++++++++---------- src/intrinsics.cpp | 13 +- 3 files changed, 904 insertions(+), 228 deletions(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index b2e3d2a4b84c5..83af669d63949 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -224,7 +224,7 @@ static DIType julia_type_to_di(jl_value_t *jt, DIBuilder *dbuilder, bool isboxed // --- emitting pointers directly into code --- -static Value *literal_static_pointer_val(const void *p, Type *t) +static Constant *literal_static_pointer_val(const void *p, Type *t) { // this function will emit a static pointer into the generated code // the generated code will only be valid during the current session, @@ -237,14 +237,13 @@ static Value *literal_static_pointer_val(const void *p, Type *t) } -static Value *julia_gv(const char *cname, void *addr) +static Value *julia_pgv(const char *cname, void *addr) { // emit a GlobalVariable for a jl_value_t named "cname" - GlobalVariable *gv = jl_get_global_for(cname, addr, jl_builderModule); - return tbaa_decorate(tbaa_const, builder.CreateLoad(gv)); + return jl_get_global_for(cname, addr, jl_builderModule); } -static Value *julia_gv(const char *prefix, jl_sym_t *name, jl_module_t *mod, void *addr) +static Value *julia_pgv(const char *prefix, jl_sym_t *name, jl_module_t *mod, void *addr) { // emit a GlobalVariable for a jl_value_t, using the prefix, name, and module to // to create a readable name of the form prefixModA.ModB.name @@ -269,44 +268,63 @@ static Value *julia_gv(const char *prefix, jl_sym_t *name, jl_module_t *mod, voi prev = parent; parent = parent->parent; } - return julia_gv(fullname, addr); + return julia_pgv(fullname, addr); } static GlobalVariable *julia_const_gv(jl_value_t *val); -static Value *literal_pointer_val(jl_value_t *p) +static Value *literal_pointer_val_slot(jl_value_t *p) { - // emit a pointer to any jl_value_t which will be valid across reloading code + // emit a pointer to a jl_value_t* which will allow it to be valid across reloading code // also, try to give it a nice name for gdb, for easy identification - if (p == NULL) - return ConstantPointerNull::get((PointerType*)T_pjlvalue); - if (!imaging_mode) - return literal_static_pointer_val(p, T_pjlvalue); - if (auto gv = julia_const_gv(p)) { - return tbaa_decorate(tbaa_const, builder.CreateLoad(prepare_global(gv))); + if (!imaging_mode) { + Module *M = jl_builderModule; + GlobalVariable *gv = new GlobalVariable( + *M, T_pjlvalue, true, GlobalVariable::PrivateLinkage, + literal_static_pointer_val(p, T_pjlvalue)); +#if JL_LLVM_VERSION >= 30900 + gv->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); +#else + gv->setUnnamedAddr(true); +#endif + return gv; + } + if (GlobalVariable *gv = julia_const_gv(p)) { + // if this is a known object, use the existing GlobalValue + return prepare_global(gv, jl_builderModule); } if (jl_is_datatype(p)) { jl_datatype_t *addr = (jl_datatype_t*)p; // DataTypes are prefixed with a + - return julia_gv("+", addr->name->name, addr->name->module, p); + return julia_pgv("+", addr->name->name, addr->name->module, p); } if (jl_is_method(p)) { jl_method_t *m = (jl_method_t*)p; // functions are prefixed with a - - return julia_gv("-", m->name, m->module, p); + return julia_pgv("-", m->name, m->module, p); } if (jl_is_method_instance(p)) { jl_method_instance_t *linfo = (jl_method_instance_t*)p; // Type-inferred functions are also prefixed with a - if (linfo->def) - return julia_gv("-", linfo->def->name, linfo->def->module, p); + return julia_pgv("-", linfo->def->name, linfo->def->module, p); } if (jl_is_symbol(p)) { jl_sym_t *addr = (jl_sym_t*)p; // Symbols are prefixed with jl_sym# - return julia_gv("jl_sym#", addr, NULL, p); + return julia_pgv("jl_sym#", addr, NULL, p); } // something else gets just a generic name - return julia_gv("jl_global#", p); + return julia_pgv("jl_global#", p); +} + +static Value *literal_pointer_val(jl_value_t *p) +{ + if (p == NULL) + return ConstantPointerNull::get((PointerType*)T_pjlvalue); + if (!imaging_mode) + return literal_static_pointer_val(p, T_pjlvalue); + Value *pgv = literal_pointer_val_slot(p); + return tbaa_decorate(tbaa_const, builder.CreateLoad(pgv)); } static Value *literal_pointer_val(jl_binding_t *p) @@ -317,7 +335,8 @@ static Value *literal_pointer_val(jl_binding_t *p) if (!imaging_mode) return literal_static_pointer_val(p, T_pjlvalue); // bindings are prefixed with jl_bnd# - return julia_gv("jl_bnd#", p->name, p->owner, p); + Value *pgv = julia_pgv("jl_bnd#", p->name, p->owner, p); + return tbaa_decorate(tbaa_const, builder.CreateLoad(pgv)); } // bitcast a value, but preserve its address space when dealing with pointer types @@ -338,18 +357,22 @@ static Value *emit_bitcast(Value *v, Type *jl_value) static Value *julia_binding_gv(Value *bv) { - return builder. - CreateGEP(bv,ConstantInt::get(T_size, - offsetof(jl_binding_t,value)/sizeof(size_t))); + Value *offset = ConstantInt::get(T_size, offsetof(jl_binding_t, value) / sizeof(size_t)); + return builder.CreateGEP(bv, offset); } static Value *julia_binding_gv(jl_binding_t *b) { // emit a literal_pointer_val to the value field of a jl_binding_t // binding->value are prefixed with * - Value *bv = imaging_mode ? - emit_bitcast(julia_gv("*", b->name, b->owner, b), T_ppjlvalue) : - literal_static_pointer_val(b,T_ppjlvalue); + Value *bv; + if (imaging_mode) + bv = emit_bitcast( + tbaa_decorate(tbaa_const, + builder.CreateLoad(julia_pgv("*", b->name, b->owner, b))), + T_ppjlvalue); + else + bv = literal_static_pointer_val(b, T_ppjlvalue); return julia_binding_gv(bv); } @@ -558,6 +581,57 @@ static bool deserves_sret(jl_value_t *dt, Type *T) return (size_t)jl_datatype_size(dt) > sizeof(void*) && !T->isFloatingPointTy() && !T->isVectorTy(); } +static bool for_each_uniontype_small( + std::function f, + jl_value_t *ty, + unsigned &counter) +{ + if (counter > 127) + return false; + if (jl_is_uniontype(ty)) { + bool allunbox = for_each_uniontype_small(f, ((jl_uniontype_t*)ty)->a, counter); + allunbox &= for_each_uniontype_small(f, ((jl_uniontype_t*)ty)->b, counter); + return allunbox; + } + else if (isbits_spec(ty)) { + f(++counter, (jl_datatype_t*)ty); + return true; + } + return false; +} + +static Value *emit_typeof_boxed(const jl_cgval_t &p, jl_codectx_t *ctx); + +static Value *compute_box_tindex(Value *datatype, jl_value_t *ut, jl_codectx_t *ctx) +{ + Value *tindex = ConstantInt::get(T_int8, 0); + unsigned counter = 0; + for_each_uniontype_small( + [&](unsigned idx, jl_datatype_t *jt) { + Value *cmp = builder.CreateICmpEQ(literal_pointer_val((jl_value_t*)jt), datatype); + tindex = builder.CreateSelect(cmp, ConstantInt::get(T_int8, idx), tindex); + }, + ut, + counter); + return tindex; +} + +static unsigned get_box_tindex(jl_datatype_t *jt, jl_value_t *ut) +{ + unsigned new_idx = 0; + unsigned new_counter = 0; + for_each_uniontype_small( + // find the corresponding index in the new union-type + [&](unsigned new_idx_, jl_datatype_t *new_jt) { + if (jt == new_jt) + new_idx = new_idx_; + }, + ut, + new_counter); + return new_idx; +} + + // --- generating various field accessors --- static Value *emit_nthptr_addr(Value *v, ssize_t n) @@ -602,24 +676,53 @@ static Value *emit_typeptr_addr(Value *p) static Value *boxed(const jl_cgval_t &v, jl_codectx_t *ctx, bool gcooted=true); static Value *boxed(const jl_cgval_t &v, jl_codectx_t *ctx, jl_value_t* type) = delete; // C++11 (temporary to prevent rebase error) +static Value* mask_gc_bits(Value *tag) +{ + return builder.CreateIntToPtr(builder.CreateAnd( + builder.CreatePtrToInt(tag, T_size), + ConstantInt::get(T_size, ~(uintptr_t)15)), + tag->getType()); +} + static Value *emit_typeof(Value *tt) { // given p, a jl_value_t*, compute its type tag - assert(tt->getType() == T_pjlvalue); - tt = tbaa_decorate(tbaa_tag, builder.CreateLoad(emit_typeptr_addr(tt), false)); - tt = builder.CreateIntToPtr(builder.CreateAnd( - builder.CreatePtrToInt(tt, T_size), - ConstantInt::get(T_size,~(uintptr_t)15)), - T_pjlvalue); - return tt; + tt = tbaa_decorate(tbaa_tag, builder.CreateLoad(emit_typeptr_addr(tt))); + return mask_gc_bits(tt); } static jl_cgval_t emit_typeof(const jl_cgval_t &p, jl_codectx_t *ctx) { // given p, compute its type - if (!p.constant && p.isboxed && !jl_is_leaf_type(p.typ)) { + if (p.constant) + return mark_julia_const(jl_typeof(p.constant)); + if (p.isboxed && !jl_is_leaf_type(p.typ)) { return mark_julia_type(emit_typeof(p.V), true, jl_datatype_type, ctx, /*needsroot*/false); } + if (p.TIndex) { + Value *tindex = p.TIndex; + Value *pdatatype; + if (p.V && !isa(p.V)) + pdatatype = emit_typeptr_addr(p.V); + else + pdatatype = Constant::getNullValue(T_ppjlvalue); + unsigned counter = 0; + for_each_uniontype_small( + [&](unsigned idx, jl_datatype_t *jt) { + Value *cmp = builder.CreateICmpEQ(tindex, ConstantInt::get(T_int8, idx)); + pdatatype = builder.CreateSelect(cmp, literal_pointer_val_slot((jl_value_t*)jt), pdatatype); + }, + p.typ, + counter); + Value *datatype; + if (p.V == NULL || isa(p.V)) { + datatype = tbaa_decorate(tbaa_const, builder.CreateLoad(pdatatype)); + } + else { + datatype = mask_gc_bits(tbaa_decorate(tbaa_tag, builder.CreateLoad(pdatatype))); + } + return mark_julia_type(datatype, true, jl_datatype_type, ctx, /*needsroot*/false); + } jl_value_t *aty = p.typ; if (jl_is_type_type(aty)) { // convert Int::Type{Int} ==> typeof(Int) ==> DataType @@ -668,6 +771,51 @@ static Value *emit_datatype_size(Value *dt) return size; } +static Value *emit_sizeof(const jl_cgval_t &p, jl_codectx_t *ctx) +{ + if (p.TIndex) { + Value *tindex = p.TIndex; + Value *size = ConstantInt::get(T_int32, -1); + unsigned counter = 0; + for_each_uniontype_small( + [&](unsigned idx, jl_datatype_t *jt) { + Value *cmp = builder.CreateICmpEQ(tindex, ConstantInt::get(T_int8, idx)); + size = builder.CreateSelect(cmp, ConstantInt::get(T_int32, jl_datatype_size(jt)), size); + }, + p.typ, + counter); + if (p.V != NULL && !isa(p.V)) { + BasicBlock *currBB = builder.GetInsertBlock(); + BasicBlock *dynloadBB = BasicBlock::Create(jl_LLVMContext, "dyn_sizeof", ctx->f); + BasicBlock *postBB = BasicBlock::Create(jl_LLVMContext, "post_sizeof", ctx->f); + Value *isboxed = builder.CreateICmpEQ(tindex, ConstantInt::get(T_int8, 0)); + builder.CreateCondBr(isboxed, dynloadBB, postBB); + builder.SetInsertPoint(dynloadBB); + Value *datatype = emit_typeof(p.V); + Value *dyn_size = emit_datatype_size(datatype); + builder.CreateBr(postBB); + builder.SetInsertPoint(postBB); + PHINode *sizeof_merge = builder.CreatePHI(T_int32, 2); + sizeof_merge->addIncoming(dyn_size, dynloadBB); + sizeof_merge->addIncoming(size, currBB); + size = sizeof_merge; + } +#ifndef NDEBUG + // try to catch codegen errors early, before it uses this to memcpy over the entire stack + CreateConditionalAbort(builder, builder.CreateICmpEQ(size, ConstantInt::get(T_int32, -1))); +#endif + return size; + } + else if (jl_is_leaf_type(p.typ)) { + return ConstantInt::get(T_int32, jl_datatype_size(p.typ)); + } + else { + Value *datatype = emit_typeof_boxed(p, ctx); + Value *dyn_size = emit_datatype_size(datatype); + return dyn_size; + } +} + static Value *emit_datatype_mutabl(Value *dt) { Value *mutabl = tbaa_decorate(tbaa_const, builder. @@ -798,18 +946,23 @@ static void emit_type_error(const jl_cgval_t &x, Value *type, const std::string static Value *emit_isa(const jl_cgval_t &x, jl_value_t *type, const std::string *msg, jl_codectx_t *ctx) { - Value *istype; - if (jl_type_intersection(x.typ, type) == (jl_value_t*)jl_bottom_type) { - if (msg) { - emit_type_error(x, literal_pointer_val(type), *msg, ctx); - builder.CreateUnreachable(); - BasicBlock *failBB = BasicBlock::Create(jl_LLVMContext, "fail", ctx->f); - builder.SetInsertPoint(failBB); - } - return ConstantInt::get(T_int1, 0); + bool maybe_isa = true; + if (x.constant) + maybe_isa = jl_isa(x.constant, type); + else if (jl_type_intersection(x.typ, type) == (jl_value_t*)jl_bottom_type) + maybe_isa = false; + if (!maybe_isa && msg) { + emit_type_error(x, literal_pointer_val(type), *msg, ctx); + builder.CreateUnreachable(); + BasicBlock *failBB = BasicBlock::Create(jl_LLVMContext, "fail", ctx->f); + builder.SetInsertPoint(failBB); } - else if (jl_has_intersect_type_not_kind(x.typ) || - jl_has_intersect_type_not_kind(type)) { + if (!maybe_isa || x.constant) + return ConstantInt::get(T_int1, maybe_isa); + + // intersection with Type needs to be handled specially + if (jl_has_intersect_type_not_kind(x.typ) || + jl_has_intersect_type_not_kind(type)) { Value *vx = boxed(x, ctx); if (msg && *msg == "typeassert") { #if JL_LLVM_VERSION >= 30700 @@ -819,7 +972,7 @@ static Value *emit_isa(const jl_cgval_t &x, jl_value_t *type, const std::string #endif return ConstantInt::get(T_int1, 1); } - istype = builder.CreateICmpNE( + return builder.CreateICmpNE( #if JL_LLVM_VERSION >= 30700 builder.CreateCall(prepare_call(jlisa_func), { vx, literal_pointer_val(type) }), #else @@ -827,20 +980,48 @@ static Value *emit_isa(const jl_cgval_t &x, jl_value_t *type, const std::string #endif ConstantInt::get(T_int32, 0)); } - else if (jl_is_leaf_type(type)) { - istype = builder.CreateICmpEQ(emit_typeof_boxed(x, ctx), literal_pointer_val(type)); + // tests for isa leaftype can be handled with pointer comparisons + if (jl_is_leaf_type(type)) { + if (x.TIndex) { + unsigned tindex = get_box_tindex((jl_datatype_t*)type, x.typ); + if (!x.V || isa(x.V)) { + // optimize more when we know that this is a split union-type where tindex = 0 is invalid + assert(tindex > 0 && "x.typ should have been a union of leaftypes at this point"); + return builder.CreateICmpEQ(x.TIndex, ConstantInt::get(T_int8, tindex)); + } + else { + // test for ((tindex > 0 && x.TIndex == tindex) || (x.TIndex == 0 && typeof(x.V) == type)) + Value *istype_union = NULL; + if (tindex > 0) + istype_union = builder.CreateICmpEQ(x.TIndex, ConstantInt::get(T_int8, tindex)); + else + istype_union = ConstantInt::get(T_int1, 0); + Value *isboxed = builder.CreateICmpEQ(x.TIndex, ConstantInt::get(T_int8, 0)); + BasicBlock *currBB = builder.GetInsertBlock(); + BasicBlock *isaBB = BasicBlock::Create(jl_LLVMContext, "isa", ctx->f); + BasicBlock *postBB = BasicBlock::Create(jl_LLVMContext, "post_isa", ctx->f); + builder.CreateCondBr(isboxed, isaBB, postBB); + builder.SetInsertPoint(isaBB); + Value *istype_boxed = builder.CreateICmpEQ(emit_typeof(x.V), literal_pointer_val(type)); + builder.CreateBr(postBB); + builder.SetInsertPoint(postBB); + PHINode *istype = builder.CreatePHI(T_int1, 2); + istype->addIncoming(istype_union, currBB); + istype->addIncoming(istype_boxed, isaBB); + return istype; + } + } + return builder.CreateICmpEQ(emit_typeof_boxed(x, ctx), literal_pointer_val(type)); } - else { - Value *vxt = emit_typeof_boxed(x, ctx); - istype = builder.CreateICmpNE( + // everything else can be handled via subtype tests + Value *vxt = emit_typeof_boxed(x, ctx); + return builder.CreateICmpNE( #if JL_LLVM_VERSION >= 30700 - builder.CreateCall(prepare_call(jlsubtype_func), { vxt, literal_pointer_val(type) }), + builder.CreateCall(prepare_call(jlsubtype_func), { vxt, literal_pointer_val(type) }), #else - builder.CreateCall2(prepare_call(jlsubtype_func), vxt, literal_pointer_val(type)), + builder.CreateCall2(prepare_call(jlsubtype_func), vxt, literal_pointer_val(type)), #endif - ConstantInt::get(T_int32, 0)); - } - return istype; + ConstantInt::get(T_int32, 0)); } static void emit_typecheck(const jl_cgval_t &x, jl_value_t *type, const std::string &msg, @@ -1130,7 +1311,7 @@ static bool emit_getfield_unknownidx(jl_cgval_t *ret, const jl_cgval_t &strct, // just compute the pointer and let user load it when necessary Type *fty = julia_type_to_llvm(jt); Value *addr = builder.CreateGEP(builder.CreatePointerCast(ptr, PointerType::get(fty,0)), idx); - *ret = mark_julia_slot(addr, jt, strct.tbaa); + *ret = mark_julia_slot(addr, jt, NULL, strct.tbaa); ret->gcroot = strct.gcroot; ret->isimmutable = strct.isimmutable; return true; @@ -1198,7 +1379,7 @@ static jl_cgval_t emit_getfield_knownidx(const jl_cgval_t &strct, unsigned idx, } else if (!jt->mutabl) { // just compute the pointer and let user load it when necessary - jl_cgval_t fieldval = mark_julia_slot(addr, jfty, strct.tbaa); + jl_cgval_t fieldval = mark_julia_slot(addr, jfty, NULL, strct.tbaa); fieldval.isimmutable = strct.isimmutable; fieldval.gcroot = strct.gcroot; return fieldval; @@ -1244,6 +1425,29 @@ static bool arraytype_constshape(jl_value_t *ty) jl_is_long(jl_tparam1(ty)) && jl_unbox_long(jl_tparam1(ty)) != 1); } +static void maybe_alloc_arrayvar(int s, jl_codectx_t *ctx) +{ + jl_value_t *jt = ctx->slots[s].value.typ; + if (arraytype_constshape(jt)) { + // TODO: this optimization does not yet work with 1-d arrays, since the + // length and data pointer can change at any time via push! + // we could make it work by reloading the metadata when the array is + // passed to an external function (ideally only impure functions) + jl_arrayvar_t av; + int ndims = jl_unbox_long(jl_tparam1(jt)); + Type *elt = julia_type_to_llvm(jl_tparam0(jt)); + if (type_is_ghost(elt)) + return; + // CreateAlloca is OK here because maybe_alloc_arrayvar is only called in the prologue setup + av.dataptr = builder.CreateAlloca(PointerType::get(elt,0)); + av.len = builder.CreateAlloca(T_size); + for (int i = 0; i < ndims - 1; i++) + av.sizes.push_back(builder.CreateAlloca(T_size)); + av.ty = jt; + (*ctx->arrayvars)[s] = av; + } +} + static Value *emit_arraysize(const jl_cgval_t &tinfo, Value *dim, jl_codectx_t *ctx) { Value *t = boxed(tinfo, ctx); @@ -1484,25 +1688,22 @@ static Value *emit_array_nd_index(const jl_cgval_t &ainfo, jl_value_t *ex, ssize // --- boxing --- static Value *emit_allocobj(jl_codectx_t *ctx, size_t static_size, Value *jt); -static Value *emit_allocobj(jl_codectx_t *ctx, size_t static_size, const jl_cgval_t &v); -static Value *init_bits_value(Value *newv, Value *v, MDNode *tbaa, unsigned alignment = sizeof(void*)) // min alignment in julia's gc is pointer-aligned +static void init_bits_value(Value *newv, Value *v, MDNode *tbaa, unsigned alignment = sizeof(void*)) // min alignment in julia's gc is pointer-aligned { // newv should already be tagged tbaa_decorate(tbaa, builder.CreateAlignedStore(v, emit_bitcast(newv, PointerType::get(v->getType(), 0)), alignment)); - return newv; } -static Value *init_bits_cgval(Value *newv, const jl_cgval_t& v, MDNode *tbaa, jl_codectx_t *ctx) +static void init_bits_cgval(Value *newv, const jl_cgval_t& v, MDNode *tbaa, jl_codectx_t *ctx) { // newv should already be tagged if (v.ispointer()) { builder.CreateMemCpy(newv, data_pointer(v, ctx, T_pint8), jl_datatype_size(v.typ), sizeof(void*)); - return newv; } else { - return init_bits_value(newv, v.V, tbaa); + init_bits_value(newv, v.V, tbaa); } } @@ -1652,6 +1853,77 @@ static Value *_boxed_special(const jl_cgval_t &vinfo, Type *t, jl_codectx_t *ctx return box; } + + +static Value *box_union(const jl_cgval_t &vinfo, jl_codectx_t *ctx, const SmallBitVector &skip) +{ + // given vinfo::Union{T, S}, emit IR of the form: + // ... + // switch , label [ 1, label + // 2, label ] + // box_union_1: + // box1 = create_box(T) + // br post_box_union + // box_union_2: + // box2 = create_box(S) + // br post_box_union + // box_union_isboxed: + // br post_box_union + // post_box_union: + // box = phi [ box1, box_union_1 ], [ box2, box_union_2 ], [ vinfo, post_box_union ] + // ... + Value *tindex = vinfo.TIndex; + BasicBlock *defaultBB = BasicBlock::Create(jl_LLVMContext, "box_union_isboxed", ctx->f); + SwitchInst *switchInst = builder.CreateSwitch(tindex, defaultBB); + BasicBlock *postBB = BasicBlock::Create(jl_LLVMContext, "post_box_union", ctx->f); + builder.SetInsertPoint(postBB); + PHINode *box_merge = builder.CreatePHI(T_pjlvalue, 2); + unsigned counter = 0; + for_each_uniontype_small( + [&](unsigned idx, jl_datatype_t *jt) { + if (idx < skip.size() && skip[idx]) + return; + Type *t = julia_type_to_llvm((jl_value_t*)jt); + BasicBlock *tempBB = BasicBlock::Create(jl_LLVMContext, "box_union", ctx->f); + builder.SetInsertPoint(tempBB); + switchInst->addCase(ConstantInt::get(T_int8, idx), tempBB); + Value *box; + if (type_is_ghost(t)) { + box = literal_pointer_val(jt->instance); + } + else { + jl_cgval_t vinfo_r = jl_cgval_t(vinfo, (jl_value_t*)jt, NULL); + box = _boxed_special(vinfo_r, t, ctx); + if (!box) { + box = emit_allocobj(ctx, jl_datatype_size(jt), literal_pointer_val((jl_value_t*)jt)); + init_bits_cgval(box, vinfo_r, jl_is_mutable(jt) ? tbaa_mutab : tbaa_immut, ctx); + } + } + box_merge->addIncoming(box, tempBB); + builder.CreateBr(postBB); + }, + vinfo.typ, + counter); + builder.SetInsertPoint(defaultBB); + if (skip.size() > 0 && skip[0]) { + box_merge->addIncoming(V_null, defaultBB); + builder.CreateBr(postBB); + } + else if (vinfo.V == NULL || isa(vinfo.V)) { + Function *trap_func = Intrinsic::getDeclaration( + ctx->f->getParent(), + Intrinsic::trap); + builder.CreateCall(trap_func); + builder.CreateUnreachable(); + } + else { + box_merge->addIncoming(emit_bitcast(vinfo.V, T_pjlvalue), defaultBB); + builder.CreateBr(postBB); + } + builder.SetInsertPoint(postBB); + return box_merge; +} + // this is used to wrap values for generic contexts, where a // dynamically-typed value is required (e.g. argument to unknown function). // if it's already a pointer it's left alone. @@ -1663,17 +1935,26 @@ static Value *boxed(const jl_cgval_t &vinfo, jl_codectx_t *ctx, bool gcrooted) return UndefValue::get(T_pjlvalue); if (vinfo.constant) return literal_pointer_val(vinfo.constant); - assert(vinfo.V); - if (vinfo.isboxed) + if (vinfo.isboxed) { + assert(vinfo.V && "Missing value for box."); return vinfo.V; + } - assert(jl_isbits(jt) && jl_is_leaf_type(jt) && "This type shouldn't have been unboxed."); - Type *t = julia_type_to_llvm(jt); - assert(!type_is_ghost(t)); // ghost values should have been handled by vinfo.constant above! - Value *box = _boxed_special(vinfo, t, ctx); - if (!box) { - box = init_bits_cgval(emit_allocobj(ctx, jl_datatype_size(jt), vinfo), - vinfo, jl_is_mutable(jt) ? tbaa_mutab : tbaa_immut, ctx); + Value *box; + if (vinfo.TIndex) { + SmallBitVector skip_none; + box = box_union(vinfo, ctx, skip_none); + } + else { + assert(vinfo.V && "Missing data for unboxed value."); + assert(jl_isbits(jt) && jl_is_leaf_type(jt) && "This type shouldn't have been unboxed."); + Type *t = julia_type_to_llvm(jt); + assert(!type_is_ghost(t)); // ghost values should have been handled by vinfo.constant above! + box = _boxed_special(vinfo, t, ctx); + if (!box) { + box = emit_allocobj(ctx, jl_datatype_size(jt), literal_pointer_val((jl_value_t*)jt)); + init_bits_cgval(box, vinfo, jl_is_mutable(jt) ? tbaa_mutab : tbaa_immut, ctx); + } } if (gcrooted) { // make a gcroot for the new box @@ -1730,11 +2011,6 @@ static Value *emit_allocobj(jl_codectx_t *ctx, size_t static_size, Value *jt) tbaa_decorate(tbaa_tag, builder.CreateStore(jt, emit_typeptr_addr(v))); return v; } -static Value *emit_allocobj(jl_codectx_t *ctx, size_t static_size, - const jl_cgval_t &v) -{ - return emit_allocobj(ctx, static_size, literal_pointer_val(v.typ)); -} // if ptr is NULL this emits a write barrier _back_ static void emit_write_barrier(jl_codectx_t *ctx, Value *parent, Value *ptr) @@ -1870,7 +2146,7 @@ static jl_cgval_t emit_new_struct(jl_value_t *ty, size_t nargs, jl_value_t **arg if (init_as_value) return mark_julia_type(strct, false, ty, ctx); else - return mark_julia_slot(strct, ty, tbaa_stack); + return mark_julia_slot(strct, ty, NULL, tbaa_stack); } Value *f1 = NULL; size_t j = 0; diff --git a/src/codegen.cpp b/src/codegen.cpp index 6961fb1a53abc..f8aecd1571a64 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -72,6 +72,7 @@ #endif // support +#include #include #include #include // for llvmcall @@ -434,6 +435,7 @@ extern "C" { // metadata tracking for a llvm Value* during codegen struct jl_cgval_t { Value *V; // may be of type T* or T, or set to NULL if ghost (or if the value has not been initialized yet, for a variable definition) + Value *TIndex; // if `V` is an unboxed (tagged) Union described by `typ`, this gives the DataType index (1-based, small int) as a T_int8 jl_value_t *constant; // constant value (rooted in linfo.def.roots) Value *gcroot; // the gcroot associated with V (if it has one) jl_value_t *typ; // the original type of V, never NULL @@ -443,10 +445,17 @@ struct jl_cgval_t { MDNode *tbaa; // The related tbaa node. Non-NULL iff this is not a pointer. bool ispointer() const { + // whether this value is compatible with `data_pointer` return tbaa != nullptr; } - jl_cgval_t(Value *V, Value *gcroot, bool isboxed, jl_value_t *typ) : // general constructor (with pointer type auto-detect) + //bool isvalue() const + //{ + // // whether this value is compatible with loading into registers (`emit_unbox` without an explicit type) + // return isbits_spec(typ) && (!ispointer() || constant); + //} + jl_cgval_t(Value *V, Value *gcroot, bool isboxed, jl_value_t *typ, Value *tindex) : // general constructor (with pointer type auto-detect) V(V), // V is allowed to be NULL in a jl_varinfo_t context, but not during codegen contexts + TIndex(tindex), constant(NULL), gcroot(gcroot), typ(typ), @@ -457,9 +466,12 @@ struct jl_cgval_t { (jl_is_mutable(typ) ? tbaa_mutab : tbaa_immut) : tbaa_value) : nullptr) { + assert(!(isboxed && TIndex != NULL)); + assert(TIndex == NULL || TIndex->getType() == T_int8); } jl_cgval_t(jl_value_t *typ) : // ghost value constructor V(NULL), + TIndex(NULL), constant(((jl_datatype_t*)typ)->instance), gcroot(NULL), typ(typ), @@ -471,8 +483,9 @@ struct jl_cgval_t { assert(jl_is_datatype(typ)); assert(constant); } - jl_cgval_t(const jl_cgval_t &v, jl_value_t *typ) : // copy constructor with new type + jl_cgval_t(const jl_cgval_t &v, jl_value_t *typ, Value *tindex) : // copy constructor with new type V(v.V), + TIndex(tindex), constant(v.constant), gcroot(v.gcroot), typ(typ), @@ -481,10 +494,18 @@ struct jl_cgval_t { isimmutable(v.isimmutable), tbaa(v.tbaa) { - assert(isboxed || v.typ == typ); // expect a badly or equivalently typed version + // this constructor expects we had a badly or equivalently typed version + // make sure we aren't discarding the actual type information + if (v.TIndex) { + assert((TIndex == NULL) == jl_is_leaf_type(typ)); + } + else { + assert(isboxed || v.typ == typ || tindex); + } } jl_cgval_t() : // undef / unreachable / default constructor V(UndefValue::get(T_void)), + TIndex(NULL), constant(NULL), gcroot(NULL), typ(jl_bottom_type), @@ -498,8 +519,9 @@ struct jl_cgval_t { // per-local-variable information struct jl_varinfo_t { - Value *boxroot; // an address, if the var is in a jl_value_t* gc stack slot or jl_box_t* Box object (marked tbaa_const, if appropriate) - jl_cgval_t value; // a value, if the var is unboxed or SSA (and thus boxroot == NULL) + Value *boxroot; // an address, if the var might be in a jl_value_t** stack slot (marked tbaa_const, if appropriate) + jl_cgval_t value; // a stack slot or constant value + Value *pTIndex; // where the current value is stored #if JL_LLVM_VERSION >= 30700 DILocalVariable *dinfo; #else @@ -517,6 +539,7 @@ struct jl_varinfo_t { jl_varinfo_t() : boxroot(NULL), value(jl_cgval_t()), + pTIndex(NULL), #if JL_LLVM_VERSION >= 30700 dinfo(NULL), #else @@ -598,7 +621,7 @@ static void allocate_gc_frame(BasicBlock *b0, jl_codectx_t *ctx); static GlobalVariable *prepare_global(GlobalVariable *G, Module *M = jl_builderModule); static Value *prepare_call(Value *Callee); static Value *prepare_call(IRBuilder<> &builder, Value *Callee); - +static void CreateTrap(IRBuilder<> &builder); template static void push_gc_use(T &&vec, const jl_cgval_t &v) { @@ -642,11 +665,11 @@ static inline jl_cgval_t ghostValue(jl_datatype_t *typ) return ghostValue((jl_value_t*)typ); } -static inline jl_cgval_t mark_julia_slot(Value *v, jl_value_t *typ, MDNode *tbaa) +static inline jl_cgval_t mark_julia_slot(Value *v, jl_value_t *typ, Value *tindex, MDNode *tbaa) { // this enables lazy-copying of immutable values and stack or argument slots assert(tbaa); - jl_cgval_t tagval(v, NULL, false, typ); + jl_cgval_t tagval(v, NULL, false, typ, tindex); tagval.tbaa = tbaa; tagval.isimmutable = true; return tagval; @@ -660,7 +683,7 @@ static inline jl_cgval_t mark_julia_type(Value *v, bool isboxed, jl_value_t *typ } if (jl_is_type_type(typ) && jl_is_leaf_type(jl_tparam0(typ))) { // replace T::Type{T} with T - jl_cgval_t constant(NULL, NULL, true, typ); + jl_cgval_t constant(NULL, NULL, true, typ, NULL); constant.constant = jl_tparam0(typ); return constant; } @@ -673,14 +696,14 @@ static inline jl_cgval_t mark_julia_type(Value *v, bool isboxed, jl_value_t *typ // llvm mem2reg pass will remove this if unneeded Value *loc = emit_static_alloca(T); builder.CreateStore(v, loc); - return mark_julia_slot(loc, typ, tbaa_stack); + return mark_julia_slot(loc, typ, NULL, tbaa_stack); } Value *froot = NULL; if (needsroot && isboxed) { froot = emit_local_root(ctx); builder.CreateStore(v, froot); } - return jl_cgval_t(v, froot, isboxed, typ); + return jl_cgval_t(v, froot, isboxed, typ, NULL); } static inline jl_cgval_t mark_julia_type(Value *v, bool isboxed, jl_datatype_t *typ, jl_codectx_t *ctx, bool needsroot = true) @@ -688,16 +711,6 @@ static inline jl_cgval_t mark_julia_type(Value *v, bool isboxed, jl_datatype_t * return mark_julia_type(v, isboxed, (jl_value_t*)typ, ctx, needsroot); } -static inline jl_cgval_t remark_julia_type(const jl_cgval_t &v, jl_value_t *typ, jl_codectx_t *ctx) -{ - if (v.typ == typ) - return v; // fast-path - Type *T = julia_type_to_llvm(typ); - if (type_is_ghost(T)) - return ghostValue(typ); - return jl_cgval_t(v, typ); -} - static inline jl_cgval_t mark_julia_const(jl_value_t *jv) { jl_value_t *typ; @@ -708,35 +721,43 @@ static inline jl_cgval_t mark_julia_const(jl_value_t *jv) if (type_is_ghost(julia_type_to_llvm(typ))) { return ghostValue(typ); } - jl_cgval_t constant(NULL, NULL, true, typ); + jl_cgval_t constant(NULL, NULL, true, typ, NULL); constant.constant = jv; return constant; } -// --- utilities --- +// --- allocating local variables --- -static void emit_write_barrier(jl_codectx_t*, Value*, Value*); +static bool isbits_spec(jl_value_t *jt, bool allow_singleton = true) +{ + return jl_isbits(jt) && jl_is_leaf_type(jt) && + (allow_singleton || (jl_datatype_size(jt) > 0) || (jl_datatype_nfields(jt) > 0)); +} -#include "cgutils.cpp" +static jl_sym_t *slot_symbol(int s, jl_codectx_t *ctx) +{ + return (jl_sym_t*)jl_array_ptr_ref(ctx->source->slotnames, s); +} -static void jl_rethrow_with_add(const char *fmt, ...) +static void store_def_flag(const jl_varinfo_t &vi, bool val) { - jl_ptls_t ptls = jl_get_ptls_states(); - if (jl_typeis(ptls->exception_in_transit, jl_errorexception_type)) { - char *str = jl_string_data(jl_fieldref(ptls->exception_in_transit,0)); - char buf[1024]; - va_list args; - va_start(args, fmt); - int nc = vsnprintf(buf, sizeof(buf), fmt, args); - va_end(args); - nc += snprintf(buf+nc, sizeof(buf)-nc, ": %s", str); - jl_value_t *msg = jl_pchar_to_string(buf, nc); - JL_GC_PUSH1(&msg); - jl_throw(jl_new_struct(jl_errorexception_type, msg)); + assert((!vi.boxroot || vi.pTIndex) && "undef check is null pointer for boxed things"); + assert(vi.usedUndef && vi.defFlag && "undef flag codegen corrupted"); + builder.CreateStore(ConstantInt::get(T_int1, val), vi.defFlag, vi.isVolatile); +} + +static void alloc_def_flag(jl_varinfo_t& vi, jl_codectx_t* ctx) +{ + assert((!vi.boxroot || vi.pTIndex) && "undef check is null pointer for boxed things"); + if (vi.usedUndef) { + vi.defFlag = emit_static_alloca(T_int1, ctx); + store_def_flag(vi, false); } - jl_rethrow(); } + +// --- utilities --- + static void CreateTrap(IRBuilder<> &builder) { Function *f = builder.GetInsertBlock()->getParent(); @@ -749,56 +770,193 @@ static void CreateTrap(IRBuilder<> &builder) builder.SetInsertPoint(newBB); } -// --- allocating local variables --- - -static bool isbits_spec(jl_value_t *jt, bool allow_singleton = true) +#ifndef NDEBUG +static void CreateConditionalAbort(IRBuilder<> &builder, Value *test) { - return jl_isbits(jt) && jl_is_leaf_type(jt) && - (allow_singleton || (jl_datatype_size(jt) > 0) || (jl_datatype_nfields(jt) > 0)); + Function *f = builder.GetInsertBlock()->getParent(); + BasicBlock *abortBB = BasicBlock::Create(jl_LLVMContext, "debug_abort", f); + BasicBlock *postBB = BasicBlock::Create(jl_LLVMContext, "post_abort", f); + builder.CreateCondBr(test, abortBB, postBB); + builder.SetInsertPoint(abortBB); + Function *trap_func = Intrinsic::getDeclaration( + f->getParent(), + Intrinsic::trap); + builder.CreateCall(trap_func); + builder.CreateUnreachable(); + builder.SetInsertPoint(postBB); } +#endif -static jl_sym_t *slot_symbol(int s, jl_codectx_t *ctx) -{ - return (jl_sym_t*)jl_array_ptr_ref(ctx->source->slotnames, s); -} +static void emit_write_barrier(jl_codectx_t*, Value*, Value*); -static void store_def_flag(const jl_varinfo_t &vi, bool val) -{ - assert(!vi.boxroot && "undef check is null pointer for boxed things"); - assert(vi.usedUndef && vi.defFlag && "undef flag codegen corrupted"); - builder.CreateStore(ConstantInt::get(T_int1, val), vi.defFlag, vi.isVolatile); -} +#include "cgutils.cpp" -static void alloc_def_flag(jl_varinfo_t& vi, jl_codectx_t* ctx) +static void jl_rethrow_with_add(const char *fmt, ...) { - assert(!vi.boxroot && "undef check is null pointer for boxed things"); - if (vi.usedUndef) { - vi.defFlag = emit_static_alloca(T_int1, ctx); - store_def_flag(vi, false); + jl_ptls_t ptls = jl_get_ptls_states(); + if (jl_typeis(ptls->exception_in_transit, jl_errorexception_type)) { + char *str = jl_string_data(jl_fieldref(ptls->exception_in_transit,0)); + char buf[1024]; + va_list args; + va_start(args, fmt); + int nc = vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + nc += snprintf(buf+nc, sizeof(buf)-nc, ": %s", str); + jl_value_t *msg = jl_pchar_to_string(buf, nc); + JL_GC_PUSH1(&msg); + jl_throw(jl_new_struct(jl_errorexception_type, msg)); } + jl_rethrow(); } -static void maybe_alloc_arrayvar(int s, jl_codectx_t *ctx) +// given a value marked with type `v.typ`, compute the mapping and/or boxing to return a value of type `typ` +static inline jl_cgval_t remark_julia_type(const jl_cgval_t &v, jl_value_t *typ, jl_codectx_t *ctx, bool needsroot = true) { - jl_value_t *jt = ctx->slots[s].value.typ; - if (arraytype_constshape(jt)) { - // TODO: this optimization does not yet work with 1-d arrays, since the - // length and data pointer can change at any time via push! - // we could make it work by reloading the metadata when the array is - // passed to an external function (ideally only impure functions) - jl_arrayvar_t av; - int ndims = jl_unbox_long(jl_tparam1(jt)); - Type *elt = julia_type_to_llvm(jl_tparam0(jt)); - if (type_is_ghost(elt)) - return; - // CreateAlloca is OK here because maybe_alloc_arrayvar is only called in the prologue setup - av.dataptr = builder.CreateAlloca(PointerType::get(elt,0)); - av.len = builder.CreateAlloca(T_size); - for (int i = 0; i < ndims - 1; i++) - av.sizes.push_back(builder.CreateAlloca(T_size)); - av.ty = jt; - (*ctx->arrayvars)[s] = av; + if (v.typ == typ || v.typ == jl_bottom_type || jl_egal(v.typ, typ)) + return v; // fast-path + Type *T = julia_type_to_llvm(typ); + if (type_is_ghost(T)) + return ghostValue(typ); + Value *new_tindex = NULL; + if (!jl_is_leaf_type(typ)) { + bool makeboxed = false; + if (v.TIndex) { + // previous value was a split union, compute new index, or box + new_tindex = ConstantInt::get(T_int8, 0); + SmallBitVector skip_box(1, true); + Value *tindex = v.TIndex; + if (jl_is_uniontype(typ)) { + // compute the TIndex mapping from v.typ -> typ + unsigned counter = 0; + for_each_uniontype_small( + // for each old union-split value + [&](unsigned idx, jl_datatype_t *jt) { + unsigned new_idx = get_box_tindex(jt, typ); + bool t; + if (new_idx) { + // found a matching element + Value *cmp = builder.CreateICmpEQ(tindex, ConstantInt::get(T_int8, idx)); + new_tindex = builder.CreateSelect(cmp, ConstantInt::get(T_int8, new_idx), new_tindex); + t = true; + } + else if (!jl_subtype((jl_value_t*)jt, typ)) { + // new value doesn't need to be boxed + // since it isn't part of the new union + t = true; + } + else { + // will actually need to box this element + // since it appeared as a leaftype in the original type + // but not in the remark type + t = false; + } + skip_box.resize(idx + 1, t); + }, + v.typ, + counter); + } + if (!isa(new_tindex)) { + if (!skip_box.all()) { + // some values weren't unboxed in the new union + // box them now (tindex above already selected 0 = box for them) + // root the result, and return a new mark_julia_slot over the result + Value *boxv = box_union(v, ctx, skip_box); + Value *froot = NULL; + if (needsroot) { + froot = emit_local_root(ctx); + if (v.V) { // oldbox might be all ghost values + Value *oldbox = v.ispointer() ? v.V : ConstantPointerNull::get((PointerType*)T_pjlvalue); + boxv = builder.CreateSelect(builder.CreateICmpEQ(tindex, ConstantInt::get(T_int8, 0)), + emit_bitcast(oldbox, boxv->getType()), boxv); + } + builder.CreateStore(boxv, froot); + } + Value *isnewbox = builder.CreateIsNotNull(boxv); + Value *slotv; + MDNode *tbaa; + bool isimmutable; + if (v.V == NULL) { + // v.V might be NULL if it was all ghost objects before + return jl_cgval_t(boxv, froot, false, typ, new_tindex); + } + else { + if (v.ispointer()) { + slotv = v.V; + tbaa = v.tbaa; + isimmutable = v.isimmutable; + } + else { + slotv = emit_static_alloca(v.V->getType()); + builder.CreateStore(v.V, slotv); + tbaa = tbaa_stack; + isimmutable = true; + } + slotv = builder.CreateSelect(isnewbox, boxv, emit_bitcast(slotv, boxv->getType())); + jl_cgval_t newv = jl_cgval_t(slotv, froot, false, typ, new_tindex); + newv.tbaa = tbaa; + newv.isimmutable = isimmutable; + return newv; + } + } + } + else { + new_tindex = NULL; + makeboxed = true; + } + } + else if (!v.isboxed && jl_is_uniontype(typ)) { + // previous value was unboxed (leaftype), statically compute union tindex + assert(jl_is_leaf_type(v.typ)); + unsigned new_idx = get_box_tindex((jl_datatype_t*)v.typ, typ); + if (new_idx) { + new_tindex = ConstantInt::get(T_int8, new_idx); + if (v.V && !v.ispointer()) { + // TODO: remove this branch once all consumers of v.TIndex understand how to handle a non-ispointer value + Value *slotv = emit_static_alloca(v.V->getType()); + builder.CreateStore(v.V, slotv); + jl_cgval_t newv = jl_cgval_t(slotv, NULL, false, typ, new_tindex); + newv.tbaa = tbaa_stack; + newv.isimmutable = true; + return newv; + } + } + else if (jl_subtype(v.typ, typ)) { + makeboxed = true; + } + else { + // unreachable + CreateTrap(builder); + return jl_cgval_t(); + } + } + else if (!v.isboxed) { + makeboxed = true; + } + if (makeboxed) { + // convert to a simple isboxed value + Value *boxv = boxed(v, ctx); + Value *froot = NULL; + if (needsroot) { + froot = emit_local_root(ctx); + builder.CreateStore(boxv, froot); + } + return jl_cgval_t(boxv, froot, true, typ, NULL); + } } + else { + if (v.TIndex && !isbits_spec(typ)) { + // discovered that this union-split type must actually be isboxed + if (v.V) { + return jl_cgval_t(v.V, v.gcroot, true, typ, NULL); + } + else { + // type mismatch (there wasn't any boxed values in the union) + CreateTrap(builder); + return jl_cgval_t(); + } + } + } + return jl_cgval_t(v, typ, new_tindex); } // Snooping on which functions are being compiled, and how long it takes @@ -933,7 +1091,6 @@ jl_llvm_functions_t jl_compile_linfo(jl_method_instance_t **pli, jl_code_info_t Function *f = (Function*)decls.functionObject; Function *specf = (Function*)decls.specFunctionObject; - if (JL_HOOK_TEST(params, module_activation)) { JL_HOOK_CALL(params, module_activation, 1, jl_box_voidpointer(wrap(m.release()))); } else { @@ -2195,8 +2352,8 @@ static Value *emit_bits_compare(const jl_cgval_t &arg1, const jl_cgval_t &arg2, if (type_is_ghost(fld1->getType()->getPointerElementType())) continue; subAns = emit_bits_compare( - mark_julia_slot(fld1, fldty, arg1.tbaa), - mark_julia_slot(fld2, fldty, arg2.tbaa), + mark_julia_slot(fld1, fldty, NULL, arg1.tbaa), + mark_julia_slot(fld2, fldty, NULL, arg2.tbaa), ctx); answer = builder.CreateAnd(answer, subAns); } @@ -2211,17 +2368,17 @@ static Value *emit_bits_compare(const jl_cgval_t &arg1, const jl_cgval_t &arg2, static Value *emit_f_is(const jl_cgval_t &arg1, const jl_cgval_t &arg2, jl_codectx_t *ctx) { jl_value_t *rt1 = arg1.typ, *rt2 = arg2.typ; - bool isleaf = jl_is_leaf_type(rt1) && jl_is_leaf_type(rt2); - if (isleaf && rt1 != rt2 && !jl_is_type_type(rt1) && !jl_is_type_type(rt2)) - // disjoint leaf types are never equal (quick test) + if (jl_is_leaf_type(rt1) && jl_is_leaf_type(rt2) && rt1 != rt2 + && !jl_is_type_type(rt1) && !jl_is_type_type(rt2)) + // disjoint concrete leaf types are never equal (quick test) return ConstantInt::get(T_int1, 0); - bool ghost1 = arg1.isghost || (isleaf && jl_is_datatype_singleton((jl_datatype_t*)rt1)); - bool ghost2 = arg2.isghost || (isleaf && jl_is_datatype_singleton((jl_datatype_t*)rt2)); - if (ghost1 || ghost2) { - // comparing singleton objects - if (ghost1 && ghost2) { - return ConstantInt::get(T_int1, rt1 == rt2); - } + + if (arg1.isghost || arg2.isghost) { + // comparing to a singleton object + if (arg1.TIndex) + return emit_isa(arg1, rt2, NULL, ctx); // rt2 is a singleton type + if (arg2.TIndex) + return emit_isa(arg2, rt1, NULL, ctx); // rt1 is a singleton type // mark_gc_use isn't needed since we won't load this pointer // and we know at least one of them is a unique Singleton // which is already enough to ensure pointer uniqueness for this test @@ -2232,24 +2389,46 @@ static Value *emit_f_is(const jl_cgval_t &arg1, const jl_cgval_t &arg2, jl_codec if (jl_type_intersection(rt1, rt2) == (jl_value_t*)jl_bottom_type) // types are disjoint (exhaustive test) return ConstantInt::get(T_int1, 0); - bool isbits = isleaf && jl_isbits(rt1) && jl_types_equal(rt1, rt2); + bool isbits = jl_isbits(rt1) || jl_isbits(rt2); if (isbits) { // whether this type is unique'd by value - return emit_bits_compare(arg1, arg2, ctx); + jl_value_t *typ = jl_isbits(rt1) ? rt1 : rt2; + if (rt1 == rt2) + return emit_bits_compare(arg1, arg2, ctx); + Value *same_type = (typ == rt2) ? emit_isa(arg1, typ, NULL, ctx) : emit_isa(arg2, typ, NULL, ctx); + BasicBlock *currBB = builder.GetInsertBlock(); + BasicBlock *isaBB = BasicBlock::Create(jl_LLVMContext, "is", ctx->f); + BasicBlock *postBB = BasicBlock::Create(jl_LLVMContext, "post_is", ctx->f); + builder.CreateCondBr(same_type, isaBB, postBB); + builder.SetInsertPoint(isaBB); + Value *bitcmp = emit_bits_compare( + jl_cgval_t(arg1, typ, NULL), + jl_cgval_t(arg2, typ, NULL), + ctx); + builder.CreateBr(postBB); + builder.SetInsertPoint(postBB); + PHINode *cmp = builder.CreatePHI(T_int1, 2); + cmp->addIncoming(ConstantInt::get(T_int1, 0), currBB); + cmp->addIncoming(bitcmp, isaBB); + return cmp; } int ptr_comparable = 0; // whether this type is unique'd by pointer - if (rt1==(jl_value_t*)jl_sym_type || rt2==(jl_value_t*)jl_sym_type || - jl_is_mutable_datatype(rt1) || jl_is_mutable_datatype(rt2)) // excludes abstract types + if (rt1 == (jl_value_t*)jl_sym_type || rt2 == (jl_value_t*)jl_sym_type) + ptr_comparable = 1; + if (jl_is_mutable_datatype(rt1) || jl_is_mutable_datatype(rt2)) // excludes abstract types ptr_comparable = 1; if (jl_subtype(rt1, (jl_value_t*)jl_type_type) || - jl_subtype(rt2, (jl_value_t*)jl_type_type)) // use typeseq for datatypes + jl_subtype(rt2, (jl_value_t*)jl_type_type)) // need to use typeseq for datatypes ptr_comparable = 0; if ((jl_is_type_type(rt1) && jl_is_leaf_type(jl_tparam0(rt1))) || (jl_is_type_type(rt2) && jl_is_leaf_type(jl_tparam0(rt2)))) // can compare leaf types by pointer ptr_comparable = 1; if (ptr_comparable) { - assert(arg1.isboxed && arg2.isboxed); // only boxed types are valid for pointer comparison - return builder.CreateICmpEQ(boxed(arg1, ctx), boxed(arg2, ctx)); + Value *varg1 = arg1.constant ? literal_pointer_val(arg1.constant) : arg1.V; + Value *varg2 = arg2.constant ? literal_pointer_val(arg2.constant) : arg2.V; + assert(varg1 && varg2 && (arg1.isboxed || arg1.TIndex) && (arg2.isboxed || arg2.TIndex) && + "Only boxed types are valid for pointer comparison."); + return builder.CreateICmpEQ(varg1, varg2); } JL_FEAT_REQUIRE(ctx, runtime); @@ -2309,13 +2488,11 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, jl_value_t *tp0 = jl_tparam0(ty); *ret = emit_expr(args[1], ctx); emit_expr(args[2], ctx); - if (jl_subtype(arg, tp0)) { - JL_GC_POP(); - return true; - } - emit_typecheck(*ret, tp0, "typeassert", ctx); - if (ret->isboxed) - *ret = remark_julia_type(*ret, expr_type(expr, ctx), ctx); + if (!jl_subtype(arg, tp0)) + emit_typecheck(*ret, tp0, "typeassert", ctx); + ty = expr_type(expr, ctx); rt2 = ty; + if (ret->isboxed || (ret->TIndex && jl_is_leaf_type(ty))) // see if it might be profitable (cheap) to remark the type + *ret = remark_julia_type(*ret, ty, ctx); JL_GC_POP(); return true; } @@ -2349,11 +2526,11 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, emit_expr(args[2], ctx); if (jl_subtype(arg, tp0)) { *ret = mark_julia_type(ConstantInt::get(T_int8, 1), false, jl_bool_type, ctx); - JL_GC_POP(); - return true; } - Value *isa = emit_isa(rt_arg, tp0, NULL, ctx); - *ret = mark_julia_type(builder.CreateZExt(isa, T_int8), false, jl_bool_type, ctx); + else { + Value *isa = emit_isa(rt_arg, tp0, NULL, ctx); + *ret = mark_julia_type(builder.CreateZExt(isa, T_int8), false, jl_bool_type, ctx); + } JL_GC_POP(); return true; } @@ -2609,7 +2786,7 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, Value *valen = emit_n_varargs(ctx); Value *idx = emit_unbox(T_size, emit_expr(args[2], ctx), fldt); idx = emit_bounds_check( - jl_cgval_t(builder.CreateGEP(ctx->argArray, ConstantInt::get(T_size, ctx->nReqArgs)), NULL, false, NULL), + jl_cgval_t(builder.CreateGEP(ctx->argArray, ConstantInt::get(T_size, ctx->nReqArgs)), NULL, false, NULL, NULL), NULL, idx, valen, ctx); idx = builder.CreateAdd(idx, ConstantInt::get(T_size, ctx->nReqArgs)); *ret = mark_julia_type( @@ -2910,7 +3087,7 @@ static jl_cgval_t emit_call_function_object(jl_method_instance_t *li, const jl_c call->setAttributes(cf->getAttributes()); mark_gc_uses(gc_uses); if (sret) - return mark_julia_slot(result, jlretty, tbaa_stack); + return mark_julia_slot(result, jlretty, NULL, tbaa_stack); // see if codegen has a better type for the call than inference had at the time if (!retboxed && jlretty != inferred_retty) { inferred_retty = jlretty; @@ -3158,9 +3335,11 @@ static jl_cgval_t emit_local(jl_value_t *slotload, jl_codectx_t *ctx) jl_cgval_t v; Value *isnull = NULL; - if (vi.boxroot == NULL) { - if (!vi.isVolatile || vi.value.constant) { + if (vi.boxroot == NULL || vi.pTIndex != NULL) { + if (!vi.isVolatile || vi.value.constant || !vi.value.V) { v = vi.value; + if (vi.pTIndex) + v.TIndex = builder.CreateLoad(vi.pTIndex); } else { // copy value to a non-volatile location @@ -3171,19 +3350,41 @@ static jl_cgval_t emit_local(jl_value_t *slotload, jl_codectx_t *ctx) // TODO: emit memcpy instead Value *unbox = builder.CreateLoad(vi.value.V, /*volatile*/true); builder.CreateStore(unbox, slot); - v = mark_julia_slot(slot, vi.value.typ, tbaa_stack); + Value *tindex = NULL; + if (vi.pTIndex) + tindex = builder.CreateLoad(vi.pTIndex, /*volatile*/true); + v = mark_julia_slot(slot, vi.value.typ, tindex, tbaa_stack); } + if (vi.boxroot == NULL && typ != v.typ) + v = remark_julia_type(v, typ, ctx); if (vi.usedUndef) { assert(vi.defFlag); isnull = builder.CreateLoad(vi.defFlag, vi.isVolatile); } } - else { + if (vi.boxroot != NULL) { Value *boxed = builder.CreateLoad(vi.boxroot, vi.isVolatile); - v = mark_julia_type(boxed, true, typ, ctx, - /*gc-root*/!vi.isArgument); // if an argument, doesn't need an additional root + Value *box_isnull; if (vi.usedUndef) - isnull = builder.CreateICmpNE(boxed, V_null); + box_isnull = builder.CreateICmpNE(boxed, V_null); + if (vi.pTIndex) { + // value is either boxed in the stack slot, or unboxed in value + // as indicated by comparing pTIndex to 0 + Value *load_box = builder.CreateICmpEQ(v.TIndex, ConstantInt::get(T_int8, 0)); + if (vi.usedUndef) + isnull = builder.CreateSelect(load_box, box_isnull, isnull); + if (v.V) // v.V will be null if it is a union of all ghost values + v.V = builder.CreateSelect(load_box, boxed, emit_bitcast(v.V, boxed->getType())); + else + v.V = boxed; + v = remark_julia_type(v, typ, ctx); + } + else { + v = mark_julia_type(boxed, true, typ, ctx, + /*gc-root*/!vi.isArgument); // if an argument, doesn't need an additional root + if (vi.usedUndef) + isnull = box_isnull; + } } if (isnull) undef_var_error_ifnot(isnull, sym, ctx); @@ -3191,6 +3392,40 @@ static jl_cgval_t emit_local(jl_value_t *slotload, jl_codectx_t *ctx) } +Value *try_emit_union_alloca(jl_uniontype_t *ut, bool &allunbox, size_t &min_align, jl_codectx_t *ctx) +{ + allunbox = true; + min_align = MAX_ALIGN; + size_t nb = 0, align = 0; + // compute the size of the union alloca that could hold this type + unsigned counter = 0; + allunbox = for_each_uniontype_small( + [&](unsigned idx, jl_datatype_t *jt) { + if (!jl_is_datatype_singleton(jt)) { + size_t nb1 = jl_datatype_size(jt); + size_t align1 = jt->layout->alignment; + if (nb1 > nb) + nb = nb1; + if (align1 > align) + align = align1; + if (align1 < min_align) + min_align = align1; + } + }, + (jl_value_t*)ut, + counter); + if (nb > 0) { + // at least some of the values can live on the stack + Type *AT = ArrayType::get(T_int8, nb); + AllocaInst *lv = emit_static_alloca(AT, ctx); + if (align > 1) + lv->setAlignment(align); + return lv; + } + return NULL; +} + + static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) { if (jl_is_ssavalue(l)) { @@ -3198,8 +3433,9 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) assert(idx >= 0); assert(!ctx->ssavalue_assigned.at(idx)); jl_cgval_t slot = emit_expr(r, ctx); // slot could be a jl_value_t (unboxed) or jl_value_t* (ispointer) - if (slot.isboxed) { - // see if inference had a better type for the ssavalue than the expression (after inlining getfield on a Tuple) + if (slot.isboxed || slot.TIndex) { + // see if inference suggested a different type for the ssavalue than the expression + // e.g. sometimes the information is inconsistent after inlining getfield on a Tuple jl_value_t *ssavalue_types = (jl_value_t*)ctx->source->ssavaluetypes; if (jl_is_array(ssavalue_types)) { jl_value_t *declType = jl_array_ptr_ref(ssavalue_types, idx); @@ -3210,12 +3446,53 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) } if (!slot.isboxed && !slot.isimmutable) { // emit a copy of values stored in mutable slots - bool isboxed; - Type *vtype = julia_type_to_llvm(slot.typ, &isboxed); - assert(!isboxed); - Value *dest = emit_static_alloca(vtype); - emit_unbox(vtype, slot, slot.typ, dest); - slot = mark_julia_slot(dest, slot.typ, tbaa_stack); + Value *dest; + jl_value_t *jt = slot.typ; + if (jl_is_uniontype(jt)) { + assert(slot.TIndex && "Unboxed union must have a type-index."); + bool allunbox; + size_t min_align; + dest = try_emit_union_alloca(((jl_uniontype_t*)jt), allunbox, min_align, ctx); + Value *isboxed = NULL; + if (slot.ispointer() && slot.V != NULL && !isa(slot.V)) { + isboxed = builder.CreateICmpEQ(slot.TIndex, ConstantInt::get(T_int8, 0)); + } + if (dest) { + Value *copy_bytes = emit_sizeof(slot, ctx); + if (isboxed) + copy_bytes = builder.CreateSelect(isboxed, ConstantInt::get(copy_bytes->getType(), 0), copy_bytes); + builder.CreateMemCpy(dest, + data_pointer(slot, ctx, T_pint8), + copy_bytes, + min_align); + } + Value *gcroot = NULL; + if (isboxed) { + if (slot.gcroot) + gcroot = emit_local_root(ctx); + else + gcroot = emit_static_alloca(T_pjlvalue); + Value *box = builder.CreateSelect(isboxed, emit_bitcast(slot.V, T_pjlvalue), ConstantPointerNull::get((PointerType*)T_pjlvalue)); + builder.CreateStore(box, gcroot); + if (dest) // might be all ghost values + dest = builder.CreateSelect(isboxed, box, emit_bitcast(dest, box->getType())); + else + dest = box; + } + else { + assert(allunbox && "Failed to allocate correct union-type storage."); + } + slot = mark_julia_slot(dest, slot.typ, slot.TIndex, tbaa_stack); + slot.gcroot = gcroot; + } + else { + bool isboxed; + Type *vtype = julia_type_to_llvm(slot.typ, &isboxed); + assert(!isboxed); + dest = emit_static_alloca(vtype); + emit_unbox(vtype, slot, slot.typ, dest); + slot = mark_julia_slot(dest, slot.typ, NULL, tbaa_stack); + } } ctx->SAvalues.at(idx) = slot; // now SAvalues[idx] contains the SAvalue ctx->ssavalue_assigned.at(idx) = true; @@ -3258,6 +3535,17 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) if (!vi.used) return; + bool needs_root = false; + if ((!vi.isSA && rval_info.gcroot) || !rval_info.isboxed) + // rval needed a gcroot, so lval will need one too + needs_root = true; + + // convert rval-type to lval-type + jl_value_t *slot_type = vi.value.typ; + rval_info = remark_julia_type(rval_info, slot_type, ctx, /*needs-root*/false); + if (rval_info.typ == jl_bottom_type) + return; + // add info to arrayvar list if (rval_info.isboxed) { // check isboxed in case rval isn't the right type (for example, on a dead branch), @@ -3267,26 +3555,105 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) assign_arrayvar(*av, rval_info, ctx); } + Value *isboxed = NULL; if (vi.boxroot) { // boxed variables - if (((!vi.isSA && rval_info.gcroot) || !rval_info.isboxed) && isa(vi.boxroot)) { - // rval had a gcroot, so lval needs one too: promote variable slot to a gcroot - emit_local_root(ctx, &vi); + if (isa(vi.boxroot) && needs_root) + emit_local_root(ctx, &vi); // promote variable slot to a gcroot + Value *rval; + if (vi.pTIndex && rval_info.TIndex) { + builder.CreateStore(rval_info.TIndex, vi.pTIndex, vi.isVolatile); + isboxed = builder.CreateICmpEQ(rval_info.TIndex, ConstantInt::get(T_int8, 0)); + rval = ConstantPointerNull::get((PointerType*)T_pjlvalue); + if (rval_info.V) // might be all ghost values + rval = builder.CreateSelect(isboxed, emit_bitcast(rval_info.V, rval->getType()), rval); + assert(!vi.value.constant); + // will handle tindex later + } + else { + assert(!vi.pTIndex || rval_info.isboxed || rval_info.constant); + if (vi.pTIndex) + builder.CreateStore(ConstantInt::get(T_int8, 0), vi.pTIndex, vi.isVolatile); + rval = boxed(rval_info, ctx, false); } - Value *rval = boxed(rval_info, ctx, false); // no root needed on the temporary since it is about to be assigned to the variable slot builder.CreateStore(rval, vi.boxroot, vi.isVolatile); } - else { + + if (!vi.boxroot || (vi.pTIndex && rval_info.TIndex)) { + // store unboxed variables if (vi.usedUndef) store_def_flag(vi, true); - if (vi.value.constant) { - // virtual store + if (!vi.value.constant) { // check that this is not a virtual store + assert(vi.value.ispointer() || (vi.pTIndex && vi.value.V == NULL)); + // store tindex info (if not handled above) + if (vi.pTIndex && !vi.boxroot) { + Value *tindex_no_zero; + if (rval_info.constant) + tindex_no_zero = ConstantInt::get(T_int8, get_box_tindex((jl_datatype_t*)jl_typeof(rval_info.constant), vi.value.typ)); + else if (rval_info.isboxed) + tindex_no_zero = compute_box_tindex(emit_typeof_boxed(rval_info, ctx), vi.value.typ, ctx); + else if (!rval_info.V || isa(rval_info.V)) + tindex_no_zero = rval_info.TIndex; + else + tindex_no_zero = builder.CreateSelect( + builder.CreateICmpEQ(rval_info.TIndex, ConstantInt::get(T_int8, 0)), + compute_box_tindex(emit_typeof(rval_info.V), vi.value.typ, ctx), + rval_info.TIndex); + builder.CreateStore(tindex_no_zero, vi.pTIndex, vi.isVolatile); + } + // store value + if (vi.value.V == NULL) { + // all ghost values in destination - nothing to copy or store + } + else if (rval_info.ispointer()) { + MDNode *tbaa = rval_info.tbaa; + // the memcpy intrinsic does not allow to specify different alias tags + // for the load part (x.tbaa) and the store part (tbaa_stack). + // since the tbaa lattice has to be a tree we have unfortunately + // x.tbaa ∪ tbaa_stack = tbaa_root if x.tbaa != tbaa_stack + if (tbaa != tbaa_stack) + tbaa = NULL; + Value *copy_bytes; + if (vi.pTIndex == NULL) { + assert(jl_is_leaf_type(vi.value.typ)); + copy_bytes = ConstantInt::get(T_int32, jl_datatype_size(vi.value.typ)); + } + else { + copy_bytes = emit_sizeof(rval_info, ctx); + if (isboxed) + copy_bytes = builder.CreateSelect(isboxed, ConstantInt::get(copy_bytes->getType(), 0), copy_bytes); + } + builder.CreateMemCpy(vi.value.V, + data_pointer(rval_info, ctx, T_pint8), + copy_bytes, + /*TODO: min_align*/1, + vi.isVolatile, + tbaa); + } + else if (rval_info.V == NULL) { + // all ghost values in source - nothing to copy or store + } + else { + if (rval_info.typ != vi.value.typ && !vi.pTIndex && !rval_info.TIndex) { + // cast-on-assignment is invalid. this branch should emit dead-code. + CreateTrap(builder); + } + else { + Value *dest = vi.value.V; + Type *store_ty = julia_type_to_llvm(rval_info.typ); + Type *dest_ty = store_ty->getPointerTo(); + if (dest_ty != dest->getType()) + dest = emit_bitcast(dest, dest_ty); + tbaa_decorate(tbaa_stack, builder.CreateStore( + emit_unbox(store_ty, rval_info, rval_info.typ), + dest, + vi.isVolatile)); + } + } } else { - // store unboxed - assert(vi.value.ispointer()); - emit_unbox(julia_type_to_llvm(vi.value.typ), rval_info, vi.value.typ, vi.value.V, vi.isVolatile); + assert(vi.pTIndex == NULL); } } } @@ -3298,6 +3665,10 @@ static Value *emit_condition(const jl_cgval_t &condV, const std::string &msg, { bool isbool = (condV.typ == (jl_value_t*)jl_bool_type); if (!isbool) { + if (condV.TIndex) { + // check whether this might be bool + isbool = jl_subtype((jl_value_t*)jl_bool_type, condV.typ); + } emit_typecheck(condV, (jl_value_t*)jl_bool_type, msg, ctx); } if (isbool) { @@ -3339,7 +3710,7 @@ static void emit_stmtpos(jl_value_t *expr, jl_codectx_t *ctx) Value *lv = vi.boxroot; if (lv != NULL) builder.CreateStore(V_null, lv); - else + if (lv == NULL || vi.pTIndex != NULL) store_def_flag(vi, false); } return; @@ -4028,7 +4399,7 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t arg_box = arg_v; } else if (et->isAggregateType()) { - arg_box = boxed(mark_julia_slot(arg_v, jt, tbaa_const), &ctx2, false); + arg_box = boxed(mark_julia_slot(arg_v, jt, NULL, tbaa_const), &ctx2, false); } else { assert(at == et); @@ -4250,7 +4621,7 @@ static Function *gen_jlcall_wrapper(jl_method_instance_t *lam, Function *f, cons (void)julia_type_to_llvm(jlretty, &retboxed); if (sret) { assert(!retboxed); } jl_cgval_t retval = sret - ? mark_julia_slot(result, jlretty, tbaa_stack) + ? mark_julia_slot(result, jlretty, NULL, tbaa_stack) : mark_julia_type(call, retboxed, jlretty, &ctx, /*needsroot*/false); builder.CreateRet(boxed(retval, &ctx, false)); // no gcroot needed since this on the return path @@ -4768,6 +5139,31 @@ static std::unique_ptr emit_function( if (i != (size_t)ctx.vaSlot && isbits_spec(jt, false)) continue; } + else if (jl_is_uniontype(jt)) { + bool allunbox; + size_t align; + Value *lv = try_emit_union_alloca((jl_uniontype_t*)jt, allunbox, align, &ctx); + if (lv) { + lv->setName(jl_symbol_name(s)); + varinfo.value = mark_julia_slot(lv, jt, NULL, tbaa_stack); + varinfo.pTIndex = emit_static_alloca(T_int8, &ctx); + // the slot is not immutable if there are multiple assignments + varinfo.value.isimmutable &= varinfo.isSA; + } + else if (allunbox) { + // all ghost values just need a selector allocated + AllocaInst *lv = emit_static_alloca(T_int8, &ctx); + lv->setName(jl_symbol_name(s)); + varinfo.pTIndex = lv; + varinfo.value.tbaa = NULL; + varinfo.value.isboxed = false; + varinfo.value.isimmutable = true; + } + if (lv || allunbox) + alloc_def_flag(varinfo, &ctx); + if (allunbox) + continue; + } else if (isbits_spec(jt, false)) { bool isboxed; Type *vtype = julia_type_to_llvm(jt, &isboxed); @@ -4775,7 +5171,7 @@ static std::unique_ptr emit_function( assert(!type_is_ghost(vtype) && "constants should already be handled"); // CreateAlloca is OK during prologue setup Value *lv = builder.CreateAlloca(vtype, NULL, jl_symbol_name(s)); - varinfo.value = mark_julia_slot(lv, jt, tbaa_stack); + varinfo.value = mark_julia_slot(lv, jt, NULL, tbaa_stack); // slot is not immutable if there are multiple assignments varinfo.value.isimmutable &= varinfo.isSA; alloc_def_flag(varinfo, &ctx); @@ -4846,7 +5242,7 @@ static std::unique_ptr emit_function( theArg = ghostValue(argType); } else if (llvmArgType->isAggregateType()) { - theArg = mark_julia_slot(&*AI++, argType, tbaa_const); // this argument is by-pointer + theArg = mark_julia_slot(&*AI++, argType, NULL, tbaa_const); // this argument is by-pointer theArg.isimmutable = true; } else { @@ -5272,10 +5668,13 @@ static std::unique_ptr emit_function( mallocVisitLine(props.file, props.line); if (toplevel) builder.CreateStore(last_age, ctx.world_age_field); - if (type_is_ghost(retty) || ctx.sret) + if (type_is_ghost(retty) || ctx.sret) { builder.CreateRetVoid(); - else + } + else { + assert(retval->getType() == ctx.f->getReturnType()); builder.CreateRet(retval); + } find_next_stmt(-1); continue; } diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index f865217b7c69b..cc444e1cf3ea6 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -459,13 +459,14 @@ static jl_cgval_t generic_bitcast(const jl_cgval_t *argv, jl_codectx_t *ctx) vx = emit_bitcast(vx, llvmt); } - if (jl_is_leaf_type(bt)) + if (jl_is_leaf_type(bt)) { return mark_julia_type(vx, false, bt, ctx); - else - return mark_julia_type( - init_bits_value(emit_allocobj(ctx, nb, boxed(bt_value, ctx)), - vx, tbaa_immut), - true, bt, ctx); + } + else { + Value *box = emit_allocobj(ctx, nb, boxed(bt_value, ctx)); + init_bits_value(box, vx, tbaa_immut); + return mark_julia_type(box, true, bt, ctx); + } } static jl_cgval_t generic_cast( From de6ad690494f7981b43f3e7f73aeef2766b32c21 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 7 Feb 2017 23:19:26 -0500 Subject: [PATCH 0012/1534] implement a union-return-type calling convention --- src/codegen.cpp | 555 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 404 insertions(+), 151 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index f8aecd1571a64..9dd7c4f34c20a 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -312,7 +312,7 @@ int32_t jl_jlcall_api(const void *function) // constants -static Value *V_null; +static Constant *V_null; static Type *NoopType; static Value *literal_pointer_val(jl_value_t *p); extern "C" { @@ -435,7 +435,7 @@ extern "C" { // metadata tracking for a llvm Value* during codegen struct jl_cgval_t { Value *V; // may be of type T* or T, or set to NULL if ghost (or if the value has not been initialized yet, for a variable definition) - Value *TIndex; // if `V` is an unboxed (tagged) Union described by `typ`, this gives the DataType index (1-based, small int) as a T_int8 + Value *TIndex; // if `V` is an unboxed (tagged) Union described by `typ`, this gives the DataType index (1-based, small int) as an i8 jl_value_t *constant; // constant value (rooted in linfo.def.roots) Value *gcroot; // the gcroot associated with V (if it has one) jl_value_t *typ; // the original type of V, never NULL @@ -519,9 +519,9 @@ struct jl_cgval_t { // per-local-variable information struct jl_varinfo_t { - Value *boxroot; // an address, if the var might be in a jl_value_t** stack slot (marked tbaa_const, if appropriate) + Instruction *boxroot; // an address, if the var might be in a jl_value_t** stack slot (marked tbaa_const, if appropriate) jl_cgval_t value; // a stack slot or constant value - Value *pTIndex; // where the current value is stored + Value *pTIndex; // i8* stack slot for the value.TIndex tag describing `value.V` #if JL_LLVM_VERSION >= 30700 DILocalVariable *dinfo; #else @@ -564,6 +564,22 @@ typedef struct { jl_value_t *ty; } jl_arrayvar_t; +struct jl_returninfo_t { + Function *decl; + enum CallingConv { + Boxed = 0, + Register, + SRet, + Union, + Ghosts + } cc; + size_t union_bytes; + size_t union_align; + size_t union_minalign; +}; + +static jl_returninfo_t get_specsig_function(Module *M, const std::string &name, jl_value_t *sig, jl_value_t *jlrettype); + // information about the context of a piece of code: its enclosing // function and module, and visible local variables and labels. class jl_codectx_t { @@ -589,7 +605,7 @@ class jl_codectx_t { std::string funcName; int vaSlot; // name of vararg argument bool vaStack; // varargs stack-allocated - bool sret; + bool has_sret; int nReqArgs; int nargs; @@ -865,7 +881,7 @@ static inline jl_cgval_t remark_julia_type(const jl_cgval_t &v, jl_value_t *typ, if (needsroot) { froot = emit_local_root(ctx); if (v.V) { // oldbox might be all ghost values - Value *oldbox = v.ispointer() ? v.V : ConstantPointerNull::get((PointerType*)T_pjlvalue); + Value *oldbox = v.ispointer() ? v.V : V_null; boxv = builder.CreateSelect(builder.CreateICmpEQ(tindex, ConstantInt::get(T_int8, 0)), emit_bitcast(oldbox, boxv->getType()), boxv); } @@ -2170,6 +2186,7 @@ static Value *emit_local_root(jl_codectx_t *ctx, jl_varinfo_t *vi) if (vi) { vi->boxroot->replaceAllUsesWith(newroot); newroot->takeName(vi->boxroot); + vi->boxroot->eraseFromParent(); vi->boxroot = newroot; } return newroot; @@ -3031,24 +3048,45 @@ static jl_cgval_t emit_call_function_object(jl_method_instance_t *li, const jl_c if (decls.specFunctionObject != NULL) { // emit specialized call site jl_value_t *jlretty = li->rettype; - bool retboxed; - (void)julia_type_to_llvm(jlretty, &retboxed); - Function *cf = cast(prepare_call((Function*)decls.specFunctionObject)); - FunctionType *cft = cf->getFunctionType(); + Function *proto = (Function*)decls.specFunctionObject; + jl_returninfo_t returninfo = get_specsig_function(jl_Module, proto->getName(), li->specTypes, jlretty); + FunctionType *cft = returninfo.decl->getFunctionType(); + assert(proto->getFunctionType() == cft); + + proto = cast(prepare_call(proto)); + if (proto != returninfo.decl) { + assert(proto->getFunctionType() == cft); + returninfo.decl->replaceAllUsesWith(proto); + returninfo.decl->eraseFromParent(); + returninfo.decl = proto; + } + size_t nfargs = cft->getNumParams(); - Value **argvals = (Value**) alloca(nfargs*sizeof(Value*)); - bool sret = cf->hasStructRetAttr(); + Value **argvals = (Value**)alloca(nfargs * sizeof(Value*)); unsigned idx = 0; - Value *result; - if (sret) { - assert(!retboxed); + AllocaInst *result; + switch (returninfo.cc) { + case jl_returninfo_t::Boxed: + case jl_returninfo_t::Register: + case jl_returninfo_t::Ghosts: + break; + case jl_returninfo_t::SRet: result = emit_static_alloca(cft->getParamType(0)->getContainedType(0), ctx); argvals[idx] = result; idx++; + break; + case jl_returninfo_t::Union: + result = emit_static_alloca(ArrayType::get(T_int8, returninfo.union_bytes), ctx); + if (returninfo.union_align > 1) + result->setAlignment(returninfo.union_align); + argvals[idx] = result; + idx++; + break; } + SmallVector gc_uses; for (size_t i = 0; i < nargs + 1; i++) { - jl_value_t *jt = jl_nth_slot_type(li->specTypes,i); + jl_value_t *jt = jl_nth_slot_type(li->specTypes, i); bool isboxed; Type *et = julia_type_to_llvm(jt, &isboxed); if (type_is_ghost(et)) { @@ -3083,16 +3121,42 @@ static jl_cgval_t emit_call_function_object(jl_method_instance_t *li, const jl_c } assert(idx == nfargs); mark_gc_uses(gc_uses); - CallInst *call = builder.CreateCall(prepare_call(cf), ArrayRef(&argvals[0], nfargs)); - call->setAttributes(cf->getAttributes()); + CallInst *call = builder.CreateCall(returninfo.decl, ArrayRef(&argvals[0], nfargs)); + call->setAttributes(returninfo.decl->getAttributes()); mark_gc_uses(gc_uses); - if (sret) - return mark_julia_slot(result, jlretty, NULL, tbaa_stack); - // see if codegen has a better type for the call than inference had at the time - if (!retboxed && jlretty != inferred_retty) { - inferred_retty = jlretty; + + jl_cgval_t retval; + switch (returninfo.cc) { + case jl_returninfo_t::Boxed: + retval = mark_julia_type(call, true, inferred_retty, ctx); + break; + case jl_returninfo_t::Register: + retval = mark_julia_type(call, false, jlretty, ctx); + break; + case jl_returninfo_t::SRet: + retval = mark_julia_slot(result, jlretty, NULL, tbaa_stack); + break; + case jl_returninfo_t::Union: + retval = mark_julia_slot(builder.CreateExtractValue(call, 0), + jlretty, + builder.CreateExtractValue(call, 1), + tbaa_stack); + // root this, if the return value was a box + retval.gcroot = emit_local_root(ctx); + builder.CreateStore( + builder.CreateSelect(builder.CreateICmpEQ(retval.TIndex, ConstantInt::get(T_int8, 0)), + retval.V, + V_null), + retval.gcroot); + break; + case jl_returninfo_t::Ghosts: + retval = mark_julia_slot(NULL, jlretty, call, tbaa_stack); + break; } - return mark_julia_type(call, retboxed, inferred_retty, ctx); + // see if inference has a different / better type for the call than the lambda + if (inferred_retty != retval.typ) + retval = remark_julia_type(retval, inferred_retty, ctx); + return retval; } Value *ret = emit_jlcall(theFptr, boxed(theF, ctx), &args[1], nargs, ctx); return mark_julia_type(ret, true, inferred_retty, ctx); @@ -3240,7 +3304,7 @@ static Value *global_binding_pointer(jl_module_t *m, jl_sym_t *s, JL_FEAT_REQUIRE(ctx, runtime); std::stringstream name; name << "delayedvar" << globalUnique++; - Constant *initnul = ConstantPointerNull::get((PointerType*)T_pjlvalue); + Constant *initnul = V_null; GlobalVariable *bindinggv = new GlobalVariable(*ctx->f->getParent(), T_pjlvalue, false, GlobalVariable::InternalLinkage, initnul, name.str()); @@ -3392,11 +3456,12 @@ static jl_cgval_t emit_local(jl_value_t *slotload, jl_codectx_t *ctx) } -Value *try_emit_union_alloca(jl_uniontype_t *ut, bool &allunbox, size_t &min_align, jl_codectx_t *ctx) +static void union_alloca_type(jl_uniontype_t *ut, + bool &allunbox, size_t &nbytes, size_t &align, size_t &min_align) { - allunbox = true; + nbytes = 0; + align = 0; min_align = MAX_ALIGN; - size_t nb = 0, align = 0; // compute the size of the union alloca that could hold this type unsigned counter = 0; allunbox = for_each_uniontype_small( @@ -3404,8 +3469,8 @@ Value *try_emit_union_alloca(jl_uniontype_t *ut, bool &allunbox, size_t &min_ali if (!jl_is_datatype_singleton(jt)) { size_t nb1 = jl_datatype_size(jt); size_t align1 = jt->layout->alignment; - if (nb1 > nb) - nb = nb1; + if (nb1 > nbytes) + nbytes = nb1; if (align1 > align) align = align1; if (align1 < min_align) @@ -3414,9 +3479,15 @@ Value *try_emit_union_alloca(jl_uniontype_t *ut, bool &allunbox, size_t &min_ali }, (jl_value_t*)ut, counter); - if (nb > 0) { +} + +static Value *try_emit_union_alloca(jl_uniontype_t *ut, bool &allunbox, size_t &min_align, jl_codectx_t *ctx) +{ + size_t nbytes, align; + union_alloca_type(ut, allunbox, nbytes, align, min_align); + if (nbytes > 0) { // at least some of the values can live on the stack - Type *AT = ArrayType::get(T_int8, nb); + Type *AT = ArrayType::get(T_int8, nbytes); AllocaInst *lv = emit_static_alloca(AT, ctx); if (align > 1) lv->setAlignment(align); @@ -3425,6 +3496,29 @@ Value *try_emit_union_alloca(jl_uniontype_t *ut, bool &allunbox, size_t &min_ali return NULL; } +static Value *compute_tindex_unboxed(const jl_cgval_t &val, jl_value_t *typ, jl_codectx_t *ctx) +{ + if (val.constant) + return ConstantInt::get(T_int8, get_box_tindex((jl_datatype_t*)jl_typeof(val.constant), typ)); + if (val.isboxed) + return compute_box_tindex(emit_typeof_boxed(val, ctx), typ, ctx); + assert(val.TIndex); + if (!val.V || isa(val.V)) + return val.TIndex; + Value *isboxed = builder.CreateICmpEQ(val.TIndex, ConstantInt::get(T_int8, 0)); + BasicBlock *currBB = builder.GetInsertBlock(); + BasicBlock *boxedBB = BasicBlock::Create(jl_LLVMContext, "tindex_boxed", ctx->f); + BasicBlock *postBB = BasicBlock::Create(jl_LLVMContext, "post_tindex", ctx->f); + builder.CreateCondBr(isboxed, boxedBB, postBB); + builder.SetInsertPoint(boxedBB); + Value *tindex_boxed = compute_box_tindex(emit_typeof(val.V), typ, ctx); + builder.CreateBr(postBB); + builder.SetInsertPoint(postBB); + PHINode *tindex = builder.CreatePHI(T_int8, 2); + tindex->addIncoming(val.TIndex, currBB); + tindex->addIncoming(tindex_boxed, boxedBB); + return tindex; +} static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) { @@ -3472,7 +3566,7 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) gcroot = emit_local_root(ctx); else gcroot = emit_static_alloca(T_pjlvalue); - Value *box = builder.CreateSelect(isboxed, emit_bitcast(slot.V, T_pjlvalue), ConstantPointerNull::get((PointerType*)T_pjlvalue)); + Value *box = builder.CreateSelect(isboxed, emit_bitcast(slot.V, T_pjlvalue), V_null); builder.CreateStore(box, gcroot); if (dest) // might be all ghost values dest = builder.CreateSelect(isboxed, box, emit_bitcast(dest, box->getType())); @@ -3564,7 +3658,7 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) if (vi.pTIndex && rval_info.TIndex) { builder.CreateStore(rval_info.TIndex, vi.pTIndex, vi.isVolatile); isboxed = builder.CreateICmpEQ(rval_info.TIndex, ConstantInt::get(T_int8, 0)); - rval = ConstantPointerNull::get((PointerType*)T_pjlvalue); + rval = V_null; if (rval_info.V) // might be all ghost values rval = builder.CreateSelect(isboxed, emit_bitcast(rval_info.V, rval->getType()), rval); assert(!vi.value.constant); @@ -3588,18 +3682,7 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) assert(vi.value.ispointer() || (vi.pTIndex && vi.value.V == NULL)); // store tindex info (if not handled above) if (vi.pTIndex && !vi.boxroot) { - Value *tindex_no_zero; - if (rval_info.constant) - tindex_no_zero = ConstantInt::get(T_int8, get_box_tindex((jl_datatype_t*)jl_typeof(rval_info.constant), vi.value.typ)); - else if (rval_info.isboxed) - tindex_no_zero = compute_box_tindex(emit_typeof_boxed(rval_info, ctx), vi.value.typ, ctx); - else if (!rval_info.V || isa(rval_info.V)) - tindex_no_zero = rval_info.TIndex; - else - tindex_no_zero = builder.CreateSelect( - builder.CreateICmpEQ(rval_info.TIndex, ConstantInt::get(T_int8, 0)), - compute_box_tindex(emit_typeof(rval_info.V), vi.value.typ, ctx), - rval_info.TIndex); + Value *tindex_no_zero = compute_tindex_unboxed(rval_info, vi.value.typ, ctx); builder.CreateStore(tindex_no_zero, vi.pTIndex, vi.isVolatile); } // store value @@ -4065,7 +4148,7 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t ctx.linfo = lam; ctx.code = NULL; ctx.world = world; - ctx.sret = false; + ctx.has_sret = false; ctx.spvals_ptr = NULL; ctx.params = &jl_default_cgparams; allocate_gc_frame(b0, &ctx); @@ -4101,6 +4184,7 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t // See whether this function is specsig or jlcall or generic (unknown) bool specsig, jlfunc_sret; + jl_returninfo_t::CallingConv cc = jl_returninfo_t::Boxed; Function *theFptr; Value *result; Value *myargs; @@ -4116,15 +4200,27 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t theFptr = NULL; } else if (lam && lam->functionObjectsDecls.specFunctionObject != NULL) { - theFptr = (Function*)lam->functionObjectsDecls.specFunctionObject; + Function *proto = (Function*)lam->functionObjectsDecls.specFunctionObject; + jl_returninfo_t returninfo = get_specsig_function(M, proto->getName(), lam->specTypes, lam->rettype); + FunctionType *cft = returninfo.decl->getFunctionType(); + assert(proto->getFunctionType() == cft); + proto = cast(prepare_call(proto)); + if (proto != returninfo.decl) { + assert(proto->getFunctionType() == cft); + returninfo.decl->replaceAllUsesWith(proto); + returninfo.decl->eraseFromParent(); + returninfo.decl = proto; + } + theFptr = returninfo.decl; specsig = true; - jlfunc_sret = theFptr->hasStructRetAttr(); - if (jlfunc_sret) { + cc = returninfo.cc; + jlfunc_sret = cc == jl_returninfo_t::SRet; + if (jlfunc_sret || cc == jl_returninfo_t::Union) { // fuse the two sret together, or emit an alloca to hold it - if (sig.sret) - result = emit_bitcast(sretPtr, theFptr->getFunctionType()->getParamType(0)); + if (sig.sret && jlfunc_sret) + result = emit_bitcast(sretPtr, cft->getParamType(0)); else - result = builder.CreateAlloca(theFptr->getFunctionType()->getParamType(0)->getContainedType(0)); + result = builder.CreateAlloca(cft->getParamType(0)->getContainedType(0)); args.push_back(result); FParamIndex++; } @@ -4254,7 +4350,6 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t } else { assert(theFptr); - bool retboxed; Value *call_v = prepare_call(theFptr); if (age_ok) { funcName << "_gfthunk"; @@ -4270,8 +4365,27 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t } CallInst *call = builder.CreateCall(call_v, ArrayRef(args)); call->setAttributes(theFptr->getAttributes()); - (void)julia_type_to_llvm(astrt, &retboxed); - retval = mark_julia_type(jlfunc_sret ? (Value*)builder.CreateLoad(result) : (Value*)call, retboxed, astrt, &ctx); + switch (cc) { + case jl_returninfo_t::Boxed: + retval = mark_julia_type(call, true, astrt, &ctx); + break; + case jl_returninfo_t::Register: + retval = mark_julia_type(call, false, astrt, &ctx); + break; + case jl_returninfo_t::SRet: + retval = mark_julia_slot(result, astrt, NULL, tbaa_stack); + break; + case jl_returninfo_t::Union: + retval = mark_julia_slot(builder.CreateExtractValue(call, 0), + astrt, + builder.CreateExtractValue(call, 1), + tbaa_stack); + // note that the value may not be rooted here (on the return path) + break; + case jl_returninfo_t::Ghosts: + retval = mark_julia_slot(NULL, astrt, call, tbaa_stack); + break; + } } } else { @@ -4334,6 +4448,7 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t } else if (sig.sret && jlfunc_sret) { // nothing to do + r = NULL; } else if (!type_is_ghost(sig.lrt)) { Type *prt = sig.prt; @@ -4343,21 +4458,23 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t Value *v = julia_to_native(sig.lrt, toboxed, declrt, NULL, retval, false, 0, &ctx, NULL); r = llvm_type_rewrite(v, prt, issigned, &ctx); - if (sig.sret) + if (sig.sret) { builder.CreateStore(r, sretPtr); + r = NULL; + } } else { assert(type_is_ghost(sig.lrt)); sig.sret = true; + r = NULL; } builder.CreateStore(last_age, ctx.world_age_field); - if (sig.sret) - builder.CreateRetVoid(); - else - builder.CreateRet(r); + builder.CreateRet(r); // also need to finish emission of our specsig -> jl_apply_generic converter thunk + // this builds a method that calls jl_apply_generic (as a closure over a singleton function pointer), + // but which has the signature of a specsig if (gf_thunk) { assert(lam && specsig); BasicBlock *b0 = BasicBlock::Create(jl_LLVMContext, "top", gf_thunk); @@ -4369,7 +4486,7 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t ctx2.linfo = NULL; ctx2.code = NULL; ctx2.world = world; - ctx2.sret = false; + ctx2.has_sret = false; ctx2.spvals_ptr = NULL; ctx2.params = &jl_default_cgparams; allocate_gc_frame(b0, &ctx2); @@ -4379,7 +4496,7 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t ConstantInt::get(T_int32, nargs + 1), "", /*InsertBefore*/ctx2.ptlsStates); - if (jlfunc_sret) + if (cc == jl_returninfo_t::SRet || cc == jl_returninfo_t::Union) ++AI; for (size_t i = 0; i < nargs + 1; i++) { jl_value_t *jt = jl_nth_slot_type(lam->specTypes, i); @@ -4417,28 +4534,45 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t #else Value *gf_ret = builder.CreateCall2(prepare_call(jlapplygeneric_func), myargs, nargs_v); #endif - bool retboxed; - (void)julia_type_to_llvm(astrt, &retboxed); - if (retboxed) { - assert(!jlfunc_sret); - builder.CreateRet(gf_ret); - } - else { - jl_cgval_t gf_retbox = mark_julia_type(gf_ret, true, jl_any_type, &ctx2); + jl_cgval_t gf_retbox = mark_julia_type(gf_ret, true, jl_any_type, &ctx, /*needsroot*/false); + if (cc != jl_returninfo_t::Boxed) { emit_typecheck(gf_retbox, astrt, "cfunction", &ctx2); + } + + switch (cc) { + case jl_returninfo_t::Boxed: + builder.CreateRet(gf_ret); + break; + case jl_returninfo_t::Register: { Type *gfrt = gf_thunk->getReturnType(); - if (jlfunc_sret) { - unsigned sret_nbytes = jl_datatype_size(astrt); - builder.CreateMemCpy(&*gf_thunk->arg_begin(), gf_ret, sret_nbytes, jl_alignment(sret_nbytes)); - builder.CreateRetVoid(); - } - else if (gfrt->isVoidTy()) { + if (gfrt->isVoidTy()) { builder.CreateRetVoid(); } else { gf_ret = emit_bitcast(gf_ret, gfrt->getPointerTo()); builder.CreateRet(builder.CreateLoad(gf_ret)); } + break; + } + case jl_returninfo_t::SRet: { + unsigned sret_nbytes = jl_datatype_size(astrt); + builder.CreateMemCpy(&*gf_thunk->arg_begin(), gf_ret, sret_nbytes, jl_alignment(sret_nbytes)); + builder.CreateRetVoid(); + break; + } + case jl_returninfo_t::Union: { + Type *retty = theFptr->getReturnType(); + Value *gf_retval = UndefValue::get(retty); + gf_retval = builder.CreateInsertValue(gf_retval, gf_ret, 0); + gf_retval = builder.CreateInsertValue(gf_retval, ConstantInt::get(T_int8, 0), 1); + builder.CreateRet(gf_retval); + break; + } + case jl_returninfo_t::Ghosts: { + Value *gf_retval = compute_tindex_unboxed(gf_retbox, astrt, &ctx); + builder.CreateRet(gf_retval); + break; + } } } @@ -4552,7 +4686,7 @@ static Function *jl_cfunction_object(jl_function_t *ff, jl_value_t *declrt, jl_t } // generate a julia-callable function that calls f (AKA lam) -static Function *gen_jlcall_wrapper(jl_method_instance_t *lam, Function *f, const std::string &funcName, bool sret, Module *M) +static Function *gen_jlcall_wrapper(jl_method_instance_t *lam, const jl_returninfo_t &f, const std::string &funcName, Module *M) { Function *w = Function::Create(jl_func_sig, GlobalVariable::ExternalLinkage, funcName, M); @@ -4575,20 +4709,34 @@ static Function *gen_jlcall_wrapper(jl_method_instance_t *lam, Function *f, cons ctx.linfo = lam; ctx.code = NULL; ctx.world = 0; - ctx.sret = false; + ctx.has_sret = false; ctx.spvals_ptr = NULL; ctx.params = &jl_default_cgparams; allocate_gc_frame(b0, &ctx); + FunctionType *ftype = f.decl->getFunctionType(); size_t nargs = lam->def->nargs; - size_t nfargs = f->getFunctionType()->getNumParams(); + size_t nfargs = ftype->getNumParams(); Value **args = (Value**) alloca(nfargs*sizeof(Value*)); unsigned idx = 0; - Value *result; - if (sret) { - result = builder.CreateAlloca(f->getFunctionType()->getParamType(0)->getContainedType(0)); + AllocaInst *result; + switch (f.cc) { + case jl_returninfo_t::Boxed: + case jl_returninfo_t::Register: + case jl_returninfo_t::Ghosts: + break; + case jl_returninfo_t::SRet: + result = builder.CreateAlloca(ftype->getParamType(0)->getContainedType(0)); args[idx] = result; idx++; + break; + case jl_returninfo_t::Union: + result = builder.CreateAlloca(ArrayType::get(T_int8, f.union_bytes)); + if (f.union_align > 1) + result->setAlignment(f.union_align); + args[idx] = result; + idx++; + break; } for (size_t i = 0; i < nargs; i++) { jl_value_t *ty = jl_nth_slot_type(lam->specTypes, i); @@ -4613,41 +4761,76 @@ static Function *gen_jlcall_wrapper(jl_method_instance_t *lam, Function *f, cons args[idx] = theArg; idx++; } - CallInst *call = builder.CreateCall(prepare_call(f), ArrayRef(&args[0], nfargs)); - call->setAttributes(f->getAttributes()); + CallInst *call = builder.CreateCall(f.decl, ArrayRef(&args[0], nfargs)); + call->setAttributes(f.decl->getAttributes()); jl_value_t *jlretty = lam->rettype; - bool retboxed; - (void)julia_type_to_llvm(jlretty, &retboxed); - if (sret) { assert(!retboxed); } - jl_cgval_t retval = sret - ? mark_julia_slot(result, jlretty, NULL, tbaa_stack) - : mark_julia_type(call, retboxed, jlretty, &ctx, /*needsroot*/false); + jl_cgval_t retval; + switch (f.cc) { + case jl_returninfo_t::Boxed: + retval = mark_julia_type(call, true, jlretty, &ctx, /*needsroot*/false); + break; + case jl_returninfo_t::Register: + retval = mark_julia_type(call, false, jlretty, &ctx, /*needsroot*/false); + break; + case jl_returninfo_t::SRet: + retval = mark_julia_slot(result, jlretty, NULL, tbaa_stack); + break; + case jl_returninfo_t::Union: + retval = mark_julia_slot(builder.CreateExtractValue(call, 0), + jlretty, + builder.CreateExtractValue(call, 1), + tbaa_stack); + break; + case jl_returninfo_t::Ghosts: + retval = mark_julia_slot(NULL, jlretty, call, tbaa_stack); + break; + } builder.CreateRet(boxed(retval, &ctx, false)); // no gcroot needed since this on the return path - assert(!ctx.roots); return w; } -static Function *get_specsig_function(Module *M, const std::string &name, jl_value_t *sig, jl_value_t *jlrettype, bool &sret) +static jl_returninfo_t get_specsig_function(Module *M, const std::string &name, jl_value_t *sig, jl_value_t *jlrettype) { + jl_returninfo_t props = {}; SmallVector fsig; Type *rt; - bool retboxed; if (jlrettype == (jl_value_t*)jl_void_type) { rt = T_void; - retboxed = false; + props.cc = jl_returninfo_t::Register; + } + else if (jl_is_uniontype(jlrettype)) { + bool allunbox; + union_alloca_type((jl_uniontype_t*)jlrettype, allunbox, props.union_bytes, props.union_align, props.union_minalign); + if (props.union_bytes) { + props.cc = jl_returninfo_t::Union; + Type *AT = ArrayType::get(T_int8, props.union_bytes); + fsig.push_back(AT->getPointerTo()); + Type *pair[] = { T_pjlvalue, T_int8 }; + rt = StructType::get(jl_LLVMContext, makeArrayRef(pair)); + } + else if (allunbox) { + props.cc = jl_returninfo_t::Ghosts; + rt = T_int8; + } + else { + rt = T_pjlvalue; + } } else { + bool retboxed; rt = julia_type_to_llvm(jlrettype, &retboxed); - } - if (!retboxed && rt != T_void && deserves_sret(jlrettype, rt)) { - sret = true; - fsig.push_back(rt->getPointerTo()); - rt = T_void; - } - else { - sret = false; + if (!retboxed) { + if (rt != T_void && deserves_sret(jlrettype, rt)) { + props.cc = jl_returninfo_t::SRet; + fsig.push_back(rt->getPointerTo()); + rt = T_void; + } + else { + props.cc = jl_returninfo_t::Register; + } + } } for (size_t i = 0; i < jl_nparams(sig); i++) { jl_value_t *jt = jl_tparam(sig, i); @@ -4660,11 +4843,17 @@ static Function *get_specsig_function(Module *M, const std::string &name, jl_val } FunctionType *ftype = FunctionType::get(rt, fsig, false); Function *f = Function::Create(ftype, GlobalVariable::ExternalLinkage, name, M); - if (sret) { + if (props.cc == jl_returninfo_t::SRet) { f->addAttribute(1, Attribute::StructRet); f->addAttribute(1, Attribute::NoAlias); + f->addAttribute(1, Attribute::NoCapture); } - return f; + if (props.cc == jl_returninfo_t::Union) { + f->addAttribute(1, Attribute::NoAlias); + f->addAttribute(1, Attribute::NoCapture); + } + props.decl = f; + return props; } #if JL_LLVM_VERSION >= 30700 @@ -4874,16 +5063,18 @@ static std::unique_ptr emit_function( // allocate Function declarations and wrapper objects Module *M = new Module(ctx.name, jl_LLVMContext); jl_setup_module(M); + jl_returninfo_t returninfo = {}; Function *f = NULL; Function *fwrap = NULL; - ctx.sret = false; if (specsig) { // assumes !va and !needsparams std::stringstream specName; specName << "julia_" << unadorned_name << "_" << globalUnique; - f = get_specsig_function(M, specName.str(), lam->specTypes, jlrettype, ctx.sret); + returninfo = get_specsig_function(M, specName.str(), lam->specTypes, jlrettype); + f = returninfo.decl; + ctx.has_sret = (returninfo.cc == jl_returninfo_t::SRet || returninfo.cc == jl_returninfo_t::Union); jl_init_function(f); - fwrap = gen_jlcall_wrapper(lam, f, funcName.str(), ctx.sret, M); + fwrap = gen_jlcall_wrapper(lam, returninfo, funcName.str(), M); declarations->functionObject = function_proto(fwrap); declarations->specFunctionObject = function_proto(f); } @@ -4891,6 +5082,7 @@ static std::unique_ptr emit_function( f = Function::Create(needsparams ? jl_func_sig_sparams : jl_func_sig, GlobalVariable::ExternalLinkage, funcName.str(), M); + returninfo.decl = f; jl_init_function(f); declarations->functionObject = function_proto(f); declarations->specFunctionObject = NULL; @@ -5004,7 +5196,7 @@ static std::unique_ptr emit_function( varinfo.dinfo = dbuilder.createParameterVariable( SP, // Scope (current function will be fill in later) jl_symbol_name(argname), // Variable name - ctx.sret + i + 1, // Argument number (1-based) + ctx.has_sret + i + 1, // Argument number (1-based) topfile, // File toplineno == -1 ? 0 : toplineno, // Line // Variable type @@ -5014,38 +5206,38 @@ static std::unique_ptr emit_function( #else varinfo.dinfo = dbuilder.createLocalVariable( llvm::dwarf::DW_TAG_arg_variable, // Tag - SP, // Scope (current function will be fill in later) - jl_symbol_name(argname), // Variable name - topfile, // File + SP, // Scope (current function will be fill in later) + jl_symbol_name(argname), // Variable name + topfile, // File toplineno == -1 ? 0 : toplineno, // Line (for now, use lineno of the function) julia_type_to_di(varinfo.value.typ, &dbuilder, false), // Variable type - AlwaysPreserve, // May be deleted if optimized out - 0, // Flags (TODO: Do we need any) - ctx.sret + i + 1); // Argument number (1-based) + AlwaysPreserve, // May be deleted if optimized out + 0, // Flags (TODO: Do we need any) + ctx.has_sret + i + 1); // Argument number (1-based) #endif } if (va && ctx.vaSlot != -1) { #if JL_LLVM_VERSION >= 30800 ctx.slots[ctx.vaSlot].dinfo = dbuilder.createParameterVariable( - SP, // Scope (current function will be fill in later) + SP, // Scope (current function will be fill in later) std::string(jl_symbol_name(slot_symbol(ctx.vaSlot, &ctx))) + "...", // Variable name - ctx.sret + nreq + 1, // Argument number (1-based) - topfile, // File - toplineno == -1 ? 0 : toplineno, // Line (for now, use lineno of the function) + ctx.has_sret + nreq + 1, // Argument number (1-based) + topfile, // File + toplineno == -1 ? 0 : toplineno, // Line (for now, use lineno of the function) julia_type_to_di(ctx.slots[ctx.vaSlot].value.typ, &dbuilder, false), - AlwaysPreserve, // May be deleted if optimized out - DIFlagZero); // Flags (TODO: Do we need any) + AlwaysPreserve, // May be deleted if optimized out + DIFlagZero); // Flags (TODO: Do we need any) #else ctx.slots[ctx.vaSlot].dinfo = dbuilder.createLocalVariable( llvm::dwarf::DW_TAG_arg_variable, // Tag SP, // Scope (current function will be fill in later) std::string(jl_symbol_name(slot_symbol(ctx.vaSlot, &ctx))) + "...", // Variable name topfile, // File - toplineno == -1 ? 0 : toplineno, // Line (for now, use lineno of the function) + toplineno == -1 ? 0 : toplineno, // Line (for now, use lineno of the function) julia_type_to_di(ctx.slots[ctx.vaSlot].value.typ, &dbuilder, false), // Variable type - AlwaysPreserve, // May be deleted if optimized out - 0, // Flags (TODO: Do we need any) - ctx.sret + nreq + 1); // Argument number (1-based) + AlwaysPreserve, // May be deleted if optimized out + 0, // Flags (TODO: Do we need any) + ctx.has_sret + nreq + 1); // Argument number (1-based) #endif } for (i = 0; i < vinfoslen; i++) { @@ -5217,7 +5409,7 @@ static std::unique_ptr emit_function( // step 9. move args into local variables Function::arg_iterator AI = f->arg_begin(); - if (ctx.sret) + if (ctx.has_sret) AI++; // skip sret slot for (i = 0; i < nreq; i++) { jl_sym_t *s = (jl_sym_t*)jl_array_ptr_ref(src->slotnames, i); @@ -5642,39 +5834,101 @@ static std::unique_ptr emit_function( continue; } if (expr && expr->head == return_sym) { - bool retboxed = false; - Type *retty; - if (specsig) { - retty = julia_type_to_llvm(jlrettype, &retboxed); - } - else { - retty = T_pjlvalue; - retboxed = true; - } + // this is basically a copy of emit_assignment, + // but where the assignment slot is the retval jl_cgval_t retvalinfo = emit_expr(jl_exprarg(expr, 0), &ctx); + retvalinfo = remark_julia_type(retvalinfo, jlrettype, &ctx, /*needs-root*/false); + if (retvalinfo.typ == jl_bottom_type) { + builder.CreateUnreachable(); + find_next_stmt(-1); + continue; + } + + Value *isboxed_union = NULL; Value *retval; - if (retboxed) { + Value *sret = ctx.has_sret ? &*f->arg_begin() : NULL; + Type *retty = f->getReturnType(); + switch (returninfo.cc) { + case jl_returninfo_t::Boxed: retval = boxed(retvalinfo, &ctx, false); // skip the gcroot on the return path - assert(!ctx.sret); + break; + case jl_returninfo_t::Register: + if (type_is_ghost(retty)) + retval = NULL; + else + retval = emit_unbox(retty, retvalinfo, jlrettype); + break; + case jl_returninfo_t::SRet: + retval = NULL; + break; + case jl_returninfo_t::Union: { + Value *data, *tindex; + if (retvalinfo.TIndex) { + tindex = retvalinfo.TIndex; + if (!retvalinfo.V) { + // treat this as a simple Ghosts + data = V_null; + sret = NULL; + } + else { + data = emit_bitcast(sret, T_pjlvalue); + if (!isa(retvalinfo.V)) { + // also need to account for the possibility the return object is boxed + // and avoid / skip copying it to the stack + isboxed_union = builder.CreateICmpEQ(tindex, ConstantInt::get(T_int8, 0)); + data = builder.CreateSelect(isboxed_union, emit_bitcast(retvalinfo.V, T_pjlvalue), data); + } + } + } + else { + // treat this as a simple boxed returninfo + //assert(retvalinfo.isboxed); + data = boxed(retvalinfo, &ctx, false); // skip the gcroot on the return path + tindex = ConstantInt::get(T_int8, 0); + sret = NULL; + } + retval = UndefValue::get(retty); + retval = builder.CreateInsertValue(retval, data, 0); + retval = builder.CreateInsertValue(retval, tindex, 1); + break; } - else if (!type_is_ghost(retty)) { - retval = emit_unbox(retty, retvalinfo, jlrettype, - ctx.sret ? &*ctx.f->arg_begin() : NULL); + case jl_returninfo_t::Ghosts: + retval = compute_tindex_unboxed(retvalinfo, jlrettype, &ctx); + break; } - else { // undef return type - retval = NULL; + if (sret) { + if (retvalinfo.ispointer()) { + Value *copy_bytes; + if (returninfo.cc == jl_returninfo_t::SRet) { + assert(jl_is_leaf_type(jlrettype)); + copy_bytes = ConstantInt::get(T_int32, jl_datatype_size(jlrettype)); + } + else { + copy_bytes = emit_sizeof(retvalinfo, &ctx); + if (isboxed_union) + copy_bytes = builder.CreateSelect(isboxed_union, ConstantInt::get(copy_bytes->getType(), 0), copy_bytes); + } + builder.CreateMemCpy(sret, + data_pointer(retvalinfo, &ctx, T_pint8), + copy_bytes, + returninfo.union_minalign); + } + else { + Type *store_ty = julia_type_to_llvm(retvalinfo.typ); + Type *dest_ty = store_ty->getPointerTo(); + if (dest_ty != sret->getType()) + sret = emit_bitcast(sret, dest_ty); + builder.CreateStore(emit_unbox(store_ty, retvalinfo, retvalinfo.typ), sret); + } } + if (do_malloc_log(props.in_user_code) && props.line != -1) mallocVisitLine(props.file, props.line); if (toplevel) builder.CreateStore(last_age, ctx.world_age_field); - if (type_is_ghost(retty) || ctx.sret) { - builder.CreateRetVoid(); - } - else { - assert(retval->getType() == ctx.f->getReturnType()); - builder.CreateRet(retval); - } + assert(type_is_ghost(retty) || returninfo.cc == jl_returninfo_t::SRet || + retval->getType() == ctx.f->getReturnType()); + builder.CreateRet(retval); find_next_stmt(-1); continue; } @@ -5854,8 +6108,7 @@ extern "C" void jl_fptr_to_llvm(jl_fptr_t fptr, jl_method_instance_t *lam, int s #endif funcName << unadorned_name << "_" << globalUnique++; if (specsig) { // assumes !va - bool sret; - Function *f = get_specsig_function(shadow_output, funcName.str(), lam->specTypes, lam->rettype, sret); + Function *f = get_specsig_function(shadow_output, funcName.str(), lam->specTypes, lam->rettype).decl; if (lam->functionObjectsDecls.specFunctionObject == NULL) { lam->functionObjectsDecls.specFunctionObject = (void*)f; } From bbe8e4022b7ce69430c425111f7eb7318168c8f1 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 15 Feb 2017 12:37:21 -0500 Subject: [PATCH 0013/1534] distinguish between "must" and "may" when remarking julia type information expr-type and slot-type may improve type information (but try not to destroy it) while slot-assignment and return must convert the type information (even if it loses information / forces boxing) --- src/ccall.cpp | 2 +- src/codegen.cpp | 112 ++++++++++++++++++++++++++++++++---------------- 2 files changed, 76 insertions(+), 38 deletions(-) diff --git a/src/ccall.cpp b/src/ccall.cpp index 1e672d198efdf..a38ab2c112ccf 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -672,7 +672,7 @@ static void interpret_symbol_arg(native_sym_arg_t &out, jl_value_t *arg, jl_code "cglobal: first argument not a pointer or valid constant expression", ctx); } - arg1 = remark_julia_type(arg1, (jl_value_t*)jl_voidpointer_type, ctx); + arg1 = update_julia_type(arg1, (jl_value_t*)jl_voidpointer_type, ctx); jl_ptr = emit_unbox(T_size, arg1, (jl_value_t*)jl_voidpointer_type); } else { diff --git a/src/codegen.cpp b/src/codegen.cpp index 9dd7c4f34c20a..81fef48b62a5a 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -432,6 +432,12 @@ extern "C" { int globalUnique = 0; } +static bool isbits_spec(jl_value_t *jt, bool allow_singleton = true) +{ + return jl_isbits(jt) && jl_is_leaf_type(jt) && + (allow_singleton || (jl_datatype_size(jt) > 0) || (jl_datatype_nfields(jt) > 0)); +} + // metadata tracking for a llvm Value* during codegen struct jl_cgval_t { Value *V; // may be of type T* or T, or set to NULL if ghost (or if the value has not been initialized yet, for a variable definition) @@ -727,6 +733,40 @@ static inline jl_cgval_t mark_julia_type(Value *v, bool isboxed, jl_datatype_t * return mark_julia_type(v, isboxed, (jl_value_t*)typ, ctx, needsroot); } +// see if it might be profitable (and cheap) to change the type of v to typ +static inline jl_cgval_t update_julia_type(const jl_cgval_t &v, jl_value_t *typ, jl_codectx_t *ctx) +{ + if (v.typ == typ || v.typ == jl_bottom_type || jl_egal(v.typ, typ) || typ == (jl_value_t*)jl_any_type) + return v; // fast-path + if (jl_is_leaf_type(v.typ) && !jl_is_kind(v.typ)) { + if (jl_is_leaf_type(typ) && !jl_is_kind(typ) && !((jl_datatype_t*)typ)->abstract && !((jl_datatype_t*)v.typ)->abstract) { + // type mismatch: changing from one leaftype to another + CreateTrap(builder); + return jl_cgval_t(); + } + return v; // doesn't improve type info + } + if (v.TIndex) { + if (!jl_is_leaf_type(typ)) + return v; // not worth trying to improve type info + if (!isbits_spec(typ)) { + // discovered that this union-split type must actually be isboxed + if (v.V) { + return jl_cgval_t(v.V, v.gcroot, true, typ, NULL); + } + else { + // type mismatch (there wasn't any boxed values in the union) + CreateTrap(builder); + return jl_cgval_t(); + } + } + } + Type *T = julia_type_to_llvm(typ); + if (type_is_ghost(T)) + return ghostValue(typ); + return jl_cgval_t(v, typ, NULL); +} + static inline jl_cgval_t mark_julia_const(jl_value_t *jv) { jl_value_t *typ; @@ -744,12 +784,6 @@ static inline jl_cgval_t mark_julia_const(jl_value_t *jv) // --- allocating local variables --- -static bool isbits_spec(jl_value_t *jt, bool allow_singleton = true) -{ - return jl_isbits(jt) && jl_is_leaf_type(jt) && - (allow_singleton || (jl_datatype_size(jt) > 0) || (jl_datatype_nfields(jt) > 0)); -} - static jl_sym_t *slot_symbol(int s, jl_codectx_t *ctx) { return (jl_sym_t*)jl_array_ptr_ref(ctx->source->slotnames, s); @@ -826,7 +860,7 @@ static void jl_rethrow_with_add(const char *fmt, ...) } // given a value marked with type `v.typ`, compute the mapping and/or boxing to return a value of type `typ` -static inline jl_cgval_t remark_julia_type(const jl_cgval_t &v, jl_value_t *typ, jl_codectx_t *ctx, bool needsroot = true) +static jl_cgval_t convert_julia_type(const jl_cgval_t &v, jl_value_t *typ, jl_codectx_t *ctx, bool needsroot = true) { if (v.typ == typ || v.typ == jl_bottom_type || jl_egal(v.typ, typ)) return v; // fast-path @@ -834,7 +868,27 @@ static inline jl_cgval_t remark_julia_type(const jl_cgval_t &v, jl_value_t *typ, if (type_is_ghost(T)) return ghostValue(typ); Value *new_tindex = NULL; - if (!jl_is_leaf_type(typ)) { + if (jl_is_leaf_type(typ)) { + if (v.TIndex && !isbits_spec(typ)) { + // discovered that this union-split type must actually be isboxed + if (v.V) { + return jl_cgval_t(v.V, v.gcroot, true, typ, NULL); + } + else { + // type mismatch: there wasn't any boxed values in the union + CreateTrap(builder); + return jl_cgval_t(); + } + } + if (jl_is_leaf_type(v.typ) && !jl_is_kind(v.typ) && !((jl_datatype_t*)v.typ)->abstract) { + if (jl_is_leaf_type(typ) && !jl_is_kind(typ) && !((jl_datatype_t*)typ)->abstract) { + // type mismatch: changing from one leaftype to another + CreateTrap(builder); + return jl_cgval_t(); + } + } + } + else { bool makeboxed = false; if (v.TIndex) { // previous value was a split union, compute new index, or box @@ -959,19 +1013,6 @@ static inline jl_cgval_t remark_julia_type(const jl_cgval_t &v, jl_value_t *typ, return jl_cgval_t(boxv, froot, true, typ, NULL); } } - else { - if (v.TIndex && !isbits_spec(typ)) { - // discovered that this union-split type must actually be isboxed - if (v.V) { - return jl_cgval_t(v.V, v.gcroot, true, typ, NULL); - } - else { - // type mismatch (there wasn't any boxed values in the union) - CreateTrap(builder); - return jl_cgval_t(); - } - } - } return jl_cgval_t(v, typ, new_tindex); } @@ -2479,9 +2520,9 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, } // FIXME: v.typ is roughly equiv. to expr_type, but with typeof(T) == Type{T} instead of DataType in a few cases if (v1.typ == (jl_value_t*)jl_datatype_type) - v1 = remark_julia_type(v1, expr_type(args[1], ctx), ctx); // patch up typ if necessary + v1 = update_julia_type(v1, expr_type(args[1], ctx), ctx); // patch up typ if necessary if (v2.typ == (jl_value_t*)jl_datatype_type) - v2 = remark_julia_type(v2, expr_type(args[2], ctx), ctx); // patch up typ if necessary + v2 = update_julia_type(v2, expr_type(args[2], ctx), ctx); // patch up typ if necessary // emit comparison test Value *ans = emit_f_is(v1, v2, ctx); mark_gc_use(v1); @@ -2508,8 +2549,7 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, if (!jl_subtype(arg, tp0)) emit_typecheck(*ret, tp0, "typeassert", ctx); ty = expr_type(expr, ctx); rt2 = ty; - if (ret->isboxed || (ret->TIndex && jl_is_leaf_type(ty))) // see if it might be profitable (cheap) to remark the type - *ret = remark_julia_type(*ret, ty, ctx); + *ret = update_julia_type(*ret, ty, ctx); JL_GC_POP(); return true; } @@ -2791,7 +2831,7 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, *ret = emit_getfield(args[1], (jl_sym_t*)jl_fieldref(args[2],0), ctx); if (ret->typ == (jl_value_t*)jl_any_type) // improve the type, if known from the expr - *ret = remark_julia_type(*ret, expr_type(expr, ctx), ctx); + *ret = update_julia_type(*ret, expr_type(expr, ctx), ctx); JL_GC_POP(); return true; } @@ -3155,7 +3195,7 @@ static jl_cgval_t emit_call_function_object(jl_method_instance_t *li, const jl_c } // see if inference has a different / better type for the call than the lambda if (inferred_retty != retval.typ) - retval = remark_julia_type(retval, inferred_retty, ctx); + retval = update_julia_type(retval, inferred_retty, ctx); return retval; } Value *ret = emit_jlcall(theFptr, boxed(theF, ctx), &args[1], nargs, ctx); @@ -3215,7 +3255,7 @@ static jl_cgval_t emit_call(jl_expr_t *ex, jl_codectx_t *ctx) if (jl_typeis(f, jl_intrinsic_type)) { result = emit_intrinsic((intrinsic)*(uint32_t*)jl_data_ptr(f), args, nargs, ctx); if (result.typ == (jl_value_t*)jl_any_type) // the select_value intrinsic may be missing type information - result = remark_julia_type(result, expr_type(expr, ctx), ctx); + result = update_julia_type(result, expr_type(expr, ctx), ctx); JL_GC_POP(); return result; } @@ -3419,8 +3459,8 @@ static jl_cgval_t emit_local(jl_value_t *slotload, jl_codectx_t *ctx) tindex = builder.CreateLoad(vi.pTIndex, /*volatile*/true); v = mark_julia_slot(slot, vi.value.typ, tindex, tbaa_stack); } - if (vi.boxroot == NULL && typ != v.typ) - v = remark_julia_type(v, typ, ctx); + if (vi.boxroot == NULL) + v = update_julia_type(v, typ, ctx); if (vi.usedUndef) { assert(vi.defFlag); isnull = builder.CreateLoad(vi.defFlag, vi.isVolatile); @@ -3441,7 +3481,7 @@ static jl_cgval_t emit_local(jl_value_t *slotload, jl_codectx_t *ctx) v.V = builder.CreateSelect(load_box, boxed, emit_bitcast(v.V, boxed->getType())); else v.V = boxed; - v = remark_julia_type(v, typ, ctx); + v = update_julia_type(v, typ, ctx); } else { v = mark_julia_type(boxed, true, typ, ctx, @@ -3534,7 +3574,7 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) if (jl_is_array(ssavalue_types)) { jl_value_t *declType = jl_array_ptr_ref(ssavalue_types, idx); if (declType != slot.typ) { - slot = remark_julia_type(slot, declType, ctx); + slot = update_julia_type(slot, declType, ctx); } } } @@ -3636,7 +3676,7 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) // convert rval-type to lval-type jl_value_t *slot_type = vi.value.typ; - rval_info = remark_julia_type(rval_info, slot_type, ctx, /*needs-root*/false); + rval_info = convert_julia_type(rval_info, slot_type, ctx, /*needs-root*/false); if (rval_info.typ == jl_bottom_type) return; @@ -3907,9 +3947,7 @@ static jl_cgval_t emit_expr(jl_value_t *expr, jl_codectx_t *ctx) // some intrinsics (e.g. typeassert) can return a wider type // than what's actually possible jl_value_t *expr_t = expr_type((jl_value_t*)ex, ctx); - if (res.typ != expr_t && res.isboxed && !jl_is_leaf_type(res.typ)) { - res = remark_julia_type(res, expr_t, ctx); - } + res = update_julia_type(res, expr_t, ctx); if (res.typ == jl_bottom_type || expr_t == jl_bottom_type) { CreateTrap(builder); } @@ -5837,7 +5875,7 @@ static std::unique_ptr emit_function( // this is basically a copy of emit_assignment, // but where the assignment slot is the retval jl_cgval_t retvalinfo = emit_expr(jl_exprarg(expr, 0), &ctx); - retvalinfo = remark_julia_type(retvalinfo, jlrettype, &ctx, /*needs-root*/false); + retvalinfo = convert_julia_type(retvalinfo, jlrettype, &ctx, /*needs-root*/false); if (retvalinfo.typ == jl_bottom_type) { builder.CreateUnreachable(); find_next_stmt(-1); From a915e0b69a3b19aee9a3e43f6321553c61c58a3e Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 15 Feb 2017 16:42:41 -0500 Subject: [PATCH 0014/1534] change union tindex representation to have the high bit indicate boxed this allows (tindex & 0x7f) to always be exact, saving the need for any dynamic loads in many cases --- src/cgutils.cpp | 62 +++++++-------- src/codegen.cpp | 200 +++++++++++++++++++++++++++++++++--------------- 2 files changed, 166 insertions(+), 96 deletions(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 83af669d63949..a607a4f9d50a7 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -602,20 +602,6 @@ static bool for_each_uniontype_small( static Value *emit_typeof_boxed(const jl_cgval_t &p, jl_codectx_t *ctx); -static Value *compute_box_tindex(Value *datatype, jl_value_t *ut, jl_codectx_t *ctx) -{ - Value *tindex = ConstantInt::get(T_int8, 0); - unsigned counter = 0; - for_each_uniontype_small( - [&](unsigned idx, jl_datatype_t *jt) { - Value *cmp = builder.CreateICmpEQ(literal_pointer_val((jl_value_t*)jt), datatype); - tindex = builder.CreateSelect(cmp, ConstantInt::get(T_int8, idx), tindex); - }, - ut, - counter); - return tindex; -} - static unsigned get_box_tindex(jl_datatype_t *jt, jl_value_t *ut) { unsigned new_idx = 0; @@ -686,6 +672,7 @@ static Value* mask_gc_bits(Value *tag) static Value *emit_typeof(Value *tt) { + assert(tt != NULL && !isa(tt) && "expected a conditionally boxed value"); // given p, a jl_value_t*, compute its type tag tt = tbaa_decorate(tbaa_tag, builder.CreateLoad(emit_typeptr_addr(tt))); return mask_gc_bits(tt); @@ -700,13 +687,19 @@ static jl_cgval_t emit_typeof(const jl_cgval_t &p, jl_codectx_t *ctx) return mark_julia_type(emit_typeof(p.V), true, jl_datatype_type, ctx, /*needsroot*/false); } if (p.TIndex) { - Value *tindex = p.TIndex; + Value *tindex = builder.CreateAnd(p.TIndex, ConstantInt::get(T_int8, 0x7f)); Value *pdatatype; - if (p.V && !isa(p.V)) - pdatatype = emit_typeptr_addr(p.V); - else + unsigned counter; + counter = 0; + bool allunboxed = for_each_uniontype_small( + [&](unsigned idx, jl_datatype_t *jt) { }, + p.typ, + counter); + if (allunboxed) pdatatype = Constant::getNullValue(T_ppjlvalue); - unsigned counter = 0; + else + pdatatype = emit_typeptr_addr(p.V); + counter = 0; for_each_uniontype_small( [&](unsigned idx, jl_datatype_t *jt) { Value *cmp = builder.CreateICmpEQ(tindex, ConstantInt::get(T_int8, idx)); @@ -715,7 +708,7 @@ static jl_cgval_t emit_typeof(const jl_cgval_t &p, jl_codectx_t *ctx) p.typ, counter); Value *datatype; - if (p.V == NULL || isa(p.V)) { + if (allunboxed) { datatype = tbaa_decorate(tbaa_const, builder.CreateLoad(pdatatype)); } else { @@ -774,21 +767,23 @@ static Value *emit_datatype_size(Value *dt) static Value *emit_sizeof(const jl_cgval_t &p, jl_codectx_t *ctx) { if (p.TIndex) { - Value *tindex = p.TIndex; + Value *tindex = builder.CreateAnd(p.TIndex, ConstantInt::get(T_int8, 0x7f)); Value *size = ConstantInt::get(T_int32, -1); unsigned counter = 0; - for_each_uniontype_small( + bool allunboxed = for_each_uniontype_small( [&](unsigned idx, jl_datatype_t *jt) { Value *cmp = builder.CreateICmpEQ(tindex, ConstantInt::get(T_int8, idx)); size = builder.CreateSelect(cmp, ConstantInt::get(T_int32, jl_datatype_size(jt)), size); }, p.typ, counter); - if (p.V != NULL && !isa(p.V)) { + if (!allunboxed && p.ispointer() && p.V && !isa(p.V)) { BasicBlock *currBB = builder.GetInsertBlock(); BasicBlock *dynloadBB = BasicBlock::Create(jl_LLVMContext, "dyn_sizeof", ctx->f); BasicBlock *postBB = BasicBlock::Create(jl_LLVMContext, "post_sizeof", ctx->f); - Value *isboxed = builder.CreateICmpEQ(tindex, ConstantInt::get(T_int8, 0)); + Value *isboxed = builder.CreateICmpNE( + builder.CreateAnd(p.TIndex, ConstantInt::get(T_int8, 0x80)), + ConstantInt::get(T_int8, 0)); builder.CreateCondBr(isboxed, dynloadBB, postBB); builder.SetInsertPoint(dynloadBB); Value *datatype = emit_typeof(p.V); @@ -984,19 +979,14 @@ static Value *emit_isa(const jl_cgval_t &x, jl_value_t *type, const std::string if (jl_is_leaf_type(type)) { if (x.TIndex) { unsigned tindex = get_box_tindex((jl_datatype_t*)type, x.typ); - if (!x.V || isa(x.V)) { + if (tindex > 0) { // optimize more when we know that this is a split union-type where tindex = 0 is invalid - assert(tindex > 0 && "x.typ should have been a union of leaftypes at this point"); - return builder.CreateICmpEQ(x.TIndex, ConstantInt::get(T_int8, tindex)); + Value *xtindex = builder.CreateAnd(x.TIndex, ConstantInt::get(T_int8, 0x7f)); + return builder.CreateICmpEQ(xtindex, ConstantInt::get(T_int8, tindex)); } else { - // test for ((tindex > 0 && x.TIndex == tindex) || (x.TIndex == 0 && typeof(x.V) == type)) - Value *istype_union = NULL; - if (tindex > 0) - istype_union = builder.CreateICmpEQ(x.TIndex, ConstantInt::get(T_int8, tindex)); - else - istype_union = ConstantInt::get(T_int1, 0); - Value *isboxed = builder.CreateICmpEQ(x.TIndex, ConstantInt::get(T_int8, 0)); + // test for (x.TIndex == 0x80 && typeof(x.V) == type) + Value *isboxed = builder.CreateICmpEQ(x.TIndex, ConstantInt::get(T_int8, 0x80)); BasicBlock *currBB = builder.GetInsertBlock(); BasicBlock *isaBB = BasicBlock::Create(jl_LLVMContext, "isa", ctx->f); BasicBlock *postBB = BasicBlock::Create(jl_LLVMContext, "post_isa", ctx->f); @@ -1006,7 +996,7 @@ static Value *emit_isa(const jl_cgval_t &x, jl_value_t *type, const std::string builder.CreateBr(postBB); builder.SetInsertPoint(postBB); PHINode *istype = builder.CreatePHI(T_int1, 2); - istype->addIncoming(istype_union, currBB); + istype->addIncoming(ConstantInt::get(T_int1, 0), currBB); istype->addIncoming(istype_boxed, isaBB); return istype; } @@ -1906,6 +1896,8 @@ static Value *box_union(const jl_cgval_t &vinfo, jl_codectx_t *ctx, const SmallB counter); builder.SetInsertPoint(defaultBB); if (skip.size() > 0 && skip[0]) { + // skip[0] specifies where to return NULL or the original pointer + // if the value was not handled above box_merge->addIncoming(V_null, defaultBB); builder.CreateBr(postBB); } diff --git a/src/codegen.cpp b/src/codegen.cpp index 81fef48b62a5a..5ded06bd359bc 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -892,9 +892,9 @@ static jl_cgval_t convert_julia_type(const jl_cgval_t &v, jl_value_t *typ, jl_co bool makeboxed = false; if (v.TIndex) { // previous value was a split union, compute new index, or box - new_tindex = ConstantInt::get(T_int8, 0); + new_tindex = ConstantInt::get(T_int8, 0x80); SmallBitVector skip_box(1, true); - Value *tindex = v.TIndex; + Value *tindex = builder.CreateAnd(v.TIndex, ConstantInt::get(T_int8, 0x7f)); if (jl_is_uniontype(typ)) { // compute the TIndex mapping from v.typ -> typ unsigned counter = 0; @@ -904,7 +904,8 @@ static jl_cgval_t convert_julia_type(const jl_cgval_t &v, jl_value_t *typ, jl_co unsigned new_idx = get_box_tindex(jt, typ); bool t; if (new_idx) { - // found a matching element + // found a matching element, + // match it against either the unboxed index Value *cmp = builder.CreateICmpEQ(tindex, ConstantInt::get(T_int8, idx)); new_tindex = builder.CreateSelect(cmp, ConstantInt::get(T_int8, new_idx), new_tindex); t = true; @@ -925,31 +926,82 @@ static jl_cgval_t convert_julia_type(const jl_cgval_t &v, jl_value_t *typ, jl_co v.typ, counter); } + + // some of the values are still unboxed if (!isa(new_tindex)) { + Value *wasboxed = NULL; + // check if some of the old values might have been boxed + // and copy that information over into the new tindex + if (v.ispointer() && v.V && !isa(v.V)) { + wasboxed = builder.CreateAnd(v.TIndex, ConstantInt::get(T_int8, 0x80)); + new_tindex = builder.CreateOr(wasboxed, new_tindex); + wasboxed = builder.CreateICmpNE(wasboxed, ConstantInt::get(T_int8, 0)); + + // may need to handle compute_box_tindex for some of the values + BasicBlock *currBB = builder.GetInsertBlock(); + Value *union_box_dt = NULL; + Value *union_box_tindex = ConstantInt::get(T_int8, 0x80); + unsigned counter = 0; + for_each_uniontype_small( + // for each new union-split value + [&](unsigned idx, jl_datatype_t *jt) { + unsigned old_idx = get_box_tindex(jt, v.typ); + if (old_idx == 0) { + if (!union_box_dt) { + BasicBlock *isaBB = BasicBlock::Create(jl_LLVMContext, "union_isa", ctx->f); + builder.SetInsertPoint(isaBB); + union_box_dt = emit_typeof(v.V); + } + // didn't handle this item before, select its new union index + Value *cmp = builder.CreateICmpEQ(literal_pointer_val((jl_value_t*)jt), union_box_dt); + union_box_tindex = builder.CreateSelect(cmp, ConstantInt::get(T_int8, 0x80 | idx), union_box_tindex); + } + }, + typ, + counter); + if (union_box_dt) { + BasicBlock *isaBB = builder.GetInsertBlock(); + BasicBlock *postBB = BasicBlock::Create(jl_LLVMContext, "post_union_isa", ctx->f); + builder.CreateBr(postBB); + builder.SetInsertPoint(currBB); + Value *wasunknown = builder.CreateICmpEQ(v.TIndex, ConstantInt::get(T_int8, 0x80)); + builder.CreateCondBr(wasunknown, isaBB, postBB); + builder.SetInsertPoint(postBB); + PHINode *tindex_phi = builder.CreatePHI(T_int8, 2); + tindex_phi->addIncoming(new_tindex, currBB); + tindex_phi->addIncoming(union_box_tindex, isaBB); + new_tindex = tindex_phi; + } + + } + if (!skip_box.all()) { // some values weren't unboxed in the new union - // box them now (tindex above already selected 0 = box for them) + // box them now (tindex above already selected 0x80 = box for them) // root the result, and return a new mark_julia_slot over the result Value *boxv = box_union(v, ctx, skip_box); Value *froot = NULL; + // XXX: need to clone the value from `v.gcroot` if this isn't a new box if (needsroot) { + // build a new gc-root, as needed froot = emit_local_root(ctx); - if (v.V) { // oldbox might be all ghost values - Value *oldbox = v.ispointer() ? v.V : V_null; - boxv = builder.CreateSelect(builder.CreateICmpEQ(tindex, ConstantInt::get(T_int8, 0)), - emit_bitcast(oldbox, boxv->getType()), boxv); + Value *newroot = boxv; + if (wasboxed) { // oldbox might be all ghost values (which don't need roots) + // store either the old box or the new box into the gc-root (skip_box ensures these are mutually-exclusive) + Value *oldroot = v.V; + newroot = builder.CreateSelect(wasboxed, emit_bitcast(oldroot, boxv->getType()), newroot); } - builder.CreateStore(boxv, froot); + builder.CreateStore(newroot, froot); } - Value *isnewbox = builder.CreateIsNotNull(boxv); - Value *slotv; - MDNode *tbaa; - bool isimmutable; if (v.V == NULL) { // v.V might be NULL if it was all ghost objects before return jl_cgval_t(boxv, froot, false, typ, new_tindex); } else { + Value *isboxv = builder.CreateIsNotNull(boxv); + Value *slotv; + MDNode *tbaa; + bool isimmutable; if (v.ispointer()) { slotv = v.V; tbaa = v.tbaa; @@ -961,7 +1013,7 @@ static jl_cgval_t convert_julia_type(const jl_cgval_t &v, jl_value_t *typ, jl_co tbaa = tbaa_stack; isimmutable = true; } - slotv = builder.CreateSelect(isnewbox, boxv, emit_bitcast(slotv, boxv->getType())); + slotv = builder.CreateSelect(isboxv, boxv, emit_bitcast(slotv, boxv->getType())); jl_cgval_t newv = jl_cgval_t(slotv, froot, false, typ, new_tindex); newv.tbaa = tbaa; newv.isimmutable = isimmutable; @@ -3181,12 +3233,15 @@ static jl_cgval_t emit_call_function_object(jl_method_instance_t *li, const jl_c jlretty, builder.CreateExtractValue(call, 1), tbaa_stack); - // root this, if the return value was a box + // root this, if the return value was a box (tindex & 0x80) != 0 retval.gcroot = emit_local_root(ctx); builder.CreateStore( - builder.CreateSelect(builder.CreateICmpEQ(retval.TIndex, ConstantInt::get(T_int8, 0)), - retval.V, - V_null), + builder.CreateSelect( + builder.CreateICmpEQ( + builder.CreateAnd(retval.TIndex, ConstantInt::get(T_int8, 0x80)), + ConstantInt::get(T_int8, 0)), + V_null, + retval.V), retval.gcroot); break; case jl_returninfo_t::Ghosts: @@ -3473,12 +3528,14 @@ static jl_cgval_t emit_local(jl_value_t *slotload, jl_codectx_t *ctx) box_isnull = builder.CreateICmpNE(boxed, V_null); if (vi.pTIndex) { // value is either boxed in the stack slot, or unboxed in value - // as indicated by comparing pTIndex to 0 - Value *load_box = builder.CreateICmpEQ(v.TIndex, ConstantInt::get(T_int8, 0)); + // as indicated by testing (pTIndex & 0x80) + Value *load_unbox = builder.CreateICmpEQ( + builder.CreateAnd(v.TIndex, ConstantInt::get(T_int8, 0x80)), + ConstantInt::get(T_int8, 0)); if (vi.usedUndef) - isnull = builder.CreateSelect(load_box, box_isnull, isnull); + isnull = builder.CreateSelect(load_unbox, isnull, box_isnull); if (v.V) // v.V will be null if it is a union of all ghost values - v.V = builder.CreateSelect(load_box, boxed, emit_bitcast(v.V, boxed->getType())); + v.V = builder.CreateSelect(load_unbox, emit_bitcast(v.V, boxed->getType()), boxed); else v.V = boxed; v = update_julia_type(v, typ, ctx); @@ -3536,28 +3593,31 @@ static Value *try_emit_union_alloca(jl_uniontype_t *ut, bool &allunbox, size_t & return NULL; } +static Value *compute_box_tindex(Value *datatype, jl_value_t *supertype, jl_value_t *ut, jl_codectx_t *ctx) +{ + Value *tindex = ConstantInt::get(T_int8, 0); + unsigned counter = 0; + for_each_uniontype_small( + [&](unsigned idx, jl_datatype_t *jt) { + if (jl_subtype((jl_value_t*)jt, supertype)) { + Value *cmp = builder.CreateICmpEQ(literal_pointer_val((jl_value_t*)jt), datatype); + tindex = builder.CreateSelect(cmp, ConstantInt::get(T_int8, idx), tindex); + } + }, + ut, + counter); + return tindex; +} + +// get the runtime tindex value static Value *compute_tindex_unboxed(const jl_cgval_t &val, jl_value_t *typ, jl_codectx_t *ctx) { if (val.constant) return ConstantInt::get(T_int8, get_box_tindex((jl_datatype_t*)jl_typeof(val.constant), typ)); if (val.isboxed) - return compute_box_tindex(emit_typeof_boxed(val, ctx), typ, ctx); + return compute_box_tindex(emit_typeof_boxed(val, ctx), val.typ, typ, ctx); assert(val.TIndex); - if (!val.V || isa(val.V)) - return val.TIndex; - Value *isboxed = builder.CreateICmpEQ(val.TIndex, ConstantInt::get(T_int8, 0)); - BasicBlock *currBB = builder.GetInsertBlock(); - BasicBlock *boxedBB = BasicBlock::Create(jl_LLVMContext, "tindex_boxed", ctx->f); - BasicBlock *postBB = BasicBlock::Create(jl_LLVMContext, "post_tindex", ctx->f); - builder.CreateCondBr(isboxed, boxedBB, postBB); - builder.SetInsertPoint(boxedBB); - Value *tindex_boxed = compute_box_tindex(emit_typeof(val.V), typ, ctx); - builder.CreateBr(postBB); - builder.SetInsertPoint(postBB); - PHINode *tindex = builder.CreatePHI(T_int8, 2); - tindex->addIncoming(val.TIndex, currBB); - tindex->addIncoming(tindex_boxed, boxedBB); - return tindex; + return builder.CreateAnd(val.TIndex, ConstantInt::get(T_int8, 0x7f)); } static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) @@ -3589,7 +3649,9 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) dest = try_emit_union_alloca(((jl_uniontype_t*)jt), allunbox, min_align, ctx); Value *isboxed = NULL; if (slot.ispointer() && slot.V != NULL && !isa(slot.V)) { - isboxed = builder.CreateICmpEQ(slot.TIndex, ConstantInt::get(T_int8, 0)); + isboxed = builder.CreateICmpNE( + builder.CreateAnd(slot.TIndex, ConstantInt::get(T_int8, 0x80)), + ConstantInt::get(T_int8, 0)); } if (dest) { Value *copy_bytes = emit_sizeof(slot, ctx); @@ -3689,42 +3751,53 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) assign_arrayvar(*av, rval_info, ctx); } + // compute / store tindex info + if (vi.pTIndex) { + Value *tindex; + if (rval_info.TIndex) { + tindex = rval_info.TIndex; + if (!vi.boxroot) + tindex = builder.CreateAnd(tindex, ConstantInt::get(T_int8, 0x7f)); + } + else { + assert(rval_info.isboxed || rval_info.constant); + tindex = compute_tindex_unboxed(rval_info, vi.value.typ, ctx); + if (vi.boxroot) + tindex = builder.CreateOr(tindex, ConstantInt::get(T_int8, 0x80)); + } + builder.CreateStore(tindex, vi.pTIndex, vi.isVolatile); + } + + // store boxed variables Value *isboxed = NULL; if (vi.boxroot) { - // boxed variables if (isa(vi.boxroot) && needs_root) emit_local_root(ctx, &vi); // promote variable slot to a gcroot Value *rval; if (vi.pTIndex && rval_info.TIndex) { builder.CreateStore(rval_info.TIndex, vi.pTIndex, vi.isVolatile); - isboxed = builder.CreateICmpEQ(rval_info.TIndex, ConstantInt::get(T_int8, 0)); + isboxed = builder.CreateICmpNE( + builder.CreateAnd(rval_info.TIndex, ConstantInt::get(T_int8, 0x80)), + ConstantInt::get(T_int8, 0)); rval = V_null; - if (rval_info.V) // might be all ghost values + if (rval_info.ispointer() && rval_info.V != NULL && !isa(rval_info.V)) // might be all ghost values or otherwise definitely not boxed rval = builder.CreateSelect(isboxed, emit_bitcast(rval_info.V, rval->getType()), rval); assert(!vi.value.constant); - // will handle tindex later } else { assert(!vi.pTIndex || rval_info.isboxed || rval_info.constant); - if (vi.pTIndex) - builder.CreateStore(ConstantInt::get(T_int8, 0), vi.pTIndex, vi.isVolatile); rval = boxed(rval_info, ctx, false); } builder.CreateStore(rval, vi.boxroot, vi.isVolatile); } + // store unboxed variables if (!vi.boxroot || (vi.pTIndex && rval_info.TIndex)) { - // store unboxed variables if (vi.usedUndef) store_def_flag(vi, true); if (!vi.value.constant) { // check that this is not a virtual store assert(vi.value.ispointer() || (vi.pTIndex && vi.value.V == NULL)); - // store tindex info (if not handled above) - if (vi.pTIndex && !vi.boxroot) { - Value *tindex_no_zero = compute_tindex_unboxed(rval_info, vi.value.typ, ctx); - builder.CreateStore(tindex_no_zero, vi.pTIndex, vi.isVolatile); - } // store value if (vi.value.V == NULL) { // all ghost values in destination - nothing to copy or store @@ -3759,7 +3832,7 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) } else { if (rval_info.typ != vi.value.typ && !vi.pTIndex && !rval_info.TIndex) { - // cast-on-assignment is invalid. this branch should emit dead-code. + // isbits cast-on-assignment is invalid. this branch should be dead-code. CreateTrap(builder); } else { @@ -4601,8 +4674,10 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t case jl_returninfo_t::Union: { Type *retty = theFptr->getReturnType(); Value *gf_retval = UndefValue::get(retty); + Value *tindex = compute_box_tindex(gf_ret, (jl_value_t*)jl_any_type, astrt, &ctx); + tindex = builder.CreateOr(tindex, ConstantInt::get(T_int8, 0x80)); gf_retval = builder.CreateInsertValue(gf_retval, gf_ret, 0); - gf_retval = builder.CreateInsertValue(gf_retval, ConstantInt::get(T_int8, 0), 1); + gf_retval = builder.CreateInsertValue(gf_retval, tindex, 1); builder.CreateRet(gf_retval); break; } @@ -5882,7 +5957,7 @@ static std::unique_ptr emit_function( continue; } - Value *isboxed_union = NULL; + Value *isunboxed_union = NULL; Value *retval; Value *sret = ctx.has_sret ? &*f->arg_begin() : NULL; Type *retty = f->getReturnType(); @@ -5903,26 +5978,29 @@ static std::unique_ptr emit_function( Value *data, *tindex; if (retvalinfo.TIndex) { tindex = retvalinfo.TIndex; - if (!retvalinfo.V) { + if (retvalinfo.V == NULL) { // treat this as a simple Ghosts data = V_null; sret = NULL; } else { data = emit_bitcast(sret, T_pjlvalue); - if (!isa(retvalinfo.V)) { + if (retvalinfo.ispointer() && !isa(retvalinfo.V)) { // also need to account for the possibility the return object is boxed // and avoid / skip copying it to the stack - isboxed_union = builder.CreateICmpEQ(tindex, ConstantInt::get(T_int8, 0)); - data = builder.CreateSelect(isboxed_union, emit_bitcast(retvalinfo.V, T_pjlvalue), data); + isunboxed_union = builder.CreateICmpEQ( + builder.CreateAnd(tindex, ConstantInt::get(T_int8, 0x80)), + ConstantInt::get(T_int8, 0)); + data = builder.CreateSelect(isunboxed_union, data, emit_bitcast(retvalinfo.V, T_pjlvalue)); } } } else { // treat this as a simple boxed returninfo //assert(retvalinfo.isboxed); + tindex = compute_tindex_unboxed(retvalinfo, jlrettype, &ctx); + tindex = builder.CreateOr(tindex, ConstantInt::get(T_int8, 0x80)); data = boxed(retvalinfo, &ctx, false); // skip the gcroot on the return path - tindex = ConstantInt::get(T_int8, 0); sret = NULL; } retval = UndefValue::get(retty); @@ -5943,8 +6021,8 @@ static std::unique_ptr emit_function( } else { copy_bytes = emit_sizeof(retvalinfo, &ctx); - if (isboxed_union) - copy_bytes = builder.CreateSelect(isboxed_union, ConstantInt::get(copy_bytes->getType(), 0), copy_bytes); + if (isunboxed_union) + copy_bytes = builder.CreateSelect(isunboxed_union, copy_bytes, ConstantInt::get(copy_bytes->getType(), 0)); } builder.CreateMemCpy(sret, data_pointer(retvalinfo, &ctx, T_pint8), From 93fcde0dfc26d5dd9626a818a2d8c2c6173416b3 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 15 Feb 2017 23:43:42 -0500 Subject: [PATCH 0015/1534] fix over-pessimistic emit_isa for Type --- src/cgutils.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index a607a4f9d50a7..f50e50394e9c3 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -956,8 +956,7 @@ static Value *emit_isa(const jl_cgval_t &x, jl_value_t *type, const std::string return ConstantInt::get(T_int1, maybe_isa); // intersection with Type needs to be handled specially - if (jl_has_intersect_type_not_kind(x.typ) || - jl_has_intersect_type_not_kind(type)) { + if (jl_has_intersect_type_not_kind(type)) { Value *vx = boxed(x, ctx); if (msg && *msg == "typeassert") { #if JL_LLVM_VERSION >= 30700 From cad430c7843bf7137ab99bf5171c7e297c75b5aa Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 16 Feb 2017 15:59:53 -0500 Subject: [PATCH 0016/1534] ensure the value in the gcroot is transferred during union conversion convert_julia_type is only ever called with needsgcroot=false, so this is mostly dead-code right now --- src/codegen.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 5ded06bd359bc..a63f01cd01464 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -981,18 +981,25 @@ static jl_cgval_t convert_julia_type(const jl_cgval_t &v, jl_value_t *typ, jl_co // root the result, and return a new mark_julia_slot over the result Value *boxv = box_union(v, ctx, skip_box); Value *froot = NULL; - // XXX: need to clone the value from `v.gcroot` if this isn't a new box if (needsroot) { // build a new gc-root, as needed froot = emit_local_root(ctx); Value *newroot = boxv; - if (wasboxed) { // oldbox might be all ghost values (which don't need roots) + if (wasboxed || v.gcroot) { // oldbox might be all ghost values (which don't need roots) // store either the old box or the new box into the gc-root (skip_box ensures these are mutually-exclusive) - Value *oldroot = v.V; + // need to clone the value from `v.gcroot` if this isn't a new box + Value *oldroot; + if (v.gcroot) + oldroot = builder.CreateLoad(v.gcroot); + else + oldroot = v.V; newroot = builder.CreateSelect(wasboxed, emit_bitcast(oldroot, boxv->getType()), newroot); } builder.CreateStore(newroot, froot); } + else { + mark_gc_use(v); + } if (v.V == NULL) { // v.V might be NULL if it was all ghost objects before return jl_cgval_t(boxv, froot, false, typ, new_tindex); From cc43c0b1e136ea48c5db407846d7ffd92aeee83a Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 16 Feb 2017 17:20:37 -0500 Subject: [PATCH 0017/1534] ensure that constants are treated as values rather than opaque pointers --- src/codegen.cpp | 44 +++++++++++++++++++++++--------------------- src/intrinsics.cpp | 2 +- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index a63f01cd01464..51c0748587ac6 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3809,7 +3809,29 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) if (vi.value.V == NULL) { // all ghost values in destination - nothing to copy or store } - else if (rval_info.ispointer()) { + else if (rval_info.constant || !rval_info.ispointer()) { + if (rval_info.isghost) { + // all ghost values in source - nothing to copy or store + } + else { + if (rval_info.typ != vi.value.typ && !vi.pTIndex && !rval_info.TIndex) { + // isbits cast-on-assignment is invalid. this branch should be dead-code. + CreateTrap(builder); + } + else { + Value *dest = vi.value.V; + Type *store_ty = julia_type_to_llvm(rval_info.constant ? jl_typeof(rval_info.constant) : rval_info.typ); + Type *dest_ty = store_ty->getPointerTo(); + if (dest_ty != dest->getType()) + dest = emit_bitcast(dest, dest_ty); + tbaa_decorate(tbaa_stack, builder.CreateStore( + emit_unbox(store_ty, rval_info, rval_info.typ), + dest, + vi.isVolatile)); + } + } + } + else { MDNode *tbaa = rval_info.tbaa; // the memcpy intrinsic does not allow to specify different alias tags // for the load part (x.tbaa) and the store part (tbaa_stack). @@ -3834,26 +3856,6 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) vi.isVolatile, tbaa); } - else if (rval_info.V == NULL) { - // all ghost values in source - nothing to copy or store - } - else { - if (rval_info.typ != vi.value.typ && !vi.pTIndex && !rval_info.TIndex) { - // isbits cast-on-assignment is invalid. this branch should be dead-code. - CreateTrap(builder); - } - else { - Value *dest = vi.value.V; - Type *store_ty = julia_type_to_llvm(rval_info.typ); - Type *dest_ty = store_ty->getPointerTo(); - if (dest_ty != dest->getType()) - dest = emit_bitcast(dest, dest_ty); - tbaa_decorate(tbaa_stack, builder.CreateStore( - emit_unbox(store_ty, rval_info, rval_info.typ), - dest, - vi.isVolatile)); - } - } } else { assert(vi.pTIndex == NULL); diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index cc444e1cf3ea6..78e4eca282bcb 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -301,7 +301,7 @@ static Value *emit_unbox(Type *to, const jl_cgval_t &x, jl_value_t *jt, Value *d // bools may be stored internally as int8 unboxed = builder.CreateZExt(unboxed, T_int8); } - else { + else if (ty != to) { unboxed = builder.CreateBitCast(unboxed, to); } if (!dest) From 6131a0f0703e7da929373d4451c8ed56713c1a38 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 20 Feb 2017 21:41:58 -0500 Subject: [PATCH 0018/1534] better optimize code for copying a value to an unboxed union --- src/cgutils.cpp | 70 +++++++++++++++++++++++++++++++++++++++++++++++-- src/codegen.cpp | 53 +++++++++++++++---------------------- 2 files changed, 89 insertions(+), 34 deletions(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index f50e50394e9c3..bf41d5e6ed557 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -320,7 +320,7 @@ static Value *literal_pointer_val_slot(jl_value_t *p) static Value *literal_pointer_val(jl_value_t *p) { if (p == NULL) - return ConstantPointerNull::get((PointerType*)T_pjlvalue); + return V_null; if (!imaging_mode) return literal_static_pointer_val(p, T_pjlvalue); Value *pgv = literal_pointer_val_slot(p); @@ -331,7 +331,7 @@ static Value *literal_pointer_val(jl_binding_t *p) { // emit a pointer to any jl_value_t which will be valid across reloading code if (p == NULL) - return ConstantPointerNull::get((PointerType*)T_pjlvalue); + return V_null; if (!imaging_mode) return literal_static_pointer_val(p, T_pjlvalue); // bindings are prefixed with jl_bnd# @@ -764,6 +764,7 @@ static Value *emit_datatype_size(Value *dt) return size; } +/* this is valid code, it's simply unused static Value *emit_sizeof(const jl_cgval_t &p, jl_codectx_t *ctx) { if (p.TIndex) { @@ -810,6 +811,7 @@ static Value *emit_sizeof(const jl_cgval_t &p, jl_codectx_t *ctx) return dyn_size; } } +*/ static Value *emit_datatype_mutabl(Value *dt) { @@ -1956,6 +1958,70 @@ static Value *boxed(const jl_cgval_t &vinfo, jl_codectx_t *ctx, bool gcrooted) return box; } +// copy src to dest, if src is isbits. if skip is true, the value of dest is undefined +static void emit_unionmove(Value *dest, const jl_cgval_t &src, Value *skip, bool isVolatile, MDNode *tbaa, jl_codectx_t *ctx) +{ + if (jl_is_leaf_type(src.typ) || src.constant) { + jl_value_t *typ = src.constant ? jl_typeof(src.constant) : src.typ; + Type *store_ty = julia_type_to_llvm(typ); + assert(skip || jl_isbits(typ)); + if (jl_isbits(typ)) { + if (!src.ispointer() || src.constant) { + emit_unbox(store_ty, src, typ, dest, isVolatile); + } + else { + Value *src_ptr = data_pointer(src, ctx, T_pint8); + if (dest->getType() != T_pint8) + dest = emit_bitcast(dest, T_pint8); + if (skip) // copy dest -> dest to simulate an undef value / conditional copy + src_ptr = builder.CreateSelect(skip, dest, src_ptr); + unsigned nb = jl_datatype_size(typ); + unsigned alignment = 0; + builder.CreateMemCpy(dest, src_ptr, nb, alignment, tbaa); + } + } + } + else if (src.TIndex) { + Value *tindex = builder.CreateAnd(src.TIndex, ConstantInt::get(T_int8, 0x7f)); + Value *copy_bytes = ConstantInt::get(T_int32, -1); + unsigned counter = 0; + bool allunboxed = for_each_uniontype_small( + [&](unsigned idx, jl_datatype_t *jt) { + Value *cmp = builder.CreateICmpEQ(tindex, ConstantInt::get(T_int8, idx)); + copy_bytes = builder.CreateSelect(cmp, ConstantInt::get(T_int32, jl_datatype_size(jt)), copy_bytes); + }, + src.typ, + counter); + Value *src_ptr = data_pointer(src, ctx, T_pint8); + if (dest->getType() != T_pint8) + dest = emit_bitcast(dest, T_pint8); + if (skip) { + if (allunboxed) // copy dest -> dest to simulate an undef value / conditional copy + src_ptr = builder.CreateSelect(skip, dest, src_ptr); + else + copy_bytes = builder.CreateSelect(skip, ConstantInt::get(copy_bytes->getType(), 0), copy_bytes); + } +#ifndef NDEBUG + // try to catch codegen errors early, before it uses this to memcpy over the entire stack + CreateConditionalAbort(builder, builder.CreateICmpEQ(copy_bytes, ConstantInt::get(T_int32, -1))); +#endif + builder.CreateMemCpy(dest, + src_ptr, + copy_bytes, + /*TODO: min-align*/1); + } + else { + Value *datatype = emit_typeof_boxed(src, ctx); + Value *copy_bytes = emit_datatype_size(datatype); + if (skip) + copy_bytes = builder.CreateSelect(skip, ConstantInt::get(copy_bytes->getType(), 0), copy_bytes); + builder.CreateMemCpy(dest, + data_pointer(src, ctx, T_pint8), + copy_bytes, + /*TODO: min-align*/1); + } +} + static void emit_cpointercheck(const jl_cgval_t &x, const std::string &msg, jl_codectx_t *ctx) { diff --git a/src/codegen.cpp b/src/codegen.cpp index 51c0748587ac6..19db3a8a2e1dd 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3660,15 +3660,8 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) builder.CreateAnd(slot.TIndex, ConstantInt::get(T_int8, 0x80)), ConstantInt::get(T_int8, 0)); } - if (dest) { - Value *copy_bytes = emit_sizeof(slot, ctx); - if (isboxed) - copy_bytes = builder.CreateSelect(isboxed, ConstantInt::get(copy_bytes->getType(), 0), copy_bytes); - builder.CreateMemCpy(dest, - data_pointer(slot, ctx, T_pint8), - copy_bytes, - min_align); - } + if (dest) + emit_unionmove(dest, slot, isboxed, false, NULL, ctx); Value *gcroot = NULL; if (isboxed) { if (slot.gcroot) @@ -3771,6 +3764,8 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) tindex = compute_tindex_unboxed(rval_info, vi.value.typ, ctx); if (vi.boxroot) tindex = builder.CreateOr(tindex, ConstantInt::get(T_int8, 0x80)); + if (!vi.boxroot) + rval_info.TIndex = tindex; } builder.CreateStore(tindex, vi.pTIndex, vi.isVolatile); } @@ -3839,22 +3834,19 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) // x.tbaa ∪ tbaa_stack = tbaa_root if x.tbaa != tbaa_stack if (tbaa != tbaa_stack) tbaa = NULL; - Value *copy_bytes; if (vi.pTIndex == NULL) { assert(jl_is_leaf_type(vi.value.typ)); - copy_bytes = ConstantInt::get(T_int32, jl_datatype_size(vi.value.typ)); + Value *copy_bytes = ConstantInt::get(T_int32, jl_datatype_size(vi.value.typ)); + builder.CreateMemCpy(vi.value.V, + data_pointer(rval_info, ctx, T_pint8), + copy_bytes, + /*TODO: min_align*/1, + vi.isVolatile, + tbaa); } else { - copy_bytes = emit_sizeof(rval_info, ctx); - if (isboxed) - copy_bytes = builder.CreateSelect(isboxed, ConstantInt::get(copy_bytes->getType(), 0), copy_bytes); + emit_unionmove(vi.value.V, rval_info, isboxed, vi.isVolatile, tbaa, ctx); } - builder.CreateMemCpy(vi.value.V, - data_pointer(rval_info, ctx, T_pint8), - copy_bytes, - /*TODO: min_align*/1, - vi.isVolatile, - tbaa); } } else { @@ -5966,7 +5958,7 @@ static std::unique_ptr emit_function( continue; } - Value *isunboxed_union = NULL; + Value *isboxed_union = NULL; Value *retval; Value *sret = ctx.has_sret ? &*f->arg_begin() : NULL; Type *retty = f->getReturnType(); @@ -5997,10 +5989,10 @@ static std::unique_ptr emit_function( if (retvalinfo.ispointer() && !isa(retvalinfo.V)) { // also need to account for the possibility the return object is boxed // and avoid / skip copying it to the stack - isunboxed_union = builder.CreateICmpEQ( + isboxed_union = builder.CreateICmpNE( builder.CreateAnd(tindex, ConstantInt::get(T_int8, 0x80)), ConstantInt::get(T_int8, 0)); - data = builder.CreateSelect(isunboxed_union, data, emit_bitcast(retvalinfo.V, T_pjlvalue)); + data = builder.CreateSelect(isboxed_union, emit_bitcast(retvalinfo.V, T_pjlvalue), data); } } } @@ -6023,20 +6015,17 @@ static std::unique_ptr emit_function( } if (sret) { if (retvalinfo.ispointer()) { - Value *copy_bytes; if (returninfo.cc == jl_returninfo_t::SRet) { assert(jl_is_leaf_type(jlrettype)); - copy_bytes = ConstantInt::get(T_int32, jl_datatype_size(jlrettype)); + Value *copy_bytes = ConstantInt::get(T_int32, jl_datatype_size(jlrettype)); + builder.CreateMemCpy(sret, + data_pointer(retvalinfo, &ctx, T_pint8), + copy_bytes, + returninfo.union_minalign); } else { - copy_bytes = emit_sizeof(retvalinfo, &ctx); - if (isunboxed_union) - copy_bytes = builder.CreateSelect(isunboxed_union, copy_bytes, ConstantInt::get(copy_bytes->getType(), 0)); + emit_unionmove(sret, retvalinfo, isboxed_union, false, NULL, &ctx); } - builder.CreateMemCpy(sret, - data_pointer(retvalinfo, &ctx, T_pint8), - copy_bytes, - returninfo.union_minalign); } else { Type *store_ty = julia_type_to_llvm(retvalinfo.typ); From 33f464ed2597193ddaa4f8c0d3b55adc993c07b4 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Tue, 21 Feb 2017 09:48:16 -0800 Subject: [PATCH 0019/1534] Tests for getindex on diff and move error throw (#20683) --- base/libgit2/diff.jl | 4 +++- test/libgit2.jl | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/base/libgit2/diff.jl b/base/libgit2/diff.jl index c3f202a90cec9..c81a51038cef2 100644 --- a/base/libgit2/diff.jl +++ b/base/libgit2/diff.jl @@ -39,9 +39,11 @@ function Base.count(diff::GitDiff) end function Base.getindex(diff::GitDiff, i::Integer) + if i < 1 || i > count(diff) + throw(BoundsError(diff, (i,))) + end delta_ptr = ccall((:git_diff_get_delta, :libgit2), Ptr{DiffDelta}, (Ptr{Void}, Csize_t), diff.ptr, i-1) - delta_ptr == C_NULL && throw(BoundsError(diff, (i,))) return unsafe_load(delta_ptr) end diff --git a/test/libgit2.jl b/test/libgit2.jl index b54a2cd0303aa..43a677fe800f4 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -516,6 +516,13 @@ mktempdir() do dir @test LibGit2.isdiff(repo, "HEAD") @test LibGit2.isdirty(repo, cached=true) @test LibGit2.isdiff(repo, "HEAD", cached=true) + tree = LibGit2.GitTree(repo, "HEAD^{tree}") + diff = LibGit2.diff_tree(repo, tree, "", cached=true) + @test count(diff) == 1 + @test_throws BoundsError diff[0] + @test_throws BoundsError diff[2] + @test diff[1].status == LibGit2.Consts.DELTA_MODIFIED + @test diff[1].nfiles == 2 LibGit2.commit(repo, "zzz") @test !LibGit2.isdirty(repo) @test !LibGit2.isdiff(repo, "HEAD") From 474d05d0bef8bd2fad984db0223162de922f0315 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Tue, 21 Feb 2017 13:13:14 -0500 Subject: [PATCH 0020/1534] Fix misc test to not hard code test module name (#20550) Use randomized test module name to prevent this from happening again. --- test/misc.jl | 16 ++++++++-------- test/testdefs.jl | 4 +++- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/test/misc.jl b/test/misc.jl index 69e634106b642..858080bf7a4c1 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -52,12 +52,12 @@ end @test all(contains.(sprint(foo), ["INFO: fooinfo", "WARNING: foowarn", "ERROR: \"fooerror\""])) -logging(DevNull, TestMain_misc.Logging, :bar; kind=:info) +logging(DevNull, Logging, :bar; kind=:info) @test all(contains.(sprint(Logging.bar), ["WARNING: barwarn", "ERROR: \"barerror\""])) @test all(contains.(sprint(Logging.pooh), ["INFO: poohinfo", "WARNING: poohwarn", "ERROR: \"pooherror\""])) @test all(contains.(sprint(foo), ["INFO: fooinfo", "WARNING: foowarn", "ERROR: \"fooerror\""])) -logging(DevNull, TestMain_misc.Logging; kind=:info) +logging(DevNull, Logging; kind=:info) @test all(contains.(sprint(Logging.bar), ["WARNING: barwarn", "ERROR: \"barerror\""])) @test all(contains.(sprint(Logging.pooh), ["WARNING: poohwarn", "ERROR: \"pooherror\""])) @test all(contains.(sprint(foo), ["INFO: fooinfo", "WARNING: foowarn", "ERROR: \"fooerror\""])) @@ -73,12 +73,12 @@ logging(kind=:info) @test all(contains.(sprint(foo), ["INFO: fooinfo", "WARNING: foowarn", "ERROR: \"fooerror\""])) -logging(DevNull, TestMain_misc.Logging, :bar; kind=:warn) +logging(DevNull, Logging, :bar; kind=:warn) @test all(contains.(sprint(Logging.bar), ["INFO: barinfo", "ERROR: \"barerror\""])) @test all(contains.(sprint(Logging.pooh), ["INFO: poohinfo", "WARNING: poohwarn", "ERROR: \"pooherror\""])) @test all(contains.(sprint(foo), ["INFO: fooinfo", "WARNING: foowarn", "ERROR: \"fooerror\""])) -logging(DevNull, TestMain_misc.Logging; kind=:warn) +logging(DevNull, Logging; kind=:warn) @test all(contains.(sprint(Logging.bar), ["INFO: barinfo", "ERROR: \"barerror\""])) @test all(contains.(sprint(Logging.pooh), ["INFO: poohinfo", "ERROR: \"pooherror\""])) @test all(contains.(sprint(foo), ["INFO: fooinfo", "WARNING: foowarn", "ERROR: \"fooerror\""])) @@ -94,12 +94,12 @@ logging(kind=:warn) @test all(contains.(sprint(foo), ["INFO: fooinfo", "WARNING: foowarn", "ERROR: \"fooerror\""])) -logging(DevNull, TestMain_misc.Logging, :bar; kind=:error) +logging(DevNull, Logging, :bar; kind=:error) @test all(contains.(sprint(Logging.bar), ["INFO: barinfo", "WARNING: barwarn"])) @test all(contains.(sprint(Logging.pooh), ["INFO: poohinfo", "WARNING: poohwarn", "ERROR: \"pooherror\""])) @test all(contains.(sprint(foo), ["INFO: fooinfo", "WARNING: foowarn", "ERROR: \"fooerror\""])) -logging(DevNull, TestMain_misc.Logging; kind=:error) +logging(DevNull, Logging; kind=:error) @test all(contains.(sprint(Logging.bar), ["INFO: barinfo", "WARNING: barwarn"])) @test all(contains.(sprint(Logging.pooh), ["INFO: poohinfo", "WARNING: poohwarn"])) @test all(contains.(sprint(foo), ["INFO: fooinfo", "WARNING: foowarn", "ERROR: \"fooerror\""])) @@ -115,12 +115,12 @@ logging(kind=:error) @test all(contains.(sprint(foo), ["INFO: fooinfo", "WARNING: foowarn", "ERROR: \"fooerror\""])) -logging(DevNull, TestMain_misc.Logging, :bar) +logging(DevNull, Logging, :bar) @test sprint(Logging.bar) == "" @test all(contains.(sprint(Logging.pooh), ["INFO: poohinfo", "WARNING: poohwarn", "ERROR: \"pooherror\""])) @test all(contains.(sprint(foo), ["INFO: fooinfo", "WARNING: foowarn", "ERROR: \"fooerror\""])) -logging(DevNull, TestMain_misc.Logging) +logging(DevNull, Logging) @test sprint(Logging.bar) == "" @test sprint(Logging.pooh) == "" @test all(contains.(sprint(foo), ["INFO: fooinfo", "WARNING: foowarn", "ERROR: \"fooerror\""])) diff --git a/test/testdefs.jl b/test/testdefs.jl index dad9cb738d99a..ba48564fb9b3d 100644 --- a/test/testdefs.jl +++ b/test/testdefs.jl @@ -5,7 +5,9 @@ function runtests(name, isolate=true) Base.Test.TESTSET_PRINT_ENABLE[] = false try if isolate - mod_name = Symbol("TestMain_", replace(name, '/', '_')) + # Simple enough to type and random enough so that no one will hard + # code it in the test + mod_name = Symbol("Test", rand(1:100), "Main_", replace(name, '/', '_')) m = @eval(Main, module $mod_name end) else m = Main From 3f7de0f9b649c1568077a7118b991309cd08b758 Mon Sep 17 00:00:00 2001 From: kshyatt Date: Mon, 20 Feb 2017 16:26:14 -0800 Subject: [PATCH 0021/1534] Add show methods for DiffDelta, DiffFile and test --- base/libgit2/consts.jl | 18 +++++++++--------- base/libgit2/types.jl | 15 +++++++++++++++ test/libgit2.jl | 13 ++++++++++++- 3 files changed, 36 insertions(+), 10 deletions(-) diff --git a/base/libgit2/consts.jl b/base/libgit2/consts.jl index 94b535b0dfce5..b37f6d283f1cc 100644 --- a/base/libgit2/consts.jl +++ b/base/libgit2/consts.jl @@ -98,15 +98,15 @@ module Consts const DIFF_FORMAT_NAME_ONLY = Cuint(4) const DIFF_FORMAT_NAME_STATUS = Cuint(5) - const DELTA_UNMODIFIED = Cint(0) - const DELTA_ADDED = Cint(1) - const DELTA_DELETED = Cint(2) - const DELTA_MODIFIED = Cint(3) - const DELTA_RENAMED = Cint(4) - const DELTA_COPIED = Cint(5) - const DELTA_IGNORED = Cint(6) - const DELTA_UNTRACKED = Cint(7) - const DELTA_TYPECHANGE = Cint(8) + @enum(DELTA_STATUS, DELTA_UNMODIFIED = Cint(0), + DELTA_ADDED = Cint(1), + DELTA_DELETED = Cint(2), + DELTA_MODIFIED = Cint(3), + DELTA_RENAMED = Cint(4), + DELTA_COPIED = Cint(5), + DELTA_IGNORED = Cint(6), + DELTA_UNTRACKED = Cint(7), + DELTA_TYPECHANGE = Cint(8)) # index const IDXENTRY_NAMEMASK = (0x0fff) diff --git a/base/libgit2/types.jl b/base/libgit2/types.jl index 10423af8e0952..8ebd5a96a15f2 100644 --- a/base/libgit2/types.jl +++ b/base/libgit2/types.jl @@ -286,6 +286,13 @@ struct DiffFile end end +function Base.show(io::IO, df::DiffFile) + println(io, "DiffFile:") + println(io, "Oid: $(df.id))") + println(io, "Path: $(df.path)") + println(io, "Size: $(df.size)") +end + """ LibGit2.DiffDelta @@ -301,6 +308,14 @@ struct DiffDelta new_file::DiffFile end +function Base.show(io::IO, dd::DiffDelta) + println(io, "DiffDelta:") + println(io, "Status: $(Consts.DELTA_STATUS(dd.status))") + println(io, "Number of files: $(dd.nfiles)") + println(io, "Old file:\n$(dd.old_file)") + println(io, "New file:\n$(dd.new_file)") +end + """ LibGit2.MergeOptions diff --git a/test/libgit2.jl b/test/libgit2.jl index 43a677fe800f4..a2a8716a5f25c 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -521,8 +521,19 @@ mktempdir() do dir @test count(diff) == 1 @test_throws BoundsError diff[0] @test_throws BoundsError diff[2] - @test diff[1].status == LibGit2.Consts.DELTA_MODIFIED + @test LibGit2.Consts.DELTA_STATUS(diff[1].status) == LibGit2.Consts.DELTA_MODIFIED @test diff[1].nfiles == 2 + diff_strs = split(sprint(show, diff[1]), '\n') + @test diff_strs[1] == "DiffDelta:" + @test diff_strs[2] == "Status: DELTA_MODIFIED" + @test diff_strs[3] == "Number of files: 2" + @test diff_strs[4] == "Old file:" + @test diff_strs[5] == "DiffFile:" + @test contains(diff_strs[6], "Oid:") + @test contains(diff_strs[7], "Path:") + @test contains(diff_strs[8], "Size:") + @test isempty(diff_strs[9]) + @test diff_strs[10] == "New file:" LibGit2.commit(repo, "zzz") @test !LibGit2.isdirty(repo) @test !LibGit2.isdiff(repo, "HEAD") From 1b30ff806abd53368a1c50d8e97689d6f37bf20d Mon Sep 17 00:00:00 2001 From: Katie Hyatt Date: Tue, 21 Feb 2017 11:02:14 -0800 Subject: [PATCH 0022/1534] Show method and test for LQ --- base/linalg/lq.jl | 7 +++++++ test/linalg/lq.jl | 3 +++ 2 files changed, 10 insertions(+) diff --git a/base/linalg/lq.jl b/base/linalg/lq.jl index eca82f2a15a7f..6ee36ffadde3f 100644 --- a/base/linalg/lq.jl +++ b/base/linalg/lq.jl @@ -79,6 +79,13 @@ end getq(A::LQ) = LQPackedQ(A.factors, A.τ) +function show(io::IO, C::LQ) + println(io, "$(typeof(C)) with factors L and Q:") + show(io, C[:L]) + println(io) + show(io, C[:Q]) +end + convert{T}(::Type{LQPackedQ{T}}, Q::LQPackedQ) = LQPackedQ(convert(AbstractMatrix{T}, Q.factors), convert(Vector{T}, Q.τ)) convert{T}(::Type{AbstractMatrix{T}}, Q::LQPackedQ) = convert(LQPackedQ{T}, Q) convert(::Type{Matrix}, A::LQPackedQ) = LAPACK.orglq!(copy(A.factors),A.τ) diff --git a/test/linalg/lq.jl b/test/linalg/lq.jl index d01d30104b05f..8329d02877cd8 100644 --- a/test/linalg/lq.jl +++ b/test/linalg/lq.jl @@ -57,6 +57,9 @@ bimg = randn(n,2)/2 @test l*q ≈ a @test full(lqa) ≈ a @test full(copy(lqa)) ≈ a + lstring = sprint(show,l) + qstring = sprint(show,q) + @test sprint(show,lqa) == "$(typeof(lqa)) with factors L and Q:\n$lstring\n$qstring" end @testset "Binary ops" begin @test a*(lqa\b) ≈ b atol=3000ε From 6e317a42157bdca8f2f821eae94972643f87c913 Mon Sep 17 00:00:00 2001 From: Katie Hyatt Date: Tue, 21 Feb 2017 11:02:26 -0800 Subject: [PATCH 0023/1534] Test of show method for Cholesky --- test/linalg/cholesky.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/linalg/cholesky.jl b/test/linalg/cholesky.jl index 795a2ad00f2b0..f0a8c7a85cb75 100644 --- a/test/linalg/cholesky.jl +++ b/test/linalg/cholesky.jl @@ -71,6 +71,8 @@ for eltya in (Float32, Float64, Complex64, Complex128, BigFloat, Int) @test inv(capds)*apds ≈ eye(n) @test abs((det(capds) - det(apd))/det(capds)) <= ε*κ*n end + ulstring = sprint(show,capds[:UL]) + @test sprint(show,capds) == "$(typeof(capds)) with factor:\n$ulstring" else capdh = cholfact(apdh) @test inv(capdh)*apdh ≈ eye(n) @@ -84,6 +86,8 @@ for eltya in (Float32, Float64, Complex64, Complex128, BigFloat, Int) capdh = cholfact!(copy(apd), :L) @test inv(capdh)*apdh ≈ eye(n) @test abs((det(capdh) - det(apd))/det(capdh)) <= ε*κ*n + ulstring = sprint(show,capdh[:UL]) + @test sprint(show,capdh) == "$(typeof(capdh)) with factor:\n$ulstring" end # test chol of 2x2 Strang matrix From 6c34f8f50bc85cc368536eb56595dc715f199744 Mon Sep 17 00:00:00 2001 From: Katie Hyatt Date: Tue, 21 Feb 2017 11:02:39 -0800 Subject: [PATCH 0024/1534] Test of show method for QR --- test/linalg/qr.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/linalg/qr.jl b/test/linalg/qr.jl index b1f48325fcb1a..e3c4becd32502 100644 --- a/test/linalg/qr.jl +++ b/test/linalg/qr.jl @@ -60,6 +60,9 @@ debug && println("QR decomposition (without pivoting)") ac = copy(a) @test qrfact!(a[:, 1:5])\b == qrfact!(view(ac, :, 1:5))\b end + rstring = sprint(show,r) + qstring = sprint(show,q) + @test sprint(show,qra) == "$(typeof(qra)) with factors Q and R:\n$qstring\n$rstring" debug && println("Thin QR decomposition (without pivoting)") qra = @inferred qrfact(a[:,1:n1], Val{false}) From e8d2d95f57704ab0b60271209d90cb9fc3886275 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 21 Feb 2017 14:11:51 -0500 Subject: [PATCH 0025/1534] tolerate non-types as Tuple parameters better part of #19998 --- src/subtype.c | 2 +- test/subtype.jl | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/subtype.c b/src/subtype.c index fc6e2467fdf24..80e75a9633dae 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -414,7 +414,7 @@ static int is_leaf_bound(jl_value_t *v) } return 1; } - return 0; + return !jl_is_type(v) && !jl_is_typevar(v); } static jl_value_t *widen_Type(jl_value_t *t) diff --git a/test/subtype.jl b/test/subtype.jl index 58a58bc322367..cf9da3cd3349a 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -938,3 +938,6 @@ ftwoparams(::TwoParams{<:Real,<:Real}) = 3 # supertype operator @test !(Int >: Integer) @test Integer >: Int + +# tolerate non-types in Tuples +@test typeintersect(Tuple{0}, Tuple{T} where T) === Tuple{0} From eac043ac4fe3d4f7097ab07b385475aacc17cb66 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 21 Feb 2017 13:22:00 -0500 Subject: [PATCH 0026/1534] add union-splitting commit comment to devdocs starting a document describing the overall code-generator structure --- doc/make.jl | 5 +- doc/src/devdocs/compiler.md | 119 ++++++++++++++++++++++++++++++++++++ doc/src/index.md | 5 +- src/codegen.cpp | 2 +- 4 files changed, 126 insertions(+), 5 deletions(-) create mode 100644 doc/src/devdocs/compiler.md diff --git a/doc/make.jl b/doc/make.jl index 1ea3d50f9f5b0..0ca31f155f940 100644 --- a/doc/make.jl +++ b/doc/make.jl @@ -87,12 +87,13 @@ const PAGES = [ "devdocs/reflection.md", "Documentation of Julia's Internals" => [ "devdocs/init.md", - "devdocs/eval.md", "devdocs/ast.md", "devdocs/types.md", "devdocs/object.md", - "devdocs/functions.md", + "devdocs/eval.md", "devdocs/callconv.md", + "devdocs/compiler.md", + "devdocs/functions.md", "devdocs/cartesian.md", "devdocs/meta.md", "devdocs/subarrays.md", diff --git a/doc/src/devdocs/compiler.md b/doc/src/devdocs/compiler.md new file mode 100644 index 0000000000000..5b4f0fd7fe3bb --- /dev/null +++ b/doc/src/devdocs/compiler.md @@ -0,0 +1,119 @@ +# High-level Overview of the Native-Code Generation Process + + + + + +## Representation of Pointers + +When emitting code to an object file, pointers will be emitted as relocations. +The deserialization code will ensure any object that pointed to one of these constants +gets recreated and contains the right runtime pointer. + +Otherwise, they will be emitted as literal constants. + +To emit one of these objects, call `literal_pointer_val`. +It'll handle tracking the Julia value and the LLVM global, +ensuring they are valid both for the current runtime and after deserialization. + +When emitted into the object file, these globals are stored as references +in a large `gvals` table. This allows the deserializer to reference them by index, +and implement a custom manual GOT-like mechanism to restore them. + +Function pointers are handled similarly. +They are stored as values in a large `fvals` table. +Like globals, this allows the deserializer to reference them by index. + +Note that extern functions are handled separately, +with names, via the usual symbol resolution mechanism in the linker. + +Note too that ccall functions are also handled separately, +via a manual GOT + PLT. + + +## Representation of Intermediate Values + +Values are passed around in a `jl_cgval_t` struct. +This represents an R-value, and includes enough information to +determine how to assign or pass it somewhere. + +They are created via one of the helper constructors, usually: +`mark_julia_type` (for immediate values) and `mark_julia_slot` (for pointers to values). + +The function `convert_julia_type` can transform between any two types. +It returns an R-value with `cgval.typ` set to `typ`. +It'll cast the object to the requested representation, +making heap boxes, allocating stack copies, and computing tagged unions as +needed to change the representation. + +By contrast `update_julia_type` will change `cgval.typ` to `typ`, +only if it can be done at zero-cost (i.e. without emitting any code). + + +## Union representation + +Inferred union types may be stack allocated via a tagged type representation. + +The primitive routines that need to be able to handle tagged unions are: +- mark-type +- load-local +- store-local +- isa +- is +- emit_typeof +- emit_sizeof +- boxed +- unbox +- specialized cc-ret + +Everything else should be possible to handle in inference by using these +primitives to implement union-splitting. + +The representation of the tagged-union is as a pair +of `< void* union, byte selector >`. +The selector is fixed-size as `byte & 0x7f`, +and will union-tag the first 126 isbits. +It records the one-based depth-first count into the type-union of the +isbits objects inside. An index of zero indicates that the `union*` is +actually a tagged heap-allocated `jl_value_t*`, +and needs to be treated as normal for a boxed object rather than as a +tagged union. + +The high bit of the selector (`byte & 0x80`) can be tested to determine if the +`void*` is actually a heap-allocated (`jl_value_t*`) box, +thus avoiding the cost of re-allocating a box, +while maintaining the ability to efficiently handle union-splitting based on the low bits. + +It is guaranteed that `byte & 0x7f` is an exact test for the type, +if the value can be represented by a tag – it will never be marked `byte = 0x80`. +It is not necessary to also test the type-tag when testing `isa`. + +The `union*` memory region may be allocated at *any* size. +The only constraint is that it is big enough to contain the data +currently specified by `selector`. +It might not be big enough to contain the union of all types that +could be stored there according to the associated Union type field. +Use appropriate care when copying. + + +## Specialized Calling Convention Signature Representation + +A `jl_returninfo_t` object describes the calling convention details of any callable. + +If any of the arguments or return type of a method can be represented unboxed, +and the method is not varargs, it'll be given an optimized calling convention +signature based on its `specTypes` and `rettype` fields. + +The general principles are that: + +- Primitive types get passed in int/float registers. +- Tuples of VecElement types get passed in vector registers. +- Structs get passed on the stack. +- Return values are handle similarly to arguments, + with a size-cutoff at which they will instead be returned via a hidden sret argument. + +The total logic for this is implemented by `get_specsig_function` and `deserves_sret`. + +Additionally, if the return type is a union, it may be returned as a pair of values (a pointer and a tag). +If the union values can be stack-allocated, then sufficient space to store them will also be passed as a hidden first argument. +It is up to the callee whether the returned pointer will point to this space, a boxed object, or even other constant memory. diff --git a/doc/src/index.md b/doc/src/index.md index a08246094d703..ff862c7d1955e 100644 --- a/doc/src/index.md +++ b/doc/src/index.md @@ -71,12 +71,13 @@ * [Reflection and introspection](@ref) * Documentation of Julia's Internals * [Initialization of the Julia runtime](@ref) - * [Eval of Julia code](@ref) * [Julia ASTs](@ref) * [More about types](@ref) * [Memory layout of Julia Objects](@ref) - * [Julia Functions](@ref) + * [Eval of Julia code](@ref) * [Calling Conventions](@ref) + * [High-level Overview of the Native-Code Generation Process](@ref) + * [Julia Functions](@ref) * [Base.Cartesian](@ref) * [Talking to the compiler (the `:meta` mechanism)](@ref) * [SubArrays](@ref) diff --git a/src/codegen.cpp b/src/codegen.cpp index 19db3a8a2e1dd..26c67da603b17 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -448,7 +448,7 @@ struct jl_cgval_t { bool isboxed; // whether this value is a jl_value_t* allocated on the heap with the right type tag bool isghost; // whether this value is "ghost" bool isimmutable; // V points to something that is definitely immutable (e.g. single-assignment, but including memory) - MDNode *tbaa; // The related tbaa node. Non-NULL iff this is not a pointer. + MDNode *tbaa; // The related tbaa node. Non-NULL iff this holds an address. bool ispointer() const { // whether this value is compatible with `data_pointer` From 35ce0fdb962c34fcb7f4086854c6742c009050c5 Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Tue, 21 Feb 2017 16:52:40 -0800 Subject: [PATCH 0027/1534] Remove duplicate ctranspose definition for real vectors (#20685) --- base/linalg/rowvector.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/base/linalg/rowvector.jl b/base/linalg/rowvector.jl index 3c4ce60137e22..ac4541ff39123 100644 --- a/base/linalg/rowvector.jl +++ b/base/linalg/rowvector.jl @@ -75,7 +75,6 @@ julia> transpose(v) """ @inline transpose(vec::AbstractVector) = RowVector(vec) @inline ctranspose(vec::AbstractVector) = RowVector(_conj(vec)) -@inline ctranspose(vec::AbstractVector{<:Real}) = RowVector(vec) @inline transpose(rowvec::RowVector) = rowvec.vec @inline transpose(rowvec::ConjRowVector) = copy(rowvec.vec) # remove the ConjArray wrapper from any raw vector From ac7459d9d763f4d04a5f4d68fbbfd7d793b75278 Mon Sep 17 00:00:00 2001 From: Katie Hyatt Date: Tue, 21 Feb 2017 16:49:21 -0800 Subject: [PATCH 0028/1534] Add a DiffStat type, methods, and tests Create a DiffStat type so that we can get more information about GitDiffs. Add a show method for this type and GitDiff. Also add methods to get the number of files changed/insertions/ deletions in the diff. --- base/libgit2/diff.jl | 33 +++++++++++++++++++++++++++++++++ base/libgit2/types.jl | 35 ++++++++++++++++++----------------- test/libgit2.jl | 7 +++++++ 3 files changed, 58 insertions(+), 17 deletions(-) diff --git a/base/libgit2/diff.jl b/base/libgit2/diff.jl index c81a51038cef2..65766185b73e5 100644 --- a/base/libgit2/diff.jl +++ b/base/libgit2/diff.jl @@ -34,6 +34,26 @@ function diff_tree(repo::GitRepo, oldtree::GitTree, newtree::GitTree) return GitDiff(repo, diff_ptr_ptr[]) end +function GitDiffStats(diff::GitDiff) + diff_stat_ptr_ptr = Ref{Ptr{Void}}(C_NULL) + @check ccall((:git_diff_get_stats, :libgit2), Cint, + (Ptr{Ptr{Void}}, Ptr{Void}), + diff_stat_ptr_ptr, diff.ptr) + return GitDiffStats(diff_stat_ptr_ptr[]) +end + +function files_changed(diff_stat::GitDiffStats) + return ccall((:git_diff_stats_files_changed, :libgit2), Csize_t, (Ptr{Void},), diff_stat.ptr) +end + +function insertions(diff_stat::GitDiffStats) + return ccall((:git_diff_stats_insertions, :libgit2), Csize_t, (Ptr{Void},), diff_stat.ptr) +end + +function deletions(diff_stat::GitDiffStats) + return ccall((:git_diff_stats_deletions, :libgit2), Csize_t, (Ptr{Void},), diff_stat.ptr) +end + function Base.count(diff::GitDiff) return ccall((:git_diff_num_deltas, :libgit2), Cint, (Ptr{Void},), diff.ptr) end @@ -47,3 +67,16 @@ function Base.getindex(diff::GitDiff, i::Integer) (Ptr{Void}, Csize_t), diff.ptr, i-1) return unsafe_load(delta_ptr) end + +function Base.show(io::IO, diff_stat::GitDiffStats) + println(io, "GitDiffStats:") + println(io, "Files changed: $(files_changed(diff_stat))") + println(io, "Insertions: $(insertions(diff_stat))") + println(io, "Deletions: $(deletions(diff_stat))") +end + +function Base.show(io::IO, diff::GitDiff) + println(io, "GitDiff:") + println(io, "Number of deltas: $(count(diff))") + show(io, GitDiffStats(diff)) +end diff --git a/base/libgit2/types.jl b/base/libgit2/types.jl index 8ebd5a96a15f2..128ab836dd69d 100644 --- a/base/libgit2/types.jl +++ b/base/libgit2/types.jl @@ -471,23 +471,24 @@ Base.isempty(obj::AbstractGitObject) = (obj.ptr == C_NULL) abstract type GitObject <: AbstractGitObject end for (typ, reporef, sup, cname) in [ - (:GitRepo, nothing, :AbstractGitObject, :git_repository), - (:GitTreeEntry, nothing, :AbstractGitObject, :git_tree_entry), - (:GitConfig, :Nullable, :AbstractGitObject, :git_config), - (:GitIndex, :Nullable, :AbstractGitObject, :git_index), - (:GitRemote, :GitRepo, :AbstractGitObject, :git_remote), - (:GitRevWalker, :GitRepo, :AbstractGitObject, :git_revwalk), - (:GitReference, :GitRepo, :AbstractGitObject, :git_reference), - (:GitDiff, :GitRepo, :AbstractGitObject, :git_diff), - (:GitAnnotated, :GitRepo, :AbstractGitObject, :git_annotated_commit), - (:GitRebase, :GitRepo, :AbstractGitObject, :git_rebase), - (:GitStatus, :GitRepo, :AbstractGitObject, :git_status_list), - (:GitBranchIter, :GitRepo, :AbstractGitObject, :git_branch_iterator), - (:GitUnknownObject, :GitRepo, :GitObject, :git_object), - (:GitCommit, :GitRepo, :GitObject, :git_commit), - (:GitBlob, :GitRepo, :GitObject, :git_blob), - (:GitTree, :GitRepo, :GitObject, :git_tree), - (:GitTag, :GitRepo, :GitObject, :git_tag)] + (:GitRepo, nothing, :AbstractGitObject, :git_repository), + (:GitTreeEntry, nothing, :AbstractGitObject, :git_tree_entry), + (:GitDiffStats, nothing, :AbstractGitObject, :git_diff_stats), + (:GitConfig, :Nullable, :AbstractGitObject, :git_config), + (:GitIndex, :Nullable, :AbstractGitObject, :git_index), + (:GitRemote, :GitRepo, :AbstractGitObject, :git_remote), + (:GitRevWalker, :GitRepo, :AbstractGitObject, :git_revwalk), + (:GitReference, :GitRepo, :AbstractGitObject, :git_reference), + (:GitDiff, :GitRepo, :AbstractGitObject, :git_diff), + (:GitAnnotated, :GitRepo, :AbstractGitObject, :git_annotated_commit), + (:GitRebase, :GitRepo, :AbstractGitObject, :git_rebase), + (:GitStatus, :GitRepo, :AbstractGitObject, :git_status_list), + (:GitBranchIter, :GitRepo, :AbstractGitObject, :git_branch_iterator), + (:GitUnknownObject, :GitRepo, :GitObject, :git_object), + (:GitCommit, :GitRepo, :GitObject, :git_commit), + (:GitBlob, :GitRepo, :GitObject, :git_blob), + (:GitTree, :GitRepo, :GitObject, :git_tree), + (:GitTag, :GitRepo, :GitObject, :git_tag)] if reporef === nothing @eval mutable struct $typ <: $sup diff --git a/test/libgit2.jl b/test/libgit2.jl index a2a8716a5f25c..6ac52a45a04a5 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -534,6 +534,13 @@ mktempdir() do dir @test contains(diff_strs[8], "Size:") @test isempty(diff_strs[9]) @test diff_strs[10] == "New file:" + diff_strs = split(sprint(show, diff), '\n') + @test diff_strs[1] == "GitDiff:" + @test diff_strs[2] == "Number of deltas: 1" + @test diff_strs[3] == "GitDiffStats:" + @test diff_strs[4] == "Files changed: 1" + @test diff_strs[5] == "Insertions: 1" + @test diff_strs[6] == "Deletions: 0" LibGit2.commit(repo, "zzz") @test !LibGit2.isdirty(repo) @test !LibGit2.isdiff(repo, "HEAD") From 0e08411adc850b45ead07557aca978beae92dd48 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Wed, 22 Feb 2017 05:05:59 -0600 Subject: [PATCH 0029/1534] Be consistent about function names in padding example --- doc/src/manual/methods.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/manual/methods.md b/doc/src/manual/methods.md index 8e681f2551194..4317e9ace8cdf 100644 --- a/doc/src/manual/methods.md +++ b/doc/src/manual/methods.md @@ -820,7 +820,7 @@ struct NoPad end # indicate that no padding is desired, or that it's already ap myfilter(A, kernel) = myfilter(A, kernel, Replicate()) # default boundary conditions function myfilter(A, kernel, ::Replicate) - Apadded = pad(A, kernel) + Apadded = replicate_edges(A, size(kernel)) myfilter(Apadded, kernel, NoPad()) # indicate the new boundary conditions end From e399558bc4c7ca56bec20c13f945c2c3e9424e77 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Tue, 21 Feb 2017 06:02:37 -0600 Subject: [PATCH 0030/1534] Add Cartesian docstrings to stdlib and reorganize some sections --- doc/src/stdlib/arrays.md | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/doc/src/stdlib/arrays.md b/doc/src/stdlib/arrays.md index 6d596f0c0d4ad..0e097e7bb71a7 100644 --- a/doc/src/stdlib/arrays.md +++ b/doc/src/stdlib/arrays.md @@ -32,13 +32,13 @@ Base.trues Base.falses Base.fill Base.fill! -Base.reshape Base.similar(::AbstractArray) Base.similar(::Any, ::Tuple) -Base.reinterpret Base.eye Base.linspace Base.logspace +Base.Random.randsubseq +Base.Random.randsubseq! ``` ## Broadcast and vectorization @@ -56,20 +56,38 @@ Base.Broadcast.broadcast_getindex Base.Broadcast.broadcast_setindex! ``` -## Indexing, Assignment, and Concatenation +## Indexing and assignment ```@docs Base.getindex(::AbstractArray, ::Any...) +Base.setindex!(::AbstractArray, ::Any, ::Any...) +Base.isassigned +Base.Colon +Base.CartesianIndex +Base.CartesianRange +Base.to_indices +Base.checkbounds +Base.checkindex +``` + +## Views (SubArrays and other view types) + +```@docs Base.view Base.@view Base.@views -Base.to_indices -Base.Colon Base.parent Base.parentindexes Base.slicedim -Base.setindex!(::AbstractArray, ::Any, ::Any...) -Base.isassigned +Base.reinterpret +Base.reshape +Base.squeeze +Base.vec +``` + +## Concatenation and permutation + +```@docs Base.cat Base.vcat Base.hcat @@ -98,13 +116,7 @@ Base.findprev(::Any, ::Any, ::Integer) Base.permutedims Base.permutedims! Base.PermutedDimsArray -Base.squeeze -Base.vec Base.promote_shape -Base.checkbounds -Base.checkindex -Base.Random.randsubseq -Base.Random.randsubseq! ``` ## Array functions From 603726ce4d3ef104e8af0a0f581f2b1413aa665b Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Tue, 21 Feb 2017 06:03:04 -0600 Subject: [PATCH 0031/1534] Be more explicit about data sharing for `reshape` --- base/reshapedarray.jl | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/base/reshapedarray.jl b/base/reshapedarray.jl index 58abec2e26c37..17e1b8af01f91 100644 --- a/base/reshapedarray.jl +++ b/base/reshapedarray.jl @@ -37,15 +37,19 @@ end length(R::ReshapedArrayIterator) = length(R.iter) """ - reshape(A, dims...) - reshape(A, dims) - -Return an array with the same data as the given array, but with different dimensions. - -The new dimensions may be specified either as a list of arguments or as a shape -tuple. At most one dimension may be specified with a `:`, in which case its -length is computed such that its product with all the specified dimensions is -equal to the length of the original array A. + reshape(A, dims...) -> R + reshape(A, dims) -> R + +Return an array `R` with the same data as `A`, but with different +dimension sizes or number of dimensions. The two arrays share the same +underlying data, so that setting elements of `R` alters the values of +`A` and vice versa. + +The new dimensions may be specified either as a list of arguments or +as a shape tuple. At most one dimension may be specified with a `:`, +in which case its length is computed such that its product with all +the specified dimensions is equal to the length of the original array +`A`. The total number of elements must not change. ```jldoctest julia> A = collect(1:16) From 6872d395f7ec6613feb6d3b7345c34a1a20578c9 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Wed, 22 Feb 2017 08:28:43 -0600 Subject: [PATCH 0032/1534] Update URL parsing to use testsets --- test/libgit2.jl | 106 +++++++++++++++++++++++++----------------------- 1 file changed, 56 insertions(+), 50 deletions(-) diff --git a/test/libgit2.jl b/test/libgit2.jl index 43a677fe800f4..39ec9b087caaf 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -57,56 +57,62 @@ end @test sig3.email == sig.email end -#@testset "URL parsing" begin - # HTTPS URL - m = match(LibGit2.URL_REGEX, "https://user:pass@server.com:80/org/project.git") - @test m[:scheme] == "https" - @test m[:user] == "user" - @test m[:password] == "pass" - @test m[:host] == "server.com" - @test m[:port] == "80" - @test m[:path] == "/org/project.git" - - # SSH URL - m = match(LibGit2.URL_REGEX, "ssh://user:pass@server:22/project.git") - @test m[:scheme] == "ssh" - @test m[:user] == "user" - @test m[:password] == "pass" - @test m[:host] == "server" - @test m[:port] == "22" - @test m[:path] == "/project.git" - - # SSH URL using scp-like syntax - m = match(LibGit2.URL_REGEX, "user@server:project.git") - @test m[:scheme] === nothing - @test m[:user] == "user" - @test m[:password] === nothing - @test m[:host] == "server" - @test m[:port] === nothing - @test m[:path] == "project.git" - - # Realistic example from GitHub using HTTPS - m = match(LibGit2.URL_REGEX, "https://github.com/JuliaLang/Example.jl.git") - @test m[:scheme] == "https" - @test m[:user] === nothing - @test m[:password] === nothing - @test m[:host] == "github.com" - @test m[:port] === nothing - @test m[:path] == "/JuliaLang/Example.jl.git" - - # Realistic example from GitHub using SSH - m = match(LibGit2.URL_REGEX, "git@github.com:JuliaLang/Example.jl.git") - @test m[:scheme] === nothing - @test m[:user] == "git" - @test m[:password] === nothing - @test m[:host] == "github.com" - @test m[:port] === nothing - @test m[:path] == "JuliaLang/Example.jl.git" - - # Make sure usernames can contain special characters - m = match(LibGit2.URL_REGEX, "user-name@hostname.com") - @test m[:user] == "user-name" -#end +@testset "URL parsing" begin + @testset "HTTPS URL" begin + m = match(LibGit2.URL_REGEX, "https://user:pass@server.com:80/org/project.git") + @test m[:scheme] == "https" + @test m[:user] == "user" + @test m[:password] == "pass" + @test m[:host] == "server.com" + @test m[:port] == "80" + @test m[:path] == "/org/project.git" + end + + @testset "SSH URL" begin + m = match(LibGit2.URL_REGEX, "ssh://user:pass@server:22/project.git") + @test m[:scheme] == "ssh" + @test m[:user] == "user" + @test m[:password] == "pass" + @test m[:host] == "server" + @test m[:port] == "22" + @test m[:path] == "/project.git" + end + + @testset "SSH URL, scp-like syntax" begin + m = match(LibGit2.URL_REGEX, "user@server:project.git") + @test m[:scheme] === nothing + @test m[:user] == "user" + @test m[:password] === nothing + @test m[:host] == "server" + @test m[:port] === nothing + @test m[:path] == "project.git" + end + + @testset "HTTPS URL, realistic" begin + m = match(LibGit2.URL_REGEX, "https://github.com/JuliaLang/Example.jl.git") + @test m[:scheme] == "https" + @test m[:user] === nothing + @test m[:password] === nothing + @test m[:host] == "github.com" + @test m[:port] === nothing + @test m[:path] == "/JuliaLang/Example.jl.git" + end + + @testset "SSH URL, realistic" begin + m = match(LibGit2.URL_REGEX, "git@github.com:JuliaLang/Example.jl.git") + @test m[:scheme] === nothing + @test m[:user] == "git" + @test m[:password] === nothing + @test m[:host] == "github.com" + @test m[:port] === nothing + @test m[:path] == "JuliaLang/Example.jl.git" + end + + @testset "usernames with special characters" begin + m = match(LibGit2.URL_REGEX, "user-name@hostname.com") + @test m[:user] == "user-name" + end +end mktempdir() do dir # test parameters From 04a4bbb8e6adaf2bbdd08dca90bd4d70e126b354 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Tue, 21 Feb 2017 13:41:16 -0600 Subject: [PATCH 0033/1534] Improve scp-like syntax parsing Found a bug where scp-like syntax would interpret a path as a port. --- base/libgit2/utils.jl | 15 ++++++++++++--- test/libgit2.jl | 27 ++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/base/libgit2/utils.jl b/base/libgit2/utils.jl index 31ccfbf6ff93e..4dd3504e707ec 100644 --- a/base/libgit2/utils.jl +++ b/base/libgit2/utils.jl @@ -1,10 +1,19 @@ # This file is a part of Julia. License is MIT: http://julialang.org/license +# Parse "GIT URLs" syntax (URLs and a scp-like syntax). For details see: +# https://git-scm.com/docs/git-clone#_git_urls_a_id_urls_a const URL_REGEX = r""" -^(?:(?https?|git|ssh)\:\/\/)? -(?:(?.*?)(?:\:(?.*?))?@)? +^(?:(?ssh|git|https?)://)? +(?: + (?.*?) + (?:\:(?.*?))?@ +)? (?[A-Za-z0-9\-\.]+) -(?:\:(?\d+)?)? +(?() + (?:\:(?\d+))? # only parse port when not using SCP-like syntax + | + :? +) (?.*?)$ """x diff --git a/test/libgit2.jl b/test/libgit2.jl index 39ec9b087caaf..131217b13ac58 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -57,7 +57,7 @@ end @test sig3.email == sig.email end -@testset "URL parsing" begin +@testset "Git URL parsing" begin @testset "HTTPS URL" begin m = match(LibGit2.URL_REGEX, "https://user:pass@server.com:80/org/project.git") @test m[:scheme] == "https" @@ -88,6 +88,18 @@ end @test m[:path] == "project.git" end + # scp-like syntax corner case. The SCP syntax does not support port so everything after + # the colon is part of the path. + @testset "scp-like syntax, no port" begin + m = match(LibGit2.URL_REGEX, "server:1234/repo") + @test m[:scheme] === nothing + @test m[:user] == nothing + @test m[:password] == nothing + @test m[:host] == "server" + @test m[:port] === nothing + @test m[:path] == "1234/repo" + end + @testset "HTTPS URL, realistic" begin m = match(LibGit2.URL_REGEX, "https://github.com/JuliaLang/Example.jl.git") @test m[:scheme] == "https" @@ -112,6 +124,19 @@ end m = match(LibGit2.URL_REGEX, "user-name@hostname.com") @test m[:user] == "user-name" end + + @testset "HTTPS URL, no path" begin + m = match(LibGit2.URL_REGEX, "https://user:pass@server.com:80") + @test m[:path] == "" + end + + @testset "scp-like syntax, no path" begin + m = match(LibGit2.URL_REGEX, "user@server:") + @test m[:path] == "" + + m = match(LibGit2.URL_REGEX, "user@server") + @test m[:path] == "" + end end mktempdir() do dir From 02346456d3ec9f6d3c49eafe88cadad6bd4b34c1 Mon Sep 17 00:00:00 2001 From: Katie Hyatt Date: Tue, 21 Feb 2017 11:02:47 -0800 Subject: [PATCH 0034/1534] Show method and test for Schur --- base/linalg/schur.jl | 10 ++++++++++ test/linalg/schur.jl | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/base/linalg/schur.jl b/base/linalg/schur.jl index 209e348829594..d2195e8e4dde1 100644 --- a/base/linalg/schur.jl +++ b/base/linalg/schur.jl @@ -61,6 +61,16 @@ function getindex(F::Schur, d::Symbol) end end +function show(io::IO, F::Schur) + println(io, "$(typeof(F)) with factors T and Z:") + show(io, F[:T]) + println(io) + show(io, F[:Z]) + println(io) + println(io, "and values:") + show(io, F[:values]) +end + """ schur(A::StridedMatrix) -> T::Matrix, Z::Matrix, λ::Vector diff --git a/test/linalg/schur.jl b/test/linalg/schur.jl index 1eff3f4885e3a..92027cad6b430 100644 --- a/test/linalg/schur.jl +++ b/test/linalg/schur.jl @@ -38,6 +38,10 @@ aimg = randn(n,n)/2 @test AbstractArray(f) ≈ a @test_throws KeyError f[:A] + tstring = sprint(show,f[:T]) + zstring = sprint(show,f[:Z]) + vstring = sprint(show,f[:values]) + @test sprint(show,f) == "$(typeof(f)) with factors T and Z:\n$tstring\n$(zstring)\nand values:\n$vstring" @testset "Reorder Schur" begin # use asym for real schur to enforce tridiag structure # avoiding partly selection of conj. eigenvalues From 4d2efd883b4186e62a4573c81fcbfce8610a1e34 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Wed, 22 Feb 2017 10:54:07 -0800 Subject: [PATCH 0035/1534] Mention devectorization deprecations in NEWS.md. (#20724) --- NEWS.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/NEWS.md b/NEWS.md index 0ec5525ed9f2b..f577b704b1cdb 100644 --- a/NEWS.md +++ b/NEWS.md @@ -356,6 +356,9 @@ Deprecated or removed * `@test_approx_eq x y` has been deprecated in favor of `@test isapprox(x,y)` or `@test x ≈ y` ([#4615]). + * Vectorized functions have been deprecated in favor of dot syntax ([#17302],[#17265], + [#18558],[#19711],[#19712],[#19791],[#19802],[#19931],[#20543],[#20228]). + [#265]: https://github.com/JuliaLang/julia/issues/265 [#4615]: https://github.com/JuliaLang/julia/issues/4615 @@ -371,6 +374,8 @@ Deprecated or removed [#16986]: https://github.com/JuliaLang/julia/issues/16986 [#17057]: https://github.com/JuliaLang/julia/issues/17057 [#17261]: https://github.com/JuliaLang/julia/issues/17261 +[#17265]: https://github.com/JuliaLang/julia/issues/17265 +[#17302]: https://github.com/JuliaLang/julia/issues/17302 [#17599]: https://github.com/JuliaLang/julia/issues/17599 [#17623]: https://github.com/JuliaLang/julia/issues/17623 [#17758]: https://github.com/JuliaLang/julia/issues/17758 @@ -384,6 +389,7 @@ Deprecated or removed [#18453]: https://github.com/JuliaLang/julia/issues/18453 [#18457]: https://github.com/JuliaLang/julia/issues/18457 [#18473]: https://github.com/JuliaLang/julia/issues/18473 +[#18558]: https://github.com/JuliaLang/julia/issues/18558 [#18628]: https://github.com/JuliaLang/julia/issues/18628 [#18644]: https://github.com/JuliaLang/julia/issues/18644 [#18660]: https://github.com/JuliaLang/julia/issues/18660 @@ -409,19 +415,25 @@ Deprecated or removed [#19677]: https://github.com/JuliaLang/julia/issues/19677 [#19680]: https://github.com/JuliaLang/julia/issues/19680 [#19692]: https://github.com/JuliaLang/julia/issues/19692 +[#19711]: https://github.com/JuliaLang/julia/issues/19711 +[#19712]: https://github.com/JuliaLang/julia/issues/19712 [#19722]: https://github.com/JuliaLang/julia/issues/19722 [#19741]: https://github.com/JuliaLang/julia/issues/19741 [#19787]: https://github.com/JuliaLang/julia/issues/19787 +[#19791]: https://github.com/JuliaLang/julia/issues/19791 [#19800]: https://github.com/JuliaLang/julia/issues/19800 +[#19802]: https://github.com/JuliaLang/julia/issues/19802 [#19841]: https://github.com/JuliaLang/julia/issues/19841 [#19900]: https://github.com/JuliaLang/julia/issues/19900 [#19903]: https://github.com/JuliaLang/julia/issues/19903 [#19919]: https://github.com/JuliaLang/julia/issues/19919 +[#19931]: https://github.com/JuliaLang/julia/issues/19931 [#19944]: https://github.com/JuliaLang/julia/issues/19944 [#19950]: https://github.com/JuliaLang/julia/issues/19950 [#20047]: https://github.com/JuliaLang/julia/issues/20047 [#20079]: https://github.com/JuliaLang/julia/issues/20079 [#20164]: https://github.com/JuliaLang/julia/issues/20164 +[#20228]: https://github.com/JuliaLang/julia/issues/20228 [#20249]: https://github.com/JuliaLang/julia/issues/20249 [#20268]: https://github.com/JuliaLang/julia/issues/20268 [#20321]: https://github.com/JuliaLang/julia/issues/20321 @@ -431,3 +443,8 @@ Deprecated or removed [#20406]: https://github.com/JuliaLang/julia/issues/20406 [#20414]: https://github.com/JuliaLang/julia/issues/20414 [#20418]: https://github.com/JuliaLang/julia/issues/20418 +[#20427]: https://github.com/JuliaLang/julia/issues/20427 +[#20530]: https://github.com/JuliaLang/julia/issues/20530 +[#20543]: https://github.com/JuliaLang/julia/issues/20543 +[#20609]: https://github.com/JuliaLang/julia/issues/20609 +[#20648]: https://github.com/JuliaLang/julia/issues/20648 From 5a1f97198c30914249fcbcf984dd92440b267066 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 22 Feb 2017 15:00:06 -0500 Subject: [PATCH 0036/1534] update DomainError showerror handling to ignoring inlining --- base/replutil.jl | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/base/replutil.jl b/base/replutil.jl index 4f60d3140e15e..dd771314b02e1 100644 --- a/base/replutil.jl +++ b/base/replutil.jl @@ -219,28 +219,29 @@ showerror(io::IO, ex::InitError) = showerror(io, ex, []) function showerror(io::IO, ex::DomainError, bt; backtrace=true) print(io, "DomainError:") for b in bt - code = StackTraces.lookup(b)[1] - if !code.from_c - if code.func == :nan_dom_err + for code in StackTraces.lookup(b) + if code.from_c + continue + elseif code.func === :nan_dom_err continue elseif code.func in (:log, :log2, :log10, :sqrt) print(io, "\n$(code.func) will only return a complex result if called ", "with a complex argument. Try $(string(code.func))(complex(x)).") - elseif (code.func == :^ && code.file == Symbol("intfuncs.jl")) || - code.func == :power_by_squaring #3024 + elseif (code.func === :^ && + (code.file === Symbol("intfuncs.jl") || code.file === Symbol(joinpath(".", "intfuncs.jl")))) || + code.func === :power_by_squaring #3024 print(io, "\nCannot raise an integer x to a negative power -n. ", "\nMake x a float by adding a zero decimal (e.g. 2.0^-n instead ", "of 2^-n), or write 1/x^n, float(x)^-n, or (x//1)^-n.") - elseif code.func == :^ && - (code.file == Symbol("promotion.jl") || code.file == Symbol("math.jl") || - code.file == Symbol(joinpath(".","promotion.jl")) || - code.file == Symbol(joinpath(".","math.jl"))) + elseif code.func === :^ && + (code.file === Symbol("math.jl") || code.file === Symbol(joinpath(".", "math.jl"))) print(io, "\nExponentiation yielding a complex result requires a complex ", "argument.\nReplace x^y with (x+0im)^y, Complex(x)^y, or similar.") end - break + @goto showbacktrace end end + @label showbacktrace backtrace && show_backtrace(io, bt) nothing end From 1c5d7339e72b64ee9289c3645eb651cc611c18b1 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 22 Feb 2017 14:58:46 -0500 Subject: [PATCH 0037/1534] only use accurate powf function The powi intrinsic optimization over calling powf is that it is inaccurate. We don't need that. When it is equally accurate (e.g. tiny constant powers), LLVM will already recognize and optimize any call to a function named `powf`, and produce the same speedup. fix #19872 --- base/fastmath.jl | 6 +++--- base/inference.jl | 1 - base/math.jl | 23 +++++++++++------------ src/codegen.cpp | 23 ----------------------- src/intrinsics.cpp | 28 ---------------------------- src/intrinsics.h | 1 - src/julia_internal.h | 1 - src/runtime_intrinsics.c | 25 ------------------------- test/math.jl | 12 ++++++++++++ 9 files changed, 26 insertions(+), 94 deletions(-) diff --git a/base/fastmath.jl b/base/fastmath.jl index f99e44b0f50e1..33c6b9884a7ac 100644 --- a/base/fastmath.jl +++ b/base/fastmath.jl @@ -23,7 +23,7 @@ module FastMath export @fastmath -import Core.Intrinsics: powi_llvm, sqrt_llvm_fast, neg_float_fast, +import Core.Intrinsics: sqrt_llvm_fast, neg_float_fast, add_float_fast, sub_float_fast, mul_float_fast, div_float_fast, rem_float_fast, eq_float_fast, ne_float_fast, lt_float_fast, le_float_fast @@ -243,8 +243,8 @@ end # builtins -pow_fast(x::FloatTypes, y::Integer) = pow_fast(x, Int32(y)) -pow_fast(x::FloatTypes, y::Int32) = Base.powi_llvm(x, y) +pow_fast(x::Float32, y::Integer) = ccall("llvm.powi.f32", llvmcall, Float32, (Float32, Int32), x, y) +pow_fast(x::Float64, y::Integer) = ccall("llvm.powi.f64", llvmcall, Float64, (Float64, Int32), x, y) # TODO: Change sqrt_llvm intrinsic to avoid nan checking; add nan # checking to sqrt in math.jl; remove sqrt_llvm_fast intrinsic diff --git a/base/inference.jl b/base/inference.jl index eb52cbde5f204..83a4a5d7f2998 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -468,7 +468,6 @@ add_tfunc(floor_llvm, 1, 1, math_tfunc) add_tfunc(trunc_llvm, 1, 1, math_tfunc) add_tfunc(rint_llvm, 1, 1, math_tfunc) add_tfunc(sqrt_llvm, 1, 1, math_tfunc) -add_tfunc(powi_llvm, 2, 2, math_tfunc) add_tfunc(sqrt_llvm_fast, 1, 1, math_tfunc) ## same-type comparisons ## cmp_tfunc(x::ANY, y::ANY) = Bool diff --git a/base/math.jl b/base/math.jl index 9fae027458b00..c75740809c400 100644 --- a/base/math.jl +++ b/base/math.jl @@ -24,7 +24,7 @@ using Base: sign_mask, exponent_mask, exponent_one, exponent_bias, exponent_half, exponent_max, exponent_raw_max, fpinttype, significand_mask, significand_bits, exponent_bits -using Core.Intrinsics: sqrt_llvm, powi_llvm +using Core.Intrinsics: sqrt_llvm const IEEEFloat = Union{Float16,Float32,Float64} # non-type specific math functions @@ -286,6 +286,8 @@ exp10(x::Float32) = 10.0f0^x exp10(x::Integer) = exp10(float(x)) # utility for converting NaN return to DomainError +# the branch in nan_dom_err prevents its callers from inlining, so be sure to force it +# until the heuristics can be improved @inline nan_dom_err(f, x) = isnan(f) & !isnan(x) ? throw(DomainError()) : f # functions that return NaN on non-NaN argument for domain error @@ -403,9 +405,9 @@ log1p(x) for f in (:sin, :cos, :tan, :asin, :acos, :acosh, :atanh, :log, :log2, :log10, :lgamma, :log1p) @eval begin - ($f)(x::Float64) = nan_dom_err(ccall(($(string(f)),libm), Float64, (Float64,), x), x) - ($f)(x::Float32) = nan_dom_err(ccall(($(string(f,"f")),libm), Float32, (Float32,), x), x) - ($f)(x::Real) = ($f)(float(x)) + @inline ($f)(x::Float64) = nan_dom_err(ccall(($(string(f)), libm), Float64, (Float64,), x), x) + @inline ($f)(x::Float32) = nan_dom_err(ccall(($(string(f, "f")), libm), Float32, (Float32,), x), x) + @inline ($f)(x::Real) = ($f)(float(x)) end end @@ -683,14 +685,11 @@ function modf(x::Float64) f, _modf_temp[] end -^(x::Float64, y::Float64) = nan_dom_err(ccall((:pow,libm), Float64, (Float64,Float64), x, y), x+y) -^(x::Float32, y::Float32) = nan_dom_err(ccall((:powf,libm), Float32, (Float32,Float32), x, y), x+y) - -^(x::Float64, y::Integer) = x^Int32(y) -^(x::Float64, y::Int32) = powi_llvm(x, y) -^(x::Float32, y::Integer) = x^Int32(y) -^(x::Float32, y::Int32) = powi_llvm(x, y) -^(x::Float16, y::Integer) = Float16(Float32(x)^y) +@inline ^(x::Float64, y::Float64) = nan_dom_err(ccall("llvm.pow.f64", llvmcall, Float64, (Float64, Float64), x, y), x + y) +@inline ^(x::Float32, y::Float32) = nan_dom_err(ccall("llvm.pow.f32", llvmcall, Float32, (Float32, Float32), x, y), x + y) +@inline ^(x::Float64, y::Integer) = x ^ Float64(y) +@inline ^(x::Float32, y::Integer) = x ^ Float32(y) +@inline ^(x::Float16, y::Integer) = Float16(Float32(x) ^ Float32(y)) ^{p}(x::Float16, ::Type{Val{p}}) = Float16(Float32(x)^Val{p}) function angle_restrict_symm(theta) diff --git a/src/codegen.cpp b/src/codegen.cpp index 26c67da603b17..4d4ec294e5f0e 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -397,10 +397,6 @@ static Function *jldlsym_func; static Function *jlnewbits_func; static Function *jltypeassert_func; static Function *jldepwarnpi_func; -#if JL_LLVM_VERSION < 30600 -static Function *jlpow_func; -static Function *jlpowf_func; -#endif //static Function *jlgetnthfield_func; static Function *jlgetnthfieldchecked_func; //static Function *jlsetnthfield_func; @@ -6857,25 +6853,6 @@ static void init_julia_llvm_env(Module *m) "jl_gc_diff_total_bytes", m); add_named_global(diff_gc_total_bytes_func, *jl_gc_diff_total_bytes); -#if JL_LLVM_VERSION < 30600 - Type *powf_type[2] = { T_float32, T_float32 }; - jlpowf_func = Function::Create(FunctionType::get(T_float32, powf_type, false), - Function::ExternalLinkage, - "powf", m); - add_named_global(jlpowf_func, &powf, false); - - Type *pow_type[2] = { T_float64, T_float64 }; - jlpow_func = Function::Create(FunctionType::get(T_float64, pow_type, false), - Function::ExternalLinkage, - "pow", m); - add_named_global(jlpow_func, -#ifdef _COMPILER_MICROSOFT_ - static_cast(&pow), -#else - &pow, -#endif - false); -#endif std::vector array_owner_args(0); array_owner_args.push_back(T_pjlvalue); jlarray_data_owner_func = diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index 78e4eca282bcb..060422a10a222 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -71,7 +71,6 @@ static void jl_init_intrinsic_functions_codegen(Module *m) float_func[rint_llvm] = true; float_func[sqrt_llvm] = true; float_func[sqrt_llvm_fast] = true; - float_func[powi_llvm] = true; } extern "C" @@ -851,33 +850,6 @@ static jl_cgval_t emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs, return mark_julia_type(ans, false, x.typ, ctx); } - case powi_llvm: { - const jl_cgval_t &x = argv[0]; - const jl_cgval_t &y = argv[1]; - if (!jl_is_primitivetype(x.typ) || !jl_is_primitivetype(y.typ) || jl_datatype_size(y.typ) != 4) - return emit_runtime_call(f, argv, nargs, ctx); - Type *xt = FLOATT(bitstype_to_llvm(x.typ)); - Type *yt = T_int32; - if (!xt) - return emit_runtime_call(f, argv, nargs, ctx); - - Value *xv = emit_unbox(xt, x, x.typ); - Value *yv = emit_unbox(yt, y, y.typ); -#if JL_LLVM_VERSION >= 30600 - Value *powi = Intrinsic::getDeclaration(jl_Module, Intrinsic::powi, makeArrayRef(xt)); -#if JL_LLVM_VERSION >= 30700 - Value *ans = builder.CreateCall(powi, {xv, yv}); -#else - Value *ans = builder.CreateCall2(powi, xv, yv); -#endif -#else - // issue #6506 - Value *ans = builder.CreateCall2(prepare_call(xt == T_float64 ? jlpow_func : jlpowf_func), - xv, builder.CreateSIToFP(yv, xt)); -#endif - return mark_julia_type(ans, false, x.typ, ctx); - } - default: { assert(nargs >= 1 && "invalid nargs for intrinsic call"); const jl_cgval_t &xinfo = argv[0]; diff --git a/src/intrinsics.h b/src/intrinsics.h index 058ccc68faaa8..15ea45dc2d73d 100644 --- a/src/intrinsics.h +++ b/src/intrinsics.h @@ -91,7 +91,6 @@ ADD_I(trunc_llvm, 1) \ ADD_I(rint_llvm, 1) \ ADD_I(sqrt_llvm, 1) \ - ADD_I(powi_llvm, 2) \ ALIAS(sqrt_llvm_fast, sqrt_llvm) \ /* pointer access */ \ ADD_I(pointerref, 3) \ diff --git a/src/julia_internal.h b/src/julia_internal.h index fc0ede8097841..135d6c5655021 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -680,7 +680,6 @@ JL_DLLEXPORT jl_value_t *jl_floor_llvm(jl_value_t *a); JL_DLLEXPORT jl_value_t *jl_trunc_llvm(jl_value_t *a); JL_DLLEXPORT jl_value_t *jl_rint_llvm(jl_value_t *a); JL_DLLEXPORT jl_value_t *jl_sqrt_llvm(jl_value_t *a); -JL_DLLEXPORT jl_value_t *jl_powi_llvm(jl_value_t *a, jl_value_t *b); JL_DLLEXPORT jl_value_t *jl_abs_float(jl_value_t *a); JL_DLLEXPORT jl_value_t *jl_copysign_float(jl_value_t *a, jl_value_t *b); JL_DLLEXPORT jl_value_t *jl_flipsign_int(jl_value_t *a, jl_value_t *b); diff --git a/src/runtime_intrinsics.c b/src/runtime_intrinsics.c index d107a3a898294..f391588c12d6b 100644 --- a/src/runtime_intrinsics.c +++ b/src/runtime_intrinsics.c @@ -925,31 +925,6 @@ un_fintrinsic(trunc_float,trunc_llvm) un_fintrinsic(rint_float,rint_llvm) un_fintrinsic(sqrt_float,sqrt_llvm) -JL_DLLEXPORT jl_value_t *jl_powi_llvm(jl_value_t *a, jl_value_t *b) -{ - jl_ptls_t ptls = jl_get_ptls_states(); - jl_value_t *ty = jl_typeof(a); - if (!jl_is_primitivetype(ty)) - jl_error("powi_llvm: a is not a primitive type"); - if (!jl_is_primitivetype(jl_typeof(b)) || jl_datatype_size(jl_typeof(b)) != 4) - jl_error("powi_llvm: b is not a 32-bit primitive type"); - int sz = jl_datatype_size(ty); - jl_value_t *newv = jl_gc_alloc(ptls, sz, ty); - void *pa = jl_data_ptr(a), *pr = jl_data_ptr(newv); - switch (sz) { - /* choose the right size c-type operation */ - case 4: - *(float*)pr = powf(*(float*)pa, (float)jl_unbox_int32(b)); - break; - case 8: - *(double*)pr = pow(*(double*)pa, (double)jl_unbox_int32(b)); - break; - default: - jl_error("powi_llvm: runtime floating point intrinsics are not implemented for bit sizes other than 32 and 64"); - } - return newv; -} - JL_DLLEXPORT jl_value_t *jl_select_value(jl_value_t *isfalse, jl_value_t *a, jl_value_t *b) { JL_TYPECHK(isfalse, bool, isfalse); diff --git a/test/math.jl b/test/math.jl index 9c43e610a9bc9..ca5b2912cfc94 100644 --- a/test/math.jl +++ b/test/math.jl @@ -590,6 +590,18 @@ end end end +@testset "issue #19872" begin + f19872a(x) = x ^ 5 + f19872b(x) = x ^ (-1024) + @test 0 < f19872b(2.0) < 1e-300 + @test issubnormal(2.0 ^ (-1024)) + @test issubnormal(f19872b(2.0)) + @test !issubnormal(f19872b(0.0)) + @test f19872a(2.0) === 32.0 + @test !issubnormal(f19872a(2.0)) + @test !issubnormal(0.0) +end + # no domain error is thrown for negative values @test invoke(cbrt, Tuple{AbstractFloat}, -1.0) == -1.0 From 0cebddf9dd0675caf4b3f0bf59cc828c8fd448de Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Wed, 22 Feb 2017 15:19:42 -0500 Subject: [PATCH 0038/1534] bug fix for x^Val{p} (fixes problem noted in #20648) (#20732) --- base/gmp.jl | 2 +- base/mpfr.jl | 2 +- test/numbers.jl | 11 +++++++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/base/gmp.jl b/base/gmp.jl index c01b491e85083..5e339929b88cc 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -444,7 +444,7 @@ end ^(x::Bool , y::BigInt ) = Base.power_by_squaring(x, y) # override default inlining of x^2 and x^3 etc. -^{p}(x::BigInt, ::Type{Val{p}}) = x^Culong(p) +^{p}(x::BigInt, ::Type{Val{p}}) = x^p function powermod(x::BigInt, p::BigInt, m::BigInt) r = BigInt() diff --git a/base/mpfr.jl b/base/mpfr.jl index 8592f2e75043a..18529931004a4 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -505,7 +505,7 @@ end ^(x::BigFloat, y::Unsigned) = typemin(Culong) <= y <= typemax(Culong) ? x^Culong(y) : x^BigInt(y) # override default inlining of x^2 etc. -^{p}(x::BigFloat, ::Type{Val{p}}) = x^Culong(p) +^{p}(x::BigFloat, ::Type{Val{p}}) = x^p for f in (:exp, :exp2, :exp10, :expm1, :cosh, :sinh, :tanh, :sech, :csch, :coth, :cbrt) @eval function $f(x::BigFloat) diff --git a/test/numbers.jl b/test/numbers.jl index d46fb92f94380..1dedb11e6a44c 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -2912,6 +2912,17 @@ immutable PR20530; end @test x^p == 1 @test x^2 == 2 @test [x,x,x].^2 == [2,2,2] + for T in (Float16, Float32, Float64, BigFloat, Int8, Int, BigInt, Complex{Int}, Complex{Float64}) + for p in -4:4 + if p < 0 && real(T) <: Integer + @test_throws DomainError eval(:($T(2)^$p)) + else + v = eval(:($T(2)^$p)) + @test 2.0^p == T(2)^p == v + @test v isa T + end + end + end end @testset "iszero" begin From 5f41bc4d582ac7210b2d3ebf7e6ad245df7c7c27 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Wed, 22 Feb 2017 13:50:48 -0800 Subject: [PATCH 0039/1534] Add deprecation of two-argument map! and asyncmap! to NEWS.md. [ci skip] --- NEWS.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS.md b/NEWS.md index f577b704b1cdb..b915dafea4c3f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -359,6 +359,9 @@ Deprecated or removed * Vectorized functions have been deprecated in favor of dot syntax ([#17302],[#17265], [#18558],[#19711],[#19712],[#19791],[#19802],[#19931],[#20543],[#20228]). + * The two-argument forms of `map` (`map!(f, A)`) and `asyncmap!` (`asyncmap!(f, A)`) + have been deprecated in anticipation of future semantic changes ([#19721]). + [#265]: https://github.com/JuliaLang/julia/issues/265 [#4615]: https://github.com/JuliaLang/julia/issues/4615 @@ -417,6 +420,7 @@ Deprecated or removed [#19692]: https://github.com/JuliaLang/julia/issues/19692 [#19711]: https://github.com/JuliaLang/julia/issues/19711 [#19712]: https://github.com/JuliaLang/julia/issues/19712 +[#19721]: https://github.com/JuliaLang/julia/issues/19721 [#19722]: https://github.com/JuliaLang/julia/issues/19722 [#19741]: https://github.com/JuliaLang/julia/issues/19741 [#19787]: https://github.com/JuliaLang/julia/issues/19787 From 5e4b9a1c90b8b06870be11787b8feb19a53a29c6 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Wed, 22 Feb 2017 13:52:36 -0800 Subject: [PATCH 0040/1534] Add deprecation of isimag to NEWS.md. [ci skip] --- NEWS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS.md b/NEWS.md index b915dafea4c3f..a14752339bf4d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -362,6 +362,8 @@ Deprecated or removed * The two-argument forms of `map` (`map!(f, A)`) and `asyncmap!` (`asyncmap!(f, A)`) have been deprecated in anticipation of future semantic changes ([#19721]). + * `isimag` has been deprecated ([#19949]). + [#265]: https://github.com/JuliaLang/julia/issues/265 [#4615]: https://github.com/JuliaLang/julia/issues/4615 @@ -433,6 +435,7 @@ Deprecated or removed [#19919]: https://github.com/JuliaLang/julia/issues/19919 [#19931]: https://github.com/JuliaLang/julia/issues/19931 [#19944]: https://github.com/JuliaLang/julia/issues/19944 +[#19949]: https://github.com/JuliaLang/julia/issues/19949 [#19950]: https://github.com/JuliaLang/julia/issues/19950 [#20047]: https://github.com/JuliaLang/julia/issues/20047 [#20079]: https://github.com/JuliaLang/julia/issues/20079 From 59013d55603d118c24044b2683c91c3df09c59a0 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Wed, 22 Feb 2017 13:54:44 -0800 Subject: [PATCH 0041/1534] Add deprecation of broadcast_zpreserving to NEWS.md. [ci skip] --- NEWS.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS.md b/NEWS.md index a14752339bf4d..feb4af5d901bb 100644 --- a/NEWS.md +++ b/NEWS.md @@ -364,6 +364,8 @@ Deprecated or removed * `isimag` has been deprecated ([#19949]). + * `broadcast_zpreserving` has been deprecated ([#19533],[#19720]). + [#265]: https://github.com/JuliaLang/julia/issues/265 [#4615]: https://github.com/JuliaLang/julia/issues/4615 @@ -413,6 +415,7 @@ Deprecated or removed [#19449]: https://github.com/JuliaLang/julia/issues/19449 [#19464]: https://github.com/JuliaLang/julia/issues/19464 [#19469]: https://github.com/JuliaLang/julia/issues/19469 +[#19533]: https://github.com/JuliaLang/julia/issues/19533 [#19543]: https://github.com/JuliaLang/julia/issues/19543 [#19598]: https://github.com/JuliaLang/julia/issues/19598 [#19635]: https://github.com/JuliaLang/julia/issues/19635 @@ -422,6 +425,7 @@ Deprecated or removed [#19692]: https://github.com/JuliaLang/julia/issues/19692 [#19711]: https://github.com/JuliaLang/julia/issues/19711 [#19712]: https://github.com/JuliaLang/julia/issues/19712 +[#19720]: https://github.com/JuliaLang/julia/issues/19720 [#19721]: https://github.com/JuliaLang/julia/issues/19721 [#19722]: https://github.com/JuliaLang/julia/issues/19722 [#19741]: https://github.com/JuliaLang/julia/issues/19741 From f0a1b8679dce18ef348b1f27436998a77588c3dd Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Wed, 22 Feb 2017 14:10:46 -0800 Subject: [PATCH 0042/1534] Add deprecation of convert(<:AbstractTriangular, [Diagonal|Bidiagonal]) to NEWS.md. [ci skip] --- NEWS.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS.md b/NEWS.md index feb4af5d901bb..dfbbb53eccd6d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -366,6 +366,9 @@ Deprecated or removed * `broadcast_zpreserving` has been deprecated ([#19533],[#19720]). + * `convert` methods from `Diagonal` and `Bidiagonal` to subtypes of + `AbstractTriangular` have been deprecated ([#17723]). + [#265]: https://github.com/JuliaLang/julia/issues/265 [#4615]: https://github.com/JuliaLang/julia/issues/4615 @@ -385,6 +388,7 @@ Deprecated or removed [#17302]: https://github.com/JuliaLang/julia/issues/17302 [#17599]: https://github.com/JuliaLang/julia/issues/17599 [#17623]: https://github.com/JuliaLang/julia/issues/17623 +[#17723]: https://github.com/JuliaLang/julia/issues/17723 [#17758]: https://github.com/JuliaLang/julia/issues/17758 [#17785]: https://github.com/JuliaLang/julia/issues/17785 [#18050]: https://github.com/JuliaLang/julia/issues/18050 From 2a19c3628371faf86a3b039f0137010dc6c90c0d Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Wed, 22 Feb 2017 15:17:37 -0800 Subject: [PATCH 0043/1534] Add show method and test for FetchHead (#20727) --- base/libgit2/types.jl | 10 ++++++++++ test/libgit2.jl | 5 +++++ 2 files changed, 15 insertions(+) diff --git a/base/libgit2/types.jl b/base/libgit2/types.jl index 8ebd5a96a15f2..91499e21e281e 100644 --- a/base/libgit2/types.jl +++ b/base/libgit2/types.jl @@ -464,6 +464,16 @@ struct FetchHead ismerge::Bool end +function Base.show(io::IO, fh::FetchHead) + println(io, "FetchHead:") + println(io, "Name: $(fh.name)") + println(io, "URL: $(fh.url)") + print(io, "OID: ") + show(io, fh.oid) + println(io) + println(io, "Merged: $(fh.ismerge)") +end + # Abstract object types abstract type AbstractGitObject end Base.isempty(obj::AbstractGitObject) = (obj.ptr == C_NULL) diff --git a/test/libgit2.jl b/test/libgit2.jl index a2a8716a5f25c..0cc28de9b2e91 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -590,6 +590,11 @@ mktempdir() do dir @test fetch_heads[3].ismerge == false for fh in fetch_heads @test fh.url == cache_repo + fh_strs = split(sprint(show, fh), '\n') + @test fh_strs[1] == "FetchHead:" + @test fh_strs[2] == "Name: $(fh.name)" + @test fh_strs[3] == "URL: $(fh.url)" + @test fh_strs[5] == "Merged: $(fh.ismerge)" end finally close(repo) From 2d5a51d94568d00a412c47f64e0180fabe654cb0 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 22 Feb 2017 22:35:26 -0500 Subject: [PATCH 0044/1534] fix #20733, inference with new definition of `getindex` for tuples --- base/inference.jl | 21 ++++++++++++--------- test/inference.jl | 7 +++++++ 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index eb52cbde5f204..6443665676a52 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -1626,7 +1626,8 @@ function abstract_call(f::ANY, fargs::Union{Tuple{},Vector{Any}}, argtypes::Vect return abstract_apply(af, fargs[3:end], argtypes[3:end], vtypes, sv) end - for i = 2:(length(argtypes) - 1) + la = length(argtypes) + for i = 2:(la - 1) if isvarargtype(argtypes[i]) return Any end @@ -1776,9 +1777,9 @@ function abstract_call(f::ANY, fargs::Union{Tuple{},Vector{Any}}, argtypes::Vect return rty end - if length(argtypes)>2 && argtypes[3] ⊑ Int + if la>2 && argtypes[3] ⊑ Int at2 = widenconst(argtypes[2]) - if at2 <: SimpleVector && istopfunction(tm, f, :getindex) + if la==3 && at2 <: SimpleVector && istopfunction(tm, f, :getindex) if isa(argtypes[2], Const) && isa(argtypes[3], Const) svecval = argtypes[2].val idx = argtypes[3].val @@ -1788,15 +1789,15 @@ function abstract_call(f::ANY, fargs::Union{Tuple{},Vector{Any}}, argtypes::Vect end end elseif (at2 <: Tuple || - (isa(at2, DataType) && (at2::DataType).name === Pair_name())) + (isa(at2, DataType) && (at2::DataType).name === Pair_name())) # allow tuple indexing functions to take advantage of constant # index arguments. - if istopfunction(tm, f, :getindex) + if istopfunction(tm, f, :getindex) && la==3 return getfield_tfunc(argtypes[2], argtypes[3]) - elseif istopfunction(tm, f, :next) + elseif istopfunction(tm, f, :next) && la==3 t1 = widenconst(getfield_tfunc(argtypes[2], argtypes[3])) return t1===Bottom ? Bottom : Tuple{t1, Int} - elseif istopfunction(tm, f, :indexed_next) + elseif istopfunction(tm, f, :indexed_next) && la==4 t1 = widenconst(getfield_tfunc(argtypes[2], argtypes[3])) return t1===Bottom ? Bottom : Tuple{t1, Int} end @@ -3814,8 +3815,10 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference force_infer = false if !method.isstaged if method.module == _topmod(method.module) || (isdefined(Main, :Base) && method.module == Main.Base) - if method.name == :getindex || method.name == :next || method.name == :indexed_next - if length(atypes) > 2 && atypes[3] ⊑ Int + la = length(atypes) + if (la==3 && (method.name == :getindex || method.name == :next)) || + (la==4 && method.name == :indexed_next) + if atypes[3] ⊑ Int at2 = widenconst(atypes[2]) if (at2 <: Tuple || at2 <: SimpleVector || (isa(at2, DataType) && (at2::DataType).name === Pair_name())) diff --git a/test/inference.jl b/test/inference.jl index 0f637df2ea25a..6ab5588907693 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -635,6 +635,13 @@ let pub = Base.parameter_upper_bound, x = fComplicatedUnionAll(Real) @test pub(pub(x, 1), 2) == Int || pub(pub(x, 1), 2) == Float64 end +# issue #20733 +# run this test in a separate process to avoid interfering with `getindex` +let def = "Base.getindex(t::NTuple{3,NTuple{2,Int}}, i::Int, j::Int, k::Int) = (t[1][i], t[2][j], t[3][k])" + @test readstring(`$(Base.julia_cmd()) --startup-file=no -E "$def;test(t) = t[2,1,2];test(((3,4), (5,6), (7,8)))"`) == + "(4, 5, 8)\n" +end + # issue #20267 mutable struct T20267{T} inds::Vector{T} From 51f7a8483c44e3e7375f8b418c98a529636ce245 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 22 Feb 2017 22:35:59 -0500 Subject: [PATCH 0045/1534] fix #20729, handle null in ASTs better --- src/ast.c | 2 ++ test/parse.jl | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/src/ast.c b/src/ast.c index b43ce6e418d54..fc65ae4b44147 100644 --- a/src/ast.c +++ b/src/ast.c @@ -693,6 +693,8 @@ static value_t julia_to_list2(fl_context_t *fl_ctx, jl_value_t *a, jl_value_t *b static value_t julia_to_scm_(fl_context_t *fl_ctx, jl_value_t *v) { + if (v == NULL) + jl_error("undefined reference in AST"); if (jl_is_symbol(v)) return symbol(fl_ctx, jl_symbol_name((jl_sym_t*)v)); if (v == jl_true) diff --git a/test/parse.jl b/test/parse.jl index 6c34f4dd68076..d8c5c3e539b04 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -1024,3 +1024,12 @@ const a = A() @test_throws MethodError a() @test call(a) === 1 end + +# issue #20729 +macro m20729() + ex = Expr(:head) + resize!(ex.args, 1) + return ex +end + +@test_throws ErrorException expand(:(@m20729)) From 03939e7a127b425502a16a38b2d8013ffc7edee4 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 22 Feb 2017 22:36:39 -0500 Subject: [PATCH 0046/1534] fix #20745, handle macrocall in `deparse` --- src/ast.scm | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ast.scm b/src/ast.scm index 2541b1cb1edd0..7b3626bea3656 100644 --- a/src/ast.scm +++ b/src/ast.scm @@ -50,6 +50,7 @@ ((call) (string (deparse (cadr e)) #\( (deparse-arglist (cddr e)) #\))) ((ref) (string (deparse (cadr e)) #\[ (deparse-arglist (cddr e)) #\])) ((curly) (string (deparse (cadr e)) #\{ (deparse-arglist (cddr e)) #\})) + ((macrocall) (string (cadr e) " " (deparse-arglist (cddr e) " "))) ((quote inert) (if (and (symbol? (cadr e)) (not (= (string.char (string (cadr e)) 0) #\=))) From 98cd6bb0c95cde82b51357308860cbf3a1ba1c4e Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Wed, 22 Feb 2017 16:47:10 -0600 Subject: [PATCH 0047/1534] Remove unnecessary nothing checks --- base/libgit2/callbacks.jl | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/base/libgit2/callbacks.jl b/base/libgit2/callbacks.jl index 06ead82ea578e..16ecf8badd11e 100644 --- a/base/libgit2/callbacks.jl +++ b/base/libgit2/callbacks.jl @@ -37,7 +37,7 @@ function authenticate_ssh(creds::SSHCredentials, libgit2credptr::Ptr{Ptr{Void}}, end # first try ssh-agent if credentials support its usage - if creds.usesshagent === nothing || creds.usesshagent == "Y" || creds.usesshagent == "U" + if creds.usesshagent == "Y" || creds.usesshagent == "U" err = ccall((:git_cred_ssh_key_from_agent, :libgit2), Cint, (Ptr{Ptr{Void}}, Cstring), libgit2credptr, username_ptr) creds.usesshagent = "U" # used ssh-agent only one time @@ -59,7 +59,6 @@ function authenticate_ssh(creds::SSHCredentials, libgit2credptr::Ptr{Ptr{Void}}, ENV["SSH_KEY_PATH"] else keydefpath = creds.prvkey # check if credentials were already used - keydefpath === nothing && (keydefpath = "") if isempty(keydefpath) || isusedcreds defaultkeydefpath = joinpath(homedir(),".ssh","id_rsa") if isempty(keydefpath) && isfile(defaultkeydefpath) @@ -81,7 +80,6 @@ function authenticate_ssh(creds::SSHCredentials, libgit2credptr::Ptr{Ptr{Void}}, ENV["SSH_PUB_KEY_PATH"] else keydefpath = creds.pubkey # check if credentials were already used - keydefpath === nothing && (keydefpath = "") if isempty(keydefpath) || isusedcreds if isempty(keydefpath) keydefpath = privatekey*".pub" @@ -108,7 +106,6 @@ function authenticate_ssh(creds::SSHCredentials, libgit2credptr::Ptr{Ptr{Void}}, ENV["SSH_KEY_PASS"] else passdef = creds.pass # check if credentials were already used - passdef === nothing && (passdef = "") if passphrase_required && (isempty(passdef) || isusedcreds) if is_windows() passdef = Base.winprompt( @@ -146,19 +143,16 @@ function authenticate_userpass(creds::UserPasswordCredentials, libgit2credptr::P if creds.prompt_if_incorrect username = creds.user userpass = creds.pass - (username === nothing) && (username = "") - (userpass === nothing) && (userpass = "") if is_windows() if isempty(username) || isempty(userpass) || isusedcreds res = Base.winprompt("Please enter your credentials for '$schema$host'", "Credentials required", - username === nothing || isempty(username) ? - urlusername : username; prompt_username = true) + isempty(username) ? urlusername : username; prompt_username = true) isnull(res) && return Cint(Error.EAUTH) username, userpass = Base.get(res) end elseif isusedcreds - username = prompt("Username for '$schema$host'", default = isempty(username) ? - urlusername : username) + username = prompt("Username for '$schema$host'", + default=isempty(username) ? urlusername : username) userpass = prompt("Password for '$schema$username@$host'", password=true) end ((creds.user != username) || (creds.pass != userpass)) && reset!(creds) From 35321e7dab6a0e0469c13f655edf823786191073 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Wed, 22 Feb 2017 21:42:55 -0600 Subject: [PATCH 0048/1534] Improve type stability regarding err variable --- base/libgit2/callbacks.jl | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/base/libgit2/callbacks.jl b/base/libgit2/callbacks.jl index 16ecf8badd11e..41d01594dfb6a 100644 --- a/base/libgit2/callbacks.jl +++ b/base/libgit2/callbacks.jl @@ -130,10 +130,9 @@ function authenticate_ssh(creds::SSHCredentials, libgit2credptr::Ptr{Ptr{Void}}, isusedcreds && return Cint(Error.EAUTH) end - err = ccall((:git_cred_ssh_key_new, :libgit2), Cint, + return ccall((:git_cred_ssh_key_new, :libgit2), Cint, (Ptr{Ptr{Void}}, Cstring, Cstring, Cstring, Cstring), libgit2credptr, creds.user, creds.pubkey, creds.prvkey, creds.pass) - return err end function authenticate_userpass(creds::UserPasswordCredentials, libgit2credptr::Ptr{Ptr{Void}}, @@ -164,10 +163,9 @@ function authenticate_userpass(creds::UserPasswordCredentials, libgit2credptr::P isusedcreds && return Cint(Error.EAUTH) end - err = ccall((:git_cred_userpass_plaintext_new, :libgit2), Cint, + return ccall((:git_cred_userpass_plaintext_new, :libgit2), Cint, (Ptr{Ptr{Void}}, Cstring, Cstring), libgit2credptr, creds.user, creds.pass) - err == 0 && return Cint(0) end @@ -200,7 +198,7 @@ counting strategy that prevents repeated usage of faulty credentials. function credentials_callback(libgit2credptr::Ptr{Ptr{Void}}, url_ptr::Cstring, username_ptr::Cstring, allowed_types::Cuint, payload_ptr::Ptr{Void}) - err = 0 + err = Cint(0) url = unsafe_string(url_ptr) # parse url for schema and host @@ -246,7 +244,7 @@ function credentials_callback(libgit2credptr::Ptr{Ptr{Void}}, url_ptr::Cstring, end err = Cint(Error.EAUTH) end - return Cint(err) + return err end function fetchhead_foreach_callback(ref_name::Cstring, remote_url::Cstring, From 9e947e5ca6276df4e2d00a860eea2d54b782ba9f Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 23 Feb 2017 00:01:14 -0500 Subject: [PATCH 0049/1534] fix #20610, add deprecation for `=>` expression head --- src/julia-syntax.scm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 452c2688c565e..b8caa322685bb 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -2083,6 +2083,11 @@ (error "assignment not allowed inside tuple")) (expand-forms `(call (core tuple) ,@(cdr e)))) + '=> + (lambda (e) + (syntax-deprecation #f "Expr(:(=>), ...)" "Expr(:call, :(=>), ...)") + `(call => ,(expand-forms (cadr e)) ,(expand-forms (caddr e)))) + 'cell1d (lambda (e) (error "{ } vector syntax is discontinued")) 'cell2d (lambda (e) (error "{ } matrix syntax is discontinued")) From f1adcc8c53d81d096e4f93878467857c954e54ae Mon Sep 17 00:00:00 2001 From: Iblis Lin Date: Thu, 23 Feb 2017 17:01:27 +0800 Subject: [PATCH 0050/1534] mmap: fix MAP_ANONYMOUS flags value for bsd family --- base/mmap.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/mmap.jl b/base/mmap.jl index 6ff2707d6e5ce..ca56126812f56 100644 --- a/base/mmap.jl +++ b/base/mmap.jl @@ -27,7 +27,7 @@ const PROT_READ = Cint(1) const PROT_WRITE = Cint(2) const MAP_SHARED = Cint(1) const MAP_PRIVATE = Cint(2) -const MAP_ANONYMOUS = Cint(is_apple() ? 0x1000 : 0x20) +const MAP_ANONYMOUS = Cint(is_bsd() ? 0x1000 : 0x20) const F_GETFL = Cint(3) gethandle(io::IO) = fd(io) From 162a61d562246562a23686485d4f5203fe9c3f32 Mon Sep 17 00:00:00 2001 From: Iblis Lin Date: Thu, 23 Feb 2017 17:45:53 +0800 Subject: [PATCH 0051/1534] sharedarray: improve error msg on bsd family --- base/sharedarray.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/base/sharedarray.jl b/base/sharedarray.jl index c48eb8d790e29..ce4925dd28929 100644 --- a/base/sharedarray.jl +++ b/base/sharedarray.jl @@ -553,7 +553,12 @@ function print_shmem_limits(slen) pfx = "kernel" elseif is_apple() pfx = "kern.sysv" + elseif Sys.KERNEL == :FreeBSD || Sys.KERNEL == :DragonFly + pfx = "kern.ipc" + elseif Sys.KERNEL == :OpenBSD + pfx = "kern.shminfo" else + # seems NetBSD does not have *.shmall return end From 0b2130e628da2ab23b4eb7cd5ff08e6e42c60bd0 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Thu, 23 Feb 2017 08:24:44 -0800 Subject: [PATCH 0052/1534] Revise mention of deprecated array-scalar methods in a news item, indicating their deprecation. [ci skip] (#20743) --- NEWS.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index f577b704b1cdb..497a94fe39d13 100644 --- a/NEWS.md +++ b/NEWS.md @@ -126,8 +126,9 @@ This section lists changes that do not have deprecation warnings. The flip-side of this is that new method definitions should now reliably actually take effect, and be called when evaluating new code ([#265]). - * The array-scalar operations `div`, `mod`, `rem`, `&`, `|`, `xor`, `/`, `\`, `*`, `+`, and `-` - now follow broadcast promotion rules ([#19692]). + * The array-scalar methods of `/`, `\`, `*`, `+`, and `-` now follow broadcast promotion + rules. (Likewise for the now-deprecated array-scalar methods of `div`, `mod`, `rem`, + `&`, `|`, and `xor`; see "Deprecated or removed" below.) ([#19692]). * `broadcast!(f, A)` now calls `f()` for each element of `A`, rather than doing `fill!(A, f())` ([#19722]). From a17b1384469c7e197298c261b5f68ebde6ff16d5 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Thu, 23 Feb 2017 08:58:38 -0800 Subject: [PATCH 0053/1534] Expand docs for mod (#20633) * Expand docs for mod Address #14826. * simplify doc text * Another rewrite * more changes * typo * some more * missing the --- base/int.jl | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/base/int.jl b/base/int.jl index aca8405da700f..56a4645275e29 100644 --- a/base/int.jl +++ b/base/int.jl @@ -131,12 +131,39 @@ fld(x::Unsigned, y::Signed) = div(x, y) - (signbit(y) & (rem(x, y) != 0)) """ mod(x, y) + rem(x, y, RoundDown) -Modulus after flooring division, returning in the range ``[0,y)``, if `y` is positive, or -``(y,0]`` if `y` is negative. - +The reduction of `x` modulo `y`, or equivalently, the remainder of `x` after floored +division by `y`, i.e. ```julia -x == fld(x,y)*y + mod(x,y) +x - y*fld(x,y) +``` +if computed without intermediate rounding. + +The result will have the same sign as `y`, and magnitude less than `abs(y)` (with some +exceptions, see note below). + +!!! note + + When used with floating point values, the exact result may not be representable by the + type, and so rounding error may occur. In particular, if the exact result is very + close to `y`, then it may be rounded to `y`. + +```jldoctest +julia> mod(8, 3) +2 + +julia> mod(9, 3) +0 + +julia> mod(8.9, 3) +2.9000000000000004 + +julia> mod(eps(), 3) +2.220446049250313e-16 + +julia> mod(-eps(), 3) +3.0 ``` """ function mod{T<:Integer}(x::T, y::T) From 4275c74ae7aa4698c5b4bb185e881636f357f83b Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Thu, 23 Feb 2017 09:29:32 -0800 Subject: [PATCH 0054/1534] Fix doc build in cygwin cross-compile (#20713) need cygpath_w to translate absolute paths from cygwin style to windows for mingw julia executable to understand them fixes buildbot failure seen at https://build.julialang.org/builders/package_win6.2-x64/builds/1346/steps/make%20binary-dist/logs/stdio was broken by me in #20519, didn't notice until now because of #20643 preventing the buildbots from making new nightlies --- doc/Makefile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/Makefile b/doc/Makefile index 39bac7ea31b59..6a8764cb3665a 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -32,32 +32,32 @@ cleanall: clean html: deps @echo "Building HTML documentation." ifneq ($(OS),WINNT) - $(JULIA_EXECUTABLE) $(SRCDIR)/make.jl -- deploy + $(JULIA_EXECUTABLE) $(call cygpath_w,$(SRCDIR)/make.jl) -- deploy else # work around issue #11727, windows output redirection breaking on buildbot - $(JULIA_EXECUTABLE) $(SRCDIR)/make.jl -- deploy > docbuild.log 2>&1 + $(JULIA_EXECUTABLE) $(call cygpath_w,$(SRCDIR)/make.jl) -- deploy > docbuild.log 2>&1 @cat docbuild.log endif @echo "Build finished. The HTML pages are in _build/html." pdf: deps @echo "Building PDF documentation." - $(JULIA_EXECUTABLE) $(SRCDIR)/make.jl -- pdf + $(JULIA_EXECUTABLE) $(call cygpath_w,$(SRCDIR)/make.jl) -- pdf @echo "Build finished." linkcheck: deps @echo "Checking external documentation links." - $(JULIA_EXECUTABLE) $(SRCDIR)/make.jl -- linkcheck + $(JULIA_EXECUTABLE) $(call cygpath_w,$(SRCDIR)/make.jl) -- linkcheck @echo "Checks finished." doctest: deps @echo "Running all embedded 'doctests'." - $(JULIA_EXECUTABLE) --color=yes $(SRCDIR)/make.jl -- doctest + $(JULIA_EXECUTABLE) --color=yes $(call cygpath_w,$(SRCDIR)/make.jl) -- doctest @echo "Checks finished." check: deps @echo "Running all embedded 'doctests' and checking external links." - $(JULIA_EXECUTABLE) --color=yes $(SRCDIR)/make.jl -- doctest linkcheck + $(JULIA_EXECUTABLE) --color=yes $(call cygpath_w,$(SRCDIR)/make.jl) -- doctest linkcheck @echo "Checks finished." .PHONY: deps From 4b76c9551bd994f586eb0647eef022ab56679f0c Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Thu, 23 Feb 2017 19:31:45 +0100 Subject: [PATCH 0055/1534] Goodbye, Human (#20748) --- base/docs/basedocs.jl | 3 --- 1 file changed, 3 deletions(-) diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index 2e90a0a73161f..3b8a35cbd0ca0 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -7,9 +7,6 @@ struct Keyword end macro kw_str(text) Keyword(Symbol(text)) end -"Hello, Human." -kw"hello", kw"hi" - """ **Welcome to Julia $(string(VERSION)).** The full manual is available at From d3ee10b04f62194868ad31fbc8873d4f1e401074 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Thu, 23 Feb 2017 19:37:15 +0100 Subject: [PATCH 0056/1534] Dict merge(!) with combiner function (#20708) --- base/associative.jl | 85 +++++++++++++++++++++++++++++++++++++++++---- test/dict.jl | 24 +++++++++++++ 2 files changed, 102 insertions(+), 7 deletions(-) diff --git a/base/associative.jl b/base/associative.jl index 0c27814c6b461..896e62d12e8cb 100644 --- a/base/associative.jl +++ b/base/associative.jl @@ -146,6 +146,44 @@ function merge!(d::Associative, others::Associative...) return d end +""" + merge!(combine, d::Associative, others::Associative...) + +Update collection with pairs from the other collections. +Values with the same key will be combined using the +combiner function. + +```jldoctest +julia> d1 = Dict(1 => 2, 3 => 4); + +julia> d2 = Dict(1 => 4, 4 => 5); + +julia> merge!(+, d1, d2); + +julia> d1 +Dict{Int64,Int64} with 3 entries: + 4 => 5 + 3 => 4 + 1 => 6 + +julia> merge!(-, d1, d1); + +julia> d1 +Dict{Int64,Int64} with 3 entries: + 4 => 0 + 3 => 0 + 1 => 0 +``` +""" +function merge!(combine::Function, d::Associative, others::Associative...) + for other in others + for (k,v) in other + d[k] = haskey(d, k) ? combine(d[k], v) : v + end + end + return d +end + # very similar to `merge!`, but accepts any iterable and extends code # that would otherwise only use `copy!` with arrays. function copy!(dest::Union{Associative,AbstractSet}, src) @@ -215,13 +253,46 @@ Dict{String,Float64} with 3 entries: "foo" => 0.0 ``` """ -function merge(d::Associative, others::Associative...) - K, V = keytype(d), valtype(d) - for other in others - K = promote_type(K, keytype(other)) - V = promote_type(V, valtype(other)) - end - merge!(Dict{K,V}(), d, others...) +merge(d::Associative, others::Associative...) = + merge!(emptymergedict(d, others...), d, others...) + +""" + merge(combine, d::Associative, others::Associative...) + +Construct a merged collection from the given collections. If necessary, the +types of the resulting collection will be promoted to accommodate the types of +the merged collections. Values with the same key will be combined using the +combiner function. + +```jldoctest +julia> a = Dict("foo" => 0.0, "bar" => 42.0) +Dict{String,Float64} with 2 entries: + "bar" => 42.0 + "foo" => 0.0 + +julia> b = Dict("baz" => 17, "bar" => 4711) +Dict{String,Int64} with 2 entries: + "bar" => 4711 + "baz" => 17 + +julia> merge(+, a, b) +Dict{String,Float64} with 3 entries: + "bar" => 4753.0 + "baz" => 17.0 + "foo" => 0.0 +``` +""" +merge(combine::Function, d::Associative, others::Associative...) = + merge!(combine, emptymergedict(d, others...), d, others...) + +promoteK(K) = K +promoteV(V) = V +promoteK(K, d, ds...) = promoteK(promote_type(K, keytype(d)), ds...) +promoteV(V, d, ds...) = promoteV(promote_type(V, valtype(d)), ds...) +function emptymergedict(d::Associative, others::Associative...) + K = promoteK(keytype(d), others...) + V = promoteV(valtype(d), others...) + Dict{K,V}() end function filter!(f, d::Associative) diff --git a/test/dict.jl b/test/dict.jl index 1ec266ec2f194..dc6e2ab66aad7 100644 --- a/test/dict.jl +++ b/test/dict.jl @@ -682,3 +682,27 @@ let @test pair[1] == tupl[1] && pair[2] == tupl[2] end end + +@testset "Dict merge" begin + d1 = Dict("A" => 1, "B" => 2) + d2 = Dict("B" => 3.0, "C" => 4.0) + @test @inferred merge(d1, d2) == Dict("A" => 1, "B" => 3, "C" => 4) + # merge with combiner function + @test @inferred merge(+, d1, d2) == Dict("A" => 1, "B" => 5, "C" => 4) + @test @inferred merge(*, d1, d2) == Dict("A" => 1, "B" => 6, "C" => 4) + @test @inferred merge(-, d1, d2) == Dict("A" => 1, "B" => -1, "C" => 4) +end + +@testset "Dict merge!" begin + d1 = Dict("A" => 1, "B" => 2) + d2 = Dict("B" => 3, "C" => 4) + @inferred merge!(d1, d2) + @test d1 == Dict("A" => 1, "B" => 3, "C" => 4) + # merge! with combiner function + @inferred merge!(+, d1, d2) + @test d1 == Dict("A" => 1, "B" => 6, "C" => 8) + @inferred merge!(*, d1, d2) + @test d1 == Dict("A" => 1, "B" => 18, "C" => 32) + @inferred merge!(-, d1, d2) + @test d1 == Dict("A" => 1, "B" => 15, "C" => 28) +end From cc7990b1936440e1b4bbe33895aa4dcdd6e2a754 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 23 Feb 2017 13:10:52 -0500 Subject: [PATCH 0057/1534] make several pure-marked math functions actually pure --- base/float.jl | 8 -------- base/math.jl | 21 +++++++++++++++------ base/special/exp.jl | 8 ++++---- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/base/float.jl b/base/float.jl index f3b7abdfa5c4c..612e9360c08a7 100644 --- a/base/float.jl +++ b/base/float.jl @@ -812,14 +812,6 @@ fpinttype(::Type{Float64}) = UInt64 fpinttype(::Type{Float32}) = UInt32 fpinttype(::Type{Float16}) = UInt16 -@pure significand_bits{T<:AbstractFloat}(::Type{T}) = trailing_ones(significand_mask(T)) -@pure exponent_bits{T<:AbstractFloat}(::Type{T}) = sizeof(T)*8 - significand_bits(T) - 1 -@pure exponent_bias{T<:AbstractFloat}(::Type{T}) = Int(exponent_one(T) >> significand_bits(T)) -# maximum float exponent -@pure exponent_max{T<:AbstractFloat}(::Type{T}) = Int(exponent_mask(T) >> significand_bits(T)) - exponent_bias(T) -# maximum float exponent without bias -@pure exponent_raw_max{T<:AbstractFloat}(::Type{T}) = Int(exponent_mask(T) >> significand_bits(T)) - ## TwicePrecision utilities # The numeric constants are half the number of bits in the mantissa for (F, T, n) in ((Float16, UInt16, 5), (Float32, UInt32, 12), (Float64, UInt64, 26)) diff --git a/base/math.jl b/base/math.jl index c75740809c400..d4db49a661030 100644 --- a/base/math.jl +++ b/base/math.jl @@ -20,13 +20,23 @@ import Base: log, exp, sin, cos, tan, sinh, cosh, tanh, asin, max, min, minmax, ^, exp2, muladd, rem, exp10, expm1, log1p -using Base: sign_mask, exponent_mask, exponent_one, exponent_bias, - exponent_half, exponent_max, exponent_raw_max, fpinttype, - significand_mask, significand_bits, exponent_bits +using Base: sign_mask, exponent_mask, exponent_one, + exponent_half, fpinttype, significand_mask using Core.Intrinsics: sqrt_llvm -const IEEEFloat = Union{Float16,Float32,Float64} +const IEEEFloat = Union{Float16, Float32, Float64} + +for T in (Float16, Float32, Float64) + @eval significand_bits(::Type{$T}) = $(trailing_ones(significand_mask(T))) + @eval exponent_bits(::Type{$T}) = $(sizeof(T)*8 - significand_bits(T) - 1) + @eval exponent_bias(::Type{$T}) = $(Int(exponent_one(T) >> significand_bits(T))) + # maximum float exponent + @eval exponent_max(::Type{$T}) = $(Int(exponent_mask(T) >> significand_bits(T)) - exponent_bias(T)) + # maximum float exponent without bias + @eval exponent_raw_max(::Type{$T}) = $(Int(exponent_mask(T) >> significand_bits(T))) +end + # non-type specific math functions """ @@ -229,8 +239,6 @@ for f in (:cbrt, :sinh, :cosh, :tanh, :atan, :asinh, :exp2, :expm1) ($f)(x::Real) = ($f)(float(x)) end end -# pure julia exp function -include("special/exp.jl") exp(x::Real) = exp(float(x)) # fallback definitions to prevent infinite loop from $f(x::Real) def above @@ -950,6 +958,7 @@ end cbrt(a::Float16) = Float16(cbrt(Float32(a))) # More special functions +include("special/exp.jl") include("special/trig.jl") include("special/gamma.jl") diff --git a/base/special/exp.jl b/base/special/exp.jl index 9d7012a98034f..7f21519c79619 100644 --- a/base/special/exp.jl +++ b/base/special/exp.jl @@ -56,8 +56,8 @@ MINEXP(::Type{Float32}) = -103.97207708f0 # log 2^-150 @inline exp_kernel(x::Float32) = @horner(x, 1.6666625440f-1, -2.7667332906f-3) # for values smaller than this threshold just use a Taylor expansion -exp_small_thres(::Type{Float64}) = 2.0^-28 -exp_small_thres(::Type{Float32}) = 2.0f0^-13 +@eval exp_small_thres(::Type{Float64}) = $(2.0^-28) +@eval exp_small_thres(::Type{Float32}) = $(2.0f0^-13) """ exp(x) @@ -114,13 +114,13 @@ function exp{T<:Union{Float32,Float64}}(x::T) # scale back if k > -significand_bits(T) # multiply by 2.0 first to prevent overflow, which helps extends the range - k == exponent_max(T) && return y*T(2.0)*T(2.0)^(exponent_max(T) - 1) + k == exponent_max(T) && return y * T(2.0) * T(2.0)^(exponent_max(T) - 1) twopk = reinterpret(T, rem(exponent_bias(T) + k, fpinttype(T)) << significand_bits(T)) return y*twopk else # add significand_bits(T) + 1 to lift the range outside the subnormals twopk = reinterpret(T, rem(exponent_bias(T) + significand_bits(T) + 1 + k, fpinttype(T)) << significand_bits(T)) - return y*twopk*T(2.0)^(-significand_bits(T) - 1) + return y * twopk * T(2.0)^(-significand_bits(T) - 1) end elseif xa < reinterpret(Unsigned, exp_small_thres(T)) # |x| < exp_small_thres # Taylor approximation for small x From 0c5eac2bc5603b82c9ac114bdc8999831cba2f6f Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 23 Feb 2017 14:10:23 -0500 Subject: [PATCH 0058/1534] make sure that the indirection through the `Val{p}` type doesn't stop inlining of `^` --- base/intfuncs.jl | 17 ++++++++++------- base/math.jl | 2 +- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index d299a8da27944..69c0df7d11c17 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -199,16 +199,19 @@ end # to enable compile-time optimizations specialized to p. # However, we still need a fallback that calls the general ^. # To avoid ambiguities for methods that dispatch on the -# first argument, we dispatch the fallback via internal_pow: -^(x, p) = internal_pow(x, p) -internal_pow{p}(x, ::Type{Val{p}}) = x^p +# first argument, we dispatch the fallback via internal_pow. +# We mark these @inline since if the target is marked @inline, +# we want to make sure that gets propagated, +# even if it is over the inlining threshold. +@inline ^(x, p) = internal_pow(x, p) +@inline internal_pow{p}(x, ::Type{Val{p}}) = x^p # inference.jl has complicated logic to inline x^2 and x^3 for # numeric types. In terms of Val we can do it much more simply: -internal_pow(x::Number, ::Type{Val{0}}) = one(x) -internal_pow(x::Number, ::Type{Val{1}}) = x -internal_pow(x::Number, ::Type{Val{2}}) = x*x -internal_pow(x::Number, ::Type{Val{3}}) = x*x*x +@inline internal_pow(x::Number, ::Type{Val{0}}) = one(x) +@inline internal_pow(x::Number, ::Type{Val{1}}) = x +@inline internal_pow(x::Number, ::Type{Val{2}}) = x*x +@inline internal_pow(x::Number, ::Type{Val{3}}) = x*x*x # b^p mod m diff --git a/base/math.jl b/base/math.jl index d4db49a661030..944514da5e736 100644 --- a/base/math.jl +++ b/base/math.jl @@ -698,7 +698,7 @@ end @inline ^(x::Float64, y::Integer) = x ^ Float64(y) @inline ^(x::Float32, y::Integer) = x ^ Float32(y) @inline ^(x::Float16, y::Integer) = Float16(Float32(x) ^ Float32(y)) -^{p}(x::Float16, ::Type{Val{p}}) = Float16(Float32(x)^Val{p}) +@inline ^{p}(x::Float16, ::Type{Val{p}}) = Float16(Float32(x) ^ Val{p}) function angle_restrict_symm(theta) const P1 = 4 * 7.8539812564849853515625e-01 From 79687179ad9c7b39d033c4512deb58c6fcaa2eb4 Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Thu, 23 Feb 2017 16:08:52 -0500 Subject: [PATCH 0059/1534] Make setindex! work for views of BitArrays by loosening signature (#20717) for Arrays to StridedArrays. This is not the fastest solution but it should be correct. Since StridedArrays are not defined when bitarray.jl is loaded, the relevant defitions are moved to multidimensional.jl Fixes #20715 --- base/bitarray.jl | 76 +------------------------------------- base/multidimensional.jl | 80 ++++++++++++++++++++++++++++++++++++++-- test/arrayops.jl | 2 + test/bitarray.jl | 8 +++- 4 files changed, 87 insertions(+), 79 deletions(-) diff --git a/base/bitarray.jl b/base/bitarray.jl index 5f24ae708c43f..53b81513146b5 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -238,7 +238,7 @@ function fill_chunks!(Bc::Array{UInt64}, x::Bool, pos::Integer, numbits::Integer end end -copy_to_bitarray_chunks!(dest::Vector{UInt64}, pos_d::Integer, src::BitArray, pos_s::Integer, numbits::Integer) = +copy_to_bitarray_chunks!(dest::Vector{UInt64}, pos_d::Int, src::BitArray, pos_s::Int, numbits::Int) = copy_chunks!(dest, pos_d, src.chunks, pos_s, numbits) # pack 8 Bools encoded as one contiguous UIn64 into a single byte, e.g.: @@ -315,79 +315,7 @@ function copy_to_bitarray_chunks!(Bc::Vector{UInt64}, pos_d::Int, C::Array{Bool} end end -function copy_to_bitarray_chunks!(Bc::Vector{UInt64}, pos_d::Int, C::Array, pos_s::Int, numbits::Int) - bind = pos_d - cind = pos_s - lastind = pos_d + numbits - 1 - @inbounds while bind ≤ lastind - unsafe_bitsetindex!(Bc, Bool(C[cind]), bind) - bind += 1 - cind += 1 - end -end - -# Note: the next two functions rely on the following definition of the conversion to Bool: -# convert(::Type{Bool}, x::Real) = x==0 ? false : x==1 ? true : throw(InexactError()) -# they're used to pre-emptively check in bulk when possible, which is much faster. -# Also, the functions can be overloaded for custom types T<:Real : -# a) in the unlikely eventuality that they use a different logic for Bool conversion -# b) to skip the check if not necessary -@inline try_bool_conversion(x::Real) = x == 0 || x == 1 || throw(InexactError()) -@inline unchecked_bool_convert(x::Real) = x == 1 - -function copy_to_bitarray_chunks!(Bc::Vector{UInt64}, pos_d::Int, C::Array{<:Real}, pos_s::Int, numbits::Int) - @inbounds for i = (1:numbits) + pos_s - 1 - try_bool_conversion(C[i]) - end - - kd0, ld0 = get_chunks_id(pos_d) - kd1, ld1 = get_chunks_id(pos_d + numbits - 1) - - delta_kd = kd1 - kd0 - - u = _msk64 - if delta_kd == 0 - msk_d0 = msk_d1 = ~(u << ld0) | (u << (ld1+1)) - lt0 = ld1 - else - msk_d0 = ~(u << ld0) - msk_d1 = (u << (ld1+1)) - lt0 = 63 - end - - bind = kd0 - ind = pos_s - @inbounds if ld0 > 0 - c = UInt64(0) - for j = ld0:lt0 - c |= (UInt64(unchecked_bool_convert(C[ind])) << j) - ind += 1 - end - Bc[kd0] = (Bc[kd0] & msk_d0) | (c & ~msk_d0) - bind += 1 - end - - nc = _div64(numbits - ind + pos_s) - @inbounds for i = 1:nc - c = UInt64(0) - for j = 0:63 - c |= (UInt64(unchecked_bool_convert(C[ind])) << j) - ind += 1 - end - Bc[bind] = c - bind += 1 - end - - @inbounds if bind ≤ kd1 - @assert bind == kd1 - c = UInt64(0) - for j = 0:ld1 - c |= (UInt64(unchecked_bool_convert(C[ind])) << j) - ind += 1 - end - Bc[kd1] = (Bc[kd1] & msk_d1) | (c & ~msk_d1) - end -end +## More definitions in multidimensional.jl # auxiliary definitions used when filling a BitArray via a Vector{Bool} cache # (e.g. when constructing from an iterable, or in broadcast!) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 283b4d6801bc5..1ec6dec50828c 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -957,10 +957,84 @@ end ## setindex! +function copy_to_bitarray_chunks!(Bc::Vector{UInt64}, pos_d::Int, C::StridedArray, pos_s::Int, numbits::Int) + bind = pos_d + cind = pos_s + lastind = pos_d + numbits - 1 + @inbounds while bind ≤ lastind + unsafe_bitsetindex!(Bc, Bool(C[cind]), bind) + bind += 1 + cind += 1 + end +end + +# Note: the next two functions rely on the following definition of the conversion to Bool: +# convert(::Type{Bool}, x::Real) = x==0 ? false : x==1 ? true : throw(InexactError()) +# they're used to pre-emptively check in bulk when possible, which is much faster. +# Also, the functions can be overloaded for custom types T<:Real : +# a) in the unlikely eventuality that they use a different logic for Bool conversion +# b) to skip the check if not necessary +@inline try_bool_conversion(x::Real) = x == 0 || x == 1 || throw(InexactError()) +@inline unchecked_bool_convert(x::Real) = x == 1 + +function copy_to_bitarray_chunks!(Bc::Vector{UInt64}, pos_d::Int, C::StridedArray{<:Real}, pos_s::Int, numbits::Int) + @inbounds for i = (1:numbits) + pos_s - 1 + try_bool_conversion(C[i]) + end + + kd0, ld0 = get_chunks_id(pos_d) + kd1, ld1 = get_chunks_id(pos_d + numbits - 1) + + delta_kd = kd1 - kd0 + + u = _msk64 + if delta_kd == 0 + msk_d0 = msk_d1 = ~(u << ld0) | (u << (ld1+1)) + lt0 = ld1 + else + msk_d0 = ~(u << ld0) + msk_d1 = (u << (ld1+1)) + lt0 = 63 + end + + bind = kd0 + ind = pos_s + @inbounds if ld0 > 0 + c = UInt64(0) + for j = ld0:lt0 + c |= (UInt64(unchecked_bool_convert(C[ind])) << j) + ind += 1 + end + Bc[kd0] = (Bc[kd0] & msk_d0) | (c & ~msk_d0) + bind += 1 + end + + nc = _div64(numbits - ind + pos_s) + @inbounds for i = 1:nc + c = UInt64(0) + for j = 0:63 + c |= (UInt64(unchecked_bool_convert(C[ind])) << j) + ind += 1 + end + Bc[bind] = c + bind += 1 + end + + @inbounds if bind ≤ kd1 + @assert bind == kd1 + c = UInt64(0) + for j = 0:ld1 + c |= (UInt64(unchecked_bool_convert(C[ind])) << j) + ind += 1 + end + Bc[kd1] = (Bc[kd1] & msk_d1) | (c & ~msk_d1) + end +end + # contiguous multidimensional indexing: if the first dimension is a range, # we can get some performance from using copy_chunks! -@inline function setindex!(B::BitArray, X::Union{BitArray,Array}, J0::Union{Colon,UnitRange{Int}}) +@inline function setindex!(B::BitArray, X::StridedArray, J0::Union{Colon,UnitRange{Int}}) I0 = to_indices(B, (J0,))[1] @boundscheck checkbounds(B, I0) l0 = length(I0) @@ -971,13 +1045,13 @@ end return B end -@inline function setindex!(B::BitArray, X::Union{BitArray,Array}, +@inline function setindex!(B::BitArray, X::StridedArray, I0::Union{Colon,UnitRange{Int}}, I::Union{Int,UnitRange{Int},Colon}...) J = to_indices(B, (I0, I...)) @boundscheck checkbounds(B, J...) _unsafe_setindex!(B, X, J...) end -@generated function _unsafe_setindex!(B::BitArray, X::Union{BitArray,Array}, +@generated function _unsafe_setindex!(B::BitArray, X::StridedArray, I0::Union{Slice,UnitRange{Int}}, I::Union{Int,UnitRange{Int},Slice}...) N = length(I) quote diff --git a/test/arrayops.jl b/test/arrayops.jl index b0c016417b02d..37c91750830b6 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -834,6 +834,8 @@ end @test isequal(c[1,:], cv2) @test isequal(c[3,:], cv) @test isequal(c[:,4], [2.0,2.0,2.0,2.0]*1000) + + @test repeat(BitMatrix(eye(2)), inner = (2,1), outer = (1,2)) == repeat(eye(2), inner = (2,1), outer = (1,2)) end @testset "indexing with bools" begin diff --git a/test/bitarray.jl b/test/bitarray.jl index 8fa43dde99793..32bbacfc197bf 100644 --- a/test/bitarray.jl +++ b/test/bitarray.jl @@ -231,7 +231,9 @@ timesofar("constructors") x = rand(Bool) @check_bit_operation setindex!(b1, x, 1:j) T b2 = bitrand(j) - @check_bit_operation setindex!(b1, b2, 1:j) T + for bb in (b2, view(b2, 1:j), view(Array{Any}(b2), :)) + @check_bit_operation setindex!(b1, bb, 1:j) T + end x = rand(Bool) @check_bit_operation setindex!(b1, x, j+1:l) T b2 = bitrand(l-j) @@ -381,7 +383,9 @@ timesofar("constructors") for (b2, k1, k2) in Channel(gen_setindex_data) # println(typeof(b2), " ", typeof(k1), " ", typeof(k2)) # uncomment to debug - @check_bit_operation setindex!(b1, b2, k1, k2) BitMatrix + for bb in ((b2 isa AbstractArray) ? (b2, view(b2, :), view(Array{Any}(b2), :)) : (b2,)) + @check_bit_operation setindex!(b1, bb, k1, k2) BitMatrix + end end m1, m2 = rand_m1m2() From c49908c27f2d3169f76738b3e9f8f17d5578625f Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 23 Feb 2017 16:59:56 -0500 Subject: [PATCH 0060/1534] fix bug where non-tuple types were shown as `NTuple` --- base/show.jl | 5 +++-- test/show.jl | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/base/show.jl b/base/show.jl index 35c69995f43c6..8d50d51e69269 100644 --- a/base/show.jl +++ b/base/show.jl @@ -211,11 +211,12 @@ end show(io::IO, x::DataType) = show_datatype(io, x) function show_datatype(io::IO, x::DataType) - if (!isempty(x.parameters) || x.name === Tuple.name) && x !== Tuple + istuple = x.name === Tuple.name + if (!isempty(x.parameters) || istuple) && x !== Tuple n = length(x.parameters) # Print homogeneous tuples with more than 3 elements compactly as NTuple{N, T} - if n > 3 && all(i -> (x.parameters[1] === i), x.parameters) + if istuple && n > 3 && all(i -> (x.parameters[1] === i), x.parameters) print(io, "NTuple{", n, ',', x.parameters[1], "}") else show(io, x.name) diff --git a/test/show.jl b/test/show.jl index 9776ab2da7b50..8f80e058be12b 100644 --- a/test/show.jl +++ b/test/show.jl @@ -646,3 +646,7 @@ let d = TextDisplay(IOBuffer()) @test e.f == show end end + +struct TypeWith4Params{a,b,c,d} +end +@test endswith(string(TypeWith4Params{Int8,Int8,Int8,Int8}), "TypeWith4Params{Int8,Int8,Int8,Int8}") From 391c7441946ac2a1c591394b68505cfaa7d750f3 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 23 Feb 2017 23:12:04 -0500 Subject: [PATCH 0061/1534] fix error reporting from `julia_to_scm` In this context we need to throw flisp errors instead of julia errors. This was causing corruption, plus error expressions got replaced with `invalid syntax` errors. --- src/ast.c | 10 +++++----- src/julia-syntax.scm | 2 ++ test/parse.jl | 9 ++++++++- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/ast.c b/src/ast.c index fc65ae4b44147..28d871ecf8407 100644 --- a/src/ast.c +++ b/src/ast.c @@ -663,7 +663,7 @@ static value_t julia_to_scm(fl_context_t *fl_ctx, jl_value_t *v) temp = julia_to_scm_(fl_ctx, v); } FL_CATCH_EXTERN(fl_ctx) { - temp = fl_list2(fl_ctx, jl_ast_ctx(fl_ctx)->error_sym, cvalue_static_cstring(fl_ctx, "expression too large")); + temp = fl_ctx->lasterror; } return temp; } @@ -671,7 +671,7 @@ static value_t julia_to_scm(fl_context_t *fl_ctx, jl_value_t *v) static void array_to_list(fl_context_t *fl_ctx, jl_array_t *a, value_t *pv) { if (jl_array_len(a) > 300000) - lerror(fl_ctx, fl_ctx->OutOfMemoryError, "expression too large"); + lerror(fl_ctx, symbol(fl_ctx, "error"), "expression too large"); value_t temp; for(long i=jl_array_len(a)-1; i >= 0; i--) { *pv = fl_cons(fl_ctx, fl_ctx->NIL, *pv); @@ -694,7 +694,7 @@ static value_t julia_to_list2(fl_context_t *fl_ctx, jl_value_t *a, jl_value_t *b static value_t julia_to_scm_(fl_context_t *fl_ctx, jl_value_t *v) { if (v == NULL) - jl_error("undefined reference in AST"); + lerror(fl_ctx, symbol(fl_ctx, "error"), "undefined reference in AST"); if (jl_is_symbol(v)) return symbol(fl_ctx, jl_symbol_name((jl_sym_t*)v)); if (v == jl_true) @@ -749,9 +749,9 @@ static value_t julia_to_scm_(fl_context_t *fl_ctx, jl_value_t *v) if (jl_is_long(v) && fits_fixnum(jl_unbox_long(v))) return fixnum(jl_unbox_long(v)); if (jl_is_ssavalue(v)) - jl_error("SSAValue objects should not occur in an AST"); + lerror(fl_ctx, symbol(fl_ctx, "error"), "SSAValue objects should not occur in an AST"); if (jl_is_slot(v)) - jl_error("Slot objects should not occur in an AST"); + lerror(fl_ctx, symbol(fl_ctx, "error"), "Slot objects should not occur in an AST"); value_t opaque = cvalue(fl_ctx, jl_ast_ctx(fl_ctx)->jvtype, sizeof(void*)); *(jl_value_t**)cv_data((cvalue_t*)ptr(opaque)) = v; return opaque; diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index b8caa322685bb..ea2028a3debb0 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -3559,6 +3559,8 @@ f(x) = yt(x) '(null))) ((...) (error "\"...\" expression outside call")) + ((error) + (error (cadr e))) (else (error (string "invalid syntax " (deparse e))))))) ;; introduce new slots for assigned arguments diff --git a/test/parse.jl b/test/parse.jl index d8c5c3e539b04..798e984517dcd 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -1032,4 +1032,11 @@ macro m20729() return ex end -@test_throws ErrorException expand(:(@m20729)) +@test_throws ErrorException eval(:(@m20729)) +@test expand(:(@m20729)) == Expr(:error, "undefined reference in AST") + +macro err20000() + return Expr(:error, "oops!") +end + +@test expand(:(@err20000)) == Expr(:error, "oops!") From dfe2dfb2e01a039b696d8530be43d3aef4e20e64 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 23 Feb 2017 23:14:39 -0500 Subject: [PATCH 0062/1534] fix #20000, parsing of parameter syntax in macro calls: `@m(a; b=c)` --- src/julia-parser.scm | 45 ++++++++++++++++++++------------------------ test/parse.jl | 4 ++++ 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 0a0633a3fbcb3..53786f4fbc6b5 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -1020,27 +1020,24 @@ ((#\( ) (if (ts:space? s) (disallowed-space ex t)) (take-token s) - (if macrocall? - (let ((args (if (eqv? (require-token s) #\) ) - (begin (take-token s) '()) - (begin0 (with-normal-ops - (with-whitespace-newline - (parse-comma-separated s parse-eq* #t))) - (if (not (eqv? (require-token s) #\) )) - (error "missing ) in argument list")) - (take-token s))))) - `(call ,ex ,@args)) - (loop (let ((al (parse-arglist s #\) ))) - (receive - (params args) (separate (lambda (x) - (and (pair? x) - (eq? (car x) 'parameters))) - al) - (if (eq? (peek-token s) 'do) - (begin - (take-token s) - `(call ,ex ,@params ,(parse-do s) ,@args)) - `(call ,ex ,@al))))))) + (let ((c (let ((al (parse-arglist s #\) ))) + (receive + (params args) (separate (lambda (x) + (and (pair? x) + (eq? (car x) 'parameters))) + al) + (if (eq? (peek-token s) 'do) + (begin + (take-token s) + `(call ,ex ,@params ,(parse-do s) ,@args)) + `(call ,ex ,@al)))))) + (if macrocall? + (map (lambda (x) ;; parse `a=b` as `=` instead of `kw` in macrocall + (if (and (pair? x) (eq? (car x) 'kw)) + `(= ,@(cdr x)) + x)) + c) + (loop c)))) ((#\[ ) (if (ts:space? s) (disallowed-space ex t)) (take-token s) @@ -1473,15 +1470,13 @@ `(,word ,@(reverse path))))))) ;; parse comma-separated assignments, like "i=1:n,j=1:m,..." -(define (parse-comma-separated s what (in-parens #f)) +(define (parse-comma-separated s what) (let loop ((exprs '())) (let ((r (what s))) (case (peek-token s) ((#\,) (take-token s) - (if (and in-parens (eqv? (require-token s) #\) )) - (reverse! (cons r exprs)) - (loop (cons r exprs)))) + (loop (cons r exprs))) (else (reverse! (cons r exprs))))))) (define (parse-comma-separated-assignments s) diff --git a/test/parse.jl b/test/parse.jl index 798e984517dcd..7fbda2b1f1317 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -1040,3 +1040,7 @@ macro err20000() end @test expand(:(@err20000)) == Expr(:error, "oops!") + +# issue #20000 +@test parse("@m(a; b=c)") == Expr(:macrocall, Symbol("@m"), + Expr(:parameters, Expr(:kw, :b, :c)), :a) From 0dca5940ee905b29a9138799910f46aa17eaff33 Mon Sep 17 00:00:00 2001 From: Stefan Karpinski Date: Fri, 24 Feb 2017 03:30:44 -0500 Subject: [PATCH 0063/1534] hashing of general objects was far too simple (fixes #20744) (#20767) * hashing of general objects was far too simple (fixes #20744) * hash_uint(3h - object_id(x)) is a somewhat better hash If we'd used `3h - object_id(x)` previously, the original issue would never have come up since `hash(a, hash(b, hash(c, h)))` wouldn't have produced `3A - 3B + 3C - h` but would instead have given the value `27h -9A - 3B - C`, which is asymmetrical in `a` and `c`. Passing the result to `hash_uint` fixes that issue since that function is non-linear, but defense in depth, right? We may as well do the same operations in such a way that the passed-through value gets the most operations done on it. --- base/hashing.jl | 3 +-- test/hashing.jl | 3 +++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/base/hashing.jl b/base/hashing.jl index 8e83b21d8ecf3..2417124bef64a 100644 --- a/base/hashing.jl +++ b/base/hashing.jl @@ -7,7 +7,7 @@ hash(w::WeakRef, h::UInt) = hash(w.value, h) ## hashing general objects ## -hash(x::ANY, h::UInt) = 3*object_id(x) - h +hash(x::ANY, h::UInt) = hash_uint(3h - object_id(x)) ## core data hashing functions ## @@ -55,7 +55,6 @@ end ## symbol & expression hashing ## -hash(x::Symbol, h::UInt) = 3*object_id(x) - h if UInt === UInt64 hash(x::Expr, h::UInt) = hash(x.args, hash(x.head, h + 0x83c7900696d26dc6)) else diff --git a/test/hashing.jl b/test/hashing.jl index 60da16201cfe9..82be0e4c7dffd 100644 --- a/test/hashing.jl +++ b/test/hashing.jl @@ -117,3 +117,6 @@ for prec in [3, 11, 15, 16, 31, 32, 33, 63, 64, 65, 254, 255, 256, 257, 258, 102 @test isequal(x, y) end end + +# issue #20744 +@test hash(:c, hash(:b, hash(:a))) != hash(:a, hash(:b, hash(:c))) From 078835c1c1a10164e376a9bcd4b7df1bd72070a8 Mon Sep 17 00:00:00 2001 From: Fengyang Wang Date: Fri, 24 Feb 2017 09:15:05 -0500 Subject: [PATCH 0064/1534] Document rounding away from zero (#20775) --- base/printf.jl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/base/printf.jl b/base/printf.jl index 754e91276b176..738b758400f44 100644 --- a/base/printf.jl +++ b/base/printf.jl @@ -1196,7 +1196,9 @@ end Print `args` using C `printf()` style format specification string, with some caveats: `Inf` and `NaN` are printed consistently as `Inf` and `NaN` for flags `%a`, `%A`, -`%e`, `%E`, `%f`, `%F`, `%g`, and `%G`. +`%e`, `%E`, `%f`, `%F`, `%g`, and `%G`. Furthermore, if a floating point number is +equally close to the numeric values of two possible output strings, the output +string further away from zero is chosen. Optionally, an `IOStream` may be passed as the first argument to redirect output. @@ -1206,6 +1208,9 @@ may be passed as the first argument to redirect output. ```jldoctest julia> @printf("%f %F %f %F\\n", Inf, Inf, NaN, NaN) Inf Inf NaN NaN\n + +julia> @printf "%.0f %.1f %f\\n" 0.5 0.025 -0.0078125 +1 0.0 -0.007813 ``` """ macro printf(args...) From 00b7b606d82c36461d448a2a7b59475235199acf Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Fri, 24 Feb 2017 09:40:37 -0600 Subject: [PATCH 0065/1534] Handle systems where `hostname` is unavailable (#20765) * Handle systems where `hostname` is unavailable Fixes #20758 * Comment on hostname regex * Fix grammar --- test/libgit2.jl | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/test/libgit2.jl b/test/libgit2.jl index 4ee3480687840..81df89d8b1ff1 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -1020,18 +1020,25 @@ mktempdir() do dir end # Find a hostname that maps to the loopback address - hostname = replace(readchomp(`hostname`), r"\..*$", "") - loopback = ip"127.0.0.1" + hostnames = ["localhost"] - for host in (hostname, "localhost") + # In minimal environments a hostname might not be available (issue #20758) + try + # In some environments, namely Macs, the hostname "macbook.local" is bound + # to the external address while "macbook" is bound to the loopback address. + unshift!(hostnames, replace(gethostname(), r"\..*$", "")) + end + + loopback = ip"127.0.0.1" + for hostname in hostnames try - addr = getaddrinfo(host) + addr = getaddrinfo(hostname) catch continue end if addr == loopback - common_name = host + common_name = hostname break end end From dce17b6583db3ae718783b1c4536652de063248e Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 31 Jan 2017 14:53:29 -0500 Subject: [PATCH 0066/1534] fix #20332, `MethodInstance` display error --- base/show.jl | 12 ++++++------ test/show.jl | 13 +++++++++++++ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/base/show.jl b/base/show.jl index 8d50d51e69269..340da4bd02c4e 100644 --- a/base/show.jl +++ b/base/show.jl @@ -1039,12 +1039,12 @@ function show_lambda_types(io::IO, li::Core.MethodInstance) returned_from_do = true return end - sig = li.specTypes.parameters - ft = sig[1] - if ft <: Function && isempty(ft.parameters) && - isdefined(ft.name.module, ft.name.mt.name) && - ft == typeof(getfield(ft.name.module, ft.name.mt.name)) - print(io, ft.name.mt.name) + sig = unwrap_unionall(li.specTypes).parameters + ft = sig[1]; uw = unwrap_unionall(ft) + if ft <: Function && isa(uw,DataType) && isempty(uw.parameters) && + isdefined(uw.name.module, uw.name.mt.name) && + ft == typeof(getfield(uw.name.module, uw.name.mt.name)) + print(io, uw.name.mt.name) elseif isa(ft, DataType) && ft.name === Type.body.name && isleaftype(ft) f = ft.parameters[1] print(io, f) diff --git a/test/show.jl b/test/show.jl index 8f80e058be12b..819e559a95604 100644 --- a/test/show.jl +++ b/test/show.jl @@ -650,3 +650,16 @@ end struct TypeWith4Params{a,b,c,d} end @test endswith(string(TypeWith4Params{Int8,Int8,Int8,Int8}), "TypeWith4Params{Int8,Int8,Int8,Int8}") + +# issues #20332 and #20781 +struct T20332{T} +end + +(::T20332{T})(x) where T = 0 + +let m = which(T20332{Int}(), (Int,)), + mi = ccall(:jl_specializations_get_linfo, Ref{Core.MethodInstance}, (Any, Any, Any, UInt), + m, Tuple{T20332{T}, Int} where T, Core.svec(), typemax(UInt)) + # test that this doesn't throw an error + @test contains(repr(mi), "MethodInstance for") +end From d321300c571051cad81f90e3a39dd381aa58e2fb Mon Sep 17 00:00:00 2001 From: H-225 Date: Fri, 24 Feb 2017 17:19:36 +0000 Subject: [PATCH 0067/1534] Improve UX of calling abstract-type constructors (#20596) * Make calling abstract type with only sysimg method display a more specific message * Do not show the Base/sysimg.jl method for Type{T} in tab-completion * Hide sysimg.jl method from closest candidates * Better type name in tests * Remove line number of sysimg.jl method from tests * Fix tests not checking for qualified names of the type * *Actually* add a test for qualified abstract types * Improve tests - Wrap long lines. - Make them easier to follow. - Fix test for tab-completion * Should be checking if the method string *starts with* the sample, and not `!=` to it. * Refactor sysimg method check * Add a comment to the sysimg.jl method for clarity * Cleanup `is_default_method` * Fix tests; well that was easy... - since the 'default' method from sysimg.jl is now hidden, there was one less method candidate, and therefore exactly three, and therefore, no elipsis anymore. - removed duplicate test for error message displayed for a MethodError on an abstract type without any constructors defined. * Add comments to the tests; make them easier to understand * Update doctests that fail due to now-hidden sysimg.jl default method * Fix rogue syntax error with '&&' * Use @test instead of @assert * Fix use of old unfactored code --- base/REPLCompletions.jl | 8 +++++- base/replutil.jl | 23 +++++++++++++++ base/sysimg.jl | 2 +- doc/src/manual/constructors.md | 3 -- doc/src/manual/types.md | 1 - test/replutil.jl | 51 +++++++++++++++++++++++++++------- 6 files changed, 72 insertions(+), 16 deletions(-) diff --git a/base/REPLCompletions.jl b/base/REPLCompletions.jl index 971a78a32fa02..1d5adf2f81ee6 100644 --- a/base/REPLCompletions.jl +++ b/base/REPLCompletions.jl @@ -330,8 +330,14 @@ function complete_methods(ex_org::Expr) kwtype = isdefined(ml.mt, :kwsorter) ? Nullable{DataType}(typeof(ml.mt.kwsorter)) : Nullable{DataType}() io = IOBuffer() for method in ml - # Check if the method's type signature intersects the input types ms = method.sig + + # Do not suggest the default method from sysimg.jl. + if Base.is_default_method(method) + continue + end + + # Check if the method's type signature intersects the input types if typeintersect(Base.rewrap_unionall(Tuple{Base.unwrap_unionall(ms).parameters[1 : min(na, end)]...}, ms), t_in) != Union{} show(io, method, kwtype=kwtype) push!(out, String(take!(io))) diff --git a/base/replutil.jl b/base/replutil.jl index dd771314b02e1..3c6a7f412b382 100644 --- a/base/replutil.jl +++ b/base/replutil.jl @@ -323,6 +323,18 @@ function showerror(io::IO, ex::MethodError) f_is_function = true print(io, "no method matching ", name) elseif isa(f, Type) + if isa(f, DataType) && f.abstract + # Print a more appropriate message if the only method + # on the type is the default one from sysimg.jl. + ms = methods(f) + if length(ms) == 1 + m = first(ms) + if Base.is_default_method(m) + print(io, "no constructors have been defined for $f") + return + end + end + end print(io, "no method matching ", f) else print(io, "no method matching (::", ft, ")") @@ -445,6 +457,9 @@ function show_method_candidates(io::IO, ex::MethodError, kwargs::Vector=Any[]) buf = IOBuffer() tv = Any[] sig0 = method.sig + if Base.is_default_method(method) + continue + end while isa(sig0, UnionAll) push!(tv, sig0.var) sig0 = sig0.body @@ -651,3 +666,11 @@ function process_backtrace(process_func::Function, t::Vector, limit::Int=typemax process_func(last_frame, n) end end + +""" +Determines whether a method is the default method which is provided to all types from sysimg.jl. +Such a method is usually undesirable to be displayed to the user in the REPL. +""" +function is_default_method(m::Method) + return m.module == Base && m.file == Symbol("sysimg.jl") && m.sig == Tuple{Type{T},Any} where T +end diff --git a/base/sysimg.jl b/base/sysimg.jl index 602c1acdabf59..b6f5beed2d5e6 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -21,7 +21,7 @@ include("coreio.jl") eval(x) = Core.eval(Base, x) eval(m, x) = Core.eval(m, x) -(::Type{T}){T}(arg) = convert(T, arg)::T +(::Type{T}){T}(arg) = convert(T, arg)::T # Hidden from the REPL. (::Type{VecElement{T}}){T}(arg) = VecElement{T}(convert(T, arg)) convert{T<:VecElement}(::Type{T}, arg) = T(arg) convert{T<:VecElement}(::Type{T}, arg::T) = arg diff --git a/doc/src/manual/constructors.md b/doc/src/manual/constructors.md index c4eaa53d6820b..79290ff5f7289 100644 --- a/doc/src/manual/constructors.md +++ b/doc/src/manual/constructors.md @@ -293,7 +293,6 @@ Point{Float64}(1.0, 2.5) julia> Point(1,2.5) ## implicit T ## ERROR: MethodError: no method matching Point(::Int64, ::Float64) Closest candidates are: - Point(::Any) where T at sysimg.jl:24 Point(::T<:Real, !Matched::T<:Real) where T<:Real at none:2 julia> Point{Int64}(1, 2) ## explicit T ## @@ -374,7 +373,6 @@ However, other similar calls still don't work: julia> Point(1.5,2) ERROR: MethodError: no method matching Point(::Float64, ::Int64) Closest candidates are: - Point(::Any) where T at sysimg.jl:24 Point(::T<:Real, !Matched::T<:Real) where T<:Real at none:1 ``` @@ -572,7 +570,6 @@ julia> SummedArray(Int32[1; 2; 3], Int32(6)) ERROR: MethodError: no method matching SummedArray(::Array{Int32,1}, ::Int32) Closest candidates are: SummedArray(::Array{T,1}) where T at none:5 - SummedArray(::Any) where T at sysimg.jl:24 ``` This constructor will be invoked by the syntax `SummedArray(a)`. The syntax `new{T,S}` allows diff --git a/doc/src/manual/types.md b/doc/src/manual/types.md index 3fc827684a6e1..f4a2851c384cf 100644 --- a/doc/src/manual/types.md +++ b/doc/src/manual/types.md @@ -680,7 +680,6 @@ to `Point` have the same type. When this isn't the case, the constructor will fa julia> Point(1,2.5) ERROR: MethodError: no method matching Point(::Int64, ::Float64) Closest candidates are: - Point(::Any) where T at sysimg.jl:24 Point(::T, !Matched::T) where T at none:2 ``` diff --git a/test/replutil.jl b/test/replutil.jl index aa113c5258a24..84b299460320d 100644 --- a/test/replutil.jl +++ b/test/replutil.jl @@ -20,6 +20,7 @@ method_c1(x::Float64, s::AbstractString...) = true buf = IOBuffer() Base.show_method_candidates(buf, Base.MethodError(method_c1,(1, 1, ""))) no_color = "\nClosest candidates are:\n method_c1(!Matched::Float64, !Matched::AbstractString...)$cfile$c1line" +@test length(methods(method_c1)) <= 3 # because of '...' in candidate printing test_have_color(buf, "\e[0m\nClosest candidates are:\n method_c1(\e[1m\e[31m::Float64\e[0m, \e[1m\e[31m::AbstractString...\e[0m)$cfile$c1line\e[0m", no_color) @@ -102,12 +103,12 @@ PR16155line2 = @__LINE__ + 1 (::Type{T}){T<:PR16155}(arg::Any) = "replace call-to-convert method from sysimg" Base.show_method_candidates(buf, MethodError(PR16155,(1.0, 2.0, Int64(3)))) -test_have_color(buf, "\e[0m\nClosest candidates are:\n $(curmod_prefix)PR16155(::Any, ::Any)$cfile$PR16155line\n $(curmod_prefix)PR16155(\e[1m\e[31m::Int64\e[0m, ::Any)$cfile$PR16155line\n $(curmod_prefix)PR16155(::Any) where T<:$(curmod_prefix)PR16155$cfile$PR16155line2\n ...\e[0m", - "\nClosest candidates are:\n $(curmod_prefix)PR16155(::Any, ::Any)$cfile$PR16155line\n $(curmod_prefix)PR16155(!Matched::Int64, ::Any)$cfile$PR16155line\n $(curmod_prefix)PR16155(::Any) where T<:$(curmod_prefix)PR16155$cfile$PR16155line2\n ...") +test_have_color(buf, "\e[0m\nClosest candidates are:\n $(curmod_prefix)PR16155(::Any, ::Any)$cfile$PR16155line\n $(curmod_prefix)PR16155(\e[1m\e[31m::Int64\e[0m, ::Any)$cfile$PR16155line\n $(curmod_prefix)PR16155(::Any) where T<:$(curmod_prefix)PR16155$cfile$PR16155line2\e[0m", + "\nClosest candidates are:\n $(curmod_prefix)PR16155(::Any, ::Any)$cfile$PR16155line\n $(curmod_prefix)PR16155(!Matched::Int64, ::Any)$cfile$PR16155line\n $(curmod_prefix)PR16155(::Any) where T<:$(curmod_prefix)PR16155$cfile$PR16155line2") Base.show_method_candidates(buf, MethodError(PR16155,(Int64(3), 2.0, Int64(3)))) -test_have_color(buf, "\e[0m\nClosest candidates are:\n $(curmod_prefix)PR16155(::Int64, ::Any)$cfile$PR16155line\n $(curmod_prefix)PR16155(::Any, ::Any)$cfile$PR16155line\n $(curmod_prefix)PR16155(::Any) where T<:$(curmod_prefix)PR16155$cfile$PR16155line2\n ...\e[0m", - "\nClosest candidates are:\n $(curmod_prefix)PR16155(::Int64, ::Any)$cfile$PR16155line\n $(curmod_prefix)PR16155(::Any, ::Any)$cfile$PR16155line\n $(curmod_prefix)PR16155(::Any) where T<:$(curmod_prefix)PR16155$cfile$PR16155line2\n ...") +test_have_color(buf, "\e[0m\nClosest candidates are:\n $(curmod_prefix)PR16155(::Int64, ::Any)$cfile$PR16155line\n $(curmod_prefix)PR16155(::Any, ::Any)$cfile$PR16155line\n $(curmod_prefix)PR16155(::Any) where T<:$(curmod_prefix)PR16155$cfile$PR16155line2\e[0m", + "\nClosest candidates are:\n $(curmod_prefix)PR16155(::Int64, ::Any)$cfile$PR16155line\n $(curmod_prefix)PR16155(::Any, ::Any)$cfile$PR16155line\n $(curmod_prefix)PR16155(::Any) where T<:$(curmod_prefix)PR16155$cfile$PR16155line2") c6line = @__LINE__ method_c6(; x=1) = x @@ -252,12 +253,6 @@ let @test contains(err_str, "column vector") end -abstract type T11007 end -let - err_str = @except_str T11007() MethodError - @test contains(err_str, "no method matching $(curmod_prefix)T11007()") -end - struct TypeWithIntParam{T <: Integer} end let undefvar err_str = @except_strbt sqrt(-1) DomainError @@ -499,3 +494,39 @@ foo_9965(x::Int) = 2x Base.show_method_candidates(io, ex, [(:w,true)]) @test contains(String(take!(io)), "got unsupported keyword argument \"w\"") end + +# Issue #20556 +module EnclosingModule + abstract type AbstractTypeNoConstructors end +end +let + method_error = MethodError(EnclosingModule.AbstractTypeNoConstructors, ()) + + # Test that it shows a special message when no constructors have been defined by the user. + @test sprint( + showerror, + method_error + ) == "MethodError: no constructors have been defined for $(EnclosingModule.AbstractTypeNoConstructors)" + + # Does it go back to previous behaviour when there *is* at least + # one constructor defined? + EnclosingModule.AbstractTypeNoConstructors(x, y) = x + y + @test startswith(sprint( + showerror, + method_error + ), "MethodError: no method matching $(EnclosingModule.AbstractTypeNoConstructors)()" + ) + + # Test that the 'default' sysimg.jl method is not displayed. + @test !contains(sprint( + showerror, + method_error + ), + "where T at sysimg.jl" + ) + + # Test that tab-completion will not show the 'default' sysimg.jl method. + for method_string in Base.REPLCompletions.complete_methods(:(EnclosingModule.AbstractTypeNoConstructors())) + @test !startswith(method_string, "(::Type{T})(arg) where T in Base at sysimg.jl") + end +end From a7816f5e5d0d0da02cec2559565c91dc3905087a Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sun, 12 Feb 2017 13:40:25 -0500 Subject: [PATCH 0068/1534] remove `map` method for `Vector{Any}` --- base/essentials.jl | 2 -- base/inference.jl | 9 ++++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/base/essentials.jl b/base/essentials.jl index 469e865bb2f1b..04f7850dec228 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -183,8 +183,6 @@ end # simple Array{Any} operations needed for bootstrap setindex!(A::Array{Any}, x::ANY, i::Int) = Core.arrayset(A, x, i) -map(f::Function, a::Array{Any,1}) = Any[ f(a[i]) for i=1:length(a) ] - function precompile(f::ANY, args::Tuple) ccall(:jl_compile_hint, Int32, (Any,), Tuple{Core.Typeof(f), args...}) != 0 end diff --git a/base/inference.jl b/base/inference.jl index a1001e131e43e..857b3f2345179 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -322,6 +322,8 @@ function contains_is(itr, x::ANY) return false end +anymap(f::Function, a::Array{Any,1}) = Any[ f(a[i]) for i=1:length(a) ] + _topmod(sv::InferenceState) = _topmod(sv.mod) _topmod(m::Module) = ccall(:jl_base_relative_to, Any, (Any,), m)::Module @@ -670,7 +672,8 @@ function limit_type_depth(t::ANY, d::Int, cov::Bool, vars::Vector{TypeVar}=TypeV if d > MAX_TYPE_DEPTH return Any end - return Union{map(x->limit_type_depth(x, d+1, cov, vars), (t.a,t.b))...} + return Union{limit_type_depth(t.a, d+1, cov, vars), + limit_type_depth(t.b, d+1, cov, vars)} elseif isa(t,UnionAll) v = t.var if v.ub === Any @@ -1084,7 +1087,7 @@ function builtin_tfunction(f::ANY, argtypes::Array{Any,1}, sv::InferenceState) return tuple_tfunc(limit_tuple_depth(sv.params, argtypes_to_type(argtypes))) end end - return Const(tuple(map(a->a.val, argtypes)...)) + return Const(tuple(anymap(a->a.val, argtypes)...)) elseif f === svec return SimpleVector elseif f === arrayset @@ -1574,7 +1577,7 @@ function pure_eval_call(f::ANY, argtypes::ANY, atype::ANY, vtypes::VarTable, sv: end end -argtypes_to_type(argtypes::Array{Any,1}) = Tuple{map(widenconst, argtypes)...} +argtypes_to_type(argtypes::Array{Any,1}) = Tuple{anymap(widenconst, argtypes)...} _Pair_name = nothing function Pair_name() From f6f7d8a7b58d80cb10af617586dd01f1754ab23d Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Tue, 21 Feb 2017 10:15:51 -0800 Subject: [PATCH 0069/1534] Remove deprecated array/vectorized operators/functions from the manual. Also revise that section. [ci skip] --- doc/src/manual/arrays.md | 45 ++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/doc/src/manual/arrays.md b/doc/src/manual/arrays.md index 017a2252817c1..d2dd09906b16f 100644 --- a/doc/src/manual/arrays.md +++ b/doc/src/manual/arrays.md @@ -519,35 +519,36 @@ Base.IndexStyle{T<:MyArray}(::Type{T}) = IndexLinear() This setting will cause `eachindex` iteration over a `MyArray` to use integers. If you don't specify this trait, the default value `IndexCartesian()` is used. -### Vectorized Operators and Functions +### Array and Vectorized Operators and Functions -The following operators are supported for arrays. Also, *every* binary -operator supports a [dot version](@ref man-dot-operators) that can be -applied to arrays (and combinations of arrays and scalars) as a -[fused broadcasting operation](@ref man-vectorized). (For comparison -operations like `<`, *only* the `.<` version is applicable to arrays.) +The following operators are supported for arrays: -1. Unary arithmetic -- `-`, `+`, `!` -2. Binary arithmetic -- `+`, `-`, `*`, `/`, `\`, `^`, `.^`, `div`, `mod` +1. Unary arithmetic -- `-`, `+` +2. Binary arithmetic -- `-`, `+`, `*`, `/`, `\`, `^` 3. Comparison -- `==`, `!=`, `≈` ([`isapprox`](@ref)), `≉` -4. Unary Boolean or bitwise -- `~` -5. Binary Boolean or bitwise -- `&`, `|`, `⊻` ([`xor`](@ref)) -Some operators without dots operate elementwise anyway when one argument is a scalar: -`*`, `+`, `-`, and the bitwise operators. The operators `/` and `\` operate elementwise when -the denominator is a scalar. +Most of the binary arithmetic operators listed above also operate elementwise +when one argument is scalar: `-`, `+`, and `*` when either argument is scalar, +and `/` and `\` when the denominator is scalar. For example, `[1, 2] + 3 == [4, 5]` +and `[6, 4] / 2 == [3, 2]`. -Note that comparisons such as `==` operate on whole arrays, giving a single boolean answer. Use -dot operators like `.==` for elementwise comparisons. +Additionally, to enable convenient vectorization of mathematical and other operations, +Julia [provides the dot syntax](@ref man-vectorized) `f.(args...)`, e.g. `sin.(x)` +or `min.(x,y)`, for elementwise operations over arrays or mixtures of arrays and +scalars (a [Broadcasting](@ref) operation); these have the additional advantage of +"fusing" into a single loop when combined with other dot calls, e.g. `sin.(cos.(x))`. -To enable convenient vectorization of mathematical and other operations, Julia [provides the compact -syntax](@ref man-vectorized) `f.(args...)`, e.g. `sin.(x)` or `min.(x,y)`, for elementwise operations over arrays or mixtures of arrays and scalars (a [Broadcasting](@ref) operation); these -have the additional advantage of "fusing" into a single loop when combined with -dot operators and other dot calls. +Also, *every* binary operator supports a [dot version](@ref man-dot-operators) +that can be applied to arrays (and combinations of arrays and scalars) in such +[fused broadcasting operations](@ref man-vectorized), e.g. `z .== sin.(x .* y)`. -Note that there is a difference between `max.(a,b)`, which `broadcast`s [`max()`](@ref) elementwise -over `a` and `b`, and `maximum(a)`, which finds the largest value within `a`. The same relationship -holds for `min.(a,b)` and `minimum(a)`. +Note that comparisons such as `==` operate on whole arrays, giving a single boolean +answer. Use dot operators like `.==` for elementwise comparisons. (For comparison +operations like `<`, *only* the elementwise `.<` version is applicable to arrays.) + +Also notice the difference between `max.(a,b)`, which `broadcast`s [`max()`](@ref) +elementwise over `a` and `b`, and `maximum(a)`, which finds the largest value within +`a`. The same relationship holds for `min.(a,b)` and `minimum(a)`. ### Broadcasting From cd65b81db4a5a6094023b81df59b57590c48fd23 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 20 Jan 2017 17:46:33 -0500 Subject: [PATCH 0070/1534] update test/perf code for 0.6 --- test/perf/kernel/bench_eu.jl | 8 ++++---- test/perf/kernel/getdivgrad.jl | 2 +- test/perf/kernel/gk.jl | 2 +- test/perf/kernel/go_benchmark.jl | 10 +++++----- test/perf/perfutil.jl | 6 +++++- 5 files changed, 16 insertions(+), 12 deletions(-) diff --git a/test/perf/kernel/bench_eu.jl b/test/perf/kernel/bench_eu.jl index 287440de2f487..ddc7d61880b51 100644 --- a/test/perf/kernel/bench_eu.jl +++ b/test/perf/kernel/bench_eu.jl @@ -17,11 +17,11 @@ function bench_eu_devec(numPaths) t2 = sigma*sqrt(dt) for i=1:steps for j=1:numPaths - S[j] .*= exp(t1 + t2*randn()) + S[j] *= exp(t1 + t2*randn()) end end - V = mean( exp(-r*T)*max(K.-S,0) ) + V = mean( exp(-r*T)*max.(K.-S,0) ) end function bench_eu_vec(numPaths) @@ -37,8 +37,8 @@ function bench_eu_vec(numPaths) t1 = (r-0.5*sigma.^2)*dt t2 = sigma*sqrt(dt) for i=1:steps - S = S .* exp(t1.+t2*randn(numPaths)) + S = S .* exp.(t1.+t2*randn(numPaths)) end - V = mean( exp(-r*T)*max(K.-S,0) ) + V = mean( exp(-r*T)*max.(K.-S,0) ) end diff --git a/test/perf/kernel/getdivgrad.jl b/test/perf/kernel/getdivgrad.jl index aed68e649bed2..091e40b7712f3 100644 --- a/test/perf/kernel/getdivgrad.jl +++ b/test/perf/kernel/getdivgrad.jl @@ -17,7 +17,7 @@ end #----------------- 1D finite difference on staggered grid function ddx(n) # generate 1D derivatives - return d = spdiags(ones(n)*[-1 1],[0,1],n,n+1) + return d = spdiags(ones(n)*[-1, 1]',[0,1],n,n+1) end #------------- Build a diagonal matrix diff --git a/test/perf/kernel/gk.jl b/test/perf/kernel/gk.jl index 620fb988946dc..ec8126e061eec 100644 --- a/test/perf/kernel/gk.jl +++ b/test/perf/kernel/gk.jl @@ -95,7 +95,7 @@ function gk(n, myeps) U[i] += A[i,k] end - s = sum(p[1:n] .* exp((eps/2)*A[1:n,k])) + s = sum(p[1:n] .* exp.((eps/2)*A[1:n,k])) for i=1:n p[i]=(p[i]*exp((eps/2)*A[i,k])) / s end diff --git a/test/perf/kernel/go_benchmark.jl b/test/perf/kernel/go_benchmark.jl index 8b821bb356d0a..b39383257583d 100644 --- a/test/perf/kernel/go_benchmark.jl +++ b/test/perf/kernel/go_benchmark.jl @@ -29,9 +29,9 @@ function xor_srand(rand::XorRand, seed::UInt32) end function xor_randn(rand::XorRand, n::UInt32) - rand.state $= rand.state << 13 - rand.state $= rand.state >> 17 - rand.state $= rand.state << 5 + rand.state ⊻= rand.state << 13 + rand.state ⊻= rand.state >> 17 + rand.state ⊻= rand.state << 5 rand.state % n end @@ -403,7 +403,7 @@ function compute_final_status(board::Board) # Set the final status of the pos vertex to either black # or white territory. if board.final_status[i, j] == UNKNOWN - if (board.final_status[ai, aj] == ALIVE) $ (board[ai, aj] == WHITE) + if (board.final_status[ai, aj] == ALIVE) ⊻ (board[ai, aj] == WHITE) board.final_status[i, j] = BLACK_TERRITORY else board.final_status[i, j] = WHITE_TERRITORY @@ -425,7 +425,7 @@ function compute_score(board::Board) score -= 1.0 elseif status == WHITE_TERRITORY score += 1.0 - elseif (status == ALIVE) $ (board[i, j] == WHITE) + elseif (status == ALIVE) ⊻ (board[i, j] == WHITE) score -= 1.0 else score += 1.0 diff --git a/test/perf/perfutil.jl b/test/perf/perfutil.jl index da9a627e76d3b..316c1528e9f94 100644 --- a/test/perf/perfutil.jl +++ b/test/perf/perfutil.jl @@ -51,6 +51,10 @@ function submit_to_codespeed(vals,name,desc,unit,test_group,lessisbetter=true) end macro output_timings(t,name,desc,group) + t = esc(t) + name = esc(name) + desc = esc(desc) + group = esc(group) quote # If we weren't given anything for the test group, infer off of file path! test_group = length($group) == 0 ? basename(dirname(Base.source_path())) : $group[1] @@ -77,7 +81,7 @@ macro timeit(ex,name,desc,group...) end i += 1 end - @output_timings t $name $desc $group + @output_timings t $(esc(name)) $(esc(desc)) $(esc(group)) end end From 221b01a2839ca30990cf2b8e90f97ca3ce01ffe4 Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Fri, 24 Feb 2017 21:35:55 +0100 Subject: [PATCH 0071/1534] Bump the stack size for ASAN builds. After #17057, building the system image seems to take significantly more stack space, resulting in a StackOverflowError. --- src/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/init.c b/src/init.c index 7081cf62b56dd..3cc3f04b22dcb 100644 --- a/src/init.c +++ b/src/init.c @@ -139,7 +139,7 @@ static void jl_find_stack_bottom(void) // When using the sanitizers, increase stack size because they bloat // stack usage - const rlim_t kStackSize = 32 * 1024 * 1024; // 32MB stack + const rlim_t kStackSize = 64 * 1024 * 1024; // 64MiB stack int result; result = getrlimit(RLIMIT_STACK, &rl); From 37d788369b8b96dde3670f722c5e591521d68fc8 Mon Sep 17 00:00:00 2001 From: kshyatt Date: Fri, 24 Feb 2017 15:38:08 -0800 Subject: [PATCH 0072/1534] More tests for OID --- test/libgit2.jl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/libgit2.jl b/test/libgit2.jl index 81df89d8b1ff1..823076bcd0742 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -294,7 +294,12 @@ mktempdir() do dir try @test commit_oid1 == LibGit2.GitHash(cmt) short_oid1 = LibGit2.GitShortHash(string(commit_oid1)) - @test cmp(commit_oid1,short_oid1) == 0 + @test hex(commit_oid1) == hex(short_oid1) + @test cmp(commit_oid1, short_oid1) == 0 + @test cmp(short_oid1, commit_oid1) == 0 + @test !(short_oid1 < commit_oid1) + short_str = sprint(show, short_oid1) + @test short_str == "GitShortHash(\"$(string(short_oid1))\")" auth = LibGit2.author(cmt) @test isa(auth, LibGit2.Signature) @test auth.name == test_sig.name From 86b56c3957667fa3c0366f110986377d735bb1e2 Mon Sep 17 00:00:00 2001 From: kshyatt Date: Fri, 24 Feb 2017 15:57:27 -0800 Subject: [PATCH 0073/1534] More tests for tree entries and blob showing --- test/libgit2.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/libgit2.jl b/test/libgit2.jl index 823076bcd0742..bf39916304a3b 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -491,6 +491,9 @@ mktempdir() do dir tree_entry = tree[1] te_str = sprint(show, tree_entry) @test te_str == "GitTreeEntry:\nEntry name: testfile\nEntry type: Base.LibGit2.GitBlob\nEntry OID: $(LibGit2.entryid(tree_entry))\n" + blob = LibGit2.GitBlob(repo, tree_entry) + blob_str = sprint(show, blob) + @test blob_str == "GitBlob:\nBlob id: $(LibGit2.GitHash(blob))\nContents:\n$(LibGit2.content(blob))\n" finally close(repo) end From 21207b7e35fd84817aaf3b40959dd1571329e2f7 Mon Sep 17 00:00:00 2001 From: kshyatt Date: Fri, 24 Feb 2017 16:36:55 -0800 Subject: [PATCH 0074/1534] Tests for showing a GitRef of a branch --- test/libgit2.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/libgit2.jl b/test/libgit2.jl index bf39916304a3b..c110587a0a992 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -344,6 +344,10 @@ mktempdir() do dir @test LibGit2.shortname(brref) == master_branch @test LibGit2.ishead(brref) @test isnull(LibGit2.upstream(brref)) + show_strs = split(sprint(show, brref), "\n") + @test show_strs[1] == "GitReference:" + @test show_strs[2] == "Branch with name refs/heads/master" + @test show_strs[3] == "Branch is HEAD." @test repo.ptr == LibGit2.repository(brref).ptr @test brnch == master_branch @test LibGit2.headname(repo) == master_branch From 6ac7e24cee81068d0d4aad55d75d0dcc1177588e Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Fri, 24 Feb 2017 19:48:50 -0500 Subject: [PATCH 0075/1534] inline x^literal only for hardware-based number types x (closes #20768) (#20782) --- NEWS.md | 2 -- base/intfuncs.jl | 14 ++++++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/NEWS.md b/NEWS.md index 497a94fe39d13..c3f3f47d12b76 100644 --- a/NEWS.md +++ b/NEWS.md @@ -76,8 +76,6 @@ Language changes * Experimental feature: `x^n` for integer literals `n` (e.g. `x^3` or `x^-3`) is now lowered to `x^Val{n}`, to enable compile-time specialization for literal integer exponents ([#20530]). - `x^p` for `x::Number` and a literal `p=0,1,2,3` is now lowered to - `one(x)`, `x`, `x*x`, and `x*x*x`, respectively ([#20648]). Breaking changes ---------------- diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 69c0df7d11c17..bab711aa566c5 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -206,12 +206,18 @@ end @inline ^(x, p) = internal_pow(x, p) @inline internal_pow{p}(x, ::Type{Val{p}}) = x^p +# Restrict inlining to hardware-supported arithmetic types, which +# are fast enough to benefit from inlining. This also makes it +# easier to override ^ without having to override the Val method. +const HWReal = Union{Int8,Int16,Int32,Int64,UInt8,UInt16,UInt32,UInt64,Float32,Float64} +const HWNumber = Union{HWReal, Complex{<:HWReal}, Rational{<:HWReal}} + # inference.jl has complicated logic to inline x^2 and x^3 for # numeric types. In terms of Val we can do it much more simply: -@inline internal_pow(x::Number, ::Type{Val{0}}) = one(x) -@inline internal_pow(x::Number, ::Type{Val{1}}) = x -@inline internal_pow(x::Number, ::Type{Val{2}}) = x*x -@inline internal_pow(x::Number, ::Type{Val{3}}) = x*x*x +@inline internal_pow(x::HWNumber, ::Type{Val{0}}) = one(x) +@inline internal_pow(x::HWNumber, ::Type{Val{1}}) = x +@inline internal_pow(x::HWNumber, ::Type{Val{2}}) = x*x +@inline internal_pow(x::HWNumber, ::Type{Val{3}}) = x*x*x # b^p mod m From 0fe6189bdaff6de76eabdc672256e02021e5310a Mon Sep 17 00:00:00 2001 From: Iblis Lin Date: Sat, 25 Feb 2017 16:22:55 +0800 Subject: [PATCH 0076/1534] socket: fix AF_INET6 value on bsd family --- base/socket.jl | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/base/socket.jl b/base/socket.jl index 421e6fece73d4..37b0ff82762d3 100644 --- a/base/socket.jl +++ b/base/socket.jl @@ -856,11 +856,23 @@ function getsockname(sock::Union{TCPServer,TCPSocket}) uv_error("cannot obtain socket name", r) if r == 0 port = ntoh(rport[]) + af_inet6 = @static if is_windows() # AF_INET6 in + 23 + elseif is_apple() + 30 + elseif Sys.KERNEL ∈ (:FreeBSD, :DragonFly) + 28 + elseif Sys.KERNEL ∈ (:NetBSD, :OpenBSD) + 24 + else + 10 + end + if rfamily[] == 2 # AF_INET addrv4 = raddress[1:4] naddr = ntoh(unsafe_load(Ptr{Cuint}(pointer(addrv4)), 1)) addr = IPv4(naddr) - elseif rfamily[] == @static is_windows() ? 23 : (@static is_apple() ? 30 : 10) # AF_INET6 + elseif rfamily[] == af_inet6 naddr = ntoh(unsafe_load(Ptr{UInt128}(pointer(raddress)), 1)) addr = IPv6(naddr) else From 1a2125e2f6f757598f2db6af1e2e19236d419153 Mon Sep 17 00:00:00 2001 From: Iblis Lin Date: Sat, 25 Feb 2017 16:28:22 +0800 Subject: [PATCH 0077/1534] test/socket: skip udp broadcast testing on bsd --- test/socket.jl | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/test/socket.jl b/test/socket.jl index 9d5421824f04b..fc55c0f82cb35 100644 --- a/test/socket.jl +++ b/test/socket.jl @@ -255,10 +255,14 @@ let end a, b, c = [create_socket() for i = 1:3] try - @sync begin - send(c, bcastdst, 2000, "hello") - recvs = [@async @test String(recv(s)) == "hello" for s in (a, b)] - map(wait, recvs) + # bsd family do not allow broadcasting to ip"255.255.255.255" + # or ip"127.255.255.255" + @static if !is_bsd() || is_apple() + @sync begin + send(c, bcastdst, 2000, "hello") + recvs = [@async @test String(recv(s)) == "hello" for s in (a, b)] + map(wait, recvs) + end end catch e if isa(e, Base.UVError) && Base.uverrorname(e) == "EPERM" From 80b2da8137c71d8d53ce70a6b439fbc06fc05192 Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Sat, 25 Feb 2017 17:13:01 +0100 Subject: [PATCH 0078/1534] Work around Clang 3.9 not being able to compile OpenBLAS. Fixes #18619 --- deps/blas.mk | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/deps/blas.mk b/deps/blas.mk index a907b45d70e1f..d8f2484156ffa 100644 --- a/deps/blas.mk +++ b/deps/blas.mk @@ -46,6 +46,14 @@ $(BUILDDIR)/$(OPENBLAS_SRC_DIR)/build-compiled: | $(BUILDDIR)/objconv/build-comp endif endif +OPENBLAS_FFLAGS := +OPENBLAS_CFLAGS := + +# Work around OpenBLAS#942 +ifeq ($(USECLANG),1) +OPENBLAS_CFLAGS += -no-integrated-as +endif + # Decide whether to build for 32-bit or 64-bit arch ifneq ($(BUILD_OS),$(OS)) OPENBLAS_BUILD_OPTS += OSNAME=$(OS) CROSS=1 HOSTCC=$(HOSTCC) CROSS_SUFFIX=$(CROSS_COMPILE) @@ -53,12 +61,15 @@ endif ifeq ($(OS),WINNT) ifneq ($(ARCH),x86_64) ifneq ($(USECLANG),1) -OPENBLAS_BUILD_OPTS += CFLAGS="$(CFLAGS) -mincoming-stack-boundary=2" +OPENBLAS_CFLAGS += $(CFLAGS) -mincoming-stack-boundary=2 endif -OPENBLAS_BUILD_OPTS += FFLAGS="$(FFLAGS) -mincoming-stack-boundary=2" +OPENBLAS_FFLAGS += $(FFLAGS) -mincoming-stack-boundary=2 endif endif +OPENBLAS_BUILD_OPTS += CFLAGS="$(OPENBLAS_CFLAGS)" +OPENBLAS_BUILD_OPTS += FFLAGS="$(OPENBLAS_FFLAGS)" + # Debug OpenBLAS ifeq ($(OPENBLAS_DEBUG), 1) OPENBLAS_BUILD_OPTS += DEBUG=1 From e21120111e56ccf63d6ec3ec05c83b0c5210dd0e Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Sat, 25 Feb 2017 17:28:38 +0100 Subject: [PATCH 0079/1534] Fix jl_is_memdebug. Need to include options.h for MEMDEBUG to be available. --- src/jlapi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/jlapi.c b/src/jlapi.c index 9e68c744e29a1..c971927528b09 100644 --- a/src/jlapi.c +++ b/src/jlapi.c @@ -12,6 +12,7 @@ #include #include #include "julia.h" +#include "options.h" #ifdef __cplusplus #include From 495114cc0dc5d066916cf2dfeddb7d94cf83b141 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sat, 25 Feb 2017 13:48:01 -0500 Subject: [PATCH 0080/1534] fix #20804, keyword args in defining UnionAll-typed function --- base/boot.jl | 2 +- src/dump.c | 2 +- src/gf.c | 6 +++++- src/julia.h | 2 +- src/julia_internal.h | 1 + src/method.c | 6 ++++++ test/keywordargs.jl | 10 ++++++++++ 7 files changed, 25 insertions(+), 4 deletions(-) diff --git a/base/boot.jl b/base/boot.jl index 1933e511210c5..cd3ae8b4909bb 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -236,7 +236,7 @@ eval(m::Module, e::ANY) = ccall(:jl_toplevel_eval_in, Any, (Any, Any), m, e) kwfunc(f::ANY) = ccall(:jl_get_keyword_sorter, Any, (Any,), f) -kwftype(t::ANY) = typeof(ccall(:jl_get_kwsorter, Any, (Any,), t.name)) +kwftype(t::ANY) = typeof(ccall(:jl_get_kwsorter, Any, (Any,), t)) mutable struct Box contents::Any diff --git a/src/dump.c b/src/dump.c index 7959f4c390b60..f227cc674c73e 100644 --- a/src/dump.c +++ b/src/dump.c @@ -1366,7 +1366,7 @@ static jl_value_t *jl_deserialize_datatype(jl_serializer_state *s, int pos, jl_v } if (tag == 9) { jl_datatype_t *primarydt = (jl_datatype_t*)jl_deserialize_value(s, NULL); - jl_value_t *dtv = jl_typeof(jl_get_kwsorter(primarydt->name)); + jl_value_t *dtv = jl_typeof(jl_get_kwsorter((jl_value_t*)primarydt)); backref_list.items[pos] = dtv; return dtv; } diff --git a/src/gf.c b/src/gf.c index 84a2bcb3923dc..79b6ea7ca7567 100644 --- a/src/gf.c +++ b/src/gf.c @@ -2402,8 +2402,12 @@ jl_function_t *jl_new_generic_function_with_supertype(jl_sym_t *name, jl_module_ return (jl_function_t*)f; } -JL_DLLEXPORT jl_function_t *jl_get_kwsorter(jl_typename_t *tn) +JL_DLLEXPORT jl_function_t *jl_get_kwsorter(jl_value_t *ty) { + jl_datatype_t *dt = jl_argument_datatype(ty); + if (dt == NULL) + jl_error("cannot get keyword sorter for abstract type"); + jl_typename_t *tn = dt->name; jl_methtable_t *mt = tn->mt; if (!mt->kwsorter) { JL_LOCK(&mt->writelock); diff --git a/src/julia.h b/src/julia.h index 89ee52892a7d8..fbb9e8ea0ad14 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1038,7 +1038,7 @@ JL_DLLEXPORT void jl_method_def(jl_svec_t *argdata, jl_code_info_t *f, jl_value_ JL_DLLEXPORT jl_code_info_t *jl_code_for_staged(jl_method_instance_t *linfo); JL_DLLEXPORT jl_code_info_t *jl_copy_code_info(jl_code_info_t *src); JL_DLLEXPORT size_t jl_get_world_counter(void); -JL_DLLEXPORT jl_function_t *jl_get_kwsorter(jl_typename_t *tn); +JL_DLLEXPORT jl_function_t *jl_get_kwsorter(jl_value_t *ty); JL_DLLEXPORT jl_value_t *jl_box_bool(int8_t x); JL_DLLEXPORT jl_value_t *jl_box_int8(int8_t x); JL_DLLEXPORT jl_value_t *jl_box_uint8(uint8_t x); diff --git a/src/julia_internal.h b/src/julia_internal.h index 135d6c5655021..1d7c4ecd171a7 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -375,6 +375,7 @@ jl_method_instance_t *jl_method_lookup(jl_methtable_t *mt, jl_value_t **args, si jl_value_t *jl_gf_invoke(jl_tupletype_t *types, jl_value_t **args, size_t nargs); JL_DLLEXPORT jl_datatype_t *jl_first_argument_datatype(jl_value_t *argtypes); +jl_datatype_t *jl_argument_datatype(jl_value_t *argt); jl_value_t *jl_nth_slot_type(jl_value_t *sig, size_t i); void jl_compute_field_offsets(jl_datatype_t *st); diff --git a/src/method.c b/src/method.c index 40fe7ec9ff31e..d9b98aecd1f8f 100644 --- a/src/method.c +++ b/src/method.c @@ -576,6 +576,12 @@ JL_DLLEXPORT jl_datatype_t *jl_first_argument_datatype(jl_value_t *argtypes) return first_arg_datatype(argtypes, 0); } +// get DataType implied by a single given type +jl_datatype_t *jl_argument_datatype(jl_value_t *argt) +{ + return first_arg_datatype(argt, 1); +} + extern tracer_cb jl_newmeth_tracer; JL_DLLEXPORT void jl_method_def(jl_svec_t *argdata, jl_code_info_t *f, diff --git a/test/keywordargs.jl b/test/keywordargs.jl index e724448d88374..e3806fc87509f 100644 --- a/test/keywordargs.jl +++ b/test/keywordargs.jl @@ -248,3 +248,13 @@ f7045(x::Real; y=true) = y ? 2 : 3 @test f7045(1.0) === 1 @test f7045(1, y=false) === 3 @test f7045(1.0, y=false) === 3 + +# issue #20804 +struct T20804{T} + y::T +end +(f::T20804)(;x=10) = f.y + x +let x = T20804(4) + @test x() == 14 + @test x(x=8) == 12 +end From 05cea50f4e46092cf380e48e105bbe083344843f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Sun, 26 Feb 2017 21:30:41 +0100 Subject: [PATCH 0081/1534] Mention in NEWS.md deprecation of Airy functions along with their removal (#20814) --- NEWS.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/NEWS.md b/NEWS.md index 0f6862e504277..c3f7bc04ecc4f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -206,7 +206,10 @@ This section lists changes that do not have deprecation warnings. trigamma, and polygamma special functions have been moved from Base to the [SpecialFunctions.jl package](https://github.com/JuliaMath/SpecialFunctions.jl) - ([#20427]). + ([#20427]). Note that `airy`, `airyx` and `airyprime` have been deprecated + in favor of more specific functions (`airyai`, `airybi`, `airyaiprime`, + `airybiprimex`, `airyaix`, `airybix`, `airyaiprimex`, `airybiprimex`) + ([#18050]). * `write` on an `IOBuffer` now returns a signed integer in order to be consistent with other buffers ([#20609]). @@ -346,10 +349,6 @@ Deprecated or removed `maxabs` and `minabs` have similarly been deprecated in favor of `maximum(abs, x)` and `minimum(abs, x)`. Likewise for the in-place counterparts of these functions ([#19598]). - * `airy`, `airyx` and `airyprime` have been deprecated in favor of more specific - functions (`airyai`, `airybi`, `airyaiprime`, `airybiprimex`, `airyaix`, `airybix`, - `airyaiprimex`, `airybiprimex`) ([#18050]). - * `produce`, `consume` and iteration over a Task object have been deprecated in favor of using Channels for inter-task communication ([#19841]). From f2b03d4072f84010f68144bb28dd2f6021ba1828 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Sun, 26 Feb 2017 12:33:16 -0800 Subject: [PATCH 0082/1534] Revamp libgit2 owner interface. (#20786) It seems that some objects can be owned by non-repo objects. This makes the code a bit more general to allow for this. * Make GitTreeEntry always have a reference to the GitTree, get rid of unnecessary repo arguments --- base/libgit2/index.jl | 4 +- base/libgit2/reference.jl | 14 +++---- base/libgit2/repository.jl | 2 +- base/libgit2/tree.jl | 12 +++--- base/libgit2/types.jl | 81 +++++++++++++++++--------------------- base/libgit2/walker.jl | 2 +- 6 files changed, 52 insertions(+), 63 deletions(-) diff --git a/base/libgit2/index.jl b/base/libgit2/index.jl index 8154c70c2c699..f3ca053d91f2c 100644 --- a/base/libgit2/index.jl +++ b/base/libgit2/index.jl @@ -25,10 +25,10 @@ function write_tree!(idx::GitIndex) end function repository(idx::GitIndex) - if isnull(idx.nrepo) + if isnull(idx.owner) throw(GitError(Error.Index, Error.ENOTFOUND, "Index does not have an owning repository.")) else - return Base.get(idx.nrepo) + return Base.get(idx.owner) end end diff --git a/base/libgit2/reference.jl b/base/libgit2/reference.jl index 5158ca4d339b9..3b44dd1ad763b 100644 --- a/base/libgit2/reference.jl +++ b/base/libgit2/reference.jl @@ -171,7 +171,7 @@ function peel{T<:GitObject}(::Type{T}, ref::GitReference) obj_ptr_ptr = Ref{Ptr{Void}}(C_NULL) @check ccall((:git_reference_peel, :libgit2), Cint, (Ptr{Ptr{Void}}, Ptr{Void}, Cint), obj_ptr_ptr, ref.ptr, Consts.OBJECT(T)) - return T(ref.repo, obj_ptr_ptr[]) + return T(ref.owner, obj_ptr_ptr[]) end peel(ref::GitReference) = peel(GitObject, ref) @@ -280,21 +280,21 @@ function upstream(ref::GitReference) return Nullable{GitReference}() end if ref_ptr_ptr[] != C_NULL - close(GitReference(ref.repo, ref_ptr_ptr[])) + close(GitReference(ref.owner, ref_ptr_ptr[])) end throw(Error.GitError(err)) end - return Nullable{GitReference}(GitReference(ref.repo, ref_ptr_ptr[])) + return Nullable{GitReference}(GitReference(ref.owner, ref_ptr_ptr[])) end -repository(ref::GitReference) = ref.repo +repository(ref::GitReference) = ref.owner function target!(ref::GitReference, new_oid::GitHash; msg::AbstractString="") ref_ptr_ptr = Ref{Ptr{Void}}(C_NULL) @check ccall((:git_reference_set_target, :libgit2), Cint, (Ptr{Ptr{Void}}, Ptr{Void}, Ptr{GitHash}, Cstring), ref_ptr_ptr, ref.ptr, Ref(new_oid), isempty(msg) ? C_NULL : msg) - return GitReference(ref.repo, ref_ptr_ptr[]) + return GitReference(ref.owner, ref_ptr_ptr[]) end function GitBranchIter(repo::GitRepo, flags::Cint=Cint(Consts.BRANCH_LOCAL)) @@ -311,7 +311,7 @@ function Base.start(bi::GitBranchIter) (Ptr{Ptr{Void}}, Ptr{Cint}, Ptr{Void}), ref_ptr_ptr, btype, bi.ptr) err != Int(Error.GIT_OK) && return (nothing, -1, true) - return (GitReference(bi.repo, ref_ptr_ptr[]), btype[], false) + return (GitReference(bi.owner, ref_ptr_ptr[]), btype[], false) end Base.done(bi::GitBranchIter, state) = Bool(state[3]) @@ -323,7 +323,7 @@ function Base.next(bi::GitBranchIter, state) (Ptr{Ptr{Void}}, Ptr{Cint}, Ptr{Void}), ref_ptr_ptr, btype, bi.ptr) err != Int(Error.GIT_OK) && return (state[1:2], (nothing, -1, true)) - return (state[1:2], (GitReference(bi.repo, ref_ptr_ptr[]), btype[], false)) + return (state[1:2], (GitReference(bi.owner, ref_ptr_ptr[]), btype[], false)) end Base.iteratorsize(::Type{GitBranchIter}) = Base.SizeUnknown() diff --git a/base/libgit2/repository.jl b/base/libgit2/repository.jl index 47ab7046339a2..a991fb806baf8 100644 --- a/base/libgit2/repository.jl +++ b/base/libgit2/repository.jl @@ -235,7 +235,7 @@ function peel{T<:GitObject}(::Type{T}, obj::GitObject) @check ccall((:git_object_peel, :libgit2), Cint, (Ptr{Ptr{Void}}, Ptr{Void}, Cint), new_ptr_ptr, obj.ptr, Consts.OBJECT(T)) - return T(obj.repo, new_ptr_ptr[]) + return T(obj.owner, new_ptr_ptr[]) end peel(obj::GitObject) = peel(GitObject, obj) diff --git a/base/libgit2/tree.jl b/base/libgit2/tree.jl index 07cc6f3783f8b..f938819f4c07d 100644 --- a/base/libgit2/tree.jl +++ b/base/libgit2/tree.jl @@ -16,11 +16,8 @@ function treewalk(f::Function, tree::GitTree, payload=Any[], post::Bool = false) return cbf_payload end -function repository(tree::GitTree) - repo_ptr = ccall((:git_tree_owner, :libgit2), Ptr{Void}, - (Ptr{Void},), tree.ptr) - return GitRepo(repo_ptr) -end +repository(tree::GitTree) = tree.owner +repository(te::GitTreeEntry) = repository(te.owner) function filename(te::GitTreeEntry) str = ccall((:git_tree_entry_name, :libgit2), Cstring, (Ptr{Void},), te.ptr) @@ -53,10 +50,11 @@ function Base.getindex(tree::GitTree, i::Integer) te_ptr = ccall((:git_tree_entry_byindex, :libgit2), Ptr{Void}, (Ptr{Void}, Csize_t), tree.ptr, i-1) - return GitTreeEntry(te_ptr, false) + return GitTreeEntry(tree, te_ptr, false) end -function (::Type{T}){T<:GitObject}(repo::GitRepo, te::GitTreeEntry) +function (::Type{T}){T<:GitObject}(te::GitTreeEntry) + repo = repository(te) obj_ptr_ptr = Ref{Ptr{Void}}(C_NULL) @check ccall((:git_tree_entry_to_object, :libgit2), Cint, (Ptr{Ptr{Void}}, Ptr{Void}, Ref{Void}), diff --git a/base/libgit2/types.jl b/base/libgit2/types.jl index accd89038c8f3..14b398bc734e5 100644 --- a/base/libgit2/types.jl +++ b/base/libgit2/types.jl @@ -480,30 +480,31 @@ Base.isempty(obj::AbstractGitObject) = (obj.ptr == C_NULL) abstract type GitObject <: AbstractGitObject end -for (typ, reporef, sup, cname) in [ - (:GitRepo, nothing, :AbstractGitObject, :git_repository), - (:GitTreeEntry, nothing, :AbstractGitObject, :git_tree_entry), - (:GitDiffStats, nothing, :AbstractGitObject, :git_diff_stats), - (:GitConfig, :Nullable, :AbstractGitObject, :git_config), - (:GitIndex, :Nullable, :AbstractGitObject, :git_index), - (:GitRemote, :GitRepo, :AbstractGitObject, :git_remote), - (:GitRevWalker, :GitRepo, :AbstractGitObject, :git_revwalk), - (:GitReference, :GitRepo, :AbstractGitObject, :git_reference), - (:GitDiff, :GitRepo, :AbstractGitObject, :git_diff), - (:GitAnnotated, :GitRepo, :AbstractGitObject, :git_annotated_commit), - (:GitRebase, :GitRepo, :AbstractGitObject, :git_rebase), - (:GitStatus, :GitRepo, :AbstractGitObject, :git_status_list), - (:GitBranchIter, :GitRepo, :AbstractGitObject, :git_branch_iterator), - (:GitUnknownObject, :GitRepo, :GitObject, :git_object), - (:GitCommit, :GitRepo, :GitObject, :git_commit), - (:GitBlob, :GitRepo, :GitObject, :git_blob), - (:GitTree, :GitRepo, :GitObject, :git_tree), - (:GitTag, :GitRepo, :GitObject, :git_tag)] - - if reporef === nothing +for (typ, owntyp, sup, cname) in [ + (:GitRepo, nothing, :AbstractGitObject, :git_repository), + (:GitDiffStats, nothing, :AbstractGitObject, :git_diff_stats), + (:GitConfig, :(Nullable{GitRepo}), :AbstractGitObject, :git_config), + (:GitIndex, :(Nullable{GitRepo}), :AbstractGitObject, :git_index), + (:GitRemote, :GitRepo, :AbstractGitObject, :git_remote), + (:GitRevWalker, :GitRepo, :AbstractGitObject, :git_revwalk), + (:GitReference, :GitRepo, :AbstractGitObject, :git_reference), + (:GitDiff, :GitRepo, :AbstractGitObject, :git_diff), + (:GitAnnotated, :GitRepo, :AbstractGitObject, :git_annotated_commit), + (:GitRebase, :GitRepo, :AbstractGitObject, :git_rebase), + (:GitStatus, :GitRepo, :AbstractGitObject, :git_status_list), + (:GitBranchIter, :GitRepo, :AbstractGitObject, :git_branch_iterator), + (:GitUnknownObject, :GitRepo, :GitObject, :git_object), + (:GitCommit, :GitRepo, :GitObject, :git_commit), + (:GitBlob, :GitRepo, :GitObject, :git_blob), + (:GitTree, :GitRepo, :GitObject, :git_tree), + (:GitTag, :GitRepo, :GitObject, :git_tag), + (:GitTreeEntry, :GitTree, :AbstractGitObject, :git_tree_entry), + ] + + if owntyp === nothing @eval mutable struct $typ <: $sup ptr::Ptr{Void} - function $typ(ptr::Ptr{Void},fin=true) + function $typ(ptr::Ptr{Void}, fin::Bool=true) # fin=false should only be used when the pointer should not be free'd # e.g. from within callback functions which are passed a pointer @assert ptr != C_NULL @@ -515,35 +516,25 @@ for (typ, reporef, sup, cname) in [ return obj end end - elseif reporef == :Nullable + else @eval mutable struct $typ <: $sup - nrepo::Nullable{GitRepo} + owner::$owntyp ptr::Ptr{Void} - function $typ(repo::GitRepo, ptr::Ptr{Void}) - @assert ptr != C_NULL - obj = new(Nullable(repo), ptr) - Threads.atomic_add!(REFCOUNT, UInt(1)) - finalizer(obj, Base.close) - return obj - end - function $typ(ptr::Ptr{Void}) + function $typ(owner::$owntyp, ptr::Ptr{Void}, fin::Bool=true) @assert ptr != C_NULL - obj = new(Nullable{GitRepo}(), ptr) - Threads.atomic_add!(REFCOUNT, UInt(1)) - finalizer(obj, Base.close) + obj = new(owner, ptr) + if fin + Threads.atomic_add!(REFCOUNT, UInt(1)) + finalizer(obj, Base.close) + end return obj end end - elseif reporef == :GitRepo - @eval mutable struct $typ <: $sup - repo::GitRepo - ptr::Ptr{Void} - function $typ(repo::GitRepo, ptr::Ptr{Void}) - @assert ptr != C_NULL - obj = new(repo, ptr) - Threads.atomic_add!(REFCOUNT, UInt(1)) - finalizer(obj, Base.close) - return obj + if isa(owntyp, Expr) && owntyp.args[1] == :Nullable + @eval begin + $typ(ptr::Ptr{Void}, fin::Bool=true) = $typ($owntyp(), ptr, fin) + $typ(owner::$(owntyp.args[2]), ptr::Ptr{Void}, fin::Bool=true) = + $typ($owntyp(owner), ptr, fin) end end end diff --git a/base/libgit2/walker.jl b/base/libgit2/walker.jl index 5a15901d3391f..8649b35cf9ca8 100644 --- a/base/libgit2/walker.jl +++ b/base/libgit2/walker.jl @@ -48,7 +48,7 @@ function Base.sort!(w::GitRevWalker; by::Cint = Consts.SORT_NONE, rev::Bool=fals return w end -repository(w::GitRevWalker) = w.repo +repository(w::GitRevWalker) = w.owner function Base.map(f::Function, walker::GitRevWalker; oid::GitHash=GitHash(), From 42f0b0b848cfabeabbe797e00bf578173ff3dcde Mon Sep 17 00:00:00 2001 From: kshyatt Date: Sun, 26 Feb 2017 15:30:00 -0800 Subject: [PATCH 0083/1534] Fix bad Blob ctor in libgit2 tests --- test/libgit2.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/libgit2.jl b/test/libgit2.jl index c110587a0a992..a573f8886d49e 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -495,7 +495,7 @@ mktempdir() do dir tree_entry = tree[1] te_str = sprint(show, tree_entry) @test te_str == "GitTreeEntry:\nEntry name: testfile\nEntry type: Base.LibGit2.GitBlob\nEntry OID: $(LibGit2.entryid(tree_entry))\n" - blob = LibGit2.GitBlob(repo, tree_entry) + blob = LibGit2.GitBlob(tree_entry) blob_str = sprint(show, blob) @test blob_str == "GitBlob:\nBlob id: $(LibGit2.GitHash(blob))\nContents:\n$(LibGit2.content(blob))\n" finally From 446539e72c9ad97a847b165c0210b5c85854ae9c Mon Sep 17 00:00:00 2001 From: kshyatt Date: Wed, 22 Feb 2017 13:24:05 -0800 Subject: [PATCH 0084/1534] Add show method and test for GitTree --- base/libgit2/tree.jl | 6 ++++++ test/libgit2.jl | 2 ++ 2 files changed, 8 insertions(+) diff --git a/base/libgit2/tree.jl b/base/libgit2/tree.jl index f938819f4c07d..64d37c8e63014 100644 --- a/base/libgit2/tree.jl +++ b/base/libgit2/tree.jl @@ -68,3 +68,9 @@ function Base.show(io::IO, te::GitTreeEntry) println(io, "Entry type: ", entrytype(te)) println(io, "Entry OID: ", entryid(te)) end + +function Base.show(io::IO, tree::GitTree) + println(io, "GitTree:") + println(io, "Owner: ", repository(tree)) + println(io, "Number of entries: ", count(tree)) +end diff --git a/test/libgit2.jl b/test/libgit2.jl index a573f8886d49e..c2f0e6ae711b3 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -490,6 +490,8 @@ mktempdir() do dir @test isa(tree, LibGit2.GitTree) @test isa(LibGit2.GitObject(repo, "HEAD^{tree}"), LibGit2.GitTree) @test count(tree) == 1 + tree_str = sprint(show, tree) + @test tree_str == "GitTree:\nOwner: $(LibGit2.repository(tree))\nNumber of entries: 1\n" @test_throws BoundsError tree[0] @test_throws BoundsError tree[2] tree_entry = tree[1] From b6cf1959ae7d20d9cd4468e65683d9f31a9dc897 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Sun, 26 Feb 2017 21:51:15 -0500 Subject: [PATCH 0085/1534] Fix compilation on LLVM svn --- src/jitlayers.cpp | 2 +- src/jitlayers.h | 18 +++++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index d6f8895dba275..5c705ad4ed2b4 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -347,7 +347,7 @@ JL_DLLEXPORT void ORCNotifyObjectEmitted(JITEventListener *Listener, // TODO: hook up RegisterJITEventListener, instead of hard-coding the GDB and JuliaListener targets template -void JuliaOJIT::DebugObjectRegistrar::operator()(ObjectLinkingLayerBase::ObjSetHandleT H, +void JuliaOJIT::DebugObjectRegistrar::operator()(RTDyldObjectLinkingLayerBase::ObjSetHandleT H, const ObjSetT &Objects, const LoadResult &LOS) { #if JL_LLVM_VERSION < 30800 diff --git a/src/jitlayers.h b/src/jitlayers.h index 5c1c3d8a51f4f..195f0a78eecff 100644 --- a/src/jitlayers.h +++ b/src/jitlayers.h @@ -11,7 +11,11 @@ #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" #include "llvm/ExecutionEngine/Orc/LambdaResolver.h" #include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" -#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" +#if JL_LLVM_VERSION >= 50000 +# include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" +#else +# include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" +#endif #include "llvm/ExecutionEngine/ObjectMemoryBuffer.h" #elif defined(USE_MCJIT) #include @@ -164,6 +168,14 @@ typedef JITSymbol JL_SymbolInfo; typedef orc::JITSymbol JL_JITSymbol; typedef RuntimeDyld::SymbolInfo JL_SymbolInfo; #endif +#if JL_LLVM_VERSION >= 50000 +using orc::RTDyldObjectLinkingLayerBase; +using orc::RTDyldObjectLinkingLayer; +#else +using RTDyldObjectLinkingLayerBase = orc::ObjectLinkingLayerBase; +template +using RTDyldObjectLinkingLayer = orc::ObjectLinkingLayer; +#endif class JuliaOJIT { // Custom object emission notification handler for the JuliaOJIT @@ -172,7 +184,7 @@ class JuliaOJIT { public: DebugObjectRegistrar(JuliaOJIT &JIT); template - void operator()(orc::ObjectLinkingLayerBase::ObjSetHandleT H, const ObjSetT &Objects, + void operator()(RTDyldObjectLinkingLayerBase::ObjSetHandleT H, const ObjSetT &Objects, const LoadResult &LOS); private: void NotifyGDB(object::OwningBinary &DebugObj); @@ -182,7 +194,7 @@ class JuliaOJIT { }; public: - typedef orc::ObjectLinkingLayer ObjLayerT; + typedef RTDyldObjectLinkingLayer ObjLayerT; typedef orc::IRCompileLayer CompileLayerT; typedef CompileLayerT::ModuleSetHandleT ModuleHandleT; typedef StringMap SymbolTableT; From 27de0b3682a56364999bde23106144a866a83345 Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Mon, 27 Feb 2017 08:22:59 +0100 Subject: [PATCH 0086/1534] Make testall copy the correct system image, depending on the build mode. --- Makefile | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 0e28cc87b7628..27b1fb43f806c 100644 --- a/Makefile +++ b/Makefile @@ -553,8 +553,13 @@ distcleanall: cleanall test: check-whitespace $(JULIA_BUILD_MODE) @$(MAKE) $(QUIET_MAKE) -C $(BUILDROOT)/test default JULIA_BUILD_MODE=$(JULIA_BUILD_MODE) +ifeq ($(JULIA_BUILD_MODE),release) +JULIA_SYSIMG=$(build_private_libdir)/sys$(JULIA_LIBSUFFIX).$(SHLIB_EXT) +else +JULIA_SYSIMG=$(build_private_libdir)/sys-$(JULIA_BUILD_MODE)$(JULIA_LIBSUFFIX).$(SHLIB_EXT) +endif testall: check-whitespace $(JULIA_BUILD_MODE) - cp $(build_private_libdir)/sys$(JULIA_LIBSUFFIX).$(SHLIB_EXT) $(BUILDROOT)/local.$(SHLIB_EXT) && $(JULIA_EXECUTABLE) -J $(call cygpath_w,$(BUILDROOT)/local.$(SHLIB_EXT)) -e 'true' && rm $(BUILDROOT)/local.$(SHLIB_EXT) + cp $(JULIA_SYSIMG) $(BUILDROOT)/local.$(SHLIB_EXT) && $(JULIA_EXECUTABLE) -J $(call cygpath_w,$(BUILDROOT)/local.$(SHLIB_EXT)) -e 'true' && rm $(BUILDROOT)/local.$(SHLIB_EXT) @$(MAKE) $(QUIET_MAKE) -C $(BUILDROOT)/test all JULIA_BUILD_MODE=$(JULIA_BUILD_MODE) testall1: check-whitespace $(JULIA_BUILD_MODE) From 5c61a0a8ec016b92ae273a277287d1de51af87b1 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Mon, 27 Feb 2017 11:40:08 -0500 Subject: [PATCH 0087/1534] Fix a few syntax error in the doc. (#20827) --- base/essentials.jl | 2 +- base/profile.jl | 2 +- base/reflection.jl | 1 + base/sparse/sparsematrix.jl | 4 ++-- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/base/essentials.jl b/base/essentials.jl index 04f7850dec228..007bf2d347525 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -224,7 +224,7 @@ function sum(A::AbstractArray) end ``` -!!! Warning +!!! warning Using `@inbounds` may return incorrect results/crashes/corruption for out-of-bounds indices. The user is responsible for checking it manually. diff --git a/base/profile.jl b/base/profile.jl index 05e0ae8668f53..76d122c066f29 100644 --- a/base/profile.jl +++ b/base/profile.jl @@ -108,7 +108,7 @@ The keyword arguments can be any combination of: - `C` -- If `true`, backtraces from C and Fortran code are shown (normally they are excluded). - - `combine` -- If true` (default), instruction pointers are merged that correspond to the same line of code. + - `combine` -- If `true` (default), instruction pointers are merged that correspond to the same line of code. - `maxdepth` -- Limits the depth higher than `maxdepth` in the `:tree` format. diff --git a/base/reflection.jl b/base/reflection.jl index 12995bcb0a55f..d79b80cef56d5 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -251,6 +251,7 @@ true julia> isleaftype(Vector{Complex{Float32}}) true +``` """ isleaftype(t::ANY) = (@_pure_meta; isa(t, DataType) && t.isleaftype) diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl index d5600a5aebea7..89bae7a60a137 100644 --- a/base/sparse/sparsematrix.jl +++ b/base/sparse/sparsematrix.jl @@ -992,7 +992,7 @@ count (`length(q) == A.n`). Row-permutation `p`'s length must match `A`'s row co (`length(p) == A.m`). `C`'s dimensions must match those of `transpose(A)` (`C.m == A.n` and `C.n == A.m`), and `C` -must have enough storage to accommodate all allocated entries in `A` (`length(C.rowval)` >= nnz(A)` +must have enough storage to accommodate all allocated entries in `A` (`length(C.rowval) >= nnz(A)` and `length(C.nzval) >= nnz(A)`). For additional (algorithmic) information, and for versions of these methods that forgo @@ -1272,7 +1272,7 @@ julia> sprand(rng, Bool, 2, 2, 0.5) julia> sprand(rng, Float64, 3, 0.75) 3-element SparseVector{Float64,Int64} with 1 stored entry: [3] = 0.298614 -```` +``` """ function sprand{T}(r::AbstractRNG, m::Integer, n::Integer, density::AbstractFloat, rfn::Function, ::Type{T}=eltype(rfn(r,1))) From 8fee77f296f5626fbcebfd87364f0ca2a3f17c87 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 21 Feb 2017 15:40:09 -0500 Subject: [PATCH 0088/1534] fix #20704, `pure` annotation should not skip method errors --- base/inference.jl | 74 +++++++++++++++++++++++++---------------------- test/inference.jl | 29 +++++++++++++++++++ 2 files changed, 68 insertions(+), 35 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 857b3f2345179..e6a4b0ffdd8f9 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -64,7 +64,9 @@ end # The type of a value might be constant struct Const val - Const(v::ANY) = new(v) + actual::Bool # if true, we obtained `val` by actually calling a @pure function + Const(v::ANY) = new(v, false) + Const(v::ANY, a::Bool) = new(v, a) end # The type of a value might be Bool, @@ -191,7 +193,7 @@ mutable struct InferenceState vararg_type = rewrap(vararg_type, linfo.specTypes) end s_types[1][la] = VarState(vararg_type, false) - src.slottypes[la] = widenconst(vararg_type) + src.slottypes[la] = vararg_type la -= 1 end end @@ -220,11 +222,11 @@ mutable struct InferenceState end i == laty && (lastatype = atyp) s_types[1][i] = VarState(atyp, false) - src.slottypes[i] = widenconst(atyp) + src.slottypes[i] = atyp end for i = (atail + 1):la s_types[1][i] = VarState(lastatype, false) - src.slottypes[i] = widenconst(lastatype) + src.slottypes[i] = lastatype end else @assert la == 0 # wrong number of arguments @@ -1546,7 +1548,7 @@ function return_type_tfunc(argtypes::ANY, vtypes::VarTable, sv::InferenceState) return NF end -function pure_eval_call(f::ANY, argtypes::ANY, atype::ANY, vtypes::VarTable, sv::InferenceState) +function pure_eval_call(f::ANY, argtypes::ANY, atype::ANY, sv::InferenceState) for i = 2:length(argtypes) a = argtypes[i] if !(isa(a,Const) || isconstType(a)) @@ -1571,7 +1573,7 @@ function pure_eval_call(f::ANY, argtypes::ANY, atype::ANY, vtypes::VarTable, sv: try value = Core._apply_pure(f, args) # TODO: add some sort of edge(s) - return abstract_eval_constant(value) + return Const(value, true) catch return false end @@ -1807,7 +1809,7 @@ function abstract_call(f::ANY, fargs::Union{Tuple{},Vector{Any}}, argtypes::Vect end atype = argtypes_to_type(argtypes) - t = pure_eval_call(f, argtypes, atype, vtypes, sv) + t = pure_eval_call(f, argtypes, atype, sv) t !== false && return t if istopfunction(tm, f, :promote_type) || istopfunction(tm, f, :typejoin) @@ -1979,14 +1981,7 @@ function abstract_eval(e::ANY, vtypes::VarTable, sv::InferenceState) return t end -const Type_Array = Const(Array) - -function abstract_eval_constant(x::ANY) - if x === Array - return Type_Array - end - return Const(x) -end +const abstract_eval_constant = Const function abstract_eval_global(M::Module, s::Symbol) if isdefined(M,s) && isconst(M,s) @@ -2930,28 +2925,33 @@ function optimize(me::InferenceState) if isa(me.bestguess, Const) || isconstType(me.bestguess) me.const_ret = true - ispure = me.src.pure - if !ispure && length(me.src.code) < 10 - ispure = true + proven_pure = false + # must be proven pure to use const_api; otherwise we might skip throwing errors + # (issue #20704) + # TODO: Improve this analysis; if a function is marked @pure we should really + # only care about certain errors (e.g. method errors and type errors). + if length(me.src.code) < 10 + proven_pure = true for stmt in me.src.code if !statement_effect_free(stmt, me.src, me.mod) - ispure = false + proven_pure = false break end end - if ispure + if proven_pure for fl in me.src.slotflags if (fl & Slot_UsedUndef) != 0 - ispure = false + proven_pure = false break end end end end - me.src.pure = ispure + if proven_pure + me.src.pure = true + end - do_coverage = coverage_enabled() - if ispure && !do_coverage + if proven_pure && !coverage_enabled() # use constant calling convention # Do not emit `jlcall_api == 2` if coverage is enabled # so that we don't need to add coverage support @@ -3082,7 +3082,7 @@ function annotate_slot_load!(e::Expr, vtypes::VarTable, sv::InferenceState, unde undefs[id] = true end # add type annotations where needed - if !(sv.src.slottypes[id] <: vt) + if !(sv.src.slottypes[id] ⊑ vt) e.args[i] = TypedSlot(id, vt) end end @@ -3225,6 +3225,7 @@ end # we also need to preserve the type for any untyped load of a DataType # since codegen optimizations of functions like `is` will depend on knowing it function widen_slot_type(ty::ANY, untypedload::Bool) + ty = widenconst(ty) if isa(ty, DataType) if untypedload || isbits(ty) || isdefined(ty, :instance) return ty @@ -3770,16 +3771,6 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference atype_unlimited, method.sig) methsp = methsp::SimpleVector end - # check whether call can be inlined to just a quoted constant value - if isa(f, widenconst(ft)) && !method.isstaged && (method.source.pure || f === return_type) - if isconstType(e.typ) - return inline_as_constant(e.typ.parameters[1], argexprs, sv, - invoke_data) - elseif isa(e.typ,Const) - return inline_as_constant(e.typ.val, argexprs, sv, - invoke_data) - end - end methsig = method.sig if !(atype <: metharg) @@ -3787,6 +3778,19 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference invoke_data) end + # check whether call can be inlined to just a quoted constant value + if isa(f, widenconst(ft)) && !method.isstaged + if f === return_type + if isconstType(e.typ) + return inline_as_constant(e.typ.parameters[1], argexprs, sv, invoke_data) + elseif isa(e.typ,Const) + return inline_as_constant(e.typ.val, argexprs, sv, invoke_data) + end + elseif method.source.pure && isa(e.typ,Const) && e.typ.actual + return inline_as_constant(e.typ.val, argexprs, sv, invoke_data) + end + end + argexprs0 = argexprs na = Int(method.nargs) # check for vararg function diff --git a/test/inference.jl b/test/inference.jl index 6ab5588907693..e9035969b3e62 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -655,3 +655,32 @@ let A = 1:2, z = zip(A, A, A, A, A, A, A, A, A, A, A, A) @test z isa Core.Inference.limit_type_depth(typeof(z), 0) @test start(z) == (1, (1, (1, (1, (1, (1, (1, (1, (1, (1, (1, 1))))))))))) end + +# issue #20704 +f20704(::Int) = 1 +Base.@pure b20704(x::ANY) = f20704(x) +@test b20704(42) === 1 +@test_throws MethodError b20704(42.0) + +bb20704() = b20704(Any[1.0][1]) +@test_throws MethodError bb20704() + +v20704() = Val{b20704(Any[1.0][1])} +@test_throws MethodError v20704() +@test Base.return_types(v20704, ()) == Any[Type{Val{1}}] + +Base.@pure g20704(::Int) = 1 +h20704(x::ANY) = g20704(x) +@test g20704(1) === 1 +@test_throws MethodError h20704(1.2) + +Base.@pure c20704() = (f20704(1.0); 1) +d20704() = c20704() +@test_throws MethodError d20704() + +Base.@pure function a20704(x) + rand() + 42 +end +aa20704(x) = x(nothing) +@test code_typed(aa20704, (typeof(a20704),))[1][1].pure From ccb426f79af059ca6a83cd117350a3a7e067ba41 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Mon, 27 Feb 2017 20:28:25 +0100 Subject: [PATCH 0089/1534] Remove package extensions in Pkg functions (#20681) * remove package extension in Pkg functions * Run Pkg.dependents("Example") tests at a fixed METADATA commit to avoid fragility in the case that any future package happens to depend on Example.jl --- base/pkg/pkg.jl | 34 ++++++++++++++----------- doc/src/manual/packages.md | 9 +++++++ test/pkg.jl | 52 +++++++++++++++++++++++++++++++++++++- 3 files changed, 79 insertions(+), 16 deletions(-) diff --git a/base/pkg/pkg.jl b/base/pkg/pkg.jl index c5d9836a0b949..53d23f5dd61e0 100644 --- a/base/pkg/pkg.jl +++ b/base/pkg/pkg.jl @@ -37,6 +37,10 @@ const cd = Dir.cd dir(path...) = Dir.path(path...) +# remove extension .jl +const PKGEXT = ".jl" +splitjl(pkg::AbstractString) = endswith(pkg, PKGEXT) ? pkg[1:(end-length(PKGEXT))] : pkg + """ dir() -> AbstractString @@ -90,7 +94,7 @@ edit() = cd(Entry.edit) Remove all requirement entries for `pkg` from `Pkg.dir("REQUIRE")` and call `Pkg.resolve()`. """ -rm(pkg::AbstractString) = cd(Entry.rm,pkg) +rm(pkg::AbstractString) = cd(Entry.rm,splitjl(pkg)) """ add(pkg, vers...) @@ -99,7 +103,7 @@ Add a requirement entry for `pkg` to `Pkg.dir("REQUIRE")` and call `Pkg.resolve( `vers` are given, they must be `VersionNumber` objects and they specify acceptable version intervals for `pkg`. """ -add(pkg::AbstractString, vers::VersionNumber...) = cd(Entry.add,pkg,vers...) +add(pkg::AbstractString, vers::VersionNumber...) = cd(Entry.add,splitjl(pkg),vers...) """ available() -> Vector{String} @@ -113,7 +117,7 @@ available() = cd(Entry.available) Returns the version numbers available for package `pkg`. """ -available(pkg::AbstractString) = cd(Entry.available,pkg) +available(pkg::AbstractString) = cd(Entry.available,splitjl(pkg)) """ installed() -> Dict{String,VersionNumber} @@ -129,7 +133,7 @@ installed() = cd(Entry.installed) If `pkg` is installed, return the installed version number. If `pkg` is registered, but not installed, return `nothing`. """ -installed(pkg::AbstractString) = cd(Entry.installed,pkg) +installed(pkg::AbstractString) = cd(Entry.installed,splitjl(pkg)) """ status() @@ -143,7 +147,7 @@ status(io::IO=STDOUT) = cd(Entry.status,io) Prints out a summary of what version and state `pkg`, specifically, is in. """ -status(pkg::AbstractString, io::IO=STDOUT) = cd(Entry.status,io,pkg) +status(pkg::AbstractString, io::IO=STDOUT) = cd(Entry.status,io,splitjl(pkg)) """ clone(pkg) @@ -160,7 +164,7 @@ Clone a package directly from the git URL `url`. The package does not need to be in `Pkg.dir("METADATA")`. The package repo is cloned by the name `pkg` if provided; if not provided, `pkg` is determined automatically from `url`. """ -clone(url::AbstractString, pkg::AbstractString) = cd(Entry.clone,url,pkg) +clone(url::AbstractString, pkg::AbstractString) = cd(Entry.clone,url,splitjl(pkg)) """ checkout(pkg, [branch="master"]; merge=true, pull=true) @@ -171,7 +175,7 @@ Checkout the `Pkg.dir(pkg)` repo to the branch `branch`. Defaults to checking ou true`, and the latest version is pulled from the upstream repo if `pull == true`. """ checkout(pkg::AbstractString, branch::AbstractString="master"; merge::Bool=true, pull::Bool=true) = - cd(Entry.checkout,pkg,branch,merge,pull) + cd(Entry.checkout,splitjl(pkg),branch,merge,pull) """ free(pkg) @@ -183,7 +187,7 @@ to determine optimal package versions after. This is an inverse for both `Pkg.ch You can also supply an iterable collection of package names, e.g., `Pkg.free(("Pkg1", "Pkg2"))` to free multiple packages at once. """ -free(pkg) = cd(Entry.free,pkg) +free(pkg) = cd(Entry.free,splitjl.(pkg)) """ pin(pkg) @@ -191,14 +195,14 @@ free(pkg) = cd(Entry.free,pkg) Pin `pkg` at the current version. To go back to using the newest compatible released version, use `Pkg.free(pkg)` """ -pin(pkg::AbstractString) = cd(Entry.pin,pkg) +pin(pkg::AbstractString) = cd(Entry.pin,splitjl(pkg)) """ pin(pkg, version) Pin `pkg` at registered version `version`. """ -pin(pkg::AbstractString, ver::VersionNumber) = cd(Entry.pin,pkg,ver) +pin(pkg::AbstractString, ver::VersionNumber) = cd(Entry.pin,splitjl(pkg),ver) """ update(pkgs...) @@ -236,7 +240,7 @@ Run the build script in `deps/build.jl` for each package in `pkgs` and all of th dependencies in depth-first recursive order. This is called automatically by `Pkg.resolve()` on all installed or updated packages. """ -build(pkgs::AbstractString...) = cd(Entry.build,[pkgs...]) +build(pkgs::AbstractString...) = cd(Entry.build,[splitjl.(pkgs)...]) """ test(; coverage=false) @@ -258,14 +262,14 @@ installed for the duration of the test. A package is tested by running its Coverage statistics for the packages may be generated by passing `coverage=true`. The default behavior is not to run coverage. """ -test(pkgs::AbstractString...; coverage::Bool=false) = cd(Entry.test,AbstractString[pkgs...]; coverage=coverage) +test(pkgs::AbstractString...; coverage::Bool=false) = cd(Entry.test,AbstractString[splitjl.(pkgs)...]; coverage=coverage) """ - dependents(packagename) + dependents(pkg) -List the packages that have `packagename` as a dependency. +List the packages that have `pkg` as a dependency. """ -dependents(packagename::AbstractString) = Reqs.dependents(packagename) +dependents(pkg::AbstractString) = Reqs.dependents(splitjl(pkg)) """ setprotocol!(proto) diff --git a/doc/src/manual/packages.md b/doc/src/manual/packages.md index 0eb96ac70ee6f..5213fdd3a421e 100644 --- a/doc/src/manual/packages.md +++ b/doc/src/manual/packages.md @@ -171,6 +171,15 @@ git config --global url."https://".insteadOf git:// However, this change will be system-wide and thus the use of [`Pkg.setprotocol!()`](@ref) is preferable. +!!! note + The package manager functions also accept the `.jl` suffix on package names, though the suffix is + stripped internally. For example: + + ```julia + Pkg.add("Distributions.jl") + Pkg.rm("Distributions.jl") + ``` + ## Offline Installation of Packages For machines with no Internet connection, packages may be installed by copying the package root diff --git a/test/pkg.jl b/test/pkg.jl index 9ecd1913d1082..357152eeb4b96 100644 --- a/test/pkg.jl +++ b/test/pkg.jl @@ -124,7 +124,6 @@ temp_pkg_dir() do Pkg.status("Example", iob) str = chomp(String(take!(iob))) @test endswith(str, string(Pkg.installed("Example"))) - @test isempty(Pkg.dependents("Example")) # 17364 - a, Pkg.checkout with specific local branch let branch_name = "test-branch-1", @@ -462,6 +461,11 @@ temp_pkg_dir() do LibGit2.reset!(repo, LibGit2.GitHash(old_commit), LibGit2.Consts.RESET_HARD) end + # run these at an old metadata commit where it's guaranteed no + # packages depend on Example.jl + @test isempty(Pkg.dependents("Example")) + @test isempty(Pkg.dependents("Example.jl")) + @test_warn ("INFO: Installing Colors v0.6.4", "INFO: Installing ColorTypes v0.2.2", "INFO: Installing FixedPointNumbers v0.1.3", @@ -496,6 +500,52 @@ temp_pkg_dir() do end end +@testset "Pkg functions with .jl extension" begin + temp_pkg_dir() do + @test Pkg.installed("Example.jl") === nothing + Pkg.add("Example.jl") + @test [keys(Pkg.installed())...] == ["Example"] + iob = IOBuffer() + Pkg.checkout("Example.jl") + Pkg.status("Example.jl", iob) + str = chomp(String(take!(iob))) + @test startswith(str, " - Example") + @test endswith(str, "master") + Pkg.free("Example.jl") + Pkg.status("Example.jl", iob) + str = chomp(String(take!(iob))) + @test endswith(str, string(Pkg.installed("Example.jl"))) + Pkg.checkout("Example.jl") + Pkg.free(("Example.jl",)) + Pkg.status("Example.jl", iob) + str = chomp(String(take!(iob))) + @test endswith(str, string(Pkg.installed("Example.jl"))) + Pkg.rm("Example.jl") + @test isempty(Pkg.installed()) + @test !isempty(Pkg.available("Example.jl")) + @test !in("Example", keys(Pkg.installed())) + Pkg.rm("Example.jl") + @test isempty(Pkg.installed()) + @test !isempty(Pkg.available("Example.jl")) + @test !in("Example", keys(Pkg.installed())) + Pkg.clone("https://github.com/JuliaLang/Example.jl.git") + @test [keys(Pkg.installed())...] == ["Example"] + Pkg.status("Example.jl", iob) + str = chomp(String(take!(iob))) + @test startswith(str, " - Example") + @test endswith(str, "master") + Pkg.free("Example.jl") + Pkg.status("Example.jl", iob) + str = chomp(String(take!(iob))) + @test endswith(str, string(Pkg.installed("Example.jl"))) + Pkg.checkout("Example.jl") + Pkg.free(("Example.jl",)) + Pkg.status("Example.jl", iob) + str = chomp(String(take!(iob))) + @test endswith(str, string(Pkg.installed("Example.jl"))) + end +end + let io = IOBuffer() Base.showerror(io, Base.Pkg.Entry.PkgTestError("ppp"), backtrace()) @test !contains(String(take!(io)), "backtrace()") From 01b0881ac86869d2cc0824d7eb5c659c483a0d94 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Mon, 27 Feb 2017 22:01:02 -0500 Subject: [PATCH 0090/1534] Remove incorrect JL_GC_POP jl_method_error roots all margs other than margs[0], so margs[0] could have been GCed. Fix that by removing the JL_GC_POP --- src/ast.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ast.c b/src/ast.c index 28d871ecf8407..b8845d2e26ca8 100644 --- a/src/ast.c +++ b/src/ast.c @@ -192,7 +192,6 @@ value_t fl_invoke_julia_macro(fl_context_t *fl_ctx, value_t *args, uint32_t narg margs[0] = jl_toplevel_eval(margs[0]); mfunc = jl_method_lookup(jl_gf_mtable(margs[0]), margs, nargs, 1, world); if (mfunc == NULL) { - JL_GC_POP(); jl_method_error((jl_function_t*)margs[0], margs, nargs, world); // unreachable } From 69f0653317392812a2018f86e1d9f478913eeef9 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Tue, 28 Feb 2017 04:59:08 -0800 Subject: [PATCH 0091/1534] partially revert #20806 (#20838) there are other ways to fix this that don't require changing compiler flags in the default build configuration --- deps/blas.mk | 5 ----- 1 file changed, 5 deletions(-) diff --git a/deps/blas.mk b/deps/blas.mk index d8f2484156ffa..0acd97947a3a1 100644 --- a/deps/blas.mk +++ b/deps/blas.mk @@ -49,11 +49,6 @@ endif OPENBLAS_FFLAGS := OPENBLAS_CFLAGS := -# Work around OpenBLAS#942 -ifeq ($(USECLANG),1) -OPENBLAS_CFLAGS += -no-integrated-as -endif - # Decide whether to build for 32-bit or 64-bit arch ifneq ($(BUILD_OS),$(OS)) OPENBLAS_BUILD_OPTS += OSNAME=$(OS) CROSS=1 HOSTCC=$(HOSTCC) CROSS_SUFFIX=$(CROSS_COMPILE) From 29bc2acd945e74a067d2904c59ab461a1a145e26 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Tue, 28 Feb 2017 05:15:45 -0800 Subject: [PATCH 0092/1534] feature freeze master for 0.6-pre (#20762) --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index fb0b754233e49..400d7dd6ed0c7 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.6.0-dev +0.6.0-pre.alpha From b1242dff002bbc8d26815b727fc122c1eb8aec01 Mon Sep 17 00:00:00 2001 From: Fengyang Wang Date: Tue, 28 Feb 2017 13:33:35 -0500 Subject: [PATCH 0093/1534] improve performance of print(DevNull, x) (#20830) improve performance of print(DevNull, x) --- base/coreio.jl | 1 + base/strings/string.jl | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/base/coreio.jl b/base/coreio.jl index 2035aae97abe9..f47286f9ea62d 100644 --- a/base/coreio.jl +++ b/base/coreio.jl @@ -12,6 +12,7 @@ iswritable(::DevNullStream) = true isopen(::DevNullStream) = true read(::DevNullStream, ::Type{UInt8}) = throw(EOFError()) write(::DevNullStream, ::UInt8) = 1 +unsafe_write(::DevNullStream, ::Ptr{UInt8}, n::UInt)::Int = n close(::DevNullStream) = nothing flush(::DevNullStream) = nothing wait_connected(::DevNullStream) = nothing diff --git a/base/strings/string.jl b/base/strings/string.jl index e7bad62e86613..4573045acfb56 100644 --- a/base/strings/string.jl +++ b/base/strings/string.jl @@ -68,7 +68,7 @@ codeunit(s::AbstractString, i::Integer) unsafe_load(pointer(s),i) end -write(io::IO, s::String) = unsafe_write(io, pointer(s), UInt(s.len)) +write(io::IO, s::String) = unsafe_write(io, pointer(s), reinterpret(UInt, s.len)) ## comparison ## From e9a4e41f5017bb1c8bcb0ce77b52fad8cc102610 Mon Sep 17 00:00:00 2001 From: tan Date: Tue, 28 Feb 2017 22:32:59 +0530 Subject: [PATCH 0094/1534] avoid unnecessary precompilation on GlusterFS While comparing timestamps of precompiled images, check for possibility of truncation at microsecond level. fixes #20837 --- base/loading.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/base/loading.jl b/base/loading.jl index aa746cdb01820..4242121aa6b08 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -765,8 +765,9 @@ function stale_cachefile(modpath::String, cachefile::String) end for (f, ftime_req) in files # Issue #13606: compensate for Docker images rounding mtimes + # Issue #20837: compensate for GlusterFS truncating mtimes to microseconds ftime = mtime(f) - if ftime != ftime_req && ftime != floor(ftime_req) + if ftime != ftime_req && ftime != floor(ftime_req) && ftime != trunc(ftime_req, 6) DEBUG_LOADING[] && info("JL_DEBUG_LOADING: Rejecting stale cache file $cachefile (mtime $ftime_req) because file $f (mtime $ftime) has changed.") return true end From 833380d9a2ab8c329e461defcf41c73a7b944f98 Mon Sep 17 00:00:00 2001 From: Katie Hyatt Date: Tue, 28 Feb 2017 15:24:13 -0800 Subject: [PATCH 0095/1534] Fix bug in diff_files, add test --- base/libgit2/libgit2.jl | 4 ++-- test/libgit2.jl | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/base/libgit2/libgit2.jl b/base/libgit2/libgit2.jl index 113946fb3ac02..edba09be9bba3 100644 --- a/base/libgit2/libgit2.jl +++ b/base/libgit2/libgit2.jl @@ -136,7 +136,7 @@ Returns only the *names* of the files which have changed, *not* their contents. Equivalent to `git diff --name-only --diff-filter= `. """ function diff_files(repo::GitRepo, branch1::AbstractString, branch2::AbstractString; - filter::Set{Cint}=Set([Consts.DELTA_ADDED, Consts.DELTA_MODIFIED, Consts.DELTA_DELETED])) + filter::Set{Consts.DELTA_STATUS}=Set([Consts.DELTA_ADDED, Consts.DELTA_MODIFIED, Consts.DELTA_DELETED])) b1_id = revparseid(repo, branch1*"^{tree}") b2_id = revparseid(repo, branch2*"^{tree}") tree1 = GitTree(repo, b1_id) @@ -147,7 +147,7 @@ function diff_files(repo::GitRepo, branch1::AbstractString, branch2::AbstractStr for i in 1:count(diff) delta = diff[i] delta === nothing && break - if delta.status in filter + if Consts.DELTA_STATUS(delta.status) in filter push!(files, unsafe_string(delta.new_file.path)) end end diff --git a/test/libgit2.jl b/test/libgit2.jl index c2f0e6ae711b3..bd5352f368aa4 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -778,6 +778,10 @@ mktempdir() do dir newhead = LibGit2.head_oid(repo) + files = LibGit2.diff_files(repo, "branch/a", "branch/b", filter=Set([LibGit2.Consts.DELTA_ADDED])) + @test files == ["file3"] + files = LibGit2.diff_files(repo, "branch/a", "branch/b", filter=Set([LibGit2.Consts.DELTA_MODIFIED])) + @test files == [] # switch back and rebase LibGit2.branch!(repo, "branch/a") newnewhead = LibGit2.rebase!(repo, "branch/b") From 420ef00778358bc5dab279aac536dd8f7a1e2f3a Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Tue, 28 Feb 2017 16:46:09 -0800 Subject: [PATCH 0096/1534] Fix doc dependency of light-source-dist target --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 27b1fb43f806c..965aadb972cd9 100644 --- a/Makefile +++ b/Makefile @@ -481,7 +481,7 @@ endif rm -fr $(BUILDROOT)/julia-$(JULIA_COMMIT) # this target does not accept BUILDROOT -light-source-dist.tmp: $(JULIAHOME)/doc/_build/html +light-source-dist.tmp: $(BUILDROOT)/doc/_build/html/en/index.html # Save git information -@$(MAKE) -C $(JULIAHOME)/base version_git.jl.phony From 7cb3b101d3d60eb89e28cb9cbee35f1e814ce781 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Wed, 22 Feb 2017 12:30:51 -0800 Subject: [PATCH 0097/1534] include in codegen.cpp otherwise msvc complains function is not a member of std --- src/codegen.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/codegen.cpp b/src/codegen.cpp index 4d4ec294e5f0e..4fc45673d88da 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -33,6 +33,7 @@ #include #include #include +#include // target machine computation #include From c50bd12819b085a097178b870c3c3a2b3f2cd2ba Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Thu, 9 Feb 2017 12:14:08 -0800 Subject: [PATCH 0098/1534] adjust ci branch whitelist regexes to only count branches that start with release-* instead of contains --- .travis.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9f44a43f0aca8..13f60015e5c17 100644 --- a/.travis.yml +++ b/.travis.yml @@ -44,7 +44,7 @@ cache: branches: only: - master - - /release-.*/ + - /^release-.*/ notifications: email: false irc: diff --git a/appveyor.yml b/appveyor.yml index 312c8da24cdef..be29747bf7d14 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -11,7 +11,7 @@ environment: branches: only: - master - - /release-.*/ + - /^release-.*/ skip_commits: # Add [av skip] to commit messages for docfixes, etc to reduce load on queue From 51e48a89f4eec868be678d171fb06fec8a2b887a Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Tue, 21 Feb 2017 14:33:39 -0800 Subject: [PATCH 0099/1534] left align preprocessor conditionals --- src/ccall.cpp | 8 ++++---- src/cgutils.cpp | 12 ++++++------ src/codegen.cpp | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/ccall.cpp b/src/ccall.cpp index a38ab2c112ccf..62f62e67c3ec8 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -851,10 +851,10 @@ class FunctionMover final : public ValueMaterializer VMap[&*I] = &*(DestI++); // Add mapping to VMap } - #if JL_LLVM_VERSION >= 30600 +#if JL_LLVM_VERSION >= 30600 // Clone debug info - Not yet public API // llvm::CloneDebugInfoMetadata(NewF,F,VMap); - #endif +#endif SmallVector Returns; llvm::CloneFunctionInto(NewF,F,VMap,true,Returns,"",NULL,NULL,this); @@ -912,10 +912,10 @@ class FunctionMover final : public ValueMaterializer if (oldF) return oldF; - #ifdef USE_ORCJIT +#ifdef USE_ORCJIT if (jl_ExecutionEngine->findSymbol(F->getName(), false)) return InjectFunctionProto(F); - #endif +#endif return CloneFunctionProto(shadow); } diff --git a/src/cgutils.cpp b/src/cgutils.cpp index bf41d5e6ed557..338db64dfbc7e 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -153,14 +153,14 @@ static DIType julia_type_to_di(jl_value_t *jt, DIBuilder *dbuilder, bool isboxed } if (jl_is_primitivetype(jt)) { uint64_t SizeInBits = jl_datatype_nbits(jdt); - #if JL_LLVM_VERSION >= 40000 +#if JL_LLVM_VERSION >= 40000 llvm::DIType *t = dbuilder->createBasicType( jl_symbol_name(jdt->name->name), SizeInBits, llvm::dwarf::DW_ATE_unsigned); jdt->ditype = t; return t; - #elif JL_LLVM_VERSION >= 30700 +#elif JL_LLVM_VERSION >= 30700 llvm::DIType *t = dbuilder->createBasicType( jl_symbol_name(jdt->name->name), SizeInBits, @@ -168,7 +168,7 @@ static DIType julia_type_to_di(jl_value_t *jt, DIBuilder *dbuilder, bool isboxed llvm::dwarf::DW_ATE_unsigned); jdt->ditype = t; return t; - #else +#else DIType t = dbuilder->createBasicType( jl_symbol_name(jdt->name->name), SizeInBits, @@ -177,9 +177,9 @@ static DIType julia_type_to_di(jl_value_t *jt, DIBuilder *dbuilder, bool isboxed MDNode *M = t; jdt->ditype = M; return t; - #endif +#endif } - #if JL_LLVM_VERSION >= 30700 +#if JL_LLVM_VERSION >= 30700 else if (!jl_is_leaf_type(jt)) { jdt->ditype = jl_pvalue_dillvmt; return jl_pvalue_dillvmt; @@ -217,7 +217,7 @@ static DIType julia_type_to_di(jl_value_t *jt, DIBuilder *dbuilder, bool isboxed jl_symbol_name(jdt->name->name), NULL, 0, NULL); return (llvm::DIType*)jdt->ditype; } - #endif +#endif // TODO: Fixme return jl_pvalue_dillvmt; } diff --git a/src/codegen.cpp b/src/codegen.cpp index 4fc45673d88da..d13c98bcf603b 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1213,11 +1213,11 @@ jl_llvm_functions_t jl_compile_linfo(jl_method_instance_t **pli, jl_code_info_t bool toplevel = li->def == NULL; if (!toplevel) { const DataLayout &DL = - #if JL_LLVM_VERSION >= 30500 +#if JL_LLVM_VERSION >= 30500 m->getDataLayout(); - #else +#else *jl_data_layout; - #endif +#endif // but don't remember toplevel thunks because // they may not be rooted in the gc for the life of the program, // and the runtime doesn't notify us when the code becomes unreachable :( From 906917ba14f7e986f5b819e9a3b94adfeaf705bf Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Tue, 28 Feb 2017 19:34:39 -0800 Subject: [PATCH 0100/1534] Automate uploads to s3 using aws cli in prepare_release.sh --- contrib/prepare_release.sh | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/contrib/prepare_release.sh b/contrib/prepare_release.sh index 6a703733e03b3..1a0aee5b9db75 100755 --- a/contrib/prepare_release.sh +++ b/contrib/prepare_release.sh @@ -69,7 +69,30 @@ gpg -u julia --armor --detach-sig julia-$version-linux-i686.tar.gz gpg -u julia --armor --detach-sig julia-$version-linux-arm.tar.gz gpg -u julia --armor --detach-sig julia-$version-linux-ppc64le.tar.gz -echo "All files prepared. Attach julia-$version.tar.gz and julia-$version-full.tar.gz" -echo "to github releases, upload all binaries and checksums to julialang S3. Be sure" -echo "to set all S3 uploads to publicly readable, and replace $majmin-latest binaries." -# TODO: also automate uploads via aws cli and github api? +aws configure +aws s3 cp --acl public-read julia-$version.sha256 s3://julialang/bin/checksums/ +aws s3 cp --acl public-read julia-$version.md5 s3://julialang/bin/checksums/ +for plat in x86_64 i686 arm ppc64le; do + platshort=$(echo $plat | sed -e 's/x86_64/x64/' -e 's/i686/x86/') + aws s3 cp --acl public-read julia-$version-linux-$plat.tar.gz \ + s3://julialang/bin/linux/$platshort/$majmin/ + aws s3 cp --acl public-read julia-$version-linux-$plat.tar.gz.asc \ + s3://julialang/bin/linux/$platshort/$majmin/ + aws s3 cp --acl public-read julia-$majmin-latest-linux-$plat.tar.gz \ + s3://julialang/bin/linux/$platshort/$majmin/ +done +aws s3 cp --acl public-read "julia-$version-osx10.7 .dmg" \ + s3://julialang/bin/osx/x64/$majmin/ +aws s3 cp --acl public-read "julia-$majmin-latest-osx10.7 .dmg" \ + s3://julialang/bin/osx/x64/$majmin/ +aws s3 cp --acl public-read "julia-$version-win64.exe" \ + s3://julialang/bin/winnt/x64/$majmin/ +aws s3 cp --acl public-read "julia-$majmin-latest-win64.exe" \ + s3://julialang/bin/winnt/x64/$majmin/ +aws s3 cp --acl public-read "julia-$version-win32.exe" \ + s3://julialang/bin/winnt/x86/$majmin/ +aws s3 cp --acl public-read "julia-$majmin-latest-win32.exe" \ + s3://julialang/bin/winnt/x86/$majmin/ + +echo "All files prepared. Attach julia-$version.tar.gz" +echo "and julia-$version-full.tar.gz to github releases." From aee6dd66aa5656983cfb261508145b2f9ba136f4 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Wed, 1 Mar 2017 07:30:29 -0800 Subject: [PATCH 0101/1534] keep reference to repo in GitDiffStats (#20785) --- base/libgit2/diff.jl | 2 +- base/libgit2/types.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/base/libgit2/diff.jl b/base/libgit2/diff.jl index 65766185b73e5..49836e2df4d3d 100644 --- a/base/libgit2/diff.jl +++ b/base/libgit2/diff.jl @@ -39,7 +39,7 @@ function GitDiffStats(diff::GitDiff) @check ccall((:git_diff_get_stats, :libgit2), Cint, (Ptr{Ptr{Void}}, Ptr{Void}), diff_stat_ptr_ptr, diff.ptr) - return GitDiffStats(diff_stat_ptr_ptr[]) + return GitDiffStats(diff.owner, diff_stat_ptr_ptr[]) end function files_changed(diff_stat::GitDiffStats) diff --git a/base/libgit2/types.jl b/base/libgit2/types.jl index 14b398bc734e5..e688792c8ee46 100644 --- a/base/libgit2/types.jl +++ b/base/libgit2/types.jl @@ -482,13 +482,13 @@ abstract type GitObject <: AbstractGitObject end for (typ, owntyp, sup, cname) in [ (:GitRepo, nothing, :AbstractGitObject, :git_repository), - (:GitDiffStats, nothing, :AbstractGitObject, :git_diff_stats), (:GitConfig, :(Nullable{GitRepo}), :AbstractGitObject, :git_config), (:GitIndex, :(Nullable{GitRepo}), :AbstractGitObject, :git_index), (:GitRemote, :GitRepo, :AbstractGitObject, :git_remote), (:GitRevWalker, :GitRepo, :AbstractGitObject, :git_revwalk), (:GitReference, :GitRepo, :AbstractGitObject, :git_reference), (:GitDiff, :GitRepo, :AbstractGitObject, :git_diff), + (:GitDiffStats, :GitRepo, :AbstractGitObject, :git_diff_stats), (:GitAnnotated, :GitRepo, :AbstractGitObject, :git_annotated_commit), (:GitRebase, :GitRepo, :AbstractGitObject, :git_rebase), (:GitStatus, :GitRepo, :AbstractGitObject, :git_status_list), From b0d222043036155c30d3e4547f3900f972486b11 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Wed, 1 Mar 2017 11:29:01 -0600 Subject: [PATCH 0102/1534] Make length for Date ranges type stable (#20839) --- base/dates/ranges.jl | 2 +- test/dates/ranges.jl | 24 ++++++++++++++++-------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/base/dates/ranges.jl b/base/dates/ranges.jl index bd853f68e5b06..3f9717fb21495 100644 --- a/base/dates/ranges.jl +++ b/base/dates/ranges.jl @@ -25,7 +25,7 @@ function len(a, b, c) end return i - 1 end -Base.length(r::StepRange{<:TimeType}) = isempty(r) ? 0 : len(r.start, r.stop, r.step) + 1 +Base.length(r::StepRange{<:TimeType}) = isempty(r) ? Int64(0) : len(r.start, r.stop, r.step) + 1 # Period ranges hook into Int64 overflow detection Base.length(r::StepRange{<:Period}) = length(StepRange(value(r.start), value(r.step), value(r.stop))) diff --git a/test/dates/ranges.jl b/test/dates/ranges.jl index 622382b9c6da3..87ed8beaa0d9f 100644 --- a/test/dates/ranges.jl +++ b/test/dates/ranges.jl @@ -11,7 +11,9 @@ let for pos_step in (P(1), P(2), P(50), P(2048), P(10000)) # empty range dr = f1:pos_step:l1 - @test length(dr) == 0 + len = length(dr) + @test len == 0 + @test isa(len, Int64) @test isempty(dr) @test first(dr) == f1 @test last(dr) < f1 @@ -36,7 +38,7 @@ let dr = f:pos_step:l len = length(dr) @test len > 0 - @test typeof(len) <: Int64 + @test isa(len, Int64) @test !isempty(dr) @test first(dr) == f @test last(dr) <= l @@ -63,7 +65,9 @@ let for neg_step in (P(-1), P(-2), P(-50), P(-2048), P(-10000)) # empty range dr = l1:neg_step:f1 - @test length(dr) == 0 + len = length(dr) + @test len == 0 + @test isa(len, Int64) @test isempty(dr) @test first(dr) == l1 @test last(dr) > l1 @@ -88,7 +92,7 @@ let dr = l:neg_step:f len = length(dr) @test len > 0 - @test typeof(len) <: Int64 + @test isa(len, Int64) @test !isempty(dr) @test first(dr) == l @test last(dr) >= f @@ -117,7 +121,9 @@ let for pos_step in (P(1), P(2), P(50), P(2048), P(10000)) # empty range dr = f1:pos_step:l1 - @test length(dr) == 0 + len = length(dr) + @test len == 0 + @test isa(len, Int64) @test isempty(dr) @test first(dr) == f1 @test last(dr) < f1 @@ -142,7 +148,7 @@ let dr = f:pos_step:l len = length(dr) @test len > 0 - @test typeof(len) <: Int64 + @test isa(len, Int64) @test !isempty(dr) @test first(dr) == f @test last(dr) <= l @@ -169,7 +175,9 @@ let for neg_step in (P(-1), P(-2), P(-50), P(-2048), P(-10000)) # empty range dr = l1:neg_step:f1 - @test length(dr) == 0 + len = length(dr) + @test len == 0 + @test isa(len, Int64) @test isempty(dr) @test first(dr) == l1 @test last(dr) > l1 @@ -194,7 +202,7 @@ let dr = l:neg_step:f len = length(dr) @test len > 0 - @test typeof(len) <: Int64 + @test isa(len, Int64) @test !isempty(dr) @test first(dr) == l @test last(dr) >= f From fa9b0c9f8d0fb2991ca2697f29aa0bd373ad9415 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Sat, 25 Feb 2017 00:21:29 -0500 Subject: [PATCH 0103/1534] add debugging code for inspecting which backedges are getting invalidated (and why) when defining a new method --- src/gf.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/gf.c b/src/gf.c index 79b6ea7ca7567..4a8258bc5dfe3 100644 --- a/src/gf.c +++ b/src/gf.c @@ -1216,22 +1216,31 @@ static void update_max_args(jl_methtable_t *mt, jl_value_t *type) mt->max_args = na; } +static int JL_DEBUG_METHOD_INVALIDATION = 0; // invalidate cached methods that had an edge to a replaced method -static void invalidate_method_instance(jl_method_instance_t *replaced, size_t max_world) +static void invalidate_method_instance(jl_method_instance_t *replaced, size_t max_world, int depth) { JL_LOCK_NOGC(&replaced->def->writelock); jl_array_t *backedges = replaced->backedges; if (replaced->max_world > max_world) { // recurse to all backedges to update their valid range also assert(replaced->min_world <= max_world && "attempting to set invalid world constraints"); + if (JL_DEBUG_METHOD_INVALIDATION) { + int d0 = depth; + char space = ' ', nl = '\n'; + while (d0-- > 0) + jl_uv_puts(JL_STDOUT, &space, 1); + jl_static_show(JL_STDOUT, (jl_value_t*)replaced); + jl_uv_puts(JL_STDOUT, &nl, 1); + } replaced->max_world = max_world; update_world_bound(replaced, set_max_world2, max_world); if (backedges) { size_t i, l = jl_array_len(backedges); for (i = 0; i < l; i++) { jl_method_instance_t *replaced = (jl_method_instance_t*)jl_array_ptr_ref(backedges, i); - invalidate_method_instance(replaced, max_world); + invalidate_method_instance(replaced, max_world, depth + 1); } } } @@ -1268,7 +1277,7 @@ static int invalidate_backedges(jl_typemap_entry_t *oldentry, struct typemap_int size_t i, l = jl_array_len(backedges); jl_method_instance_t **replaced = (jl_method_instance_t**)jl_array_data(backedges); for (i = 0; i < l; i++) { - invalidate_method_instance(replaced[i], closure->max_world); + invalidate_method_instance(replaced[i], closure->max_world, 0); } } def.replaced->backedges = NULL; @@ -1357,7 +1366,7 @@ JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method jl_value_t *backedgetyp = backedges[i - 1]; if (jl_type_intersection(backedgetyp, (jl_value_t*)type) != (jl_value_t*)jl_bottom_type) { jl_method_instance_t *backedge = (jl_method_instance_t*)backedges[i]; - invalidate_method_instance(backedge, env.max_world); + invalidate_method_instance(backedge, env.max_world, 0); } else { backedges[ins++] = backedges[i - 1]; From c716e638bba74f52114c7adedfe4a653e42c40d0 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Wed, 1 Mar 2017 10:29:10 -0800 Subject: [PATCH 0104/1534] Backport openblas patch to fix compilation of assembly with clang 3.9 (#20842) this version should avoid breaking the mac build --- deps/blas.mk | 7 +- deps/patches/openblas-clangasmbug.patch | 856 ++++++++++++++++++++++++ 2 files changed, 862 insertions(+), 1 deletion(-) create mode 100644 deps/patches/openblas-clangasmbug.patch diff --git a/deps/blas.mk b/deps/blas.mk index 0acd97947a3a1..2c70c0b745087 100644 --- a/deps/blas.mk +++ b/deps/blas.mk @@ -86,7 +86,12 @@ $(BUILDDIR)/$(OPENBLAS_SRC_DIR)/openblas-freebsd.patch-applied: $(BUILDDIR)/$(OP cd $(BUILDDIR)/$(OPENBLAS_SRC_DIR) && patch -p0 -f < $(SRCDIR)/patches/openblas-freebsd.patch echo 1 > $@ -$(BUILDDIR)/$(OPENBLAS_SRC_DIR)/build-configured: $(BUILDDIR)/$(OPENBLAS_SRC_DIR)/openblas-freebsd.patch-applied +# Clang assembler bug workaround from https://github.com/xianyi/OpenBLAS/pull/982 +$(BUILDDIR)/$(OPENBLAS_SRC_DIR)/openblas-clangasmbug.patch-applied: $(BUILDDIR)/$(OPENBLAS_SRC_DIR)/openblas-freebsd.patch-applied + cd $(BUILDDIR)/$(OPENBLAS_SRC_DIR) && patch -p1 -f < $(SRCDIR)/patches/openblas-clangasmbug.patch + echo 1 > $@ + +$(BUILDDIR)/$(OPENBLAS_SRC_DIR)/build-configured: $(BUILDDIR)/$(OPENBLAS_SRC_DIR)/openblas-clangasmbug.patch-applied perl -i -ple 's/^\s*(EXTRALIB\s*\+=\s*-lSystemStubs)\s*$$/# $$1/g' $(dir $<)/Makefile.system echo 1 > $@ diff --git a/deps/patches/openblas-clangasmbug.patch b/deps/patches/openblas-clangasmbug.patch new file mode 100644 index 0000000000000..11c85f68f0247 --- /dev/null +++ b/deps/patches/openblas-clangasmbug.patch @@ -0,0 +1,856 @@ +commit 3705f5675ae45f3cc662927db1955701cf73d95b (from ef52a9266ba8900774a1f3e77561c5c8a75c5828) +Merge: ef52a92 bce2b34 +Author: Zhang Xianyi +Date: Mon Oct 17 11:32:20 2016 +0800 + + Merge pull request #982 from martin-frbg/develop + + Change file comments to work around clang 3.9 assembler bug; add support for Bay Trail atom + +diff --git a/cpuid_x86.c b/cpuid_x86.c +index bbd377f..dff1507 100644 +--- a/cpuid_x86.c ++++ b/cpuid_x86.c +@@ -1110,6 +1110,9 @@ int get_cpuname(void){ + break; + case 3: + switch (model) { ++ case 7: ++ // Bay Trail ++ return CPUTYPE_ATOM; + case 10: + case 14: + // Ivy Bridge +diff --git a/driver/others/dynamic.c b/driver/others/dynamic.c +index 18f85c3..a09660f 100644 +--- a/driver/others/dynamic.c ++++ b/driver/others/dynamic.c +@@ -232,6 +232,7 @@ static gotoblas_t *get_coretype(void){ + return &gotoblas_NEHALEM; //OS doesn't support AVX. Use old kernels. + } + } ++ if (model == 7) return &gotoblas_ATOM; //Bay Trail + return NULL; + case 4: + //Intel Haswell +diff --git a/kernel/x86_64/dgemm_kernel_4x8_sandy.S b/kernel/x86_64/dgemm_kernel_4x8_sandy.S +index a52bb07..926395c 100644 +--- a/kernel/x86_64/dgemm_kernel_4x8_sandy.S ++++ b/kernel/x86_64/dgemm_kernel_4x8_sandy.S +@@ -277,7 +277,7 @@ LEAQ (, %rax, SIZE), %rax; + LEAQ (ptrba, %rax, 8), ptrba; + LEAQ (ptrbb, %rax, 4), ptrbb; + #endif +-#### Initial Results Register #### ++//#### Initial Results Register #### + PREFETCH2 0*SIZE(prebb); + XOR_DY yvec15, yvec15, yvec15; + PREFETCH2 8*SIZE(prebb); +@@ -317,7 +317,7 @@ ALIGN_5; + .L2_bodyB:; + # Computing kernel + +-#### Unroll times 1 #### ++//#### Unroll times 1 #### + LD_DY 4*SIZE(ptrba), yvec1; + MUL_DY yvec0, yvec2, yvec6; + SHUF_DY $0x03, yvec2, yvec2, yvec4; +@@ -345,7 +345,7 @@ MUL_DY yvec1, yvec5, yvec7; + ADD_DY yvec10, yvec6, yvec10; + ADD_DY yvec8, yvec7, yvec8; + +-#### Unroll times 2 #### ++//#### Unroll times 2 #### + LD_DY 12*SIZE(ptrba), yvec1; + MUL_DY yvec0, yvec2, yvec6; + SHUF_DY $0x03, yvec2, yvec2, yvec4; +@@ -373,7 +373,7 @@ MUL_DY yvec1, yvec5, yvec7; + ADD_DY yvec10, yvec6, yvec10; + ADD_DY yvec8, yvec7, yvec8; + +-#### Unroll times 3 #### ++//#### Unroll times 3 #### + LD_DY 20*SIZE(ptrba), yvec1; + MUL_DY yvec0, yvec2, yvec6; + SHUF_DY $0x03, yvec2, yvec2, yvec4; +@@ -402,7 +402,7 @@ MUL_DY yvec1, yvec5, yvec7; + ADD_DY yvec10, yvec6, yvec10; + ADD_DY yvec8, yvec7, yvec8; + +-#### Unroll times 4 #### ++//#### Unroll times 4 #### + LD_DY 28*SIZE(ptrba), yvec1; + MUL_DY yvec0, yvec2, yvec6; + SHUF_DY $0x03, yvec2, yvec2, yvec4; +@@ -446,7 +446,7 @@ TEST $2, %rax; + JLE .L3_loopE; + ALIGN_5 + .L3_bodyB: +-#### Unroll times 1 #### ++//#### Unroll times 1 #### + PREFETCH0 64*SIZE(ptrba) + LD_DY 4*SIZE(ptrba), yvec1; + MUL_DY yvec0, yvec2, yvec6; +@@ -475,7 +475,7 @@ MUL_DY yvec1, yvec5, yvec7; + ADD_DY yvec10, yvec6, yvec10; + ADD_DY yvec8, yvec7, yvec8; + +-#### Unroll times 2 #### ++//#### Unroll times 2 #### + PREFETCH0 72*SIZE(ptrba) + LD_DY 12*SIZE(ptrba), yvec1; + MUL_DY yvec0, yvec2, yvec6; +@@ -516,7 +516,7 @@ TEST $1, %rax; + JLE .L4_loopE; + ALIGN_5 + .L4_bodyB:; +-#### Unroll times 1 #### ++//#### Unroll times 1 #### + PREFETCH0 64*SIZE(ptrba) + LD_DY 4*SIZE(ptrba), yvec1; + MUL_DY yvec0, yvec2, yvec6; +@@ -544,9 +544,9 @@ ADD_DY yvec10, yvec6, yvec10; + ADD_DY yvec8, yvec7, yvec8; + + .L4_loopE:; +-#### Load Alpha #### ++//#### Load Alpha #### + BROAD_DY MEMALPHA,yvec7; +-#### Multiply Alpha #### ++//#### Multiply Alpha #### + MUL_DY yvec7,yvec15,yvec15; + MUL_DY yvec7,yvec14,yvec14; + MUL_DY yvec7,yvec13,yvec13; +@@ -555,7 +555,7 @@ MUL_DY yvec7,yvec11,yvec11; + MUL_DY yvec7,yvec10,yvec10; + MUL_DY yvec7,yvec9,yvec9; + MUL_DY yvec7,yvec8,yvec8; +-#### Reverse the Results #### ++//#### Reverse the Results #### + MOV_DY yvec15,yvec7; + REVS_DY $0x0a,yvec13,yvec15,yvec15; + REVS_DY $0x0a,yvec7,yvec13,yvec13; +@@ -568,13 +568,13 @@ REVS_DY $0x0a,yvec7,yvec9,yvec9; + MOV_DY yvec10,yvec7; + REVS_DY $0x0a,yvec8,yvec10,yvec10; + REVS_DY $0x0a,yvec7,yvec8,yvec8; +-#### Testing alignment #### ++//#### Testing alignment #### + MOVQ C0, %rax; + OR ldc, %rax; + TEST $15, %rax; + JNE .L4_loopEx; # Unalign part write back + ALIGN_5 +-#### Writing Back #### ++//#### Writing Back #### + EXTRA_DY $1,yvec15,xvec7; + EXTRA_DY $1,yvec14,xvec6; + EXTRA_DY $1,yvec13,xvec5; +@@ -776,7 +776,7 @@ LEAQ (, %rax, SIZE), %rax; + LEAQ (ptrba, %rax, 4), ptrba; + LEAQ (ptrbb, %rax, 4), ptrbb; + #endif +-#### Initial Results Register #### ++//#### Initial Results Register #### + XOR_DY yvec15, yvec15, yvec15; + XOR_DY yvec13, yvec13, yvec13; + LD_DY 0*SIZE(ptrbb), yvec2; +@@ -805,7 +805,7 @@ ALIGN_5; + .L6_bodyB:; + # Computing kernel + +-#### Untoll time 1 #### ++//#### Untoll time 1 #### + LD_DY 4*SIZE(ptrba), yvec1; + MUL_DY yvec0, yvec2, yvec6; + ADD_DY yvec15, yvec6, yvec15; +@@ -821,7 +821,7 @@ VPERMILP_DY $0x05, yvec2, yvec3; + MUL_DY yvec0, yvec5, yvec7; + ADD_DY yvec9, yvec7, yvec9; + +-#### Untoll time 2 #### ++//#### Untoll time 2 #### + LD_DY 8*SIZE(ptrba), yvec0; + MUL_DY yvec1, yvec2, yvec6; + ADD_DY yvec15, yvec6, yvec15; +@@ -837,7 +837,7 @@ VPERMILP_DY $0x05, yvec2, yvec3; + MUL_DY yvec1, yvec5, yvec7; + ADD_DY yvec9, yvec7, yvec9; + +-#### Untoll time 3 #### ++//#### Untoll time 3 #### + LD_DY 12*SIZE(ptrba), yvec1; + MUL_DY yvec0, yvec2, yvec6; + ADD_DY yvec15, yvec6, yvec15; +@@ -855,7 +855,7 @@ ADDQ $16*SIZE, ptrbb; + MUL_DY yvec0, yvec5, yvec7; + ADD_DY yvec9, yvec7, yvec9; + +-#### Untoll time 4 #### ++//#### Untoll time 4 #### + LD_DY 0*SIZE(ptrba), yvec0; + MUL_DY yvec1, yvec2, yvec6; + ADD_DY yvec15, yvec6, yvec15; +@@ -883,7 +883,7 @@ TEST $2, %rax; + JLE .L7_loopE; + ALIGN_5 + .L7_bodyB:; +-#### Untoll time 1 #### ++//#### Untoll time 1 #### + LD_DY 4*SIZE(ptrba), yvec1; + MUL_DY yvec0, yvec2, yvec6; + ADD_DY yvec15, yvec6, yvec15; +@@ -901,7 +901,7 @@ ADDQ $8*SIZE, ptrbb; + MUL_DY yvec0, yvec5, yvec7; + ADD_DY yvec9, yvec7, yvec9; + +-#### Untoll time 2 #### ++//#### Untoll time 2 #### + LD_DY 0*SIZE(ptrba), yvec0; + MUL_DY yvec1, yvec2, yvec6; + ADD_DY yvec15, yvec6, yvec15; +@@ -927,7 +927,7 @@ TEST $1, %rax; + JLE .L8_loopE; + ALIGN_5 + .L8_bodyB:; +-#### Untoll time 1 #### ++//#### Untoll time 1 #### + MUL_DY yvec0, yvec2, yvec6; + ADD_DY yvec15, yvec6, yvec15; + SHUF_DY $0x03, yvec2, yvec2, yvec4; +@@ -943,27 +943,27 @@ MUL_DY yvec0, yvec5, yvec7; + ADD_DY yvec9, yvec7, yvec9; + + .L8_loopE:; +-#### Load Alpha #### ++//#### Load Alpha #### + BROAD_DY MEMALPHA, yvec7; +-#### Multiply Alpha #### ++//#### Multiply Alpha #### + MUL_DY yvec7,yvec15,yvec15; + MUL_DY yvec7,yvec13,yvec13; + MUL_DY yvec7,yvec11,yvec11; + MUL_DY yvec7,yvec9,yvec9; +-#### Reverse the Results #### ++//#### Reverse the Results #### + MOV_DY yvec15, yvec7; + REVS_DY $0x0a,yvec13,yvec15,yvec15; + REVS_DY $0x0a,yvec7,yvec13,yvec13; + MOV_DY yvec11,yvec7; + REVS_DY $0x0a,yvec9,yvec11,yvec11; + REVS_DY $0x0a,yvec7,yvec9,yvec9; +-#### Testing alignment #### ++//#### Testing alignment #### + MOVQ C0, %rax; + OR ldc, %rax; + TEST $15, %rax; + JNE .L8_loopEx; # Unalign part write back + ALIGN_5 +-#### Writing Back #### ++//#### Writing Back #### + EXTRA_DY $1,yvec15,xvec7; + EXTRA_DY $1,yvec13,xvec5; + EXTRA_DY $1,yvec11,xvec3; +@@ -1076,7 +1076,7 @@ LEAQ (, %rax, SIZE), %rax; + LEAQ (ptrba, %rax, 2), ptrba; + LEAQ (ptrbb, %rax, 4), ptrbb + #endif +-#### Initial Results Register #### ++//#### Initial Results Register #### + LD_DX 0*SIZE(ptrbb), xvec2; + XOR_DY yvec15, yvec15, yvec15; + LD_DX 2*SIZE(ptrbb), xvec3; +@@ -1106,7 +1106,7 @@ ALIGN_5; + .L10_bodyB:; + # Computing kernel + +-##### Unroll time 1 #### ++//#### Unroll time 1 #### + LD_DX 4*SIZE(ptrbb), xvec6; + SHUF_DX $0x4e, xvec3, xvec5; + MUL_DX xvec0, xvec2, xvec2; +@@ -1123,7 +1123,7 @@ SHUF_DX $0x4e, xvec6, xvec4; + MUL_DX xvec0, xvec5, xvec5; + ADD_DX xvec5, xvec9, xvec9; + +-#### Unroll time 2 #### ++//#### Unroll time 2 #### + LD_DX 8*SIZE(ptrbb), xvec2; + SHUF_DX $0x4e, xvec7, xvec5; + MUL_DX xvec1, xvec6, xvec6; +@@ -1140,7 +1140,7 @@ SHUF_DX $0x4e, xvec2, xvec4; + MUL_DX xvec1, xvec5, xvec5; + ADD_DX xvec5, xvec9, xvec9; + +-##### Unroll time 3 #### ++//#### Unroll time 3 #### + LD_DX 12*SIZE(ptrbb), xvec6; + SHUF_DX $0x4e, xvec3, xvec5; + MUL_DX xvec0, xvec2, xvec2; +@@ -1159,7 +1159,7 @@ ADDQ $8*SIZE, ptrba; + MUL_DX xvec0, xvec5, xvec5; + ADD_DX xvec5, xvec9, xvec9; + +-#### Unroll time 4 #### ++//#### Unroll time 4 #### + LD_DX 0*SIZE(ptrbb), xvec2; + SHUF_DX $0x4e, xvec7, xvec5; + MUL_DX xvec1, xvec6, xvec6; +@@ -1188,7 +1188,7 @@ TEST $2, %rax; + JLE .L11_loopE; + ALIGN_5 + .L11_bodyB:; +-##### Unroll time 1 #### ++//#### Unroll time 1 #### + LD_DX 4*SIZE(ptrbb), xvec6; + SHUF_DX $0x4e, xvec3, xvec5; + MUL_DX xvec0, xvec2, xvec2; +@@ -1208,7 +1208,7 @@ ADDQ $4*SIZE, ptrba; + MUL_DX xvec0, xvec5, xvec5; + ADD_DX xvec5, xvec9, xvec9; + +-#### Unroll time 2 #### ++//#### Unroll time 2 #### + LD_DX 0*SIZE(ptrbb), xvec2; + SHUF_DX $0x4e, xvec7, xvec5; + MUL_DX xvec1, xvec6, xvec6; +@@ -1251,27 +1251,27 @@ MUL_DX xvec0, xvec5, xvec5; + ADD_DX xvec5, xvec9, xvec9; + + .L12_loopE:; +-#### Load Alpha #### ++//#### Load Alpha #### + BROAD_DX MEMALPHA, xvec7; +-#### Multiply Alpha #### ++//#### Multiply Alpha #### + MUL_DX xvec7, xvec15, xvec15; + MUL_DX xvec7, xvec13, xvec13; + MUL_DX xvec7, xvec11, xvec11; + MUL_DX xvec7, xvec9, xvec9; +-#### Reverse the Results #### ++//#### Reverse the Results #### + MOV_DX xvec15, xvec6; + REVS_DX xvec13, xvec15, xvec15; + REVS_DX xvec6, xvec13, xvec13; + MOV_DX xvec11, xvec6; + REVS_DX xvec9, xvec11, xvec11; + REVS_DX xvec6, xvec9, xvec9; +-#### Testing Alignment #### ++//#### Testing Alignment #### + MOVQ C0, %rax; + OR ldc, %rax; + TEST $15, %rax; + JNE .L12_loopEx; + ALIGN_5 +-#### Writing Back #### ++//#### Writing Back #### + #ifndef TRMMKERNEL + ADD_DX 0*SIZE(C0), xvec13, xvec13; + ADD_DX 0*SIZE(C0, ldc, 1), xvec15, xvec15; +@@ -1345,7 +1345,7 @@ LEAQ (,%rax, SIZE), %rax; + ADDQ %rax, ptrba; + LEAQ (ptrbb, %rax, 4), ptrbb; + #endif +-#### Initial Results Register #### ++//#### Initial Results Register #### + XOR_DY yvec15, yvec15, yvec15; + #ifndef TRMMKERNEL + MOVQ bk, k; +@@ -1429,11 +1429,11 @@ ADDQ $1*SIZE, ptrba; + ADDQ $4*SIZE, ptrbb; + + .L16_loopE: +-#### Load Alpha #### ++//#### Load Alpha #### + BROAD_DY MEMALPHA, yvec7; +-#### Multiply Alpha #### ++//#### Multiply Alpha #### + MUL_DY yvec15, yvec7, yvec15; +-#### Writing Back #### ++//#### Writing Back #### + EXTRA_DY $1, yvec15, xvec7; + #ifndef TRMMKERNEL + LDL_DX 0*SIZE(C0), xvec0, xvec0; +@@ -1497,7 +1497,7 @@ LEAQ (, %rax, SIZE), %rax; + LEAQ (ptrba, %rax, 8), ptrba; + LEAQ (ptrbb, %rax, 2), ptrbb; + #endif +-#### Initial Results Register #### ++//#### Initial Results Register #### + XOR_DY yvec15, yvec15, yvec15; + XOR_DY yvec14, yvec14, yvec14; + XOR_DY yvec13, yvec13, yvec13; +@@ -1526,7 +1526,7 @@ JLE .L211_loopE; + ALIGN_5; + .L211_bodyB: + # Computing kernel +-#### Unroll time 1 #### ++//#### Unroll time 1 #### + LD_DX 0*SIZE(ptrba), xvec0; + LD_DX 0*SIZE(ptrbb), xvec4; + MOV_DX xvec4, xvec5; +@@ -1563,7 +1563,7 @@ ADD_DX xvec6, xvec9, xvec9; + MUL_DX xvec3, xvec7, xvec7; + ADD_DX xvec7, xvec8, xvec8; + +-#### Unroll time 2 #### ++//#### Unroll time 2 #### + LD_DX 8*SIZE(ptrba), xvec0; + LD_DX 2*SIZE(ptrbb), xvec4; + MOV_DX xvec4, xvec5; +@@ -1600,7 +1600,7 @@ ADD_DX xvec6, xvec9, xvec9; + MUL_DX xvec3, xvec7, xvec7; + ADD_DX xvec7, xvec8, xvec8; + +-#### Unroll time 3 #### ++//#### Unroll time 3 #### + LD_DX 16*SIZE(ptrba), xvec0; + LD_DX 4*SIZE(ptrbb), xvec4; + MOV_DX xvec4, xvec5; +@@ -1637,7 +1637,7 @@ ADD_DX xvec6, xvec9, xvec9; + MUL_DX xvec3, xvec7, xvec7; + ADD_DX xvec7, xvec8, xvec8; + +-#### Unroll time 4 #### ++//#### Unroll time 4 #### + LD_DX 24*SIZE(ptrba), xvec0; + LD_DX 6*SIZE(ptrbb), xvec4; + MOV_DX xvec4, xvec5; +@@ -1689,7 +1689,7 @@ JLE .L212_loopE; + ALIGN_5; + .L212_bodyB: + # Computing kernel +-#### Unroll time 1 #### ++//#### Unroll time 1 #### + LD_DX 0*SIZE(ptrba), xvec0; + LD_DX 0*SIZE(ptrbb), xvec4; + MOV_DX xvec4, xvec5; +@@ -1726,7 +1726,7 @@ ADD_DX xvec6, xvec9, xvec9; + MUL_DX xvec3, xvec7, xvec7; + ADD_DX xvec7, xvec8, xvec8; + +-#### Unroll time 2 #### ++//#### Unroll time 2 #### + LD_DX 8*SIZE(ptrba), xvec0; + LD_DX 2*SIZE(ptrbb), xvec4; + MOV_DX xvec4, xvec5; +@@ -1775,7 +1775,7 @@ TEST $1, %rax; + JLE .L213_loopE; + ALIGN_5 + .L213_bodyB: +-#### Unroll time 1 #### ++//#### Unroll time 1 #### + LD_DX 0*SIZE(ptrba), xvec0; + LD_DX 0*SIZE(ptrbb), xvec4; + MOV_DX xvec4, xvec5; +@@ -1815,7 +1815,7 @@ MUL_DX xvec3, xvec7, xvec7; + ADD_DX xvec7, xvec8, xvec8; + + .L213_loopE: +-#### Multiply Alpha #### ++//#### Multiply Alpha #### + BROAD_DX MEMALPHA, xvec7; + MUL_DX xvec7, xvec15, xvec15; + MUL_DX xvec7, xvec14, xvec14; +@@ -1825,7 +1825,7 @@ MUL_DX xvec7, xvec11, xvec11; + MUL_DX xvec7, xvec10, xvec10; + MUL_DX xvec7, xvec9, xvec9; + MUL_DX xvec7, xvec8, xvec8; +-#### Reverse ##### ++//#### Reverse #### + MOV_DX xvec15, xvec6; + REVS_DX xvec11, xvec15, xvec15; + REVS_DX xvec6, xvec11, xvec11; +@@ -1838,13 +1838,13 @@ REVS_DX xvec6, xvec9, xvec9; + MOV_DX xvec12, xvec6; + REVS_DX xvec8, xvec12, xvec12; + REVS_DX xvec6, xvec8, xvec8; +-#### Testing Alignment #### ++//#### Testing Alignment #### + MOVQ C0, %rax; + OR ldc, %rax; + TEST $15, %rax; + JNE .L213_loopEx; + ALIGN_5 +-#### Writing Back #### ++//#### Writing Back #### + #ifndef TRMMKERNEL + ADD_DX 0*SIZE(C0), xvec11, xvec11; + ADD_DX 2*SIZE(C0), xvec10, xvec10; +@@ -1952,7 +1952,7 @@ LEAQ (,%rax, SIZE), %rax; + LEAQ (ptrba, %rax, 4), ptrba; + LEAQ (ptrbb, %rax, 2), ptrbb; + #endif +-#### Initial Results Register #### ++//#### Initial Results Register #### + XOR_DY yvec15, yvec15, yvec15; + XOR_DY yvec14, yvec14, yvec14; + XOR_DY yvec11, yvec11, yvec11; +@@ -1977,7 +1977,7 @@ JLE .L221_loopE; + ALIGN_5 + .L221_bodyB:; + # Computing kernel +-#### Unroll time 1 #### ++//#### Unroll time 1 #### + LD_DX 0*SIZE(ptrba), xvec0; + LD_DX 0*SIZE(ptrbb), xvec4; + MOV_DX xvec4, xvec5; +@@ -1996,7 +1996,7 @@ ADD_DX xvec4, xvec11, xvec11; + MUL_DX xvec1, xvec5, xvec5; + ADD_DX xvec5, xvec10, xvec10; + +-#### Unroll time 2 #### ++//#### Unroll time 2 #### + LD_DX 4*SIZE(ptrba), xvec0; + LD_DX 2*SIZE(ptrbb), xvec4; + MOV_DX xvec4, xvec5; +@@ -2015,7 +2015,7 @@ ADD_DX xvec4, xvec11, xvec11; + MUL_DX xvec1, xvec5, xvec5; + ADD_DX xvec5, xvec10, xvec10; + +-#### Unroll time 3 #### ++//#### Unroll time 3 #### + LD_DX 8*SIZE(ptrba), xvec0; + LD_DX 4*SIZE(ptrbb), xvec4; + MOV_DX xvec4, xvec5; +@@ -2034,7 +2034,7 @@ ADD_DX xvec4, xvec11, xvec11; + MUL_DX xvec1, xvec5, xvec5; + ADD_DX xvec5, xvec10, xvec10; + +-#### Unroll time 4 #### ++//#### Unroll time 4 #### + LD_DX 12*SIZE(ptrba), xvec0; + LD_DX 6*SIZE(ptrbb), xvec4; + MOV_DX xvec4, xvec5; +@@ -2067,7 +2067,7 @@ TEST $2, %rax; + JLE .L222_loopE; + ALIGN_5 + .L222_bodyB: +-#### Unroll time 1 #### ++//#### Unroll time 1 #### + LD_DX 0*SIZE(ptrba), xvec0; + LD_DX 0*SIZE(ptrbb), xvec4; + MOV_DX xvec4, xvec5; +@@ -2086,7 +2086,7 @@ ADD_DX xvec4, xvec11, xvec11; + MUL_DX xvec1, xvec5, xvec5; + ADD_DX xvec5, xvec10, xvec10; + +-#### Unroll time 2 #### ++//#### Unroll time 2 #### + LD_DX 4*SIZE(ptrba), xvec0; + LD_DX 2*SIZE(ptrbb), xvec4; + MOV_DX xvec4, xvec5; +@@ -2116,7 +2116,7 @@ TEST $1, %rax; + JLE .L223_loopE; + ALIGN_5 + .L223_bodyB: +-#### Unroll time 1 #### ++//#### Unroll time 1 #### + LD_DX 0*SIZE(ptrba), xvec0; + LD_DX 0*SIZE(ptrbb), xvec4; + MOV_DX xvec4, xvec5; +@@ -2138,26 +2138,26 @@ MUL_DX xvec1, xvec5, xvec5; + ADD_DX xvec5, xvec10, xvec10; + + .L223_loopE: +-#### Multiply Alpha #### ++//#### Multiply Alpha #### + BROAD_DX MEMALPHA, xvec7; + MUL_DX xvec7, xvec15, xvec15; + MUL_DX xvec7, xvec14, xvec14; + MUL_DX xvec7, xvec11, xvec11; + MUL_DX xvec7, xvec10, xvec10; +-#### Reverse ##### ++//#### Reverse #### + MOV_DX xvec15, xvec6; + REVS_DX xvec11, xvec15, xvec15; + REVS_DX xvec6, xvec11, xvec11; + MOV_DX xvec14, xvec6; + REVS_DX xvec10, xvec14, xvec14; + REVS_DX xvec6, xvec10, xvec10; +-#### Testing Alignment #### ++//#### Testing Alignment #### + MOVQ C0, %rax; + OR ldc, %rax; + TEST $15, %rax; + JNE .L223_loopEx; + ALIGN_5 +-#### Writing Back #### ++//#### Writing Back #### + #ifndef TRMMKERNEL + ADD_DX 0*SIZE(C0), xvec11, xvec11; + ADD_DX 2*SIZE(C0), xvec10, xvec10; +@@ -2220,7 +2220,7 @@ ADDQ $4, kk + ADDQ $4*SIZE, C0; + ADDQ $4*SIZE, C1; + .L22_loopE:; +-TEST $2, bm; # Rm = 2 ++TEST $2, bm; // Rm = 2 + JLE .L23_loopE; + ALIGN_5; + .L23_bodyB: +@@ -2255,7 +2255,7 @@ JLE .L231_loopE; + ALIGN_5 + .L231_bodyB: + # Computing kernel +-#### Unroll time 1 #### ++//#### Unroll time 1 #### + LD_DX 0*SIZE(ptrba), xvec0; + LD_DX 0*SIZE(ptrbb), xvec4; + SHUF_DX $0x4e, xvec4, xvec5; +@@ -2264,7 +2264,7 @@ ADD_DX xvec4, xvec15, xvec15; + + MUL_DX xvec0, xvec5, xvec5; + ADD_DX xvec5, xvec11, xvec11; +-#### Unroll time 2 #### ++//#### Unroll time 2 #### + LD_DX 2*SIZE(ptrba), xvec0; + LD_DX 2*SIZE(ptrbb), xvec4; + SHUF_DX $0x4e, xvec4, xvec5; +@@ -2273,7 +2273,7 @@ ADD_DX xvec4, xvec15, xvec15; + + MUL_DX xvec0, xvec5, xvec5; + ADD_DX xvec5, xvec11, xvec11; +-#### Unroll time 3 #### ++//#### Unroll time 3 #### + LD_DX 4*SIZE(ptrba), xvec0; + LD_DX 4*SIZE(ptrbb), xvec4; + SHUF_DX $0x4e, xvec4, xvec5; +@@ -2282,7 +2282,7 @@ ADD_DX xvec4, xvec15, xvec15; + + MUL_DX xvec0, xvec5, xvec5; + ADD_DX xvec5, xvec11, xvec11; +-#### Unroll time 4 #### ++//#### Unroll time 4 #### + LD_DX 6*SIZE(ptrba), xvec0; + LD_DX 6*SIZE(ptrbb), xvec4; + SHUF_DX $0x4e, xvec4, xvec5; +@@ -2305,7 +2305,7 @@ TEST $2, %rax; + JLE .L232_loopE; + ALIGN_5 + .L232_bodyB: +-#### Unroll time 1 #### ++//#### Unroll time 1 #### + LD_DX 0*SIZE(ptrba), xvec0; + LD_DX 0*SIZE(ptrbb), xvec4; + SHUF_DX $0x4e, xvec4, xvec5; +@@ -2314,7 +2314,7 @@ ADD_DX xvec4, xvec15, xvec15; + + MUL_DX xvec0, xvec5, xvec5; + ADD_DX xvec5, xvec11, xvec11; +-#### Unroll time 2 #### ++//#### Unroll time 2 #### + LD_DX 2*SIZE(ptrba), xvec0; + LD_DX 2*SIZE(ptrbb), xvec4; + SHUF_DX $0x4e, xvec4, xvec5; +@@ -2334,7 +2334,7 @@ TEST $1, %rax; + JLE .L233_loopE; + ALIGN_5 + .L233_bodyB: +-#### Unroll time 1 #### ++//#### Unroll time 1 #### + LD_DX 0*SIZE(ptrba), xvec0; + LD_DX 0*SIZE(ptrbb), xvec4; + SHUF_DX $0x4e, xvec4, xvec5; +@@ -2345,21 +2345,21 @@ MUL_DX xvec0, xvec5, xvec5; + ADD_DX xvec5, xvec11, xvec11; + ADDQ $2*SIZE, ptrbb; + .L233_loopE: +-#### Multiply Alpha #### ++//#### Multiply Alpha #### + BROAD_DX MEMALPHA, xvec7; + MUL_DX xvec7, xvec15, xvec15; + MUL_DX xvec7, xvec11, xvec11; +-#### Reverse ##### ++//#### Reverse #### + MOV_DX xvec15, xvec6; + REVS_DX xvec11, xvec15, xvec15; + REVS_DX xvec6, xvec11, xvec11; +-#### Testing Alignment #### ++//#### Testing Alignment #### + MOVQ C0, %rax; + OR ldc, %rax; + TEST $15, %rax; + JNE .L233_loopEx; + ALIGN_5 +-#### Writing Back #### ++//#### Writing Back #### + #ifndef TRMMKERNEL + ADD_DX 0*SIZE(C0), xvec11, xvec11; + ADD_DX 0*SIZE(C1), xvec15, xvec15; +@@ -2408,7 +2408,7 @@ ADDQ $2, kk; + ADDQ $2*SIZE, C0; + ADDQ $2*SIZE, C1; + .L23_loopE: +-TEST $1, bm; # Rm = 1 ++TEST $1, bm; // Rm = 1 + JLE .L24_loopE; + ALIGN_5; + .L24_bodyB: +@@ -2534,7 +2534,7 @@ SALQ $4, k; + ADDQ k, bb; + LEAQ (C, ldc, 2), C; + .L20_loopE:; +-TEST $1, bn; # Rn = 1 ++TEST $1, bn; // Rn = 1 + JLE .L30_loopE; + ALIGN_5 + .L30_bodyB: +@@ -2558,7 +2558,7 @@ LEAQ (, %rax, SIZE), %rax; + LEAQ (ptrba, %rax, 8), ptrba; + ADDQ %rax, ptrbb; + #endif +-#### Initial Results Register #### ++//#### Initial Results Register #### + XOR_DY yvec15, yvec15, yvec15; + XOR_DY yvec14, yvec14, yvec14; + #ifndef TRMMKERNEL +@@ -2580,7 +2580,7 @@ SARQ $2, k; + JLE .L311_loopE; + ALIGN_5 + .L311_bodyB: +-#### Unroll time 1 #### ++//#### Unroll time 1 #### + LD_DY 0*SIZE(ptrba), yvec0; + LD_DY 4*SIZE(ptrba), yvec1; + BROAD_DY 0*SIZE(ptrbb), yvec2; +@@ -2589,7 +2589,7 @@ ADD_DY yvec0, yvec15, yvec15; + MUL_DY yvec2, yvec1, yvec1; + ADD_DY yvec1, yvec14, yvec14; + +-#### Unroll time 2 #### ++//#### Unroll time 2 #### + LD_DY 8*SIZE(ptrba), yvec3; + LD_DY 12*SIZE(ptrba), yvec4; + BROAD_DY 1*SIZE(ptrbb), yvec5; +@@ -2598,7 +2598,7 @@ ADD_DY yvec3, yvec15, yvec15; + MUL_DY yvec5, yvec4, yvec4 + ADD_DY yvec4, yvec14, yvec14; + +-#### Unroll time 3 #### ++//#### Unroll time 3 #### + LD_DY 16*SIZE(ptrba), yvec0; + LD_DY 20*SIZE(ptrba), yvec1; + BROAD_DY 2*SIZE(ptrbb), yvec2; +@@ -2607,7 +2607,7 @@ ADD_DY yvec0, yvec15, yvec15; + MUL_DY yvec2, yvec1, yvec1; + ADD_DY yvec1, yvec14, yvec14; + +-#### Unroll time 2 #### ++//#### Unroll time 2 #### + LD_DY 24*SIZE(ptrba), yvec3; + LD_DY 28*SIZE(ptrba), yvec4; + BROAD_DY 3*SIZE(ptrbb), yvec5; +@@ -2630,7 +2630,7 @@ TEST $2, %rax; + JLE .L312_loopE; + ALIGN_5 + .L312_bodyB: +-#### Unroll time 1 #### ++//#### Unroll time 1 #### + LD_DY 0*SIZE(ptrba), yvec0; + LD_DY 4*SIZE(ptrba), yvec1; + BROAD_DY 0*SIZE(ptrbb), yvec2; +@@ -2639,7 +2639,7 @@ ADD_DY yvec0, yvec15, yvec15; + MUL_DY yvec2, yvec1, yvec1; + ADD_DY yvec1, yvec14, yvec14; + +-#### Unroll time 2 #### ++//#### Unroll time 2 #### + LD_DY 8*SIZE(ptrba), yvec3; + LD_DY 12*SIZE(ptrba), yvec4; + BROAD_DY 1*SIZE(ptrbb), yvec5; +@@ -2660,7 +2660,7 @@ TEST $1, %rax; + JLE .L313_loopE; + ALIGN_5 + .L313_bodyB: +-#### Unroll time 1 #### ++//#### Unroll time 1 #### + LD_DY 0*SIZE(ptrba), yvec0; + LD_DY 4*SIZE(ptrba), yvec1; + BROAD_DY 0*SIZE(ptrbb), yvec2; +@@ -2672,17 +2672,17 @@ ADD_DY yvec1, yvec14, yvec14; + ADDQ $1*SIZE, ptrbb; + + .L313_loopE: +-#### Multiply Alpha #### ++//#### Multiply Alpha #### + BROAD_DY MEMALPHA, yvec7; + MUL_DY yvec7, yvec15, yvec15; + MUL_DY yvec7, yvec14, yvec14; +-#### Testing Alignment #### ++//#### Testing Alignment #### + MOVQ C0, %rax; + OR ldc, %rax; + TEST $15, %rax; + JNE .L313_loopEx; + ALIGN_5 +-#### Writing Back #### ++//#### Writing Back #### + EXTRA_DY $1, yvec15, xvec13; + EXTRA_DY $1, yvec14, xvec12; + #ifndef TRMMKERNEL +@@ -2762,7 +2762,7 @@ LEAQ (,%rax, SIZE), %rax; + LEAQ (ptrba, %rax, 4), ptrba; + ADDQ %rax, ptrbb; + #endif +-#### Initial Results Register #### ++//#### Initial Results Register #### + XOR_DY yvec15, yvec15, yvec15; + #ifndef TRMMKERNEL + MOVQ bk, k; +@@ -2847,16 +2847,16 @@ ADDQ $4*SIZE, ptrba; + ADDQ $1*SIZE, ptrbb; + + .L323_loopE: +-#### Multiply Alpha #### ++//#### Multiply Alpha #### + BROAD_DY MEMALPHA, yvec7; + MUL_DY yvec7, yvec15, yvec15; +-#### Testing Alignment #### ++//#### Testing Alignment #### + MOVQ C0, %rax; + OR ldc, %rax; + TEST $15, %rax; + JNE .L323_loopEx; + ALIGN_5 +-#### Writing Back #### ++//#### Writing Back #### + EXTRA_DY $1, yvec15, xvec14; + #ifndef TRMMKERNEL + ADD_DX 0*SIZE(C0), xvec15, xvec15; +@@ -2878,7 +2878,7 @@ ADDQ $4*SIZE, C0; + JMP .L32_loopE; + ALIGN_5 + .L323_loopEx: +-#### Writing Back #### ++//#### Writing Back #### + EXTRA_DY $1, yvec15, xvec14; + #ifndef TRMMKERNEL + LDL_DX 0*SIZE(C0), xvec13, xvec13; +@@ -2917,7 +2917,7 @@ LEAQ (, %rax, SIZE), %rax + LEAQ (ptrba, %rax, 2), ptrba + ADDQ %rax, ptrbb; + #endif +-#### Initial Result #### ++//#### Initial Result #### + XOR_DY yvec15, yvec15, yvec15; + #ifndef TRMMKERNEL + MOVQ bk, k; +@@ -3000,7 +3000,7 @@ ADD_DX xvec2, xvec15, xvec15; + ADDQ $2*SIZE, ptrba; + ADDQ $1*SIZE, ptrbb; + .L333_loopE: +-#### Multiply Alpha #### ++//#### Multiply Alpha #### + BROAD_DX MEMALPHA, xvec7; + MUL_DX xvec7, xvec15, xvec15; + #ifndef TRMMKERNEL +@@ -3119,7 +3119,7 @@ addq $1*SIZE, ptrba; + addq $1*SIZE, ptrbb; + + .L343_loopE: +-#### Writing Back #### ++//#### Writing Back #### + vmovsd MEMALPHA, xvec7; + vmulsd xvec7, xvec15, xvec15; + #ifndef TRMMKERNEL From d53647dd685ec25c3585d86b7a3a93b83c9093c2 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Wed, 1 Mar 2017 14:04:48 -0500 Subject: [PATCH 0105/1534] Upgrade curl to 7.53.1 this includes a CVE security fix --- deps/Versions.make | 2 +- deps/checksums/curl-7.52.1.tar.bz2/md5 | 1 - deps/checksums/curl-7.52.1.tar.bz2/sha512 | 1 - deps/checksums/curl-7.53.1.tar.bz2/md5 | 1 + deps/checksums/curl-7.53.1.tar.bz2/sha512 | 1 + 5 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 deps/checksums/curl-7.52.1.tar.bz2/md5 delete mode 100644 deps/checksums/curl-7.52.1.tar.bz2/sha512 create mode 100644 deps/checksums/curl-7.53.1.tar.bz2/md5 create mode 100644 deps/checksums/curl-7.53.1.tar.bz2/sha512 diff --git a/deps/Versions.make b/deps/Versions.make index 7e5a0486f9971..9d205fc7d9d02 100644 --- a/deps/Versions.make +++ b/deps/Versions.make @@ -11,4 +11,4 @@ GMP_VER = 6.1.2 MPFR_VER = 3.1.5 PATCHELF_VER = 0.9 MBEDTLS_VER = 2.3.0 -CURL_VER = 7.52.1 +CURL_VER = 7.53.1 diff --git a/deps/checksums/curl-7.52.1.tar.bz2/md5 b/deps/checksums/curl-7.52.1.tar.bz2/md5 deleted file mode 100644 index 4e898c45ec9be..0000000000000 --- a/deps/checksums/curl-7.52.1.tar.bz2/md5 +++ /dev/null @@ -1 +0,0 @@ -dd014df06ff1d12e173de86873f9f77a diff --git a/deps/checksums/curl-7.52.1.tar.bz2/sha512 b/deps/checksums/curl-7.52.1.tar.bz2/sha512 deleted file mode 100644 index b4af993ab5fef..0000000000000 --- a/deps/checksums/curl-7.52.1.tar.bz2/sha512 +++ /dev/null @@ -1 +0,0 @@ -cf36563c77d096f2c6084354ed6d45ccca7c557828ceab21204e4e8be0d4f0d287839c8cfac906174b86d51a1ee816c2769fc78ef88f039c9645bd2c27982a75 diff --git a/deps/checksums/curl-7.53.1.tar.bz2/md5 b/deps/checksums/curl-7.53.1.tar.bz2/md5 new file mode 100644 index 0000000000000..216ef57c5cffb --- /dev/null +++ b/deps/checksums/curl-7.53.1.tar.bz2/md5 @@ -0,0 +1 @@ +fb1f03a142236840c1a77c035fa4c542 diff --git a/deps/checksums/curl-7.53.1.tar.bz2/sha512 b/deps/checksums/curl-7.53.1.tar.bz2/sha512 new file mode 100644 index 0000000000000..0e5c4da7d4b67 --- /dev/null +++ b/deps/checksums/curl-7.53.1.tar.bz2/sha512 @@ -0,0 +1 @@ +c668494d0e795f34b00505ca68ab41fbb475a1bccbcac1d0bbacbbbafa40a994472e100be18a0c10f8fa21b5b9bd3f4e66c1e68ff5423b13b82d829cbaefcd52 From e0a86112e6dc5c11b6d71efded3db42b53e4fc42 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Wed, 1 Mar 2017 14:11:52 -0500 Subject: [PATCH 0106/1534] Upgrade libgit2 to 0.25.1 this includes some security issues, ref https://github.com/libgit2/libgit2/releases/tag/v0.25.1 --- .../md5 | 1 + .../sha512 | 1 + .../md5 | 1 - .../sha512 | 1 - deps/libgit2.version | 4 ++-- 5 files changed, 4 insertions(+), 4 deletions(-) create mode 100644 deps/checksums/libgit2-2fcb8705e584ca61f6c4657525c9d2713f6a39d2.tar.gz/md5 create mode 100644 deps/checksums/libgit2-2fcb8705e584ca61f6c4657525c9d2713f6a39d2.tar.gz/sha512 delete mode 100644 deps/checksums/libgit2-75db289a041b1f1084768244e167b953ac7eeaa5.tar.gz/md5 delete mode 100644 deps/checksums/libgit2-75db289a041b1f1084768244e167b953ac7eeaa5.tar.gz/sha512 diff --git a/deps/checksums/libgit2-2fcb8705e584ca61f6c4657525c9d2713f6a39d2.tar.gz/md5 b/deps/checksums/libgit2-2fcb8705e584ca61f6c4657525c9d2713f6a39d2.tar.gz/md5 new file mode 100644 index 0000000000000..ccc33a35bb056 --- /dev/null +++ b/deps/checksums/libgit2-2fcb8705e584ca61f6c4657525c9d2713f6a39d2.tar.gz/md5 @@ -0,0 +1 @@ +fb1f1140f9b55fc8499caa960382fc03 diff --git a/deps/checksums/libgit2-2fcb8705e584ca61f6c4657525c9d2713f6a39d2.tar.gz/sha512 b/deps/checksums/libgit2-2fcb8705e584ca61f6c4657525c9d2713f6a39d2.tar.gz/sha512 new file mode 100644 index 0000000000000..cc5156e0c027d --- /dev/null +++ b/deps/checksums/libgit2-2fcb8705e584ca61f6c4657525c9d2713f6a39d2.tar.gz/sha512 @@ -0,0 +1 @@ +2086269728e14c0ec38f322b01f89d4d98a31a395cab3937591826a232193f00ec07bafe938ad99d70c74cb695af26c7228513019bfe6fc06427229bd2e098cf diff --git a/deps/checksums/libgit2-75db289a041b1f1084768244e167b953ac7eeaa5.tar.gz/md5 b/deps/checksums/libgit2-75db289a041b1f1084768244e167b953ac7eeaa5.tar.gz/md5 deleted file mode 100644 index 5ece749b8ff06..0000000000000 --- a/deps/checksums/libgit2-75db289a041b1f1084768244e167b953ac7eeaa5.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -43f28f86c884c3c469ce4080de287ee7 diff --git a/deps/checksums/libgit2-75db289a041b1f1084768244e167b953ac7eeaa5.tar.gz/sha512 b/deps/checksums/libgit2-75db289a041b1f1084768244e167b953ac7eeaa5.tar.gz/sha512 deleted file mode 100644 index 3f7eed8a611dd..0000000000000 --- a/deps/checksums/libgit2-75db289a041b1f1084768244e167b953ac7eeaa5.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -6d7c5a6fd0f6678944e0ae379f5b5fa628f7a6936db6fbff4442e98db7037fd3baf2010ffc7c45ed7a30c7ebff1973a0a9047d67dbac1dedf2df444a80bdf43b diff --git a/deps/libgit2.version b/deps/libgit2.version index 76a3ffbbc1641..f5596b2fce3b9 100644 --- a/deps/libgit2.version +++ b/deps/libgit2.version @@ -1,2 +1,2 @@ -LIBGIT2_BRANCH=v0.25.0 -LIBGIT2_SHA1=75db289a041b1f1084768244e167b953ac7eeaa5 +LIBGIT2_BRANCH=v0.25.1 +LIBGIT2_SHA1=2fcb8705e584ca61f6c4657525c9d2713f6a39d2 From 5d64b2067f59b622bd53fa3d29ef2e08ea16ba68 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Wed, 1 Mar 2017 18:42:55 -0500 Subject: [PATCH 0107/1534] Avoid corrupting signal stack before signal handler returns by hiding the top 16bytes that might be used for `jl_call_in_ctx` --- src/signals-unix.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/signals-unix.c b/src/signals-unix.c index d49485625a87f..2c50ff9ba7b68 100644 --- a/src/signals-unix.c +++ b/src/signals-unix.c @@ -117,7 +117,7 @@ static void jl_call_in_ctx(jl_ptls_t ptls, void (*fptr)(void), void *_ctx) ucontext_t *ctx = (ucontext_t*)_ctx; uintptr_t target = (uintptr_t)fptr; // Apparently some glibc's sigreturn target is running in thumb state. - // Mimic a `bx` instruction by settting the T(5) bit of CPSR + // Mimic a `bx` instruction by setting the T(5) bit of CPSR // depending on the target address. uintptr_t cpsr = ctx->uc_mcontext.arm_cpsr; // Thumb mode function pointer should have the lowest bit set @@ -482,7 +482,7 @@ void jl_install_thread_signal_handler(jl_ptls_t ptls) void *signal_stack = alloc_sigstack(sig_stack_size); stack_t ss; ss.ss_flags = 0; - ss.ss_size = sig_stack_size; + ss.ss_size = sig_stack_size - 16; ss.ss_sp = signal_stack; if (sigaltstack(&ss, NULL) < 0) { jl_errorf("fatal error: sigaltstack: %s", strerror(errno)); From 9707136cc15842cb39321445dce9ea3c3ddc0f75 Mon Sep 17 00:00:00 2001 From: kshyatt Date: Wed, 1 Mar 2017 17:31:26 -0800 Subject: [PATCH 0108/1534] Add test for showing indexentry --- test/libgit2.jl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/libgit2.jl b/test/libgit2.jl index 848168af9ad4d..eafa293e44410 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -716,7 +716,10 @@ mktempdir() do dir LibGit2.with(LibGit2.GitIndex(repo)) do idx i = find(test_file, idx) @test !isnull(i) - @test idx[get(i)] !== nothing + idx_entry = idx[get(i)] + @test idx_entry !== nothing + idx_entry_str = sprint(show, idx_entry) + @test idx_entry_str == "IndexEntry($(string(idx_entry.id)))" i = find("zzz", idx) @test isnull(i) From 1ec7c66318c0c315863fa7531974096877633424 Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Wed, 1 Mar 2017 23:13:51 -0800 Subject: [PATCH 0109/1534] Integrate OpenBLAS fix for cross compiler autodetection Ported from https://github.com/xianyi/OpenBLAS/pull/968 --- deps/blas.mk | 8 +++++++- deps/patches/openblas-cross-compile.patch | 13 +++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 deps/patches/openblas-cross-compile.patch diff --git a/deps/blas.mk b/deps/blas.mk index 2c70c0b745087..b1992cabf8ba0 100644 --- a/deps/blas.mk +++ b/deps/blas.mk @@ -91,7 +91,13 @@ $(BUILDDIR)/$(OPENBLAS_SRC_DIR)/openblas-clangasmbug.patch-applied: $(BUILDDIR)/ cd $(BUILDDIR)/$(OPENBLAS_SRC_DIR) && patch -p1 -f < $(SRCDIR)/patches/openblas-clangasmbug.patch echo 1 > $@ -$(BUILDDIR)/$(OPENBLAS_SRC_DIR)/build-configured: $(BUILDDIR)/$(OPENBLAS_SRC_DIR)/openblas-clangasmbug.patch-applied +# Cross compiler autodetection workaround from https://github.com/xianyi/OpenBLAS/pull/968 +# Remove this when we upgrade beyond OpenBLAS v0.2.19 +$(BUILDDIR)/$(OPENBLAS_SRC_DIR)/openblas-cross-compile.patch-applied: $(BUILDDIR)/$(OPENBLAS_SRC_DIR)/openblas-clangasmbug.patch-applied + cd $(BUILDDIR)/$(OPENBLAS_SRC_DIR) && patch -p1 -f < $(SRCDIR)/patches/openblas-cross-compile.patch + echo 1 > $@ + +$(BUILDDIR)/$(OPENBLAS_SRC_DIR)/build-configured: $(BUILDDIR)/$(OPENBLAS_SRC_DIR)/openblas-cross-compile.patch-applied perl -i -ple 's/^\s*(EXTRALIB\s*\+=\s*-lSystemStubs)\s*$$/# $$1/g' $(dir $<)/Makefile.system echo 1 > $@ diff --git a/deps/patches/openblas-cross-compile.patch b/deps/patches/openblas-cross-compile.patch new file mode 100644 index 0000000000000..60997cc64f9ab --- /dev/null +++ b/deps/patches/openblas-cross-compile.patch @@ -0,0 +1,13 @@ +diff --git a/c_check b/c_check +index 371dbf61..2ec9fc48 100644 +--- a/c_check ++++ b/c_check +@@ -34,7 +34,7 @@ if (dirname($compiler_name) ne ".") { + $cross_suffix .= dirname($compiler_name) . "/"; + } + +-if (basename($compiler_name) =~ /([^\s]*-)(.*)/) { ++if (basename($compiler_name) =~ /(.*-)(.*)/) { + $cross_suffix .= $1; + } + From e7d583cc85133f0d8c19ca218903abe13f1a3a0b Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Wed, 1 Mar 2017 23:22:21 -0800 Subject: [PATCH 0110/1534] And that's what happens when you try to apply a back patchwards --- deps/patches/openblas-cross-compile.patch | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/deps/patches/openblas-cross-compile.patch b/deps/patches/openblas-cross-compile.patch index 60997cc64f9ab..a71b30cc19b12 100644 --- a/deps/patches/openblas-cross-compile.patch +++ b/deps/patches/openblas-cross-compile.patch @@ -1,13 +1,13 @@ diff --git a/c_check b/c_check -index 371dbf61..2ec9fc48 100644 +index 2ec9fc48..371dbf61 100644 --- a/c_check +++ b/c_check @@ -34,7 +34,7 @@ if (dirname($compiler_name) ne ".") { $cross_suffix .= dirname($compiler_name) . "/"; } --if (basename($compiler_name) =~ /([^\s]*-)(.*)/) { -+if (basename($compiler_name) =~ /(.*-)(.*)/) { +-if (basename($compiler_name) =~ /(.*-)(.*)/) { ++if (basename($compiler_name) =~ /([^\s]*-)(.*)/) { $cross_suffix .= $1; } From 453da2c4899e7285eccd9349033e9a213a286a4f Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 26 Feb 2017 12:59:57 -0800 Subject: [PATCH 0111/1534] Much faster broadcast over combinations of tuples and broadcast scalars. --- base/broadcast.jl | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/base/broadcast.jl b/base/broadcast.jl index d85194e670cc9..7dc7800da7688 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -297,11 +297,6 @@ _broadcast_eltype(f, A, Bs...) = Base._return_type(f, eltypestuple(A, Bs...)) end return broadcast_t(f, Any, shape, iter, A, Bs...) end -function broadcast_c(f, ::Type{Tuple}, As...) - shape = broadcast_indices(As...) - n = length(shape[1]) - return ntuple(k->f((_broadcast_getindex(A, k) for A in As)...), n) -end @inline function broadcast_c(f, ::Type{Nullable}, a...) nonnull = all(hasvalue, a) S = _broadcast_eltype(f, a...) @@ -316,6 +311,20 @@ end end end @inline broadcast_c(f, ::Type{Any}, a...) = f(a...) +broadcast_c(f, ::Type{Tuple}, As...) = + ntuple(k -> f(_tuplebroadcast_getargs(As, k)...), _tuplebroadcast_reslength(As)) +broadcast_c{T}(f, ::Type{Tuple}, ::Type{T}, As...) = + ntuple(k -> f(T, _tuplebroadcast_getargs(As, k)...), _tuplebroadcast_reslength(As)) +@inline _tuplebroadcast_getargs(::Tuple{}, k) = () +@inline _tuplebroadcast_getargs(As, k) = + (_broadcast_getindex(first(As), k), _tuplebroadcast_getargs(tail(As), k)...) +@noinline _tuplebroadcast_reslength(As) = + _tuplebroadcast_maxlength(_tuplebroadcast_length(first(As)), tail(As)) +@inline _tuplebroadcast_maxlength(l, As) = + _tuplebroadcast_maxlength(max(l, _tuplebroadcast_length(first(As))), tail(As)) +@inline _tuplebroadcast_maxlength(l, ::Tuple{}) = l +@inline _tuplebroadcast_length(t::Tuple) = length(t) +@inline _tuplebroadcast_length(s) = 1 """ broadcast(f, As...) From 374519e7d742a8b412c1f3aee1be0ef8eebd448e Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Thu, 2 Mar 2017 14:37:47 -0500 Subject: [PATCH 0112/1534] Error if source-dist target is run in out-of-tree build --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 965aadb972cd9..61c6caf5c9542 100644 --- a/Makefile +++ b/Makefile @@ -480,8 +480,10 @@ else endif rm -fr $(BUILDROOT)/julia-$(JULIA_COMMIT) -# this target does not accept BUILDROOT light-source-dist.tmp: $(BUILDROOT)/doc/_build/html/en/index.html +ifneq ($(BUILDROOT),$(JULIAHOME)) + $(error make light-source-dist does not work in out-of-tree builds) +endif # Save git information -@$(MAKE) -C $(JULIAHOME)/base version_git.jl.phony @@ -491,7 +493,6 @@ light-source-dist.tmp: $(BUILDROOT)/doc/_build/html/en/index.html find doc/_build/html >> light-source-dist.tmp # Make tarball with only Julia code -# this target does not accept BUILDROOT light-source-dist: light-source-dist.tmp # Prefix everything with the current directory name (usually "julia"), then create tarball DIRNAME=$$(basename $$(pwd)); \ @@ -502,7 +503,6 @@ source-dist: @echo \'source-dist\' target is deprecated: use \'full-source-dist\' instead. # Make tarball with Julia code plus all dependencies -# this target does not accept BUILDROOT full-source-dist: light-source-dist.tmp # Get all the dependencies downloaded @$(MAKE) -C deps getall NO_GIT=1 From 7be90097b2868b56280e16d3095561011db0d536 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 24 Feb 2017 16:49:58 -0500 Subject: [PATCH 0113/1534] break some dependency backedges This would be nicer if we had function types, but this tries to at least hit a couple of the high points fix #20780 --- base/deprecated.jl | 1 + base/operators.jl | 18 +++++++++++------- base/promotion.jl | 4 ++-- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index 9ecfd1843f90f..36fc639baa403 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -826,6 +826,7 @@ end # Deprecate vectorized ! @deprecate(!(A::AbstractArray{Bool}), .!A) # parens for #20541 @deprecate(!(B::BitArray), .!B) # parens for #20541 +!(::typeof(()->())) = () # make sure ! has at least 4 methods so that for-loops don't end up getting a back-edge to depwarn # Deprecate vectorized ~ @deprecate ~(A::AbstractArray) .~A diff --git a/base/operators.jl b/base/operators.jl index 29e90e5890b88..bd8eceffbe108 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -86,13 +86,17 @@ false """ isequal(x, y) = x == y -isequal(x::AbstractFloat, y::AbstractFloat) = (isnan(x) & isnan(y)) | (signbit(x) == signbit(y)) & (x == y) -isequal(x::Real, y::AbstractFloat) = (isnan(x) & isnan(y)) | (signbit(x) == signbit(y)) & (x == y) -isequal(x::AbstractFloat, y::Real ) = (isnan(x) & isnan(y)) | (signbit(x) == signbit(y)) & (x == y) +signequal(x, y) = signbit(x)::Bool == signbit(y)::Bool +signless(x, y) = signbit(x)::Bool & !signbit(y)::Bool + +isequal(x::AbstractFloat, y::AbstractFloat) = (isnan(x) & isnan(y)) | signequal(x, y) & (x == y) +isequal(x::Real, y::AbstractFloat) = (isnan(x) & isnan(y)) | signequal(x, y) & (x == y) +isequal(x::AbstractFloat, y::Real ) = (isnan(x) & isnan(y)) | signequal(x, y) & (x == y) + +isless(x::AbstractFloat, y::AbstractFloat) = (!isnan(x) & isnan(y)) | signless(x, y) | (x < y) +isless(x::Real, y::AbstractFloat) = (!isnan(x) & isnan(y)) | signless(x, y) | (x < y) +isless(x::AbstractFloat, y::Real ) = (!isnan(x) & isnan(y)) | signless(x, y) | (x < y) -isless(x::AbstractFloat, y::AbstractFloat) = (!isnan(x) & isnan(y)) | (signbit(x) & !signbit(y)) | (x < y) -isless(x::Real, y::AbstractFloat) = (!isnan(x) & isnan(y)) | (signbit(x) & !signbit(y)) | (x < y) -isless(x::AbstractFloat, y::Real ) = (!isnan(x) & isnan(y)) | (signbit(x) & !signbit(y)) | (x < y) function ==(T::Type, S::Type) @_pure_meta @@ -122,7 +126,7 @@ julia> "foo" ≠ "foo" false ``` """ -!=(x, y) = !(x == y) +!=(x, y) = !(x == y)::Bool const ≠ = != """ diff --git a/base/promotion.jl b/base/promotion.jl index 98efd35b044a3..ef5d989e322d5 100644 --- a/base/promotion.jl +++ b/base/promotion.jl @@ -352,6 +352,6 @@ min(x::Real) = x max(x::Real) = x minmax(x::Real) = (x, x) -max{T<:Real}(x::T, y::T) = ifelse(y < x, x, y) -min{T<:Real}(x::T, y::T) = ifelse(y < x, y, x) +max{T<:Real}(x::T, y::T) = select_value(y < x, x, y) +min{T<:Real}(x::T, y::T) = select_value(y < x, y, x) minmax{T<:Real}(x::T, y::T) = y < x ? (y, x) : (x, y) From 7031584cf41d74365e54ec1afd290071342d0b3d Mon Sep 17 00:00:00 2001 From: Katie Hyatt Date: Mon, 27 Feb 2017 16:42:02 -0800 Subject: [PATCH 0114/1534] Add show methods for GitRebase and RebaseOperation --- base/libgit2/consts.jl | 12 ++++++------ base/libgit2/rebase.jl | 5 +++++ base/libgit2/types.jl | 5 ++++- test/libgit2.jl | 17 +++++++++++++++++ 4 files changed, 32 insertions(+), 7 deletions(-) diff --git a/base/libgit2/consts.jl b/base/libgit2/consts.jl index b37f6d283f1cc..5810e3293db14 100644 --- a/base/libgit2/consts.jl +++ b/base/libgit2/consts.jl @@ -177,12 +177,12 @@ module Consts const RESET_HARD = Cint(3) # MIXED plus changes in working tree discarded #rebase - const REBASE_OPERATION_PICK = Cint(0) - const REBASE_OPERATION_REWORD = Cint(1) - const REBASE_OPERATION_EDIT = Cint(2) - const REBASE_OPERATION_SQUASH = Cint(3) - const REBASE_OPERATION_FIXUP = Cint(4) - const REBASE_OPERATION_EXEC = Cint(5) + @enum(GIT_REBASE_OPERATION, REBASE_OPERATION_PICK = Cint(0), + REBASE_OPERATION_REWORD = Cint(1), + REBASE_OPERATION_EDIT = Cint(2), + REBASE_OPERATION_SQUASH = Cint(3), + REBASE_OPERATION_FIXUP = Cint(4), + REBASE_OPERATION_EXEC = Cint(5)) # fetch_prune const FETCH_PRUNE_UNSPECIFIED = Cint(0) diff --git a/base/libgit2/rebase.jl b/base/libgit2/rebase.jl index d89738d89672a..57d2ed0491f21 100644 --- a/base/libgit2/rebase.jl +++ b/base/libgit2/rebase.jl @@ -41,6 +41,11 @@ function Base.next(rb::GitRebase) return unsafe_load(rb_op_ptr_ptr[]) end +function Base.show(io::IO, rb::GitRebase) + println(io, "GitRebase:") + println(io, "Number: ", count(rb)) + println(io, "Currently performing operation: ",current(rb)+1) +end """ LibGit2.commit(rb::GitRebase, sig::GitSignature) diff --git a/base/libgit2/types.jl b/base/libgit2/types.jl index e688792c8ee46..3227475631d46 100644 --- a/base/libgit2/types.jl +++ b/base/libgit2/types.jl @@ -419,7 +419,10 @@ struct RebaseOperation id::GitHash exec::Cstring end -Base.show(io::IO, rbo::RebaseOperation) = print(io, "RebaseOperation($(string(rbo.id)))") +function Base.show(io::IO, rbo::RebaseOperation) + println(io, "RebaseOperation($(string(rbo.id)))") + println(io, "Operation type: $(Consts.GIT_REBASE_OPERATION(rbo.optype))") +end """ LibGit2.StatusOptions diff --git a/test/libgit2.jl b/test/libgit2.jl index eafa293e44410..3c80a53df456b 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -835,6 +835,23 @@ mktempdir() do dir newerhead = LibGit2.head_oid(repo) @test newerhead == newhead + + # add yet another file + open(joinpath(LibGit2.path(repo),"file5"),"w") do f + write(f, "555\n") + end + LibGit2.add!(repo, "file5") + LibGit2.commit(repo, "add file5") + + # Rebase type + head_ann = LibGit2.GitAnnotated(repo, "branch/a") + upst_ann = LibGit2.GitAnnotated(repo, "master") + rb = LibGit2.GitRebase(repo, head_ann, upst_ann) + rbo = next(rb) + rbo_str = sprint(show, rbo) + @test rbo_str == "RebaseOperation($(string(rbo.id)))\nOperation type: REBASE_OPERATION_PICK\n" + rb_str = sprint(show, rb) + @test rb_str == "GitRebase:\nNumber: 1\nCurrently performing operation: 1\n" finally close(repo) end From 8ca9f4c3a1ad25afaaf47a6286a54946e9302fc7 Mon Sep 17 00:00:00 2001 From: Katie Hyatt Date: Mon, 27 Feb 2017 17:46:43 -0800 Subject: [PATCH 0115/1534] Add a bounds check for getindex too --- base/libgit2/rebase.jl | 4 +++- test/libgit2.jl | 11 +++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/base/libgit2/rebase.jl b/base/libgit2/rebase.jl index 57d2ed0491f21..8a740497013af 100644 --- a/base/libgit2/rebase.jl +++ b/base/libgit2/rebase.jl @@ -21,10 +21,12 @@ function current(rb::GitRebase) end function Base.getindex(rb::GitRebase, i::Integer) + if !(1 <= i <= count(rb)) + throw(BoundsError(rb, (i,))) + end rb_op_ptr = ccall((:git_rebase_operation_byindex, :libgit2), Ptr{RebaseOperation}, (Ptr{Void}, Csize_t), rb.ptr, i-1) - rb_op_ptr == C_NULL && return nothing return unsafe_load(rb_op_ptr) end diff --git a/test/libgit2.jl b/test/libgit2.jl index 3c80a53df456b..6c350e757894b 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -836,22 +836,29 @@ mktempdir() do dir newerhead = LibGit2.head_oid(repo) @test newerhead == newhead - # add yet another file + # add yet more files open(joinpath(LibGit2.path(repo),"file5"),"w") do f write(f, "555\n") end LibGit2.add!(repo, "file5") LibGit2.commit(repo, "add file5") + open(joinpath(LibGit2.path(repo),"file6"),"w") do f + write(f, "666\n") + end + LibGit2.add!(repo, "file6") + LibGit2.commit(repo, "add file6") # Rebase type head_ann = LibGit2.GitAnnotated(repo, "branch/a") upst_ann = LibGit2.GitAnnotated(repo, "master") rb = LibGit2.GitRebase(repo, head_ann, upst_ann) + @test_throws BoundsError rb[3] + @test_throws BoundsError rb[0] rbo = next(rb) rbo_str = sprint(show, rbo) @test rbo_str == "RebaseOperation($(string(rbo.id)))\nOperation type: REBASE_OPERATION_PICK\n" rb_str = sprint(show, rb) - @test rb_str == "GitRebase:\nNumber: 1\nCurrently performing operation: 1\n" + @test rb_str == "GitRebase:\nNumber: 2\nCurrently performing operation: 1\n" finally close(repo) end From 81f72432ec3a0eb3b299d0815b103035368c981e Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 2 Mar 2017 21:27:21 -0500 Subject: [PATCH 0116/1534] fix #20835, segfault in ccall where type depends on local var (#20841) --- src/interpreter.c | 4 ++-- src/method.c | 19 ++++++++++++------- test/ccall.jl | 3 +++ 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/interpreter.c b/src/interpreter.c index 36e072c76458d..e5bd9b99a337f 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -191,14 +191,14 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s) jl_code_info_t *src = s==NULL ? NULL : s->src; if (jl_is_ssavalue(e)) { ssize_t id = ((jl_ssavalue_t*)e)->id; - if (id >= jl_source_nssavalues(src) || id < 0 || s->locals == NULL) + if (src == NULL || id >= jl_source_nssavalues(src) || id < 0 || s->locals == NULL) jl_error("access to invalid SSAValue"); else return s->locals[jl_source_nslots(src) + id]; } if (jl_is_slot(e)) { ssize_t n = jl_slot_number(e); - if (n > jl_source_nslots(src) || n < 1 || s->locals == NULL) + if (src == NULL || n > jl_source_nslots(src) || n < 1 || s->locals == NULL) jl_error("access to invalid slot number"); jl_value_t *v = s->locals[n-1]; if (v == NULL) diff --git a/src/method.c b/src/method.c index d9b98aecd1f8f..f6349122fd78c 100644 --- a/src/method.c +++ b/src/method.c @@ -72,13 +72,18 @@ jl_value_t *jl_resolve_globals(jl_value_t *expr, jl_module_t *module, jl_svec_t JL_NARGSV(ccall method definition, 3); // (fptr, rt, at) jl_value_t *rt = jl_exprarg(e, 1); jl_value_t *at = jl_exprarg(e, 2); - if (!jl_is_type(rt)) { - rt = jl_interpret_toplevel_expr_in(module, rt, NULL, sparam_vals); - jl_exprargset(e, 1, rt); + JL_TRY { + if (!jl_is_type(rt)) { + rt = jl_interpret_toplevel_expr_in(module, rt, NULL, sparam_vals); + jl_exprargset(e, 1, rt); + } + if (!jl_is_svec(at)) { + at = jl_interpret_toplevel_expr_in(module, at, NULL, sparam_vals); + jl_exprargset(e, 2, at); + } } - if (!jl_is_svec(at)) { - at = jl_interpret_toplevel_expr_in(module, at, NULL, sparam_vals); - jl_exprargset(e, 2, at); + JL_CATCH { + jl_error("invalid return type or argument type in ccall"); } if (jl_is_svec(rt)) jl_error("ccall: missing return type"); @@ -91,7 +96,7 @@ jl_value_t *jl_resolve_globals(jl_value_t *expr, jl_module_t *module, jl_svec_t if ((!isVa && nargt != (nargs - 2) / 2) || ( isVa && nargt - 1 > (nargs - 2) / 2)) { jl_printf(JL_STDERR, "WARNING: ccall: wrong number of arguments to C function in %s\n", - jl_symbol_name(module->name)); // TODO: make this an error + jl_symbol_name(module->name)); // TODO: make this an error } } if (e->head == method_sym || e->head == abstracttype_sym || e->head == compositetype_sym || diff --git a/test/ccall.jl b/test/ccall.jl index 2e8c067474646..a2c6d19f17b71 100644 --- a/test/ccall.jl +++ b/test/ccall.jl @@ -1236,3 +1236,6 @@ for i in 1:100 @test_spill_n 9 int32args float32args @test_spill_n 10 int32args float32args end + +# issue #20835 +@test_throws ErrorException eval(:(f20835(x) = ccall(:fn, Void, (Ptr{typeof(x)},), x))) From e9c1c3b11775bcaffb2e8f3f934d95f40aa63591 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Thu, 2 Mar 2017 20:10:19 -0800 Subject: [PATCH 0117/1534] Fix type of diff-files kwarg (#20861) --- base/libgit2/libgit2.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/libgit2/libgit2.jl b/base/libgit2/libgit2.jl index edba09be9bba3..3ef4a9dd379d8 100644 --- a/base/libgit2/libgit2.jl +++ b/base/libgit2/libgit2.jl @@ -128,7 +128,7 @@ Show which files have changed in the git repository `repo` between branches `bra and `branch2`. The keyword argument is: - * `filter::Set{Cint}=Set([Consts.DELTA_ADDED, Consts.DELTA_MODIFIED, Consts.DELTA_DELETED]))`, + * `filter::Set{Consts.DELTA_STATUS}=Set([Consts.DELTA_ADDED, Consts.DELTA_MODIFIED, Consts.DELTA_DELETED]))`, and it sets options for the diff. The default is to show files added, modified, or deleted. Returns only the *names* of the files which have changed, *not* their contents. From 0864d7ef34e29599df0a0cd933c162f150fa155a Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Fri, 3 Mar 2017 07:17:28 -0800 Subject: [PATCH 0118/1534] More tests for GitIndex (#20864) --- test/libgit2.jl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/libgit2.jl b/test/libgit2.jl index eafa293e44410..b0e4b7bfe5a07 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -725,6 +725,13 @@ mktempdir() do dir @test isnull(i) idx_str = sprint(show, idx) @test idx_str == "GitIndex:\nRepository: $(LibGit2.repository(idx))\nNumber of elements: 1\n" + + LibGit2.remove!(repo, test_file) + LibGit2.read!(repo) + @test count(idx) == 0 + LibGit2.add!(repo, test_file) + LibGit2.update!(repo, test_file) + @test count(idx) == 1 end # check non-existent file status From bb76add105e4dbda5185815fe0509b1b70fc0486 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Fri, 3 Mar 2017 16:14:28 -0800 Subject: [PATCH 0119/1534] Fix sparse broadcast[!] for some cases (#20862) where the output eltype is not a concrete subtype of Number (#19561, later part). --- base/sparse/higherorderfns.jl | 10 +++++----- test/sparse/higherorderfns.jl | 24 +++++++++++++++++------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/base/sparse/higherorderfns.jl b/base/sparse/higherorderfns.jl index 858d4527fdb49..e4fa8b7613ea6 100644 --- a/base/sparse/higherorderfns.jl +++ b/base/sparse/higherorderfns.jl @@ -582,7 +582,7 @@ function _broadcast_zeropres!{Tf}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, B Bk, stopBk = numcols(B) == 1 ? (colstartind(B, 1), colboundind(B, 1)) : (colstartind(B, j), colboundind(B, j)) Ax = Ak < stopAk ? storedvals(A)[Ak] : zero(eltype(A)) fvAzB = f(Ax, zero(eltype(B))) - if fvAzB == zero(eltype(C)) + if _iszero(fvAzB) # either A's jth column is empty, or A's jth column contains a nonzero value # Ax but f(Ax, zero(eltype(B))) is nonetheless zero, so we can scan through # B's jth column without storing every entry in C's jth column @@ -623,7 +623,7 @@ function _broadcast_zeropres!{Tf}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, B Bk, stopBk = numcols(B) == 1 ? (colstartind(B, 1), colboundind(B, 1)) : (colstartind(B, j), colboundind(B, j)) Bx = Bk < stopBk ? storedvals(B)[Bk] : zero(eltype(B)) fzAvB = f(zero(eltype(A)), Bx) - if fzAvB == zero(eltype(C)) + if _iszero(fzAvB) # either B's jth column is empty, or B's jth column contains a nonzero value # Bx but f(zero(eltype(A)), Bx) is nonetheless zero, so we can scan through # A's jth column without storing every entry in C's jth column @@ -701,7 +701,7 @@ function _broadcast_notzeropres!{Tf}(f::Tf, fillvalue, C::SparseVecOrMat, A::Spa Bk, stopBk = numcols(B) == 1 ? (colstartind(B, 1), colboundind(B, 1)) : (colstartind(B, j), colboundind(B, j)) Ax = Ak < stopAk ? storedvals(A)[Ak] : zero(eltype(A)) fvAzB = f(Ax, zero(eltype(B))) - if fvAzB == zero(eltype(C)) + if _iszero(fvAzB) while Bk < stopBk Cx = f(Ax, storedvals(B)[Bk]) Cx != fillvalue && (storedvals(C)[jo + storedinds(B)[Bk]] = Cx) @@ -726,7 +726,7 @@ function _broadcast_notzeropres!{Tf}(f::Tf, fillvalue, C::SparseVecOrMat, A::Spa Bk, stopBk = numcols(B) == 1 ? (colstartind(B, 1), colboundind(B, 1)) : (colstartind(B, j), colboundind(B, j)) Bx = Bk < stopBk ? storedvals(B)[Bk] : zero(eltype(B)) fzAvB = f(zero(eltype(A)), Bx) - if fzAvB == zero(eltype(C)) + if _iszero(fzAvB) while Ak < stopAk Cx = f(storedvals(A)[Ak], Bx) Cx != fillvalue && (storedvals(C)[jo + storedinds(A)[Ak]] = Cx) @@ -771,7 +771,7 @@ function _broadcast_zeropres!{Tf,N}(f::Tf, C::SparseVecOrMat, As::Vararg{SparseV rows = _initrowforcol_all(j, rowsentinel, isemptys, expandsverts, ks, As) defaultCx = f(defargs...) activerow = min(rows...) - if defaultCx == zero(eltype(C)) # zero-preserving column scan + if _iszero(defaultCx) # zero-preserving column scan while activerow < rowsentinel # activerows = _isactiverow_all(activerow, rows) # Cx = f(_gatherbcargs(activerows, defargs, ks, As)...) diff --git a/test/sparse/higherorderfns.jl b/test/sparse/higherorderfns.jl index a8589f205ade6..591b86ad4bdc3 100644 --- a/test/sparse/higherorderfns.jl +++ b/test/sparse/higherorderfns.jl @@ -265,14 +265,24 @@ end end end - @testset "sparse map/broadcast with result eltype not a concrete subtype of Number (#19561/#19589)" begin - intoneorfloatzero(x) = x != 0.0 ? Int(1) : Float64(x) - stringorfloatzero(x) = x != 0.0 ? "Hello" : Float64(x) - @test map(intoneorfloatzero, speye(4)) == sparse(map(intoneorfloatzero, eye(4))) - @test map(stringorfloatzero, speye(4)) == sparse(map(stringorfloatzero, eye(4))) - @test broadcast(intoneorfloatzero, speye(4)) == sparse(broadcast(intoneorfloatzero, eye(4))) - @test broadcast(stringorfloatzero, speye(4)) == sparse(broadcast(stringorfloatzero, eye(4))) + N = 4 + A, fA = speye(N), eye(N) + B, fB = spzeros(1, N), zeros(1, N) + intorfloat_zeropres(xs...) = all(iszero, xs) ? zero(Float64) : Int(1) + stringorfloat_zeropres(xs...) = all(iszero, xs) ? zero(Float64) : "hello" + intorfloat_notzeropres(xs...) = all(iszero, xs) ? Int(1) : zero(Float64) + stringorfloat_notzeropres(xs...) = all(iszero, xs) ? "hello" : zero(Float64) + for fn in (intorfloat_zeropres, intorfloat_notzeropres, + stringorfloat_zeropres, stringorfloat_notzeropres) + @test map(fn, A) == sparse(map(fn, fA)) + @test broadcast(fn, A) == sparse(broadcast(fn, fA)) + @test broadcast(fn, A, B) == sparse(broadcast(fn, fA, fB)) + @test broadcast(fn, B, A) == sparse(broadcast(fn, fB, fA)) + end + for fn in (intorfloat_zeropres, stringorfloat_zeropres) + @test broadcast(fn, A, B, A) == sparse(broadcast(fn, fA, fB, fA)) + end end @testset "broadcast[!] over combinations of scalars and sparse vectors/matrices" begin From 86d103ca60e24db16c104f3ebb797857cd5a1884 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Fri, 3 Mar 2017 22:33:28 -0500 Subject: [PATCH 0120/1534] Fix missing GC root `jl_svec` needs rooted arguments, but even so jl_alloc_vec_any allocates, so mti could have been gc'ed there. --- src/gf.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/gf.c b/src/gf.c index 4a8258bc5dfe3..636c1f0fb0da7 100644 --- a/src/gf.c +++ b/src/gf.c @@ -2584,12 +2584,13 @@ static int ml_matches_visitor(jl_typemap_entry_t *ml, struct typemap_intersectio // add it to the results. if (return_this_match && meth->ambig != jl_nothing && (!closure->include_ambiguous || done)) { jl_svec_t *env = NULL; - JL_GC_PUSH1(&env); + jl_value_t *mti = NULL; + JL_GC_PUSH2(&env, &mti); for (size_t j = 0; j < jl_array_len(meth->ambig); j++) { jl_method_t *mambig = (jl_method_t*)jl_array_ptr_ref(meth->ambig, j); env = jl_emptysvec; - jl_value_t *mti = jl_type_intersection_env((jl_value_t*)closure->match.type, - (jl_value_t*)mambig->sig, &env); + mti = jl_type_intersection_env((jl_value_t*)closure->match.type, + (jl_value_t*)mambig->sig, &env); if (mti != (jl_value_t*)jl_bottom_type) { if (closure->include_ambiguous) { assert(done); @@ -2602,8 +2603,8 @@ static int ml_matches_visitor(jl_typemap_entry_t *ml, struct typemap_intersectio if (len == 0) { closure->t = (jl_value_t*)jl_alloc_vec_any(0); } - jl_array_ptr_1d_push((jl_array_t*)closure->t, - (jl_value_t*)jl_svec(3, mti, env, mambig)); + mti = (jl_value_t*)jl_svec(3, mti, env, mambig); + jl_array_ptr_1d_push((jl_array_t*)closure->t, mti); len++; } } From 145eae8c28d627eb1e81c5d965db200ab49ff75d Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Sat, 4 Mar 2017 02:09:47 -0800 Subject: [PATCH 0121/1534] Add patch to set `-O2` for suitesparse build (#20165) [ci skip] --- deps/patches/SuiteSparse-O2.patch | 11 +++++++++++ deps/suitesparse.mk | 7 ++++++- 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 deps/patches/SuiteSparse-O2.patch diff --git a/deps/patches/SuiteSparse-O2.patch b/deps/patches/SuiteSparse-O2.patch new file mode 100644 index 0000000000000..7f2144f21261e --- /dev/null +++ b/deps/patches/SuiteSparse-O2.patch @@ -0,0 +1,11 @@ +--- SuiteSparse_config/SuiteSparse_config.mk 2014-12-22 14:21:00.000000000 -0800 ++++ SuiteSparse_config/SuiteSparse_config.mk 2017-01-20 15:17:43.000000000 -0800 +@@ -69,7 +69,7 @@ + # C and C++ compiler flags. The first three are standard for *.c and *.cpp + # Add -DNTIMER if you do use any timing routines (otherwise -lrt is required). + # CF = $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -O3 -fexceptions -fPIC -DNTIMER +- CF = $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -O3 -fexceptions -fPIC ++ CF = $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -O2 -fexceptions -fPIC + # for the MKL BLAS: + # CF = $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -O3 -fexceptions -fPIC -I$(MKLROOT)/include -D_GNU_SOURCE + # with no optimization: diff --git a/deps/suitesparse.mk b/deps/suitesparse.mk index 90b237628175e..8baf6014eaf23 100644 --- a/deps/suitesparse.mk +++ b/deps/suitesparse.mk @@ -37,12 +37,17 @@ $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/SuiteSparse-winclang.patch-applied: $ cd $(dir $@) && patch -p0 < $(SRCDIR)/patches/SuiteSparse-winclang.patch echo 1 > $@ +$(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/SuiteSparse-O2.patch-applied: $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/SuiteSparse-winclang.patch-applied + cd $(dir $@) && patch -p0 < $(SRCDIR)/patches/SuiteSparse-O2.patch + echo 1 > $@ + + ifeq ($(USE_SYSTEM_BLAS), 0) $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/build-compiled: | $(build_prefix)/manifest/openblas else ifeq ($(USE_SYSTEM_LAPACK), 0) $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/build-compiled: | $(build_prefix)/manifest/lapack endif -$(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/build-compiled: $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/source-extracted $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/SuiteSparse-winclang.patch-applied +$(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/build-compiled: $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/source-extracted $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/SuiteSparse-O2.patch-applied $(MAKE) -C $(dir $<) library $(SUITESPARSE_MFLAGS) echo 1 > $@ From 51b4f64ddc16642beaa12750ce1ad3f5e95a7874 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Mon, 8 Aug 2016 13:22:04 +0800 Subject: [PATCH 0122/1534] Accept any callable object as input of `cfucntion` --- base/c.jl | 2 +- test/ccall.jl | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/base/c.jl b/base/c.jl index 1e9764e1c12aa..34d4f86c80c4a 100644 --- a/base/c.jl +++ b/base/c.jl @@ -4,7 +4,7 @@ import Core.Intrinsics: cglobal, bitcast -cfunction(f::Function, r, a) = ccall(:jl_function_ptr, Ptr{Void}, (Any, Any, Any), f, r, a) +cfunction(f, r, a) = ccall(:jl_function_ptr, Ptr{Void}, (Any, Any, Any), f, r, a) if ccall(:jl_is_char_signed, Ref{Bool}, ()) const Cchar = Int8 diff --git a/test/ccall.jl b/test/ccall.jl index a2c6d19f17b71..33b4ec9811948 100644 --- a/test/ccall.jl +++ b/test/ccall.jl @@ -1239,3 +1239,10 @@ end # issue #20835 @test_throws ErrorException eval(:(f20835(x) = ccall(:fn, Void, (Ptr{typeof(x)},), x))) + +# cfunction on non-function singleton +struct CallableSingleton +end +(::CallableSingleton)(x, y) = x + y +@test ccall(cfunction(CallableSingleton(), Int, Tuple{Int,Int}), + Int, (Int, Int), 1, 2) === 3 From 656da3399bb481e99feb2cd30d1916cb3ae5babe Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 3 Mar 2017 18:20:53 -0500 Subject: [PATCH 0123/1534] ensure codegen normalizes BottomType to Type{Union{}} otherwise, it can become confused why both Type{Union{}} and BottomType are both leaftypes that are not equal but are both accepted as the type of the constant singleton type object Union{} fix #20764 --- src/codegen.cpp | 58 +++++++++++++++++++++++++++++++------------------ test/core.jl | 5 +++++ 2 files changed, 42 insertions(+), 21 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index d13c98bcf603b..b487f10d2902d 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -677,6 +677,16 @@ static inline jl_cgval_t ghostValue(jl_value_t *typ) { if (typ == jl_bottom_type) return jl_cgval_t(); // Undef{} + if (typ == (jl_value_t*)jl_bottomtype_type) { + // normalize BottomType to Type{Union{}} + typ = (jl_value_t*)jl_wrap_Type(jl_bottom_type); + } + if (jl_is_type_type(typ)) { + // replace T::Type{T} with T, by assuming that T must be a leaftype of some sort + jl_cgval_t constant(NULL, NULL, true, typ, NULL); + constant.constant = jl_tparam0(typ); + return constant; + } return jl_cgval_t(typ); } static inline jl_cgval_t ghostValue(jl_datatype_t *typ) @@ -684,6 +694,24 @@ static inline jl_cgval_t ghostValue(jl_datatype_t *typ) return ghostValue((jl_value_t*)typ); } +static inline jl_cgval_t mark_julia_const(jl_value_t *jv) +{ + jl_value_t *typ; + if (jl_is_type(jv)) { + typ = (jl_value_t*)jl_wrap_Type(jv); // TODO: gc-root this? + } + else { + typ = jl_typeof(jv); + if (type_is_ghost(julia_type_to_llvm(typ))) { + return ghostValue(typ); + } + } + jl_cgval_t constant(NULL, NULL, true, typ, NULL); + constant.constant = jv; + return constant; +} + + static inline jl_cgval_t mark_julia_slot(Value *v, jl_value_t *typ, Value *tindex, MDNode *tbaa) { // this enables lazy-copying of immutable values and stack or argument slots @@ -700,11 +728,12 @@ static inline jl_cgval_t mark_julia_type(Value *v, bool isboxed, jl_value_t *typ // no need to explicitly load/store a constant/ghost value return ghostValue(typ); } - if (jl_is_type_type(typ) && jl_is_leaf_type(jl_tparam0(typ))) { - // replace T::Type{T} with T - jl_cgval_t constant(NULL, NULL, true, typ, NULL); - constant.constant = jl_tparam0(typ); - return constant; + if (jl_is_type_type(typ)) { + jl_value_t *tp0 = jl_tparam0(typ); + if (jl_is_leaf_type(tp0) || tp0 == jl_bottom_type) { + // replace T::Type{T} with T + return ghostValue(typ); + } } Type *T = julia_type_to_llvm(typ); if (type_is_ghost(T)) { @@ -733,7 +762,7 @@ static inline jl_cgval_t mark_julia_type(Value *v, bool isboxed, jl_datatype_t * // see if it might be profitable (and cheap) to change the type of v to typ static inline jl_cgval_t update_julia_type(const jl_cgval_t &v, jl_value_t *typ, jl_codectx_t *ctx) { - if (v.typ == typ || v.typ == jl_bottom_type || jl_egal(v.typ, typ) || typ == (jl_value_t*)jl_any_type) + if (v.typ == typ || v.typ == jl_bottom_type || v.constant || typ == (jl_value_t*)jl_any_type || jl_egal(v.typ, typ)) return v; // fast-path if (jl_is_leaf_type(v.typ) && !jl_is_kind(v.typ)) { if (jl_is_leaf_type(typ) && !jl_is_kind(typ) && !((jl_datatype_t*)typ)->abstract && !((jl_datatype_t*)v.typ)->abstract) { @@ -764,21 +793,6 @@ static inline jl_cgval_t update_julia_type(const jl_cgval_t &v, jl_value_t *typ, return jl_cgval_t(v, typ, NULL); } -static inline jl_cgval_t mark_julia_const(jl_value_t *jv) -{ - jl_value_t *typ; - if (jl_is_type(jv)) - typ = (jl_value_t*)jl_wrap_Type(jv); // TODO: gc-root this? - else - typ = jl_typeof(jv); - if (type_is_ghost(julia_type_to_llvm(typ))) { - return ghostValue(typ); - } - jl_cgval_t constant(NULL, NULL, true, typ, NULL); - constant.constant = jv; - return constant; -} - // --- allocating local variables --- static jl_sym_t *slot_symbol(int s, jl_codectx_t *ctx) @@ -859,6 +873,8 @@ static void jl_rethrow_with_add(const char *fmt, ...) // given a value marked with type `v.typ`, compute the mapping and/or boxing to return a value of type `typ` static jl_cgval_t convert_julia_type(const jl_cgval_t &v, jl_value_t *typ, jl_codectx_t *ctx, bool needsroot = true) { + if (typ == (jl_value_t*)jl_bottomtype_type) + return ghostValue(typ); // normalize BottomType to Type{Union{}} if (v.typ == typ || v.typ == jl_bottom_type || jl_egal(v.typ, typ)) return v; // fast-path Type *T = julia_type_to_llvm(typ); diff --git a/test/core.jl b/test/core.jl index dc777dbe03a4c..bf8dfac0febf5 100644 --- a/test/core.jl +++ b/test/core.jl @@ -4755,3 +4755,8 @@ end x::Vector{S} y::Vector{T} end + +let a = Array{Core.BottomType, 1}(2) + @test a[1] == Union{} + @test a == [Union{}, Union{}] +end From f92f6ad0ec4cc3f1ba93e41367343a170bfa705b Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Tue, 7 Feb 2017 09:39:24 -0500 Subject: [PATCH 0124/1534] Move `static_assert` to `julia_internal.h` --- src/codegen.cpp | 4 ---- src/jl_uv.c | 14 -------------- src/julia_internal.h | 14 ++++++++++++++ 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index d13c98bcf603b..7e72160ec86d0 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -137,10 +137,6 @@ PassManager *jl_globalPM; #define AddrSpaceCastInst BitCastInst #endif -#if !defined(_COMPILER_MICROSOFT_) && __cplusplus < 201103L && !defined(static_assert) -# define static_assert(...) -#endif - extern "C" { #include "builtin_proto.h" diff --git a/src/jl_uv.c b/src/jl_uv.c index 6c8bbe3e90007..249d63a98678c 100644 --- a/src/jl_uv.c +++ b/src/jl_uv.c @@ -28,20 +28,6 @@ #define write _write #endif -#ifndef static_assert -# ifndef __cplusplus -# define static_assert(...) -// Remove the following gcc special handling when we officially requires -// gcc 4.7 (for c++11) and -std=gnu11 -# ifdef __GNUC__ -# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) -# undef static_assert -# define static_assert _Static_assert -# endif -# endif -# endif -#endif - #ifdef __cplusplus #include extern "C" { diff --git a/src/julia_internal.h b/src/julia_internal.h index 1d7c4ecd171a7..a652ef16ef85e 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -26,6 +26,20 @@ #endif #endif +// Remove when C11 is required for C code. +#ifndef static_assert +# ifndef __cplusplus +// C11 should already have `static_assert` from `` so there's no need +// to check C version. +# ifdef __GNUC__ +# define static_assert _Static_assert +# else +# define static_assert(...) +# endif +# endif +// For C++, C++11 or MSVC is required. Both provide `static_assert`. +#endif + #ifdef __cplusplus extern "C" { #endif From 08f00b583e849a3c28ab61d44ab34972e35ef9c2 Mon Sep 17 00:00:00 2001 From: fcard Date: Sat, 4 Mar 2017 20:55:16 -0300 Subject: [PATCH 0125/1534] RFC: Fix skipchars inexact error/hanging (#16892) (#18752) * Fix skipchars inexact error (#16892) * fix indent ((squash)) * add parentheses to test_skipchars macrocalls ((squash)) The whitespace separating strings containing whitespace was hurting my eyes. * Remove now unused unexported function peekchar And its friend, the _chtmp const. * Make Char(0xffffffff) as a possible value for the linecomment argument ((squash)) * change `action` argument name to `skipcomment` ((squash)) * Simplify function * Restore peekchar * Remove support for IOBuffer * Trailling whitespace + typo --- base/iostream.jl | 21 +++++++++++---------- test/choosetests.jl | 2 +- test/iostream.jl | 31 +++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 11 deletions(-) create mode 100644 test/iostream.jl diff --git a/base/iostream.jl b/base/iostream.jl index 099e11afc33ff..0fa45aea98954 100644 --- a/base/iostream.jl +++ b/base/iostream.jl @@ -312,7 +312,7 @@ end const _chtmp = Array{Char}(1) function peekchar(s::IOStream) if ccall(:ios_peekutf8, Cint, (Ptr{Void}, Ptr{Char}), s, _chtmp) < 0 - return Char(-1) + return typemax(Char) end return _chtmp[1] end @@ -321,15 +321,16 @@ function peek(s::IOStream) ccall(:ios_peekc, Cint, (Ptr{Void},), s) end -function skipchars(s::IOStream, pred; linecomment::Char=Char(0xffffffff)) - ch = peekchar(s); status = Int(ch) - while status >= 0 && (pred(ch) || ch == linecomment) - if ch == linecomment - readline(s) - else - read(s, Char) # advance one character +function skipchars(io::IOStream, pred; linecomment=nothing) + while !eof(io) + c = read(io, Char) + if c === linecomment + readline(io) + elseif !pred(c) + seek(io,position(io)-sizeof(string(c))) + break end - ch = peekchar(s); status = Int(ch) end - return s + return io end + diff --git a/test/choosetests.jl b/test/choosetests.jl index dff7ae807b7fb..c693ecdcaecba 100644 --- a/test/choosetests.jl +++ b/test/choosetests.jl @@ -35,7 +35,7 @@ function choosetests(choices = []) "enums", "cmdlineargs", "i18n", "workspace", "libdl", "int", "checked", "intset", "floatfuncs", "compile", "distributed", "inline", "boundscheck", "error", "ambiguous", "cartesian", "asmvariant", "osutils", - "channels" + "channels", "iostream" ] profile_skipped = false if startswith(string(Sys.ARCH), "arm") diff --git a/test/iostream.jl b/test/iostream.jl new file mode 100644 index 0000000000000..fb241ae728e8c --- /dev/null +++ b/test/iostream.jl @@ -0,0 +1,31 @@ +# Test skipchars for IOStreams +mktemp() do path, file + function append_to_file(str) + mark(file) + println(file, str) + flush(file) + reset(file) + end + + # test it doesn't error on eof + @test skipchars(file, isspace) == file + + # test if it correctly skips + append_to_file(" ") + @test eof(skipchars(file, isspace)) + + # test it correctly detects comment lines + append_to_file("# \n ") + @test eof(skipchars(file, isspace, linecomment='#')) + + # test it stops at the appropriate time + append_to_file(" not a space") + @test skipchars(file, isspace) == file + @test !eof(file) && read(file, Char) == 'n' + + # test it correctly ignores the contents of comment lines + append_to_file(" #not a space \n not a space") + @test skipchars(file, isspace, linecomment='#') == file + @test !eof(file) && read(file, Char) == 'n' +end + From 05d66d1982a85de64b59eb83659a5e30a98c1186 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Wed, 1 Mar 2017 13:48:42 -0500 Subject: [PATCH 0126/1534] Upgrade PCRE to 10.23 Add patch for https://bugs.exim.org/show_bug.cgi?id=2067 --- deps/Versions.make | 2 +- deps/checksums/pcre2-10.22.tar.bz2/md5 | 1 - deps/checksums/pcre2-10.22.tar.bz2/sha512 | 1 - deps/checksums/pcre2-10.23.tar.bz2/md5 | 1 + deps/checksums/pcre2-10.23.tar.bz2/sha512 | 1 + deps/patches/pcre-mingw.patch | 13 +++++++++++++ deps/pcre.mk | 7 ++++++- 7 files changed, 22 insertions(+), 4 deletions(-) delete mode 100644 deps/checksums/pcre2-10.22.tar.bz2/md5 delete mode 100644 deps/checksums/pcre2-10.22.tar.bz2/sha512 create mode 100644 deps/checksums/pcre2-10.23.tar.bz2/md5 create mode 100644 deps/checksums/pcre2-10.23.tar.bz2/sha512 create mode 100644 deps/patches/pcre-mingw.patch diff --git a/deps/Versions.make b/deps/Versions.make index 9d205fc7d9d02..e45337dab8c65 100644 --- a/deps/Versions.make +++ b/deps/Versions.make @@ -1,5 +1,5 @@ LLVM_VER = 3.9.1 -PCRE_VER = 10.22 +PCRE_VER = 10.23 DSFMT_VER = 2.2.3 LAPACK_VER = 3.5.0 ARPACK_VER = 3.3.0 diff --git a/deps/checksums/pcre2-10.22.tar.bz2/md5 b/deps/checksums/pcre2-10.22.tar.bz2/md5 deleted file mode 100644 index 6d0daf513a250..0000000000000 --- a/deps/checksums/pcre2-10.22.tar.bz2/md5 +++ /dev/null @@ -1 +0,0 @@ -c0c02517938ee2b0d350d53edf450664 diff --git a/deps/checksums/pcre2-10.22.tar.bz2/sha512 b/deps/checksums/pcre2-10.22.tar.bz2/sha512 deleted file mode 100644 index f900dfbc64833..0000000000000 --- a/deps/checksums/pcre2-10.22.tar.bz2/sha512 +++ /dev/null @@ -1 +0,0 @@ -dcf70b5e5b73f29188a56e4d9efb9afdf2b9ebe50e13a7640b80f543851235a289e476e1f517f49fac9628b456268bcdaf2b492237bc879ddff36f84ef4f32ea diff --git a/deps/checksums/pcre2-10.23.tar.bz2/md5 b/deps/checksums/pcre2-10.23.tar.bz2/md5 new file mode 100644 index 0000000000000..a562ef4a269d3 --- /dev/null +++ b/deps/checksums/pcre2-10.23.tar.bz2/md5 @@ -0,0 +1 @@ +b2cd00ca7e24049040099b0a46bb3649 diff --git a/deps/checksums/pcre2-10.23.tar.bz2/sha512 b/deps/checksums/pcre2-10.23.tar.bz2/sha512 new file mode 100644 index 0000000000000..61a5555f9b950 --- /dev/null +++ b/deps/checksums/pcre2-10.23.tar.bz2/sha512 @@ -0,0 +1 @@ +3e5910bd2405cc35934d91e4be760abe4f2e900202a20b6ba74adb7a3acb2b74b3bf9b0e97e8de10f8e8534133e0722e0bf0f5fb40d6c2c4520d1ed61749d456 diff --git a/deps/patches/pcre-mingw.patch b/deps/patches/pcre-mingw.patch new file mode 100644 index 0000000000000..862cd4bf3a0a9 --- /dev/null +++ b/deps/patches/pcre-mingw.patch @@ -0,0 +1,13 @@ +diff --git a/src/pcre2grep.c b/src/pcre2grep.c +index e98d743..f00dac2 100644 +--- a/src/pcre2grep.c ++++ b/src/pcre2grep.c +@@ -628,7 +628,7 @@ z/OS, and "no support". */ + + /************* Directory scanning Unix-style and z/OS ***********/ + +-#if (defined HAVE_SYS_STAT_H && defined HAVE_DIRENT_H && defined HAVE_SYS_TYPES_H) || defined NATIVE_ZOS ++#if ((defined HAVE_SYS_STAT_H && defined HAVE_DIRENT_H && defined HAVE_SYS_TYPES_H) || defined NATIVE_ZOS) && !defined WIN32 + #include + #include + #include diff --git a/deps/pcre.mk b/deps/pcre.mk index 1fc32088f778e..bdc784d67eb19 100644 --- a/deps/pcre.mk +++ b/deps/pcre.mk @@ -13,7 +13,12 @@ $(SRCDIR)/srccache/pcre2-$(PCRE_VER)/source-extracted: $(SRCDIR)/srccache/pcre2- touch -c $(SRCDIR)/srccache/pcre2-$(PCRE_VER)/configure # old target echo $1 > $@ -$(BUILDDIR)/pcre2-$(PCRE_VER)/build-configured: $(SRCDIR)/srccache/pcre2-$(PCRE_VER)/source-extracted +# patch for mingw build https://bugs.exim.org/show_bug.cgi?id=2067 +$(SRCDIR)/srccache/pcre2-$(PCRE_VER)/pcre-mingw.patch-applied: $(SRCDIR)/srccache/pcre2-$(PCRE_VER)/source-extracted + cd $(dir $@) && patch -p1 < $(SRCDIR)/patches/pcre-mingw.patch + echo 1 > $@ + +$(BUILDDIR)/pcre2-$(PCRE_VER)/build-configured: $(SRCDIR)/srccache/pcre2-$(PCRE_VER)/source-extracted $(SRCDIR)/srccache/pcre2-$(PCRE_VER)/pcre-mingw.patch-applied mkdir -p $(dir $@) cd $(dir $@) && \ $(dir $<)/configure $(CONFIGURE_COMMON) --enable-jit --includedir=$(build_includedir) CFLAGS="$(CFLAGS) $(PCRE_CFLAGS)" LDFLAGS="$(LDFLAGS) $(PCRE_LDFLAGS)" From 9048c04374a8485a2ea9ee3fc4c577ab65199b71 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Sun, 5 Mar 2017 00:25:55 -0800 Subject: [PATCH 0127/1534] Upgrade FFTW to 3.3.6-pl1 --- deps/Versions.make | 2 +- deps/checksums/fftw-3.3.5.tar.gz/md5 | 1 - deps/checksums/fftw-3.3.5.tar.gz/sha512 | 1 - deps/checksums/fftw-3.3.6-pl1.tar.gz/md5 | 1 + deps/checksums/fftw-3.3.6-pl1.tar.gz/sha512 | 1 + deps/fftw.mk | 6 +-- deps/patches/fftw-win32-intrin-h.patch | 42 --------------------- 7 files changed, 4 insertions(+), 50 deletions(-) delete mode 100644 deps/checksums/fftw-3.3.5.tar.gz/md5 delete mode 100644 deps/checksums/fftw-3.3.5.tar.gz/sha512 create mode 100644 deps/checksums/fftw-3.3.6-pl1.tar.gz/md5 create mode 100644 deps/checksums/fftw-3.3.6-pl1.tar.gz/sha512 delete mode 100644 deps/patches/fftw-win32-intrin-h.patch diff --git a/deps/Versions.make b/deps/Versions.make index e45337dab8c65..0486758d2bc2b 100644 --- a/deps/Versions.make +++ b/deps/Versions.make @@ -3,7 +3,7 @@ PCRE_VER = 10.23 DSFMT_VER = 2.2.3 LAPACK_VER = 3.5.0 ARPACK_VER = 3.3.0 -FFTW_VER = 3.3.5 +FFTW_VER = 3.3.6-pl1 SUITESPARSE_VER = 4.4.5 UNWIND_VER = 1.1-julia2 OSXUNWIND_VER = 0.0.3 diff --git a/deps/checksums/fftw-3.3.5.tar.gz/md5 b/deps/checksums/fftw-3.3.5.tar.gz/md5 deleted file mode 100644 index c6a010259df7a..0000000000000 --- a/deps/checksums/fftw-3.3.5.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -6cc08a3b9c7ee06fdd5b9eb02e06f569 diff --git a/deps/checksums/fftw-3.3.5.tar.gz/sha512 b/deps/checksums/fftw-3.3.5.tar.gz/sha512 deleted file mode 100644 index 947ef17fab632..0000000000000 --- a/deps/checksums/fftw-3.3.5.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -a81f02d884cfe4171fab479b0e5ec76eceb9c5da6d4eda1f89281b7e1efa2d8176c9ba87051595c402889eb32172d216ce40eb2bef41289c646f01002fb4ba8e diff --git a/deps/checksums/fftw-3.3.6-pl1.tar.gz/md5 b/deps/checksums/fftw-3.3.6-pl1.tar.gz/md5 new file mode 100644 index 0000000000000..d0f6e35fbb74f --- /dev/null +++ b/deps/checksums/fftw-3.3.6-pl1.tar.gz/md5 @@ -0,0 +1 @@ +682a0e78d6966ca37c7446d4ab4cc2a1 diff --git a/deps/checksums/fftw-3.3.6-pl1.tar.gz/sha512 b/deps/checksums/fftw-3.3.6-pl1.tar.gz/sha512 new file mode 100644 index 0000000000000..ed286e18ccd6f --- /dev/null +++ b/deps/checksums/fftw-3.3.6-pl1.tar.gz/sha512 @@ -0,0 +1 @@ +e2ed33fcb068a36a841bbd898d12ceec74f4e9a0a349e7c55959878b50224a69a0f87656347dad7d7e1448ebc50d28d8f34f6da7992c43072d26942fd97c0134 diff --git a/deps/fftw.mk b/deps/fftw.mk index 7a717d19b2045..c9fc7ae035735 100644 --- a/deps/fftw.mk +++ b/deps/fftw.mk @@ -33,11 +33,7 @@ $(SRCDIR)/srccache/fftw-$(FFTW_VER)/source-extracted: $(SRCDIR)/srccache/fftw-$( touch -c $(SRCDIR)/srccache/fftw-$(FFTW_VER)/configure # old target echo 1 > $@ -$(SRCDIR)/srccache/fftw-$(FFTW_VER)/fftw-win32-intrin-h.patch-applied: $(SRCDIR)/srccache/fftw-$(FFTW_VER)/source-extracted - cd $(SRCDIR)/srccache/fftw-$(FFTW_VER) && patch -p1 -f < $(SRCDIR)/patches/fftw-win32-intrin-h.patch - echo 1 > $@ - -$(BUILDDIR)/fftw-$(FFTW_VER)-%/build-configured: $(SRCDIR)/srccache/fftw-$(FFTW_VER)/source-extracted $(SRCDIR)/srccache/fftw-$(FFTW_VER)/fftw-win32-intrin-h.patch-applied +$(BUILDDIR)/fftw-$(FFTW_VER)-%/build-configured: $(SRCDIR)/srccache/fftw-$(FFTW_VER)/source-extracted mkdir -p $(dir $@) @# try to configure with avx support. if that fails, try again without it cd $(dir $@) && \ diff --git a/deps/patches/fftw-win32-intrin-h.patch b/deps/patches/fftw-win32-intrin-h.patch deleted file mode 100644 index 5ca07881dc2d3..0000000000000 --- a/deps/patches/fftw-win32-intrin-h.patch +++ /dev/null @@ -1,42 +0,0 @@ -From cca0c6e5a8c717df10f380411709f3360ceea6e9 Mon Sep 17 00:00:00 2001 -From: Tony Kelman -Date: Fri, 9 Sep 2016 03:24:30 -0700 -Subject: [PATCH] #include in threads.c for windows build - -otherwise an i686-w64-mingw32 cross compile is giving -``` -libtool: link: i686-w64-mingw32-gcc -march=pentium4 -m32 -std=gnu99 -shared -Wl,--whole-archive kernel/.libs/libkernel.a dft/.libs/libdft.a dft/scalar/.libs/libdft_scalar.a dft/scalar/codelets/.libs/libdft_scalar_codelets.a rdft/.libs/librdft.a rdft/scalar/.libs/librdft_scalar.a rdft/scalar/r2cf/.libs/librdft_scalar_r2cf.a rdft/scalar/r2cb/.libs/librdft_scalar_r2cb.a rdft/scalar/r2r/.libs/librdft_scalar_r2r.a reodft/.libs/libreodft.a api/.libs/libapi.a simd-support/.libs/libsimd_support.a simd-support/.libs/libsimd_sse2_nonportable.a dft/simd/avx/.libs/libdft_avx_codelets.a rdft/simd/avx/.libs/librdft_avx_codelets.a threads/.libs/libfftw3f_threads.a -Wl,--no-whole-archive -march=pentium4 -m32 -O3 -mtune=native -malign-double -Wl,--stack -Wl,8388608 -o .libs/libfftw3f-3.dll -Wl,--enable-auto-image-base -Xlinker --out-implib -Xlinker .libs/libfftw3f.dll.a -libtool: link: i686-w64-mingw32-gcc -march=pentium4 -m32 -std=gnu99 -shared -Wl,--whole-archive kernel/.libs/libkernel.a dft/.libs/libdft.a dft/scalar/.libs/libdft_scalar.a dft/scalar/codelets/.libs/libdft_scalar_codelets.a rdft/.libs/librdft.a rdft/scalar/.libs/librdft_scalar.a rdft/scalar/r2cf/.libs/librdft_scalar_r2cf.a rdft/scalar/r2cb/.libs/librdft_scalar_r2cb.a rdft/scalar/r2r/.libs/librdft_scalar_r2r.a reodft/.libs/libreodft.a api/.libs/libapi.a simd-support/.libs/libsimd_support.a simd-support/.libs/libsimd_sse2_nonportable.a dft/simd/avx/.libs/libdft_avx_codelets.a rdft/simd/avx/.libs/librdft_avx_codelets.a threads/.libs/libfftw3_threads.a -Wl,--no-whole-archive -march=pentium4 -m32 -O3 -mtune=native -malign-double -Wl,--stack -Wl,8388608 -o .libs/libfftw3-3.dll -Wl,--enable-auto-image-base -Xlinker --out-implib -Xlinker .libs/libfftw3.dll.a -threads/.libs/libfftw3_threads.a(libfftw3_threads_la-threads.o):threads.c:(.text+0x121): undefined reference to `_mm_pause' -threads/.libs/libfftw3_threads.a(libfftw3_threads_la-threads.o):threads.c:(.text+0x581): undefined reference to `_mm_pause' -collect2: error: ld returned 1 exit status -threads/.libs/libfftw3f_threads.a(libfftw3f_threads_la-threads.o):threads.c:(.text+0x121): undefined reference to `_mm_pause' -threads/.libs/libfftw3f_threads.a(libfftw3f_threads_la-threads.o):threads.c:(.text+0x581): undefined reference to `_mm_pause' -collect2: error: ld returned 1 exit status -make[4]: *** [Makefile:627: libfftw3f.la] Error 1 -make[4]: *** [Makefile:627: libfftw3.la] Error 1 -make[3]: *** [Makefile:672: all-recursive] Error 1 -make[2]: *** [Makefile:536: all] Error 2 -make[3]: *** [Makefile:672: all-recursive] Error 1 -make[1]: *** [/home/Tony/julia32/deps/fftw.mk:46: scratch/fftw-3.3.5-single/build-compiled] Error 2 -make[1]: *** Waiting for unfinished jobs.... -make[2]: *** [Makefile:536: all] Error 2 -make[1]: *** [/home/Tony/julia32/deps/fftw.mk:46: scratch/fftw-3.3.5-double/build-compiled] Error 2 -make: *** [Makefile:81: julia-deps] Error 2 -``` ---- - threads/threads.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/threads/threads.c b/threads/threads.c -index fd55ced..43fc3e1 100644 ---- a/threads/threads.c -+++ b/threads/threads.c -@@ -163,6 +163,7 @@ static void os_static_mutex_unlock(os_static_mutex_t *s) { pthread_mutex_unlock( - #define INT magnus_ab_INTegro_seclorum_nascitur_ordo - #include - #include -+#include - #undef INT - - typedef HANDLE os_mutex_t; From 7d18704e3b6454ec0caade324af73e9b870e0ec4 Mon Sep 17 00:00:00 2001 From: Jon Malmaud Date: Sun, 26 Feb 2017 18:01:56 -0800 Subject: [PATCH 0128/1534] Loosen signature on println_with_color --- base/util.jl | 12 ++++++------ test/misc.jl | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/base/util.jl b/base/util.jl index 2e467e2a2de4f..9a50ddf25db31 100644 --- a/base/util.jl +++ b/base/util.jl @@ -406,21 +406,21 @@ function with_output_color(f::Function, color::Union{Int, Symbol}, io::IO, args. end """ - print_with_color(color::Union{Symbol, Int}, [io], strings...; bold::Bool = false) + print_with_color(color::Union{Symbol, Int}, [io], xs...; bold::Bool = false) -Print strings in a color specified as a symbol. +Print `xs` in a color specified as a symbol. `color` may take any of the values $(Base.available_text_colors_docstring) or an integer between 0 and 255 inclusive. Note that not all terminals support 256 colors. If the keyword `bold` is given as `true`, the result will be printed in bold. """ -print_with_color(color::Union{Int, Symbol}, io::IO, msg::AbstractString...; bold::Bool = false) = +print_with_color(color::Union{Int, Symbol}, io::IO, msg...; bold::Bool = false) = with_output_color(print, color, io, msg...; bold = bold) -print_with_color(color::Union{Int, Symbol}, msg::AbstractString...; bold::Bool = false) = +print_with_color(color::Union{Int, Symbol}, msg...; bold::Bool = false) = print_with_color(color, STDOUT, msg...; bold = bold) -println_with_color(color::Union{Int, Symbol}, io::IO, msg::AbstractString...; bold::Bool = false) = +println_with_color(color::Union{Int, Symbol}, io::IO, msg...; bold::Bool = false) = with_output_color(println, color, io, msg...; bold = bold) -println_with_color(color::Union{Int, Symbol}, msg::AbstractString...; bold::Bool = false) = +println_with_color(color::Union{Int, Symbol}, msg...; bold::Bool = false) = println_with_color(color, STDOUT, msg...; bold = bold) ## warnings and messages ## diff --git a/test/misc.jl b/test/misc.jl index 858080bf7a4c1..27db61156ea91 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -572,6 +572,25 @@ let end end +# Test that `print_with_color` accepts non-string values, just as `print` does +let + old_have_color = Base.have_color + try + @eval Base have_color = true + buf_color = IOBuffer() + args = (3.2, "foo", :testsym) + print_with_color(:red, buf_color, args...) + buf_plain = IOBuffer() + print(buf_plain, args...) + expected_str = string(Base.text_colors[:red], + String(take!(buf_plain)), + Base.text_colors[:default]) + @test expected_str == String(take!(buf_color)) + finally + @eval Base have_color = $(old_have_color) + end +end + let global c_18711 = 0 buf = IOContext(IOBuffer(), :hascontext => true) From 805f096c42cf55178a16cbd7b33d5379c6c7306d Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 5 Mar 2017 20:46:12 -0800 Subject: [PATCH 0129/1534] Fixes and stronger tests for Bidiagonal setindex! and friends. (#20891) Makes Bidiagonal setindex! support assigning zero off the main diagonal and sub/super diagonal as appropriate (like Diagonal). Strengthens tests for Bidiagonal size, setindex!, and getindex. --- base/linalg/bidiag.jl | 15 ++++++++----- test/linalg/bidiag.jl | 51 +++++++++++++++++++++++++++++++------------ 2 files changed, 47 insertions(+), 19 deletions(-) diff --git a/base/linalg/bidiag.jl b/base/linalg/bidiag.jl index fc3b0910f8fb5..ae566dda9a5c1 100644 --- a/base/linalg/bidiag.jl +++ b/base/linalg/bidiag.jl @@ -158,13 +158,18 @@ function getindex{T}(A::Bidiagonal{T}, i::Integer, j::Integer) end function setindex!(A::Bidiagonal, x, i::Integer, j::Integer) + @boundscheck checkbounds(A, i, j) if i == j - A.dv[i] = x - elseif (istriu(A) && (i == j - 1)) || (istril(A) && (i == j + 1)) - return A.ev[min(i,j)] = x - else - throw(ArgumentError("cannot set elements outside main and $(istriu(A) ? "super": "sub") diagonals.")) + @inbounds A.dv[i] = x + elseif istriu(A) && (i == j - 1) + @inbounds A.ev[i] = x + elseif istril(A) && (i == j + 1) + @inbounds A.ev[j] = x + elseif !iszero(x) + throw(ArgumentError(string("cannot set entry ($i, $j) off the ", + "$(istriu(A) ? "upper" : "lower") bidiagonal band to a nonzero value ($x)"))) end + return x end ## structured matrix methods ## diff --git a/test/linalg/bidiag.jl b/test/linalg/bidiag.jl index 5d350dacb1e7f..73f972b998f4a 100644 --- a/test/linalg/bidiag.jl +++ b/test/linalg/bidiag.jl @@ -30,23 +30,46 @@ srand(1) @test_throws ArgumentError Bidiagonal(dv,ev) end - BD = Bidiagonal(dv, ev, true) @testset "getindex, setindex!, size, and similar" begin - @test_throws BoundsError BD[n+1,1] - @test BD[2,2] == dv[2] - @test BD[2,3] == ev[2] - @test_throws ArgumentError BD[2,1] = 1 - @test_throws ArgumentError BD[3,1] = 1 - cBD = copy(BD) - cBD[2,2] = BD[2,2] - @test BD == cBD - @test_throws ArgumentError size(BD,0) - @test size(BD,3) == 1 - @test isa(similar(BD), Bidiagonal{elty}) - @test isa(similar(BD, Int), Bidiagonal{Int}) - @test isa(similar(BD, Int, (3,2)), Matrix{Int}) + ubd = Bidiagonal(dv, ev, true) + lbd = Bidiagonal(dv, ev, false) + # bidiagonal getindex / upper & lower + @test_throws BoundsError ubd[n + 1, 1] + @test_throws BoundsError ubd[1, n + 1] + @test ubd[2, 2] == dv[2] + # bidiagonal getindex / upper + @test ubd[2, 3] == ev[2] + @test iszero(ubd[3, 2]) + # bidiagonal getindex / lower + @test lbd[3, 2] == ev[2] + @test iszero(lbd[2, 3]) + # bidiagonal setindex! / upper + cubd = copy(ubd) + @test_throws ArgumentError ubd[2, 1] = 1 + @test_throws ArgumentError ubd[3, 1] = 1 + @test (cubd[2, 1] = 0; cubd == ubd) + @test ((cubd[1, 2] = 10) == 10; cubd[1, 2] == 10) + # bidiagonal setindex! / lower + clbd = copy(lbd) + @test_throws ArgumentError lbd[1, 2] = 1 + @test_throws ArgumentError lbd[1, 3] = 1 + @test (clbd[1, 2] = 0; clbd == lbd) + @test ((clbd[2, 1] = 10) == 10; clbd[2, 1] == 10) + # bidiagonal setindex! / upper & lower + @test_throws BoundsError ubd[n + 1, 1] = 1 + @test_throws BoundsError ubd[1, n + 1] = 1 + @test ((cubd[2, 2] = 10) == 10; cubd[2, 2] == 10) + # bidiagonal size + @test_throws ArgumentError size(ubd, 0) + @test size(ubd, 1) == size(ubd, 2) == n + @test size(ubd, 3) == 1 + # bidiagonal similar + @test isa(similar(ubd), Bidiagonal{elty}) + @test isa(similar(ubd, Int), Bidiagonal{Int}) + @test isa(similar(ubd, Int, (3, 2)), Matrix{Int}) end + BD = Bidiagonal(dv, ev, true) @testset "show" begin dstring = sprint(Base.print_matrix,BD.dv') estring = sprint(Base.print_matrix,BD.ev') From 418e1673b210844a07fb15b8d50badee45d845a4 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 5 Mar 2017 22:44:14 -0800 Subject: [PATCH 0130/1534] Fix broadcast! for structured matrix destinations. (#20886) --- base/sparse/higherorderfns.jl | 1 + test/sparse/higherorderfns.jl | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/base/sparse/higherorderfns.jl b/base/sparse/higherorderfns.jl index e4fa8b7613ea6..1c73c3c957e77 100644 --- a/base/sparse/higherorderfns.jl +++ b/base/sparse/higherorderfns.jl @@ -1009,6 +1009,7 @@ struct PromoteToSparse end # broadcast containertype definitions for structured matrices StructuredMatrix = Union{Diagonal,Bidiagonal,Tridiagonal,SymTridiagonal} _containertype(::Type{<:StructuredMatrix}) = PromoteToSparse +broadcast_indices(::Type{PromoteToSparse}, A) = indices(A) # combinations explicitly involving Tuples and PromoteToSparse collections # divert to the generic AbstractArray broadcast code diff --git a/test/sparse/higherorderfns.jl b/test/sparse/higherorderfns.jl index 591b86ad4bdc3..3e77a1c81372d 100644 --- a/test/sparse/higherorderfns.jl +++ b/test/sparse/higherorderfns.jl @@ -415,6 +415,33 @@ end end end +@testset "broadcast! where the destination is a structured matrix" begin + # Where broadcast!'s destination is a structured matrix, broadcast! should fall back + # to the generic AbstractArray broadcast! code (at least for now). + N, p = 5, 0.4 + A = sprand(N, N, p) + sA = A + transpose(A) + D = Diagonal(rand(N)) + B = Bidiagonal(rand(N), rand(N - 1), true) + T = Tridiagonal(rand(N - 1), rand(N), rand(N - 1)) + S = SymTridiagonal(rand(N), rand(N - 1)) + # why some of the tests below are broken: + # Diagonal setindex! allows setting off-diagonal entries to zero. Subtypes of + # AbstractTriangular allow analogs. But Bidiagonal, Tridiagonal, and SymTridiagonal + # do not, which seems like a bug. setindex! behavior like that for Diagonal and + # subtypes of AbstractTriangular is necessary for Bidiagonal, Tridiagonal, and + # SymTridiagonal to be targets of the AbstractArray broadcast! methods, hence + # the test failures below. + @test broadcast!(sin, copy(D), D) == Diagonal(sin.(D)) + @test_broken broadcast!(sin, copy(B), B) == Bidiagonal(sin.(B), true) + @test_broken broadcast!(sin, copy(T), T) == Tridiagonal(sin.(T)) + @test_broken broadcast!(sin, copy(S), S) == SymTridiagonal(sin.(S)) + @test broadcast!(*, copy(D), D, A) == Diagonal(broadcast(*, D, A)) + @test_broken broadcast!(*, copy(B), B, A) == Bidiagonal(broadcast(*, B, A), true) + @test_broken broadcast!(*, copy(T), T, A) == Tridiagonal(broadcast(*, T, A)) + @test_broken broadcast!(*, copy(S), T, sA) == SymTridiagonal(broadcast(*, T, sA)) +end + @testset "map[!] over combinations of sparse and structured matrices" begin N, p = 10, 0.4 A = sprand(N, N, p) From 73e20a36c421788113ed6a31fb4e28e78137927c Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 5 Mar 2017 23:55:35 -0800 Subject: [PATCH 0131/1534] Fixes and stronger tests for Tridiagonal setindex! (#20892) Makes Tridiagonal setindex! support assigning zero off the main, sub, and super diagonals. Strengthens tests for Tridiagonal setindex!. --- base/linalg/tridiag.jl | 13 ++++++++----- test/linalg/tridiag.jl | 13 +++++++------ 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/base/linalg/tridiag.jl b/base/linalg/tridiag.jl index 279e2aca796ad..805f5516f1354 100644 --- a/base/linalg/tridiag.jl +++ b/base/linalg/tridiag.jl @@ -559,15 +559,18 @@ function getindex{T}(A::Tridiagonal{T}, i::Integer, j::Integer) end function setindex!(A::Tridiagonal, x, i::Integer, j::Integer) + @boundscheck checkbounds(A, i, j) if i == j - A.d[i] = x + @inbounds A.d[i] = x elseif i - j == 1 - A.dl[j] = x + @inbounds A.dl[j] = x elseif j - i == 1 - A.du[i] = x - else - throw(ArgumentError("cannot set elements outside the sub, main, or super diagonals")) + @inbounds A.du[i] = x + elseif !iszero(x) + throw(ArgumentError(string("cannot set entry ($i, $j) off ", + "the tridiagonal band to a nonzero value ($x)"))) end + return x end ## structured matrix methods ## diff --git a/test/linalg/tridiag.jl b/test/linalg/tridiag.jl index d6f12d402915d..98371fff8a3b0 100644 --- a/test/linalg/tridiag.jl +++ b/test/linalg/tridiag.jl @@ -459,12 +459,13 @@ let n = 12 #Size of matrix problem to test @test_throws BoundsError A[1,n+1] debug && println("setindex!") - @test_throws ArgumentError A[n,1] = 1 - @test_throws ArgumentError A[1,n] = 1 - A[3,3] = A[3,3] - A[2,3] = A[2,3] - A[3,2] = A[3,2] - @test A == fA + @test_throws BoundsError A[n + 1, 1] = 0 # test bounds check + @test_throws BoundsError A[1, n + 1] = 0 # test bounds check + @test (A[3, 3] = A[3, 3]; A == fA) # test assignment on the main diagonal + @test (A[3, 2] = A[3, 2]; A == fA) # test assignment on the subdiagonal + @test (A[2, 3] = A[2, 3]; A == fA) # test assignment on the superdiagonal + @test ((A[1, 3] = 0) == 0; A == fA) # test zero assignment off the main/sub/super diagonal + @test_throws ArgumentError A[1, 3] = 1 # test non-zero assignment off the main/sub/super diagonal end end From 0827820b3d6d1e6db0a0d4431f2faacf57cdb1fe Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Mon, 6 Mar 2017 06:49:34 -0800 Subject: [PATCH 0132/1534] Fix broken tests causing failures in test/sparse/higherorderfns (#20906) multiple related PR's were merged which changed the behavior here, without re-running CI --- test/sparse/higherorderfns.jl | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/test/sparse/higherorderfns.jl b/test/sparse/higherorderfns.jl index 3e77a1c81372d..79a382699ffe1 100644 --- a/test/sparse/higherorderfns.jl +++ b/test/sparse/higherorderfns.jl @@ -427,18 +427,14 @@ end S = SymTridiagonal(rand(N), rand(N - 1)) # why some of the tests below are broken: # Diagonal setindex! allows setting off-diagonal entries to zero. Subtypes of - # AbstractTriangular allow analogs. But Bidiagonal, Tridiagonal, and SymTridiagonal - # do not, which seems like a bug. setindex! behavior like that for Diagonal and - # subtypes of AbstractTriangular is necessary for Bidiagonal, Tridiagonal, and - # SymTridiagonal to be targets of the AbstractArray broadcast! methods, hence - # the test failures below. + # AbstractTriangular allow analogs. @test broadcast!(sin, copy(D), D) == Diagonal(sin.(D)) - @test_broken broadcast!(sin, copy(B), B) == Bidiagonal(sin.(B), true) - @test_broken broadcast!(sin, copy(T), T) == Tridiagonal(sin.(T)) + @test broadcast!(sin, copy(B), B) == Bidiagonal(sin.(B), true) + @test broadcast!(sin, copy(T), T) == Tridiagonal(sin.(T)) @test_broken broadcast!(sin, copy(S), S) == SymTridiagonal(sin.(S)) @test broadcast!(*, copy(D), D, A) == Diagonal(broadcast(*, D, A)) - @test_broken broadcast!(*, copy(B), B, A) == Bidiagonal(broadcast(*, B, A), true) - @test_broken broadcast!(*, copy(T), T, A) == Tridiagonal(broadcast(*, T, A)) + @test broadcast!(*, copy(B), B, A) == Bidiagonal(broadcast(*, B, A), true) + @test broadcast!(*, copy(T), T, A) == Tridiagonal(broadcast(*, T, A)) @test_broken broadcast!(*, copy(S), T, sA) == SymTridiagonal(broadcast(*, T, sA)) end From 8fb132f41566915c9175b3dce0f818e5f02cdbf3 Mon Sep 17 00:00:00 2001 From: Stefan Karpinski Date: Mon, 6 Mar 2017 10:45:14 -0500 Subject: [PATCH 0133/1534] work-around joinpath error when cloning git ssh urls (fix #20695) --- base/pkg/entry.jl | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/base/pkg/entry.jl b/base/pkg/entry.jl index 0d53268f96d5a..84f128d268578 100644 --- a/base/pkg/entry.jl +++ b/base/pkg/entry.jl @@ -207,18 +207,20 @@ function clone(url::AbstractString, pkg::AbstractString) end function clone(url_or_pkg::AbstractString) - urlpath = joinpath("METADATA",url_or_pkg,"url") - if !(':' in url_or_pkg) && isfile(urlpath) - pkg = url_or_pkg - url = readchomp(urlpath) - # TODO: Cache.prefetch(pkg,url) - else - url = url_or_pkg - m = match(r"(?:^|[/\\])(\w+?)(?:\.jl)?(?:\.git)?$", url) - m !== nothing || throw(PkgError("can't determine package name from URL: $url")) - pkg = m.captures[1] + if !(':' in url_or_pkg) + urlpath = joinpath("METADATA",url_or_pkg,"url") + if isfile(urlpath) + pkg = url_or_pkg + url = readchomp(urlpath) + # TODO: Cache.prefetch(pkg,url) + return clone(url,pkg) + end end - clone(url,pkg) + url = url_or_pkg + m = match(r"(?:^|[/\\])(\w+?)(?:\.jl)?(?:\.git)?$", url) + m !== nothing || throw(PkgError("can't determine package name from URL: $url")) + pkg = m.captures[1] + return clone(url,pkg) end function checkout(pkg::AbstractString, branch::AbstractString, do_merge::Bool, do_pull::Bool) From 2f800a5ba17fc5fe53614239b575a3af98205007 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 28 Feb 2017 16:23:58 -0500 Subject: [PATCH 0134/1534] improve `effect_free` to fix regressions from #20726 --- base/coreimg.jl | 2 ++ base/inference.jl | 18 ++++++++++++++++-- base/promotion.jl | 2 +- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/base/coreimg.jl b/base/coreimg.jl index 0d2ee886141c3..00b225780ebaa 100644 --- a/base/coreimg.jl +++ b/base/coreimg.jl @@ -13,6 +13,8 @@ const include = Core.include # conditional to allow redefining Core.Inference after base exists isdefined(Main, :Base) || ((::Type{T}){T}(arg) = convert(T, arg)::T) +function return_type end + ## Load essential files and libraries include("essentials.jl") include("ctypes.jl") diff --git a/base/inference.jl b/base/inference.jl index e6a4b0ffdd8f9..ca2ca0b8c5251 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -3363,6 +3363,9 @@ function is_pure_builtin(f::ANY) return true end end + if f === return_type + return true + end return false end @@ -3394,24 +3397,35 @@ function effect_free(e::ANY, src::CodeInfo, mod::Module, allow_volatile::Bool) return true end ea = e.args - if head === :call && !isa(e.args[1], SSAValue) && !isa(e.args[1], Slot) + if head === :call if is_known_call_p(e, is_pure_builtin, src, mod) if !allow_volatile if is_known_call(e, arrayref, src, mod) || is_known_call(e, arraylen, src, mod) return false elseif is_known_call(e, getfield, src, mod) + length(ea) == 3 || return false et = exprtype(e, src, mod) if !isa(et,Const) && !(isType(et) && isleaftype(et)) # first argument must be immutable to ensure e is affect_free a = ea[2] typ = widenconst(exprtype(a, src, mod)) - if !isa(typ, DataType) || typ.mutable || typ.abstract + if isconstType(typ) + if Const(:uid) ⊑ exprtype(ea[3], src, mod) + return false # DataType uid field can change + end + elseif !isa(typ, DataType) || typ.mutable || typ.abstract return false end end end end # fall-through + elseif is_known_call(e, _apply, src, mod) && length(ea) > 1 + ft = exprtype(ea[2], src, mod) + if !isa(ft, Const) || !contains_is(_pure_builtins, ft.val) + return false + end + # fall-through else return false end diff --git a/base/promotion.jl b/base/promotion.jl index ef5d989e322d5..ed3c6389b2a5b 100644 --- a/base/promotion.jl +++ b/base/promotion.jl @@ -305,7 +305,7 @@ minmax(x::Real, y::Real) = minmax(promote(x, y)...) _default_type(T::Type) = (@_pure_meta; T) if isdefined(Core, :Inference) - _return_type(f::ANY, t::ANY) = Core.Inference.return_type(f, t) + const _return_type = Core.Inference.return_type else _return_type(f::ANY, t::ANY) = Any end From df62c9922c320bff0f6d32bdf3faf87337925e2f Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Mon, 6 Mar 2017 18:01:04 +0000 Subject: [PATCH 0135/1534] Fix missing GC root Type intersection can return a new type and jl_subtype can allocate, so this value needs to be rooted. --- src/gf.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/gf.c b/src/gf.c index 636c1f0fb0da7..fbda17c9d2c58 100644 --- a/src/gf.c +++ b/src/gf.c @@ -766,11 +766,17 @@ JL_DLLEXPORT int jl_is_cacheable_sig( if (jl_is_vararg_type(declt)) declt = jl_unwrap_vararg(declt); jl_value_t *di = jl_type_intersection(declt, (jl_value_t*)jl_typetype_type); + JL_GC_PUSH1(&di); assert(di != (jl_value_t*)jl_bottom_type); - if (jl_is_kind(di)) + if (jl_is_kind(di)) { + JL_GC_POP(); return 0; - else if (!jl_subtype(di, elt) || !jl_subtype(elt, di)) + } + else if (!jl_subtype(di, elt) || !jl_subtype(elt, di)) { + JL_GC_POP(); return 0; + } + JL_GC_POP(); } else { return 0; From c9f28da19bfe061280fa91120c08ee851e1ff31e Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 6 Mar 2017 12:11:19 -0500 Subject: [PATCH 0136/1534] avoid CHA escape sequence \r should be more generally available, and should work as long as the stream is not actively ignoring CR characters fix #20557 --- base/Terminals.jl | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/base/Terminals.jl b/base/Terminals.jl index dfdc909f902fa..11b75bf89aa3f 100644 --- a/base/Terminals.jl +++ b/base/Terminals.jl @@ -113,7 +113,7 @@ cmove_right(t::UnixTerminal, n) = write(t.out_stream, "$(CSI)$(n)C") cmove_left(t::UnixTerminal, n) = write(t.out_stream, "$(CSI)$(n)D") cmove_line_up(t::UnixTerminal, n) = (cmove_up(t, n); cmove_col(t, 1)) cmove_line_down(t::UnixTerminal, n) = (cmove_down(t, n); cmove_col(t, 1)) -cmove_col(t::UnixTerminal, n) = write(t.out_stream, "$(CSI)$(n)G") +cmove_col(t::UnixTerminal, n) = (write(t.out_stream, '\r'); n > 1 && cmove_right(t, n - 1)) if is_windows() function raw!(t::TTYTerminal,raw::Bool) @@ -137,19 +137,21 @@ else ccall(:jl_tty_set_mode, Int32, (Ptr{Void},Int32), t.in_stream.handle, raw) != -1 end end -enable_bracketed_paste(t::UnixTerminal) = write(t.out_stream, "$(CSI)?2004h") -disable_bracketed_paste(t::UnixTerminal) = write(t.out_stream, "$(CSI)?2004l") -end_keypad_transmit_mode(t::UnixTerminal) = # tput rmkx - write(t.out_stream, "$(CSI)?1l\x1b>") + +# eval some of these definitions to insert CSI as a constant string +@eval enable_bracketed_paste(t::UnixTerminal) = write(t.out_stream, $"$(CSI)?2004h") +@eval disable_bracketed_paste(t::UnixTerminal) = write(t.out_stream, $"$(CSI)?2004l") +@eval end_keypad_transmit_mode(t::UnixTerminal) = # tput rmkx + write(t.out_stream, $"$(CSI)?1l\x1b>") + +@eval clear(t::UnixTerminal) = write(t.out_stream, $"$(CSI)H$(CSI)2J") +@eval clear_line(t::UnixTerminal) = write(t.out_stream, $"\r$(CSI)0K") +#beep(t::UnixTerminal) = write(t.err_stream,"\x7") function Base.displaysize(t::UnixTerminal) return displaysize(t.out_stream) end -clear(t::UnixTerminal) = write(t.out_stream, "\x1b[H\x1b[2J") -clear_line(t::UnixTerminal) = write(t.out_stream, "\x1b[1G\x1b[0K") -#beep(t::UnixTerminal) = write(t.err_stream,"\x7") - if is_windows() hascolor(t::TTYTerminal) = true else From 19fd1e66c174a44566713d5cedb85f684d5c4c68 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 6 Mar 2017 12:31:20 -0500 Subject: [PATCH 0137/1534] REPL: prevent errors in running client code from terminating process ensures that the standard on_done respond handlers will fail gracefully fix #20771 --- base/REPL.jl | 15 +++++++++++---- test/repl.jl | 20 ++++++++++++++++++-- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/base/REPL.jl b/base/REPL.jl index c65876b3c984d..4b52dc7b55222 100644 --- a/base/REPL.jl +++ b/base/REPL.jl @@ -65,7 +65,7 @@ function eval_user_input(ast::ANY, backend::REPLBackend) backend.in_eval = true value = eval(Main, ast) backend.in_eval = false - # note: value wrapped in a closure to ensure it doesn't get passed through expand + # note: value wrapped carefully here to ensure it doesn't get passed through expand eval(Main, Expr(:body, Expr(:(=), :ans, QuoteNode(value)), Expr(:return, nothing))) put!(backend.response_channel, (value, nothing)) end @@ -622,18 +622,25 @@ backend(r::AbstractREPL) = r.backendref send_to_backend(ast, backend::REPLBackendRef) = send_to_backend(ast, backend.repl_channel, backend.response_channel) function send_to_backend(ast, req, rep) put!(req, (ast, 1)) - val, bt = take!(rep) + return take!(rep) # (val, bt) end function respond(f, repl, main; pass_empty = false) - (s,buf,ok)->begin + return function do_respond(s, buf, ok) if !ok return transition(s, :abort) end line = String(take!(buf)) if !isempty(line) || pass_empty reset(repl) - val, bt = send_to_backend(eval(:(($f)($line))), backend(repl)) + try + # note: value wrapped carefully here to ensure it doesn't get passed through expand + response = eval(Main, Expr(:body, Expr(:return, Expr(:call, QuoteNode(f), QuoteNode(line))))) + val, bt = send_to_backend(response, backend(repl)) + catch err + val = err + bt = catch_backtrace() + end if !ends_with_semicolon(line) || bt !== nothing print_response(repl, val, bt, true, Base.have_color) end diff --git a/test/repl.jl b/test/repl.jl index ec48afc3e3e4f..b9529caa38a38 100644 --- a/test/repl.jl +++ b/test/repl.jl @@ -105,8 +105,24 @@ if !is_windows() || Sys.windows_version() >= Sys.WINDOWS_VISTA_VER write(stdin_write, ";") readuntil(stdout_read, "shell> ") write(stdin_write, "echo hello >/dev/null\n") - readuntil(stdout_read, "\n") - readuntil(stdout_read, "\n") + let s = readuntil(stdout_read, "\n") + @test contains(s, "shell> ") # make sure we echoed the prompt + @test contains(s, "echo hello >/dev/null") # make sure we echoed the input + end + @test readuntil(stdout_read, "\n") == "\e[0m\n" + end + + # issue #20771 + let s + write(stdin_write, ";") + readuntil(stdout_read, "shell> ") + write(stdin_write, "'\n") # invalid input + s = readuntil(stdout_read, "\n") + @test contains(s, "shell> ") # check for the echo of the prompt + @test contains(s, "'") # check for the echo of the input + s = readuntil(stdout_read, "\n\n") + @test startswith(s, "\e[0mERROR: unterminated single quote\nStacktrace:\n [1] ") || + startswith(s, "\e[0m\e[1m\e[91mERROR: \e[39m\e[22m\e[91munterminated single quote\e[39m\nStacktrace:\n [1] ") end # Test that accepting a REPL result immediately shows up, not From 49976950f23d045a845d718d313424a2c214af24 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 6 Mar 2017 13:25:58 -0500 Subject: [PATCH 0138/1534] make ends_with_semicolon more capable it can still be confused, but hopefully less commonly it is also no longer correct for shell_mode now fix #19296 --- base/REPL.jl | 44 ++++++++++++++++++++++++++++++++++++++++++-- test/repl.jl | 15 +++++++++++++++ 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/base/REPL.jl b/base/REPL.jl index 4b52dc7b55222..c5fc6d306f4ba 100644 --- a/base/REPL.jl +++ b/base/REPL.jl @@ -970,11 +970,51 @@ answer_color(r::StreamREPL) = r.answer_color input_color(r::LineEditREPL) = r.envcolors ? Base.input_color() : r.input_color input_color(r::StreamREPL) = r.input_color +# heuristic function to decide if the presence of a semicolon +# at the end of the expression was intended for suppressing output function ends_with_semicolon(line) match = rsearch(line, ';') if match != 0 - for c in line[(match+1):end] - isspace(c) || return c == '#' + # state for comment parser, assuming that the `;` isn't in a string or comment + # so input like ";#" will still thwart this to give the wrong (anti-conservative) answer + comment = false + comment_start = false + comment_close = false + comment_multi = 0 + for c in line[(match + 1):end] + if comment_multi > 0 + # handle nested multi-line comments + if comment_close && c == '#' + comment_close = false + comment_multi -= 1 + elseif comment_start && c == '=' + comment_start = false + comment_multi += 1 + else + comment_start = (c == '#') + comment_close = (c == '=') + end + elseif comment + # handle line comments + if c == '\r' || c == '\n' + comment = false + end + elseif comment_start + # see what kind of comment this is + comment_start = false + if c == '=' + comment_multi = 1 + else + comment = true + end + elseif c == '#' + # start handling for a comment + comment_start = true + else + # outside of a comment, encountering anything but whitespace + # means the semi-colon was internal to the expression + isspace(c) || return false + end end return true end diff --git a/test/repl.jl b/test/repl.jl index b9529caa38a38..3f8fed44846ad 100644 --- a/test/repl.jl +++ b/test/repl.jl @@ -598,3 +598,18 @@ function test_replinit() copy!(Base.repl_hooks, saved_replinit) end test_replinit() + +let ends_with_semicolon = Base.REPL.ends_with_semicolon + @test !ends_with_semicolon("") + @test ends_with_semicolon(";") + @test !ends_with_semicolon("a") + @test ends_with_semicolon("1;") + @test ends_with_semicolon("1;\n") + @test ends_with_semicolon("1;\r") + @test ends_with_semicolon("1;\r\n \t\f") + @test ends_with_semicolon("1;#text\n") + @test ends_with_semicolon("a; #=#=# =# =#\n") + @test !ends_with_semicolon("begin\na;\nb;\nend") + @test !ends_with_semicolon("begin\na; #=#=#\n=#b=#\nend") + @test ends_with_semicolon("\na; #=#=#\n=#b=#\n# test\n#=\nfoobar\n=##bazbax\n") +end From d6743f176e40e373340317b0fba4dd85c0a41549 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Sat, 4 Mar 2017 10:21:21 -0500 Subject: [PATCH 0139/1534] Slightly reduce threading overhead * Do dispatch on master thread. Avoid construction of tuple type. * Pass the closure direction instead of having to wrap it in a svec. --- base/threadingconstructs.jl | 2 +- src/gf.c | 34 +++++----- src/julia_internal.h | 130 ++++++++++++++++++++++++++++-------- src/threading.c | 58 +++++++++++----- src/threading.h | 14 ++-- 5 files changed, 170 insertions(+), 68 deletions(-) diff --git a/base/threadingconstructs.jl b/base/threadingconstructs.jl index a9a3e3940507c..678e9c3d92c3b 100644 --- a/base/threadingconstructs.jl +++ b/base/threadingconstructs.jl @@ -54,7 +54,7 @@ function _threadsfor(iter,lbody) $(esc(lbody)) end end - ccall(:jl_threading_run, Void, (Any,), Core.svec($fun)) + ccall(:jl_threading_run, Ref{Void}, (Any,), $fun) end end """ diff --git a/src/gf.c b/src/gf.c index 636c1f0fb0da7..f7554065e16da 100644 --- a/src/gf.c +++ b/src/gf.c @@ -2076,17 +2076,6 @@ static jl_value_t *verify_type(jl_value_t *v) return v; } -STATIC_INLINE uint32_t int32hash_fast(uint32_t a) -{ -// a = (a+0x7ed55d16) + (a<<12); -// a = (a^0xc761c23c) ^ (a>>19); -// a = (a+0x165667b1) + (a<<5); -// a = (a+0xd3a2646c) ^ (a<<9); -// a = (a+0xfd7046c5) + (a<<3); -// a = (a^0xb55a4f09) ^ (a>>16); - return a; // identity hashing seems to work well enough here -} - STATIC_INLINE int sig_match_fast(jl_value_t **args, jl_value_t **sig, size_t i, size_t n) { // NOTE: This function is a huge performance hot spot!! @@ -2124,11 +2113,8 @@ void call_cache_stats() { } #endif -#ifdef _COMPILER_MICROSOFT_ -#define __builtin_return_address(n) _ReturnAddress() -#endif - -JL_DLLEXPORT jl_value_t *jl_apply_generic(jl_value_t **args, uint32_t nargs) +STATIC_INLINE jl_method_instance_t *jl_lookup_generic_(jl_value_t **args, uint32_t nargs, + uint32_t callsite, size_t world) { #ifdef JL_GF_PROFILE ncalls++; @@ -2138,7 +2124,6 @@ JL_DLLEXPORT jl_value_t *jl_apply_generic(jl_value_t **args, uint32_t nargs) if (traceen) show_call(args[0], &args[1], nargs-1); #endif - size_t world = jl_get_ptls_states()->world_age; /* search order: @@ -2150,7 +2135,6 @@ JL_DLLEXPORT jl_value_t *jl_apply_generic(jl_value_t **args, uint32_t nargs) if no generic match, use the concrete one even if inexact otherwise instantiate the generic method and use it */ - uint32_t callsite = int32hash_fast((uintptr_t)__builtin_return_address(0)); // compute the entry hashes // use different parts of the value // so that a collision across all of @@ -2218,6 +2202,20 @@ JL_DLLEXPORT jl_value_t *jl_apply_generic(jl_value_t **args, uint32_t nargs) if (traceen) jl_printf(JL_STDOUT, " at %s:%d\n", jl_symbol_name(mfunc->def->file), mfunc->def->line); #endif + return mfunc; +} + +jl_method_instance_t *jl_lookup_generic(jl_value_t **args, uint32_t nargs, uint32_t callsite, + size_t world) +{ + return jl_lookup_generic_(args, nargs, callsite, world); +} + +JL_DLLEXPORT jl_value_t *jl_apply_generic(jl_value_t **args, uint32_t nargs) +{ + jl_method_instance_t *mfunc = jl_lookup_generic_(args, nargs, + jl_int32hash_fast(jl_return_address()), + jl_get_ptls_states()->world_age); jl_value_t *res = jl_call_method_internal(mfunc, args, nargs); return verify_type(res); } diff --git a/src/julia_internal.h b/src/julia_internal.h index a652ef16ef85e..ceff5aa311952 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -12,6 +12,12 @@ #define sleep(x) Sleep(1000*x) #endif +#ifdef __has_builtin +# define jl_has_builtin(x) __has_builtin(x) +#else +# define jl_has_builtin(x) 0 +#endif + #if defined(__has_feature) #if __has_feature(address_sanitizer) #define JL_ASAN_ENABLED // Clang flavor @@ -40,12 +46,63 @@ // For C++, C++11 or MSVC is required. Both provide `static_assert`. #endif +#if jl_has_builtin(__builtin_assume) +#define jl_assume(cond) (__extension__ ({ \ + __builtin_assume(!!(cond)); \ + cond; \ + })) +#elif defined(_COMPILER_GCC_) +static inline void jl_assume_(int cond) +{ + if (!cond) { + __builtin_unreachable(); + } +} +#define jl_assume(cond) (__extension__ ({ \ + __typeof__(cond) cond_ = (cond); \ + jl_assume_(!!(cond_)); \ + cond_; \ + })) +#elif defined(_COMPILER_INTEL_) +#define jl_assume(cond) (__extension__ ({ \ + __assume(!!(cond)); \ + cond; \ + })) +#elif defined(_COMPILER_MICROSOFT_) && defined(__cplusplus) +template +static inline T +jl_assume(T v) +{ + __assume(!!v); + return v; +} +#else +#define jl_assume(cond) (cond) +#endif + #ifdef __cplusplus extern "C" { #endif #include "timing.h" +#ifdef _COMPILER_MICROSOFT_ +# define jl_return_address() ((uintptr_t)_ReturnAddress()) +#else +# define jl_return_address() ((uintptr_t)__builtin_return_address(0)) +#endif + +STATIC_INLINE uint32_t jl_int32hash_fast(uint32_t a) +{ +// a = (a+0x7ed55d16) + (a<<12); +// a = (a^0xc761c23c) ^ (a>>19); +// a = (a+0x165667b1) + (a<<5); +// a = (a+0xd3a2646c) ^ (a<<9); +// a = (a+0xfd7046c5) + (a<<3); +// a = (a^0xb55a4f09) ^ (a>>16); + return a; // identity hashing seems to work well enough here +} + #define GC_CLEAN 0 // freshly allocated #define GC_MARKED 1 // reachable and young #define GC_OLD 2 // if it is reachable it will be marked as old @@ -222,52 +279,72 @@ jl_method_t *jl_new_method(jl_code_info_t *definition, jl_svec_t *tvars, int isstaged); -// invoke (compiling if necessary) the jlcall function pointer for a method -STATIC_INLINE jl_value_t *jl_call_method_internal(jl_method_instance_t *meth, jl_value_t **args, uint32_t nargs) +STATIC_INLINE jl_value_t *jl_compile_method_internal(jl_generic_fptr_t *fptr, + jl_method_instance_t *meth) { - jl_generic_fptr_t fptr; - fptr.fptr = meth->fptr; - fptr.jlcall_api = meth->jlcall_api; - if (fptr.jlcall_api == 2) - return meth->inferred; - if (__unlikely(fptr.fptr == NULL || fptr.jlcall_api == 0)) { + if (meth->jlcall_api == 2) + return jl_assume(meth->inferred); + fptr->fptr = meth->fptr; + fptr->jlcall_api = meth->jlcall_api; + if (__unlikely(fptr->fptr == NULL || fptr->jlcall_api == 0)) { size_t world = jl_get_ptls_states()->world_age; // first see if it likely needs to be compiled void *F = meth->functionObjectsDecls.functionObject; if (!F) // ask codegen to try to turn it into llvm code F = jl_compile_for_dispatch(&meth, world).functionObject; if (meth->jlcall_api == 2) - return meth->inferred; + return jl_assume(meth->inferred); // if it hasn't been inferred, try using the unspecialized meth cache instead if (!meth->inferred) { - fptr.fptr = meth->unspecialized_ducttape; - fptr.jlcall_api = 1; - if (!fptr.fptr) { + fptr->fptr = meth->unspecialized_ducttape; + fptr->jlcall_api = 1; + if (!fptr->fptr) { if (meth->def && !meth->def->isstaged && meth->def->unspecialized) { - fptr.fptr = meth->def->unspecialized->fptr; - fptr.jlcall_api = meth->def->unspecialized->jlcall_api; - if (fptr.jlcall_api == 2) - return meth->def->unspecialized->inferred; + fptr->fptr = meth->def->unspecialized->fptr; + fptr->jlcall_api = meth->def->unspecialized->jlcall_api; + if (fptr->jlcall_api == 2) { + return jl_assume(meth->def->unspecialized->inferred); + } } } } - if (!fptr.fptr || fptr.jlcall_api == 0) { + if (!fptr->fptr || fptr->jlcall_api == 0) { // ask codegen to make the fptr - fptr = jl_generate_fptr(meth, F, world); - if (fptr.jlcall_api == 2) - return meth->inferred; + *fptr = jl_generate_fptr(meth, F, world); + if (fptr->jlcall_api == 2) + return jl_assume(meth->inferred); } } - if (fptr.jlcall_api == 1) - return fptr.fptr1(args[0], &args[1], nargs-1); - else if (fptr.jlcall_api == 3) - return fptr.fptr3(meth->sparam_vals, args[0], &args[1], nargs-1); - else if (fptr.jlcall_api == 4) - return fptr.fptr4(meth, &args[0], nargs, meth->sparam_vals); + return NULL; +} + +STATIC_INLINE jl_value_t *jl_call_fptr_internal(const jl_generic_fptr_t *fptr, + jl_method_instance_t *meth, + jl_value_t **args, uint32_t nargs) +{ + if (fptr->jlcall_api == 1) + return fptr->fptr1(args[0], &args[1], nargs-1); + else if (fptr->jlcall_api == 2) + return meth->inferred; + else if (fptr->jlcall_api == 3) + return fptr->fptr3(meth->sparam_vals, args[0], &args[1], nargs-1); + else if (fptr->jlcall_api == 4) + return fptr->fptr4(meth, &args[0], nargs, meth->sparam_vals); else abort(); } +// invoke (compiling if necessary) the jlcall function pointer for a method +STATIC_INLINE jl_value_t *jl_call_method_internal(jl_method_instance_t *meth, jl_value_t **args, uint32_t nargs) +{ + jl_generic_fptr_t fptr; + jl_value_t *v = jl_compile_method_internal(&fptr, meth); + if (v) + return v; + jl_assume(fptr.jlcall_api != 2); + return jl_call_fptr_internal(&fptr, meth, args, nargs); +} + jl_tupletype_t *jl_argtype_with_function(jl_function_t *f, jl_tupletype_t *types); JL_DLLEXPORT jl_value_t *jl_apply_2va(jl_value_t *f, jl_value_t **args, uint32_t nargs); @@ -387,6 +464,7 @@ jl_method_instance_t *jl_method_lookup_by_type(jl_methtable_t *mt, jl_tupletype_ int cache, int inexact, int allow_exec, size_t world); jl_method_instance_t *jl_method_lookup(jl_methtable_t *mt, jl_value_t **args, size_t nargs, int cache, size_t world); jl_value_t *jl_gf_invoke(jl_tupletype_t *types, jl_value_t **args, size_t nargs); +jl_method_instance_t *jl_lookup_generic(jl_value_t **args, uint32_t nargs, uint32_t callsite, size_t world); JL_DLLEXPORT jl_datatype_t *jl_first_argument_datatype(jl_value_t *argtypes); jl_datatype_t *jl_argument_datatype(jl_value_t *argt); diff --git a/src/threading.c b/src/threading.c index b0182146017da..81a47b55977e6 100644 --- a/src/threading.c +++ b/src/threading.c @@ -307,11 +307,13 @@ static void ti_init_master_thread(void) } // all threads call this function to run user code -static jl_value_t *ti_run_fun(jl_svec_t *args) +static jl_value_t *ti_run_fun(const jl_generic_fptr_t *fptr, jl_method_instance_t *mfunc, + jl_value_t **args, uint32_t nargs) { jl_ptls_t ptls = jl_get_ptls_states(); JL_TRY { - jl_apply(jl_svec_data(args), jl_svec_len(args)); + jl_assume(fptr->jlcall_api != 2); + jl_call_fptr_internal(fptr, mfunc, args, nargs); } JL_CATCH { return ptls->exception_in_transit; @@ -406,7 +408,7 @@ void ti_threadfun(void *arg) JL_GC_PUSH1(&last_m); ptls->current_module = work->current_module; ptls->world_age = work->world_age; - ti_run_fun(work->args); + ti_run_fun(&work->fptr, work->mfunc, work->args, work->nargs); ptls->current_module = last_m; ptls->world_age = last_age; JL_GC_POP(); @@ -650,26 +652,34 @@ JL_DLLEXPORT void *jl_threadgroup(void) { return (void *)tgworld; } // interface to user code: specialize and compile the user thread function // and run it in all threads -JL_DLLEXPORT jl_value_t *jl_threading_run(jl_svec_t *args) +JL_DLLEXPORT jl_value_t *jl_threading_run(jl_value_t *_args) { jl_ptls_t ptls = jl_get_ptls_states(); // GC safe #if PROFILE_JL_THREADING uint64_t tstart = uv_hrtime(); #endif - - jl_tupletype_t *argtypes = NULL; - JL_TYPECHK(jl_threading_run, simplevector, (jl_value_t*)args); + uint32_t nargs; + jl_value_t **args; + if (!jl_is_svec(_args)) { + nargs = 1; + args = &_args; + } + else { + nargs = jl_svec_len(_args); + args = jl_svec_data(_args); + } int8_t gc_state = jl_gc_unsafe_enter(ptls); - JL_GC_PUSH1(&argtypes); - argtypes = arg_type_tuple(jl_svec_data(args), jl_svec_len(args)); - jl_compile_hint(argtypes); threadwork.command = TI_THREADWORK_RUN; - // TODO jb/functions: lookup and store jlcall fptr here - threadwork.fun = NULL; + threadwork.mfunc = jl_lookup_generic(args, nargs, + jl_int32hash_fast(jl_return_address()), ptls->world_age); + // Ignore constant return value for now. + if (jl_compile_method_internal(&threadwork.fptr, threadwork.mfunc)) + return jl_nothing; threadwork.args = args; + threadwork.nargs = nargs; threadwork.ret = jl_nothing; threadwork.current_module = ptls->current_module; threadwork.world_age = ptls->world_age; @@ -689,7 +699,7 @@ JL_DLLEXPORT jl_value_t *jl_threading_run(jl_svec_t *args) #endif // this thread must do work too (TODO: reduction?) - tw->ret = ti_run_fun(args); + tw->ret = ti_run_fun(&threadwork.fptr, threadwork.mfunc, args, nargs); #if PROFILE_JL_THREADING uint64_t trun = uv_hrtime(); @@ -704,7 +714,6 @@ JL_DLLEXPORT jl_value_t *jl_threading_run(jl_svec_t *args) join_ns[ptls->tid] += (tjoin - trun); #endif - JL_GC_POP(); jl_gc_unsafe_leave(ptls, gc_state); return tw->ret; @@ -766,10 +775,25 @@ JL_DLLEXPORT void jl_threading_profile(void) #else // !JULIA_ENABLE_THREADING -JL_DLLEXPORT jl_value_t *jl_threading_run(jl_svec_t *args) +JL_DLLEXPORT jl_value_t *jl_threading_run(jl_value_t *_args) { - JL_TYPECHK(jl_threading_run, simplevector, (jl_value_t*)args); - return ti_run_fun(args); + uint32_t nargs; + jl_value_t **args; + if (!jl_is_svec(_args)) { + nargs = 1; + args = &_args; + } + else { + nargs = jl_svec_len(_args); + args = jl_svec_data(_args); + } + jl_method_instance_t *mfunc = jl_lookup_generic(args, nargs, + jl_int32hash_fast(jl_return_address()), + jl_get_ptls_states()->world_age); + jl_generic_fptr_t fptr; + if (jl_compile_method_internal(&fptr, mfunc)) + return jl_nothing; + return ti_run_fun(&fptr, mfunc, args, nargs); } void jl_init_threading(void) diff --git a/src/threading.h b/src/threading.h index b21863a3e5338..803a54a006919 100644 --- a/src/threading.h +++ b/src/threading.h @@ -38,12 +38,14 @@ enum { // work command to thread function typedef struct { - uint8_t command; - jl_function_t *fun; - jl_svec_t *args; - jl_value_t *ret; - jl_module_t *current_module; - size_t world_age; + uint8_t command; + jl_method_instance_t *mfunc; + jl_generic_fptr_t fptr; + jl_value_t **args; + uint32_t nargs; + jl_value_t *ret; + jl_module_t *current_module; + size_t world_age; } ti_threadwork_t; // thread function From 8af48fcebaa256722d42d01b59ef5e518621c36a Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Fri, 3 Mar 2017 14:08:57 -0500 Subject: [PATCH 0140/1534] Enable assertion in C++ code in debug/force assertion build even if LLVM assertion is off. --- Make.inc | 6 +++++- src/APInt-C.cpp | 2 ++ src/Makefile | 2 +- src/ccall.cpp | 2 +- src/cgmemmgr.cpp | 2 ++ src/cgutils.cpp | 4 ++-- src/codegen.cpp | 5 +++-- src/debuginfo.cpp | 6 ++---- src/disasm.cpp | 1 + src/fix_llvm_assert.h | 16 ++++++++++++++++ src/jitlayers.cpp | 3 ++- src/jitlayers.h | 1 + src/julia.h | 2 +- src/llvm-gcroot.cpp | 10 ++++++---- src/llvm-ptls.cpp | 7 ++++--- src/llvm-simdloop.cpp | 2 ++ src/llvm-version.h | 1 + src/runtime_ccall.cpp | 3 ++- 18 files changed, 54 insertions(+), 21 deletions(-) create mode 100644 src/fix_llvm_assert.h diff --git a/Make.inc b/Make.inc index abad5fe879cce..14c79c7e1c5de 100644 --- a/Make.inc +++ b/Make.inc @@ -316,9 +316,13 @@ JULIACODEGEN := LLVM # flag for disabling assertions ifeq ($(FORCE_ASSERTIONS), 1) +# C++ code needs to include LLVM header with the same assertion flag as LLVM +# Use this flag to re-enable assertion in our code after all the LLVM headers are included +CXX_DISABLE_ASSERTION := DISABLE_ASSERTIONS := else -DISABLE_ASSERTIONS := -DNDEBUG +CXX_DISABLE_ASSERTION := -DJL_NDEBUG +DISABLE_ASSERTIONS := -DNDEBUG -DJL_NDEBUG endif # Compiler specific stuff diff --git a/src/APInt-C.cpp b/src/APInt-C.cpp index a4ba5d0a7158c..6c29d7e9ced40 100644 --- a/src/APInt-C.cpp +++ b/src/APInt-C.cpp @@ -6,6 +6,8 @@ #include #include +#include "fix_llvm_assert.h" + #include "APInt-C.h" #include "julia.h" diff --git a/src/Makefile b/src/Makefile index 4dab3bfa2a334..ae3db0cb4c649 100644 --- a/src/Makefile +++ b/src/Makefile @@ -141,7 +141,7 @@ $(BUILDDIR)/%.o: $(SRCDIR)/%.c $(HEADERS) | $(BUILDDIR) $(BUILDDIR)/%.dbg.obj: $(SRCDIR)/%.c $(HEADERS) | $(BUILDDIR) @$(call PRINT_CC, $(CC) $(CPPFLAGS) $(CFLAGS) $(DEBUGFLAGS) -c $< -o $@) $(BUILDDIR)/%.o: $(SRCDIR)/%.cpp $(SRCDIR)/llvm-version.h $(HEADERS) $(LLVM_CONFIG_ABSOLUTE) | $(BUILDDIR) - @$(call PRINT_CC, $(CXX) $(shell $(LLVM_CONFIG_HOST) --cxxflags) $(CPPFLAGS) $(CXXFLAGS) $(SHIPFLAGS) -c $< -o $@) + @$(call PRINT_CC, $(CXX) $(shell $(LLVM_CONFIG_HOST) --cxxflags) $(CPPFLAGS) $(CXXFLAGS) $(SHIPFLAGS) $(CXX_DISABLE_ASSERTION) -c $< -o $@) $(BUILDDIR)/%.dbg.obj: $(SRCDIR)/%.cpp $(SRCDIR)/llvm-version.h $(HEADERS) $(LLVM_CONFIG_ABSOLUTE) | $(BUILDDIR) @$(call PRINT_CC, $(CXX) $(shell $(LLVM_CONFIG_HOST) --cxxflags) $(CPPFLAGS) $(CXXFLAGS) $(DEBUGFLAGS) -c $< -o $@) diff --git a/src/ccall.cpp b/src/ccall.cpp index 62f62e67c3ec8..37215e94ba992 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -2039,7 +2039,7 @@ jl_cgval_t function_sig_t::emit_a_ccall( assert(rtsz > 0); Value *strct = emit_allocobj(ctx, rtsz, runtime_bt); int boxalign = jl_gc_alignment(rtsz); -#ifndef NDEBUG +#ifndef JL_NDEBUG #if JL_LLVM_VERSION >= 30600 const DataLayout &DL = jl_ExecutionEngine->getDataLayout(); #else diff --git a/src/cgmemmgr.cpp b/src/cgmemmgr.cpp index c4b93638caed3..95f0fbdfc17b5 100644 --- a/src/cgmemmgr.cpp +++ b/src/cgmemmgr.cpp @@ -6,12 +6,14 @@ #ifdef USE_MCJIT #include +#include "fix_llvm_assert.h" #include "julia.h" #include "julia_internal.h" #if JL_LLVM_VERSION >= 30700 #if JL_LLVM_VERSION < 30800 # include +# include "fix_llvm_assert.h" #endif #ifdef _OS_LINUX_ # include diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 338db64dfbc7e..0b55c53db4ca8 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -528,7 +528,7 @@ static Type *julia_struct_to_llvm(jl_value_t *jt, jl_unionall_t *ua, bool *isbox jst->struct_decl = StructType::get(jl_LLVMContext, ArrayRef(&latypes[0], ntypes)); } } -#ifndef NDEBUG +#ifndef JL_NDEBUG // If LLVM and Julia disagree about alignment, much trouble ensues, so check it! if (jst->layout) { const DataLayout &DL = @@ -2001,7 +2001,7 @@ static void emit_unionmove(Value *dest, const jl_cgval_t &src, Value *skip, bool else copy_bytes = builder.CreateSelect(skip, ConstantInt::get(copy_bytes->getType(), 0), copy_bytes); } -#ifndef NDEBUG +#ifndef JL_NDEBUG // try to catch codegen errors early, before it uses this to memcpy over the entire stack CreateConditionalAbort(builder, builder.CreateICmpEQ(copy_bytes, ConstantInt::get(T_int32, -1))); #endif diff --git a/src/codegen.cpp b/src/codegen.cpp index ead8701ea08fd..d79efe233dc48 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -103,6 +103,7 @@ #include #include #endif +#include "fix_llvm_assert.h" using namespace llvm; namespace llvm { @@ -827,7 +828,7 @@ static void CreateTrap(IRBuilder<> &builder) builder.SetInsertPoint(newBB); } -#ifndef NDEBUG +#ifndef JL_NDEBUG static void CreateConditionalAbort(IRBuilder<> &builder, Value *test) { Function *f = builder.GetInsertBlock()->getParent(); @@ -5714,7 +5715,7 @@ static std::unique_ptr emit_function( cur_prop.is_poploc = false; jl_value_t *stmt = jl_array_ptr_ref(stmts, i); jl_expr_t *expr = jl_is_expr(stmt) ? (jl_expr_t*)stmt : nullptr; -#ifndef NDEBUG +#ifndef JL_NDEBUG if (jl_is_labelnode(stmt)) { size_t lname = jl_labelnode_label(stmt); if (lname != i + 1) { diff --git a/src/debuginfo.cpp b/src/debuginfo.cpp index 743af5f97a964..aca5b74e6b978 100644 --- a/src/debuginfo.cpp +++ b/src/debuginfo.cpp @@ -34,10 +34,7 @@ #if JL_LLVM_VERSION >= 30700 # include #endif - -#if defined(USE_MCJIT) && JL_LLVM_VERSION < 30600 && defined(_OS_DARWIN_) -#include "../deps/llvm-3.5.0/lib/ExecutionEngine/MCJIT/MCJIT.h" -#endif +#include "fix_llvm_assert.h" using namespace llvm; @@ -1040,6 +1037,7 @@ template static inline void ignoreError(T &err) { #if JL_LLVM_VERSION >= 30900 && !defined(NDEBUG) + // Needed only with LLVM assertion build consumeError(err.takeError()); #endif } diff --git a/src/disasm.cpp b/src/disasm.cpp index d0a07dc5d9f83..2e30877a5315d 100644 --- a/src/disasm.cpp +++ b/src/disasm.cpp @@ -83,6 +83,7 @@ #else #include #endif +#include "fix_llvm_assert.h" #include "julia.h" #include "julia_internal.h" diff --git a/src/fix_llvm_assert.h b/src/fix_llvm_assert.h new file mode 100644 index 0000000000000..8ed8a5ce4e144 --- /dev/null +++ b/src/fix_llvm_assert.h @@ -0,0 +1,16 @@ +// This file is a part of Julia. License is MIT: http://julialang.org/license + +// Include this file after every blocks of LLVM includes to set the assertion back. + +#ifdef NDEBUG +# ifndef JL_NDEBUG +# undef NDEBUG +# include +// Set NDEBUG back so that we can include another LLVM header right after +# define NDEBUG +# endif +#else +# ifdef JL_NDEBUG +# undef JL_NDEBUG +# endif +#endif diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index 5c705ad4ed2b4..5853fe8aba69b 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -70,6 +70,7 @@ namespace llvm { #include #include #include +#include "fix_llvm_assert.h" using namespace llvm; @@ -512,7 +513,7 @@ void *JuliaOJIT::getPointerToGlobalIfAvailable(const GlobalValue *GV) void JuliaOJIT::addModule(std::unique_ptr M) { -#ifndef NDEBUG +#ifndef JL_NDEBUG // validate the relocations for M for (Module::iterator I = M->begin(), E = M->end(); I != E; ) { Function *F = &*I; diff --git a/src/jitlayers.h b/src/jitlayers.h index 195f0a78eecff..6a110e092d898 100644 --- a/src/jitlayers.h +++ b/src/jitlayers.h @@ -40,6 +40,7 @@ extern PassManager *jl_globalPM; #if JL_LLVM_VERSION >= 30500 #include #endif +#include "fix_llvm_assert.h" extern "C" { extern int globalUnique; diff --git a/src/julia.h b/src/julia.h index fbb9e8ea0ad14..58ce43257e5ac 100644 --- a/src/julia.h +++ b/src/julia.h @@ -984,7 +984,7 @@ JL_DLLEXPORT int jl_type_morespecific(jl_value_t *a, jl_value_t *b); jl_value_t *jl_unwrap_unionall(jl_value_t *v); jl_value_t *jl_rewrap_unionall(jl_value_t *t, jl_value_t *u); -#ifdef NDEBUG +#if defined(NDEBUG) && defined(JL_NDEBUG) STATIC_INLINE int jl_is_leaf_type_(jl_value_t *v) { return jl_is_datatype(v) && ((jl_datatype_t*)v)->isleaftype; diff --git a/src/llvm-gcroot.cpp b/src/llvm-gcroot.cpp index 5a36eb594cf0f..57c34f53e2e50 100644 --- a/src/llvm-gcroot.cpp +++ b/src/llvm-gcroot.cpp @@ -24,6 +24,8 @@ #endif #include +#include "fix_llvm_assert.h" + #include #include #include @@ -44,7 +46,7 @@ extern std::pair tbaa_make_child(const char *name, MDNode *pare namespace { -#ifndef NDEBUG +#ifndef JL_NDEBUG static struct { unsigned count; unsigned locals; @@ -778,7 +780,7 @@ void JuliaGCAllocator::allocate_frame() if (CallInst *callInst = dyn_cast(user)) { assert(bb == NULL); bb = callInst->getParent(); -#ifdef NDEBUG +#ifdef JL_NDEBUG break; #endif } @@ -1130,7 +1132,7 @@ void JuliaGCAllocator::allocate_frame() } } -#ifndef NDEBUG +#ifndef JL_NDEBUG jl_gc_frame_stats.count++; jl_gc_frame_stats.locals += argSpaceSize; jl_gc_frame_stats.temp += maxDepth; @@ -1232,7 +1234,7 @@ static RegisterPass X("LowerGCFrame", "Lower GCFrame Pass", false /* Analysis Pass */); } -#ifndef NDEBUG // llvm assertions build +#ifndef JL_NDEBUG // llvm assertions build // gdb debugging code for inspecting the bb_uses map void jl_dump_bb_uses(std::map > &bb_uses) { diff --git a/src/llvm-ptls.cpp b/src/llvm-ptls.cpp index 8e88d05460da3..12286e7a6fe0a 100644 --- a/src/llvm-ptls.cpp +++ b/src/llvm-ptls.cpp @@ -22,12 +22,13 @@ #endif #include -#include "julia.h" -#include "julia_internal.h" - #if JL_LLVM_VERSION >= 30700 && defined(JULIA_ENABLE_THREADING) # include #endif +#include "fix_llvm_assert.h" + +#include "julia.h" +#include "julia_internal.h" using namespace llvm; diff --git a/src/llvm-simdloop.cpp b/src/llvm-simdloop.cpp index a30a4091e6092..f5f9d90cdd54e 100644 --- a/src/llvm-simdloop.cpp +++ b/src/llvm-simdloop.cpp @@ -14,6 +14,8 @@ #include #include #include +#include "fix_llvm_assert.h" + #include namespace llvm { diff --git a/src/llvm-version.h b/src/llvm-version.h index 0149b4016cb22..02817494c2999 100644 --- a/src/llvm-version.h +++ b/src/llvm-version.h @@ -1,6 +1,7 @@ // This file is a part of Julia. License is MIT: http://julialang.org/license #include +#include "fix_llvm_assert.h" #ifndef LLVM_VERSION_PATCH // for LLVM 3.3 #define LLVM_VERSION_PATCH 0 diff --git a/src/runtime_ccall.cpp b/src/runtime_ccall.cpp index 9800805e87106..470652d6357da 100644 --- a/src/runtime_ccall.cpp +++ b/src/runtime_ccall.cpp @@ -1,12 +1,13 @@ // This file is a part of Julia. License is MIT: http://julialang.org/license +#include "llvm-version.h" #include #include #include #include +#include "fix_llvm_assert.h" #include "julia.h" #include "julia_internal.h" -#include "llvm-version.h" using namespace llvm; // --- library symbol lookup --- From fb845c7b1c23414de4e3203cedb38babc2e40e7c Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 6 Mar 2017 14:04:31 -0500 Subject: [PATCH 0141/1534] REPL: better error handling printing for keymap failures --- base/LineEdit.jl | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/base/LineEdit.jl b/base/LineEdit.jl index bc9367022511a..23772de428ca1 100644 --- a/base/LineEdit.jl +++ b/base/LineEdit.jl @@ -1572,7 +1572,6 @@ end function run_interface(terminal, m::ModalInterface) s::MIState = init_state(terminal, m) while !s.aborted - p = s.current_mode buf, ok, suspend = prompt!(terminal, m, s) while suspend @static if is_unix(); ccall(:jl_repl_raise_sigtstp, Cint, ()); end @@ -1597,17 +1596,22 @@ function prompt!(term, prompt, s = init_state(term, prompt)) enable_bracketed_paste(term) try activate(prompt, s, term, term) + old_state = mode(s) while true - map = keymap(s, prompt) - fcn = match_input(map, s) + kmap = keymap(s, prompt) + fcn = match_input(kmap, s) + kdata = keymap_data(s, prompt) # errors in keymaps shouldn't cause the REPL to fail, so wrap in a # try/catch block local state try - state = fcn(s, keymap_data(s, prompt)) + state = fcn(s, kdata) catch e - warn("Caught an exception in the keymap:") - warn(e) + bt = catch_backtrace() + warn(e, bt = bt, prefix = "ERROR (in the keymap): ") + # try to cleanup and get `s` back to its original state before returning + transition(s, :reset) + transition(s, old_state) state = :done end if state === :abort From 666eee60d02f3d7bc8433185b3eb70a3b84f22eb Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 6 Mar 2017 11:58:25 -0800 Subject: [PATCH 0142/1534] A fix and stronger tests for Diagonal setindex! and friends. (#20900) Makes Diagonal setindex! return the assigned value (like other setindex! methods) rather than the Diagonal matrix. Strengthens tests for Diagonal setindex! Touches up tests for Diagonal getindex. Cleans up, annotates some other tests that were coupled to the setindex! and getindex tests. Reduces nonlocality of some of the other tests. --- base/linalg/diagonal.jl | 6 +-- test/linalg/diagonal.jl | 88 ++++++++++++++++++++++------------------- 2 files changed, 50 insertions(+), 44 deletions(-) diff --git a/base/linalg/diagonal.jl b/base/linalg/diagonal.jl index bb2416d56989f..4da93594a9b1e 100644 --- a/base/linalg/diagonal.jl +++ b/base/linalg/diagonal.jl @@ -86,10 +86,10 @@ function setindex!(D::Diagonal, v, i::Int, j::Int) @boundscheck checkbounds(D, i, j) if i == j @inbounds D.diag[i] = v - elseif v != 0 - throw(ArgumentError("cannot set an off-diagonal index ($i, $j) to a nonzero value ($v)")) + elseif !iszero(v) + throw(ArgumentError("cannot set off-diagonal entry ($i, $j) to a nonzero value ($v)")) end - D + return v end diff --git a/test/linalg/diagonal.jl b/test/linalg/diagonal.jl index d2cec79cd9602..9031e2dde7aa2 100644 --- a/test/linalg/diagonal.jl +++ b/test/linalg/diagonal.jl @@ -206,7 +206,7 @@ srand(1) end end - @testset "svd" begin + @testset "svd (#11120/#11247)" begin U, s, V = svd(D) @test (U*Diagonal(s))*V' ≈ D @test svdvals(D) == s @@ -214,45 +214,49 @@ srand(1) end end -D = Diagonal(Matrix{Float64}[randn(3,3), randn(2,2)]) -@test sort([svdvals(D)...;], rev = true) ≈ svdvals([D.diag[1] zeros(3,2); zeros(2,3) D.diag[2]]) -@test [eigvals(D)...;] ≈ eigvals([D.diag[1] zeros(3,2); zeros(2,3) D.diag[2]]) -#isposdef -@test !isposdef(Diagonal(-1.0 * rand(n))) +@testset "svdvals and eigvals (#11120/#11247)" begin + D = Diagonal(Matrix{Float64}[randn(3,3), randn(2,2)]) + @test sort([svdvals(D)...;], rev = true) ≈ svdvals([D.diag[1] zeros(3,2); zeros(2,3) D.diag[2]]) + @test [eigvals(D)...;] ≈ eigvals([D.diag[1] zeros(3,2); zeros(2,3) D.diag[2]]) +end -@testset "Indexing" begin - let d = randn(n), D = Diagonal(d) - for i=1:n - @test D[i,i] == d[i] - end - for i=1:n - for j=1:n - @test D[i,j] == (i==j ? d[i] : 0) - end - end - D2 = copy(D) - for i=1:n - D2[i,i] = i - end - for i=1:n - for j=1:n - if i == j - @test D2[i,j] == i - else - @test D2[i,j] == 0 - D2[i,j] = 0 - @test_throws ArgumentError (D2[i,j] = 1) - end - end +@testset "isposdef" begin + @test !isposdef(Diagonal(-1.0 * rand(n))) +end + +@testset "getindex" begin + d = randn(n) + D = Diagonal(d) + # getindex bounds checking + @test_throws BoundsError D[0, 0] + @test_throws BoundsError D[-1, -2] + @test_throws BoundsError D[n, n + 1] + @test_throws BoundsError D[n + 1, n] + @test_throws BoundsError D[n + 1, n + 1] + # getindex on and off the diagonal + for i in 1:n, j in 1:n + @test D[i, j] == (i == j ? d[i] : 0) + end +end + +@testset "setindex!" begin + d = randn(n) + D = Diagonal(d) + # setindex! bounds checking + @test_throws BoundsError D[0, 0] = 0 + @test_throws BoundsError D[-1 , -2] = 0 + @test_throws BoundsError D[n, n + 1] = 0 + @test_throws BoundsError D[n + 1, n] = 0 + @test_throws BoundsError D[n + 1, n + 1] = 0 + for i in 1:n, j in 1:n + if i == j + # setindex on! the diagonal + @test ((D[i, j] = i) == i; D[i, j] == i) + else + # setindex! off the diagonal + @test ((D[i, j] = 0) == 0; iszero(D[i, j])) + @test_throws ArgumentError D[i, j] = 1 end - @test_throws BoundsError D[0, 0] - @test_throws BoundsError (D[0, 0] = 0) - @test_throws BoundsError D[-1,-2] - @test_throws BoundsError (D[-1,-2] = 0) - @test_throws BoundsError D[n+1,n+1] - @test_throws BoundsError (D[n+1,n+1] = 0) - @test_throws BoundsError D[n,n+1] - @test_throws BoundsError (D[n,n+1] = 0) end end @@ -295,6 +299,8 @@ let D1 = Diagonal(rand(5)), D2 = Diagonal(rand(5)) @test_throws MethodError Ac_mul_B!(D1,D2) end -# Diagonal and Q -Q = qrfact(randn(5,5))[:Q] -@test D*Q' == Array(D)*Q' +@testset "multiplication of QR Q-factor and Diagonal (#16615 spot test)" begin + D = Diagonal(randn(5)) + Q = qrfact(randn(5, 5))[:Q] + @test D * Q' == Array(D) * Q' +end From d5566f7e6d101536db4b8be5ff7826f9b7154ff4 Mon Sep 17 00:00:00 2001 From: Simon Kornblith Date: Mon, 6 Mar 2017 18:44:24 -0500 Subject: [PATCH 0143/1534] Allow quantile function to accept tuples Fixes #18458 --- base/statistics.jl | 38 +++++++++++++++++++------------------- test/statistics.jl | 4 ++++ 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/base/statistics.jl b/base/statistics.jl index a2c47f2481d1a..d5bc7b1cf7b2b 100644 --- a/base/statistics.jl +++ b/base/statistics.jl @@ -630,19 +630,10 @@ function quantile!(q::AbstractArray, v::AbstractVector, p::AbstractArray; if size(p) != size(q) throw(DimensionMismatch("size of p, $(size(p)), must equal size of q, $(size(q))")) end + isempty(q) && return q - isempty(v) && throw(ArgumentError("empty data vector")) - - lv = length(v) - if !sorted - minp, maxp = extrema(p) - lo = floor(Int,1+minp*(lv-1)) - hi = ceil(Int,1+maxp*(lv-1)) - - # only need to perform partial sort - sort!(v, 1, lv, PartialQuickSort(lo:hi), Base.Sort.Forward) - end - isnan(v[end]) && throw(ArgumentError("quantiles are undefined in presence of NaNs")) + minp, maxp = extrema(p) + _quantilesort!(v, sorted, minp, maxp) for (i, j) in zip(eachindex(p), eachindex(q)) @inbounds q[j] = _quantile(v,p[i]) @@ -653,21 +644,30 @@ end quantile!(v::AbstractVector, p::AbstractArray; sorted::Bool=false) = quantile!(similar(p,float(eltype(v))), v, p; sorted=sorted) -function quantile!(v::AbstractVector, p::Real; - sorted::Bool=false) +quantile!(v::AbstractVector, p::Real; sorted::Bool=false) = + _quantile(_quantilesort!(v, sorted, p, p), p) + +function quantile!(v::AbstractVector, p::Tuple{Vararg{Real}}; sorted::Bool=false) + isempty(p) && return () + minp, maxp = extrema(p) + _quantilesort!(v, sorted, minp, maxp) + return map(x->_quantile(v, x), p) +end + +# Function to perform partial sort of v for quantiles in given range +function _quantilesort!(v::AbstractArray, sorted::Bool, minp::Real, maxp::Real) isempty(v) && throw(ArgumentError("empty data vector")) - lv = length(v) if !sorted - lo = floor(Int,1+p*(lv-1)) - hi = ceil(Int,1+p*(lv-1)) + lv = length(v) + lo = floor(Int,1+minp*(lv-1)) + hi = ceil(Int,1+maxp*(lv-1)) # only need to perform partial sort sort!(v, 1, lv, PartialQuickSort(lo:hi), Base.Sort.Forward) end isnan(v[end]) && throw(ArgumentError("quantiles are undefined in presence of NaNs")) - - return _quantile(v,p) + return v end # Core quantile lookup function: assumes `v` sorted diff --git a/test/statistics.jl b/test/statistics.jl index 9efcbeeb87f6e..41f4d4e44c773 100644 --- a/test/statistics.jl +++ b/test/statistics.jl @@ -326,6 +326,10 @@ end @test quantile([Inf,Inf],0.5) == Inf @test quantile([-Inf,1],0.5) == -Inf @test quantile([0,1],1e-18) == 1e-18 +@test quantile([1, 2, 3, 4],[]) == [] +@test quantile([1, 2, 3, 4], (0.5,)) == (2.5,) +@test quantile([4, 9, 1, 5, 7, 8, 2, 3, 5, 17, 11], (0.1, 0.2, 0.4, 0.9)) == (2.0, 3.0, 5.0, 11.0) +@test quantile([1, 2, 3, 4], ()) == () # StatsBase issue 164 y = [0.40003674665581906,0.4085630862624367,0.41662034698690303,0.41662034698690303,0.42189053966652057,0.42189053966652057,0.42553514344518345,0.43985732442991354] From 9771c7830e85da43c8910d818091969bd5db9fc0 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Tue, 7 Mar 2017 07:52:19 +0100 Subject: [PATCH 0144/1534] Support @inbounds in setindex!(::Array, ::AbstractArray, ::AbstractVector} (#20910) Previously this annotation wouldn't have any effect on Array, contrary to what happens with the general AbstractArray fallback method. Also always use @inbounds for X[count] since count depends on the length of I, (which is checked), and mark setindex_shape_check() as a bounds check. --- base/array.jl | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/base/array.jl b/base/array.jl index 153f7cbf942c8..e46c552abf936 100644 --- a/base/array.jl +++ b/base/array.jl @@ -528,6 +528,7 @@ setindex!{T}(A::Array{T}, x, i1::Int, i2::Int, I::Int...) = (@_inline_meta; arra # These are redundant with the abstract fallbacks but needed for bootstrap function setindex!(A::Array, x, I::AbstractVector{Int}) + @_propagate_inbounds_meta A === I && (I = copy(I)) for i in I A[i] = x @@ -535,7 +536,8 @@ function setindex!(A::Array, x, I::AbstractVector{Int}) return A end function setindex!(A::Array, X::AbstractArray, I::AbstractVector{Int}) - setindex_shape_check(X, length(I)) + @_propagate_inbounds_meta + @boundscheck setindex_shape_check(X, length(I)) count = 1 if X === A X = copy(X) @@ -544,7 +546,8 @@ function setindex!(A::Array, X::AbstractArray, I::AbstractVector{Int}) I = copy(I) end for i in I - A[i] = X[count] + @inbounds x = X[count] + A[i] = x count += 1 end return A @@ -555,15 +558,16 @@ function setindex!{T}(A::Array{T}, X::Array{T}, I::UnitRange{Int}) @_inline_meta @boundscheck checkbounds(A, I) lI = length(I) - setindex_shape_check(X, lI) + @boundscheck setindex_shape_check(X, lI) if lI > 0 unsafe_copy!(A, first(I), X, 1, lI) end return A end function setindex!{T}(A::Array{T}, X::Array{T}, c::Colon) + @_inline_meta lI = length(A) - setindex_shape_check(X, lI) + @boundscheck setindex_shape_check(X, lI) if lI > 0 unsafe_copy!(A, 1, X, 1, lI) end From 470f6064c0f2315e7064e5c4f782dd95c0e847c3 Mon Sep 17 00:00:00 2001 From: Martin Holters Date: Tue, 7 Mar 2017 08:10:54 +0100 Subject: [PATCH 0145/1534] Make `_reshape_uncolon` easier on inference (#20874) * Make `_reshape_uncolon` easier on inference Fixes #20848 --- base/reshapedarray.jl | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/base/reshapedarray.jl b/base/reshapedarray.jl index 17e1b8af01f91..587c568b09f4a 100644 --- a/base/reshapedarray.jl +++ b/base/reshapedarray.jl @@ -95,23 +95,19 @@ reshape(parent::AbstractArray, dims::Dims) = _reshape(parent, dims) reshape(parent::AbstractArray, dims::Int...) = reshape(parent, dims) reshape(parent::AbstractArray, dims::Union{Int,Colon}...) = reshape(parent, dims) reshape(parent::AbstractArray, dims::Tuple{Vararg{Union{Int,Colon}}}) = _reshape(parent, _reshape_uncolon(parent, dims)) -# Recursively move dimensions to pre and post tuples, splitting on the Colon -@inline _reshape_uncolon(A, dims) = _reshape_uncolon(A, (), nothing, (), dims) -@inline _reshape_uncolon(A, pre, c::Void, post, dims::Tuple{Any, Vararg{Any}}) = - _reshape_uncolon(A, (pre..., dims[1]), c, post, tail(dims)) -@inline _reshape_uncolon(A, pre, c::Void, post, dims::Tuple{Colon, Vararg{Any}}) = - _reshape_uncolon(A, pre, dims[1], post, tail(dims)) -@inline _reshape_uncolon(A, pre, c::Colon, post, dims::Tuple{Any, Vararg{Any}}) = - _reshape_uncolon(A, pre, c, (post..., dims[1]), tail(dims)) -_reshape_uncolon(A, pre, c::Colon, post, dims::Tuple{Colon, Vararg{Any}}) = - throw(DimensionMismatch("new dimensions $((pre..., c, post..., dims...)) may only have at most one omitted dimension specified by Colon()")) -@inline function _reshape_uncolon(A, pre, c::Colon, post, dims::Tuple{}) +@inline function _reshape_uncolon(A, dims) + pre, post = _split_at_colon((), dims...) + if any(d -> d isa Colon, post) + throw(DimensionMismatch("new dimensions $(dims) may have at most one omitted dimension specified by Colon()")) + end sz, remainder = divrem(length(A), prod(pre)*prod(post)) - remainder == 0 || _throw_reshape_colon_dimmismatch(A, pre, post) + remainder == 0 || _throw_reshape_colon_dimmismatch(A, dims) (pre..., sz, post...) end -_throw_reshape_colon_dimmismatch(A, pre, post) = - throw(DimensionMismatch("array size $(length(A)) must be divisible by the product of the new dimensions $((pre..., :, post...))")) +@inline _split_at_colon(pre, dim::Any, tail...) = _split_at_colon((pre..., dim), tail...) +@inline _split_at_colon(pre, ::Colon, tail...) = (pre, tail) +_throw_reshape_colon_dimmismatch(A, dims) = + throw(DimensionMismatch("array size $(length(A)) must be divisible by the product of the new dimensions $dims")) reshape{T,N}(parent::AbstractArray{T,N}, ndims::Type{Val{N}}) = parent function reshape{N}(parent::AbstractArray, ndims::Type{Val{N}}) From 6a24a567117b1d8346842bcd7b1fea1f76cf6404 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 6 Mar 2017 14:40:01 -0500 Subject: [PATCH 0146/1534] fix over-eager Unicode fixes this is converting between zero-based file-position and one-based string indexign not adjusting Unicode codepoints (bug introduced by dcb529b0cd7) fix #19153 --- base/REPL.jl | 8 ++++---- test/repl.jl | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/base/REPL.jl b/base/REPL.jl index c5fc6d306f4ba..7a4eb61b46d6c 100644 --- a/base/REPL.jl +++ b/base/REPL.jl @@ -551,8 +551,8 @@ function history_search(hist::REPLHistoryProvider, query_buffer::IOBuffer, respo response_str = String(response_buffer) # Alright, first try to see if the current match still works - a = position(response_buffer) + 1 - b = min(endof(response_str), prevind(response_str, a + sizeof(searchdata))) + a = position(response_buffer) + 1 # position is zero-indexed + b = min(endof(response_str), prevind(response_str, a + sizeof(searchdata))) # ensure that b is valid !skip_current && searchdata == response_str[a:b] && return true @@ -565,7 +565,7 @@ function history_search(hist::REPLHistoryProvider, query_buffer::IOBuffer, respo if 1 <= searchstart <= endof(response_str) match = searchfunc(response_str, searchdata, searchstart) if match != 0:-1 - seek(response_buffer, prevind(response_str, first(match))) + seek(response_buffer, first(match) - 1) return true end end @@ -578,7 +578,7 @@ function history_search(hist::REPLHistoryProvider, query_buffer::IOBuffer, respo if match != 0:-1 && h != response_str && haskey(hist.mode_mapping, hist.modes[idx]) truncate(response_buffer, 0) write(response_buffer, h) - seek(response_buffer, prevind(h, first(match))) + seek(response_buffer, first(match) - 1) hist.cur_idx = idx return true end diff --git a/test/repl.jl b/test/repl.jl index 3f8fed44846ad..d4adaf0fdd193 100644 --- a/test/repl.jl +++ b/test/repl.jl @@ -242,6 +242,9 @@ fakehistory = """ # time: 2014-06-30 17:32:59 EDT # mode: shell \tll +# time: 2014-06-30 99:99:99 EDT +# mode: julia +\tx ΔxΔ # time: 2014-06-30 17:32:49 EDT # mode: julia \t1 + 1 @@ -363,6 +366,8 @@ begin LineEdit.enter_search(s, histp, true) write(ss.query_buffer, "l") LineEdit.update_display_buffer(ss, ss) + @test buffercontents(ss.response_buffer) == "ll" + @test position(ss.response_buffer) == 1 write(ss.query_buffer, "l") LineEdit.update_display_buffer(ss, ss) LineEdit.accept_result(s, histp) @@ -426,6 +431,20 @@ begin @test LineEdit.input_string(ps) == "ls" @test position(LineEdit.buffer(s)) == 1 + # Some Unicode handling testing + LineEdit.history_prev(s, hp) + LineEdit.enter_search(s, histp, true) + write(ss.query_buffer, "x") + LineEdit.update_display_buffer(ss, ss) + @test buffercontents(ss.response_buffer) == "x ΔxΔ" + @test position(ss.response_buffer) == 4 + write(ss.query_buffer, " ") + LineEdit.update_display_buffer(ss, ss) + LineEdit.accept_result(s, histp) + @test LineEdit.mode(s) == repl_mode + @test buffercontents(LineEdit.buffer(s)) == "x ΔxΔ" + @test position(LineEdit.buffer(s)) == 0 + # Try entering search mode while in custom repl mode LineEdit.enter_search(s, custom_histp, true) end From ba5d0137ac22d8a5d292cd69df4f7fa632cebaad Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 7 Mar 2017 13:02:29 -0500 Subject: [PATCH 0147/1534] correct the type-equal assertion in the incremental deserializer the usual jl_types_equal function has performance optimizations that assume the types were constructed correctly we don't do that here (which is why it requires all this extra work in the first place), so we also need to avoid the type-equal test optimizations fix #20922 --- src/dump.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/dump.c b/src/dump.c index f227cc674c73e..c8c0364e8828f 100644 --- a/src/dump.c +++ b/src/dump.c @@ -2696,6 +2696,15 @@ JL_DLLEXPORT int jl_save_incremental(const char *fname, jl_array_t *worklist) return 0; } +#ifndef NDEBUG +// skip the performance optimizations of jl_types_equal and just use subtyping directly +// ones of these types is invalid - that's why we're doing the recache type operation +static int jl_invalid_types_equal(jl_datatype_t *a, jl_datatype_t *b) +{ + return jl_subtype((jl_value_t*)a, (jl_value_t*)b) && jl_subtype((jl_value_t*)b, (jl_value_t*)a); +} +#endif + static jl_datatype_t *jl_recache_type(jl_datatype_t *dt, size_t start, jl_value_t *v) { if (v == NULL) @@ -2710,7 +2719,7 @@ static jl_datatype_t *jl_recache_type(jl_datatype_t *dt, size_t start, jl_value_ if (p->uid == -1 || p->uid == 0) { jl_datatype_t *cachep = jl_recache_type(p, start, NULL); if (p != cachep) { - assert(jl_types_equal((jl_value_t*)p, (jl_value_t*)cachep)); + assert(jl_invalid_types_equal(p, cachep)); jl_svecset(tt, i, cachep); } } @@ -2739,7 +2748,7 @@ static jl_datatype_t *jl_recache_type(jl_datatype_t *dt, size_t start, jl_value_ else { dt->uid = 0; t = (jl_datatype_t*)jl_cache_type_(dt); - assert(jl_types_equal((jl_value_t*)t, (jl_value_t*)dt)); + assert(jl_invalid_types_equal(t, dt)); } } else { From b6bac94cfd68a69bd69b720722b1ad33791ed522 Mon Sep 17 00:00:00 2001 From: Simon Kornblith Date: Tue, 7 Mar 2017 15:39:37 -0500 Subject: [PATCH 0148/1534] Document that `p` can be a tuple --- base/statistics.jl | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/base/statistics.jl b/base/statistics.jl index d5bc7b1cf7b2b..9af97c10bc9db 100644 --- a/base/statistics.jl +++ b/base/statistics.jl @@ -605,10 +605,11 @@ median{T}(v::AbstractArray{T}, region) = mapslices(median!, v, region) """ quantile!([q, ] v, p; sorted=false) -Compute the quantile(s) of a vector `v` at the probabilities `p`, with optional output into -array `q` (if not provided, a new output array is created). The keyword argument `sorted` -indicates whether `v` can be assumed to be sorted; if `false` (the default), then the -elements of `v` may be partially sorted. +Compute the quantile(s) of a vector `v` at the probability or vector or tuple of +probabilities `p`. If `p` is a vector, an optional output array `q` may also be specified. +(If not provided, a new output array is created.) The keyword argument `sorted` indicates +whether `v` can be assumed to be sorted; if `false` (the default), then the elements of `v` +may be partially sorted. The elements of `p` should be on the interval [0,1], and `v` should not have any `NaN` values. @@ -699,8 +700,9 @@ end """ quantile(v, p; sorted=false) -Compute the quantile(s) of a vector `v` at a specified probability or vector `p`. The -keyword argument `sorted` indicates whether `v` can be assumed to be sorted. +Compute the quantile(s) of a vector `v` at a specified probability or vector or tuple of +probabilities `p`. The keyword argument `sorted` indicates whether `v` can be assumed to +be sorted. The `p` should be on the interval [0,1], and `v` should not have any `NaN` values. From 6fb5dfabf5d9a2de9055983b8d9304c4c0dcddb6 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Tue, 7 Mar 2017 12:12:15 -0800 Subject: [PATCH 0149/1534] Fix shape corner cases in zero-preserving sparse broadcast!(f, C, A, B). Specifically, fix zero-preserving sparse broadcast!(f, C, A, B) where C's shape does not match the broadcast shape of A and B. Strengthen associated tests. --- base/sparse/higherorderfns.jl | 40 ++++++++++++++++++++++++----------- test/sparse/higherorderfns.jl | 11 +++++----- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/base/sparse/higherorderfns.jl b/base/sparse/higherorderfns.jl index 1c73c3c957e77..c86602a219bef 100644 --- a/base/sparse/higherorderfns.jl +++ b/base/sparse/higherorderfns.jl @@ -515,16 +515,15 @@ function _broadcast_zeropres!{Tf}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, B spaceC::Int = min(length(storedinds(C)), length(storedvals(C))) rowsentinelA = convert(indtype(A), numrows(C) + 1) rowsentinelB = convert(indtype(B), numrows(C) + 1) - # A and B cannot have the same shape, as we directed that case to map in broadcast's - # entry point; here we need efficiently handle only heterogeneous combinations of matrices - # with no singleton dimensions ("matrices" hereafter), one singleton dimension ("columns" - # and "rows"), and two singleton dimensions ("scalars"). Cases involving scalars should - # be rare and optimizing that case complicates the code appreciably, so we largely - # ignore that case's performance below. + # C, A, and B cannot all have the same shape, as we directed that case to map in broadcast's + # entry point; here we need efficiently handle only heterogeneous combinations of mats/vecs + # with no singleton dimensions, one singleton dimension, and two singleton dimensions. + # Cases involving objects with two singleton dimensions should be rare and optimizing + # that case complicates the code appreciably, so we largely ignore that case's + # performance below. # - # We first divide the cases into two groups: those in which neither argument expands - # vertically (matrix-column combinations) and those in which an argument expands - # vertically (matrix-row and column-row combinations). + # We first divide the cases into two groups: those in which neither input argument + # expands vertically, and those in which at least one argument expands vertically. # # NOTE: Placing the loops over columns outside the conditional chain segregating # argument shape combinations eliminates some code replication but unfortunately @@ -532,7 +531,7 @@ function _broadcast_zeropres!{Tf}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, B # # Cases without vertical expansion Ck = 1 - if numrows(A) == numrows(B) + if numrows(A) == numrows(B) == numrows(C) @inbounds for j in columns(C) setcolptr!(C, j, Ck) Ak, stopAk = numcols(A) == 1 ? (colstartind(A, 1), colboundind(A, 1)) : (colstartind(A, j), colboundind(A, j)) @@ -575,7 +574,24 @@ function _broadcast_zeropres!{Tf}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, B end end # Cases with vertical expansion - elseif numrows(A) == 1 # && numrows(B) != 1, vertically expand first argument + elseif numrows(A) == numrows(B) == 1 # && numrows(C) != 1, vertically expand both A and B + @inbounds for j in columns(C) + setcolptr!(C, j, Ck) + Ak, stopAk = numcols(A) == 1 ? (colstartind(A, 1), colboundind(A, 1)) : (colstartind(A, j), colboundind(A, j)) + Bk, stopBk = numcols(B) == 1 ? (colstartind(B, 1), colboundind(B, 1)) : (colstartind(B, j), colboundind(B, j)) + Ax = Ak < stopAk ? storedvals(A)[Ak] : zero(eltype(A)) + Bx = Bk < stopBk ? storedvals(B)[Bk] : zero(eltype(B)) + Cx = f(Ax, Bx) + if !_iszero(Cx) + for Ci::indtype(C) in 1:numrows(C) + Ck > spaceC && (spaceC = expandstorage!(C, _unchecked_maxnnzbcres(size(C), A, B))) + storedinds(C)[Ck] = Ci + storedvals(C)[Ck] = Cx + Ck += 1 + end + end + end + elseif numrows(A) == 1 # && numrows(B) == numrows(C) != 1 , vertically expand only A @inbounds for j in columns(C) setcolptr!(C, j, Ck) Ak, stopAk = numcols(A) == 1 ? (colstartind(A, 1), colboundind(A, 1)) : (colstartind(A, j), colboundind(A, j)) @@ -616,7 +632,7 @@ function _broadcast_zeropres!{Tf}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, B end end end - elseif numrows(B) == 1 # && numrows(A) != 1, vertically expand second argument + else # numrows(B) == 1 && numrows(A) == numrows(C) != 1, vertically expand only B @inbounds for j in columns(C) setcolptr!(C, j, Ck) Ak, stopAk = numcols(A) == 1 ? (colstartind(A, 1), colboundind(A, 1)) : (colstartind(A, j), colboundind(A, j)) diff --git a/test/sparse/higherorderfns.jl b/test/sparse/higherorderfns.jl index 79a382699ffe1..61f8c3b6ce3c2 100644 --- a/test/sparse/higherorderfns.jl +++ b/test/sparse/higherorderfns.jl @@ -164,6 +164,7 @@ end mats = (sprand(N, M, p), sprand(N, 1, p), sprand(1, M, p), sprand(1, 1, 1.0), spzeros(1, 1)) vecs = (sprand(N, p), sprand(1, 1.0), spzeros(1)) tens = (mats..., vecs...) + fZ = Array(first(mats)) for Xo in tens X = ndims(Xo) == 1 ? SparseVector{Float32,Int32}(Xo) : SparseMatrixCSC{Float32,Int32}(Xo) # use different types to check internal type stability via allocation tests below @@ -182,20 +183,20 @@ end @test_throws DimensionMismatch broadcast(+, spzeros((shapeX .- 1)...), Y) end # --> test broadcast! entry point / +-like zero-preserving op - fZ = broadcast(+, fX, fY); Z = sparse(fZ) + broadcast!(+, fZ, fX, fY); Z = sparse(fZ) broadcast!(+, Z, X, Y); Z = sparse(fZ) # warmup for @allocated @test (@allocated broadcast!(+, Z, X, Y)) == 0 @test broadcast!(+, Z, X, Y) == sparse(broadcast!(+, fZ, fX, fY)) # --> test broadcast! entry point / *-like zero-preserving op - fZ = broadcast(*, fX, fY); Z = sparse(fZ) + broadcast!(*, fZ, fX, fY); Z = sparse(fZ) broadcast!(*, Z, X, Y); Z = sparse(fZ) # warmup for @allocated @test (@allocated broadcast!(*, Z, X, Y)) == 0 @test broadcast!(*, Z, X, Y) == sparse(broadcast!(*, fZ, fX, fY)) # --> test broadcast! entry point / not zero-preserving op - fZ = broadcast(f, fX, fY); Z = sparse(fZ) - broadcast!(f, Z, X, Y); Z = sparse(fZ) # warmup for @allocated + fZo = broadcast(f, fX, fY); Z = sparse(fZo) + broadcast!(f, Z, X, Y); Z = sparse(fZo) # warmup for @allocated @test (@allocated broadcast!(f, Z, X, Y)) == 0 - @test broadcast!(f, Z, X, Y) == sparse(broadcast!(f, fZ, fX, fY)) + @test broadcast!(f, Z, X, Y) == sparse(broadcast!(f, fZo, fX, fY)) # --> test shape checks for both broadcast and broadcast! entry points # TODO strengthen this test, avoiding dependence on checking whether # broadcast_indices throws to determine whether sparse broadcast should throw From 8c00a687b4daaabaf49d76bb1608bdf3fafa08f4 Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Tue, 7 Mar 2017 12:52:05 -0800 Subject: [PATCH 0150/1534] Minor update to the docstring wording for clarity --- base/statistics.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/base/statistics.jl b/base/statistics.jl index 9af97c10bc9db..36dc307da3204 100644 --- a/base/statistics.jl +++ b/base/statistics.jl @@ -605,11 +605,11 @@ median{T}(v::AbstractArray{T}, region) = mapslices(median!, v, region) """ quantile!([q, ] v, p; sorted=false) -Compute the quantile(s) of a vector `v` at the probability or vector or tuple of -probabilities `p`. If `p` is a vector, an optional output array `q` may also be specified. -(If not provided, a new output array is created.) The keyword argument `sorted` indicates -whether `v` can be assumed to be sorted; if `false` (the default), then the elements of `v` -may be partially sorted. +Compute the quantile(s) of a vector `v` at the probability or probabilities `p`, which +can be given as a single value, a vector, or a tuple. If `p` is a vector, an optional +output array `q` may also be specified. (If not provided, a new output array is created.) +The keyword argument `sorted` indicates whether `v` can be assumed to be sorted; if +`false` (the default), then the elements of `v` may be partially sorted. The elements of `p` should be on the interval [0,1], and `v` should not have any `NaN` values. From cfbca08aa59ab134eea2f7c7f9544843538c4aa0 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Tue, 7 Mar 2017 13:14:16 -0800 Subject: [PATCH 0151/1534] Fix shape corner cases in not-zero-preserving sparse broadcast!(f, C, A, B). Specifically, fix not-zero-preserving sparse broadcast!(f, C, A, B) where C's shape does not match the broadcast shape of A and B. Strengthen associated tests. --- base/sparse/higherorderfns.jl | 19 ++++++++++++++++--- test/sparse/higherorderfns.jl | 6 +++--- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/base/sparse/higherorderfns.jl b/base/sparse/higherorderfns.jl index c86602a219bef..6ef9e4270063d 100644 --- a/base/sparse/higherorderfns.jl +++ b/base/sparse/higherorderfns.jl @@ -687,7 +687,7 @@ function _broadcast_notzeropres!{Tf}(f::Tf, fillvalue, C::SparseVecOrMat, A::Spa rowsentinelA = convert(indtype(A), numrows(C) + 1) rowsentinelB = convert(indtype(B), numrows(C) + 1) # Cases without vertical expansion - if numrows(A) == numrows(B) + if numrows(A) == numrows(B) == numrows(C) @inbounds for (j, jo) in zip(columns(C), _densecoloffsets(C)) Ak, stopAk = numcols(A) == 1 ? (colstartind(A, 1), colboundind(A, 1)) : (colstartind(A, j), colboundind(A, j)) Bk, stopBk = numcols(B) == 1 ? (colstartind(B, 1), colboundind(B, 1)) : (colstartind(B, j), colboundind(B, j)) @@ -711,7 +711,20 @@ function _broadcast_notzeropres!{Tf}(f::Tf, fillvalue, C::SparseVecOrMat, A::Spa end end # Cases with vertical expansion - elseif numrows(A) == 1 # && numrows(B) != 1, vertically expand first argument + elseif numrows(A) == numrows(B) == 1 # && numrows(C) != 1, vertically expand both A and B + @inbounds for (j, jo) in zip(columns(C), _densecoloffsets(C)) + Ak, stopAk = numcols(A) == 1 ? (colstartind(A, 1), colboundind(A, 1)) : (colstartind(A, j), colboundind(A, j)) + Bk, stopBk = numcols(B) == 1 ? (colstartind(B, 1), colboundind(B, 1)) : (colstartind(B, j), colboundind(B, j)) + Ax = Ak < stopAk ? storedvals(A)[Ak] : zero(eltype(A)) + Bx = Bk < stopBk ? storedvals(B)[Bk] : zero(eltype(B)) + Cx = f(Ax, Bx) + if Cx != fillvalue + for Ck::Int in (jo + 1):(jo + numrows(C)) + storedvals(C)[Ck] = Cx + end + end + end + elseif numrows(A) == 1 # && numrows(B) == numrows(C) != 1, vertically expand only A @inbounds for (j, jo) in zip(columns(C), _densecoloffsets(C)) Ak, stopAk = numcols(A) == 1 ? (colstartind(A, 1), colboundind(A, 1)) : (colstartind(A, j), colboundind(A, j)) Bk, stopBk = numcols(B) == 1 ? (colstartind(B, 1), colboundind(B, 1)) : (colstartind(B, j), colboundind(B, j)) @@ -736,7 +749,7 @@ function _broadcast_notzeropres!{Tf}(f::Tf, fillvalue, C::SparseVecOrMat, A::Spa end end end - elseif numrows(B) == 1 # && numrows(A) != 1, vertically expand second argument + else # numrows(B) == 1 && numrows(A) == numrows(C) != 1, vertically expand only B @inbounds for (j, jo) in zip(columns(C), _densecoloffsets(C)) Ak, stopAk = numcols(A) == 1 ? (colstartind(A, 1), colboundind(A, 1)) : (colstartind(A, j), colboundind(A, j)) Bk, stopBk = numcols(B) == 1 ? (colstartind(B, 1), colboundind(B, 1)) : (colstartind(B, j), colboundind(B, j)) diff --git a/test/sparse/higherorderfns.jl b/test/sparse/higherorderfns.jl index 61f8c3b6ce3c2..492a477ee5b38 100644 --- a/test/sparse/higherorderfns.jl +++ b/test/sparse/higherorderfns.jl @@ -193,10 +193,10 @@ end @test (@allocated broadcast!(*, Z, X, Y)) == 0 @test broadcast!(*, Z, X, Y) == sparse(broadcast!(*, fZ, fX, fY)) # --> test broadcast! entry point / not zero-preserving op - fZo = broadcast(f, fX, fY); Z = sparse(fZo) - broadcast!(f, Z, X, Y); Z = sparse(fZo) # warmup for @allocated + broadcast!(f, fZ, fX, fY); Z = sparse(fZ) + broadcast!(f, Z, X, Y); Z = sparse(fZ) # warmup for @allocated @test (@allocated broadcast!(f, Z, X, Y)) == 0 - @test broadcast!(f, Z, X, Y) == sparse(broadcast!(f, fZo, fX, fY)) + @test broadcast!(f, Z, X, Y) == sparse(broadcast!(f, fZ, fX, fY)) # --> test shape checks for both broadcast and broadcast! entry points # TODO strengthen this test, avoiding dependence on checking whether # broadcast_indices throws to determine whether sparse broadcast should throw From e3bbd2627a8d31a08a66e7a57666b6d2ffd07f14 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Tue, 7 Mar 2017 17:52:54 -0800 Subject: [PATCH 0152/1534] Fixes and stronger tests for SymTridiagonal setindex!. (#20901) Makes SymTridiagonal setindex! no longer support off-diagonal assignment of any form. Strengthens tests for SymTridiagonal setindex!. Cleans up associated tests for broadcast! with structured-matrix destination. --- base/linalg/tridiag.jl | 8 ++++---- test/linalg/tridiag.jl | 12 ++++++------ test/sparse/higherorderfns.jl | 8 ++------ 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/base/linalg/tridiag.jl b/base/linalg/tridiag.jl index 805f5516f1354..0542a5edc91f3 100644 --- a/base/linalg/tridiag.jl +++ b/base/linalg/tridiag.jl @@ -375,13 +375,13 @@ function getindex{T}(A::SymTridiagonal{T}, i::Integer, j::Integer) end function setindex!(A::SymTridiagonal, x, i::Integer, j::Integer) + @boundscheck checkbounds(A, i, j) if i == j - A.dv[i] = x - elseif abs(i - j) == 1 - A.ev[min(i,j)] = x + @inbounds A.dv[i] = x else - throw(ArgumentError("cannot set elements outside the sub, main, or super diagonals")) + throw(ArgumentError("cannot set off-diagonal entry ($i, $j)")) end + return x end ## Tridiagonal matrices ## diff --git a/test/linalg/tridiag.jl b/test/linalg/tridiag.jl index 98371fff8a3b0..284c58053eefc 100644 --- a/test/linalg/tridiag.jl +++ b/test/linalg/tridiag.jl @@ -266,12 +266,12 @@ let n = 12 #Size of matrix problem to test @test A[1,1] == a[1] debug && println("setindex!") - @test_throws ArgumentError A[n,1] = 1 - @test_throws ArgumentError A[1,n] = 1 - A[3,3] = A[3,3] - A[2,3] = A[2,3] - A[3,2] = A[3,2] - @test A == fA + @test_throws BoundsError A[n + 1, 1] = 0 # test bounds check + @test_throws BoundsError A[1, n + 1] = 0 # test bounds check + @test ((A[3, 3] = A[3, 3]) == A[3, 3]; A == fA) # test assignment on the main diagonal + @test_throws ArgumentError A[3, 2] = 1 # test assignment on the subdiagonal + @test_throws ArgumentError A[2, 3] = 1 # test assignment on the superdiagonal + @test_throws ArgumentError A[1, 3] = 1 # test assignment off the main/sub/super diagonal debug && println("Diagonal extraction") @test diag(A,1) == b diff --git a/test/sparse/higherorderfns.jl b/test/sparse/higherorderfns.jl index 79a382699ffe1..f4edcdb10e2d2 100644 --- a/test/sparse/higherorderfns.jl +++ b/test/sparse/higherorderfns.jl @@ -424,18 +424,14 @@ end D = Diagonal(rand(N)) B = Bidiagonal(rand(N), rand(N - 1), true) T = Tridiagonal(rand(N - 1), rand(N), rand(N - 1)) - S = SymTridiagonal(rand(N), rand(N - 1)) - # why some of the tests below are broken: - # Diagonal setindex! allows setting off-diagonal entries to zero. Subtypes of - # AbstractTriangular allow analogs. @test broadcast!(sin, copy(D), D) == Diagonal(sin.(D)) @test broadcast!(sin, copy(B), B) == Bidiagonal(sin.(B), true) @test broadcast!(sin, copy(T), T) == Tridiagonal(sin.(T)) - @test_broken broadcast!(sin, copy(S), S) == SymTridiagonal(sin.(S)) @test broadcast!(*, copy(D), D, A) == Diagonal(broadcast(*, D, A)) @test broadcast!(*, copy(B), B, A) == Bidiagonal(broadcast(*, B, A), true) @test broadcast!(*, copy(T), T, A) == Tridiagonal(broadcast(*, T, A)) - @test_broken broadcast!(*, copy(S), T, sA) == SymTridiagonal(broadcast(*, T, sA)) + # SymTridiagonal (and similar symmetric matrix types) do not support setindex! + # off the diagonal, and so cannot serve as a destination for broadcast! end @testset "map[!] over combinations of sparse and structured matrices" begin From 78b96d067b038de22489a9337c751416b19c4e2b Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Wed, 8 Mar 2017 03:52:44 +0000 Subject: [PATCH 0153/1534] do checkout before changing HEAD (#20916) * do checkout before changing HEAD * add test for change to file permissions * add test for symlinks * add issue numbers to comments --- base/libgit2/libgit2.jl | 12 ++++++------ test/libgit2.jl | 28 ++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/base/libgit2/libgit2.jl b/base/libgit2/libgit2.jl index 3ef4a9dd379d8..6084a5d2dd96b 100644 --- a/base/libgit2/libgit2.jl +++ b/base/libgit2/libgit2.jl @@ -403,15 +403,15 @@ function checkout!(repo::GitRepo, commit::AbstractString = ""; # search for commit to get a commit object obj = GitObject(repo, GitHash(commit)) peeled = peel(GitCommit, obj) - - opts = force ? CheckoutOptions(checkout_strategy = Consts.CHECKOUT_FORCE) : CheckoutOptions() - # detach commit obj_oid = GitHash(peeled) - ref = GitReference(repo, obj_oid, force=force, - msg="libgit2.checkout: moving from $head_name to $(string(obj_oid))") # checkout commit - checkout_tree(repo, peeled, options = opts) + checkout_tree(repo, peeled, options = force ? CheckoutOptions(checkout_strategy = Consts.CHECKOUT_FORCE) : CheckoutOptions()) + + GitReference(repo, obj_oid, force=force, + msg="libgit2.checkout: moving from $head_name to $(obj_oid))") + + return nothing end """ diff --git a/test/libgit2.jl b/test/libgit2.jl index cc6878c7ccdd4..fb4c18a5e65b8 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -902,6 +902,34 @@ mktempdir() do dir end end + + if is_unix() + @testset "checkout/proptest" begin + repo = LibGit2.GitRepo(test_repo) + try + cp(joinpath(test_repo, test_file), joinpath(test_repo, "proptest")) + LibGit2.add!(repo, "proptest") + id1 = LibGit2.commit(repo, "test property change 1") + # change in file permissions (#17610) + chmod(joinpath(test_repo, "proptest"),0o744) + LibGit2.add!(repo, "proptest") + id2 = LibGit2.commit(repo, "test property change 2") + LibGit2.checkout!(repo, string(id1)) + @test !LibGit2.isdirty(repo) + # change file to symlink (#18420) + mv(joinpath(test_repo, "proptest"), joinpath(test_repo, "proptest2")) + symlink(joinpath(test_repo, "proptest2"), joinpath(test_repo, "proptest")) + LibGit2.add!(repo, "proptest", "proptest2") + id3 = LibGit2.commit(repo, "test symlink change") + LibGit2.checkout!(repo, string(id1)) + @test !LibGit2.isdirty(repo) + finally + close(repo) + end + end + end + + @testset "Credentials" begin creds_user = "USER" creds_pass = "PASS" From e8d2a6c464c3c55d84b0d3e3a058496606d078f9 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Wed, 8 Mar 2017 04:00:00 -0800 Subject: [PATCH 0154/1534] Remove unused import from sparse/sparse.jl. (#20938) Base.Broadcast.broadcast_indices is no longer used in SparseArrays outside of SparseArrays.HigherOrderFns, so remove the unused import. --- base/sparse/sparse.jl | 2 -- 1 file changed, 2 deletions(-) diff --git a/base/sparse/sparse.jl b/base/sparse/sparse.jl index 8f97fcecb57de..3ca298a66099d 100644 --- a/base/sparse/sparse.jl +++ b/base/sparse/sparse.jl @@ -26,8 +26,6 @@ import Base: @get!, acos, acosd, acot, acotd, acsch, asech, asin, asind, asinh, rotl90, rotr90, round, scale!, setindex!, similar, size, transpose, tril, triu, vec, permute!, map, map! -import Base.Broadcast: broadcast_indices - export AbstractSparseArray, AbstractSparseMatrix, AbstractSparseVector, SparseMatrixCSC, SparseVector, blkdiag, dense, droptol!, dropzeros!, dropzeros, issparse, nonzeros, nzrange, rowvals, sparse, sparsevec, spdiagm, speye, spones, From f4d1149774f05f3a6e1cd80029d6d7be2c3349ba Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Wed, 8 Mar 2017 12:29:29 +0000 Subject: [PATCH 0155/1534] Add fix for JULIA_PKGDIR using relative path (#20898) * Add fix for JULIA_PKGDIR using relative path Fixes #20896. * use withenv, and unversioned path * shorten withenv --- base/pkg/dir.jl | 8 +++++++- test/pkg.jl | 26 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/base/pkg/dir.jl b/base/pkg/dir.jl index 3b4d2da1bbd9c..2eb9a5312aaed 100644 --- a/base/pkg/dir.jl +++ b/base/pkg/dir.jl @@ -28,7 +28,13 @@ function cd(f::Function, args...; kws...) !haskey(ENV,"JULIA_PKGDIR") ? init() : throw(PkgError("Package metadata directory $metadata_dir doesn't exist; run Pkg.init() to initialize it.")) end - Base.cd(()->f(args...; kws...), dir) + if haskey(ENV,"JULIA_PKGDIR") + withenv("JULIA_PKGDIR" => abspath(ENV["JULIA_PKGDIR"])) do + Base.cd(()->f(args...; kws...), dir) + end + else + Base.cd(()->f(args...; kws...), dir) + end end function init(meta::AbstractString=DEFAULT_META, branch::AbstractString=META_BRANCH) diff --git a/test/pkg.jl b/test/pkg.jl index 357152eeb4b96..4679d179fb990 100644 --- a/test/pkg.jl +++ b/test/pkg.jl @@ -550,3 +550,29 @@ let io = IOBuffer() Base.showerror(io, Base.Pkg.Entry.PkgTestError("ppp"), backtrace()) @test !contains(String(take!(io)), "backtrace()") end + + +function temp_rel_pkg_dir(fn::Function, remove_tmp_dir::Bool=true) + # Used in tests below to set up and tear down a sandboxed package directory + cd(tempdir()) do + const tmpdir = randstring() + withenv("JULIA_PKGDIR" => tmpdir) do + @test !isdir(Pkg.dir()) + try + Pkg.init() + @test isdir(Pkg.dir()) + Pkg.resolve() + fn() + finally + remove_tmp_dir && rm(tmpdir, recursive=true) + end + end + end +end + +@testset "Relative path operations" begin + temp_rel_pkg_dir() do + Pkg.add("Example") + @test [keys(Pkg.installed())...] == ["Example"] + end +end From c29fc1ece97e5c7d1812dd115a0758396c7e2384 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Wed, 8 Mar 2017 13:43:35 +0000 Subject: [PATCH 0156/1534] Add octal prefix (0o) to filemode in StatStruct (#20919) * Add octal prefix (0o) to filemode in StatStruct Makes it clear it is in octal * add parsing test --- base/stat.jl | 2 +- test/file.jl | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/base/stat.jl b/base/stat.jl index d6922fc626572..3a54b213cea53 100644 --- a/base/stat.jl +++ b/base/stat.jl @@ -57,7 +57,7 @@ StatStruct(buf::Union{Vector{UInt8},Ptr{UInt8}}) = StatStruct( ccall(:jl_stat_ctime, Float64, (Ptr{UInt8},), buf), ) -show(io::IO, st::StatStruct) = print(io, "StatStruct(mode=$(oct(filemode(st),6)), size=$(filesize(st)))") +show(io::IO, st::StatStruct) = print(io, "StatStruct(mode=0o$(oct(filemode(st),6)), size=$(filesize(st)))") # stat & lstat functions diff --git a/test/file.jl b/test/file.jl index 3db007556679a..ca1429605cd25 100644 --- a/test/file.jl +++ b/test/file.jl @@ -430,6 +430,8 @@ c_stat = stat(cfile) @test a_stat.size == b_stat.size @test a_stat.size == c_stat.size +@test parse(Int,match(r"mode=(.*),",sprint(show,a_stat)).captures[1]) == a_stat.mode + close(af) rm(afile) rm(bfile) From 3334f7fd54c31cf92dda2298e90f6db5da4bc3e7 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 1 Mar 2017 16:49:44 -0500 Subject: [PATCH 0157/1534] improve ability to inline away `typeassert` and `===` this was affected by using `Const` in more cases instead of `Type{}` --- base/inference.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index ca2ca0b8c5251..8b2dba8b85bd6 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -3467,8 +3467,7 @@ struct InvokeData texpr end -function inline_as_constant(val::ANY, argexprs, sv::InferenceState, - invoke_data::ANY) +function inline_as_constant(val::ANY, argexprs, sv::InferenceState, invoke_data::ANY) if invoke_data === nothing invoke_fexpr = nothing invoke_texpr = nothing @@ -3661,8 +3660,9 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference if (f === typeassert || ft ⊑ typeof(typeassert)) && length(atypes)==3 # typeassert(x::S, T) => x, when S<:T - if isType(atypes[3]) && isleaftype(atypes[3]) && - atypes[2] ⊑ atypes[3].parameters[1] + a3 = atypes[3] + if (isType(a3) && isleaftype(a3) && atypes[2] ⊑ a3.parameters[1]) || + (isa(a3,Const) && isa(a3.val,Type) && atypes[2] ⊑ a3.val) return (argexprs[2], ()) end end @@ -3670,7 +3670,7 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference # special-case inliners for known pure functions that compute types if sv.params.inlining if isa(e.typ, Const) # || isconstType(e.typ) - if (f === apply_type || f === fieldtype || f === typeof || + if (f === apply_type || f === fieldtype || f === typeof || f === (===) || istopfunction(topmod, f, :typejoin) || istopfunction(topmod, f, :isbits) || istopfunction(topmod, f, :promote_type) || From e8c12ade3b3a2f3d43c3c8f6e96f4a33d012f7f1 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 1 Mar 2017 16:52:56 -0500 Subject: [PATCH 0158/1534] remove effect-free statements in `void_use_elim_pass!` --- base/inference.jl | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 8b2dba8b85bd6..8580b63d03a26 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -2114,7 +2114,7 @@ issubstate(a::VarState, b::VarState) = (a.typ ⊑ b.typ && a.undef <= b.undef) # in a dead branch but can be ignored when analyzing uses/liveness. is_meta_expr_head(head::Symbol) = (head === :inbounds || head === :boundscheck || head === :meta || - head === :line) + head === :line || head === :simdloop) is_meta_expr(ex::Expr) = is_meta_expr_head(ex.head) function tmerge(typea::ANY, typeb::ANY) @@ -3359,7 +3359,8 @@ function is_pure_builtin(f::ANY) f === Intrinsics.checked_srem_int || f === Intrinsics.checked_urem_int || f === Intrinsics.check_top_bit || - f === Intrinsics.sqrt_llvm) + f === Intrinsics.sqrt_llvm || + f === Intrinsics.cglobal) # cglobal throws an error for symbol-not-found return true end end @@ -3390,12 +3391,17 @@ function effect_free(e::ANY, src::CodeInfo, mod::Module, allow_volatile::Bool) return (isdefined(e.mod, e.name) && (allow_volatile || isconst(e.mod, e.name))) elseif isa(e, Symbol) return allow_volatile + elseif isa(e, Slot) + return src.slotflags[slot_id(e)] & Slot_UsedUndef == 0 elseif isa(e, Expr) e = e::Expr head = e.head if head === :static_parameter || is_meta_expr_head(head) return true end + if e.typ === Bottom + return false + end ea = e.args if head === :call if is_known_call_p(e, is_pure_builtin, src, mod) @@ -4646,7 +4652,13 @@ function void_use_elim_pass!(sv::InferenceState) elseif isa(ex, GlobalRef) ex = ex::GlobalRef return !isdefined(ex.mod, ex.name) - elseif (isa(ex, Expr) || isa(ex, GotoNode) || isa(ex, LineNumberNode) || + elseif isa(ex, Expr) + h = ex.head + if h === :return || h === :(=) || h === :gotoifnot || is_meta_expr_head(h) + return true + end + return !effect_free(ex, sv.src, sv.mod, false) + elseif (isa(ex, GotoNode) || isa(ex, LineNumberNode) || isa(ex, NewvarNode) || isa(ex, Symbol) || isa(ex, LabelNode)) # This is a list of special type handled by the compiler return true From 6d6218fa74f6b4b80956df6e1da853f98bd31a15 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 1 Mar 2017 16:55:32 -0500 Subject: [PATCH 0159/1534] add a pass to remove variables whose values are never read --- base/inference.jl | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/base/inference.jl b/base/inference.jl index 8580b63d03a26..a9a81279d993c 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -4505,6 +4505,37 @@ function is_known_call_p(e::Expr, pred::ANY, src::CodeInfo, mod::Module) return (isa(f, Const) && pred(f.val)) || (isType(f) && pred(f.parameters[1])) end +function record_used(e::ANY, T::ANY, used::Vector{Bool}) + if isa(e,T) + used[e.id+1] = true + elseif isa(e,Expr) + i0 = e.head === :(=) ? 2 : 1 + for i = i0:length(e.args) + record_used(e.args[i], T, used) + end + end +end + +function remove_unused_vars!(src::CodeInfo) + used = fill(false, length(src.slotnames)+1) + used_ssa = fill(false, length(src.ssavaluetypes)+1) + for i = 1:length(src.code) + record_used(src.code[i], Slot, used) + record_used(src.code[i], SSAValue, used_ssa) + end + for i = 1:length(src.code) + e = src.code[i] + if isa(e,NewvarNode) && !used[e.slot.id+1] + src.code[i] = nothing + elseif isa(e,Expr) && e.head === :(=) + if (isa(e.args[1],Slot) && !used[e.args[1].id+1]) || + (isa(e.args[1],SSAValue) && !used_ssa[e.args[1].id+1]) + src.code[i] = e.args[2] + end + end + end +end + function delete_var!(src::CodeInfo, id, T) filter!(x->!(isa(x,Expr) && (x.head === :(=) || x.head === :const) && isa(x.args[1],T) && x.args[1].id == id), @@ -5038,6 +5069,7 @@ function alloc_elim_pass!(sv::InferenceState) vs, gs = find_sa_vars(sv.src, sv.nargs) remove_redundant_temp_vars(sv.src, sv.nargs, vs, Slot) remove_redundant_temp_vars(sv.src, sv.nargs, gs, SSAValue) + remove_unused_vars!(sv.src) i = 1 while i < length(body) e = body[i] From c703c4dd63621e51389ea6e4d0a5ef90dcf7ee57 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 1 Mar 2017 17:00:14 -0500 Subject: [PATCH 0160/1534] overhaul `remove_redundant_temp_vars` pass to remove more variables --- base/inference.jl | 119 +++++++++++++++++++++++++++++----------------- 1 file changed, 75 insertions(+), 44 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index a9a81279d993c..ad52c02a2efcb 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -4536,62 +4536,90 @@ function remove_unused_vars!(src::CodeInfo) end end -function delete_var!(src::CodeInfo, id, T) +var_matches(a::ANY, b::ANY) = false +var_matches(a::SSAValue, b::SSAValue) = a.id == b.id +var_matches(a::Slot, b::Slot) = a.id == b.id + +function delete_var!(src::CodeInfo, v::Union{Slot,SSAValue}) filter!(x->!(isa(x,Expr) && (x.head === :(=) || x.head === :const) && - isa(x.args[1],T) && x.args[1].id == id), + var_matches(x.args[1], v)), src.code) return src end -function slot_replace!(src::CodeInfo, id::Int, rhs::ANY, T::ANY) +function slot_replace!(src::CodeInfo, v::Union{Slot,SSAValue}, rhs::ANY) for i = 1:length(src.code) - src.code[i] = _slot_replace!(src.code[i], id, rhs, T) + src.code[i] = _slot_replace!(src.code[i], v, rhs) end return src end -function _slot_replace!(e, id::Int, rhs::ANY, T::ANY) - if isa(e,T) && e.id == id +function _slot_replace!(e::ANY, v::Union{Slot,SSAValue}, rhs::ANY) + if var_matches(e, v) return rhs end if isa(e,Expr) for i = 1:length(e.args) - e.args[i] = _slot_replace!(e.args[i], id, rhs, T) + e.args[i] = _slot_replace!(e.args[i], v, rhs) end end return e end -occurs_undef(var::Int, expr, flags) = - flags[var] & Slot_UsedUndef != 0 && occurs_more(expr, e -> (isa(e, Slot) && slot_id(e) == var), 0) > 0 - is_argument(nargs::Int, v::Slot) = slot_id(v) <= nargs +normslot(s::SlotNumber) = s +normslot(s::TypedSlot) = SlotNumber(slot_id(s)) + +# given a single-assigned var and its initializer `init`, return what we can +# replace `var` with, or `var` itself if we shouldn't replace it +function get_replacement(table, var::Union{SlotNumber, SSAValue}, init::ANY, nargs, slottypes, ssavaluetypes) + #if isa(init, QuoteNode) # this can cause slight code size increases + # return init + if isa(init, Expr) && init.head === :static_parameter + return init + elseif isa(init, Slot) && is_argument(nargs, init::Slot) + # the transformation is not ideal if the assignment + # is present for the auto-unbox functionality + # (from inlining improved type inference information) + # and this transformation would worsen the type information + # everywhere later in the function + ityp = isa(init, TypedSlot) ? init.typ : slottypes[(init::SlotNumber).id] + if ityp ⊑ (isa(var,SSAValue) ? ssavaluetypes[var.id + 1] : slottypes[var.id]) + return init + end + elseif isa(init, SSAValue) + if haskey(table, init) + return get_replacement(table, init, table[init], nargs, slottypes, ssavaluetypes) + end + return init + elseif isa(init, SlotNumber) && haskey(table, init) + return get_replacement(table, init, table[init], nargs, slottypes, ssavaluetypes) + elseif isa(init, TypedSlot) + sl = normslot(init) + if haskey(table, sl) + rep = get_replacement(table, sl, table[sl], nargs, slottypes, ssavaluetypes) + if isa(rep, SlotNumber) + rep = TypedSlot(rep.id, init.typ) + end + return rep + end + end + return var +end + # remove all single-assigned vars v in "v = x" where x is an argument. # "sa" is the result of find_sa_vars -# T: Slot or SSAValue -function remove_redundant_temp_vars(src::CodeInfo, nargs::Int, sa, T) +function remove_redundant_temp_vars!(src::CodeInfo, nargs::Int, sa) flags = src.slotflags - ssavalue_types = src.ssavaluetypes - bexpr = Expr(:block) - bexpr.args = src.code + slottypes = src.slottypes + ssavaluetypes = src.ssavaluetypes for (v, init) in sa - if isa(init, Slot) && is_argument(nargs, init::Slot) - # this transformation is not valid for vars used before def. - # we need to preserve the point of assignment to know where to - # throw errors (issue #4645). - if T === SSAValue || !occurs_undef(v, bexpr, flags) - # the transformation is not ideal if the assignment - # is present for the auto-unbox functionality - # (from inlining improved type inference information) - # and this transformation would worsen the type information - # everywhere later in the function - ityp = isa(init, TypedSlot) ? init.typ : src.slottypes[(init::SlotNumber).id] - if ityp ⊑ (T === SSAValue ? ssavalue_types[v + 1] : src.slottypes[v]) - delete_var!(src, v, T) - slot_replace!(src, v, init, T) - end - end + repl = get_replacement(sa, v, init, nargs, slottypes, ssavaluetypes) + compare = isa(repl,TypedSlot) ? normslot(repl) : repl + if compare !== v + delete_var!(src, v) + slot_replace!(src, v, repl) end end return src @@ -4602,27 +4630,31 @@ function find_sa_vars(src::CodeInfo, nargs::Int) body = src.code av = ObjectIdDict() av2 = ObjectIdDict() - gss = ObjectIdDict() for i = 1:length(body) e = body[i] if isa(e,Expr) && e.head === :(=) lhs = e.args[1] if isa(lhs, SSAValue) - gss[lhs.id] = e.args[2] + av[lhs] = e.args[2] elseif isa(lhs, Slot) - id = slot_id(lhs) - if id > nargs # exclude args - if !haskey(av, id) - av[id] = e.args[2] + lhs = normslot(lhs) + id = lhs.id + # exclude args and used undef vars + # this transformation is not valid for vars used before def. + # we need to preserve the point of assignment to know where to + # throw errors (issue #4645). + if id > nargs && (src.slotflags[id] & Slot_UsedUndef == 0) + if !haskey(av, lhs) + av[lhs] = e.args[2] else - av2[id] = true + av2[lhs] = true end end end end end - filter!((id, _) -> !haskey(av2, id), av) - return (av, gss) + filter!((v, _) -> !haskey(av2, v), av) + return av end symequal(x::SSAValue, y::SSAValue) = x.id === y.id @@ -5066,9 +5098,8 @@ function alloc_elim_pass!(sv::InferenceState) body = sv.src.code bexpr = Expr(:block) bexpr.args = body - vs, gs = find_sa_vars(sv.src, sv.nargs) - remove_redundant_temp_vars(sv.src, sv.nargs, vs, Slot) - remove_redundant_temp_vars(sv.src, sv.nargs, gs, SSAValue) + vs = find_sa_vars(sv.src, sv.nargs) + remove_redundant_temp_vars!(sv.src, sv.nargs, vs) remove_unused_vars!(sv.src) i = 1 while i < length(body) @@ -5079,7 +5110,7 @@ function alloc_elim_pass!(sv::InferenceState) end e = e::Expr if e.head === :(=) && (isa(e.args[1], SSAValue) || - (isa(e.args[1], Slot) && haskey(vs, slot_id(e.args[1])))) + (isa(e.args[1], Slot) && haskey(vs, normslot(e.args[1])))) var = e.args[1] rhs = e.args[2] # Need to make sure LLVM can recognize this as LLVM ssa value too From 763f36c6780f74a81196a50d7a79b0f236e22cef Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 8 Mar 2017 01:49:32 -0500 Subject: [PATCH 0161/1534] add an inlining heuristic that helps avoid allocations don't inline into a function `f` if doing so would put it over the inlining threshhold, and if inlining `f` itself would help avoid tuple allocations. so far this is only used on `promote`, to limit the effects as much as possible. --- base/inference.jl | 154 +++++++++++++++++++++++++--------------------- 1 file changed, 85 insertions(+), 69 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index ad52c02a2efcb..298a84d679dab 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -2875,9 +2875,7 @@ function isinlineable(m::Method, src::CodeInfo) end end if !inlineable - body = Expr(:block) - body.args = src.code - inlineable = inline_worthy(body, cost) + inlineable = inline_worthy_stmts(src.code, cost) end return inlineable end @@ -3661,7 +3659,10 @@ end # static parameters are ok if all the static parameter values are leaf types, # meaning they are fully known. # `ft` is the type of the function. `f` is the exact function if known, or else `nothing`. -function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::InferenceState) +# `pending_stmts` is an array of statements from functions inlined so far, so +# we can estimate the total size of the enclosing function after inlining. +function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::InferenceState, + pending_stmts) argexprs = e.args if (f === typeassert || ft ⊑ typeof(typeassert)) && length(atypes)==3 @@ -3932,6 +3933,34 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference invoke_data) end + if !isa(ast, Array{Any,1}) + ast = ccall(:jl_uncompress_ast, Any, (Any, Any), method, ast) + else + ast = copy_exprargs(ast) + end + ast = ast::Array{Any,1} + + # `promote` is a tuple-returning function that is very important to inline + if isdefined(Main, :Base) && isdefined(Main.Base, :promote) && + length(sv.src.slottypes) > 0 && sv.src.slottypes[1] ⊑ typeof(getfield(Main.Base, :promote)) + # check for non-isbits Tuple return + if sv.bestguess ⊑ Tuple && !isbits(widenconst(sv.bestguess)) + # See if inlining this call would change the enclosing function + # from inlineable to not inlineable. + # This heuristic is applied to functions that return non-bits + # tuples, since we want to be able to inline those functions to + # avoid the tuple allocation. + current_stmts = vcat(sv.src.code, pending_stmts) + if inline_worthy_stmts(current_stmts) + append!(current_stmts, ast) + if !inline_worthy_stmts(current_stmts) + return invoke_NF(argexprs0, e.typ, atypes, sv, atype_unlimited, + invoke_data) + end + end + end + end + # create the backedge if isa(frame, InferenceState) && !frame.inferred && frame.cached # in this case, the actual backedge linfo hasn't been computed @@ -3954,13 +3983,6 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference nm = length(unwrap_unionall(metharg).parameters) - if !isa(ast, Array{Any,1}) - ast = ccall(:jl_uncompress_ast, Any, (Any, Any), method, ast) - else - ast = copy_exprargs(ast) - end - ast = ast::Array{Any,1} - body = Expr(:block) body.args = ast propagate_inbounds = src.propagate_inbounds @@ -4187,10 +4209,13 @@ function inline_ignore(ex::ANY) return isa(ex, Expr) && is_meta_expr(ex::Expr) end +function inline_worthy_stmts(stmts::Vector{Any}, cost::Integer = 1000) + body = Expr(:block) + body.args = stmts + return inline_worthy(body, cost) +end + function inline_worthy(body::Expr, cost::Integer=1000) # precondition: 0 < cost; nominal cost = 1000 - if popmeta!(body, :noinline)[1] - return false - end symlim = 1000 + 5_000_000 ÷ cost nstmt = 0 for stmt in body.args @@ -4238,17 +4263,15 @@ end function inlining_pass!(sv::InferenceState) eargs = sv.src.code i = 1 + stmtbuf = [] while i <= length(eargs) ei = eargs[i] if isa(ei, Expr) - res = inlining_pass(ei, sv) - eargs[i] = res[1] - if isa(res[2], Array) - sts = res[2]::Array{Any,1} - for j = 1:length(sts) - insert!(eargs, i, sts[j]) - i += 1 - end + eargs[i] = inlining_pass(ei, sv, stmtbuf, 1) + if !isempty(stmtbuf) + splice!(eargs, i:i-1, stmtbuf) + i += length(stmtbuf) + empty!(stmtbuf) end end i += 1 @@ -4257,16 +4280,17 @@ end const corenumtype = Union{Int32, Int64, Float32, Float64} -function inlining_pass(e::Expr, sv::InferenceState) +# return inlined replacement for `e`, inserting new needed statements +# at index `ins` in `stmts`. +function inlining_pass(e::Expr, sv::InferenceState, stmts, ins) if e.head === :method # avoid running the inlining pass on function definitions - return (e, ()) + return e end eargs = e.args if length(eargs) < 1 - return (e, ()) + return e end - stmts = [] arg1 = eargs[1] isccall = false i0 = 1 @@ -4281,6 +4305,7 @@ function inlining_pass(e::Expr, sv::InferenceState) i0 = 5 end has_stmts = false # needed to preserve order-of-execution + prev_stmts_length = length(stmts) for _i = length(eargs):-1:i0 if isccall && _i == 3 i = 1 @@ -4303,40 +4328,33 @@ function inlining_pass(e::Expr, sv::InferenceState) else argloc = eargs end - res = inlining_pass(ei, sv) - res1 = res[1] - res2 = res[2] - has_new_stmts = isa(res2, Array) && !isempty(res2::Array{Any,1}) + sl0 = length(stmts) + res = inlining_pass(ei, sv, stmts, ins) + ns = length(stmts) - sl0 # number of new statements just added if isccallee - restype = exprtype(res1, sv.src, sv.mod) + restype = exprtype(res, sv.src, sv.mod) if isa(restype, Const) argloc[i] = restype.val - if !effect_free(res1, sv.src, sv.mod, false) - insert!(stmts, 1, res1) - end - if has_new_stmts - prepend!(stmts, res2::Array{Any,1}) + if !effect_free(res, sv.src, sv.mod, false) + insert!(stmts, ins+ns, res) end # Assume this is the last argument to process break end end - if has_stmts && !effect_free(res1, sv.src, sv.mod, false) - restype = exprtype(res1, sv.src, sv.mod) + if has_stmts && !effect_free(res, sv.src, sv.mod, false) + restype = exprtype(res, sv.src, sv.mod) vnew = newvar!(sv, restype) argloc[i] = vnew - unshift!(stmts, Expr(:(=), vnew, res1)) + insert!(stmts, ins+ns, Expr(:(=), vnew, res)) else - argloc[i] = res1 - end - if has_new_stmts - res2 = res2::Array{Any,1} - prepend!(stmts, res2) - if !has_stmts && !(_i == i0) - for stmt in res2 - if !effect_free(stmt, sv.src, sv.mod, true) - has_stmts = true - end + argloc[i] = res + end + if !has_stmts && ns > 0 && !(_i == i0) + for s = ins:ins+ns-1 + stmt = stmts[s] + if !effect_free(stmt, sv.src, sv.mod, true) + has_stmts = true; break end end end @@ -4351,7 +4369,7 @@ function inlining_pass(e::Expr, sv::InferenceState) end end if e.head !== :call - return (e, stmts) + return e end ft = exprtype(arg1, sv.src, sv.mod) @@ -4363,10 +4381,12 @@ function inlining_pass(e::Expr, sv::InferenceState) else f = nothing if !( isleaftype(ft) || ft<:Type ) - return (e, stmts) + return e end end + ins += (length(stmts) - prev_stmts_length) + if sv.params.inlining if isdefined(Main, :Base) && ((isdefined(Main.Base, :^) && f === Main.Base.:^) || @@ -4390,19 +4410,13 @@ function inlining_pass(e::Expr, sv::InferenceState) exprtype(a1, sv.src, sv.mod) ⊑ basenumtype) if square e.args = Any[GlobalRef(Main.Base,:*), a1, a1] - res = inlining_pass(e, sv) + res = inlining_pass(e, sv, stmts, ins) else e.args = Any[GlobalRef(Main.Base,:*), Expr(:call, GlobalRef(Main.Base,:*), a1, a1), a1] e.args[2].typ = e.typ - res = inlining_pass(e, sv) - end - if isa(res, Tuple) - if isa(res[2], Array) && !isempty(res[2]) - append!(stmts, res[2]) - end - res = res[1] + res = inlining_pass(e, sv, stmts, ins) end - return (res, stmts) + return res end end end @@ -4413,13 +4427,14 @@ function inlining_pass(e::Expr, sv::InferenceState) ata[1] = ft for i = 2:length(e.args) a = exprtype(e.args[i], sv.src, sv.mod) - (a === Bottom || isvarargtype(a)) && return (e, stmts) + (a === Bottom || isvarargtype(a)) && return e ata[i] = a end - res = inlineable(f, ft, e, ata, sv) + res = inlineable(f, ft, e, ata, sv, stmts) if isa(res,Tuple) if isa(res[2],Array) && !isempty(res[2]) - append!(stmts,res[2]) + splice!(stmts, ins:ins-1, res[2]) + ins += length(res[2]) end res = res[1] end @@ -4431,7 +4446,7 @@ function inlining_pass(e::Expr, sv::InferenceState) e = res::Expr f = _apply; ft = abstract_eval_constant(f) else - return (res,stmts) + return res end end @@ -4453,7 +4468,7 @@ function inlining_pass(e::Expr, sv::InferenceState) newargs[i-2] = Any[ mk_getfield(aarg,j,tp[j]) for j=1:length(tp) ] else # not all args expandable - return (e,stmts) + return e end end e.args = [Any[e.args[2]]; newargs...] @@ -4468,14 +4483,14 @@ function inlining_pass(e::Expr, sv::InferenceState) else f = nothing if !( isleaftype(ft) || ft<:Type ) - return (e,stmts) + return e end end else - return (e,stmts) + return e end end - return (e,stmts) + return e end const compiler_temp_sym = Symbol("#temp#") @@ -4576,7 +4591,8 @@ normslot(s::TypedSlot) = SlotNumber(slot_id(s)) function get_replacement(table, var::Union{SlotNumber, SSAValue}, init::ANY, nargs, slottypes, ssavaluetypes) #if isa(init, QuoteNode) # this can cause slight code size increases # return init - if isa(init, Expr) && init.head === :static_parameter + if (isa(init, Expr) && init.head === :static_parameter) || isa(init, corenumtype) || + init === () || init === nothing return init elseif isa(init, Slot) && is_argument(nargs, init::Slot) # the transformation is not ideal if the assignment From dcec46711d3c642b8e4b77ddd5bc67145c57f7a4 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Mon, 6 Mar 2017 17:13:15 -0500 Subject: [PATCH 0162/1534] Take thread count into account in max collection interval --- src/gc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gc.c b/src/gc.c index 2b5e61f57d10f..f23a3a8de3608 100644 --- a/src/gc.c +++ b/src/gc.c @@ -2099,8 +2099,8 @@ void jl_gc_init(void) gc_num.allocd = -default_collect_interval; #ifdef _P64 - // on a big memory machine, set max_collect_interval to totalmem/ncores/2 - size_t maxmem = (uv_get_total_memory()/jl_cpu_cores())/2; + // on a big memory machine, set max_collect_interval to totalmem * nthreads / ncores / 2 + size_t maxmem = (uv_get_total_memory() * jl_n_threads) / jl_cpu_cores() / 2; if (maxmem > max_collect_interval) max_collect_interval = maxmem; #endif From ebf675b50a16812c4a0b8b248eae0ac883d6999c Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Wed, 8 Mar 2017 18:45:09 +0000 Subject: [PATCH 0163/1534] remove fastmath version of mod (#20859) --- base/fastmath.jl | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/base/fastmath.jl b/base/fastmath.jl index 33c6b9884a7ac..7d51eba54a6d4 100644 --- a/base/fastmath.jl +++ b/base/fastmath.jl @@ -42,7 +42,6 @@ const fast_op = :cmp => :cmp_fast, :conj => :conj_fast, :inv => :inv_fast, - :mod => :mod_fast, :rem => :rem_fast, :sign => :sign_fast, :isfinite => :isfinite_fast, @@ -148,10 +147,6 @@ mul_fast{T<:FloatTypes}(x::T, y::T, zs::T...) = @fastmath begin cmp_fast{T<:FloatTypes}(x::T, y::T) = ifelse(x==y, 0, ifelse(x 0) ⊻ (y > 0), r+y, r) - end end eq_fast{T<:FloatTypes}(x::T, y::T) = eq_float_fast(x, y) @@ -225,7 +220,7 @@ for op in (:abs, :abs2, :conj, :inv, :sign) end end -for op in (:+, :-, :*, :/, :(==), :!=, :<, :<=, :cmp, :mod, :rem) +for op in (:+, :-, :*, :/, :(==), :!=, :<, :<=, :cmp, :rem) op_fast = fast_op[op] @eval begin # fall-back implementation for non-numeric types From 1d678da21c5b504dc06cb5bffe2478cab301066d Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Wed, 8 Mar 2017 10:07:19 -0800 Subject: [PATCH 0164/1534] Identify `ppc64le` as a 64-bit architecture --- Make.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/Make.inc b/Make.inc index 14c79c7e1c5de..ffc1bde03162c 100644 --- a/Make.inc +++ b/Make.inc @@ -660,6 +660,7 @@ ifneq (,$(filter $(ARCH), powerpc64le ppc64le)) JCFLAGS += -fsigned-char OPENBLAS_DYNAMIC_ARCH:=0 OPENBLAS_TARGET_ARCH:=POWER8 +BINARY:=64 # GCC doesn't do -march= on ppc64le MARCH= endif From ef49fcb22025a50de51f46aaea6667eee2a2452c Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Wed, 8 Mar 2017 11:38:33 -0600 Subject: [PATCH 0165/1534] Improve docs for copy! --- base/docs/helpdb/Base.jl | 7 ------- base/multidimensional.jl | 25 +++++++++++++++++++++++++ doc/src/stdlib/arrays.md | 1 + 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/base/docs/helpdb/Base.jl b/base/docs/helpdb/Base.jl index d725d54390b6d..d5f9000b947be 100644 --- a/base/docs/helpdb/Base.jl +++ b/base/docs/helpdb/Base.jl @@ -2027,13 +2027,6 @@ algorithms. See [`muladd`](@ref). """ fma -""" - copy!(dest, src) - -Copy all elements from collection `src` to array `dest`. Returns `dest`. -""" -copy!(dest,src) - """ copy!(dest, do, src, so, N) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 6e0b8a567b57f..f6a6814351f86 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -209,6 +209,16 @@ module IteratorsMD @inline _split{N}(tN::NTuple{N,Any}, ::Tuple{}, ::Type{Val{N}}) = tN, () # ambig. @inline _split{N}(tN, ::Tuple{}, ::Type{Val{N}}) = tN, () @inline _split{N}(tN::NTuple{N,Any}, trest, ::Type{Val{N}}) = tN, trest + + @inline function split(I::CartesianIndex, V::Type{<:Val}) + i, j = split(I.I, V) + CartesianIndex(i), CartesianIndex(j) + end + function split(R::CartesianRange, V::Type{<:Val}) + istart, jstart = split(first(R), V) + istop, jstop = split(last(R), V) + CartesianRange(istart, istop), CartesianRange(jstart, jstop) + end end # IteratorsMD @@ -781,6 +791,13 @@ function fill!{T}(A::AbstractArray{T}, x) A end +""" + copy!(dest, src) -> dest + +Copy all elements from collection `src` to array `dest`. +""" +copy!(dest, src) + function copy!{T,N}(dest::AbstractArray{T,N}, src::AbstractArray{T,N}) @boundscheck checkbounds(dest, indices(src)...) for I in eachindex(IndexStyle(src,dest), src) @@ -805,6 +822,14 @@ function copy!(dest::AbstractArray, Rdest::CartesianRange, src::AbstractArray, R dest end +""" + copy!(dest, Rdest::CartesianRange, src, Rsrc::CartesianRange) -> dest + +Copy the block of `src` in the range of `Rsrc` to the block of `dest` +in the range of `Rdest`. The sizes of the two regions must match. +""" +copy!(::AbstractArray, ::CartesianRange, ::AbstractArray, ::CartesianRange) + # circshift! circshift!(dest::AbstractArray, src, ::Tuple{}) = copy!(dest, src) """ diff --git a/doc/src/stdlib/arrays.md b/doc/src/stdlib/arrays.md index 0e097e7bb71a7..87c06ac591ebb 100644 --- a/doc/src/stdlib/arrays.md +++ b/doc/src/stdlib/arrays.md @@ -61,6 +61,7 @@ Base.Broadcast.broadcast_setindex! ```@docs Base.getindex(::AbstractArray, ::Any...) Base.setindex!(::AbstractArray, ::Any, ::Any...) +Base.copy!(::AbstractArray, ::CartesianRange, ::AbstractArray, ::CartesianRange) Base.isassigned Base.Colon Base.CartesianIndex From 810cade782d58217ac1c422d52e7bd7c952c0738 Mon Sep 17 00:00:00 2001 From: JKrehl Date: Wed, 8 Mar 2017 11:43:47 -0600 Subject: [PATCH 0166/1534] Speed up copy!(dest, Rdest, src, Rsrc) for CartesianRange inputs --- base/multidimensional.jl | 33 ++++++++++++++++++++------------- test/copy.jl | 15 ++++++++++++++- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index f6a6814351f86..8c5ce2ad155fd 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -806,20 +806,27 @@ function copy!{T,N}(dest::AbstractArray{T,N}, src::AbstractArray{T,N}) dest end -function copy!(dest::AbstractArray, Rdest::CartesianRange, src::AbstractArray, Rsrc::CartesianRange) - isempty(Rdest) && return dest - if size(Rdest) != size(Rsrc) - throw(ArgumentError("source and destination must have same size (got $(size(Rsrc)) and $(size(Rdest)))")) - end - @boundscheck checkbounds(dest, Rdest.start) - @boundscheck checkbounds(dest, Rdest.stop) - @boundscheck checkbounds(src, Rsrc.start) - @boundscheck checkbounds(src, Rsrc.stop) - deltaI = Rdest.start - Rsrc.start - for I in Rsrc - @inbounds dest[I+deltaI] = src[I] +@generated function copy!{T1,T2,N}(dest::AbstractArray{T1,N}, + Rdest::CartesianRange{CartesianIndex{N}}, + src::AbstractArray{T2,N}, + Rsrc::CartesianRange{CartesianIndex{N}}) + quote + isempty(Rdest) && return dest + if size(Rdest) != size(Rsrc) + throw(ArgumentError("source and destination must have same size (got $(size(Rsrc)) and $(size(Rdest)))")) + end + @boundscheck checkbounds(dest, Rdest.start) + @boundscheck checkbounds(dest, Rdest.stop) + @boundscheck checkbounds(src, Rsrc.start) + @boundscheck checkbounds(src, Rsrc.stop) + ΔI = Rdest.start - Rsrc.start + # for I in Rsrc + # @inbounds dest[I+ΔI] = src[I] + @nloops $N i (n->Rsrc.start[n]:Rsrc.stop[n]) begin + @inbounds @nref($N,dest,n->i_n+ΔI[n]) = @nref($N,src,i) + end + dest end - dest end """ diff --git a/test/copy.jl b/test/copy.jl index 015e3b3e507bf..2e48fc9912afe 100644 --- a/test/copy.jl +++ b/test/copy.jl @@ -48,6 +48,20 @@ for (dest, src, bigsrc, emptysrc, res) in [ @test_throws BoundsError copy!(dest, 1, src(), 2, 2) end +let A = reshape(1:6, 3, 2), B = similar(A) + RA = CartesianRange(indices(A)) + copy!(B, RA, A, RA) + @test B == A +end +let A = reshape(1:6, 3, 2), B = zeros(8,8) + RA = CartesianRange(indices(A)) + copy!(B, CartesianRange((5:7,2:3)), A, RA) + @test B[5:7,2:3] == A + B[5:7,2:3] = 0 + @test all(x->x==0, B) +end + + # test behavior of shallow and deep copying let a = Any[[1]], q = QuoteNode([1]) ca = copy(a); dca = @inferred(deepcopy(a)) @@ -128,4 +142,3 @@ end @test bar2.fooDict[bar2.foo] != nothing end end - From 9ceb52b14fb5f2ed7e165e31bcd3933703e505c5 Mon Sep 17 00:00:00 2001 From: JKrehl Date: Wed, 8 Mar 2017 11:06:22 -0600 Subject: [PATCH 0167/1534] Force inlining on CartesianIndex operations --- base/multidimensional.jl | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 8c5ce2ad155fd..f944d114b1072 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -65,22 +65,23 @@ module IteratorsMD one{N}(::Type{CartesianIndex{N}}) = CartesianIndex(ntuple(x -> 1, Val{N})) # arithmetic, min/max - (-){N}(index::CartesianIndex{N}) = CartesianIndex{N}(map(-, index.I)) - (+){N}(index1::CartesianIndex{N}, index2::CartesianIndex{N}) = + @inline (-){N}(index::CartesianIndex{N}) = + CartesianIndex{N}(map(-, index.I)) + @inline (+){N}(index1::CartesianIndex{N}, index2::CartesianIndex{N}) = CartesianIndex{N}(map(+, index1.I, index2.I)) - (-){N}(index1::CartesianIndex{N}, index2::CartesianIndex{N}) = + @inline (-){N}(index1::CartesianIndex{N}, index2::CartesianIndex{N}) = CartesianIndex{N}(map(-, index1.I, index2.I)) - min{N}(index1::CartesianIndex{N}, index2::CartesianIndex{N}) = + @inline min{N}(index1::CartesianIndex{N}, index2::CartesianIndex{N}) = CartesianIndex{N}(map(min, index1.I, index2.I)) - max{N}(index1::CartesianIndex{N}, index2::CartesianIndex{N}) = + @inline max{N}(index1::CartesianIndex{N}, index2::CartesianIndex{N}) = CartesianIndex{N}(map(max, index1.I, index2.I)) - (+)(i::Integer, index::CartesianIndex) = index+i - (+){N}(index::CartesianIndex{N}, i::Integer) = CartesianIndex{N}(map(x->x+i, index.I)) - (-){N}(index::CartesianIndex{N}, i::Integer) = CartesianIndex{N}(map(x->x-i, index.I)) - (-){N}(i::Integer, index::CartesianIndex{N}) = CartesianIndex{N}(map(x->i-x, index.I)) - (*){N}(a::Integer, index::CartesianIndex{N}) = CartesianIndex{N}(map(x->a*x, index.I)) - (*)(index::CartesianIndex,a::Integer)=*(a,index) + @inline (+)(i::Integer, index::CartesianIndex) = index+i + @inline (+){N}(index::CartesianIndex{N}, i::Integer) = CartesianIndex{N}(map(x->x+i, index.I)) + @inline (-){N}(index::CartesianIndex{N}, i::Integer) = CartesianIndex{N}(map(x->x-i, index.I)) + @inline (-){N}(i::Integer, index::CartesianIndex{N}) = CartesianIndex{N}(map(x->i-x, index.I)) + @inline (*){N}(a::Integer, index::CartesianIndex{N}) = CartesianIndex{N}(map(x->a*x, index.I)) + @inline (*)(index::CartesianIndex,a::Integer)=*(a,index) # comparison @inline isless{N}(I1::CartesianIndex{N}, I2::CartesianIndex{N}) = _isless(0, I1.I, I2.I) From ade58878fa4ea8943bb32e17881305a7e6716288 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Wed, 8 Mar 2017 11:29:34 -0800 Subject: [PATCH 0168/1534] Always include FFTW docstrings, even when USE_GPL_LIBS=0 (#20941) --- base/dft.jl | 223 +++++++++++++++++++++++++++++++++++++++-------- base/fft/FFTW.jl | 80 +---------------- base/fft/dct.jl | 73 ---------------- 3 files changed, 188 insertions(+), 188 deletions(-) diff --git a/base/dft.jl b/base/dft.jl index bbef1f433e550..e846ff54f335c 100644 --- a/base/dft.jl +++ b/base/dft.jl @@ -398,45 +398,194 @@ end ############################################################################## # FFTW module (may move to an external package at some point): -if Base.USE_GPL_LIBS - @doc """ - fft(A [, dims]) - - Performs a multidimensional FFT of the array `A`. The optional `dims` argument specifies an - iterable subset of dimensions (e.g. an integer, range, tuple, or array) to transform along. - Most efficient if the size of `A` along the transformed dimensions is a product of small - primes; see `nextprod()`. See also `plan_fft()` for even greater efficiency. - - A one-dimensional FFT computes the one-dimensional discrete Fourier transform (DFT) as - defined by - - ```math - \\operatorname{DFT}(A)[k] = - \\sum_{n=1}^{\\operatorname{length}(A)} - \\exp\\left(-i\\frac{2\\pi - (n-1)(k-1)}{\\operatorname{length}(A)} \\right) A[n]. - ``` - - A multidimensional FFT simply performs this operation along each transformed dimension of `A`. - - !!! note - * Julia starts FFTW up with 1 thread by default. Higher performance is usually possible by - increasing number of threads. Use `FFTW.set_num_threads(Sys.CPU_CORES)` to use as many - threads as cores on your system. - - * This performs a multidimensional FFT by default. FFT libraries in other languages such as - Python and Octave perform a one-dimensional FFT along the first non-singleton dimension - of the array. This is worth noting while performing comparisons. For more details, - refer to the [Noteworthy Differences from other Languages](@ref) - section of the manual. - """ -> - fft - - include("fft/FFTW.jl") - importall .FFTW - export FFTW, dct, idct, dct!, idct!, plan_dct, plan_idct, plan_dct!, plan_idct! +""" + fft(A [, dims]) + +Performs a multidimensional FFT of the array `A`. The optional `dims` argument specifies an +iterable subset of dimensions (e.g. an integer, range, tuple, or array) to transform along. +Most efficient if the size of `A` along the transformed dimensions is a product of small +primes; see `nextprod()`. See also `plan_fft()` for even greater efficiency. + +A one-dimensional FFT computes the one-dimensional discrete Fourier transform (DFT) as +defined by + +```math +\\operatorname{DFT}(A)[k] = + \\sum_{n=1}^{\\operatorname{length}(A)} + \\exp\\left(-i\\frac{2\\pi + (n-1)(k-1)}{\\operatorname{length}(A)} \\right) A[n]. +``` + +A multidimensional FFT simply performs this operation along each transformed dimension of `A`. + +!!! note + * Julia starts FFTW up with 1 thread by default. Higher performance is usually possible by + increasing number of threads. Use `FFTW.set_num_threads(Sys.CPU_CORES)` to use as many + threads as cores on your system. + + * This performs a multidimensional FFT by default. FFT libraries in other languages such as + Python and Octave perform a one-dimensional FFT along the first non-singleton dimension + of the array. This is worth noting while performing comparisons. For more details, + refer to the [Noteworthy Differences from other Languages](@ref) + section of the manual. +""" +fft + +""" + plan_rfft(A [, dims]; flags=FFTW.ESTIMATE; timelimit=Inf) + +Pre-plan an optimized real-input FFT, similar to [`plan_fft`](@ref) except for +[`rfft`](@ref) instead of [`fft`](@ref). The first two arguments, and the +size of the transformed result, are the same as for [`rfft`](@ref). +""" +plan_rfft + +""" + plan_brfft(A, d [, dims]; flags=FFTW.ESTIMATE; timelimit=Inf) + +Pre-plan an optimized real-input unnormalized transform, similar to +[`plan_rfft`](@ref) except for [`brfft`](@ref) instead of +[`rfft`](@ref). The first two arguments and the size of the transformed result, are +the same as for [`brfft`](@ref). +""" +plan_brfft + +module FFTW + import ..DFT: fft, bfft, ifft, rfft, brfft, irfft, plan_fft, plan_bfft, plan_ifft, + plan_rfft, plan_brfft, plan_irfft, fft!, bfft!, ifft!, plan_fft!, plan_bfft!, plan_ifft!, + Plan, rfft_output_size, brfft_output_size, plan_inv, normalization, ScaledPlan + + export r2r, r2r!, plan_r2r, plan_r2r! + + """ + plan_dct!(A [, dims [, flags [, timelimit]]]) + + Same as [`plan_dct`](@ref), but operates in-place on `A`. + """ + function plan_dct! end + + """ + plan_idct(A [, dims [, flags [, timelimit]]]) + + Pre-plan an optimized inverse discrete cosine transform (DCT), similar to + [`plan_fft`](@ref) except producing a function that computes + [`idct`](@ref). The first two arguments have the same meaning as for + [`idct`](@ref). + """ + function plan_idct end + + """ + plan_dct(A [, dims [, flags [, timelimit]]]) + + Pre-plan an optimized discrete cosine transform (DCT), similar to + [`plan_fft`](@ref) except producing a function that computes + [`dct`](@ref). The first two arguments have the same meaning as for + [`dct`](@ref). + """ + function plan_dct end + + """ + plan_idct!(A [, dims [, flags [, timelimit]]]) + + Same as [`plan_idct`](@ref), but operates in-place on `A`. + """ + function plan_idct! end + + """ + dct(A [, dims]) + + Performs a multidimensional type-II discrete cosine transform (DCT) of the array `A`, using + the unitary normalization of the DCT. The optional `dims` argument specifies an iterable + subset of dimensions (e.g. an integer, range, tuple, or array) to transform along. Most + efficient if the size of `A` along the transformed dimensions is a product of small primes; + see [`nextprod`](@ref). See also [`plan_dct`](@ref) for even greater + efficiency. + """ + function dct end + + """ + idct(A [, dims]) + + Computes the multidimensional inverse discrete cosine transform (DCT) of the array `A` + (technically, a type-III DCT with the unitary normalization). The optional `dims` argument + specifies an iterable subset of dimensions (e.g. an integer, range, tuple, or array) to + transform along. Most efficient if the size of `A` along the transformed dimensions is a + product of small primes; see [`nextprod`](@ref). See also + [`plan_idct`](@ref) for even greater efficiency. + """ + function idct end + + """ + dct!(A [, dims]) + + Same as [`dct!`](@ref), except that it operates in-place on `A`, which must be an + array of real or complex floating-point values. + """ + function dct! end + + """ + idct!(A [, dims]) + + Same as [`idct!`](@ref), but operates in-place on `A`. + """ + function idct! end + + """ + r2r(A, kind [, dims]) + + Performs a multidimensional real-input/real-output (r2r) transform + of type `kind` of the array `A`, as defined in the FFTW manual. + `kind` specifies either a discrete cosine transform of various types + (`FFTW.REDFT00`, `FFTW.REDFT01`, `FFTW.REDFT10`, or + `FFTW.REDFT11`), a discrete sine transform of various types + (`FFTW.RODFT00`, `FFTW.RODFT01`, `FFTW.RODFT10`, or + `FFTW.RODFT11`), a real-input DFT with halfcomplex-format output + (`FFTW.R2HC` and its inverse `FFTW.HC2R`), or a discrete + Hartley transform (`FFTW.DHT`). The `kind` argument may be + an array or tuple in order to specify different transform types + along the different dimensions of `A`; `kind[end]` is used + for any unspecified dimensions. See the FFTW manual for precise + definitions of these transform types, at http://www.fftw.org/doc. + + The optional `dims` argument specifies an iterable subset of + dimensions (e.g. an integer, range, tuple, or array) to transform + along. `kind[i]` is then the transform type for `dims[i]`, + with `kind[end]` being used for `i > length(kind)`. + + See also [`plan_r2r`](@ref) to pre-plan optimized r2r transforms. + """ + function r2r end + + """ + r2r!(A, kind [, dims]) + + Same as [`r2r`](@ref), but operates in-place on `A`, which must be + an array of real or complex floating-point numbers. + """ + function r2r! end + + """ + plan_r2r!(A, kind [, dims [, flags [, timelimit]]]) + + Similar to [`plan_fft`](@ref), but corresponds to [`r2r!`](@ref). + """ + function plan_r2r! end + + """ + plan_r2r(A, kind [, dims [, flags [, timelimit]]]) + + Pre-plan an optimized r2r transform, similar to [`plan_fft`](@ref) + except that the transforms (and the first three arguments) + correspond to [`r2r`](@ref) and [`r2r!`](@ref), respectively. + """ + function plan_r2r end + + Base.USE_GPL_LIBS && include("fft/FFTW.jl") end +importall .FFTW +export FFTW, dct, idct, dct!, idct!, plan_dct, plan_idct, plan_dct!, plan_idct! + ############################################################################## end diff --git a/base/fft/FFTW.jl b/base/fft/FFTW.jl index d68e302c98a8e..6bd73247cbbe1 100644 --- a/base/fft/FFTW.jl +++ b/base/fft/FFTW.jl @@ -1,13 +1,7 @@ # This file is a part of Julia. License is MIT: http://julialang.org/license -module FFTW - -import ..DFT: fft, bfft, ifft, rfft, brfft, irfft, plan_fft, plan_bfft, plan_ifft, plan_rfft, plan_brfft, plan_irfft, fft!, bfft!, ifft!, plan_fft!, plan_bfft!, plan_ifft!, Plan, rfft_output_size, brfft_output_size, plan_inv, normalization, ScaledPlan - import Base: show, *, convert, unsafe_convert, size, strides, ndims, pointer, A_mul_B! -export r2r, r2r!, plan_r2r, plan_r2r! - export export_wisdom, import_wisdom, import_system_wisdom, forget_wisdom, MEASURE, DESTROY_INPUT, UNALIGNED, CONSERVE_MEMORY, EXHAUSTIVE, PRESERVE_INPUT, PATIENT, ESTIMATE, WISDOM_ONLY, NO_TIMELIMIT, @@ -20,7 +14,8 @@ export export_wisdom, import_wisdom, import_system_wisdom, forget_wisdom, const libfftw = Base.libfftw_name const libfftwf = Base.libfftwf_name -const version = convert(VersionNumber, split(unsafe_string(cglobal((:fftw_version,Base.DFT.FFTW.libfftw), UInt8)), ['-', ' '])[2]) +const version = convert(VersionNumber, split(unsafe_string(cglobal( + (:fftw_version,Base.DFT.FFTW.libfftw), UInt8)), ['-', ' '])[2]) ## Direction of FFT @@ -713,25 +708,6 @@ for (Tr,Tc) in ((:Float32,:Complex64),(:Float64,:Complex128)) end end -""" - plan_rfft(A [, dims]; flags=FFTW.ESTIMATE; timelimit=Inf) - -Pre-plan an optimized real-input FFT, similar to [`plan_fft`](@ref) except for -[`rfft`](@ref) instead of [`fft`](@ref). The first two arguments, and the -size of the transformed result, are the same as for [`rfft`](@ref). -""" -plan_rfft - -""" - plan_brfft(A, d [, dims]; flags=FFTW.ESTIMATE; timelimit=Inf) - -Pre-plan an optimized real-input unnormalized transform, similar to -[`plan_rfft`](@ref) except for [`brfft`](@ref) instead of -[`rfft`](@ref). The first two arguments and the size of the transformed result, are -the same as for [`brfft`](@ref). -""" -plan_brfft - # FFTW r2r transforms (low-level interface) for f in (:r2r, :r2r!) @@ -760,56 +736,6 @@ function plan_r2r!{T<:fftwNumber,N}(X::StridedArray{T,N}, kinds, region; r2rFFTWPlan{T,ANY,true,N}(X, X, region, kinds, flags, timelimit) end -""" - r2r(A, kind [, dims]) - -Performs a multidimensional real-input/real-output (r2r) transform -of type `kind` of the array `A`, as defined in the FFTW manual. -`kind` specifies either a discrete cosine transform of various types -(`FFTW.REDFT00`, `FFTW.REDFT01`, `FFTW.REDFT10`, or -`FFTW.REDFT11`), a discrete sine transform of various types -(`FFTW.RODFT00`, `FFTW.RODFT01`, `FFTW.RODFT10`, or -`FFTW.RODFT11`), a real-input DFT with halfcomplex-format output -(`FFTW.R2HC` and its inverse `FFTW.HC2R`), or a discrete -Hartley transform (`FFTW.DHT`). The `kind` argument may be -an array or tuple in order to specify different transform types -along the different dimensions of `A`; `kind[end]` is used -for any unspecified dimensions. See the FFTW manual for precise -definitions of these transform types, at http://www.fftw.org/doc. - -The optional `dims` argument specifies an iterable subset of -dimensions (e.g. an integer, range, tuple, or array) to transform -along. `kind[i]` is then the transform type for `dims[i]`, -with `kind[end]` being used for `i > length(kind)`. - -See also [`plan_r2r`](@ref) to pre-plan optimized r2r transforms. -""" -FFTW.r2r - -""" - r2r!(A, kind [, dims]) - -Same as [`r2r`](@ref), but operates in-place on `A`, which must be -an array of real or complex floating-point numbers. -""" -FFTW.r2r! - -""" - plan_r2r!(A, kind [, dims [, flags [, timelimit]]]) - -Similar to [`plan_fft`](@ref), but corresponds to [`r2r!`](@ref). -""" -FFTW.plan_r2r! - -""" - plan_r2r(A, kind [, dims [, flags [, timelimit]]]) - -Pre-plan an optimized r2r transform, similar to [`plan_fft`](@ref) -except that the transforms (and the first three arguments) -correspond to [`r2r`](@ref) and [`r2r!`](@ref), respectively. -""" -FFTW.plan_r2r - # mapping from r2r kind to the corresponding inverse transform const inv_kind = Dict{Int,Int}(R2HC => HC2R, HC2R => R2HC, DHT => DHT, REDFT00 => REDFT00, @@ -859,5 +785,3 @@ function *{T,K}(p::r2rFFTWPlan{T,K,true}, x::StridedArray{T}) end include("dct.jl") - -end # module diff --git a/base/fft/dct.jl b/base/fft/dct.jl index c5590c9623d0e..6ce51e5ab25c3 100644 --- a/base/fft/dct.jl +++ b/base/fft/dct.jl @@ -38,40 +38,6 @@ for (pf, pfr, K, inplace) in ((:plan_dct, :plan_r2r, REDFT10, false), end end -""" - plan_dct!(A [, dims [, flags [, timelimit]]]) - -Same as [`plan_dct`](@ref), but operates in-place on `A`. -""" -plan_dct! - -""" - plan_idct(A [, dims [, flags [, timelimit]]]) - -Pre-plan an optimized inverse discrete cosine transform (DCT), similar to -[`plan_fft`](@ref) except producing a function that computes -[`idct`](@ref). The first two arguments have the same meaning as for -[`idct`](@ref). -""" -plan_idct - -""" - plan_dct(A [, dims [, flags [, timelimit]]]) - -Pre-plan an optimized discrete cosine transform (DCT), similar to -[`plan_fft`](@ref) except producing a function that computes -[`dct`](@ref). The first two arguments have the same meaning as for -[`dct`](@ref). -""" -plan_dct - -""" - plan_idct!(A [, dims [, flags [, timelimit]]]) - -Same as [`plan_idct`](@ref), but operates in-place on `A`. -""" -plan_idct! - function plan_inv{T,K,inplace}(p::DCTPlan{T,K,inplace}) X = Array{T}(p.plan.sz) iK = inv_kind[K] @@ -93,45 +59,6 @@ for f in (:dct, :dct!, :idct, :idct!) end end -""" - dct(A [, dims]) - -Performs a multidimensional type-II discrete cosine transform (DCT) of the array `A`, using -the unitary normalization of the DCT. The optional `dims` argument specifies an iterable -subset of dimensions (e.g. an integer, range, tuple, or array) to transform along. Most -efficient if the size of `A` along the transformed dimensions is a product of small primes; -see [`nextprod`](@ref). See also [`plan_dct`](@ref) for even greater -efficiency. -""" -dct - -""" - idct(A [, dims]) - -Computes the multidimensional inverse discrete cosine transform (DCT) of the array `A` -(technically, a type-III DCT with the unitary normalization). The optional `dims` argument -specifies an iterable subset of dimensions (e.g. an integer, range, tuple, or array) to -transform along. Most efficient if the size of `A` along the transformed dimensions is a -product of small primes; see [`nextprod`](@ref). See also -[`plan_idct`](@ref) for even greater efficiency. -""" -idct - -""" - dct!(A [, dims]) - -Same as [`dct!`](@ref), except that it operates in-place on `A`, which must be an -array of real or complex floating-point values. -""" -dct! - -""" - idct!(A [, dims]) - -Same as [`idct!`](@ref), but operates in-place on `A`. -""" -idct! - const sqrthalf = sqrt(0.5) const sqrt2 = sqrt(2.0) const onerange = 1:1 From 8436f459e44532675b54ddd38b0c14ebd1dbfa01 Mon Sep 17 00:00:00 2001 From: Fengyang Wang Date: Wed, 8 Mar 2017 14:30:16 -0500 Subject: [PATCH 0169/1534] Correct an inaccuracy in Strings documentation (#20935) --- doc/src/manual/strings.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/src/manual/strings.md b/doc/src/manual/strings.md index 0d5788b18707a..15041d695a39d 100644 --- a/doc/src/manual/strings.md +++ b/doc/src/manual/strings.md @@ -179,7 +179,8 @@ julia> str[end] ``` All indexing in Julia is 1-based: the first element of any integer-indexed object is found at -index 1, and the last element is found at index `n`, when the string has a length of `n`. +index 1. (As we will see below, this does not necessarily mean that the last element is found +at index `n`, where `n` is the length of the string.) In any indexing expression, the keyword `end` can be used as a shorthand for the last index (computed by [`endof(str)`](@ref)). You can perform arithmetic and other operations with `end`, just like From b96ce3be2d8ba29a23ef0d079907eb5650bf0fbf Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Wed, 8 Mar 2017 19:57:12 -0600 Subject: [PATCH 0170/1534] Add TODO upon fixing issue 9080 [ci skip] --- base/multidimensional.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index f944d114b1072..9fd9d40837523 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -821,6 +821,7 @@ end @boundscheck checkbounds(src, Rsrc.start) @boundscheck checkbounds(src, Rsrc.stop) ΔI = Rdest.start - Rsrc.start + # TODO: restore when #9080 is fixed # for I in Rsrc # @inbounds dest[I+ΔI] = src[I] @nloops $N i (n->Rsrc.start[n]:Rsrc.stop[n]) begin From 79a58c32096db9908fc2bbddc2532ca8174b3d48 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Wed, 8 Mar 2017 18:02:33 -0800 Subject: [PATCH 0171/1534] [docathon] Add examples for isdiff/isdirty (#20940) * [docathon] Add examples for isdiff/isdirty * add space after # in comments --- base/libgit2/libgit2.jl | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/base/libgit2/libgit2.jl b/base/libgit2/libgit2.jl index 6084a5d2dd96b..6f5f9bebbb34e 100644 --- a/base/libgit2/libgit2.jl +++ b/base/libgit2/libgit2.jl @@ -95,6 +95,17 @@ Checks if there have been any changes to tracked files in the working tree (if `cached=false`) or the index (if `cached=true`). `pathspecs` are the specifications for options for the diff. +# Example +```julia +repo = LibGit2.GitRepo(repo_path) +LibGit2.isdirty(repo) # should be false +open(joinpath(repo_path, new_file), "a") do f + println(f, "here's my cool new file") +end +LibGit2.isdirty(repo) # now true +LibGit2.isdirty(repo, new_file) # now true +``` + Equivalent to `git diff-index HEAD [-- ]`. """ isdirty(repo::GitRepo, paths::AbstractString=""; cached::Bool=false) = @@ -107,6 +118,16 @@ Checks if there are any differences between the tree specified by `treeish` and tracked files in the working tree (if `cached=false`) or the index (if `cached=true`). `pathspecs` are the specifications for options for the diff. +# Example +```julia +repo = LibGit2.GitRepo(repo_path) +LibGit2.isdiff(repo, "HEAD") # should be false +open(joinpath(repo_path, new_file), "a") do f + println(f, "here's my cool new file") +end +LibGit2.isdiff(repo, "HEAD") # now true +``` + Equivalent to `git diff-index [-- ]`. """ function isdiff(repo::GitRepo, treeish::AbstractString, paths::AbstractString=""; cached::Bool=false) From 3e53392feaa9be3cf6733d4d80f929fbfe7e4870 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 9 Mar 2017 20:02:13 -0500 Subject: [PATCH 0172/1534] fix regressions due to replacing too many slots with SSAValues --- base/inference.jl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/base/inference.jl b/base/inference.jl index 298a84d679dab..402d167cb4ba2 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -4605,6 +4605,12 @@ function get_replacement(table, var::Union{SlotNumber, SSAValue}, init::ANY, nar return init end elseif isa(init, SSAValue) + if isa(var, SlotNumber) && slottypes[var.id] ⊑ Tuple + # Here we avoid replacing a Slot with an SSAValue when the type is an + # aggregate. That can cause LLVM to generate a bunch of extra memcpys + # if the data ever needs to be stack allocated later. + return var + end if haskey(table, init) return get_replacement(table, init, table[init], nargs, slottypes, ssavaluetypes) end From 4521e6b0681fea26e8896a2213807f99af9b67c7 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Thu, 9 Mar 2017 18:06:12 -0800 Subject: [PATCH 0173/1534] Work around bug in tar 1.29 with --no-recursion and -T (#20942) causing duplicate files and including directories it shouldn't be --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 61c6caf5c9542..9c0b67f6e03f1 100644 --- a/Makefile +++ b/Makefile @@ -497,7 +497,7 @@ light-source-dist: light-source-dist.tmp # Prefix everything with the current directory name (usually "julia"), then create tarball DIRNAME=$$(basename $$(pwd)); \ sed -e "s_.*_$$DIRNAME/&_" light-source-dist.tmp > light-source-dist.tmp1; \ - cd ../ && tar -cz -T $$DIRNAME/light-source-dist.tmp1 --no-recursion -f $$DIRNAME/julia-$(JULIA_VERSION)_$(JULIA_COMMIT).tar.gz + cd ../ && tar -cz --no-recursion -T $$DIRNAME/light-source-dist.tmp1 -f $$DIRNAME/julia-$(JULIA_VERSION)_$(JULIA_COMMIT).tar.gz source-dist: @echo \'source-dist\' target is deprecated: use \'full-source-dist\' instead. @@ -514,7 +514,7 @@ full-source-dist: light-source-dist.tmp # Prefix everything with the current directory name (usually "julia"), then create tarball DIRNAME=$$(basename $$(pwd)); \ sed -e "s_.*_$$DIRNAME/&_" full-source-dist.tmp > full-source-dist.tmp1; \ - cd ../ && tar -cz -T $$DIRNAME/full-source-dist.tmp1 --no-recursion -f $$DIRNAME/julia-$(JULIA_VERSION)_$(JULIA_COMMIT)-full.tar.gz + cd ../ && tar -cz --no-recursion -T $$DIRNAME/full-source-dist.tmp1 -f $$DIRNAME/julia-$(JULIA_VERSION)_$(JULIA_COMMIT)-full.tar.gz clean: | $(CLEAN_TARGETS) @-$(MAKE) -C $(BUILDROOT)/base clean From 3b5a0eb315399aee6c4b4e0d93835378ea20933f Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Fri, 10 Mar 2017 00:19:38 -0600 Subject: [PATCH 0174/1534] Fix printing of indices in the depwarn for to_indexes (#20960) --- base/deprecated.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index 36fc639baa403..05f2c7f66e166 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -478,7 +478,8 @@ function getindex(A::LogicalIndex, i::Int) first(Iterators.drop(A, i-1)) end function to_indexes(I...) - depwarn("to_indexes is deprecated; pass both the source array `A` and indices as `to_indices(A, $(I...))` instead.", :to_indexes) + Istr = join(I, ", ") + depwarn("to_indexes is deprecated; pass both the source array `A` and indices as `to_indices(A, $Istr)` instead.", :to_indexes) map(_to_index, I) end _to_index(i) = to_index(I) From 8880d9641dab4e6c19861acfc5821b2d21b52275 Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Fri, 10 Mar 2017 15:08:12 +0100 Subject: [PATCH 0175/1534] Use proper alignment when copying data to a variable. Using align=1 is very expensive on hardware without unaligned ld/st (eg. GPUs). --- src/codegen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index d79efe233dc48..0a270f14dcf3d 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3850,7 +3850,7 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) builder.CreateMemCpy(vi.value.V, data_pointer(rval_info, ctx, T_pint8), copy_bytes, - /*TODO: min_align*/1, + ((jl_datatype_t*)rval_info.typ)->layout->alignment, vi.isVolatile, tbaa); } From 75c2e72c505be06e1f80498d3746a62a4f239237 Mon Sep 17 00:00:00 2001 From: Andrew Keller Date: Fri, 10 Mar 2017 06:36:51 -0800 Subject: [PATCH 0176/1534] Lower `x^n` (literal n) to `Base.literal_pow(^, x, Val{n})` (#20889) Fixes #20882 --- NEWS.md | 4 ++-- base/intfuncs.jl | 25 ++++++++++++------------- base/promotion.jl | 8 +++++--- src/julia-syntax.scm | 2 +- test/numbers.jl | 13 +++++++++++-- 5 files changed, 31 insertions(+), 21 deletions(-) diff --git a/NEWS.md b/NEWS.md index c3f7bc04ecc4f..5ca7ed2007655 100644 --- a/NEWS.md +++ b/NEWS.md @@ -74,8 +74,8 @@ Language changes `Vector{T} = Array{T,1}` or a `const` assignment. * Experimental feature: `x^n` for integer literals `n` (e.g. `x^3` - or `x^-3`) is now lowered to `x^Val{n}`, to enable compile-time - specialization for literal integer exponents ([#20530]). + or `x^-3`) is now lowered to `Base.literal_pow(^, x, Val{n})`, to enable + compile-time specialization for literal integer exponents ([#20530], [#20889]). Breaking changes ---------------- diff --git a/base/intfuncs.jl b/base/intfuncs.jl index bab711aa566c5..53b46e4f1ff5e 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -195,29 +195,28 @@ end ^(x::Number, p::Integer) = power_by_squaring(x,p) ^(x, p::Integer) = power_by_squaring(x,p) -# x^p for any literal integer p is lowered to x^Val{p}, +# x^p for any literal integer p is lowered to Base.literal_pow(^, x, Val{p}) # to enable compile-time optimizations specialized to p. -# However, we still need a fallback that calls the general ^. -# To avoid ambiguities for methods that dispatch on the -# first argument, we dispatch the fallback via internal_pow. +# However, we still need a fallback that calls the function ^ which may either +# mean Base.^ or something else, depending on context. # We mark these @inline since if the target is marked @inline, # we want to make sure that gets propagated, # even if it is over the inlining threshold. -@inline ^(x, p) = internal_pow(x, p) -@inline internal_pow{p}(x, ::Type{Val{p}}) = x^p +@inline literal_pow{p}(f, x, ::Type{Val{p}}) = f(x,p) # Restrict inlining to hardware-supported arithmetic types, which -# are fast enough to benefit from inlining. This also makes it -# easier to override ^ without having to override the Val method. +# are fast enough to benefit from inlining. const HWReal = Union{Int8,Int16,Int32,Int64,UInt8,UInt16,UInt32,UInt64,Float32,Float64} const HWNumber = Union{HWReal, Complex{<:HWReal}, Rational{<:HWReal}} # inference.jl has complicated logic to inline x^2 and x^3 for -# numeric types. In terms of Val we can do it much more simply: -@inline internal_pow(x::HWNumber, ::Type{Val{0}}) = one(x) -@inline internal_pow(x::HWNumber, ::Type{Val{1}}) = x -@inline internal_pow(x::HWNumber, ::Type{Val{2}}) = x*x -@inline internal_pow(x::HWNumber, ::Type{Val{3}}) = x*x*x +# numeric types. In terms of Val we can do it much more simply. +# (The first argument prevents unexpected behavior if a function ^ +# is defined that is not equal to Base.^) +@inline literal_pow(::typeof(^), x::HWNumber, ::Type{Val{0}}) = one(x) +@inline literal_pow(::typeof(^), x::HWNumber, ::Type{Val{1}}) = x +@inline literal_pow(::typeof(^), x::HWNumber, ::Type{Val{2}}) = x*x +@inline literal_pow(::typeof(^), x::HWNumber, ::Type{Val{3}}) = x*x*x # b^p mod m diff --git a/base/promotion.jl b/base/promotion.jl index ed3c6389b2a5b..2f78d66354aec 100644 --- a/base/promotion.jl +++ b/base/promotion.jl @@ -254,9 +254,11 @@ end Exponentiation operator. If `x` is a matrix, computes matrix exponentiation. If `y` is an `Int` literal (e.g. `2` in `x^2` or `-3` in `x^-3`), the Julia code -`x^y` is transformed by the compiler to `x^Val{y}`, to enable compile-time -specialization on the value of the exponent. (As a default fallback, -however, `x^Val{y}` simply calls the `^(x,y)` function.) +`x^y` is transformed by the compiler to `Base.literal_pow(^, x, Val{y})`, to +enable compile-time specialization on the value of the exponent. +(As a default fallback we have `Base.literal_pow(^, x, Val{y}) = ^(x,y)`, +where usually `^ == Base.^` unless `^` has been defined in the calling +namespace.) ```jldoctest julia> 3^5 diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index ea2028a3debb0..b4cb4b580c61b 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -2057,7 +2057,7 @@ ((and (eq? f '^) (length= e 4) (integer? (cadddr e))) (expand-forms - `(call ^ ,(caddr e) (call (core apply_type) (top Val) ,(cadddr e))))) + `(call (top literal_pow) ^ ,(caddr e) (call (core apply_type) (top Val) ,(cadddr e))))) ((and (eq? f '*) (length= e 4)) (expand-transposed-op diff --git a/test/numbers.jl b/test/numbers.jl index 1dedb11e6a44c..f926085912ba3 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -2903,9 +2903,12 @@ end end import Base.^ -immutable PR20530; end +struct PR20530; end +struct PR20889; x; end ^(::PR20530, p::Int) = 1 -^{p}(::PR20530, ::Type{Val{p}}) = 2 +^(t::PR20889, b) = t.x + b +^(t::PR20889, b::Integer) = t.x + b +Base.literal_pow{p}(::typeof(^), ::PR20530, ::Type{Val{p}}) = 2 @testset "literal powers" begin x = PR20530() p = 2 @@ -2923,6 +2926,12 @@ immutable PR20530; end end end end + @test PR20889(2)^3 == 5 +end +module M20889 # do we get the expected behavior without importing Base.^? + struct PR20889; x; end + ^(t::PR20889, b) = t.x + b + Base.Test.@test PR20889(2)^3 == 5 end @testset "iszero" begin From 9bec6d22ae4b878523d56889d70c30e03ee73ccf Mon Sep 17 00:00:00 2001 From: Andrew Keller Date: Fri, 10 Mar 2017 08:07:25 -0800 Subject: [PATCH 0177/1534] Add section on type piracy to style guide (#20967) * Add section on type piracy. * Add examples of type piracy. --- doc/src/manual/style-guide.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/doc/src/manual/style-guide.md b/doc/src/manual/style-guide.md index 2b0b0fc09dba7..eb6a41f62aea3 100644 --- a/doc/src/manual/style-guide.md +++ b/doc/src/manual/style-guide.md @@ -273,6 +273,37 @@ This would provide custom showing of vectors with a specific new element type. W this should be avoided. The trouble is that users will expect a well-known type like `Vector()` to behave in a certain way, and overly customizing its behavior can make it harder to work with. +## Avoid type piracy + +"Type piracy" refers to the practice of extending or redefining methods in Base +or other packages on types that you have not defined. In some cases, you can get away with +type piracy with little ill effect. In extreme cases, however, you can even crash Julia +(e.g. if your method extension or redefinition causes invalid input to be passed to a +`ccall`). Type piracy can complicate reasoning about code, and may introduce +incompatibilities that are hard to predict and diagnose. + +As an example, suppose you wanted to define multiplication on symbols in a module: + +```julia +module A +import Base.* +*(x::Symbol, y::Symbol) = Symbol(x,y) +end +``` + +The problem is that now any other module that uses `Base.*` will also see this definition. +Since `Symbol` is defined in Base and is used by other modules, this can change the +behavior of unrelated code unexpectedly. There are several alternatives here, including +using a different function name, or wrapping the `Symbol`s in another type that you define. + +Sometimes, coupled packages may engage in type piracy to separate features from definitions, +especially when the packages were designed by collaborating authors, and when the +definitions are reusable. For example, one package might provide some types useful for +working with colors; another package could define methods for those types that enable +conversions between color spaces. Another example might be a package that acts as a thin +wrapper for some C code, which another package might then pirate to implement a +higher-level, Julia-friendly API. + ## Be careful with type equality You generally want to use [`isa()`](@ref) and `<:` ([`issubtype()`](@ref)) for testing types, From 294b253e29336ae943f91c4c62730236c3f3259c Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Thu, 9 Mar 2017 20:43:27 -0800 Subject: [PATCH 0178/1534] Resolve ambiguity between * methods associated with RowVectors. --- base/linalg/rowvector.jl | 1 + test/linalg/rowvector.jl | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/base/linalg/rowvector.jl b/base/linalg/rowvector.jl index ac4541ff39123..32ecc91fea37a 100644 --- a/base/linalg/rowvector.jl +++ b/base/linalg/rowvector.jl @@ -165,6 +165,7 @@ end # inner product -> dot product specializations @inline *{T<:Real}(rowvec::RowVector{T}, vec::AbstractVector{T}) = dot(parent(rowvec), vec) +@inline *{T<:Real}(rowvec::ConjRowVector{T}, vec::AbstractVector{T}) = dot(rowvec', vec) @inline *(rowvec::ConjRowVector, vec::AbstractVector) = dot(rowvec', vec) # Generic behavior diff --git a/test/linalg/rowvector.jl b/test/linalg/rowvector.jl index f188a3082c000..0345808d8a66a 100644 --- a/test/linalg/rowvector.jl +++ b/test/linalg/rowvector.jl @@ -249,3 +249,7 @@ end @test A'*x' == A'*y == B*x' == B*y == C' end end + +@testset "ambiguity between * methods with RowVectors and ConjRowVectors (#20971)" begin + @test RowVector(ConjArray(ones(4))) * ones(4) == 4 +end From abe1a719ff0b231780ae6a39ba14e0ab393991e1 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 10 Mar 2017 15:00:04 -0500 Subject: [PATCH 0179/1534] use explicit checks instead of try/catch to detect BLAS vendor --- base/linalg/blas.jl | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/base/linalg/blas.jl b/base/linalg/blas.jl index 3a7a9fb4b676e..d31d415f88291 100644 --- a/base/linalg/blas.jl +++ b/base/linalg/blas.jl @@ -61,17 +61,15 @@ import ..LinAlg: BlasReal, BlasComplex, BlasFloat, BlasInt, DimensionMismatch, c # utility routines function vendor() - try - cglobal((:openblas_set_num_threads, Base.libblas_name), Void) - return :openblas - end - try - cglobal((:openblas_set_num_threads64_, Base.libblas_name), Void) - return :openblas64 - end - try - cglobal((:MKL_Set_Num_Threads, Base.libblas_name), Void) - return :mkl + lib = Libdl.dlopen_e(Base.libblas_name) + if lib != C_NULL + if Libdl.dlsym_e(lib, :openblas_set_num_threads) != C_NULL + return :openblas + elseif Libdl.dlsym_e(lib, :openblas_set_num_threads64_) != C_NULL + return :openblas64 + elseif Libdl.dlsym_e(lib, :MKL_Set_Num_Threads) != C_NULL + return :mkl + end end return :unknown end From 6a1a45538e8f69da245a28581107f72d717f6a57 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Thu, 9 Mar 2017 20:08:06 -0800 Subject: [PATCH 0180/1534] Nix ambiguity between \ methods. --- base/sparse/cholmod.jl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/base/sparse/cholmod.jl b/base/sparse/cholmod.jl index 451d200c6ad87..aae1ea4d581d0 100644 --- a/base/sparse/cholmod.jl +++ b/base/sparse/cholmod.jl @@ -1598,9 +1598,10 @@ Ac_ldiv_B(L::FactorComponent, B) = ctranspose(L)\B Ac_ldiv_B(L::FactorComponent, B::RowVector) = ctranspose(L)\B # ambiguity (\){T<:VTypes}(L::Factor{T}, B::Dense{T}) = solve(CHOLMOD_A, L, B) -(\)(L::Factor{Float64}, B::VecOrMat{Complex{Float64}}) = complex.(L\real(B), L\imag(B)) -# First explicit TypeVars are necessary to avoid ambiguity errors with definition in -# linalg/factorizations.jl +# Explicit typevars are necessary to avoid ambiguities with defs in linalg/factorizations.jl +# Likewise the two following explicit Vector and Matrix defs (rather than a single VecOrMat) +(\){T<:Float64}(L::Factor{T}, B::Vector{Complex{T}}) = complex.(L\real(B), L\imag(B)) +(\){T<:Float64}(L::Factor{T}, B::Matrix{Complex{T}}) = complex.(L\real(B), L\imag(B)) (\){T<:VTypes}(L::Factor{T}, b::StridedVector) = Vector(L\convert(Dense{T}, b)) (\){T<:VTypes}(L::Factor{T}, B::StridedMatrix) = Matrix(L\convert(Dense{T}, B)) (\)(L::Factor, B::Sparse) = spsolve(CHOLMOD_A, L, B) From b2f89ce759fe0830bc025c4802c0c5cefb7f7d40 Mon Sep 17 00:00:00 2001 From: Ken-B Date: Sat, 11 Mar 2017 20:59:49 +0100 Subject: [PATCH 0181/1534] fix broken link to xterm 256 colors in NEWS --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 5ca7ed2007655..92fbf9b2d0a40 100644 --- a/NEWS.md +++ b/NEWS.md @@ -239,7 +239,7 @@ Library improvements This can be disabled or enabled at will with `Base.REPL.enable_promptpaste(::Bool)`. * The function `print_with_color` can now take a color represented by an integer between 0 and 255 inclusive as its first argument ([#18473]). - For a number to color mapping please refer to [this chart](https://upload.wikimedia.org/wikipedia/en/1/15/Xterm_256color_chart.svg). + For a number to color mapping please refer to [this chart](https://upload.wikimedia.org/wikipedia/commons/1/15/Xterm_256color_chart.svg). It is also possible to use numbers as colors in environment variables that customizes colors in the REPL. For example, to get orange warning messages, simply set `ENV["JULIA_WARN_COLOR"] = 208`. Please note that not all terminals support 256 colors. From d22d81c348a1758c1bf1fe774ed38e07be80ecd4 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sat, 11 Mar 2017 13:25:51 -0800 Subject: [PATCH 0182/1534] Resolve ambiguities between checkbounds_indices methods. --- base/multidimensional.jl | 4 ++-- test/abstractarray.jl | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 9fd9d40837523..0e50fdd342c9e 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -258,8 +258,8 @@ end I::Tuple{AbstractArray{CartesianIndex{0}},Vararg{Any}}) checkbounds_indices(Bool, IA, tail(I)) end -@inline function checkbounds_indices(::Type{Bool}, IA::Tuple{Any}, - I::Tuple{<:AbstractArray{<:CartesianIndex},Vararg{Any}}) +@inline function checkbounds_indices{N}(::Type{Bool}, IA::Tuple{Any}, + I::Tuple{AbstractArray{CartesianIndex{N}},Vararg{Any}}) checkindex(Bool, IA, I[1]) & checkbounds_indices(Bool, (), tail(I)) end @inline function checkbounds_indices{N}(::Type{Bool}, IA::Tuple, diff --git a/test/abstractarray.jl b/test/abstractarray.jl index b97c51066b798..276c074d91dd0 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -836,3 +836,7 @@ end @testset "dispatch loop introduced in #19305" begin @test [(1:2) zeros(2,2); ones(3,3)] == [[1,2] zeros(2,2); ones(3,3)] == [reshape([1,2],2,1) zeros(2,2); ones(3,3)] end + +@testset "checkbounds_indices method ambiguities #20989" begin + @test Base.checkbounds_indices(Bool, (1:1,), ([CartesianIndex(1)],)) +end From 840f5fbc38eaf734225397d72c9d8d9afee35f7f Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sat, 11 Mar 2017 14:02:23 -0800 Subject: [PATCH 0183/1534] Resolve ambiguity between tuple constructors. --- base/tuple.jl | 3 +++ test/tuple.jl | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/base/tuple.jl b/base/tuple.jl index bc0d3c932b0c4..b3799e57d6fba 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -186,6 +186,9 @@ if isdefined(Main, :Base) (::Type{T}){T<:Tuple}(x::Tuple) = convert(T, x) # still use `convert` for tuples +# resolve ambiguity between preceding and following methods +(::Type{All16{E,N}}){E,N}(x::Tuple) = convert(All16{E,N}, x) + function (T::Type{All16{E,N}}){E,N}(itr) len = N+16 elts = collect(E, Iterators.take(itr,len)) diff --git a/test/tuple.jl b/test/tuple.jl index 9f2496d364007..20ccbe348587c 100644 --- a/test/tuple.jl +++ b/test/tuple.jl @@ -236,3 +236,9 @@ end @test_throws MethodError (1,)[] @test_throws MethodError (1,1,1)[1,1] end + +@testset "ambiguity between tuple constructors #20990" begin + Tuple16Int = Tuple{Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int} + tuple16int = (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) + @test Tuple16Int(tuple16int) isa Tuple16Int +end From ec4444acaa05544d632a64e43e57d9837173ea11 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sun, 12 Mar 2017 06:48:11 -0500 Subject: [PATCH 0184/1534] Fix handling of `allow_bottom_tparams` in `isambiguous` The former version failed to detect that certain type parameters were Bottom (for example, in the case in the added docstring for `isambiguous`). --- base/reflection.jl | 51 +++++++++++++++++++++++++++++++++++++++++++--- base/test.jl | 6 +++++- test/ambiguous.jl | 2 +- 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/base/reflection.jl b/base/reflection.jl index d79b80cef56d5..1286689f75283 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -941,13 +941,41 @@ function method_exists(f::ANY, t::ANY) typemax(UInt)) != 0 end +""" + isambiguous(m1, m2, [allow_bottom_tparams=true]) -> Bool + +Determine whether two methods `m1` and `m2` (typically of the same +function) are ambiguous. This test is performed in the context of +other methods of the same function; in isolation, `m1` and `m2` might +be ambiguous, but if a third method resolving the ambiguity has been +defined, this returns `false`. + +For parametric types, `allow_bottom_tparams` controls whether +`Union{}` is considered a valid intersection of type parameters. For example: +```jldoctest +julia> foo(x::Complex{<:Integer}) = 1 +foo (generic function with 1 method) + +julia> foo(x::Complex{<:Rational}) = 2 +foo (generic function with 2 methods) + +julia> m1, m2 = collect(methods(foo)); + +julia> typeintersect(m1.sig, m2.sig) +Tuple{#foo,Complex{Union{}}} + +julia> Base.isambiguous(m1, m2, true) +true + +julia> Base.isambiguous(m1, m2, false) +false +``` +""" function isambiguous(m1::Method, m2::Method, allow_bottom_tparams::Bool=true) ti = typeintersect(m1.sig, m2.sig) ti === Bottom && return false if !allow_bottom_tparams - (_, env) = ccall(:jl_match_method, Ref{SimpleVector}, (Any, Any), - ti, m1.sig) - any(x->x === Bottom, env) && return false + has_bottom_parameter(ti) && return false end ml = _methods_by_ftype(ti, -1, typemax(UInt)) isempty(ml) && return true @@ -959,6 +987,23 @@ function isambiguous(m1::Method, m2::Method, allow_bottom_tparams::Bool=true) return true end +""" + has_bottom_parameter(t) -> Bool + +Determine whether `t` is a Type for which one or more of its parameters is `Union{}`. +""" +function has_bottom_parameter(t::Type) + ret = false + for p in t.parameters + ret |= (p == Bottom) || has_bottom_parameter(p) + end + ret +end +has_bottom_parameter(t::UnionAll) = has_bottom_parameter(unwrap_unionall(t)) +has_bottom_parameter(t::Union) = has_bottom_parameter(t.a) & has_bottom_parameter(t.b) +has_bottom_parameter(t::TypeVar) = has_bottom_parameter(t.ub) +has_bottom_parameter(::Any) = false + min_world(m::Method) = reinterpret(UInt, m.min_world) max_world(m::Method) = reinterpret(UInt, m.max_world) min_world(m::Core.MethodInstance) = reinterpret(UInt, m.min_world) diff --git a/base/test.jl b/base/test.jl index f460b97a73989..95bbd0f6f44be 100644 --- a/base/test.jl +++ b/base/test.jl @@ -1117,12 +1117,16 @@ function test_approx_eq_modphase{S<:Real,T<:Real}( end """ - detect_ambiguities(mod1, mod2...; imported=false) + detect_ambiguities(mod1, mod2...; imported=false, allow_bottom=true) Returns a vector of `(Method,Method)` pairs of ambiguous methods defined in the specified modules. Use `imported=true` if you wish to also test functions that were imported into these modules from elsewhere. + +`allow_bottom` controls whether ambiguities triggered only by +`Union{}` type parameters are included; in most cases you probably +want to set this to `false`. See [`Base.isambiguous`](@ref). """ function detect_ambiguities(mods...; imported::Bool=false, allow_bottom::Bool=true) function sortdefs(m1, m2) diff --git a/test/ambiguous.jl b/test/ambiguous.jl index fa6cc8c54e355..1e97b6e564680 100644 --- a/test/ambiguous.jl +++ b/test/ambiguous.jl @@ -134,7 +134,7 @@ ambs = detect_ambiguities(Ambig5) # Test that Core and Base are free of ambiguities # TODO jb/subtype: we now detect a lot more -@test_broken detect_ambiguities(Core, Base; imported=true) == [] +@test_broken detect_ambiguities(Core, Base; imported=true, allow_bottom=false) == [] # not using isempty so this prints more information when it fails amb_1(::Int8, ::Int) = 1 From 416d85b08840123451c224d97099d9a6dff6cf38 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sat, 11 Mar 2017 12:47:50 -0800 Subject: [PATCH 0185/1534] Resolve ambiguity between colon methods. --- base/range.jl | 6 +++++- test/ranges.jl | 8 ++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/base/range.jl b/base/range.jl index cc2ad162eb7ff..420a57e60a55a 100644 --- a/base/range.jl +++ b/base/range.jl @@ -38,7 +38,11 @@ Range operator. `a:b` constructs a range from `a` to `b` with a step size of 1, is similar but uses a step size of `s`. These syntaxes call the function `colon`. The colon is also used in indexing to select whole dimensions. """ -function colon{T}(start::T, step, stop::T) +colon{T}(start::T, step, stop::T) = _colon(start, step, stop) +colon{T<:Real}(start::T, step, stop::T) = _colon(start, step, stop) +# without the second method above, the first method above is ambiguous with +# colon{A<:Real,C<:Real}(start::A, step, stop::C) +function _colon{T}(start::T, step, stop::T) T′ = typeof(start+step) StepRange(convert(T′,start), step, convert(T′,stop)) end diff --git a/test/ranges.jl b/test/ranges.jl index 79502315ccbd1..d990f0fad3410 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -894,6 +894,14 @@ let r = linspace(1.0, 3+im, 4) @test r[4] === 3.0+im end +# ambiguity between colon methods (#20988) +struct NotReal; val; end +Base.:+(x, y::NotReal) = x + y.val +Base.zero(y::NotReal) = zero(y.val) +Base.rem(x, y::NotReal) = rem(x, y.val) +Base.isless(x, y::NotReal) = isless(x, y.val) +@test colon(1, NotReal(1), 5) isa StepRange{Int,NotReal} + # dimensional correctness: isdefined(Main, :TestHelpers) || @eval Main include("TestHelpers.jl") using TestHelpers.Furlong From 3777aabc43d4797de6b284cdbd245ecaf30b40d7 Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Sun, 12 Mar 2017 15:56:07 -0500 Subject: [PATCH 0186/1534] Fix broadcast with RowVectors of matrices (#20980) Fix #20979. Amusingly, this bug is a direct result of `transpose` being recursive. --- base/linalg/rowvector.jl | 9 +++++---- test/linalg/rowvector.jl | 17 ++++++++++++++++- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/base/linalg/rowvector.jl b/base/linalg/rowvector.jl index 32ecc91fea37a..aaca0d86d3917 100644 --- a/base/linalg/rowvector.jl +++ b/base/linalg/rowvector.jl @@ -140,16 +140,17 @@ end @inline check_tail_indices(i1, i2, i3, is...) = i3 == 1 ? check_tail_indices(i1, i2, is...) : false # helper function for below -@inline to_vec(rowvec::RowVector) = transpose(rowvec) +@inline to_vec(rowvec::RowVector) = map(transpose, transpose(rowvec)) @inline to_vec(x::Number) = x @inline to_vecs(rowvecs...) = (map(to_vec, rowvecs)...) -# map -@inline map(f, rowvecs::RowVector...) = RowVector(map(f, to_vecs(rowvecs...)...)) +# map: Preserve the RowVector by un-wrapping and re-wrapping, but note that `f` +# expects to operate within the transposed domain, so to_vec transposes the elements +@inline map(f, rowvecs::RowVector...) = RowVector(map(transpose∘f, to_vecs(rowvecs...)...)) # broacast (other combinations default to higher-dimensional array) @inline broadcast(f, rowvecs::Union{Number,RowVector}...) = - RowVector(broadcast(f, to_vecs(rowvecs...)...)) + RowVector(broadcast(transpose∘f, to_vecs(rowvecs...)...)) # Horizontal concatenation # diff --git a/test/linalg/rowvector.jl b/test/linalg/rowvector.jl index 0345808d8a66a..011a17992eb68 100644 --- a/test/linalg/rowvector.jl +++ b/test/linalg/rowvector.jl @@ -250,6 +250,21 @@ end end end +@testset "issue #20979" begin + f20979(z::Complex) = [z.re -z.im; z.im z.re] + v = [1+2im]' + @test (f20979.(v))[1] == f20979(v[1]) + @test f20979.(v) == f20979.(collect(v)) + + w = rand(Complex128, 3) + @test f20979.(v') == f20979.(collect(v')) == (f20979.(v))' + + g20979(x, y) = [x[2,1] x[1,2]; y[1,2] y[2,1]] + v = [rand(2,2), rand(2,2), rand(2,2)] + @test g20979.(v', v') == g20979.(collect(v'), collect(v')) == + map(g20979, v', v') == map(g20979, collect(v'), collect(v')) +end + @testset "ambiguity between * methods with RowVectors and ConjRowVectors (#20971)" begin @test RowVector(ConjArray(ones(4))) * ones(4) == 4 -end +end \ No newline at end of file From 16324730a997d3b8cab404782e668aa3b6b8b4ad Mon Sep 17 00:00:00 2001 From: Stefan Karpinski Date: Sun, 12 Mar 2017 19:00:37 -0400 Subject: [PATCH 0187/1534] pkg: factor url_or_pkg logic into its own function and test it --- base/pkg/entry.jl | 25 +++++++++++-------------- test/pkg.jl | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/base/pkg/entry.jl b/base/pkg/entry.jl index 84f128d268578..13f9abcb6d867 100644 --- a/base/pkg/entry.jl +++ b/base/pkg/entry.jl @@ -206,23 +206,20 @@ function clone(url::AbstractString, pkg::AbstractString) end end -function clone(url_or_pkg::AbstractString) +function url_and_pkg(url_or_pkg::AbstractString) if !(':' in url_or_pkg) - urlpath = joinpath("METADATA",url_or_pkg,"url") - if isfile(urlpath) - pkg = url_or_pkg - url = readchomp(urlpath) - # TODO: Cache.prefetch(pkg,url) - return clone(url,pkg) - end - end - url = url_or_pkg - m = match(r"(?:^|[/\\])(\w+?)(?:\.jl)?(?:\.git)?$", url) - m !== nothing || throw(PkgError("can't determine package name from URL: $url")) - pkg = m.captures[1] - return clone(url,pkg) + # no colon, could be a package name + url_file = joinpath("METADATA", url_or_pkg, "url") + isfile(url_file) && return readchomp(url_file), url_or_pkg + end + # try to parse as URL or local path + m = match(r"(?:^|[/\\])(\w+?)(?:\.jl)?(?:\.git)?$", url_or_pkg) + m === nothing && throw(PkgError("can't determine package name from URL: $url_or_pkg")) + return url_or_pkg, m.captures[1] end +clone(url_or_pkg::AbstractString) = clone(url_and_pkg(url_or_pkg)...) + function checkout(pkg::AbstractString, branch::AbstractString, do_merge::Bool, do_pull::Bool) ispath(pkg,".git") || throw(PkgError("$pkg is not a git repo")) info("Checking out $pkg $branch...") diff --git a/test/pkg.jl b/test/pkg.jl index 357152eeb4b96..d194a066c03fb 100644 --- a/test/pkg.jl +++ b/test/pkg.jl @@ -419,6 +419,24 @@ temp_pkg_dir() do @test !contains(msg, "signal (15)") end + # issue #20695 + Pkg.cd() do + @test Pkg.Entry.url_and_pkg("Example") == ("git://github.com/JuliaLang/Example.jl.git", "Example") + for url = [ + "https://github.com/Org/Nonsense", + "git@github.com:Org/Nonsense", + "file:///home/user/Nonsense", + "/home/user/Nonsense", + ] + @test Pkg.Entry.url_and_pkg(url) == (url, "Nonsense") + @test Pkg.Entry.url_and_pkg("$url.jl") == ("$url.jl", "Nonsense") + @test Pkg.Entry.url_and_pkg("$url.git") == ("$url.git", "Nonsense") + @test Pkg.Entry.url_and_pkg("$url.jl.git") == ("$url.jl.git", "Nonsense") + end + pkg = randstring(20) + @test Pkg.Entry.url_and_pkg(pkg) == (pkg, pkg) + end + # partial Pkg.update @test "" == capture_stdout() do nothingtodomsg = "INFO: No packages to install, update or remove" From a132ae2747564936ea1bbd347d51be6911c6fa1b Mon Sep 17 00:00:00 2001 From: Christian Kurz Date: Mon, 13 Mar 2017 15:27:50 +0100 Subject: [PATCH 0188/1534] `abstract` -> `abstract type` (#21002) --- doc/src/manual/types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/manual/types.md b/doc/src/manual/types.md index f4a2851c384cf..2928db8be59df 100644 --- a/doc/src/manual/types.md +++ b/doc/src/manual/types.md @@ -154,7 +154,7 @@ abstract type «name» end abstract type «name» <: «supertype» end ``` -The `abstract` keyword introduces a new abstract type, whose name is given by `«name»`. This +The `abstract type` keyword introduces a new abstract type, whose name is given by `«name»`. This name can be optionally followed by `<:` and an already-existing type, indicating that the newly declared abstract type is a subtype of this "parent" type. From b626d0b4e3c6eabda0057016268a77eec29f23ab Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Mon, 13 Mar 2017 10:36:45 -0700 Subject: [PATCH 0189/1534] Upgrade Documenter to 0.9.1 (#20997) fixes some windows path issues --- doc/REQUIRE | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/REQUIRE b/doc/REQUIRE index 53e5f8775c238..aef596ad84444 100644 --- a/doc/REQUIRE +++ b/doc/REQUIRE @@ -1,3 +1,3 @@ -Compat 0.9.5 0.9.5+ +Compat 0.20.0 0.20.0+ DocStringExtensions 0.3.1 0.3.1+ -Documenter 0.9.0 0.9.0+ +Documenter 0.9.1 0.9.1+ From dcc71f29927c88353c3c89053066979e651bdf51 Mon Sep 17 00:00:00 2001 From: Martin Holters Date: Mon, 13 Mar 2017 08:27:55 +0100 Subject: [PATCH 0190/1534] Fix `typeintersect` involving `TypeVar`s bound to non-types Modify `var_gt` and `intersect_var` to cope with cases where a `TypeVar` has been deduced to be a non-type constant as is compared or intersected with another `TypeVar` or vice versa. --- src/subtype.c | 10 ++++++++-- test/subtype.jl | 7 +++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/subtype.c b/src/subtype.c index 80e75a9633dae..e8251bc15733c 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -385,6 +385,12 @@ static int var_gt(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int param) record_var_occurrence(bb, e, param); if (!bb->right) // check ∀b . b>:a return subtype_ufirst(a, bb->lb, e); + if (bb->lb == bb->ub) { + if (jl_is_typevar(bb->lb) && !jl_is_type(a) && !jl_is_typevar(a)) + return var_gt((jl_tvar_t*)bb->lb, a, e, param); + if (jl_is_typevar(a) && !jl_is_type(bb->lb) && !jl_is_typevar(bb->lb)) + return var_lt((jl_tvar_t*)a, bb->lb, e, param); + } if (!((bb->ub == (jl_value_t*)jl_any_type && !jl_is_type(a) && !jl_is_typevar(a)) || subtype_ufirst(a, bb->ub, e))) return 0; bb->lb = simple_join(bb->lb, a); @@ -1109,13 +1115,13 @@ static jl_value_t *intersect_var(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int jl_varbinding_t *bb = lookup(e, b); if (bb == NULL) return R ? intersect_ufirst(a, b->ub, e, 0) : intersect_ufirst(b->ub, a, e, 0); + if (bb->lb == bb->ub && jl_is_typevar(bb->lb)) + return intersect(a, bb->lb, e, param); if (!jl_is_type(a) && !jl_is_typevar(a)) return set_var_to_const(bb, a, NULL); int d = bb->depth0; jl_value_t *root=NULL; jl_savedenv_t se; if (param == 2) { - if (bb->lb == bb->ub && jl_is_typevar(bb->lb)) - return intersect(a, bb->ub, e, param); jl_value_t *ub = R ? intersect_ufirst(a, bb->ub, e, d) : intersect_ufirst(bb->ub, a, e, d); JL_GC_PUSH1(&ub); if (!subtype_in_env(bb->lb, a, e)) { diff --git a/test/subtype.jl b/test/subtype.jl index cf9da3cd3349a..a5010df309b52 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -941,3 +941,10 @@ ftwoparams(::TwoParams{<:Real,<:Real}) = 3 # tolerate non-types in Tuples @test typeintersect(Tuple{0}, Tuple{T} where T) === Tuple{0} + +# TypeVars deduced as non-type constants (#20869) +@testintersect(Tuple{Val{0}, Val{Val{N}}} where N, Tuple{Val{N}, Val{Val{N}}} where N, Tuple{Val{0},Val{Val{0}}}) +@testintersect(Tuple{Val{N}, Val{Val{0}}} where N, Tuple{Val{N}, Val{Val{N}}} where N, Tuple{Val{0},Val{Val{0}}}) + +@testintersect(Tuple{Val{Val{0}}, Val{N}} where N, Tuple{Val{Val{N}}, Val{N}} where N, Tuple{Val{Val{0}},Val{0}}) +@testintersect(Tuple{Val{Val{N}}, Val{0}} where N, Tuple{Val{Val{N}}, Val{N}} where N, Tuple{Val{Val{0}},Val{0}}) From 6fb2c67e9e4461d48cbfe57bd30849a6615b06a1 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 13 Mar 2017 19:01:03 -0400 Subject: [PATCH 0191/1534] fix #20998 This was a case where an unknown typevar was incorrectly inferred to have the value `Any`. --- src/subtype.c | 4 ++-- test/subtype.jl | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/subtype.c b/src/subtype.c index 80e75a9633dae..8159377324425 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -1286,9 +1286,9 @@ static jl_value_t *finish_unionall(jl_value_t *res, jl_varbinding_t *vb, jl_sten if (vb->right && e->envidx < e->envsz) { jl_value_t *oldval = e->envout[e->envidx]; - if (!varval) + if (!varval || (!is_leaf_bound(varval) && !var_occurs_invariant(res, vb->var, 0))) e->envout[e->envidx] = (jl_value_t*)vb->var; - else if (!oldval || !jl_is_typevar(oldval) || !jl_is_long(varval)) + else if (!(oldval && jl_is_typevar(oldval) && jl_is_long(varval))) e->envout[e->envidx] = varval; } diff --git a/test/subtype.jl b/test/subtype.jl index cf9da3cd3349a..12f0fd2c1eb76 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -853,6 +853,10 @@ function test_intersection() @testintersect(Tuple{Ref{Pair{p2,T2}}, Pair{p1,Pair}} where T2 where p2 where p1, Tuple{Ref{Pair{p3,T3}}, Pair{p3}} where T3 where p3, Tuple{Ref{Pair{p1,T2}}, Pair{p1,Pair}} where T2 where p1) + + # issue #20998 + _, E = intersection_env(Tuple{Int,Any,Any}, Tuple{T,T,S} where {T,S}) + @test length(E) == 2 && E[1] == Int && isa(E[2], TypeVar) end function test_intersection_properties() From 5f35b96645986ac53a39eb08f01d97b6e7785bfa Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 13 Mar 2017 23:33:22 -0400 Subject: [PATCH 0192/1534] fix #20992, compiler hang This was due to type intersection returning a type containing a free variable. --- base/inference.jl | 22 +++++++++++----------- src/subtype.c | 6 ++++-- test/subtype.jl | 9 +++++++++ 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 402d167cb4ba2..fbdde0def09d6 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -1405,8 +1405,8 @@ end # Union of Tuples of the same length is converted to Tuple of Unions. # returns an array of types, or `nothing`. function precise_container_type(arg, typ, vtypes::VarTable, sv) - tti = widenconst(typ) - tti = unwrap_unionall(tti) + tti0 = widenconst(typ) + tti = unwrap_unionall(tti0) if isa(typ, Const) && (isa(typ.val, SimpleVector) || isa(typ.val, Tuple)) return Any[ abstract_eval_constant(x) for x in typ.val ] elseif isa(arg, Expr) && arg.head === :call && (abstract_evals_to_constant(arg.args[1], svec, vtypes, sv) || @@ -1422,26 +1422,26 @@ function precise_container_type(arg, typ, vtypes::VarTable, sv) if _any(t -> !isa(t,DataType) || !(t <: Tuple) || !isknownlength(t), utis) return Any[Vararg{Any}] end - result = Any[utis[1].parameters...] + result = Any[rewrap_unionall(p, tti0) for p in utis[1].parameters] for t in utis[2:end] if length(t.parameters) != length(result) return Any[Vararg{Any}] end for j in 1:length(t.parameters) - result[j] = tmerge(result[j], t.parameters[j]) + result[j] = tmerge(result[j], rewrap_unionall(t.parameters[j], tti0)) end end return result - elseif isa(tti,DataType) && tti <: Tuple - if isvatuple(tti) && length(tti.parameters) == 1 - return Any[Vararg{unwrapva(tti.parameters[1])}] + elseif isa(tti0,DataType) && tti0 <: Tuple + if isvatuple(tti0) && length(tti0.parameters) == 1 + return Any[Vararg{unwrapva(tti0.parameters[1])}] else - return tti.parameters + return tti0.parameters end - elseif tti <: Array - return Any[Vararg{eltype(tti)}] + elseif tti0 <: Array + return Any[Vararg{eltype(tti0)}] else - return Any[Vararg{abstract_iteration(tti, vtypes, sv)}] + return Any[Vararg{abstract_iteration(tti0, vtypes, sv)}] end end diff --git a/src/subtype.c b/src/subtype.c index e8251bc15733c..646ae4b73079c 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -1542,8 +1542,10 @@ static jl_value_t *intersect_sub_datatype(jl_datatype_t *xd, jl_datatype_t *yd, for(i=0; ivar) + // the exact typevar from the type's `wrapper`, or a free typevar. + jl_value_t *ei = env[i]; + if (ei == (jl_value_t*)((jl_unionall_t*)wr)->var || + (jl_is_typevar(ei) && lookup(e, (jl_tvar_t*)ei) == NULL)) env[i] = jl_tparam(xd,i); wr = ((jl_unionall_t*)wr)->body; } diff --git a/test/subtype.jl b/test/subtype.jl index a5010df309b52..07c4196b5e41b 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -948,3 +948,12 @@ ftwoparams(::TwoParams{<:Real,<:Real}) = 3 @testintersect(Tuple{Val{Val{0}}, Val{N}} where N, Tuple{Val{Val{N}}, Val{N}} where N, Tuple{Val{Val{0}},Val{0}}) @testintersect(Tuple{Val{Val{N}}, Val{0}} where N, Tuple{Val{Val{N}}, Val{N}} where N, Tuple{Val{Val{0}},Val{0}}) + +# issue #20992 +abstract type A20992{T,D,d} end +abstract type B20992{SV,T,D,d} <: A20992{T,D,d} end +struct C20992{S,n,T,D,d} <: B20992{NTuple{n,S},T,D,d} +end +@testintersect(Tuple{A20992{R, D, d} where d where D, Int} where R, + Tuple{C20992{S, n, T, D, d} where d where D where T where n where S, Any}, + Tuple{C20992, Int}) From 3b0a5dccd467021652aca5ffe58df86e9459c278 Mon Sep 17 00:00:00 2001 From: Pablo Zubieta Date: Wed, 8 Mar 2017 23:49:49 -0600 Subject: [PATCH 0193/1534] Make broadcast over sparse and rowvecs sparse --- base/sparse/higherorderfns.jl | 15 +++++++++------ test/sparse/higherorderfns.jl | 13 ++++++++----- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/base/sparse/higherorderfns.jl b/base/sparse/higherorderfns.jl index 6ef9e4270063d..abc148485a195 100644 --- a/base/sparse/higherorderfns.jl +++ b/base/sparse/higherorderfns.jl @@ -6,10 +6,11 @@ module HigherOrderFns # particularly map[!]/broadcast[!] for SparseVectors and SparseMatrixCSCs at present. import Base: map, map!, broadcast, broadcast! import Base.Broadcast: _containertype, promote_containertype, - broadcast_indices, broadcast_c, broadcast_c! + broadcast_indices, broadcast_c, broadcast_c! using Base: front, tail, to_shape -using ..SparseArrays: SparseVector, SparseMatrixCSC, AbstractSparseArray, indtype +using ..SparseArrays: SparseVector, SparseMatrixCSC, AbstractSparseVector, + AbstractSparseMatrix, AbstractSparseArray, indtype # This module is organized as follows: # (1) Define a common interface to SparseVectors and SparseMatrixCSCs sufficient for @@ -1063,6 +1064,7 @@ promote_containertype(::Type{Array}, ::Type{AbstractSparseArray}) = PromoteToSpa _spcontainertype(x) = _containertype(x) _spcontainertype(::Type{<:Vector}) = Vector _spcontainertype(::Type{<:Matrix}) = Matrix +_spcontainertype(::Type{<:RowVector}) = Matrix _spcontainertype(::Type{<:Ref}) = AbstractArray _spcontainertype(::Type{<:AbstractArray}) = AbstractArray # need the following two methods to override the immediately preceding method @@ -1105,10 +1107,11 @@ promote_spcontainertype(::FunnelToSparseBC, ::FunnelToSparseBC) = PromoteToSpars @inline spbroadcast_c!{N}(f, ::Type{AbstractSparseArray}, ::Type{AbstractArray}, C, B, As::Vararg{Any,N}) = broadcast_c!(f, Array, Array, C, B, As...) -@inline _sparsifystructured(A::AbstractSparseArray) = A -@inline _sparsifystructured(M::StructuredMatrix) = SparseMatrixCSC(M) -@inline _sparsifystructured(M::Matrix) = SparseMatrixCSC(M) -@inline _sparsifystructured(V::Vector) = SparseVector(V) +@inline _sparsifystructured(M::AbstractMatrix) = SparseMatrixCSC(M) +@inline _sparsifystructured(V::AbstractVector) = SparseVector(V) +@inline _sparsifystructured(M::AbstractSparseMatrix) = SparseMatrixCSC(M) +@inline _sparsifystructured(V::AbstractSparseVector) = SparseVector(V) +@inline _sparsifystructured(S::SparseVecOrMat) = S @inline _sparsifystructured(x) = x diff --git a/test/sparse/higherorderfns.jl b/test/sparse/higherorderfns.jl index a9cbd40de46e3..32b9de28c3dd2 100644 --- a/test/sparse/higherorderfns.jl +++ b/test/sparse/higherorderfns.jl @@ -403,16 +403,19 @@ end densearrays = (C, M) fD, fB = Array(D), Array(B) for X in densearrays - @test (Q = broadcast(+, D, X); Q isa SparseMatrixCSC && Q == sparse(broadcast(+, fD, X))) + @test broadcast(+, D, X)::SparseMatrixCSC == sparse(broadcast(+, fD, X)) @test broadcast!(+, Z, D, X) == sparse(broadcast(+, fD, X)) - @test (Q = broadcast(*, s, B, X); Q isa SparseMatrixCSC && Q == sparse(broadcast(*, s, fB, X))) + @test broadcast(*, s, B, X)::SparseMatrixCSC == sparse(broadcast(*, s, fB, X)) @test broadcast!(*, Z, s, B, X) == sparse(broadcast(*, s, fB, X)) - @test (Q = broadcast(+, V, B, X); Q isa SparseMatrixCSC && Q == sparse(broadcast(+, fV, fB, X))) + @test broadcast(+, V, B, X)::SparseMatrixCSC == sparse(broadcast(+, fV, fB, X)) @test broadcast!(+, Z, V, B, X) == sparse(broadcast(+, fV, fB, X)) - @test (Q = broadcast(+, V, A, X); Q isa SparseMatrixCSC && Q == sparse(broadcast(+, fV, fA, X))) + @test broadcast(+, V, A, X)::SparseMatrixCSC == sparse(broadcast(+, fV, fA, X)) @test broadcast!(+, Z, V, A, X) == sparse(broadcast(+, fV, fA, X)) - @test (Q = broadcast(*, s, V, A, X); Q isa SparseMatrixCSC && Q == sparse(broadcast(*, s, fV, fA, X))) + @test broadcast(*, s, V, A, X)::SparseMatrixCSC == sparse(broadcast(*, s, fV, fA, X)) @test broadcast!(*, Z, s, V, A, X) == sparse(broadcast(*, s, fV, fA, X)) + # Issue #20954 combinations of sparse arrays and RowVectors + @test broadcast(+, A, X')::SparseMatrixCSC == sparse(broadcast(+, fA, X')) + @test broadcast(*, V, X')::SparseMatrixCSC == sparse(broadcast(*, fV, X')) end end From 1a89587d3ef2a0c5016e6c8930af433500e29492 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 14 Mar 2017 14:31:13 -0400 Subject: [PATCH 0194/1534] fix #20999, allow type redefinition with UnionAll-typed fields --- src/interpreter.c | 16 ++++++++++++++-- test/core.jl | 13 +++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/interpreter.c b/src/interpreter.c index e5bd9b99a337f..e724aa172e583 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -130,8 +130,6 @@ static int equiv_type(jl_datatype_t *dta, jl_datatype_t *dtb) } if (!ok) goto no; assert(jl_is_datatype(a)); - if (!jl_egal((jl_value_t*)((jl_datatype_t*)a)->types, (jl_value_t*)dta->types)) - goto no; a = dta->name->wrapper; b = dtb->name->wrapper; while (jl_is_unionall(a)) { @@ -143,6 +141,20 @@ static int equiv_type(jl_datatype_t *dta, jl_datatype_t *dtb) a = jl_instantiate_unionall(ua, (jl_value_t*)ub->var); b = ub->body; } + assert(jl_is_datatype(a) && jl_is_datatype(b)); + size_t i, nf = jl_field_count(dta); + for (i=0; i < nf; i++) { + jl_value_t *ta = jl_svecref(((jl_datatype_t*)a)->types, i); + jl_value_t *tb = jl_svecref(((jl_datatype_t*)b)->types, i); + if (jl_has_free_typevars(ta)) { + if (!jl_has_free_typevars(tb) || !jl_egal(ta, tb)) + goto no; + } + else if (jl_has_free_typevars(tb) || jl_typeof(ta) != jl_typeof(tb) || + !jl_types_equal(ta, tb)) { + goto no; + } + } JL_GC_POP(); return 1; no: diff --git a/test/core.jl b/test/core.jl index bf8dfac0febf5..f90962824d88a 100644 --- a/test/core.jl +++ b/test/core.jl @@ -4756,6 +4756,19 @@ end y::Vector{T} end +# issue #20999, allow more type redefinitions +struct T20999 + x::Array{T} where T<:Real +end + +struct T20999 + x::Array{T} where T<:Real +end + +@test_throws ErrorException struct T20999 + x::Array{T} where T<:Integer +end + let a = Array{Core.BottomType, 1}(2) @test a[1] == Union{} @test a == [Union{}, Union{}] From 1cad4f2556b7ad5acc0e868b0b74f607d0d86a33 Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Wed, 15 Mar 2017 07:08:36 -0700 Subject: [PATCH 0195/1534] Clarify data sharing behavior of vec (#21030) [ci skip] --- base/abstractarraymath.jl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/base/abstractarraymath.jl b/base/abstractarraymath.jl index 14fb13a94a3f7..ec0b6440de291 100644 --- a/base/abstractarraymath.jl +++ b/base/abstractarraymath.jl @@ -12,7 +12,9 @@ all(::typeof(isinteger), ::AbstractArray{<:Integer}) = true """ vec(a::AbstractArray) -> Vector -Reshape array `a` as a one-dimensional column vector. +Reshape the array `a` as a one-dimensional column vector. The resulting array +shares the same underlying data as `a`, so modifying one will also modify the +other. ```jldoctest julia> a = [1 2 3; 4 5 6] @@ -29,6 +31,8 @@ julia> vec(a) 3 6 ``` + +See also [`reshape`](@ref). """ vec(a::AbstractArray) = reshape(a,_length(a)) vec(a::AbstractVector) = a From c3995583c0cc1634c5c191e35cfa6721dd3b9f56 Mon Sep 17 00:00:00 2001 From: Waldir Pimenta Date: Wed, 15 Mar 2017 15:20:10 +0000 Subject: [PATCH 0196/1534] NEWS.md: various fixes (#20996) --- NEWS.md | 133 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 77 insertions(+), 56 deletions(-) diff --git a/NEWS.md b/NEWS.md index 92fbf9b2d0a40..22e46469ec85b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,18 +5,22 @@ New language features --------------------- * New type system capabilities ([#8974], [#18457]) - * Type parameter constraints can refer to previous parameters, e.g. + + + Type parameter constraints can refer to previous parameters, e.g. `type Foo{R<:Real, A<:AbstractArray{R}}`. Can also be used in method definitions. - * New syntax `Array{T} where T<:Integer`, indicating a union of types over all + + + New syntax `Array{T} where T<:Integer`, indicating a union of types over all specified values of `T` (represented by a `UnionAll` type). This provides behavior similar to parametric methods or `typealias`, but can be used anywhere a type is accepted. This syntax can also be used in method definitions, e.g. `function inv(M::Matrix{T}) where T<:AbstractFloat`. Anonymous functions can have type parameters via the syntax `((x::Array{T}) where T<:Real) -> 2x`. - * Implicit type parameters, e.g. `Vector{<:Real}` is equivalent to + + + Implicit type parameters, e.g. `Vector{<:Real}` is equivalent to `Vector{T} where T<:Real`, and similarly for `Vector{>:Int}` ([#20414]). - * Much more accurate subtype and type intersection algorithms. Method sorting and + + + Much more accurate subtype and type intersection algorithms. Method sorting and identification of equivalent and ambiguous methods are improved as a result. Language changes @@ -32,13 +36,18 @@ Language changes ``` the syntax `Foo(x) = new(x)` actually defined a constructor for `Foo{T,S}`, i.e. the case where the type parameters are specified. For clarity, this - definition now must be written as `Foo{T,S}(x) where {T,S<:Real} = new(x)`. ([#11310]) + definition now must be written as `Foo{T,S}(x) where {T,S<:Real} = new(x)` ([#11310]). * The keywords used to define types have changed ([#19157], [#20418]). + + `immutable` changes to `struct` + + `type` changes to `mutable struct` + + `abstract` changes to `abstract type ... end` + + `bitstype 32 Char` changes to `primitive type Char 32 end` + In 0.6, `immutable` and `type` are still allowed as synonyms without a deprecation warning. @@ -46,16 +55,16 @@ Language changes nonstandard command literal is like a nonstandard string literal, but the syntax uses backquotes (``` ` ```) instead of double quotes, and the resulting macro called is suffixed with `_cmd`. For instance, the syntax - ``` q`xyz` ``` is equivalent to `@q_cmd "xyz"`. ([#18644]) + ``` q`xyz` ``` is equivalent to `@q_cmd "xyz"` ([#18644]). * Nonstandard string and command literals can now be qualified with their module. For instance, `Base.r"x"` is now parsed as `Base.@r_str "x"`. - Previously, this syntax parsed as an implicit multiplication. ([#18690]) + Previously, this syntax parsed as an implicit multiplication ([#18690]). * For every binary operator `⨳`, `a .⨳ b` is now automatically equivalent to the `broadcast` call `(⨳).(a, b)`. Hence, one no longer defines methods for `.*` etcetera. This also means that "dot operations" automatically - fuse into a single loop, along with other dot calls `f.(x)`. ([#17623]) + fuse into a single loop, along with other dot calls `f.(x)` ([#17623]). Similarly for unary operators ([#20249]). * Newly defined methods are no longer callable from the same dynamic runtime @@ -71,7 +80,7 @@ Language changes allowing this syntax to be used in the future for discarding values ([#9343], [#18251]). * The `typealias` keyword is deprecated, and should be replaced with - `Vector{T} = Array{T,1}` or a `const` assignment. + `Vector{T} = Array{T,1}` or a `const` assignment ([#20500]). * Experimental feature: `x^n` for integer literals `n` (e.g. `x^3` or `x^-3`) is now lowered to `Base.literal_pow(^, x, Val{n})`, to enable @@ -84,16 +93,16 @@ This section lists changes that do not have deprecation warnings. * `readline`, `readlines` and `eachline` return lines without line endings by default. You *must* use `readline(s, chomp=false)`, etc. to get the old behavior where - returned lines include trailing end-of-line character(s). ([#19944]) + returned lines include trailing end-of-line character(s) ([#19944]). * `String`s no longer have a `.data` field (as part of a significant performance improvement). Use `Vector{UInt8}(str)` to access a string as a byte array. However, allocating the `Vector` object has overhead. You can also use `codeunit(str, i)` to access the `i`th byte of a `String`. Use `sizeof(str)` instead of `length(str.data)`, and `pointer(str)` instead of - `pointer(str.data)`. ([#19449]) + `pointer(str.data)` ([#19449]). - * Operations between `Float16` and `Integers` now return `Float16` instead of `Float32`. ([#17261]) + * Operations between `Float16` and `Integers` now return `Float16` instead of `Float32` ([#17261]). * Keyword arguments are processed left-to-right: if the same keyword is specified more than once, the rightmost occurrence takes precedence ([#17785]). @@ -110,15 +119,15 @@ This section lists changes that do not have deprecation warnings. `broadcast!` or `.=` ([#17623]). * Operations like `.+` and `.*` on `Range` objects are now generic - `broadcast` calls (see above) and produce an `Array`. If you want - a `Range` result, use `+` and `*`, etcetera ([#17623]). + `broadcast` calls (see [above](#language-changes)) and produce an `Array`. + If you want a `Range` result, use `+` and `*`, etcetera ([#17623]). * `broadcast` now treats `Ref` (except for `Ptr`) arguments as 0-dimensional arrays ([#18965]). * `broadcast` now handles missing data (`Nullable`s) allowing operations to be lifted over mixtures of `Nullable`s and scalars, as if the `Nullable` - were like an array with zero or one element. ([#16961], [#19787]). + were like an array with zero or one element ([#16961], [#19787]). * The runtime now enforces when new method definitions can take effect ([#17057]). The flip-side of this is that new method definitions should now reliably actually @@ -134,19 +143,19 @@ This section lists changes that do not have deprecation warnings. removed before `waitfor` seconds. With a `waitfor=0`, `rmprocs` returns immediately without waiting for worker exits. - * `quadgk` has been moved from Base into a separate package. ([#19741]) + * `quadgk` has been moved from Base into a separate package ([#19741]). * The `Collections` module has been removed, and all functions defined therein have been - moved to the `DataStructures` package. ([#19800]) + moved to the `DataStructures` package ([#19800]). * The `RepString` type has been moved to the [LegacyStrings.jl package](https://github.com/JuliaArchive/LegacyStrings.jl). * In macro calls with parentheses, e.g. `@m(a=1)`, assignments are now parsed as - `=` expressions, instead of as `kw` expressions. ([#7669]) + `=` expressions, instead of as `kw` expressions ([#7669]). * When used as an infix operator, `~` is now parsed as a call to an ordinary operator - with assignment precedence, instead of as a macro call. ([#20406]) + with assignment precedence, instead of as a macro call ([#20406]). * (µ "micro" and ɛ "latin epsilon") are considered equivalent to the corresponding Greek characters in identifiers. `\varepsilon` @@ -154,11 +163,11 @@ This section lists changes that do not have deprecation warnings. * `retry` now inputs the keyword arguments `delays` and `check` instead of `n` and `max_delay`. The previous functionality can be achieved setting - `delays` to `ExponentialBackOff`. ([#19331]) + `delays` to `ExponentialBackOff` ([#19331]). * `transpose(::AbstractVector)` now always returns a `RowVector` view of the input (which is a special 1×n-sized `AbstractMatrix`), not a `Matrix`, etc. In particular, for - `v::AbstractVector` we now have `(v.').' === v` and `v.' * v` is a scalar. ([#19670]) + `v::AbstractVector` we now have `(v.').' === v` and `v.' * v` is a scalar ([#19670]). * Parametric types with "unspecified" parameters, such as `Array`, are now represented as `UnionAll` types instead of `DataType`s ([#18457]). @@ -217,18 +226,18 @@ This section lists changes that do not have deprecation warnings. Library improvements -------------------- - * `@views` macro to convert a whole expression or block of code to + * A new `@views` macro was added to convert a whole expression or block of code to use views for all slices ([#20164]). - * `max`, `min`, and related functions (`minmax`, `maximum`, `minimum`, - `extrema`) now return `NaN` for `NaN` arguments ([#12563]). + * `max`, `min`, and related functions (`minmax`, `maximum`, `minimum`, `extrema`) + now return `NaN` for `NaN` arguments ([#12563]). - * `oneunit(x)` function to return a dimensionful version of `one(x)` (which - is clarified to mean a dimensionless quantity if `x` is dimensionful) ([#20268]). + * `oneunit(x)` function to return a dimensionful version of `one(x)` + (which is clarified to mean a dimensionless quantity if `x` is dimensionful) ([#20268]). * The `chop` and `chomp` functions now return a `SubString` ([#18339]). - * Numbered stackframes printed in stacktraces can be opened in an editor by + * Numbered stackframes printed in stacktraces can now be opened in an editor by entering the corresponding number in the REPL and pressing `^Q` ([#19680]). * The REPL now supports something called *prompt pasting* ([#17599]). @@ -238,22 +247,28 @@ Library improvements without having to scrub away prompts and outputs. This can be disabled or enabled at will with `Base.REPL.enable_promptpaste(::Bool)`. - * The function `print_with_color` can now take a color represented by an integer between 0 and 255 inclusive as its first argument ([#18473]). - For a number to color mapping please refer to [this chart](https://upload.wikimedia.org/wikipedia/commons/1/15/Xterm_256color_chart.svg). + * The function `print_with_color` can now take a color + represented by an integer between 0 and 255 inclusive + as its first argument ([#18473]). For a number-to-color mapping, please refer to + [this chart](https://upload.wikimedia.org/wikipedia/commons/1/15/Xterm_256color_chart.svg). It is also possible to use numbers as colors in environment variables that customizes colors in the REPL. For example, to get orange warning messages, simply set `ENV["JULIA_WARN_COLOR"] = 208`. Please note that not all terminals support 256 colors. * The function `print_with_color` no longer prints text in bold by default ([#18628]). - Instead, the function now take a keyword argument `bold::Bool` which determines whether to print in bold or not. - On some terminals, printing a color in non bold results in slightly darker colors being printed than when printing in bold. + Instead, the function now take a keyword argument `bold::Bool` + which determines whether to print in bold or not. On some terminals, printing a color in non bold + results in slightly darker colors being printed than when printing in bold. Therefore, light versions of the colors are now supported. For the available colors see the help entry on `print_with_color`. * The default text style for REPL input and answers has been changed from bold to normal ([#11250]). - They can be changed back to bold by setting the environment variables `JULIA_INPUT_COLOR` and `JULIA_ANSWER_COLOR` to `"bold"`. - For example, one way of doing this is adding `ENV["JULIA_INPUT_COLOR"] = :bold` and `ENV["JULIA_ANSWER_COLOR"] = :bold` to the `.juliarc.jl` file. - See the [manual section on customizing colors](http://docs.julialang.org/en/latest/manual/interacting-with-julia#Customizing-Colors-1) for more information. + They can be changed back to bold by setting the environment variables + `JULIA_INPUT_COLOR` and `JULIA_ANSWER_COLOR` to `"bold"`. + For example, one way of doing this is adding `ENV["JULIA_INPUT_COLOR"] = :bold` + and `ENV["JULIA_ANSWER_COLOR"] = :bold` to the `.juliarc.jl` file. See the + [manual section on customizing colors](http://docs.julialang.org/en/latest/manual/interacting-with-julia#Customizing-Colors-1) + for more information. * The default color for info messages has been changed from blue to cyan ([#18442]), and for warning messages from red to yellow ([#18453]). This @@ -271,57 +286,61 @@ Library improvements you can now do e.g. `[A I]` and it will concatenate an appropriately sized identity matrix ([#19305]). - * New `accumulate` and `accumulate!` functions, which generalize `cumsum` and - `cumprod`. Also known as a [scan](https://en.wikipedia.org/wiki/Prefix_sum) - operation ([#18931]). + * New `accumulate` and `accumulate!` functions were added, which generalize `cumsum` and `cumprod`. + Also known as a [scan](https://en.wikipedia.org/wiki/Prefix_sum) operation ([#18931]). * `reshape` now allows specifying one dimension with a `Colon()` (`:`) for the new shape, in which case that dimension's length will be computed such that its product with all the other dimensions is equal to the length of the original array ([#19919]). - * New `titlecase` function, which capitalizes the first character of each word within a string ([#19469]). + * A new `titlecase` function was added, to capitalize the first character of each word within a string ([#19469]). * `any` and `all` now always short-circuit, and `mapreduce` never short-circuits ([#19543]). That is, not every member of the input iterable will be visited if a `true` (in the case of `any`) or `false` (in the case of `all`) value is found, and `mapreduce` will visit all members of the iterable. - * Additional methods for `ones` and `zeros` functions to support the same signature as the `similar` function ([#19635]). + * Additional methods for `ones` and `zeros` functions were added + to support the same signature as the `similar` function ([#19635]). * `count` now has a `count(itr)` method equivalent to `count(identity, itr)` ([#20403]). - * Methods for `map` and `filter` with `Nullable` arguments have been - implemented; the semantics are as if the `Nullable` were a container with - zero or one elements ([#16961]). + * Methods for `map` and `filter` with `Nullable` arguments have been implemented; + the semantics are as if the `Nullable` were a container with zero or one elements ([#16961]). - * New `@test_warn` and `@test_nowarn` macros in the `Base.Test` module to + * New `@test_warn` and `@test_nowarn` macros were added in the `Base.Test` module to test for the presence or absence of warning messages ([#19903]). - * `logging` can be used to redirect `info`, `warn`, and `error` messages + * `logging` can now be used to redirect `info`, `warn`, and `error` messages either universally or on a per-module/function basis ([#16213]). - * New `iszero(x)` function to quickly check whether `x` is zero (or is all zeros, for an array) ([#19950]). + * A new `iszero(x)` function was added, to quickly check whether `x` is zero + (or is all zeros, for an array) ([#19950]). * `notify` now returns a count of tasks woken up ([#19841]). - * New nonstandard string literal `raw"..."` for creating strings - with no interpolation or unescaping ([#19900]). + * A new nonstandard string literal `raw"..."` was added, + for creating strings with no interpolation or unescaping ([#19900]). - * A new `Dates.Time` type was added that supports representing the time of day with up to nanosecond resolution ([#12274]). + * A new `Dates.Time` type was added that supports representing the time of day + with up to nanosecond resolution ([#12274]). - * New `@macroexpand` macro as a convenient alternative to the `macroexpand` function ([#18660]). + * A new `@macroexpand` macro was added as a convenient alternative to the `macroexpand` function ([#18660]). - * Introduced a wrapper type for lazy complex conjugation of arrays, `ConjArray`. + * A new `ConjArray` type was added, as a wrapper type for lazy complex conjugation of arrays. Currently, it is used by default for the new `RowVector` type only, and enforces that both `transpose(vec)` and `ctranspose(vec)` are views not copies ([#20047]). Compiler/Runtime improvements ----------------------------- -* `ccall` is now implemented as a macro, removing the need for special code-generator support for Intrinsics. + * `ccall` is now implemented as a macro, + removing the need for special code-generator support for Intrinsics. -* `ccall` gained limited support for a `llvmcall` calling-convention. This can replace many uses of `llvmcall` with a simpler, shorter declaration. + * `ccall` gained limited support for a `llvmcall` calling-convention. + This can replace many uses of `llvmcall` with a simpler, shorter declaration. -* All Intrinsics are now Builtin functions instead and have proper error checking and fall-back static compilation support. + * All Intrinsics are now Builtin functions instead and have proper error checking + and fall-back static compilation support. Deprecated or removed --------------------- @@ -354,15 +373,15 @@ Deprecated or removed * `@test_approx_eq x y` has been deprecated in favor of `@test isapprox(x,y)` or `@test x ≈ y` ([#4615]). - * Vectorized functions have been deprecated in favor of dot syntax ([#17302],[#17265], - [#18558],[#19711],[#19712],[#19791],[#19802],[#19931],[#20543],[#20228]). + * Vectorized functions have been deprecated in favor of dot syntax ([#17302], [#17265], + [#18558], [#19711], [#19712], [#19791], [#19802], [#19931], [#20543], [#20228]). * The two-argument forms of `map` (`map!(f, A)`) and `asyncmap!` (`asyncmap!(f, A)`) have been deprecated in anticipation of future semantic changes ([#19721]). * `isimag` has been deprecated ([#19949]). - * `broadcast_zpreserving` has been deprecated ([#19533],[#19720]). + * `broadcast_zpreserving` has been deprecated ([#19533], [#19720]). * `convert` methods from `Diagonal` and `Bidiagonal` to subtypes of `AbstractTriangular` have been deprecated ([#17723]). @@ -457,7 +476,9 @@ Deprecated or removed [#20414]: https://github.com/JuliaLang/julia/issues/20414 [#20418]: https://github.com/JuliaLang/julia/issues/20418 [#20427]: https://github.com/JuliaLang/julia/issues/20427 +[#20500]: https://github.com/JuliaLang/julia/issues/20500 [#20530]: https://github.com/JuliaLang/julia/issues/20530 [#20543]: https://github.com/JuliaLang/julia/issues/20543 [#20609]: https://github.com/JuliaLang/julia/issues/20609 [#20648]: https://github.com/JuliaLang/julia/issues/20648 +[#20889]: https://github.com/JuliaLang/julia/issues/20889 From 08182714e09e3b2243f6f82fa578f54876e2d331 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 15 Mar 2017 17:05:55 -0400 Subject: [PATCH 0197/1534] fix #21028, static parameter value incorrectly set to typevar This issue was caused by 6fb2c67e9e4461d48cbfe57bd30849a6615b06a1. --- src/subtype.c | 2 +- test/subtype.jl | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/subtype.c b/src/subtype.c index e03f88b0fdb98..d1461eefc47ad 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -1292,7 +1292,7 @@ static jl_value_t *finish_unionall(jl_value_t *res, jl_varbinding_t *vb, jl_sten if (vb->right && e->envidx < e->envsz) { jl_value_t *oldval = e->envout[e->envidx]; - if (!varval || (!is_leaf_bound(varval) && !var_occurs_invariant(res, vb->var, 0))) + if (!varval || (!is_leaf_bound(varval) && !vb->occurs_inv)) e->envout[e->envidx] = (jl_value_t*)vb->var; else if (!(oldval && jl_is_typevar(oldval) && jl_is_long(varval))) e->envout[e->envidx] = varval; diff --git a/test/subtype.jl b/test/subtype.jl index 503e6e34eed7e..774929132255d 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -857,6 +857,9 @@ function test_intersection() # issue #20998 _, E = intersection_env(Tuple{Int,Any,Any}, Tuple{T,T,S} where {T,S}) @test length(E) == 2 && E[1] == Int && isa(E[2], TypeVar) + _, E = intersection_env(Tuple{Dict{Int,Type}, Type, Any}, + Tuple{Dict{K,V}, Any, Int} where {K,V}) + @test E[2] == Type end function test_intersection_properties() From d23e7c633b48e5b68ba9ebab1b715c6ac5640264 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Mon, 13 Mar 2017 10:09:55 -0400 Subject: [PATCH 0198/1534] Improve printing of manually thrown `MethodError`s Make sure the world age is only mentioned for valid exception world age and when exception world has no matching method. --- base/reflection.jl | 9 ++++----- base/replutil.jl | 3 ++- test/replutil.jl | 42 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/base/reflection.jl b/base/reflection.jl index 1286689f75283..d4ff5fe571998 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -924,21 +924,20 @@ function function_module(f::ANY, types::ANY) end """ - method_exists(f, Tuple type) -> Bool + method_exists(f, Tuple type, world=typemax(UInt)) -> Bool Determine whether the given generic function has a method matching the given -`Tuple` of argument types. +`Tuple` of argument types with the upper bound of world age given by `world`. ```jldoctest julia> method_exists(length, Tuple{Array}) true ``` """ -function method_exists(f::ANY, t::ANY) +function method_exists(f::ANY, t::ANY, world=typemax(UInt)) t = to_tuple_type(t) t = Tuple{isa(f,Type) ? Type{f} : typeof(f), t.parameters...} - return ccall(:jl_method_exists, Cint, (Any, Any, UInt), typeof(f).name.mt, t, - typemax(UInt)) != 0 + return ccall(:jl_method_exists, Cint, (Any, Any, UInt), typeof(f).name.mt, t, world) != 0 end """ diff --git a/base/replutil.jl b/base/replutil.jl index 3c6a7f412b382..3827db8bd278a 100644 --- a/base/replutil.jl +++ b/base/replutil.jl @@ -365,7 +365,8 @@ function showerror(io::IO, ex::MethodError) print(io, "You may have intended to import Base.", name) end end - if method_exists(ex.f, arg_types) + if (ex.world != typemax(UInt) && method_exists(ex.f, arg_types) && + !method_exists(ex.f, arg_types, ex.world)) curworld = ccall(:jl_get_world_counter, UInt, ()) println(io) print(io, "The applicable method may be too new: running in world age $(ex.world), while current world is $(curworld).") diff --git a/test/replutil.jl b/test/replutil.jl index 84b299460320d..8d00670c63d1d 100644 --- a/test/replutil.jl +++ b/test/replutil.jl @@ -530,3 +530,45 @@ let @test !startswith(method_string, "(::Type{T})(arg) where T in Base at sysimg.jl") end end + +@testset "show for manually thrown MethodError" begin + global f21006 + + f21006() = nothing + # Normal method error should not warn about world age. + ex1 = try + f21006(()) + catch e + e + end::MethodError + str = sprint(Base.showerror, ex1) + @test startswith(str, "MethodError: no method matching f21006(::Tuple{})") + @test !contains(str, "The applicable method may be too new") + + # If newer applicable methods are available, world age should be mentioned. + f21006(x) = x + @test f21006(()) === () + str = sprint(Base.showerror, ex1) + @test startswith(str, "MethodError: no method matching f21006(::Tuple{})") + @test contains(str, "The applicable method may be too new: running in world age $(ex1.world)") + + # This method error should be thrown in a world new enough for `f21006(())`. + # Also makes sure it's printed correctly. + ex2 = try + f21006((), ()) + catch e + e + end::MethodError + str = sprint(Base.showerror, ex2) + @test startswith(str, "MethodError: no method matching f21006(::Tuple{}, ::Tuple{})") + @test !contains(str, "The applicable method may be too new") + + # If the method is available in the exception world or if the exception world is invalid, + # don't warn about world age + for ex3 in (MethodError(ex1.f, ex1.args, ex2.world), + MethodError(ex1.f, ex1.args, typemax(UInt))) + str = sprint(Base.showerror, ex3) + @test startswith(str, "MethodError: no method matching f21006(::Tuple{})") + @test !contains(str, "The applicable method may be too new") + end +end From 97ddb1845aae3003caf607aa102ea9d798945cbb Mon Sep 17 00:00:00 2001 From: Amit Murthy Date: Thu, 16 Mar 2017 11:15:01 +0530 Subject: [PATCH 0199/1534] Update NEWS.md w.r.t. removal of localize_vars [ci skip] (#21034) Changes related to PR #19594 --- NEWS.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/NEWS.md b/NEWS.md index 22e46469ec85b..9b6c0b5c4f8b6 100644 --- a/NEWS.md +++ b/NEWS.md @@ -223,6 +223,15 @@ This section lists changes that do not have deprecation warnings. * `write` on an `IOBuffer` now returns a signed integer in order to be consistent with other buffers ([#20609]). + * `@async`, `@spawn`, `@spawnat`, `@fetch` and `@fetchfrom` no longer implicitly + localize variables. Previously, the expression would be wrapped in an implicit + `let` block ([#19594]). + + * Closures shipped for remote execution via `@spawn` or `remotecall` now automatically + serialize globals defined under Main. For details, please refer to the paragraph + on "Global variables" under the "Parallel computing" chapter in the manual ([#19594]). + + Library improvements -------------------- From 102800a54343f58e798b97fd8946437ca95f2352 Mon Sep 17 00:00:00 2001 From: Amit Murthy Date: Thu, 16 Mar 2017 11:16:15 +0530 Subject: [PATCH 0200/1534] Correct error message when adding/removing processes from workers (#21033) --- base/distributed/cluster.jl | 13 +++++++++---- test/distributed_exec.jl | 10 ++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/base/distributed/cluster.jl b/base/distributed/cluster.jl index 6dfd36e99786b..d307382dc4884 100644 --- a/base/distributed/cluster.jl +++ b/base/distributed/cluster.jl @@ -278,6 +278,8 @@ master can be specified via variable `JULIA_WORKER_TIMEOUT` in the worker proces environment. Relevant only when using TCP/IP as transport. """ function addprocs(manager::ClusterManager; kwargs...) + cluster_mgmt_from_master_check() + lock(worker_lock) try addprocs_locked(manager::ClusterManager; kwargs...) @@ -662,6 +664,12 @@ function workers() end end +function cluster_mgmt_from_master_check() + if myid() != 1 + throw(ErrorException("Only process 1 can add and remove workers")) + end +end + """ rmprocs(pids...; waitfor=typemax(Int)) @@ -678,10 +686,7 @@ Argument `waitfor` specifies how long to wait for the workers to shut down: parallel calls. """ function rmprocs(pids...; waitfor=typemax(Int)) - # Only pid 1 can add and remove processes - if myid() != 1 - throw(ErrorException("only process 1 can add and remove processes")) - end + cluster_mgmt_from_master_check() pids = vcat(pids...) if waitfor == 0 diff --git a/test/distributed_exec.jl b/test/distributed_exec.jl index 0c6f0ee59d178..4a90015c89934 100644 --- a/test/distributed_exec.jl +++ b/test/distributed_exec.jl @@ -1272,6 +1272,16 @@ if DoFullTest rmprocs(pids) end +# Test addprocs/rmprocs from master node only +for f in [ ()->addprocs(1), ()->rmprocs(workers()) ] + try + remotecall_fetch(f, id_other) + catch ex + @test isa(ex, RemoteException) + @test ex.captured.ex.msg == "Only process 1 can add and remove workers" + end +end + # Auto serialization of globals from Main. # bitstypes global v1 = 1 From 028a4b16e52ba397f60af23a94921eb5c1df9f24 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Thu, 16 Mar 2017 06:29:16 -0700 Subject: [PATCH 0201/1534] Clarify some license exceptions FFTW wrappers were moved and mostly rewritten - the Julia wrappers are probably not GPL? ref https://github.com/JuliaLang/julia/commit/481f3517d7dc00ac89c3a53f29a5a73faa1f3650 and https://github.com/JuliaLang/julia/issues/8248 and https://github.com/JuliaLang/julia/pull/12201 make note of grisu derived license in top-level LICENSE.md and update links, repo was moved from github.com/floitsch to github.com/google umfpack and cholmod code were moved from base/linalg to base/sparse --- LICENSE.md | 6 +++--- README.md | 1 - base/grisu/bignum.jl | 2 +- base/grisu/bignums.jl | 2 +- base/grisu/fastfixed.jl | 2 +- base/grisu/fastprecision.jl | 2 +- base/grisu/fastshortest.jl | 2 +- base/grisu/float.jl | 2 +- 8 files changed, 9 insertions(+), 10 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index c81b1ef7ea7f4..e601fa09f6be3 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -70,9 +70,9 @@ their own licenses: The following components of Julia's standard library have separate licenses: -- base/fftw.jl (see [FFTW](http://fftw.org/doc/License-and-Copyright.html)) -- base/linalg/umfpack.jl (see [SUITESPARSE](http://faculty.cse.tamu.edu/davis/suitesparse.html)) -- base/linalg/cholmod.jl (see [SUITESPARSE](http://faculty.cse.tamu.edu/davis/suitesparse.html)) +- base/grisu/* (see [double-conversion](https://github.com/google/double-conversion/blob/master/LICENSE)) +- base/sparse/umfpack.jl (see [SUITESPARSE](http://faculty.cse.tamu.edu/davis/suitesparse.html)) +- base/sparse/cholmod.jl (see [SUITESPARSE](http://faculty.cse.tamu.edu/davis/suitesparse.html)) - base/special/exp.jl (see [FREEBSD MSUN](https://github.com/freebsd/freebsd) [FreeBSD/2-clause BSD/Simplified BSD License]) diff --git a/README.md b/README.md index 43e19ece0f37e..6e4eae1e1e281 100644 --- a/README.md +++ b/README.md @@ -323,7 +323,6 @@ Julia uses the following external libraries, which are automatically downloaded [FemtoLisp]: https://github.com/JeffBezanson/femtolisp [GMP]: http://gmplib.org [MPFR]: http://www.mpfr.org -[double-conversion]: http://double-conversion.googlecode.com [libuv]: https://github.com/JuliaLang/libuv [libgit2]: https://libgit2.github.com/ [utf8proc]: http://julialang.org/utf8proc/ diff --git a/base/grisu/bignum.jl b/base/grisu/bignum.jl index 2182602163537..734dbefca1f1a 100644 --- a/base/grisu/bignum.jl +++ b/base/grisu/bignum.jl @@ -1,5 +1,5 @@ # This file is a part of Julia, but is derived from -# https://github.com/floitsch/double-conversion which has the following license +# https://github.com/google/double-conversion which has the following license # # Copyright 2006-2014, the V8 project authors. All rights reserved. # Redistribution and use in source and binary forms, with or without diff --git a/base/grisu/bignums.jl b/base/grisu/bignums.jl index fe50bf35a12ef..14fb922edb3df 100644 --- a/base/grisu/bignums.jl +++ b/base/grisu/bignums.jl @@ -1,5 +1,5 @@ # This file is a part of Julia, but is derived from -# https://github.com/floitsch/double-conversion which has the following license +# https://github.com/google/double-conversion which has the following license # # Copyright 2006-2014, the V8 project authors. All rights reserved. # Redistribution and use in source and binary forms, with or without diff --git a/base/grisu/fastfixed.jl b/base/grisu/fastfixed.jl index f1eda5058ad5a..014806b6531ea 100644 --- a/base/grisu/fastfixed.jl +++ b/base/grisu/fastfixed.jl @@ -1,5 +1,5 @@ # This file is a part of Julia, but is derived from -# https://github.com/floitsch/double-conversion which has the following license +# https://github.com/google/double-conversion which has the following license # # Copyright 2006-2014, the V8 project authors. All rights reserved. # Redistribution and use in source and binary forms, with or without diff --git a/base/grisu/fastprecision.jl b/base/grisu/fastprecision.jl index 4167557f034fc..d4515f96a0b3d 100644 --- a/base/grisu/fastprecision.jl +++ b/base/grisu/fastprecision.jl @@ -1,5 +1,5 @@ # This file is a part of Julia, but is derived from -# https://github.com/floitsch/double-conversion which has the following license +# https://github.com/google/double-conversion which has the following license # # Copyright 2006-2014, the V8 project authors. All rights reserved. # Redistribution and use in source and binary forms, with or without diff --git a/base/grisu/fastshortest.jl b/base/grisu/fastshortest.jl index 519850e009abc..0f4ef6c9cc80b 100644 --- a/base/grisu/fastshortest.jl +++ b/base/grisu/fastshortest.jl @@ -1,5 +1,5 @@ # This file is a part of Julia, but is derived from -# https://github.com/floitsch/double-conversion which has the following license +# https://github.com/google/double-conversion which has the following license # # Copyright 2006-2014, the V8 project authors. All rights reserved. # Redistribution and use in source and binary forms, with or without diff --git a/base/grisu/float.jl b/base/grisu/float.jl index c545b8c10d216..24073c5c3a4cf 100644 --- a/base/grisu/float.jl +++ b/base/grisu/float.jl @@ -1,5 +1,5 @@ # This file is a part of Julia, but is derived from -# https://github.com/floitsch/double-conversion which has the following license +# https://github.com/google/double-conversion which has the following license # # Copyright 2006-2014, the V8 project authors. All rights reserved. # Redistribution and use in source and binary forms, with or without From b2795eb4d5aed38abd95495be049e29693d7b52e Mon Sep 17 00:00:00 2001 From: Andy Ferris Date: Fri, 17 Mar 2017 02:58:13 +1000 Subject: [PATCH 0202/1534] RFC: Added recursive transpose to `Diagonal` (#21019) * Added recursive transpose to `Diagonal` `Diagonal` might be used to represent a block-diagonal matrix structure. * Fixes plus expm, logm, sqrtm --- base/linalg/diagonal.jl | 15 +++++++++++---- test/linalg/diagonal.jl | 24 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/base/linalg/diagonal.jl b/base/linalg/diagonal.jl index 4da93594a9b1e..66fe02e8f5e99 100644 --- a/base/linalg/diagonal.jl +++ b/base/linalg/diagonal.jl @@ -101,8 +101,10 @@ end parent(D::Diagonal) = D.diag ishermitian(D::Diagonal{<:Real}) = true -ishermitian(D::Diagonal) = isreal(D.diag) -issymmetric(D::Diagonal) = true +ishermitian(D::Diagonal{<:Number}) = isreal(D.diag) +ishermitian(D::Diagonal) = all(ishermitian, D.diag) +issymmetric(D::Diagonal{<:Number}) = true +issymmetric(D::Diagonal) = all(issymmetric, D.diag) isposdef(D::Diagonal) = all(x -> x > 0, D.diag) factorize(D::Diagonal) = D @@ -260,8 +262,10 @@ end @inline A_mul_Bc(D::Diagonal, rowvec::RowVector) = D*ctranspose(rowvec) conj(D::Diagonal) = Diagonal(conj(D.diag)) -transpose(D::Diagonal) = D -ctranspose(D::Diagonal) = conj(D) +transpose(D::Diagonal{<:Number}) = D +transpose(D::Diagonal) = Diagonal(transpose.(D.diag)) +ctranspose(D::Diagonal{<:Number}) = conj(D) +ctranspose(D::Diagonal) = Diagonal(ctranspose.(D.diag)) diag(D::Diagonal) = D.diag trace(D::Diagonal) = sum(D.diag) @@ -275,8 +279,11 @@ end eye{T}(::Type{Diagonal{T}}, n::Int) = Diagonal(ones(T,n)) expm(D::Diagonal) = Diagonal(exp.(D.diag)) +expm(D::Diagonal{<:AbstractMatrix}) = Diagonal(expm.(D.diag)) logm(D::Diagonal) = Diagonal(log.(D.diag)) +logm(D::Diagonal{<:AbstractMatrix}) = Diagonal(logm.(D.diag)) sqrtm(D::Diagonal) = Diagonal(sqrt.(D.diag)) +sqrtm(D::Diagonal{<:AbstractMatrix}) = Diagonal(sqrtm.(D.diag)) #Linear solver function A_ldiv_B!(D::Diagonal, B::StridedVecOrMat) diff --git a/test/linalg/diagonal.jl b/test/linalg/diagonal.jl index 9031e2dde7aa2..502adf31c408c 100644 --- a/test/linalg/diagonal.jl +++ b/test/linalg/diagonal.jl @@ -304,3 +304,27 @@ end Q = qrfact(randn(5, 5))[:Q] @test D * Q' == Array(D) * Q' end + +@testset "block diagonal matrices" begin + D = Diagonal([[1 2; 3 4], [1 2; 3 4]]) + Dherm = Diagonal([[1 1+im; 1-im 1], [1 1+im; 1-im 1]]) + Dsym = Diagonal([[1 1+im; 1+im 1], [1 1+im; 1+im 1]]) + @test D' == Diagonal([[1 3; 2 4], [1 3; 2 4]]) + @test D.' == Diagonal([[1 3; 2 4], [1 3; 2 4]]) + @test Dherm' == Dherm + @test Dherm.' == Diagonal([[1 1-im; 1+im 1], [1 1-im; 1+im 1]]) + @test Dsym' == Diagonal([[1 1-im; 1-im 1], [1 1-im; 1-im 1]]) + @test Dsym.' == Dsym + + @test issymmetric(D) == false + @test issymmetric(Dherm) == false + @test issymmetric(Dsym) == true + + @test ishermitian(D) == false + @test ishermitian(Dherm) == true + @test ishermitian(Dsym) == false + + @test expm(D) == Diagonal([expm([1 2; 3 4]), expm([1 2; 3 4])]) + @test logm(D) == Diagonal([logm([1 2; 3 4]), logm([1 2; 3 4])]) + @test sqrtm(D) == Diagonal([sqrtm([1 2; 3 4]), sqrtm([1 2; 3 4])]) +end From 540728706239a8a3a625cf0548423a424351d106 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Wed, 8 Feb 2017 01:14:56 -0800 Subject: [PATCH 0203/1534] fix strtod indentation and mention it in LICENSE.md ref https://github.com/JuliaLang/julia/pull/5988 --- LICENSE.md | 1 + src/support/strtod.c | 167 ++++++++++++++++++++----------------------- 2 files changed, 79 insertions(+), 89 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index e601fa09f6be3..1d812d2a7c300 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -35,6 +35,7 @@ Julia includes code from the following projects, which have their own licenses: - [MUSL](http://git.musl-libc.org/cgit/musl/tree/COPYRIGHT) (for getopt implementation on Windows) [MIT] - [MINGW](https://sourceforge.net/p/mingw/mingw-org-wsl/ci/legacy/tree/mingwrt/mingwex/dirname.c) (for dirname implementation on Windows) [MIT] - [NetBSD](http://www.netbsd.org/about/redistribution.html) (for setjmp, longjmp, and strptime implementations on Windows) [BSD-3] +- [Python](https://docs.python.org/2/license.html) (for strtod implementation on Windows) [BSD-3, effectively] - [randmtzig.c](https://github.com/JuliaLang/julia/blob/master/test/perf/micro/randmtzig.c) for Gaussian random number generation (for C benchmarks only) [BSD-3] The Julia language links to the following external libraries, which have their diff --git a/src/support/strtod.c b/src/support/strtod.c index 1dc2b961576ca..fe617da2490d2 100644 --- a/src/support/strtod.c +++ b/src/support/strtod.c @@ -20,22 +20,21 @@ static locale_t c_locale; locale_t get_c_locale(void) { - if(!c_locale_initialized) - { - c_locale_initialized = 1; - c_locale = newlocale(LC_ALL_MASK, "C", NULL); - } - return c_locale; + if (!c_locale_initialized) { + c_locale_initialized = 1; + c_locale = newlocale(LC_ALL_MASK, "C", NULL); + } + return c_locale; } JL_DLLEXPORT double jl_strtod_c(const char *nptr, char **endptr) { - return strtod_l(nptr, endptr, get_c_locale()); + return strtod_l(nptr, endptr, get_c_locale()); } JL_DLLEXPORT float jl_strtof_c(const char *nptr, char **endptr) { - return strtof_l(nptr, endptr, get_c_locale()); + return strtof_l(nptr, endptr, get_c_locale()); } @@ -58,7 +57,7 @@ JL_DLLEXPORT float jl_strtof_c(const char *nptr, char **endptr) int case_insensitive_match(const char *s, const char *t) { - while(*t && tolower(*s) == *t) { + while (*t && tolower(*s) == *t) { s++; t++; } @@ -147,84 +146,75 @@ JL_DLLEXPORT double jl_strtod_c(const char *nptr, char **endptr) } /* This code path is used for hex floats */ - if (*p == '0' && (*(p+1) == 'x' || *(p+1) == 'X')) - { - digits_pos = p; - p += 2; - /* Check that what's left begins with a digit or decimal point */ - if (!isxdigit(*p) && *p != '.') - goto invalid_string; - - - if (decimal_point[0] != '.' || - decimal_point[1] != 0) - { - /* Look for a '.' in the input; if present, it'll need to be - swapped for the current locale's decimal point before we - call strtod. On the other hand, if we find the current - locale's decimal point then the input is invalid. */ - while (isxdigit(*p)) - p++; - - if (*p == '.') - { - decimal_point_pos = p++; - - /* locate end of number */ - while (isxdigit(*p)) - p++; - - if (*p == 'p' || *p == 'P') - p++; - if (*p == '+' || *p == '-') - p++; - while (isdigit(*p)) - p++; - end = p; - } - else if (strncmp(p, decimal_point, decimal_point_len) == 0) - goto invalid_string; - /* For the other cases, we need not convert the decimal - point */ - } - } else - { - /* Check that what's left begins with a digit or decimal point */ - if (!isdigit(*p) && *p != '.') - goto invalid_string; - - digits_pos = p; - if (decimal_point[0] != '.' || - decimal_point[1] != 0) - { - /* Look for a '.' in the input; if present, it'll need to be - swapped for the current locale's decimal point before we - call strtod. On the other hand, if we find the current - locale's decimal point then the input is invalid. */ - while (isdigit(*p)) - p++; - - if (*p == '.') - { - decimal_point_pos = p++; - - /* locate end of number */ - while (isdigit(*p)) - p++; - - if (*p == 'e' || *p == 'E') - p++; - if (*p == '+' || *p == '-') - p++; - while (isdigit(*p)) - p++; - end = p; - } - else if (strncmp(p, decimal_point, decimal_point_len) == 0) + if (*p == '0' && (*(p+1) == 'x' || *(p+1) == 'X')) { + digits_pos = p; + p += 2; + /* Check that what's left begins with a digit or decimal point */ + if (!isxdigit(*p) && *p != '.') + goto invalid_string; + + + if (decimal_point[0] != '.' || decimal_point[1] != 0) { + /* Look for a '.' in the input; if present, it'll need to be + swapped for the current locale's decimal point before we + call strtod. On the other hand, if we find the current + locale's decimal point then the input is invalid. */ + while (isxdigit(*p)) + p++; + + if (*p == '.') { + decimal_point_pos = p++; + + /* locate end of number */ + while (isxdigit(*p)) + p++; + + if (*p == 'p' || *p == 'P') + p++; + if (*p == '+' || *p == '-') + p++; + while (isdigit(*p)) + p++; + end = p; + } + else if (strncmp(p, decimal_point, decimal_point_len) == 0) + goto invalid_string; + /* For the other cases, we need not convert the decimal point */ + } + } + else { + /* Check that what's left begins with a digit or decimal point */ + if (!isdigit(*p) && *p != '.') goto invalid_string; - /* For the other cases, we need not convert the decimal - point */ - } + + digits_pos = p; + if (decimal_point[0] != '.' || decimal_point[1] != 0) { + /* Look for a '.' in the input; if present, it'll need to be + swapped for the current locale's decimal point before we + call strtod. On the other hand, if we find the current + locale's decimal point then the input is invalid. */ + while (isdigit(*p)) + p++; + + if (*p == '.') { + decimal_point_pos = p++; + + /* locate end of number */ + while (isdigit(*p)) + p++; + + if (*p == 'e' || *p == 'E') + p++; + if (*p == '+' || *p == '-') + p++; + while (isdigit(*p)) + p++; + end = p; + } + else if (strncmp(p, decimal_point, decimal_point_len) == 0) + goto invalid_string; + /* For the other cases, we need not convert the decimal point */ + } } if (decimal_point_pos) { @@ -263,7 +253,6 @@ JL_DLLEXPORT double jl_strtod_c(const char *nptr, char **endptr) } free(copy); - } else { val = strtod(digits_pos, &fail_pos); @@ -278,7 +267,7 @@ JL_DLLEXPORT double jl_strtod_c(const char *nptr, char **endptr) return val; - invalid_string: +invalid_string: *endptr = (char*)nptr; errno = EINVAL; return -1.0; @@ -287,7 +276,7 @@ JL_DLLEXPORT double jl_strtod_c(const char *nptr, char **endptr) JL_DLLEXPORT float jl_strtof_c(const char *nptr, char **endptr) { - return (float) jl_strtod_c(nptr, endptr); + return (float) jl_strtod_c(nptr, endptr); } #endif From e8e8012b25567f1817c38065948c97867401ff2c Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Thu, 16 Mar 2017 20:18:27 +0000 Subject: [PATCH 0204/1534] Change default proxy settings to auto (#21044) --- base/libgit2/consts.jl | 5 +++++ base/libgit2/types.jl | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/base/libgit2/consts.jl b/base/libgit2/consts.jl index 5810e3293db14..0e563e35ebeb4 100644 --- a/base/libgit2/consts.jl +++ b/base/libgit2/consts.jl @@ -345,4 +345,9 @@ These are used to select which global option to set or get and are used in `git_ SET_TEMPLATE_PATH = 11, SET_SSL_CERT_LOCATIONS = 12) + + @enum(GIT_PROXY, PROXY_NONE, + PROXY_AUTO, + PROXY_SPECIFIED) + end diff --git a/base/libgit2/types.jl b/base/libgit2/types.jl index 3227475631d46..a2296354dc57a 100644 --- a/base/libgit2/types.jl +++ b/base/libgit2/types.jl @@ -196,8 +196,8 @@ Options for connecting through a proxy. Matches the [`git_proxy_options`](https://libgit2.github.com/libgit2/#HEAD/type/git_proxy_options) struct. """ @kwdef struct ProxyOptions - version::Cuint = 1 - proxytype::Cint + version::Cuint = 1 + proxytype::Consts.GIT_PROXY = Consts.PROXY_AUTO url::Cstring credential_cb::Ptr{Void} certificate_cb::Ptr{Void} @@ -611,7 +611,7 @@ function with_warn{T}(f::Function, ::Type{T}, args...) end """ - LibGit2.Const.OBJECT{T<:GitObject}(::Type{T}) + LibGit2.Consts.OBJECT{T<:GitObject}(::Type{T}) The `OBJECT` enum value corresponding to type `T`. """ From c3f2f4ccca5da3465f278a0c6beb0bdf3d4b3bf1 Mon Sep 17 00:00:00 2001 From: Jonas Klasen Date: Thu, 16 Mar 2017 22:09:20 +0100 Subject: [PATCH 0205/1534] documentation: change `immutable` to `struct` (#21056) --- doc/src/stdlib/test.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/stdlib/test.md b/doc/src/stdlib/test.md index 7c4195014b0e0..f4e2999fbf06e 100644 --- a/doc/src/stdlib/test.md +++ b/doc/src/stdlib/test.md @@ -235,7 +235,7 @@ Defining a basic `AbstractTestSet` subtype might look like: import Base.Test: record, finish using Base.Test: AbstractTestSet, Result, Pass, Fail, Error using Base.Test: get_testset_depth, get_testset -immutable CustomTestSet <: Base.Test.AbstractTestSet +struct CustomTestSet <: Base.Test.AbstractTestSet description::AbstractString foo::Int results::Vector From 2f1fdb941b2bf28feaf6d893a1c7ee3d55c69209 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Thu, 16 Mar 2017 15:33:20 -0400 Subject: [PATCH 0206/1534] Fix errors in, and run, add_license_to_files.jl --- base/dates/parse.jl | 2 ++ base/libgit2/types.jl | 1 + base/linalg/rowvector.jl | 2 ++ base/summarysize.jl | 2 ++ base/weakkeydict.jl | 2 ++ contrib/add_license_to_files.jl | 3 ++- src/support/crc32c-tables.c | 2 ++ src/support/crc32c.h | 2 ++ test/dimensionful.jl | 2 ++ test/iostream.jl | 2 ++ test/iterators.jl | 2 ++ test/osutils.jl | 2 ++ test/runtests.jl | 1 + test/sparse/higherorderfns.jl | 2 +- test/subtype.jl | 2 ++ test/util/segfault.jl | 2 ++ test/util/throw_error_exception.jl | 2 ++ 17 files changed, 31 insertions(+), 2 deletions(-) diff --git a/base/dates/parse.jl b/base/dates/parse.jl index e638319f10b09..7fdfb4d7c85e9 100644 --- a/base/dates/parse.jl +++ b/base/dates/parse.jl @@ -1,3 +1,5 @@ +# This file is a part of Julia. License is MIT: http://julialang.org/license + ### Parsing utilities @generated function tryparse_internal{T<:TimeType, S, F}(::Type{T}, str::AbstractString, df::DateFormat{S, F}, raise::Bool=false) diff --git a/base/libgit2/types.jl b/base/libgit2/types.jl index a2296354dc57a..cec1e28081e5e 100644 --- a/base/libgit2/types.jl +++ b/base/libgit2/types.jl @@ -1,4 +1,5 @@ # This file is a part of Julia. License is MIT: http://julialang.org/license + import Base.@kwdef import .Consts: GIT_SUBMODULE_IGNORE, GIT_MERGE_FILE_FAVOR, GIT_MERGE_FILE diff --git a/base/linalg/rowvector.jl b/base/linalg/rowvector.jl index aaca0d86d3917..dd8607fad9349 100644 --- a/base/linalg/rowvector.jl +++ b/base/linalg/rowvector.jl @@ -1,3 +1,5 @@ +# This file is a part of Julia. License is MIT: http://julialang.org/license + """ RowVector(vector) diff --git a/base/summarysize.jl b/base/summarysize.jl index 174f18f3cf8fc..7fd7a6e71c304 100644 --- a/base/summarysize.jl +++ b/base/summarysize.jl @@ -1,3 +1,5 @@ +# This file is a part of Julia. License is MIT: http://julialang.org/license + struct SummarySize seen::ObjectIdDict frontier_x::Vector{Any} diff --git a/base/weakkeydict.jl b/base/weakkeydict.jl index a20be01394a26..1eb2822e70d8a 100644 --- a/base/weakkeydict.jl +++ b/base/weakkeydict.jl @@ -1,3 +1,5 @@ +# This file is a part of Julia. License is MIT: http://julialang.org/license + # weak key dictionaries """ diff --git a/contrib/add_license_to_files.jl b/contrib/add_license_to_files.jl index 7cfaae2ab9f0a..2bfc43da2d934 100644 --- a/contrib/add_license_to_files.jl +++ b/contrib/add_license_to_files.jl @@ -34,7 +34,7 @@ const skipfiles = [ # files to check - already copyright # see: https://github.com/JuliaLang/julia/pull/11073#issuecomment-98099389 "../base/special/trig.jl", - "../base/special/exp.jl" + "../base/special/exp.jl", "../base/linalg/givens.jl", # "../src/abi_llvm.cpp", @@ -59,6 +59,7 @@ const skipfiles = [ "../src/support/utf8.c", "../test/perf/micro/randmtzig.c", "../src/support/crc32c.c", + "../examples/quine.jl", # has license text in code ] const ext_prefix = Dict([ diff --git a/src/support/crc32c-tables.c b/src/support/crc32c-tables.c index 10811d6cc3edf..539b3577175b6 100644 --- a/src/support/crc32c-tables.c +++ b/src/support/crc32c-tables.c @@ -1,3 +1,5 @@ +// This file is a part of Julia. License is MIT: http://julialang.org/license + /* Pregenerated tables for crc32c.c, produced by compiling with -DGEN_CRC32C_TABLES. */ #if POLY != 0x82f63b78 # error "tables generated for different polynomial" diff --git a/src/support/crc32c.h b/src/support/crc32c.h index fbec8256168e4..559cf35903a00 100644 --- a/src/support/crc32c.h +++ b/src/support/crc32c.h @@ -1,3 +1,5 @@ +// This file is a part of Julia. License is MIT: http://julialang.org/license + #ifndef CRC32C_H #define CRC32C_H 1 diff --git a/test/dimensionful.jl b/test/dimensionful.jl index 5abc866329c67..f7450b896401f 100644 --- a/test/dimensionful.jl +++ b/test/dimensionful.jl @@ -1,3 +1,5 @@ +# This file is a part of Julia. License is MIT: http://julialang.org/license + # Here we implement a minimal dimensionful type Furlong, which is used # to test dimensional correctness of various functions in Base. Furlong # is exported by the TestHelpers module. diff --git a/test/iostream.jl b/test/iostream.jl index fb241ae728e8c..3ca501aa8e4ab 100644 --- a/test/iostream.jl +++ b/test/iostream.jl @@ -1,3 +1,5 @@ +# This file is a part of Julia. License is MIT: http://julialang.org/license + # Test skipchars for IOStreams mktemp() do path, file function append_to_file(str) diff --git a/test/iterators.jl b/test/iterators.jl index 3f7b96e8b6b57..d3e8baf65dd1d 100644 --- a/test/iterators.jl +++ b/test/iterators.jl @@ -1,3 +1,5 @@ +# This file is a part of Julia. License is MIT: http://julialang.org/license + using Base.Iterators # zip and filter iterators diff --git a/test/osutils.jl b/test/osutils.jl index e75ded56a1eaf..3eba2323a9a3e 100644 --- a/test/osutils.jl +++ b/test/osutils.jl @@ -1,3 +1,5 @@ +# This file is a part of Julia. License is MIT: http://julialang.org/license + @test !Base.is_unix(:Windows) @test !Base.is_linux(:Windows) @test Base.is_linux(:Linux) diff --git a/test/runtests.jl b/test/runtests.jl index 539e69eba4ae0..72585cf098959 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,4 +1,5 @@ # This file is a part of Julia. License is MIT: http://julialang.org/license + using Base.Test include("choosetests.jl") tests, net_on = choosetests(ARGS) diff --git a/test/sparse/higherorderfns.jl b/test/sparse/higherorderfns.jl index a9cbd40de46e3..76714ce3430bc 100644 --- a/test/sparse/higherorderfns.jl +++ b/test/sparse/higherorderfns.jl @@ -1,5 +1,5 @@ # This file is a part of Julia. License is MIT: http://julialang.org/license -# + # These tests cover the higher order functions specialized for sparse arrays defined in # base/sparse/higherorderfns.jl, particularly map[!]/broadcast[!] for SparseVectors and # SparseMatrixCSCs at present. diff --git a/test/subtype.jl b/test/subtype.jl index 6356244c4a95b..43ff5ce159d99 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -1,3 +1,5 @@ +# This file is a part of Julia. License is MIT: http://julialang.org/license + using Base.Bottom using Base.Test diff --git a/test/util/segfault.jl b/test/util/segfault.jl index 245005eeb615e..ebc1a5d8edb90 100644 --- a/test/util/segfault.jl +++ b/test/util/segfault.jl @@ -1 +1,3 @@ +# This file is a part of Julia. License is MIT: http://julialang.org/license + unsafe_load(convert(Ptr{UInt8},C_NULL)) diff --git a/test/util/throw_error_exception.jl b/test/util/throw_error_exception.jl index 847f4b26321ac..035afea8388ff 100644 --- a/test/util/throw_error_exception.jl +++ b/test/util/throw_error_exception.jl @@ -1 +1,3 @@ +# This file is a part of Julia. License is MIT: http://julialang.org/license + error("This purposefully dies") From 36b88ae5a2f27b98947fc0dd028d2facf8746cda Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Thu, 16 Mar 2017 15:34:30 -0400 Subject: [PATCH 0207/1534] Fix line numbers and schurfact `show` output in doctests --- base/array.jl | 4 ++-- base/linalg/schur.jl | 6 +++++- base/math.jl | 2 +- doc/src/manual/complex-and-rational-numbers.md | 2 +- doc/src/manual/control-flow.md | 2 +- doc/src/manual/faq.md | 4 ++-- 6 files changed, 12 insertions(+), 8 deletions(-) diff --git a/base/array.jl b/base/array.jl index e46c552abf936..5de013272a606 100644 --- a/base/array.jl +++ b/base/array.jl @@ -842,8 +842,8 @@ julia> deleteat!([6, 5, 4, 3, 2, 1], [true, false, true, false, true, false]) julia> deleteat!([6, 5, 4, 3, 2, 1], (2, 2)) ERROR: ArgumentError: indices must be unique and sorted Stacktrace: - [1] _deleteat!(::Array{Int64,1}, ::Tuple{Int64,Int64}) at ./array.jl:858 - [2] deleteat!(::Array{Int64,1}, ::Tuple{Int64,Int64}) at ./array.jl:845 + [1] _deleteat!(::Array{Int64,1}, ::Tuple{Int64,Int64}) at ./array.jl:862 + [2] deleteat!(::Array{Int64,1}, ::Tuple{Int64,Int64}) at ./array.jl:849 ``` """ deleteat!(a::Vector, inds) = _deleteat!(a, inds) diff --git a/base/linalg/schur.jl b/base/linalg/schur.jl index d2195e8e4dde1..50c4a6e74cc45 100644 --- a/base/linalg/schur.jl +++ b/base/linalg/schur.jl @@ -34,7 +34,11 @@ julia> A = [-2. 1. 3.; 2. 1. -1.; -7. 2. 7.] -7.0 2.0 7.0 julia> F = schurfact(A) -Base.LinAlg.Schur{Float64,Array{Float64,2}}([2.0 0.801792 6.63509; -8.55988e-11 2.0 8.08286; 0.0 0.0 1.99999], [0.577351 0.154299 -0.801784; 0.577346 -0.77152 0.267262; 0.577354 0.617211 0.534522], Complex{Float64}[2.0+8.28447e-6im, 2.0-8.28447e-6im, 1.99999+0.0im]) +Base.LinAlg.Schur{Float64,Array{Float64,2}} with factors T and Z: +[2.0 0.801792 6.63509; -8.55988e-11 2.0 8.08286; 0.0 0.0 1.99999] +[0.577351 0.154299 -0.801784; 0.577346 -0.77152 0.267262; 0.577354 0.617211 0.534522] +and values: +Complex{Float64}[2.0+8.28447e-6im, 2.0-8.28447e-6im, 1.99999+0.0im] julia> F[:vectors] * F[:Schur] * F[:vectors]' 3×3 Array{Float64,2}: diff --git a/base/math.jl b/base/math.jl index 944514da5e736..cc239cab8f298 100644 --- a/base/math.jl +++ b/base/math.jl @@ -446,7 +446,7 @@ julia> √(a^2 + a^2) # a^2 overflows ERROR: DomainError: sqrt will only return a complex result if called with a complex argument. Try sqrt(complex(x)). Stacktrace: - [1] sqrt(::Int64) at ./math.jl:421 + [1] sqrt(::Int64) at ./math.jl:431 ``` """ hypot(x::Number, y::Number) = hypot(promote(x, y)...) diff --git a/doc/src/manual/complex-and-rational-numbers.md b/doc/src/manual/complex-and-rational-numbers.md index 767428ee623e1..d3245c27a9639 100644 --- a/doc/src/manual/complex-and-rational-numbers.md +++ b/doc/src/manual/complex-and-rational-numbers.md @@ -143,7 +143,7 @@ julia> sqrt(-1) ERROR: DomainError: sqrt will only return a complex result if called with a complex argument. Try sqrt(complex(x)). Stacktrace: - [1] sqrt(::Int64) at ./math.jl:421 + [1] sqrt(::Int64) at ./math.jl:431 julia> sqrt(-1 + 0im) 0.0 + 1.0im diff --git a/doc/src/manual/control-flow.md b/doc/src/manual/control-flow.md index 336ed7da59d32..0d71040c604d3 100644 --- a/doc/src/manual/control-flow.md +++ b/doc/src/manual/control-flow.md @@ -571,7 +571,7 @@ julia> sqrt(-1) ERROR: DomainError: sqrt will only return a complex result if called with a complex argument. Try sqrt(complex(x)). Stacktrace: - [1] sqrt(::Int64) at ./math.jl:421 + [1] sqrt(::Int64) at ./math.jl:431 ``` You may define your own exceptions in the following way: diff --git a/doc/src/manual/faq.md b/doc/src/manual/faq.md index 052cfe9d21b38..653c9030621c0 100644 --- a/doc/src/manual/faq.md +++ b/doc/src/manual/faq.md @@ -227,7 +227,7 @@ julia> sqrt(-2.0) ERROR: DomainError: sqrt will only return a complex result if called with a complex argument. Try sqrt(complex(x)). Stacktrace: - [1] sqrt(::Float64) at ./math.jl:412 + [1] sqrt(::Float64) at ./math.jl:422 julia> 2^-5 ERROR: DomainError: @@ -235,7 +235,7 @@ Cannot raise an integer x to a negative power -n. Make x a float by adding a zero decimal (e.g. 2.0^-n instead of 2^-n), or write 1/x^n, float(x)^-n, or (x//1)^-n. Stacktrace: [1] power_by_squaring(::Int64, ::Int64) at ./intfuncs.jl:170 - [2] ^(::Int64, ::Type{Val{-5}}) at ./intfuncs.jl:201 + [2] literal_pow(::Base.#^, ::Int64, ::Type{Val{-5}}) at ./intfuncs.jl:205 ``` This behavior is an inconvenient consequence of the requirement for type-stability. In the case From 5b18b740c6301a15678b1a1820c41bb8c923d59d Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Sat, 4 Mar 2017 19:56:45 -0500 Subject: [PATCH 0208/1534] Fix links in documentation smaller version of 0cc7d79d93cfea use --color=yes when running linkcheck --- base/linalg/bunchkaufman.jl | 2 +- doc/Makefile | 2 +- doc/src/manual/dates.md | 4 ++-- doc/src/manual/faq.md | 2 +- doc/src/manual/getting-started.md | 1 - doc/src/manual/integers-and-floating-point-numbers.md | 4 ++-- doc/src/manual/mathematical-operations.md | 4 ++-- doc/src/manual/packages.md | 2 +- doc/src/manual/parallel-computing.md | 2 +- doc/src/manual/strings.md | 8 +++++--- 10 files changed, 16 insertions(+), 15 deletions(-) diff --git a/base/linalg/bunchkaufman.jl b/base/linalg/bunchkaufman.jl index e21acd3727754..8d6cbf8f32a21 100644 --- a/base/linalg/bunchkaufman.jl +++ b/base/linalg/bunchkaufman.jl @@ -66,7 +66,7 @@ If `symmetric` is `true`, `A` is assumed to be symmetric. If `symmetric` is `fal The following functions are available for `BunchKaufman` objects: [`size`](@ref), `\\`, [`inv`](@ref), [`issymmetric`](@ref), [`ishermitian`](@ref). -[^Bunch1977]: J R Bunch and L Kaufman, Some stable methods for calculating inertia and solving symmetric linear systems, Mathematics of Computation 31:137 (1977), 163-179. [url](http://www.ams.org/journals/mcom/1977-31-137/S0025-5718-1977-0428694-0). +[^Bunch1977]: J R Bunch and L Kaufman, Some stable methods for calculating inertia and solving symmetric linear systems, Mathematics of Computation 31:137 (1977), 163-179. [url](http://www.ams.org/journals/mcom/1977-31-137/S0025-5718-1977-0428694-0/). """ bkfact(A::StridedMatrix{<:BlasFloat}, uplo::Symbol=:U, symmetric::Bool=issymmetric(A), diff --git a/doc/Makefile b/doc/Makefile index 6a8764cb3665a..791f095b6162c 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -47,7 +47,7 @@ pdf: deps linkcheck: deps @echo "Checking external documentation links." - $(JULIA_EXECUTABLE) $(call cygpath_w,$(SRCDIR)/make.jl) -- linkcheck + $(JULIA_EXECUTABLE) --color=yes $(call cygpath_w,$(SRCDIR)/make.jl) -- linkcheck @echo "Checks finished." doctest: deps diff --git a/doc/src/manual/dates.md b/doc/src/manual/dates.md index dc72256fdf0ed..6c4e4a84a40a8 100644 --- a/doc/src/manual/dates.md +++ b/doc/src/manual/dates.md @@ -559,7 +559,7 @@ julia> round(DateTime(2016, 8, 6, 20, 15), Dates.Day) Unlike the numeric [`round()`](@ref) method, which breaks ties toward the even number by default, the [`TimeType`](@ref)[`round()`](@ref) method uses the `RoundNearestTiesUp` rounding mode. (It's difficult to guess what breaking ties to nearest "even" [`TimeType`](@ref) would entail.) Further -details on the available `RoundingMode` s can be found in the [API reference](http://docs.julialang.org/en/latest/stdlib/dates/). +details on the available `RoundingMode` s can be found in the [API reference](http://docs.julialang.org/en/latest/stdlib/dates.html). Rounding should generally behave as expected, but there are a few cases in which the expected behaviour is not obvious. @@ -624,5 +624,5 @@ will result in the months field having an odd value. Because both months and yea an irregular number of days, whether rounding to an even number of days will result in an even value in the days field is uncertain. -See the [API reference](http://docs.julialang.org/en/latest/stdlib/dates/) for additional information +See the [API reference](http://docs.julialang.org/en/latest/stdlib/dates.html) for additional information on methods exported from the `Dates` module. diff --git a/doc/src/manual/faq.md b/doc/src/manual/faq.md index 653c9030621c0..cf2f4b78f3710 100644 --- a/doc/src/manual/faq.md +++ b/doc/src/manual/faq.md @@ -474,7 +474,7 @@ the loop, but it cannot algebraically reduce multiple operations into fewer equi The most reasonable alternative to having integer arithmetic silently overflow is to do checked arithmetic everywhere, raising errors when adds, subtracts, and multiplies overflow, producing -values that are not value-correct. In this [blog post](http://danluu.com/integer-overflow), Dan +values that are not value-correct. In this [blog post](http://danluu.com/integer-overflow/), Dan Luu analyzes this and finds that rather than the trivial cost that this approach should in theory have, it ends up having a substantial cost due to compilers (LLVM and GCC) not gracefully optimizing around the added overflow checks. If this improves in the future, we could consider defaulting diff --git a/doc/src/manual/getting-started.md b/doc/src/manual/getting-started.md index 94979fbda50cb..8dc9b7d9e53fc 100644 --- a/doc/src/manual/getting-started.md +++ b/doc/src/manual/getting-started.md @@ -152,5 +152,4 @@ with Julia: * [Tutorial for Homer Reid's numerical analysis class](http://homerreid.dyndns.org/teaching/18.330/JuliaProgramming.shtml) * [An introductory presentation](https://raw.githubusercontent.com/ViralBShah/julia-presentations/master/Fifth-Elephant-2013/Fifth-Elephant-2013.pdf) * [Videos from the Julia tutorial at MIT](http://julialang.org/blog/2013/03/julia-tutorial-MIT) - * [Forio Julia Tutorials](http://forio.com/about/labs/julia-studio/tutorials/) * [YouTube videos from the JuliaCons](https://www.youtube.com/user/JuliaLanguage/playlists) diff --git a/doc/src/manual/integers-and-floating-point-numbers.md b/doc/src/manual/integers-and-floating-point-numbers.md index 6d7d8aaeb96da..9d0932bbde923 100644 --- a/doc/src/manual/integers-and-floating-point-numbers.md +++ b/doc/src/manual/integers-and-floating-point-numbers.md @@ -492,8 +492,8 @@ most books on scientific computation, and also in the following references: * The definitive guide to floating point arithmetic is the [IEEE 754-2008 Standard](http://standards.ieee.org/findstds/standard/754-2008.html); however, it is not available for free online. * For a brief but lucid presentation of how floating-point numbers are represented, see John D. - Cook's [article](http://www.johndcook.com/blog/2009/04/06/anatomy-of-a-floating-point-number/) - on the subject as well as his [introduction](http://www.johndcook.com/blog/2009/04/06/numbers-are-a-leaky-abstraction/) + Cook's [article](https://www.johndcook.com/blog/2009/04/06/anatomy-of-a-floating-point-number/) + on the subject as well as his [introduction](https://www.johndcook.com/blog/2009/04/06/numbers-are-a-leaky-abstraction/) to some of the issues arising from how this representation differs in behavior from the idealized abstraction of real numbers. * Also recommended is Bruce Dawson's [series of blog posts on floating-point numbers](https://randomascii.wordpress.com/2012/05/20/thats-not-normalthe-performance-of-odd-floats/). diff --git a/doc/src/manual/mathematical-operations.md b/doc/src/manual/mathematical-operations.md index f25778f895dbe..faebc4227408c 100644 --- a/doc/src/manual/mathematical-operations.md +++ b/doc/src/manual/mathematical-operations.md @@ -478,8 +478,8 @@ See [Conversion and Promotion](@ref conversion-and-promotion) for how to define | [`significand(x)`](@ref) | binary significand (a.k.a. mantissa) of a floating-point number `x` | For an overview of why functions like [`hypot()`](@ref), [`expm1()`](@ref), and [`log1p()`](@ref) -are necessary and useful, see John D. Cook's excellent pair of blog posts on the subject: [expm1, log1p, erfc](http://www.johndcook.com/blog/2010/06/07/math-library-functions-that-seem-unnecessary/), -and [hypot](http://www.johndcook.com/blog/2010/06/02/whats-so-hard-about-finding-a-hypotenuse/). +are necessary and useful, see John D. Cook's excellent pair of blog posts on the subject: [expm1, log1p, erfc](https://www.johndcook.com/blog/2010/06/07/math-library-functions-that-seem-unnecessary/), +and [hypot](https://www.johndcook.com/blog/2010/06/02/whats-so-hard-about-finding-a-hypotenuse/). ### Trigonometric and hyperbolic functions diff --git a/doc/src/manual/packages.md b/doc/src/manual/packages.md index 5213fdd3a421e..6955cf4265039 100644 --- a/doc/src/manual/packages.md +++ b/doc/src/manual/packages.md @@ -903,7 +903,7 @@ INFO: To create a pull-request open: is to delete the "Julia Package Manager" personal access token [from your Github account](https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fsettings%2Ftokens) and try again. - Other failures may require you to circumvent `PkgDev.publish()` by [creating a pull request on GitHub](https://help.github.com/articles/creating-a-pull-request). + Other failures may require you to circumvent `PkgDev.publish()` by [creating a pull request on GitHub](https://help.github.com/articles/creating-a-pull-request/). See: [Publishing METADATA manually](@ref) below. Once the package URL for `FooBar` is registered in the official `METADATA` repo, people know where diff --git a/doc/src/manual/parallel-computing.md b/doc/src/manual/parallel-computing.md index ec83bae36cd5f..a986fa00f1b0e 100644 --- a/doc/src/manual/parallel-computing.md +++ b/doc/src/manual/parallel-computing.md @@ -1413,5 +1413,5 @@ It is very important that the called function does not call back into Julia. In this context, MPI refers to the MPI-1 standard. Beginning with MPI-2, the MPI standards committee introduced a new set of communication mechanisms, collectively referred to as Remote Memory Access (RMA). The motivation for adding RMA to the MPI standard was to facilitate one-sided communication - patterns. For additional information on the latest MPI standard, see [http://mpi-forum.org/docs](http://mpi-forum.org/docs). + patterns. For additional information on the latest MPI standard, see [http://mpi-forum.org/docs](http://mpi-forum.org/docs/). diff --git a/doc/src/manual/strings.md b/doc/src/manual/strings.md index 15041d695a39d..352b0a1e70b0c 100644 --- a/doc/src/manual/strings.md +++ b/doc/src/manual/strings.md @@ -838,9 +838,11 @@ so the distinction can safely be ignored. For the escapes `\x80` through `\xff` bytes, which -- unless followed by very specific continuation bytes -- do not form valid UTF-8 data, whereas the latter escapes all represent Unicode code points with two-byte encodings. -If this is all extremely confusing, try reading ["The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode -and Character Sets"](http://www.joelonsoftware.com/articles/Unicode.html). It's an excellent introduction -to Unicode and UTF-8, and may help alleviate some confusion regarding the matter. +If this is all extremely confusing, try reading ["The Absolute Minimum Every +Software Developer Absolutely, Positively Must Know About Unicode and Character +Sets"](https://www.joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-developer-absolutely-positively-must-know-about-unicode-and-character-sets-no-excuses/). +It's an excellent introduction to Unicode and UTF-8, and may help alleviate +some confusion regarding the matter. ## [Version Number Literals](@id man-version-number-literals) From 4eb8c0613a47a2d03518217a207a5af7a06bfdce Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Thu, 16 Mar 2017 18:41:10 -0500 Subject: [PATCH 0209/1534] Extensible and fast date parsing (#20952) * Refactor date parsing to be fast and extensible * Deprecate parse(::AbstractString, ::DateFormat) * fixup * Switch to datatype_name * Move towards consistent terminology * Rename parse(::Vector, ...) to parse_components * Internal parse funcs now take and return position * Documentation for internal functions * Corrections to documentation * Corrections from review * More details about raise * Remove outdated comment --- base/dates/io.jl | 51 ++++++--- base/dates/parse.jl | 264 +++++++++++++++++++++++++++++++------------- base/deprecated.jl | 11 ++ test/dates/io.jl | 56 ++++++---- 4 files changed, 268 insertions(+), 114 deletions(-) diff --git a/base/dates/io.jl b/base/dates/io.jl index 778e7e99641bc..29170630395e1 100644 --- a/base/dates/io.jl +++ b/base/dates/io.jl @@ -175,17 +175,17 @@ Delim(d::Char) = Delim{Char, 1}(d) Delim(d::String) = Delim{String, length(d)}(d) @inline function tryparsenext{N}(d::Delim{Char, N}, str, i::Int, len) - R = Nullable{Int64} + R = Nullable{Bool} for j=1:N i > len && return (R(), i) c, i = next(str, i) c != d.d && return (R(), i) end - return R(0), i + return R(true), i end @inline function tryparsenext{N}(d::Delim{String, N}, str, i::Int, len) - R = Nullable{Int64} + R = Nullable{Bool} i1 = i i2 = start(d.d) for j = 1:N @@ -198,7 +198,7 @@ end return R(), i1 end end - return R(0), i1 + return R(true), i1 end @inline function format(io, d::Delim, dt, locale) @@ -206,7 +206,7 @@ end end function _show_content{N}(io::IO, d::Delim{Char, N}) - if d.d in keys(SLOT_RULE) + if d.d in keys(CONVERSION_SPECIFIERS) for i = 1:N write(io, '\\', d.d) end @@ -219,7 +219,7 @@ end function _show_content(io::IO, d::Delim) for c in d.d - if c in keys(SLOT_RULE) + if c in keys(CONVERSION_SPECIFIERS) write(io, '\\') end write(io, c) @@ -236,8 +236,9 @@ end abstract type DayOfWeekToken end # special addition to Period types -# mapping format specifiers to period types -const SLOT_RULE = Dict{Char, Type}( +# Map conversion specifiers or character codes to tokens. +# Note: Allow addition of new character codes added by packages +const CONVERSION_SPECIFIERS = Dict{Char, Type}( 'y' => Year, 'Y' => Year, 'm' => Month, @@ -252,13 +253,26 @@ const SLOT_RULE = Dict{Char, Type}( 's' => Millisecond, ) -slot_order(::Type{Date}) = (Year, Month, Day) -slot_order(::Type{DateTime}) = (Year, Month, Day, Hour, Minute, Second, Millisecond) - -slot_defaults(::Type{Date}) = map(Int64, (1, 1, 1)) -slot_defaults(::Type{DateTime}) = map(Int64, (1, 1, 1, 0, 0, 0, 0)) +# Default values are needed when a conversion specifier is used in a DateFormat for parsing +# and we have reached the end of the input string. +# Note: Allow `Any` value as a default to support extensibility +const CONVERSION_DEFAULTS = Dict{Type, Any}( + Year => Int64(1), + Month => Int64(1), + DayOfWeekToken => Int64(0), + Day => Int64(1), + Hour => Int64(0), + Minute => Int64(0), + Second => Int64(0), + Millisecond => Int64(0), +) -slot_types{T<:TimeType}(::Type{T}) = typeof(slot_defaults(T)) +# Specifies the required fields in order to parse a TimeType +# Note: Allows for addition of new TimeTypes +const CONVERSION_TRANSLATIONS = Dict{Type{<:TimeType}, Tuple}( + Date => (Year, Month, Day), + DateTime => (Year, Month, Day, Hour, Minute, Second, Millisecond), +) """ DateFormat(format::AbstractString, locale="english") -> DateFormat @@ -300,13 +314,13 @@ function DateFormat(f::AbstractString, locale::DateLocale=ENGLISH) prev = () prev_offset = 1 - letters = String(collect(keys(Base.Dates.SLOT_RULE))) + letters = String(collect(keys(CONVERSION_SPECIFIERS))) for m in eachmatch(Regex("(? DateTime diff --git a/base/dates/parse.jl b/base/dates/parse.jl index e638319f10b09..84b3c475717a2 100644 --- a/base/dates/parse.jl +++ b/base/dates/parse.jl @@ -1,97 +1,161 @@ ### Parsing utilities -@generated function tryparse_internal{T<:TimeType, S, F}(::Type{T}, str::AbstractString, df::DateFormat{S, F}, raise::Bool=false) - token_types = Type[dp <: DatePart ? SLOT_RULE[first(dp.parameters)] : Void for dp in F.parameters] - N = length(F.parameters) - - types = slot_order(T) - num_types = length(types) - order = Vector{Int}(num_types) - for i = 1:num_types - order[i] = findfirst(token_types, types[i]) +_directives{S,T}(::Type{DateFormat{S,T}}) = T.parameters + +character_codes{S,T}(df::Type{DateFormat{S,T}}) = character_codes(_directives(df)) +function character_codes(directives::SimpleVector) + letters = sizehint!(Char[], length(directives)) + for (i, directive) in enumerate(directives) + if directive <: DatePart + letter = first(directive.parameters) + push!(letters, letter) + end end + return letters +end - field_defaults = slot_defaults(T) - field_order = tuple(order...) - tuple_type = slot_types(T) - - # `slot_order`, `slot_defaults`, and `slot_types` return tuples of the same length - assert(num_types == length(field_order) == length(field_defaults)) +genvar(t::DataType) = Symbol(lowercase(string(Base.datatype_name(t)))) + +""" + tryparsenext_core(str::AbstractString, pos::Int, len::Int, df::DateFormat, raise=false) + +Parses the string according to the directives within the DateFormat. Parsing will start at +character index `pos` and will stop when all directives are used or we have parsed up to +the end of the string, `len`. When a directive cannot be parsed the returned value tuple +will be null if `raise` is false otherwise an exception will be thrown. + +Returns a 3-element tuple `(values, pos, num_parsed)`: +* `values::Nullable{Tuple}`: A tuple which contains a value for each `DatePart` within the + `DateFormat` in the order in which they occur. If the string ends before we finish parsing + all the directives the missing values will be filled in with default values. +* `pos::Int`: The character index at which parsing stopped. +* `num_parsed::Int`: The number of values which were parsed and stored within `values`. + Useful for distinguishing parsed values from default values. +""" +@generated function tryparsenext_core( + str::AbstractString, pos::Int, len::Int, df::DateFormat, raise::Bool=false, +) + directives = _directives(df) + letters = character_codes(directives) + + tokens = Type[CONVERSION_SPECIFIERS[letter] for letter in letters] + value_names = Symbol[genvar(t) for t in tokens] + value_defaults = Tuple(CONVERSION_DEFAULTS[t] for t in tokens) + R = typeof(value_defaults) + + # Pre-assign variables to defaults. Allows us to use `@goto done` without worrying about + # unassigned variables. + assign_defaults = Expr[ + quote + $name = $default + end + for (name, default) in zip(value_names, value_defaults) + ] + + vi = 1 + parsers = Expr[ + begin + if directives[i] <: DatePart + name = value_names[vi] + nullable = Symbol(:nullable_, name) + vi += 1 + quote + pos > len && @goto done + $nullable, next_pos = tryparsenext(directives[$i], str, pos, len, locale) + isnull($nullable) && @goto error + $name = unsafe_get($nullable) + pos = next_pos + num_parsed += 1 + directive_index += 1 + end + else + quote + pos > len && @goto done + nullable_delim, next_pos = tryparsenext(directives[$i], str, pos, len, locale) + isnull(nullable_delim) && @goto error + pos = next_pos + directive_index += 1 + end + end + end + for i in 1:length(directives) + ] quote - R = Nullable{$tuple_type} - t = df.tokens - l = df.locale - pos, len = start(str), endof(str) + directives = df.tokens + locale::DateLocale = df.locale - err_idx = 1 - Base.@nexprs $N i->val_i = 0 - Base.@nexprs $N i->(begin - pos > len && @goto done - nv, next_pos = tryparsenext(t[i], str, pos, len, l) - isnull(nv) && @goto error - val_i, pos = unsafe_get(nv), next_pos - err_idx += 1 - end) - pos <= len && @goto error + num_parsed = 0 + directive_index = 1 - @label done - parts = Base.@ntuple $N val - return R(reorder_args(parts, $field_order, $field_defaults, err_idx)::$tuple_type) + $(assign_defaults...) + $(parsers...) - @label error - # Note: Keeping exception generation in separate function helps with performance - raise && throw(gen_exception(t, err_idx, pos)) - return R() - end -end + pos > len || @goto error -function gen_exception(tokens, err_idx, pos) - if err_idx > length(tokens) - ArgumentError("Found extra characters at the end of date time string") - else - ArgumentError("Unable to parse date time. Expected token $(tokens[err_idx]) at char $pos") - end -end + @label done + return Nullable{$R}($(Expr(:tuple, value_names...))), pos, num_parsed -# reorder_args(val, idx, default, default_from) -# -# reorder elements of `val` tuple according to `idx` tuple. Use `default[i]` -# when `idx[i] == 0` or i >= default_from -# -# returns a tuple `xs` of the same length as `idx` where `xs[i]` is -# `val[idx[i]]` if `idx[i]` is non zero, `default[i]` if `idx[i]` is zero. -# -# `xs[i]` is `default[i]` for all i >= `default_from`. -# -# -function reorder_args{N}(val::Tuple, idx::NTuple{N}, default::Tuple, default_from::Integer) - ntuple(Val{N}) do i - if idx[i] == 0 || idx[i] >= default_from - default[i] - else - val[idx[i]] + @label error + if raise + if directive_index > length(directives) + throw(ArgumentError("Found extra characters at the end of date time string")) + else + d = directives[directive_index] + throw(ArgumentError("Unable to parse date time. Expected directive $d at char $pos")) + end end + return Nullable{$R}(), pos, 0 end end -function Base.tryparse{T<:TimeType}(::Type{T}, str::AbstractString, df::DateFormat) - nt = tryparse_internal(T, str, df, false) - if isnull(nt) - return Nullable{T}() - else - return Nullable{T}(T(unsafe_get(nt)...)) - end -end +""" + tryparsenext_internal(::Type{<:TimeType}, str, pos, len, df::DateFormat, raise=false) + +Parses the string according to the directives within the DateFormat. The specified TimeType +type determines the type of and order of tokens returned. If the given DateFormat or string +does not provide a required token a default value will be used. When the string cannot be +parsed the returned value tuple will be null if `raise` is false otherwise an exception will +be thrown. + +Returns a 2-element tuple `(values, pos)`: +* `values::Nullable{Tuple}`: A tuple which contains a value for each token as specified by + the passed in type. +* `pos::Int`: The character index at which parsing stopped. +""" +@generated function tryparsenext_internal{T<:TimeType}( + ::Type{T}, str::AbstractString, pos::Int, len::Int, df::DateFormat, raise::Bool=false, +) + letters = character_codes(df) + + tokens = Type[CONVERSION_SPECIFIERS[letter] for letter in letters] + value_names = Symbol[genvar(t) for t in tokens] + + output_tokens = CONVERSION_TRANSLATIONS[T] + output_names = Symbol[genvar(t) for t in output_tokens] + output_defaults = Tuple(CONVERSION_DEFAULTS[t] for t in output_tokens) + R = typeof(output_defaults) + + # Pre-assign output variables to defaults. Ensures that all output variables are + # assigned as the value tuple returned from `tryparsenext_core` may not include all + # of the required variables. + assign_defaults = Expr[ + quote + $name = $default + end + for (name, default) in zip(output_names, output_defaults) + ] -default_format(::Type{Date}) = ISODateFormat -default_format(::Type{DateTime}) = ISODateTimeFormat + # Unpacks the value tuple returned by `tryparsenext_core` into separate variables. + value_tuple = Expr(:tuple, value_names...) -function Base.parse{T<:TimeType}(::Type{T}, - str::AbstractString, - df::DateFormat=default_format(T)) - nt = tryparse_internal(T, str, df, true) - T(unsafe_get(nt)...) + quote + values, pos, num_parsed = tryparsenext_core(str, pos, len, df, raise) + isnull(values) && return Nullable{$R}(), pos + $(assign_defaults...) + $value_tuple = unsafe_get(values) + return Nullable{$R}($(Expr(:tuple, output_names...))), pos + end end @inline function tryparsenext_base10(str::AbstractString, i::Int, len::Int, min_width::Int=1, max_width::Int=0) @@ -200,3 +264,49 @@ function Base.parse(::Type{DateTime}, s::AbstractString, df::typeof(ISODateTimeF @label error throw(ArgumentError("Invalid DateTime string")) end + +function Base.parse{T<:TimeType}( + ::Type{T}, str::AbstractString, df::DateFormat=default_format(T), +) + pos, len = start(str), endof(str) + values, pos = tryparsenext_internal(T, str, pos, len, df, true) + T(unsafe_get(values)...) +end + +function Base.tryparse{T<:TimeType}( + ::Type{T}, str::AbstractString, df::DateFormat=default_format(T), +) + pos, len = start(str), endof(str) + values, pos = tryparsenext_internal(T, str, pos, len, df, false) + if isnull(values) + Nullable{T}() + else + Nullable{T}(T(unsafe_get(values)...)) + end +end + +""" + parse_components(str::AbstractString, df::DateFormat) -> Array{Any} + +Parse the string into its components according to the directives in the DateFormat. +Each component will be a distinct type, typically a subtype of Period. The order of the +components will match the order of the `DatePart` directives within the DateFormat. The +number of components may be less than the total number of `DatePart`. +""" +@generated function parse_components(str::AbstractString, df::DateFormat) + letters = character_codes(df) + tokens = Type[CONVERSION_SPECIFIERS[letter] for letter in letters] + + quote + pos, len = start(str), endof(str) + values, pos, num_parsed = tryparsenext_core(str, pos, len, df, true) + t = unsafe_get(values) + types = $(Expr(:tuple, tokens...)) + result = Vector{Any}(num_parsed) + for (i, typ) in enumerate(types) + i > num_parsed && break + result[i] = typ(t[i]) # Constructing types takes most of the time + end + return result + end +end diff --git a/base/deprecated.jl b/base/deprecated.jl index 05f2c7f66e166..086e03949e09a 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1280,6 +1280,17 @@ end @deprecate_binding LinearSlow IndexCartesian false @deprecate_binding linearindexing IndexStyle false +# #20876 +@eval Base.Dates begin + function Base.Dates.parse(x::AbstractString, df::DateFormat) + Base.depwarn(string( + "`Dates.parse(x::AbstractString, df::DateFormat)` is deprecated, use ", + "`sort!(filter!(el -> isa(el, Dates.Period), Dates.parse_components(x, df), rev=true, lt=Dates.periodisless)` ", + " instead."), :parse) + sort!(filter!(el -> isa(el, Period), parse_components(x, df)), rev=true, lt=periodisless) + end +end + # END 0.6 deprecations # BEGIN 1.0 deprecations diff --git a/test/dates/io.jl b/test/dates/io.jl index 7a3790478c2fc..8564265d880cf 100644 --- a/test/dates/io.jl +++ b/test/dates/io.jl @@ -29,10 +29,13 @@ # DateTime parsing # Useful reference for different locales: http://library.princeton.edu/departments/tsd/katmandu/reference/months.html -let str = "1996/02/15 24:00", format = "yyyy/mm/dd HH:MM" - expected = (1996, 2, 15, 24, 0, 0, 0) - @test get(Dates.tryparse_internal(DateTime, str, Dates.DateFormat(format))) == expected - @test_throws ArgumentError Dates.DateTime(str, Dates.DateFormat(format)) +# Allow parsing of strings which are not representable as a TimeType +let str = "02/15/1996 24:00", df = Dates.DateFormat("mm/dd/yyyy HH:MM") + parsed = Any[ + Dates.Month(2), Dates.Day(15), Dates.Year(1996), Dates.Hour(24), Dates.Minute(0) + ] + @test Dates.parse_components(str, df) == parsed + @test_throws ArgumentError Dates.parse(DateTime, str, df) end # DateFormat printing @@ -76,18 +79,18 @@ b2 = "96/Feb/1" b3 = "96/2/15" @test_throws ArgumentError Dates.DateTime(b3, f) try - Dates.tryparse_internal(DateTime, "2012/02/20T09:09:31.25i90", dateformat"yyyy/mm/ddTHH:MM:SS.s", true) + Dates.parse(DateTime, "2012/2/20T9:9:31.25i90", dateformat"yyyy/mm/ddTHH:MM:SS.s") @test false catch err @test isa(err, ArgumentError) @test err.msg == "Found extra characters at the end of date time string" end try - Dates.tryparse_internal(DateTime, "2012/02/20T09:09:3i90", dateformat"yyyy/mm/ddTHH:MM:SS.s", true) + Dates.parse(DateTime, "2012/2/20T9:9:3i90", dateformat"yyyy/mm/ddTHH:MM:SS.s") @test false catch err @test isa(err, ArgumentError) - @test err.msg == "Unable to parse date time. Expected token Delim(.) at char 19" + @test err.msg == "Unable to parse date time. Expected directive Delim(.) at char 16" end f = "yy:dd:mm" @@ -375,29 +378,42 @@ let f = "YY" end # Issue: https://github.com/quinnj/TimeZones.jl/issues/19 -let ds = "2015-07-24T05:38:19.591Z", - dt = Dates.DateTime(2015, 7, 24, 5, 38, 19, 591), +let + const Zulu = String - format = "yyyy-mm-ddTHH:MM:SS.sssZ", + function Dates.tryparsenext(d::Dates.DatePart{'Z'}, str, i, len) + Dates.tryparsenext_word(str, i, len, Dates.min_width(d), Dates.max_width(d)) + end + + str = "2015-07-24T05:38:19.591Z" + dt = Dates.DateTime(2015, 7, 24, 5, 38, 19, 591) + parsed = Any[ + Dates.Year(2015), Dates.Month(7), Dates.Day(24), + Dates.Hour(5), Dates.Minute(38), Dates.Second(19), Dates.Millisecond(591) + ] + + format = "yyyy-mm-ddTHH:MM:SS.sssZ" escaped_format = "yyyy-mm-dd\\THH:MM:SS.sss\\Z" - # Typically 'Z' isn't treated as a slot so it doesn't have to be escaped - @test DateTime(ds, format) == dt - @test DateTime(ds, escaped_format) == dt + # Typically 'Z' isn't treated as a specifier so it doesn't have to be escaped + @test Dates.parse_components(str, Dates.DateFormat(format)) == parsed + @test Dates.parse_components(str, Dates.DateFormat(escaped_format)) == parsed try - # Make 'Z' into a slot - Dates.SLOT_RULE['Z'] = Dates.TimeZone + # Make 'Z' into a specifier + Dates.CONVERSION_SPECIFIERS['Z'] = Zulu + Dates.CONVERSION_DEFAULTS[Zulu] = "" - @test_throws MethodError DateTime(ds, format) - @test DateTime(ds, escaped_format) == dt + @test Dates.parse_components(str, Dates.DateFormat(format)) == [parsed; Zulu("Z")] + @test Dates.parse_components(str, Dates.DateFormat(escaped_format)) == parsed finally - delete!(Dates.SLOT_RULE, 'Z') + delete!(Dates.CONVERSION_SPECIFIERS, 'Z') + delete!(Dates.CONVERSION_DEFAULTS, Zulu) end # Ensure that the default behaviour has been restored - @test DateTime(ds, format) == dt - @test DateTime(ds, escaped_format) == dt + @test Dates.parse_components(str, Dates.DateFormat(format)) == parsed + @test Dates.parse_components(str, Dates.DateFormat(escaped_format)) == parsed end # Issue 10817 From 8f97e6ef32e5dfc00abe9cfd048ad8695e80047e Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Thu, 16 Mar 2017 21:27:03 -0500 Subject: [PATCH 0210/1534] Cleanup function signatures using DateLocale (#21011) --- base/dates/io.jl | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/base/dates/io.jl b/base/dates/io.jl index 29170630395e1..c87013c43068f 100644 --- a/base/dates/io.jl +++ b/base/dates/io.jl @@ -386,6 +386,9 @@ default_format(::Type{DateTime}) = ISODateTimeFormat default_format(::Type{Date}) = ISODateFormat ### API + +const Locale = Union{DateLocale, String} + """ DateTime(dt::AbstractString, format::AbstractString; locale="english") -> DateTime @@ -396,8 +399,9 @@ This method creates a `DateFormat` object each time it is called. If you are par date strings of the same format, consider creating a [`DateFormat`](@ref) object once and using that as the second argument instead. """ -DateTime(dt::AbstractString, format::AbstractString; - locale::Union{DateLocale, String}=ENGLISH) = parse(DateTime, dt, DateFormat(format, locale)) +function DateTime(dt::AbstractString, format::AbstractString; locale::Locale=ENGLISH) + parse(DateTime, dt, DateFormat(format, locale)) +end """ DateTime(dt::AbstractString, df::DateFormat) -> DateTime @@ -416,8 +420,9 @@ Construct a `Date` object by parsing a `dt` date string following the pattern gi `format` string. Follows the same conventions as `DateTime(::AbstractString, ::AbstractString)`. """ -Date(dt::AbstractString, format::AbstractString; - locale::Union{DateLocale, String}=ENGLISH) = parse(Date, dt, DateFormat(format, locale)) +function Date(dt::AbstractString, format::AbstractString; locale::Locale=ENGLISH) + parse(Date, dt, DateFormat(format, locale)) +end """ Date(dt::AbstractString, df::DateFormat) -> Date @@ -476,8 +481,9 @@ generate the string "1996-01-15T00:00:00" you could use `format`: "yyyy-mm-ddTHH Note that if you need to use a code character as a literal you can use the escape character backslash. The string "1996y01m" can be produced with the format "yyyy\\ymm\\m". """ -format(dt::TimeType, f::AbstractString; - locale::Union{DateLocale, String}=ENGLISH) = format(dt, DateFormat(f, locale)) +function format(dt::TimeType, f::AbstractString; locale::Locale=ENGLISH) + format(dt, DateFormat(f, locale)) +end # show @@ -512,22 +518,22 @@ function Base.string(dt::Date) end # vectorized -DateTime(Y::AbstractArray{<:AbstractString}, format::AbstractString; - locale::Union{DateLocale, String}=ENGLISH) = DateTime(Y, DateFormat(format, locale)) +function DateTime(Y::AbstractArray{<:AbstractString}, f::AbstractString; locale::Locale=ENGLISH) + DateTime(Y, DateFormat(f, locale)) +end function DateTime(Y::AbstractArray{<:AbstractString}, df::DateFormat=ISODateTimeFormat) return reshape(DateTime[parse(DateTime, y, df) for y in Y], size(Y)) end -Date(Y::AbstractArray{<:AbstractString}, format::AbstractString; - locale::Union{DateLocale, String}=ENGLISH) = Date(Y, DateFormat(format, locale)) +function Date(Y::AbstractArray{<:AbstractString}, f::AbstractString; locale::Locale=ENGLISH) + Date(Y, DateFormat(f, locale)) +end function Date(Y::AbstractArray{<:AbstractString}, df::DateFormat=ISODateFormat) return reshape(Date[Date(parse(Date, y, df)) for y in Y], size(Y)) end -format(Y::AbstractArray{<:TimeType}, fmt::AbstractString; - locale::Union{DateLocale, String}=ENGLISH) = format(Y, DateFormat(fmt, locale)) -function format(Y::AbstractArray{Date}, df::DateFormat=ISODateFormat) - return reshape([format(y, df) for y in Y], size(Y)) +function format(Y::AbstractArray{<:TimeType}, f::AbstractString; locale::Locale=ENGLISH) + format(Y, DateFormat(f, locale)) end -function format(Y::AbstractArray{DateTime}, df::DateFormat=ISODateTimeFormat) +function format{T<:TimeType}(Y::AbstractArray{T}, df::DateFormat=default_format(T)) return reshape([format(y, df) for y in Y], size(Y)) end From 548480739b3d16db94c295f4e28e4aa16242d444 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 16 Mar 2017 21:00:45 -0400 Subject: [PATCH 0211/1534] fix `return_type_tfunc` in the case where no methods match also fix `return_type` on Builtins; this was another disparity with `return_type_tfunc` --- base/inference.jl | 38 +++++++++++++++++++++++++++----------- test/inference.jl | 9 +++++++++ 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index fbdde0def09d6..42b4d86cc2012 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -1081,12 +1081,13 @@ function tuple_tfunc(argtype::ANY) return argtype end -function builtin_tfunction(f::ANY, argtypes::Array{Any,1}, sv::InferenceState) +function builtin_tfunction(f::ANY, argtypes::Array{Any,1}, + sv::Union{InferenceState,Void}, params::InferenceParams = sv.params) isva = !isempty(argtypes) && isvarargtype(argtypes[end]) if f === tuple for a in argtypes if !isa(a, Const) - return tuple_tfunc(limit_tuple_depth(sv.params, argtypes_to_type(argtypes))) + return tuple_tfunc(limit_tuple_depth(params, argtypes_to_type(argtypes))) end end return Const(tuple(anymap(a->a.val, argtypes)...)) @@ -1135,7 +1136,7 @@ function builtin_tfunction(f::ANY, argtypes::Array{Any,1}, sv::InferenceState) else sigty = nothing end - if isa(sigty, Type) && sigty <: Tuple + if isa(sigty, Type) && sigty <: Tuple && sv !== nothing return invoke_tfunc(af, sigty, argtypes_to_type(argtypes[3:end]), sv) end end @@ -1517,21 +1518,29 @@ function return_type_tfunc(argtypes::ANY, vtypes::VarTable, sv::InferenceState) if isa(tt, Const) || (isType(tt) && !has_free_typevars(tt)) aft = argtypes[2] if isa(aft, Const) || (isType(aft) && !has_free_typevars(aft)) || - (isleaftype(aft) && !(aft <: Builtin) && !(aft <: IntrinsicFunction)) + (isleaftype(aft) && !(aft <: Builtin)) af_argtype = isa(tt, Const) ? tt.val : tt.parameters[1] if isa(af_argtype, DataType) && af_argtype <: Tuple argtypes_vec = Any[aft, af_argtype.parameters...] + astype = argtypes_to_type(argtypes_vec) + if !(aft ⊑ Builtin) && + _methods_by_ftype(astype, 0, sv.params.world, + UInt[typemin(UInt)], UInt[typemax(UInt)]) !== false + # return_type returns Bottom if no methods match, even though + # inference doesn't necessarily. + return Const(Bottom) + end if isa(aft, Const) rt = abstract_call(aft.val, (), argtypes_vec, vtypes, sv) elseif isconstType(aft) rt = abstract_call(aft.parameters[1], (), argtypes_vec, vtypes, sv) else - rt = abstract_call_gf_by_type(nothing, argtypes_to_type(argtypes_vec), sv) + rt = abstract_call_gf_by_type(nothing, astype, sv) end if isa(rt, Const) # output was computed to be constant return Const(typeof(rt.val)) - elseif isleaftype(rt) + elseif isleaftype(rt) || rt === Bottom # output type was known for certain return Const(rt) elseif (isa(tt, Const) || isconstType(tt)) && @@ -5345,11 +5354,18 @@ end function return_type(f::ANY, t::ANY) params = InferenceParams(ccall(:jl_get_tls_world_age, UInt, ())) rt = Union{} - for m in _methods(f, t, -1, params.world) - ty = typeinf_type(m[3], m[1], m[2], true, params) - ty === nothing && return Any - rt = tmerge(rt, ty) - rt === Any && break + if isa(f, Builtin) + rt = builtin_tfunction(f, Any[t.parameters...], nothing, params) + if isa(rt, TypeVar) + rt = rt.ub + end + else + for m in _methods(f, t, -1, params.world) + ty = typeinf_type(m[3], m[1], m[2], true, params) + ty === nothing && return Any + rt = tmerge(rt, ty) + rt === Any && break + end end return rt end diff --git a/test/inference.jl b/test/inference.jl index e9035969b3e62..54621e6c892c8 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -684,3 +684,12 @@ Base.@pure function a20704(x) end aa20704(x) = x(nothing) @test code_typed(aa20704, (typeof(a20704),))[1][1].pure + +# issue #20033 +# check return_type_tfunc for calls where no method matches +bcast_eltype_20033(f, A) = Core.Inference.return_type(f, Tuple{eltype(A)}) +err20033(x::Float64...) = prod(x) +@test bcast_eltype_20033(err20033, [1]) === Union{} +@test Base.return_types(bcast_eltype_20033, (typeof(err20033), Vector{Int},)) == Any[Type{Union{}}] +# return_type on builtins +@test Core.Inference.return_type(tuple, Tuple{Int,Int8,Int}) === Tuple{Int,Int8,Int} From f65f273cf78125ad0c63ac27d63071296a625c04 Mon Sep 17 00:00:00 2001 From: Martin Holters Date: Fri, 17 Mar 2017 14:25:15 +0100 Subject: [PATCH 0212/1534] Introduce temporary if necessary to inline `_apply` --- base/inference.jl | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index fbdde0def09d6..29c9df6e340a5 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -4462,10 +4462,18 @@ function inlining_pass(e::Expr, sv::InferenceState, stmts, ins) elseif isa(aarg, Tuple) newargs[i-2] = Any[ QuoteNode(x) for x in aarg ] elseif isa(t, DataType) && t.name === Tuple.name && !isvatuple(t) && - effect_free(aarg, sv.src, sv.mod, true) && length(t.parameters) <= sv.params.MAX_TUPLE_SPLAT - # apply(f,t::(x,y)) => f(t[1],t[2]) + length(t.parameters) <= sv.params.MAX_TUPLE_SPLAT + if effect_free(aarg, sv.src, sv.mod, true) + # apply(f,t::(x,y)) => f(t[1],t[2]) + tmpv = aarg + else + # apply(f,t::(x,y)) => tmp=t; f(tmp[1],tmp[2]) + tmpv = add_slot!(sv.src, t, false) + insert!(stmts, ins, Expr(:(=), tmpv, aarg)) + ins += 1 + end tp = t.parameters - newargs[i-2] = Any[ mk_getfield(aarg,j,tp[j]) for j=1:length(tp) ] + newargs[i-2] = Any[ mk_getfield(tmpv,j,tp[j]) for j=1:length(tp) ] else # not all args expandable return e From 038390b09c1b645274cfed5338c9452dfcee81d9 Mon Sep 17 00:00:00 2001 From: Martin Holters Date: Fri, 17 Mar 2017 17:09:58 +0100 Subject: [PATCH 0213/1534] use `newvar!` instead of `add_slot!` --- base/inference.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/inference.jl b/base/inference.jl index 29c9df6e340a5..bbc1f8fb8bdcf 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -4468,7 +4468,7 @@ function inlining_pass(e::Expr, sv::InferenceState, stmts, ins) tmpv = aarg else # apply(f,t::(x,y)) => tmp=t; f(tmp[1],tmp[2]) - tmpv = add_slot!(sv.src, t, false) + tmpv = newvar!(sv, t) insert!(stmts, ins, Expr(:(=), tmpv, aarg)) ins += 1 end From 1594692547d179bb106e2b70ac1d177e8db9f262 Mon Sep 17 00:00:00 2001 From: Martin Holters Date: Fri, 17 Mar 2017 17:35:39 +0100 Subject: [PATCH 0214/1534] add test --- test/inference.jl | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/inference.jl b/test/inference.jl index e9035969b3e62..8440293624c38 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -684,3 +684,18 @@ Base.@pure function a20704(x) end aa20704(x) = x(nothing) @test code_typed(aa20704, (typeof(a20704),))[1][1].pure + +#issue #21065, elision of _apply when splatted expression is not effect_free +function f21065(x,y) + println("x=$x, y=$y") + return x, y +end +g21065(x,y) = +(f21065(x,y)...) +function test_no_apply(expr::Expr) + return all(test_no_apply, expr.args) +end +function test_no_apply(ref::GlobalRef) + return ref.mod != Core || ref.name !== :_apply +end +test_no_apply(::Any) = true +@test all(test_no_apply, code_typed(g21065, Tuple{Int,Int})[1].first.code) From 9932c2bfa19066ca2938b3bab349879462afc6b6 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Fri, 17 Mar 2017 11:41:02 -0500 Subject: [PATCH 0215/1534] Download failure with curl no longer create a file --- base/interactiveutil.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/interactiveutil.jl b/base/interactiveutil.jl index 1d569265a3773..a966d50fb3864 100644 --- a/base/interactiveutil.jl +++ b/base/interactiveutil.jl @@ -589,7 +589,7 @@ else if downloadcmd == :wget run(`wget -O $filename $url`) elseif downloadcmd == :curl - run(`curl -o $filename -L $url`) + run(`curl -L -f -o $filename $url`) elseif downloadcmd == :fetch run(`fetch -f $filename $url`) else From 89de7df66e88cce61827bb9864cb55d9bfb2d046 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 17 Mar 2017 14:33:51 -0400 Subject: [PATCH 0216/1534] fix #21054, parse/lowering problem with `<:T` syntax --- src/julia-parser.scm | 12 +++++++----- src/julia-syntax.scm | 4 ++-- test/parse.jl | 9 +++++++++ 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 53786f4fbc6b5..8ea23c1f1eda2 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -928,11 +928,13 @@ ((not (memq op unary-ops)) (error (string "\"" op "\" is not a unary operator"))) (else - (let ((arg (parse-unary s))) - (if (and (pair? arg) - (eq? (car arg) 'tuple)) - (list* 'call op (cdr arg)) - (list 'call op arg))))))))) + (let* ((arg (parse-unary s)) + (args (if (and (pair? arg) (eq? (car arg) 'tuple)) + (cons op (cdr arg)) + (list op arg)))) + (if (or (eq? op '|<:|) (eq? op '|>:|)) + args + (cons 'call args))))))))) (else (parse-juxtapose (parse-factor s) s))))) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index b4cb4b580c61b..c7ae4e9fdbde5 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -1763,9 +1763,9 @@ (if (null? params) (cons (reverse newparams) (reverse whereparams)) (let ((p (car params))) - (if (and (list? p) (= (length p) 3) (eq? (car p) 'call) (or (eq? (cadr p) '|<:|) (eq? (cadr p) '|>:|))) + (if (and (length= p 2) (or (eq? (car p) '|<:|) (eq? (car p) '|>:|))) (let ((T (gensy))) - (extract (cdr params) (cons T newparams) (cons (list (cadr p) T (caddr p)) whereparams))) + (extract (cdr params) (cons T newparams) (cons (list (car p) T (cadr p)) whereparams))) (extract (cdr params) (cons p newparams) whereparams))))) (extract (cddr e) '() '())) diff --git a/test/parse.jl b/test/parse.jl index 7fbda2b1f1317..c1609310afb01 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -1044,3 +1044,12 @@ end # issue #20000 @test parse("@m(a; b=c)") == Expr(:macrocall, Symbol("@m"), Expr(:parameters, Expr(:kw, :b, :c)), :a) + +# issue #21054 +macro make_f21054(T) + quote + $(esc(:f21054))(X::Type{<:$T}) = 1 + end +end +@eval @make_f21054 $Array +@test isa(f21054, Function) From 93cddfc09651ba52c99c1571a91c884c08158149 Mon Sep 17 00:00:00 2001 From: Randy Lai Date: Sat, 18 Mar 2017 13:19:35 -0400 Subject: [PATCH 0217/1534] use newest world callback on_done (#21027) * use newest world callback on_done * use QuoteNode to prevent parameters being expanded * also quote on_done --- base/LineEdit.jl | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/base/LineEdit.jl b/base/LineEdit.jl index 23772de428ca1..e1e7bedb75098 100644 --- a/base/LineEdit.jl +++ b/base/LineEdit.jl @@ -1577,7 +1577,14 @@ function run_interface(terminal, m::ModalInterface) @static if is_unix(); ccall(:jl_repl_raise_sigtstp, Cint, ()); end buf, ok, suspend = prompt!(terminal, m, s) end - mode(state(s, s.current_mode)).on_done(s, buf, ok) + eval(Main, + Expr(:body, + Expr(:return, + Expr(:call, + QuoteNode(mode(state(s, s.current_mode)).on_done), + QuoteNode(s), + QuoteNode(buf), + QuoteNode(ok))))) end end From d8f4b2238a33e21158d15e97adf67ec8c6fba260 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sat, 18 Mar 2017 17:02:04 -0400 Subject: [PATCH 0218/1534] fix #20611, type intersection inferring wrong parameter value --- src/subtype.c | 36 ++++++++++++++++++++++++------------ test/subtype.jl | 5 +++++ 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/subtype.c b/src/subtype.c index 8d5e3da7d5a83..f4b6290b3764d 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -1110,6 +1110,20 @@ static jl_value_t *set_var_to_const(jl_varbinding_t *bb, jl_value_t *v, jl_varbi return v; } +static int try_subtype_in_env(jl_value_t *a, jl_value_t *b, jl_stenv_t *e) +{ + jl_value_t *root=NULL; jl_savedenv_t se; int ret=0; + JL_GC_PUSH1(&root); + save_env(e, &root, &se); + if (subtype_in_env(a, b, e)) + ret = 1; + else + restore_env(e, root, &se); + free(se.buf); + JL_GC_POP(); + return ret; +} + static jl_value_t *intersect_var(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int8_t R, int param) { jl_varbinding_t *bb = lookup(e, b); @@ -1137,16 +1151,8 @@ static jl_value_t *intersect_var(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int } else if (bb->constraintkind == 0) { if (!jl_is_typevar(a)) { - jl_value_t *ret=NULL; - JL_GC_PUSH1(&root); - save_env(e, &root, &se); - if (subtype_in_env(bb->ub, a, e)) - ret = (jl_value_t*)b; - else - restore_env(e, root, &se); - free(se.buf); - JL_GC_POP(); - if (ret) return ret; + if (try_subtype_in_env(bb->ub, a, e)) + return (jl_value_t*)b; } return R ? intersect_ufirst(a, bb->ub, e, d) : intersect_ufirst(bb->ub, a, e, d); } @@ -1177,8 +1183,14 @@ static jl_value_t *intersect_var(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int if (jl_is_typevar(a)) return (jl_value_t*)b; if (ub == a) { - bb->ub = ub; - return (jl_value_t*)b; + if (bb->lb == jl_bottom_type || + // if the var has an equality constraint then make sure bounds stay consistent. + // TODO: try to use this check in more cases + bb->ub != bb->lb || try_subtype_in_env(bb->lb, ub, e)) { + bb->ub = ub; + return (jl_value_t*)b; + } + return ub; } root = NULL; JL_GC_PUSH2(&root, &ub); diff --git a/test/subtype.jl b/test/subtype.jl index 6356244c4a95b..7723fa82e7444 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -860,6 +860,11 @@ function test_intersection() _, E = intersection_env(Tuple{Dict{Int,Type}, Type, Any}, Tuple{Dict{K,V}, Any, Int} where {K,V}) @test E[2] == Type + + # issue #20611 + I, E = intersection_env(Tuple{Ref{Integer},Int,Any}, Tuple{Ref{Z},Z,Z} where Z) + @test isequal_type(I, Tuple{Ref{Integer},Int,Integer}) + @test E[1] == Integer end function test_intersection_properties() From 2f102de5543c8a24a5a3f955fe082c1962178262 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sat, 18 Mar 2017 20:31:19 -0400 Subject: [PATCH 0219/1534] fix #21081, quadratic slowdown in `remove_redundant_temp_vars!` --- base/inference.jl | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index fdba556e21692..b96b26d22b3e5 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -4568,31 +4568,30 @@ function remove_unused_vars!(src::CodeInfo) end end -var_matches(a::ANY, b::ANY) = false -var_matches(a::SSAValue, b::SSAValue) = a.id == b.id -var_matches(a::Slot, b::Slot) = a.id == b.id - -function delete_var!(src::CodeInfo, v::Union{Slot,SSAValue}) +function delete_vars!(src::CodeInfo, r::ObjectIdDict) filter!(x->!(isa(x,Expr) && (x.head === :(=) || x.head === :const) && - var_matches(x.args[1], v)), + haskey(r, normvar(x.args[1]))), src.code) return src end -function slot_replace!(src::CodeInfo, v::Union{Slot,SSAValue}, rhs::ANY) +function replace_vars!(src::CodeInfo, r::ObjectIdDict) for i = 1:length(src.code) - src.code[i] = _slot_replace!(src.code[i], v, rhs) + src.code[i] = _replace_vars!(src.code[i], r) end return src end -function _slot_replace!(e::ANY, v::Union{Slot,SSAValue}, rhs::ANY) - if var_matches(e, v) - return rhs +function _replace_vars!(e::ANY, r::ObjectIdDict) + if isa(e,SSAValue) || isa(e,Slot) + v = normvar(e) + if haskey(r, v) + return r[v] + end end if isa(e,Expr) for i = 1:length(e.args) - e.args[i] = _slot_replace!(e.args[i], v, rhs) + e.args[i] = _replace_vars!(e.args[i], r) end end return e @@ -4602,6 +4601,9 @@ is_argument(nargs::Int, v::Slot) = slot_id(v) <= nargs normslot(s::SlotNumber) = s normslot(s::TypedSlot) = SlotNumber(slot_id(s)) +normvar(s::Slot) = normslot(s) +normvar(s::SSAValue) = s +normvar(s::ANY) = s # given a single-assigned var and its initializer `init`, return what we can # replace `var` with, or `var` itself if we shouldn't replace it @@ -4649,18 +4651,22 @@ end # remove all single-assigned vars v in "v = x" where x is an argument. # "sa" is the result of find_sa_vars -function remove_redundant_temp_vars!(src::CodeInfo, nargs::Int, sa) +function remove_redundant_temp_vars!(src::CodeInfo, nargs::Int, sa::ObjectIdDict) flags = src.slotflags slottypes = src.slottypes ssavaluetypes = src.ssavaluetypes + repls = ObjectIdDict() for (v, init) in sa repl = get_replacement(sa, v, init, nargs, slottypes, ssavaluetypes) compare = isa(repl,TypedSlot) ? normslot(repl) : repl if compare !== v - delete_var!(src, v) - slot_replace!(src, v, repl) + repls[v] = repl end end + if !isempty(repls) + delete_vars!(src, repls) + replace_vars!(src, repls) + end return src end From 2e947bae7e6d03dc776c71b85e2bdd1f70983df6 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Sun, 19 Mar 2017 12:01:14 +0100 Subject: [PATCH 0220/1534] ensure the gc-rooting pass does not discard derived roots fix #21015 --- src/cgutils.cpp | 4 ++++ src/intrinsics.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 0b55c53db4ca8..60a8c7db5b8fb 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -1910,6 +1910,10 @@ static Value *box_union(const jl_cgval_t &vinfo, jl_codectx_t *ctx, const SmallB builder.CreateUnreachable(); } else { + if (vinfo.gcroot && vinfo.V != vinfo.gcroot) { + // if this is a derived pointer, make sure the root usage itself is also visible to the delete-root pass + mark_gc_use(vinfo); + } box_merge->addIncoming(emit_bitcast(vinfo.V, T_pjlvalue), defaultBB); builder.CreateBr(postBB); } diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index 060422a10a222..3856f4d10ce5b 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -309,6 +309,10 @@ static Value *emit_unbox(Type *to, const jl_cgval_t &x, jl_value_t *jt, Value *d return NULL; } + // if this is a derived pointer, make sure the root usage itself is also visible to the delete-root pass + if (x.gcroot && x.V != x.gcroot) + mark_gc_use(x); + // bools stored as int8, so an extra Trunc is needed to get an int1 Value *p = x.constant ? literal_pointer_val(x.constant) : x.V; Type *ptype = (to == T_int1 ? T_pint8 : to->getPointerTo()); From 26beab3d13eb28d9d5324b2bc652d79899d8eafe Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Sun, 19 Mar 2017 09:05:53 -0400 Subject: [PATCH 0221/1534] Carry openblas power assembly fixes from https://github.com/xianyi/OpenBLAS/pull/1098 --- deps/blas.mk | 8 +- .../openblas-power-assembly-fixes.patch | 7834 +++++++++++++++++ 2 files changed, 7841 insertions(+), 1 deletion(-) create mode 100644 deps/patches/openblas-power-assembly-fixes.patch diff --git a/deps/blas.mk b/deps/blas.mk index b1992cabf8ba0..d473dd4825bc2 100644 --- a/deps/blas.mk +++ b/deps/blas.mk @@ -97,7 +97,13 @@ $(BUILDDIR)/$(OPENBLAS_SRC_DIR)/openblas-cross-compile.patch-applied: $(BUILDDIR cd $(BUILDDIR)/$(OPENBLAS_SRC_DIR) && patch -p1 -f < $(SRCDIR)/patches/openblas-cross-compile.patch echo 1 > $@ -$(BUILDDIR)/$(OPENBLAS_SRC_DIR)/build-configured: $(BUILDDIR)/$(OPENBLAS_SRC_DIR)/openblas-cross-compile.patch-applied +# Power inline assembly fixes from https://github.com/xianyi/OpenBLAS/pull/1098 +# Remove this when we upgrade beyond OpenBLAS v0.2.19 +$(BUILDDIR)/$(OPENBLAS_SRC_DIR)/openblas-power-assembly-fixes.patch-applied: $(BUILDDIR)/$(OPENBLAS_SRC_DIR)/openblas-cross-compile.patch-applied + cd $(BUILDDIR)/$(OPENBLAS_SRC_DIR) && patch -p1 -f < $(SRCDIR)/patches/openblas-power-assembly-fixes.patch + echo 1 > $@ + +$(BUILDDIR)/$(OPENBLAS_SRC_DIR)/build-configured: $(BUILDDIR)/$(OPENBLAS_SRC_DIR)/openblas-power-assembly-fixes.patch-applied perl -i -ple 's/^\s*(EXTRALIB\s*\+=\s*-lSystemStubs)\s*$$/# $$1/g' $(dir $<)/Makefile.system echo 1 > $@ diff --git a/deps/patches/openblas-power-assembly-fixes.patch b/deps/patches/openblas-power-assembly-fixes.patch new file mode 100644 index 0000000000000..2031a131422ad --- /dev/null +++ b/deps/patches/openblas-power-assembly-fixes.patch @@ -0,0 +1,7834 @@ +commit 9e2f316ede9ee12441e9eb30784ceb653295b80a +Author: Martin Kroeker +Date: Mon Feb 13 23:38:50 2017 +0100 + + Power8 inline assembly fixes + + Quoting patch author amodra from #1078 + Lots of issues here. + - The vsx regs weren't listed as clobbered. + - Poor choice of vsx regs, which along with the lack of clobbers led to + trashing v0..v21 and fr14..fr23. Ideally you'd let gcc choose all + temp vsx regs, but asms currently have a limit of 30 i/o parms. + - Other regs were clobbered unnecessarily, seemingly in an attempt to + clobber inputs, with gcc-7 complaining about the clobber of r2. + (Changed inputs should be also listed as outputs or as an i/o.) + - "r" constraint used instead of "b" for gprs used in insns where the + r0 encoding means zero rather than r0. + - There were unused asm inputs too. + - All memory was clobbered rather than hooking up memory outputs with + proper memory constraints, and that and the lack of proper memory + input constraints meant the asms needed to be volatile and their + containing function noinline. + - Some parameters were being passed unnecessarily via memory. + - When a copy of a + +diff --git a/kernel/power/casum.c b/kernel/power/casum.c +index aeed0ca..d110858 100644 +--- a/kernel/power/casum.c ++++ b/kernel/power/casum.c +@@ -53,7 +53,7 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + #ifndef HAVE_KERNEL_16 + +-static void casum_kernel_16(BLASLONG n, FLOAT *x1, FLOAT *svec) ++static FLOAT casum_kernel_16(BLASLONG n, FLOAT *x1) + { + + BLASLONG i=0; +@@ -92,11 +92,7 @@ static void casum_kernel_16(BLASLONG n, FLOAT *x1, FLOAT *svec) + + } + +- svec[0] = sum0+sum1+sum2+sum3; +- svec[1] = 0.0; +- svec[2] = 0.0; +- svec[3] = 0.0; +- ++ return sum0+sum1+sum2+sum3; + } + + #endif +@@ -106,7 +102,6 @@ FLOAT CNAME(BLASLONG n, FLOAT *x, BLASLONG inc_x) + BLASLONG i=0; + BLASLONG ip=0; + FLOAT sumf = 0.0; +- FLOAT svec[4] __attribute__ ((aligned (16)));; + BLASLONG n1; + BLASLONG inc_x2; + +@@ -119,8 +114,7 @@ FLOAT CNAME(BLASLONG n, FLOAT *x, BLASLONG inc_x) + if ( n1 > 0 ) + { + +- casum_kernel_16(n1, x, svec); +- sumf = svec[0] + svec[1]+svec[2]+svec[3]; ++ sumf = casum_kernel_16(n1, x); + i=n1; + ip = 2 * n1; + } +diff --git a/kernel/power/casum_microk_power8.c b/kernel/power/casum_microk_power8.c +index cb50234..38a1143 100644 +--- a/kernel/power/casum_microk_power8.c ++++ b/kernel/power/casum_microk_power8.c +@@ -34,144 +34,145 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + **************************************************************************************/ + + #define HAVE_KERNEL_16 1 +-static void casum_kernel_16( BLASLONG n, FLOAT *x, FLOAT *svec) __attribute__ ((noinline)); + +-static void casum_kernel_16( BLASLONG n, FLOAT *x, FLOAT *svec) ++static float casum_kernel_16 (long n, float *x) + { +- +- +- BLASLONG i = n; +- BLASLONG o16 = 16; +- BLASLONG o32 = 32; +- BLASLONG o48 = 48; +- BLASLONG o64 = 64; +- BLASLONG o80 = 80; +- BLASLONG o96 = 96; +- BLASLONG o112 = 112; +- FLOAT *x1=x; +- BLASLONG pre = 384; +- +- __asm__ __volatile__ +- ( +- +- "dcbt %2 , %4 \n\t" +- +- "xxlxor 32,32,32 \n\t" +- "xxlxor 33,33,33 \n\t" +- "xxlxor 34,34,34 \n\t" +- "xxlxor 35,35,35 \n\t" +- "xxlxor 36,36,36 \n\t" +- "xxlxor 37,37,37 \n\t" +- "xxlxor 38,38,38 \n\t" +- "xxlxor 39,39,39 \n\t" +- +- "lxvw4x 40, 0, %2 \n\t" +- "lxvw4x 41, %5, %2 \n\t" +- "lxvw4x 42, %6, %2 \n\t" +- "lxvw4x 43, %7, %2 \n\t" +- "lxvw4x 44, %8, %2 \n\t" +- "lxvw4x 45, %9, %2 \n\t" +- "lxvw4x 46, %10, %2 \n\t" +- "lxvw4x 47, %11, %2 \n\t" +- +- "addi %2, %2, 128 \n\t" +- +- "addic. %0 , %0 , -16 \n\t" +- "ble 2f \n\t" +- +- ".align 5 \n\t" +- "1: \n\t" +- +- "dcbt %2 , %4 \n\t" +- +- "xvabssp 48, 40 \n\t" +- "xvabssp 49, 41 \n\t" +- "xvabssp 50, 42 \n\t" +- "xvabssp 51, 43 \n\t" +- +- "lxvw4x 40, 0, %2 \n\t" +- "lxvw4x 41, %5, %2 \n\t" +- +- "xvabssp 52, 44 \n\t" +- "xvabssp 53, 45 \n\t" +- +- "lxvw4x 42, %6, %2 \n\t" +- "lxvw4x 43, %7, %2 \n\t" +- +- "xvabssp 54, 46 \n\t" +- "xvabssp 55, 47 \n\t" +- +- "lxvw4x 44, %8, %2 \n\t" +- "lxvw4x 45, %9, %2 \n\t" +- +- "xvaddsp 32, 32, 48 \n\t" +- "xvaddsp 33, 33, 49 \n\t" +- +- "lxvw4x 46, %10, %2 \n\t" +- "lxvw4x 47, %11, %2 \n\t" +- +- "xvaddsp 34, 34, 50 \n\t" +- "xvaddsp 35, 35, 51 \n\t" +- "addi %2, %2, 128 \n\t" +- "xvaddsp 36, 36, 52 \n\t" +- "xvaddsp 37, 37, 53 \n\t" +- "addic. %0 , %0 , -16 \n\t" +- "xvaddsp 38, 38, 54 \n\t" +- "xvaddsp 39, 39, 55 \n\t" +- +- "bgt 1b \n\t" +- +- "2: \n\t" +- +- +- "xvabssp 48, 40 \n\t" +- "xvabssp 49, 41 \n\t" +- "xvabssp 50, 42 \n\t" +- "xvabssp 51, 43 \n\t" +- "xvabssp 52, 44 \n\t" +- "xvabssp 53, 45 \n\t" +- "xvabssp 54, 46 \n\t" +- "xvabssp 55, 47 \n\t" +- +- "xvaddsp 32, 32, 48 \n\t" +- "xvaddsp 33, 33, 49 \n\t" +- "xvaddsp 34, 34, 50 \n\t" +- "xvaddsp 35, 35, 51 \n\t" +- "xvaddsp 36, 36, 52 \n\t" +- "xvaddsp 37, 37, 53 \n\t" +- "xvaddsp 38, 38, 54 \n\t" +- "xvaddsp 39, 39, 55 \n\t" +- +- "xvaddsp 32, 32, 33 \n\t" +- "xvaddsp 34, 34, 35 \n\t" +- "xvaddsp 36, 36, 37 \n\t" +- "xvaddsp 38, 38, 39 \n\t" +- +- "xvaddsp 32, 32, 34 \n\t" +- "xvaddsp 36, 36, 38 \n\t" +- +- "xvaddsp 32, 32, 36 \n\t" +- +- +- "stxvw4x 32, 0, %3 \n\t" +- +- : +- : +- "r" (i), // 0 +- "r" (n), // 1 +- "r" (x1), // 2 +- "r" (svec), // 3 +- "r" (pre), // 4 +- "r" (o16), // 5 +- "r" (o32), // 6 +- "r" (o48), // 7 +- "r" (o64), // 8 +- "r" (o80), // 9 +- "r" (o96), // 10 +- "r" (o112) // 11 +- : "cr0", "%0", "%2", "memory" +- ); +- +-} +- +- ++ float sum; ++ __vector float t0; ++ __vector float t1; ++ __vector float t2; ++ __vector float t3; ++ ++ __asm__ ++ ( ++ "dcbt 0, %2 \n\t" ++ ++ "xxlxor 32, 32, 32 \n\t" ++ "xxlxor 33, 33, 33 \n\t" ++ "xxlxor 34, 34, 34 \n\t" ++ "xxlxor 35, 35, 35 \n\t" ++ "xxlxor 36, 36, 36 \n\t" ++ "xxlxor 37, 37, 37 \n\t" ++ "xxlxor 38, 38, 38 \n\t" ++ "xxlxor 39, 39, 39 \n\t" ++ ++ "lxvw4x 40, 0, %2 \n\t" ++ "lxvw4x 41, %8, %2 \n\t" ++ "lxvw4x 42, %9, %2 \n\t" ++ "lxvw4x 43, %10, %2 \n\t" ++ "lxvw4x 44, %11, %2 \n\t" ++ "lxvw4x 45, %12, %2 \n\t" ++ "lxvw4x 46, %13, %2 \n\t" ++ "lxvw4x 47, %14, %2 \n\t" ++ ++ "addi %2, %2, 128 \n\t" ++ ++ "addic. %1, %1, -16 \n\t" ++ "ble 2f \n\t" ++ ++ ".p2align 5 \n" ++ "1: \n\t" ++ ++ "xvabssp 48, 40 \n\t" ++ "xvabssp 49, 41 \n\t" ++ "xvabssp 50, 42 \n\t" ++ "xvabssp 51, 43 \n\t" ++ ++ "lxvw4x 40, 0, %2 \n\t" ++ "lxvw4x 41, %8, %2 \n\t" ++ ++ "xvabssp %x3, 44 \n\t" ++ "xvabssp %x4, 45 \n\t" ++ ++ "lxvw4x 42, %9, %2 \n\t" ++ "lxvw4x 43, %10, %2 \n\t" ++ ++ "xvabssp %x5, 46 \n\t" ++ "xvabssp %x6, 47 \n\t" ++ ++ "lxvw4x 44, %11, %2 \n\t" ++ "lxvw4x 45, %12, %2 \n\t" ++ ++ "xvaddsp 32, 32, 48 \n\t" ++ "xvaddsp 33, 33, 49 \n\t" ++ ++ "lxvw4x 46, %13, %2 \n\t" ++ "lxvw4x 47, %14, %2 \n\t" ++ ++ "xvaddsp 34, 34, 50 \n\t" ++ "xvaddsp 35, 35, 51 \n\t" ++ "addi %2, %2, 128 \n\t" ++ "xvaddsp 36, 36, %x3 \n\t" ++ "xvaddsp 37, 37, %x4 \n\t" ++ "addic. %1, %1, -16 \n\t" ++ "xvaddsp 38, 38, %x5 \n\t" ++ "xvaddsp 39, 39, %x6 \n\t" ++ ++ "bgt 1b \n" ++ ++ "2: \n\t" ++ ++ "xvabssp 48, 40 \n\t" ++ "xvabssp 49, 41 \n\t" ++ "xvabssp 50, 42 \n\t" ++ "xvabssp 51, 43 \n\t" ++ "xvabssp %x3, 44 \n\t" ++ "xvabssp %x4, 45 \n\t" ++ "xvabssp %x5, 46 \n\t" ++ "xvabssp %x6, 47 \n\t" ++ ++ "xvaddsp 32, 32, 48 \n\t" ++ "xvaddsp 33, 33, 49 \n\t" ++ "xvaddsp 34, 34, 50 \n\t" ++ "xvaddsp 35, 35, 51 \n\t" ++ "xvaddsp 36, 36, %x3 \n\t" ++ "xvaddsp 37, 37, %x4 \n\t" ++ "xvaddsp 38, 38, %x5 \n\t" ++ "xvaddsp 39, 39, %x6 \n\t" ++ ++ "xvaddsp 32, 32, 33 \n\t" ++ "xvaddsp 34, 34, 35 \n\t" ++ "xvaddsp 36, 36, 37 \n\t" ++ "xvaddsp 38, 38, 39 \n\t" ++ ++ "xvaddsp 32, 32, 34 \n\t" ++ "xvaddsp 36, 36, 38 \n\t" ++ ++ "xvaddsp 32, 32, 36 \n\t" ++ ++ "xxsldwi 33, 32, 32, 2 \n\t" ++ "xvaddsp 32, 32, 33 \n\t" ++ ++ "xxsldwi 33, 32, 32, 1 \n\t" ++ "xvaddsp 32, 32, 33 \n\t" ++ ++ "xscvspdp %0, 32 \n" ++ ++ "#n=%1 x=%3=%2 sum=%0 o16=%8 o32=%9 o48=%10 o64=%11 o80=%12 o96=%13 o112=%14\n" ++ "#t0=%x3 t1=%x4 t2=%x5 t3=%x6" ++ : ++ "=f" (sum), // 0 ++ "+r" (n), // 1 ++ "+b" (x), // 2 ++ "=wa" (t0), // 3 ++ "=wa" (t1), // 4 ++ "=wa" (t2), // 5 ++ "=wa" (t3) // 6 ++ : ++ "m" (*x), ++ "b" (16), // 8 ++ "b" (32), // 9 ++ "b" (48), // 10 ++ "b" (64), // 11 ++ "b" (80), // 12 ++ "b" (96), // 13 ++ "b" (112) // 14 ++ : ++ "cr0", ++ "vs32","vs33","vs34","vs35","vs36","vs37","vs38","vs39", ++ "vs40","vs41","vs42","vs43","vs44","vs45","vs46","vs47", ++ "vs48","vs49","vs50","vs51" ++ ); ++ ++ return sum; ++} +diff --git a/kernel/power/ccopy_microk_power8.c b/kernel/power/ccopy_microk_power8.c +index 95b3559..b2b1bea 100644 +--- a/kernel/power/ccopy_microk_power8.c ++++ b/kernel/power/ccopy_microk_power8.c +@@ -35,140 +35,121 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + #define HAVE_KERNEL_32 1 + +-static void ccopy_kernel_32( BLASLONG n, FLOAT *x, FLOAT *y) __attribute__ ((noinline)); +- +-static void ccopy_kernel_32( BLASLONG n, FLOAT *x, FLOAT *y) ++static void ccopy_kernel_32 (long n, float *x, float *y) + { +- +- +- BLASLONG i = n; +- BLASLONG o16 = 16; +- BLASLONG o32 = 32; +- BLASLONG o48 = 48; +- BLASLONG o64 = 64; +- BLASLONG o80 = 80; +- BLASLONG o96 = 96; +- BLASLONG o112 = 112; +- FLOAT *x1=x; +- FLOAT *y1=y; +- BLASLONG pre = 384; +- BLASLONG alpha=0; +- +- __asm__ __volatile__ +- ( +- +- "lxvw4x 40, 0, %2 \n\t" +- "lxvw4x 41, %5, %2 \n\t" +- "lxvw4x 42, %6, %2 \n\t" +- "lxvw4x 43, %7, %2 \n\t" +- "lxvw4x 44, %8, %2 \n\t" +- "lxvw4x 45, %9, %2 \n\t" +- "lxvw4x 46, %10, %2 \n\t" +- "lxvw4x 47, %11, %2 \n\t" +- +- "addi %2, %2, 128 \n\t" +- +- "lxvw4x 50, 0, %2 \n\t" +- "lxvw4x 51, %5, %2 \n\t" +- "lxvw4x 52, %6, %2 \n\t" +- "lxvw4x 53, %7, %2 \n\t" +- "lxvw4x 54, %8, %2 \n\t" +- "lxvw4x 55, %9, %2 \n\t" +- "lxvw4x 56, %10, %2 \n\t" +- "lxvw4x 57, %11, %2 \n\t" +- +- "addi %2, %2, 128 \n\t" +- +- "addic. %0 , %0 , -32 \n\t" +- "ble 2f \n\t" +- +- ".align 5 \n\t" +- "1: \n\t" +- +- "stxvw4x 40, 0, %1 \n\t" +- "stxvw4x 41, %5, %1 \n\t" +- "lxvw4x 40, 0, %2 \n\t" +- "lxvw4x 41, %5, %2 \n\t" +- "stxvw4x 42, %6, %1 \n\t" +- "stxvw4x 43, %7, %1 \n\t" +- "lxvw4x 42, %6, %2 \n\t" +- "lxvw4x 43, %7, %2 \n\t" +- "stxvw4x 44, %8, %1 \n\t" +- "stxvw4x 45, %9, %1 \n\t" +- "lxvw4x 44, %8, %2 \n\t" +- "lxvw4x 45, %9, %2 \n\t" +- "stxvw4x 46, %10, %1 \n\t" +- "stxvw4x 47, %11, %1 \n\t" +- "lxvw4x 46, %10, %2 \n\t" +- "lxvw4x 47, %11, %2 \n\t" +- +- +- "addi %1, %1, 128 \n\t" +- "addi %2, %2, 128 \n\t" +- +- "stxvw4x 50, 0, %1 \n\t" +- "stxvw4x 51, %5, %1 \n\t" +- "lxvw4x 50, 0, %2 \n\t" +- "lxvw4x 51, %5, %2 \n\t" +- "stxvw4x 52, %6, %1 \n\t" +- "stxvw4x 53, %7, %1 \n\t" +- "lxvw4x 52, %6, %2 \n\t" +- "lxvw4x 53, %7, %2 \n\t" +- "stxvw4x 54, %8, %1 \n\t" +- "stxvw4x 55, %9, %1 \n\t" +- "lxvw4x 54, %8, %2 \n\t" +- "lxvw4x 55, %9, %2 \n\t" +- "stxvw4x 56, %10, %1 \n\t" +- "stxvw4x 57, %11, %1 \n\t" +- "lxvw4x 56, %10, %2 \n\t" +- "lxvw4x 57, %11, %2 \n\t" +- +- "addi %1, %1, 128 \n\t" +- "addi %2, %2, 128 \n\t" +- +- "addic. %0 , %0 , -32 \n\t" +- "bgt 1b \n\t" +- +- "2: \n\t" +- +- "stxvw4x 40, 0, %1 \n\t" +- "stxvw4x 41, %5, %1 \n\t" +- "stxvw4x 42, %6, %1 \n\t" +- "stxvw4x 43, %7, %1 \n\t" +- "stxvw4x 44, %8, %1 \n\t" +- "stxvw4x 45, %9, %1 \n\t" +- "stxvw4x 46, %10, %1 \n\t" +- "stxvw4x 47, %11, %1 \n\t" +- +- "addi %1, %1, 128 \n\t" +- +- "stxvw4x 50, 0, %1 \n\t" +- "stxvw4x 51, %5, %1 \n\t" +- "stxvw4x 52, %6, %1 \n\t" +- "stxvw4x 53, %7, %1 \n\t" +- "stxvw4x 54, %8, %1 \n\t" +- "stxvw4x 55, %9, %1 \n\t" +- "stxvw4x 56, %10, %1 \n\t" +- "stxvw4x 57, %11, %1 \n\t" +- +- +- : +- : +- "r" (i), // 0 +- "r" (y1), // 1 +- "r" (x1), // 2 +- "r" (alpha), // 3 +- "r" (pre), // 4 +- "r" (o16), // 5 +- "r" (o32), // 6 +- "r" (o48), // 7 +- "r" (o64), // 8 +- "r" (o80), // 9 +- "r" (o96), // 10 +- "r" (o112) // 11 +- : "cr0", "%0", "%2" , "%1", "memory" +- ); +- +-} +- +- ++ __asm__ ++ ( ++ "lxvw4x 32, 0, %2 \n\t" ++ "lxvw4x 33, %5, %2 \n\t" ++ "lxvw4x 34, %6, %2 \n\t" ++ "lxvw4x 35, %7, %2 \n\t" ++ "lxvw4x 36, %8, %2 \n\t" ++ "lxvw4x 37, %9, %2 \n\t" ++ "lxvw4x 38, %10, %2 \n\t" ++ "lxvw4x 39, %11, %2 \n\t" ++ ++ "addi %2, %2, 128 \n\t" ++ ++ "lxvw4x 40, 0, %2 \n\t" ++ "lxvw4x 41, %5, %2 \n\t" ++ "lxvw4x 42, %6, %2 \n\t" ++ "lxvw4x 43, %7, %2 \n\t" ++ "lxvw4x 44, %8, %2 \n\t" ++ "lxvw4x 45, %9, %2 \n\t" ++ "lxvw4x 46, %10, %2 \n\t" ++ "lxvw4x 47, %11, %2 \n\t" ++ ++ "addi %2, %2, 128 \n\t" ++ ++ "addic. %1, %1, -32 \n\t" ++ "ble 2f \n\t" ++ ++ ".p2align 5 \n" ++ "1: \n\t" ++ ++ "stxvw4x 32, 0, %3 \n\t" ++ "stxvw4x 33, %5, %3 \n\t" ++ "lxvw4x 32, 0, %2 \n\t" ++ "lxvw4x 33, %5, %2 \n\t" ++ "stxvw4x 34, %6, %3 \n\t" ++ "stxvw4x 35, %7, %3 \n\t" ++ "lxvw4x 34, %6, %2 \n\t" ++ "lxvw4x 35, %7, %2 \n\t" ++ "stxvw4x 36, %8, %3 \n\t" ++ "stxvw4x 37, %9, %3 \n\t" ++ "lxvw4x 36, %8, %2 \n\t" ++ "lxvw4x 37, %9, %2 \n\t" ++ "stxvw4x 38, %10, %3 \n\t" ++ "stxvw4x 39, %11, %3 \n\t" ++ "lxvw4x 38, %10, %2 \n\t" ++ "lxvw4x 39, %11, %2 \n\t" ++ ++ "addi %3, %3, 128 \n\t" ++ "addi %2, %2, 128 \n\t" ++ ++ "stxvw4x 40, 0, %3 \n\t" ++ "stxvw4x 41, %5, %3 \n\t" ++ "lxvw4x 40, 0, %2 \n\t" ++ "lxvw4x 41, %5, %2 \n\t" ++ "stxvw4x 42, %6, %3 \n\t" ++ "stxvw4x 43, %7, %3 \n\t" ++ "lxvw4x 42, %6, %2 \n\t" ++ "lxvw4x 43, %7, %2 \n\t" ++ "stxvw4x 44, %8, %3 \n\t" ++ "stxvw4x 45, %9, %3 \n\t" ++ "lxvw4x 44, %8, %2 \n\t" ++ "lxvw4x 45, %9, %2 \n\t" ++ "stxvw4x 46, %10, %3 \n\t" ++ "stxvw4x 47, %11, %3 \n\t" ++ "lxvw4x 46, %10, %2 \n\t" ++ "lxvw4x 47, %11, %2 \n\t" ++ ++ "addi %3, %3, 128 \n\t" ++ "addi %2, %2, 128 \n\t" ++ ++ "addic. %1, %1, -32 \n\t" ++ "bgt 1b \n" ++ ++ "2: \n\t" ++ ++ "stxvw4x 32, 0, %3 \n\t" ++ "stxvw4x 33, %5, %3 \n\t" ++ "stxvw4x 34, %6, %3 \n\t" ++ "stxvw4x 35, %7, %3 \n\t" ++ "stxvw4x 36, %8, %3 \n\t" ++ "stxvw4x 37, %9, %3 \n\t" ++ "stxvw4x 38, %10, %3 \n\t" ++ "stxvw4x 39, %11, %3 \n\t" ++ ++ "addi %3, %3, 128 \n\t" ++ ++ "stxvw4x 40, 0, %3 \n\t" ++ "stxvw4x 41, %5, %3 \n\t" ++ "stxvw4x 42, %6, %3 \n\t" ++ "stxvw4x 43, %7, %3 \n\t" ++ "stxvw4x 44, %8, %3 \n\t" ++ "stxvw4x 45, %9, %3 \n\t" ++ "stxvw4x 46, %10, %3 \n\t" ++ "stxvw4x 47, %11, %3 \n" ++ ++ "#n=%1 x=%4=%2 y=%0=%3 o16=%5 o32=%6 o48=%7 o64=%8 o80=%9 o96=%10 o112=%11" ++ : ++ "=m" (*y), ++ "+r" (n), // 1 ++ "+b" (x), // 2 ++ "+b" (y) // 3 ++ : ++ "m" (*x), ++ "b" (16), // 5 ++ "b" (32), // 6 ++ "b" (48), // 7 ++ "b" (64), // 8 ++ "b" (80), // 9 ++ "b" (96), // 10 ++ "b" (112) // 11 ++ : ++ "cr0", ++ "vs32","vs33","vs34","vs35","vs36","vs37","vs38","vs39", ++ "vs40","vs41","vs42","vs43","vs44","vs45","vs46","vs47" ++ ); ++} +diff --git a/kernel/power/cswap_microk_power8.c b/kernel/power/cswap_microk_power8.c +index 90ab59c..1dd03dc 100644 +--- a/kernel/power/cswap_microk_power8.c ++++ b/kernel/power/cswap_microk_power8.c +@@ -35,146 +35,124 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + #define HAVE_KERNEL_32 1 + +-static void cswap_kernel_32( BLASLONG n, FLOAT *x, FLOAT *y) __attribute__ ((noinline)); +- +-static void cswap_kernel_32( BLASLONG n, FLOAT *x, FLOAT *y) ++static void cswap_kernel_32 (long n, float *x, float *y) + { +- +- +- BLASLONG i = n; +- BLASLONG o16 = 16; +- BLASLONG o32 = 32; +- BLASLONG o48 = 48; +- BLASLONG o64 = 64; +- BLASLONG o80 = 80; +- BLASLONG o96 = 96; +- BLASLONG o112 = 112; +- FLOAT *x1=x; +- FLOAT *y1=y; +- FLOAT *x2=x+1; +- FLOAT *y2=y+1; +- BLASLONG pre = 384; +- BLASLONG alpha=0; +- +- __asm__ __volatile__ +- ( +- +- "addi %3, %3, -4 \n\t" +- "addi %4, %4, -4 \n\t" +- +- ".align 5 \n\t" +- "1: \n\t" +- +- "lxvw4x 32, 0, %2 \n\t" +- "lxvw4x 33, %5, %2 \n\t" +- "lxvw4x 34, %6, %2 \n\t" +- "lxvw4x 35, %7, %2 \n\t" +- "lxvw4x 36, %8, %2 \n\t" +- "lxvw4x 37, %9, %2 \n\t" +- "lxvw4x 38, %10, %2 \n\t" +- "lxvw4x 39, %11, %2 \n\t" +- +- "addi %2, %2, 128 \n\t" +- +- "lxvw4x 40, 0, %2 \n\t" +- "lxvw4x 41, %5, %2 \n\t" +- "lxvw4x 42, %6, %2 \n\t" +- "lxvw4x 43, %7, %2 \n\t" +- "lxvw4x 44, %8, %2 \n\t" +- "lxvw4x 45, %9, %2 \n\t" +- "lxvw4x 46, %10, %2 \n\t" +- "lxvw4x 47, %11, %2 \n\t" +- +- "addi %2, %2, 128 \n\t" +- +- "lxvw4x 48, 0, %1 \n\t" +- "lxvw4x 49, %5, %1 \n\t" +- "lxvw4x 50, %6, %1 \n\t" +- "lxvw4x 51, %7, %1 \n\t" +- "lxvw4x 52, %8, %1 \n\t" +- "lxvw4x 53, %9, %1 \n\t" +- "lxvw4x 54, %10, %1 \n\t" +- "lxvw4x 55, %11, %1 \n\t" +- +- "addi %1, %1, 128 \n\t" +- +- "lxvw4x 56, 0, %1 \n\t" +- "lxvw4x 57, %5, %1 \n\t" +- "lxvw4x 58, %6, %1 \n\t" +- "lxvw4x 59, %7, %1 \n\t" +- "lxvw4x 60, %8, %1 \n\t" +- "lxvw4x 61, %9, %1 \n\t" +- "lxvw4x 62, %10, %1 \n\t" +- "lxvw4x 63, %11, %1 \n\t" +- +- "addi %1, %1, 128 \n\t" +- +- "stxvw4x 32, 0, %3 \n\t" +- "stxvw4x 33, %5, %3 \n\t" +- "stxvw4x 34, %6, %3 \n\t" +- "stxvw4x 35, %7, %3 \n\t" +- "stxvw4x 36, %8, %3 \n\t" +- "stxvw4x 37, %9, %3 \n\t" +- "stxvw4x 38, %10, %3 \n\t" +- "stxvw4x 39, %11, %3 \n\t" +- +- "addi %3, %3, 128 \n\t" +- +- "stxvw4x 40, 0, %3 \n\t" +- "stxvw4x 41, %5, %3 \n\t" +- "stxvw4x 42, %6, %3 \n\t" +- "stxvw4x 43, %7, %3 \n\t" +- "stxvw4x 44, %8, %3 \n\t" +- "stxvw4x 45, %9, %3 \n\t" +- "stxvw4x 46, %10, %3 \n\t" +- "stxvw4x 47, %11, %3 \n\t" +- +- "addi %3, %3, 128 \n\t" +- +- "stxvw4x 48, 0, %4 \n\t" +- "stxvw4x 49, %5, %4 \n\t" +- "stxvw4x 50, %6, %4 \n\t" +- "stxvw4x 51, %7, %4 \n\t" +- "stxvw4x 52, %8, %4 \n\t" +- "stxvw4x 53, %9, %4 \n\t" +- "stxvw4x 54, %10, %4 \n\t" +- "stxvw4x 55, %11, %4 \n\t" +- +- "addi %4, %4, 128 \n\t" +- +- "stxvw4x 56, 0, %4 \n\t" +- "stxvw4x 57, %5, %4 \n\t" +- "stxvw4x 58, %6, %4 \n\t" +- "stxvw4x 59, %7, %4 \n\t" +- "stxvw4x 60, %8, %4 \n\t" +- "stxvw4x 61, %9, %4 \n\t" +- "stxvw4x 62, %10, %4 \n\t" +- "stxvw4x 63, %11, %4 \n\t" +- +- "addi %4, %4, 128 \n\t" +- +- "addic. %0 , %0 , -32 \n\t" +- "bgt 1b \n\t" +- +- "2: \n\t" +- +- : +- : +- "r" (i), // 0 +- "r" (y1), // 1 +- "r" (x1), // 2 +- "r" (y2), // 3 +- "r" (x2), // 4 +- "r" (o16), // 5 +- "r" (o32), // 6 +- "r" (o48), // 7 +- "r" (o64), // 8 +- "r" (o80), // 9 +- "r" (o96), // 10 +- "r" (o112) // 11 +- : "cr0", "%0", "%2" , "%1", "%3", "%4", "memory" +- ); +- +-} +- +- ++ __asm__ ++ ( ++ ".p2align 5 \n" ++ "1: \n\t" ++ ++ "lxvw4x 32, 0, %4 \n\t" ++ "lxvw4x 33, %5, %4 \n\t" ++ "lxvw4x 34, %6, %4 \n\t" ++ "lxvw4x 35, %7, %4 \n\t" ++ "lxvw4x 36, %8, %4 \n\t" ++ "lxvw4x 37, %9, %4 \n\t" ++ "lxvw4x 38, %10, %4 \n\t" ++ "lxvw4x 39, %11, %4 \n\t" ++ ++ "addi %4, %4, 128 \n\t" ++ ++ "lxvw4x 40, 0, %4 \n\t" ++ "lxvw4x 41, %5, %4 \n\t" ++ "lxvw4x 42, %6, %4 \n\t" ++ "lxvw4x 43, %7, %4 \n\t" ++ "lxvw4x 44, %8, %4 \n\t" ++ "lxvw4x 45, %9, %4 \n\t" ++ "lxvw4x 46, %10, %4 \n\t" ++ "lxvw4x 47, %11, %4 \n\t" ++ ++ "addi %4, %4, -128 \n\t" ++ ++ "lxvw4x 48, 0, %3 \n\t" ++ "lxvw4x 49, %5, %3 \n\t" ++ "lxvw4x 50, %6, %3 \n\t" ++ "lxvw4x 51, %7, %3 \n\t" ++ "lxvw4x 0, %8, %3 \n\t" ++ "lxvw4x 1, %9, %3 \n\t" ++ "lxvw4x 2, %10, %3 \n\t" ++ "lxvw4x 3, %11, %3 \n\t" ++ ++ "addi %3, %3, 128 \n\t" ++ ++ "lxvw4x 4, 0, %3 \n\t" ++ "lxvw4x 5, %5, %3 \n\t" ++ "lxvw4x 6, %6, %3 \n\t" ++ "lxvw4x 7, %7, %3 \n\t" ++ "lxvw4x 8, %8, %3 \n\t" ++ "lxvw4x 9, %9, %3 \n\t" ++ "lxvw4x 10, %10, %3 \n\t" ++ "lxvw4x 11, %11, %3 \n\t" ++ ++ "addi %3, %3, -128 \n\t" ++ ++ "stxvw4x 32, 0, %3 \n\t" ++ "stxvw4x 33, %5, %3 \n\t" ++ "stxvw4x 34, %6, %3 \n\t" ++ "stxvw4x 35, %7, %3 \n\t" ++ "stxvw4x 36, %8, %3 \n\t" ++ "stxvw4x 37, %9, %3 \n\t" ++ "stxvw4x 38, %10, %3 \n\t" ++ "stxvw4x 39, %11, %3 \n\t" ++ ++ "addi %3, %3, 128 \n\t" ++ ++ "stxvw4x 40, 0, %3 \n\t" ++ "stxvw4x 41, %5, %3 \n\t" ++ "stxvw4x 42, %6, %3 \n\t" ++ "stxvw4x 43, %7, %3 \n\t" ++ "stxvw4x 44, %8, %3 \n\t" ++ "stxvw4x 45, %9, %3 \n\t" ++ "stxvw4x 46, %10, %3 \n\t" ++ "stxvw4x 47, %11, %3 \n\t" ++ ++ "addi %3, %3, 128 \n\t" ++ ++ "stxvw4x 48, 0, %4 \n\t" ++ "stxvw4x 49, %5, %4 \n\t" ++ "stxvw4x 50, %6, %4 \n\t" ++ "stxvw4x 51, %7, %4 \n\t" ++ "stxvw4x 0, %8, %4 \n\t" ++ "stxvw4x 1, %9, %4 \n\t" ++ "stxvw4x 2, %10, %4 \n\t" ++ "stxvw4x 3, %11, %4 \n\t" ++ ++ "addi %4, %4, 128 \n\t" ++ ++ "stxvw4x 4, 0, %4 \n\t" ++ "stxvw4x 5, %5, %4 \n\t" ++ "stxvw4x 6, %6, %4 \n\t" ++ "stxvw4x 7, %7, %4 \n\t" ++ "stxvw4x 8, %8, %4 \n\t" ++ "stxvw4x 9, %9, %4 \n\t" ++ "stxvw4x 10, %10, %4 \n\t" ++ "stxvw4x 11, %11, %4 \n\t" ++ ++ "addi %4, %4, 128 \n\t" ++ ++ "addic. %2, %2, -32 \n\t" ++ "bgt 1b \n" ++ ++ "#n=%2 x=%0=%3 y=%1=%4 o16=%5 o32=%6 o48=%7 o64=%8 o80=%9 o96=%10 o112=%11" ++ : ++ "+m" (*x), ++ "+m" (*y), ++ "+r" (n), // 2 ++ "+b" (x), // 3 ++ "+b" (y) // 4 ++ : ++ "b" (16), // 5 ++ "b" (32), // 6 ++ "b" (48), // 7 ++ "b" (64), // 8 ++ "b" (80), // 9 ++ "b" (96), // 10 ++ "b" (112) // 11 ++ : ++ "cr0", ++ "vs32","vs33","vs34","vs35","vs36","vs37","vs38","vs39", ++ "vs40","vs41","vs42","vs43","vs44","vs45","vs46","vs47", ++ "vs48","vs49","vs50","vs51","vs0","vs1","vs2","vs3", ++ "vs4","vs5","vs6","vs7","vs8","vs9","vs10","vs11" ++ ); ++} +diff --git a/kernel/power/dasum.c b/kernel/power/dasum.c +index 77f5345..73962c2 100644 +--- a/kernel/power/dasum.c ++++ b/kernel/power/dasum.c +@@ -42,7 +42,7 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + #else + +-#define ABS fabsf ++#error supports double only + + #endif + +@@ -53,7 +53,7 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + #ifndef HAVE_KERNEL_16 + +-static void dasum_kernel_16(BLASLONG n, FLOAT *x1, FLOAT *svec) ++static FLOAT dasum_kernel_16(BLASLONG n, FLOAT *x1) + { + + BLASLONG i=0; +@@ -92,9 +92,7 @@ static void dasum_kernel_16(BLASLONG n, FLOAT *x1, FLOAT *svec) + + } + +- svec[0] = sum0+sum1+sum2+sum3; +- svec[1] = 0.0; +- ++ return sum0+sum1+sum2+sum3; + } + + #endif +@@ -103,7 +101,6 @@ FLOAT CNAME(BLASLONG n, FLOAT *x, BLASLONG inc_x) + { + BLASLONG i=0; + FLOAT sumf = 0.0; +- FLOAT svec[2] __attribute__ ((aligned (16)));; + BLASLONG n1; + + if (n <= 0 || inc_x <= 0) return(sumf); +@@ -115,8 +112,7 @@ FLOAT CNAME(BLASLONG n, FLOAT *x, BLASLONG inc_x) + if ( n1 > 0 ) + { + +- dasum_kernel_16(n1, x, svec); +- sumf = svec[0] + svec[1]; ++ sumf = dasum_kernel_16(n1, x); + i=n1; + } + +diff --git a/kernel/power/dasum_microk_power8.c b/kernel/power/dasum_microk_power8.c +index cc38c4f..880d7d2 100644 +--- a/kernel/power/dasum_microk_power8.c ++++ b/kernel/power/dasum_microk_power8.c +@@ -34,144 +34,142 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + **************************************************************************************/ + + #define HAVE_KERNEL_16 1 +-static void dasum_kernel_16( BLASLONG n, FLOAT *x, FLOAT *svec) __attribute__ ((noinline)); + +-static void dasum_kernel_16( BLASLONG n, FLOAT *x, FLOAT *svec) ++static double dasum_kernel_16 (long n, double *x) + { +- +- +- BLASLONG i = n; +- BLASLONG o16 = 16; +- BLASLONG o32 = 32; +- BLASLONG o48 = 48; +- BLASLONG o64 = 64; +- BLASLONG o80 = 80; +- BLASLONG o96 = 96; +- BLASLONG o112 = 112; +- FLOAT *x1=x; +- BLASLONG pre = 384; +- +- __asm__ __volatile__ +- ( +- +- "dcbt %2 , %4 \n\t" +- +- "xxlxor 32,32,32 \n\t" +- "xxlxor 33,33,33 \n\t" +- "xxlxor 34,34,34 \n\t" +- "xxlxor 35,35,35 \n\t" +- "xxlxor 36,36,36 \n\t" +- "xxlxor 37,37,37 \n\t" +- "xxlxor 38,38,38 \n\t" +- "xxlxor 39,39,39 \n\t" +- +- "lxvd2x 40, 0, %2 \n\t" +- "lxvd2x 41, %5, %2 \n\t" +- "lxvd2x 42, %6, %2 \n\t" +- "lxvd2x 43, %7, %2 \n\t" +- "lxvd2x 44, %8, %2 \n\t" +- "lxvd2x 45, %9, %2 \n\t" +- "lxvd2x 46, %10, %2 \n\t" +- "lxvd2x 47, %11, %2 \n\t" +- +- "addi %2, %2, 128 \n\t" +- +- "addic. %0 , %0 , -16 \n\t" +- "ble 2f \n\t" +- +- ".align 5 \n\t" +- "1: \n\t" +- +- "dcbt %2 , %4 \n\t" +- +- "xvabsdp 48, 40 \n\t" +- "xvabsdp 49, 41 \n\t" +- "xvabsdp 50, 42 \n\t" +- "xvabsdp 51, 43 \n\t" +- +- "lxvd2x 40, 0, %2 \n\t" +- "lxvd2x 41, %5, %2 \n\t" +- +- "xvabsdp 52, 44 \n\t" +- "xvabsdp 53, 45 \n\t" +- +- "lxvd2x 42, %6, %2 \n\t" +- "lxvd2x 43, %7, %2 \n\t" +- +- "xvabsdp 54, 46 \n\t" +- "xvabsdp 55, 47 \n\t" +- +- "lxvd2x 44, %8, %2 \n\t" +- "lxvd2x 45, %9, %2 \n\t" +- +- "xvadddp 32, 32, 48 \n\t" +- "xvadddp 33, 33, 49 \n\t" +- +- "lxvd2x 46, %10, %2 \n\t" +- "lxvd2x 47, %11, %2 \n\t" +- +- "xvadddp 34, 34, 50 \n\t" +- "xvadddp 35, 35, 51 \n\t" +- "addi %2, %2, 128 \n\t" +- "xvadddp 36, 36, 52 \n\t" +- "xvadddp 37, 37, 53 \n\t" +- "addic. %0 , %0 , -16 \n\t" +- "xvadddp 38, 38, 54 \n\t" +- "xvadddp 39, 39, 55 \n\t" +- +- "bgt 1b \n\t" +- +- "2: \n\t" +- +- +- "xvabsdp 48, 40 \n\t" +- "xvabsdp 49, 41 \n\t" +- "xvabsdp 50, 42 \n\t" +- "xvabsdp 51, 43 \n\t" +- "xvabsdp 52, 44 \n\t" +- "xvabsdp 53, 45 \n\t" +- "xvabsdp 54, 46 \n\t" +- "xvabsdp 55, 47 \n\t" +- +- "xvadddp 32, 32, 48 \n\t" +- "xvadddp 33, 33, 49 \n\t" +- "xvadddp 34, 34, 50 \n\t" +- "xvadddp 35, 35, 51 \n\t" +- "xvadddp 36, 36, 52 \n\t" +- "xvadddp 37, 37, 53 \n\t" +- "xvadddp 38, 38, 54 \n\t" +- "xvadddp 39, 39, 55 \n\t" +- +- "xvadddp 32, 32, 33 \n\t" +- "xvadddp 34, 34, 35 \n\t" +- "xvadddp 36, 36, 37 \n\t" +- "xvadddp 38, 38, 39 \n\t" +- +- "xvadddp 32, 32, 34 \n\t" +- "xvadddp 36, 36, 38 \n\t" +- +- "xvadddp 32, 32, 36 \n\t" +- +- +- "stxvd2x 32, 0, %3 \n\t" +- +- : +- : +- "r" (i), // 0 +- "r" (n), // 1 +- "r" (x1), // 2 +- "r" (svec), // 3 +- "r" (pre), // 4 +- "r" (o16), // 5 +- "r" (o32), // 6 +- "r" (o48), // 7 +- "r" (o64), // 8 +- "r" (o80), // 9 +- "r" (o96), // 10 +- "r" (o112) // 11 +- : "cr0", "%0", "%2", "memory" +- ); +- +-} ++ double sum; ++ __vector double t0; ++ __vector double t1; ++ __vector double t2; ++ __vector double t3; ++ ++ __asm__ ++ ( ++ "dcbt 0, %2 \n\t" ++ ++ "xxlxor 32, 32, 32 \n\t" ++ "xxlxor 33, 33, 33 \n\t" ++ "xxlxor 34, 34, 34 \n\t" ++ "xxlxor 35, 35, 35 \n\t" ++ "xxlxor 36, 36, 36 \n\t" ++ "xxlxor 37, 37, 37 \n\t" ++ "xxlxor 38, 38, 38 \n\t" ++ "xxlxor 39, 39, 39 \n\t" ++ ++ "lxvd2x 40, 0, %2 \n\t" ++ "lxvd2x 41, %8, %2 \n\t" ++ "lxvd2x 42, %9, %2 \n\t" ++ "lxvd2x 43, %10, %2 \n\t" ++ "lxvd2x 44, %11, %2 \n\t" ++ "lxvd2x 45, %12, %2 \n\t" ++ "lxvd2x 46, %13, %2 \n\t" ++ "lxvd2x 47, %14, %2 \n\t" ++ ++ "addi %2, %2, 128 \n\t" ++ ++ "addic. %1, %1, -16 \n\t" ++ "ble 2f \n\t" ++ ++ ".p2align 5 \n" ++ "1: \n\t" ++ ++ "xvabsdp 48, 40 \n\t" ++ "xvabsdp 49, 41 \n\t" ++ "xvabsdp 50, 42 \n\t" ++ "xvabsdp 51, 43 \n\t" ++ ++ "lxvd2x 40, 0, %2 \n\t" ++ "lxvd2x 41, %8, %2 \n\t" ++ ++ "xvabsdp %x3, 44 \n\t" ++ "xvabsdp %x4, 45 \n\t" ++ ++ "lxvd2x 42, %9, %2 \n\t" ++ "lxvd2x 43, %10, %2 \n\t" ++ ++ "xvabsdp %x5, 46 \n\t" ++ "xvabsdp %x6, 47 \n\t" ++ ++ "lxvd2x 44, %11, %2 \n\t" ++ "lxvd2x 45, %12, %2 \n\t" ++ ++ "xvadddp 32, 32, 48 \n\t" ++ "xvadddp 33, 33, 49 \n\t" ++ ++ "lxvd2x 46, %13, %2 \n\t" ++ "lxvd2x 47, %14, %2 \n\t" ++ ++ "xvadddp 34, 34, 50 \n\t" ++ "xvadddp 35, 35, 51 \n\t" ++ "addi %2, %2, 128 \n\t" ++ "xvadddp 36, 36, %x3 \n\t" ++ "xvadddp 37, 37, %x4 \n\t" ++ "addic. %1, %1, -16 \n\t" ++ "xvadddp 38, 38, %x5 \n\t" ++ "xvadddp 39, 39, %x6 \n\t" ++ ++ "bgt 1b \n" ++ ++ "2: \n\t" ++ ++ "xvabsdp 48, 40 \n\t" ++ "xvabsdp 49, 41 \n\t" ++ "xvabsdp 50, 42 \n\t" ++ "xvabsdp 51, 43 \n\t" ++ "xvabsdp %x3, 44 \n\t" ++ "xvabsdp %x4, 45 \n\t" ++ "xvabsdp %x5, 46 \n\t" ++ "xvabsdp %x6, 47 \n\t" ++ ++ "xvadddp 32, 32, 48 \n\t" ++ "xvadddp 33, 33, 49 \n\t" ++ "xvadddp 34, 34, 50 \n\t" ++ "xvadddp 35, 35, 51 \n\t" ++ "xvadddp 36, 36, %x3 \n\t" ++ "xvadddp 37, 37, %x4 \n\t" ++ "xvadddp 38, 38, %x5 \n\t" ++ "xvadddp 39, 39, %x6 \n\t" ++ ++ "xvadddp 32, 32, 33 \n\t" ++ "xvadddp 34, 34, 35 \n\t" ++ "xvadddp 36, 36, 37 \n\t" ++ "xvadddp 38, 38, 39 \n\t" ++ ++ "xvadddp 32, 32, 34 \n\t" ++ "xvadddp 36, 36, 38 \n\t" ++ ++ "xvadddp 32, 32, 36 \n\t" ++ ++ "xxswapd 33, 32 \n\t" ++ "xsadddp %x0, 32, 33 \n" ++ ++ "#n=%1 x=%3=%2 sum=%0 o16=%8 o32=%9 o48=%10 o64=%11 o80=%12 o96=%13 o112=%14\n" ++ "#t0=%x3 t1=%x4 t2=%x5 t3=%x6" ++ : ++ "=d" (sum), // 0 ++ "+r" (n), // 1 ++ "+b" (x), // 2 ++ "=wa" (t0), // 3 ++ "=wa" (t1), // 4 ++ "=wa" (t2), // 5 ++ "=wa" (t3) // 6 ++ : ++ "m" (*x), ++ "b" (16), // 8 ++ "b" (32), // 9 ++ "b" (48), // 10 ++ "b" (64), // 11 ++ "b" (80), // 12 ++ "b" (96), // 13 ++ "b" (112) // 14 ++ : ++ "cr0", ++ "vs32","vs33","vs34","vs35","vs36","vs37","vs38","vs39", ++ "vs40","vs41","vs42","vs43","vs44","vs45","vs46","vs47", ++ "vs48","vs49","vs50","vs51" ++ ); ++ ++ return sum; ++} + + +diff --git a/kernel/power/daxpy.c b/kernel/power/daxpy.c +index 4365bd8..df0572e 100644 +--- a/kernel/power/daxpy.c ++++ b/kernel/power/daxpy.c +@@ -43,21 +43,20 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + #ifndef HAVE_KERNEL_8 + +-static void daxpy_kernel_8(BLASLONG n, FLOAT *x, FLOAT *y, FLOAT *alpha) ++static void daxpy_kernel_8(BLASLONG n, FLOAT *x, FLOAT *y, FLOAT alpha) + { + BLASLONG register i = 0; +- FLOAT a = *alpha; + + while(i < n) + { +- y[i] += a * x[i]; +- y[i+1] += a * x[i+1]; +- y[i+2] += a * x[i+2]; +- y[i+3] += a * x[i+3]; +- y[i+4] += a * x[i+4]; +- y[i+5] += a * x[i+5]; +- y[i+6] += a * x[i+6]; +- y[i+7] += a * x[i+7]; ++ y[i] += alpha * x[i]; ++ y[i+1] += alpha * x[i+1]; ++ y[i+2] += alpha * x[i+2]; ++ y[i+3] += alpha * x[i+3]; ++ y[i+4] += alpha * x[i+4]; ++ y[i+5] += alpha * x[i+5]; ++ y[i+6] += alpha * x[i+6]; ++ y[i+7] += alpha * x[i+7]; + i+=8 ; + + } +@@ -70,11 +69,6 @@ int CNAME(BLASLONG n, BLASLONG dummy0, BLASLONG dummy1, FLOAT da, FLOAT *x, BLAS + { + BLASLONG i=0; + BLASLONG ix=0,iy=0; +- FLOAT a2[4]; +- a2[0]=da; +- a2[1]=da; +- a2[2]=da; +- a2[3]=da; + + if ( n <= 0 ) return(0); + +@@ -84,7 +78,7 @@ int CNAME(BLASLONG n, BLASLONG dummy0, BLASLONG dummy1, FLOAT da, FLOAT *x, BLAS + BLASLONG n1 = n & -16; + + if ( n1 ) +- daxpy_kernel_8(n1, x, y , a2 ); ++ daxpy_kernel_8(n1, x, y, da); + + i = n1; + while(i < n) +diff --git a/kernel/power/daxpy_microk_power8.c b/kernel/power/daxpy_microk_power8.c +index bb3f73a..fb714a3 100644 +--- a/kernel/power/daxpy_microk_power8.c ++++ b/kernel/power/daxpy_microk_power8.c +@@ -35,167 +35,183 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + #define HAVE_KERNEL_8 1 +-static void daxpy_kernel_8( BLASLONG n, FLOAT *x, FLOAT *y , FLOAT *alpha) __attribute__ ((noinline)); + +-static void daxpy_kernel_8( BLASLONG n, FLOAT *x, FLOAT *y, FLOAT *alpha) ++static void daxpy_kernel_8 (long n, double *x, double *y, double alpha) + { ++ __vector double t0; ++ __vector double t1; ++ __vector double t2; ++ __vector double t3; ++ __vector double t4; ++ __vector double t5; ++ __vector double t6; ++ __vector double t7; ++ __vector double t8; ++ __vector double t9; ++ __vector double t10; ++ __vector double t11; ++ __vector double t12; ++ __vector double t13; ++ __vector double t14; ++ __vector double t15; ++ __vector double t16; + ++ __asm__ ++ ( ++ "xxspltd %x4, %x22, 0 \n\t" + +- BLASLONG i = n; +- BLASLONG o16 = 16; +- BLASLONG o32 = 32; +- BLASLONG o48 = 48; +- FLOAT *x1=x; +- FLOAT *y1=y; +- FLOAT *y2=y+1; +- BLASLONG pre = 384; ++ "dcbt 0, %2 \n\t" ++ "dcbt 0, %3 \n\t" + +- __asm__ __volatile__ +- ( ++ "lxvd2x %x5, 0, %2 \n\t" ++ "lxvd2x %x6, %23, %2 \n\t" ++ "lxvd2x %x7, %24, %2 \n\t" ++ "lxvd2x %x8, %25, %2 \n\t" + +- "lxsdx 33, %5, %4 \n\t" +- "xxspltd 32, 33, 0 \n\t" +- "addi %8, %8, -8 \n\t" ++ "lxvd2x %x13, 0, %3 \n\t" ++ "lxvd2x %x14, %23, %3 \n\t" ++ "lxvd2x %x15, %24, %3 \n\t" ++ "lxvd2x %x16, %25, %3 \n\t" + +- "dcbt %2, %9 \n\t" +- "dcbt %3, %9 \n\t" ++ "addi %2, %2, 64 \n\t" ++ "addi %3, %3, 64 \n\t" + +- "lxvd2x 40, 0, %2 \n\t" +- "lxvd2x 41, %5, %2 \n\t" +- "lxvd2x 42, %6, %2 \n\t" +- "lxvd2x 43, %7, %2 \n\t" ++ "lxvd2x %x9, 0, %2 \n\t" ++ "lxvd2x %x10, %23, %2 \n\t" ++ "lxvd2x %x11, %24, %2 \n\t" ++ "lxvd2x %x12, %25, %2 \n\t" + +- "lxvd2x 48, 0, %3 \n\t" +- "lxvd2x 49, %5, %3 \n\t" +- "lxvd2x 50, %6, %3 \n\t" +- "lxvd2x 51, %7, %3 \n\t" +- +- "addi %2, %2, 64 \n\t" +- "addi %3, %3, 64 \n\t" +- +- "lxvd2x 44, 0, %2 \n\t" +- "lxvd2x 45, %5, %2 \n\t" +- "lxvd2x 46, %6, %2 \n\t" +- "lxvd2x 47, %7, %2 \n\t" +- +- "lxvd2x 52, 0, %3 \n\t" +- "lxvd2x 53, %5, %3 \n\t" +- "lxvd2x 54, %6, %3 \n\t" +- "lxvd2x 55, %7, %3 \n\t" +- +- "addi %2, %2, 64 \n\t" +- "addi %3, %3, 64 \n\t" +- +- "addic. %0 , %0 , -16 \n\t" +- "ble 2f \n\t" +- +- ".align 5 \n\t" +- "1: \n\t" +- +- "dcbt %2, %9 \n\t" +- "dcbt %3, %9 \n\t" +- +- "xvmaddadp 48, 40, 32 \n\t" +- "xvmaddadp 49, 41, 32 \n\t" +- +- "lxvd2x 40, 0, %2 \n\t" +- "lxvd2x 41, %5, %2 \n\t" +- +- "stxvd2x 48, 0, %8 \n\t" +- "stxvd2x 49, %5, %8 \n\t" +- +- "xvmaddadp 50, 42, 32 \n\t" +- "xvmaddadp 51, 43, 32 \n\t" +- +- "lxvd2x 42, %6, %2 \n\t" +- "lxvd2x 43, %7, %2 \n\t" +- +- "stxvd2x 50, %6, %8 \n\t" +- "stxvd2x 51, %7, %8 \n\t" +- +- "lxvd2x 48, 0, %3 \n\t" +- "lxvd2x 49, %5, %3 \n\t" +- "lxvd2x 50, %6, %3 \n\t" +- "lxvd2x 51, %7, %3 \n\t" +- +- "addi %2, %2, 64 \n\t" +- "addi %8, %8, 64 \n\t" +- +- "xvmaddadp 52, 44, 32 \n\t" +- "addi %3, %3, 64 \n\t" +- "xvmaddadp 53, 45, 32 \n\t" +- +- "lxvd2x 44, 0, %2 \n\t" +- "lxvd2x 45, %5, %2 \n\t" +- +- "stxvd2x 52, 0, %8 \n\t" +- "stxvd2x 53, %5, %8 \n\t" +- +- "xvmaddadp 54, 46, 32 \n\t" +- "xvmaddadp 55, 47, 32 \n\t" +- +- "lxvd2x 46, %6, %2 \n\t" +- "lxvd2x 47, %7, %2 \n\t" +- +- "stxvd2x 54, %6, %8 \n\t" +- "stxvd2x 55, %7, %8 \n\t" +- +- "addi %2, %2, 64 \n\t" +- "addi %8, %8, 64 \n\t" +- +- "lxvd2x 52, 0, %3 \n\t" +- "lxvd2x 53, %5, %3 \n\t" +- "lxvd2x 54, %6, %3 \n\t" +- "lxvd2x 55, %7, %3 \n\t" +- +- "addi %3, %3, 64 \n\t" +- +- +- "addic. %0 , %0 , -16 \n\t" +- "bgt 1b \n\t" +- +- "2: \n\t" +- +- +- "xvmaddadp 48, 40, 32 \n\t" +- "xvmaddadp 49, 41, 32 \n\t" +- "xvmaddadp 50, 42, 32 \n\t" +- "xvmaddadp 51, 43, 32 \n\t" +- +- "xvmaddadp 52, 44, 32 \n\t" +- "xvmaddadp 53, 45, 32 \n\t" +- "xvmaddadp 54, 46, 32 \n\t" +- "xvmaddadp 55, 47, 32 \n\t" +- +- "stxvd2x 48, 0, %8 \n\t" +- "stxvd2x 49, %5, %8 \n\t" +- "stxvd2x 50, %6, %8 \n\t" +- "stxvd2x 51, %7, %8 \n\t" +- +- "addi %8, %8, 64 \n\t" +- +- "stxvd2x 52, 0, %8 \n\t" +- "stxvd2x 53, %5, %8 \n\t" +- "stxvd2x 54, %6, %8 \n\t" +- "stxvd2x 55, %7, %8 \n\t" +- +- "addi %8, %8, 64 \n\t" +- +- : +- : +- "r" (i), // 0 +- "r" (n), // 1 +- "r" (x1), // 2 +- "r" (y1), // 3 +- "r" (alpha), // 4 +- "r" (o16), // 5 +- "r" (o32), // 6 +- "r" (o48), // 7 +- "r" (y2), // 8 +- "r" (pre) // 9 +- : "cr0", "%0", "%2" , "%3", "%8", "memory" +- ); +- +-} ++ "lxvd2x %x17, 0, %3 \n\t" ++ "lxvd2x %x18, %23, %3 \n\t" ++ "lxvd2x %x19, %24, %3 \n\t" ++ "lxvd2x %x20, %25, %3 \n\t" ++ ++ "addi %2, %2, 64 \n\t" ++ "addi %3, %3, -64 \n\t" ++ ++ "addic. %1, %1, -16 \n\t" ++ "ble 2f \n\t" ++ ++ ".align 5 \n" ++ "1: \n\t" ++ ++ "xvmaddadp %x13, %x5, %x4 \n\t" ++ "xvmaddadp %x14, %x6, %x4 \n\t" ++ ++ "lxvd2x %x5, 0, %2 \n\t" ++ "lxvd2x %x6, %23, %2 \n\t" ++ ++ "stxvd2x %x13, 0, %3 \n\t" ++ "stxvd2x %x14, %23, %3 \n\t" ++ ++ "xvmaddadp %x15, %x7, %x4 \n\t" ++ "xvmaddadp %x16, %x8, %x4 \n\t" ++ ++ "lxvd2x %x7, %24, %2 \n\t" ++ "lxvd2x %x8, %25, %2 \n\t" ++ ++ "stxvd2x %x15, %24, %3 \n\t" ++ "stxvd2x %x16, %25, %3 \n\t" ++ ++ "addi %2, %2, 64 \n\t" ++ "addi %3, %3, 128 \n\t" ++ ++ "lxvd2x %x13, 0, %3 \n\t" ++ "lxvd2x %x14, %23, %3 \n\t" ++ "lxvd2x %x15, %24, %3 \n\t" ++ "lxvd2x %x16, %25, %3 \n\t" ++ ++ "addi %3, %3, -64 \n\t" ++ ++ "xvmaddadp %x17, %x9, %x4 \n\t" ++ "xvmaddadp %x18, %x10, %x4 \n\t" ++ ++ "lxvd2x %x9, 0, %2 \n\t" ++ "lxvd2x %x10, %23, %2 \n\t" ++ ++ "stxvd2x %x17, 0, %3 \n\t" ++ "stxvd2x %x18, %23, %3 \n\t" ++ ++ "xvmaddadp %x19, %x11, %x4 \n\t" ++ "xvmaddadp %x20, %x12, %x4 \n\t" ++ ++ "lxvd2x %x11, %24, %2 \n\t" ++ "lxvd2x %x12, %25, %2 \n\t" ++ ++ "stxvd2x %x19, %24, %3 \n\t" ++ "stxvd2x %x20, %25, %3 \n\t" ++ ++ "addi %2, %2, 64 \n\t" ++ "addi %3, %3, 128 \n\t" ++ ++ "lxvd2x %x17, 0, %3 \n\t" ++ "lxvd2x %x18, %23, %3 \n\t" ++ "lxvd2x %x19, %24, %3 \n\t" ++ "lxvd2x %x20, %25, %3 \n\t" ++ ++ "addi %3, %3, -64 \n\t" ++ ++ "addic. %1, %1, -16 \n\t" ++ "bgt 1b \n" ++ ++ "2: \n\t" ++ ++ "xvmaddadp %x13, %x5, %x4 \n\t" ++ "xvmaddadp %x14, %x6, %x4 \n\t" ++ "xvmaddadp %x15, %x7, %x4 \n\t" ++ "xvmaddadp %x16, %x8, %x4 \n\t" ++ ++ "xvmaddadp %x17, %x9, %x4 \n\t" ++ "xvmaddadp %x18, %x10, %x4 \n\t" ++ "xvmaddadp %x19, %x11, %x4 \n\t" ++ "xvmaddadp %x20, %x12, %x4 \n\t" ++ ++ "stxvd2x %x13, 0, %3 \n\t" ++ "stxvd2x %x14, %23, %3 \n\t" ++ "stxvd2x %x15, %24, %3 \n\t" ++ "stxvd2x %x16, %25, %3 \n\t" ++ ++ "addi %3, %3, 64 \n\t" ++ ++ "stxvd2x %x17, 0, %3 \n\t" ++ "stxvd2x %x18, %23, %3 \n\t" ++ "stxvd2x %x19, %24, %3 \n\t" ++ "stxvd2x %x20, %25, %3 \n" ++ ++ "#n=%1 x=%21=%2 y=%0=%3 alpha=%22 o16=%23 o32=%24 o48=%25\n" ++ "#t0=%x4 t1=%x5 t2=%x6 t3=%x7 t4=%x8 t5=%x9 t6=%x10 t7=%x11 t8=%x12 t9=%x13 t10=%x14 t11=%x15 t12=%x16 t13=%x17 t14=%x18 t15=%x19 t16=%x20" ++ : ++ "+m" (*y), ++ "+r" (n), // 1 ++ "+b" (x), // 2 ++ "+b" (y), // 3 ++ "=wa" (t0), // 4 ++ "=wa" (t1), // 5 ++ "=wa" (t2), // 6 ++ "=wa" (t3), // 7 ++ "=wa" (t4), // 8 ++ "=wa" (t5), // 9 ++ "=wa" (t6), // 10 ++ "=wa" (t7), // 11 ++ "=wa" (t8), // 12 ++ "=wa" (t9), // 13 ++ "=wa" (t10), // 14 ++ "=wa" (t11), // 15 ++ "=wa" (t12), // 16 ++ "=wa" (t13), // 17 ++ "=wa" (t14), // 18 ++ "=wa" (t15), // 19 ++ "=wa" (t16) // 20 ++ : ++ "m" (*x), ++ "d" (alpha), // 22 ++ "b" (16), // 23 ++ "b" (32), // 24 ++ "b" (48) // 25 ++ : ++ "cr0" ++ ); ++ ++} + + +diff --git a/kernel/power/dcopy_microk_power8.c b/kernel/power/dcopy_microk_power8.c +index 04f7db5..261dc04 100644 +--- a/kernel/power/dcopy_microk_power8.c ++++ b/kernel/power/dcopy_microk_power8.c +@@ -35,140 +35,121 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + #define HAVE_KERNEL_32 1 + +-static void dcopy_kernel_32( BLASLONG n, FLOAT *x, FLOAT *y) __attribute__ ((noinline)); +- +-static void dcopy_kernel_32( BLASLONG n, FLOAT *x, FLOAT *y) ++static void dcopy_kernel_32 (long n, double *x, double *y) + { +- +- +- BLASLONG i = n; +- BLASLONG o16 = 16; +- BLASLONG o32 = 32; +- BLASLONG o48 = 48; +- BLASLONG o64 = 64; +- BLASLONG o80 = 80; +- BLASLONG o96 = 96; +- BLASLONG o112 = 112; +- FLOAT *x1=x; +- FLOAT *y1=y; +- BLASLONG pre = 384; +- BLASLONG alpha=0; +- +- __asm__ __volatile__ +- ( +- +- "lxvd2x 40, 0, %2 \n\t" +- "lxvd2x 41, %5, %2 \n\t" +- "lxvd2x 42, %6, %2 \n\t" +- "lxvd2x 43, %7, %2 \n\t" +- "lxvd2x 44, %8, %2 \n\t" +- "lxvd2x 45, %9, %2 \n\t" +- "lxvd2x 46, %10, %2 \n\t" +- "lxvd2x 47, %11, %2 \n\t" +- +- "addi %2, %2, 128 \n\t" +- +- "lxvd2x 50, 0, %2 \n\t" +- "lxvd2x 51, %5, %2 \n\t" +- "lxvd2x 52, %6, %2 \n\t" +- "lxvd2x 53, %7, %2 \n\t" +- "lxvd2x 54, %8, %2 \n\t" +- "lxvd2x 55, %9, %2 \n\t" +- "lxvd2x 56, %10, %2 \n\t" +- "lxvd2x 57, %11, %2 \n\t" +- +- "addi %2, %2, 128 \n\t" +- +- "addic. %0 , %0 , -32 \n\t" +- "ble 2f \n\t" +- +- ".align 5 \n\t" +- "1: \n\t" +- +- "stxvd2x 40, 0, %1 \n\t" +- "stxvd2x 41, %5, %1 \n\t" +- "lxvd2x 40, 0, %2 \n\t" +- "lxvd2x 41, %5, %2 \n\t" +- "stxvd2x 42, %6, %1 \n\t" +- "stxvd2x 43, %7, %1 \n\t" +- "lxvd2x 42, %6, %2 \n\t" +- "lxvd2x 43, %7, %2 \n\t" +- "stxvd2x 44, %8, %1 \n\t" +- "stxvd2x 45, %9, %1 \n\t" +- "lxvd2x 44, %8, %2 \n\t" +- "lxvd2x 45, %9, %2 \n\t" +- "stxvd2x 46, %10, %1 \n\t" +- "stxvd2x 47, %11, %1 \n\t" +- "lxvd2x 46, %10, %2 \n\t" +- "lxvd2x 47, %11, %2 \n\t" +- +- +- "addi %1, %1, 128 \n\t" +- "addi %2, %2, 128 \n\t" +- +- "stxvd2x 50, 0, %1 \n\t" +- "stxvd2x 51, %5, %1 \n\t" +- "lxvd2x 50, 0, %2 \n\t" +- "lxvd2x 51, %5, %2 \n\t" +- "stxvd2x 52, %6, %1 \n\t" +- "stxvd2x 53, %7, %1 \n\t" +- "lxvd2x 52, %6, %2 \n\t" +- "lxvd2x 53, %7, %2 \n\t" +- "stxvd2x 54, %8, %1 \n\t" +- "stxvd2x 55, %9, %1 \n\t" +- "lxvd2x 54, %8, %2 \n\t" +- "lxvd2x 55, %9, %2 \n\t" +- "stxvd2x 56, %10, %1 \n\t" +- "stxvd2x 57, %11, %1 \n\t" +- "lxvd2x 56, %10, %2 \n\t" +- "lxvd2x 57, %11, %2 \n\t" +- +- "addi %1, %1, 128 \n\t" +- "addi %2, %2, 128 \n\t" +- +- "addic. %0 , %0 , -32 \n\t" +- "bgt 1b \n\t" +- +- "2: \n\t" +- +- "stxvd2x 40, 0, %1 \n\t" +- "stxvd2x 41, %5, %1 \n\t" +- "stxvd2x 42, %6, %1 \n\t" +- "stxvd2x 43, %7, %1 \n\t" +- "stxvd2x 44, %8, %1 \n\t" +- "stxvd2x 45, %9, %1 \n\t" +- "stxvd2x 46, %10, %1 \n\t" +- "stxvd2x 47, %11, %1 \n\t" +- +- "addi %1, %1, 128 \n\t" +- +- "stxvd2x 50, 0, %1 \n\t" +- "stxvd2x 51, %5, %1 \n\t" +- "stxvd2x 52, %6, %1 \n\t" +- "stxvd2x 53, %7, %1 \n\t" +- "stxvd2x 54, %8, %1 \n\t" +- "stxvd2x 55, %9, %1 \n\t" +- "stxvd2x 56, %10, %1 \n\t" +- "stxvd2x 57, %11, %1 \n\t" +- +- +- : +- : +- "r" (i), // 0 +- "r" (y1), // 1 +- "r" (x1), // 2 +- "r" (alpha), // 3 +- "r" (pre), // 4 +- "r" (o16), // 5 +- "r" (o32), // 6 +- "r" (o48), // 7 +- "r" (o64), // 8 +- "r" (o80), // 9 +- "r" (o96), // 10 +- "r" (o112) // 11 +- : "cr0", "%0", "%2" , "%1", "memory" +- ); +- +-} +- +- ++ __asm__ ++ ( ++ "lxvd2x 32, 0, %2 \n\t" ++ "lxvd2x 33, %5, %2 \n\t" ++ "lxvd2x 34, %6, %2 \n\t" ++ "lxvd2x 35, %7, %2 \n\t" ++ "lxvd2x 36, %8, %2 \n\t" ++ "lxvd2x 37, %9, %2 \n\t" ++ "lxvd2x 38, %10, %2 \n\t" ++ "lxvd2x 39, %11, %2 \n\t" ++ ++ "addi %2, %2, 128 \n\t" ++ ++ "lxvd2x 40, 0, %2 \n\t" ++ "lxvd2x 41, %5, %2 \n\t" ++ "lxvd2x 42, %6, %2 \n\t" ++ "lxvd2x 43, %7, %2 \n\t" ++ "lxvd2x 44, %8, %2 \n\t" ++ "lxvd2x 45, %9, %2 \n\t" ++ "lxvd2x 46, %10, %2 \n\t" ++ "lxvd2x 47, %11, %2 \n\t" ++ ++ "addi %2, %2, 128 \n\t" ++ ++ "addic. %1, %1, -32 \n\t" ++ "ble 2f \n\t" ++ ++ ".p2align 5 \n" ++ "1: \n\t" ++ ++ "stxvd2x 32, 0, %3 \n\t" ++ "stxvd2x 33, %5, %3 \n\t" ++ "lxvd2x 32, 0, %2 \n\t" ++ "lxvd2x 33, %5, %2 \n\t" ++ "stxvd2x 34, %6, %3 \n\t" ++ "stxvd2x 35, %7, %3 \n\t" ++ "lxvd2x 34, %6, %2 \n\t" ++ "lxvd2x 35, %7, %2 \n\t" ++ "stxvd2x 36, %8, %3 \n\t" ++ "stxvd2x 37, %9, %3 \n\t" ++ "lxvd2x 36, %8, %2 \n\t" ++ "lxvd2x 37, %9, %2 \n\t" ++ "stxvd2x 38, %10, %3 \n\t" ++ "stxvd2x 39, %11, %3 \n\t" ++ "lxvd2x 38, %10, %2 \n\t" ++ "lxvd2x 39, %11, %2 \n\t" ++ ++ "addi %3, %3, 128 \n\t" ++ "addi %2, %2, 128 \n\t" ++ ++ "stxvd2x 40, 0, %3 \n\t" ++ "stxvd2x 41, %5, %3 \n\t" ++ "lxvd2x 40, 0, %2 \n\t" ++ "lxvd2x 41, %5, %2 \n\t" ++ "stxvd2x 42, %6, %3 \n\t" ++ "stxvd2x 43, %7, %3 \n\t" ++ "lxvd2x 42, %6, %2 \n\t" ++ "lxvd2x 43, %7, %2 \n\t" ++ "stxvd2x 44, %8, %3 \n\t" ++ "stxvd2x 45, %9, %3 \n\t" ++ "lxvd2x 44, %8, %2 \n\t" ++ "lxvd2x 45, %9, %2 \n\t" ++ "stxvd2x 46, %10, %3 \n\t" ++ "stxvd2x 47, %11, %3 \n\t" ++ "lxvd2x 46, %10, %2 \n\t" ++ "lxvd2x 47, %11, %2 \n\t" ++ ++ "addi %3, %3, 128 \n\t" ++ "addi %2, %2, 128 \n\t" ++ ++ "addic. %1, %1, -32 \n\t" ++ "bgt 1b \n" ++ ++ "2: \n\t" ++ ++ "stxvd2x 32, 0, %3 \n\t" ++ "stxvd2x 33, %5, %3 \n\t" ++ "stxvd2x 34, %6, %3 \n\t" ++ "stxvd2x 35, %7, %3 \n\t" ++ "stxvd2x 36, %8, %3 \n\t" ++ "stxvd2x 37, %9, %3 \n\t" ++ "stxvd2x 38, %10, %3 \n\t" ++ "stxvd2x 39, %11, %3 \n\t" ++ ++ "addi %3, %3, 128 \n\t" ++ ++ "stxvd2x 40, 0, %3 \n\t" ++ "stxvd2x 41, %5, %3 \n\t" ++ "stxvd2x 42, %6, %3 \n\t" ++ "stxvd2x 43, %7, %3 \n\t" ++ "stxvd2x 44, %8, %3 \n\t" ++ "stxvd2x 45, %9, %3 \n\t" ++ "stxvd2x 46, %10, %3 \n\t" ++ "stxvd2x 47, %11, %3 \n" ++ ++ "#n=%1 x=%4=%2 y=%0=%3 o16=%5 o32=%6 o48=%7 o64=%8 o80=%9 o96=%10 o112=%11" ++ : ++ "=m" (*y), ++ "+r" (n), // 1 ++ "+b" (x), // 2 ++ "+b" (y) // 3 ++ : ++ "m" (*x), ++ "b" (16), // 5 ++ "b" (32), // 6 ++ "b" (48), // 7 ++ "b" (64), // 8 ++ "b" (80), // 9 ++ "b" (96), // 10 ++ "b" (112) // 11 ++ : ++ "cr0", ++ "vs32","vs33","vs34","vs35","vs36","vs37","vs38","vs39", ++ "vs40","vs41","vs42","vs43","vs44","vs45","vs46","vs47" ++ ); ++} +diff --git a/kernel/power/ddot.c b/kernel/power/ddot.c +index cef60a2..e43470e 100644 +--- a/kernel/power/ddot.c ++++ b/kernel/power/ddot.c +@@ -43,7 +43,7 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + #ifndef HAVE_KERNEL_8 + +-static void ddot_kernel_8(BLASLONG n, FLOAT *x, FLOAT *y, FLOAT *d) ++static FLOAT ddot_kernel_8 (BLASLONG n, FLOAT *x, FLOAT *y) + { + BLASLONG register i = 0; + FLOAT dot = 0.0; +@@ -62,8 +62,7 @@ static void ddot_kernel_8(BLASLONG n, FLOAT *x, FLOAT *y, FLOAT *d) + i+=8 ; + + } +- *d += dot; +- ++ return dot; + } + + #endif +@@ -83,7 +82,7 @@ FLOAT CNAME(BLASLONG n, FLOAT *x, BLASLONG inc_x, FLOAT *y, BLASLONG inc_y) + BLASLONG n1 = n & -16; + + if ( n1 ) +- ddot_kernel_8(n1, x, y , &dot ); ++ dot = ddot_kernel_8(n1, x, y); + + i = n1; + while(i < n) +diff --git a/kernel/power/ddot_microk_power8.c b/kernel/power/ddot_microk_power8.c +index b880492..4e6bc29 100644 +--- a/kernel/power/ddot_microk_power8.c ++++ b/kernel/power/ddot_microk_power8.c +@@ -34,145 +34,138 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + **************************************************************************************/ + + #define HAVE_KERNEL_8 1 +-static void ddot_kernel_8( BLASLONG n, FLOAT *x, FLOAT *y , FLOAT *dot) __attribute__ ((noinline)); + +-static void ddot_kernel_8( BLASLONG n, FLOAT *x, FLOAT *y, FLOAT *dot) ++static double ddot_kernel_8 (long n, double *x, double *y) + { +- +- +- BLASLONG i = n; +- BLASLONG o16 = 16; +- BLASLONG o32 = 32; +- BLASLONG o48 = 48; +- BLASLONG o64 = 64; +- BLASLONG o80 = 80; +- BLASLONG o96 = 96; +- BLASLONG o112 = 112; +- FLOAT *x1=x; +- FLOAT *y1=y; +- BLASLONG pre = 384; +- +- __asm__ __volatile__ +- ( +- "xxlxor 32,32,32 \n\t" +- "xxlxor 33,33,33 \n\t" +- "xxlxor 34,34,34 \n\t" +- "xxlxor 35,35,35 \n\t" +- "xxlxor 36,36,36 \n\t" +- "xxlxor 37,37,37 \n\t" +- "xxlxor 38,38,38 \n\t" +- "xxlxor 39,39,39 \n\t" +- +- "dcbt %2, %12 \n\t" +- "dcbt %3, %12 \n\t" +- +- "lxvd2x 40, 0, %2 \n\t" +- "lxvd2x 48, 0, %3 \n\t" +- "lxvd2x 41, %5, %2 \n\t" +- "lxvd2x 49, %5, %3 \n\t" +- "lxvd2x 42, %6, %2 \n\t" +- "lxvd2x 50, %6, %3 \n\t" +- "lxvd2x 43, %7, %2 \n\t" +- "lxvd2x 51, %7, %3 \n\t" +- "lxvd2x 44, %8, %2 \n\t" +- "lxvd2x 52, %8, %3 \n\t" +- "lxvd2x 45, %9, %2 \n\t" +- "lxvd2x 53, %9, %3 \n\t" +- "lxvd2x 46, %10, %2 \n\t" +- "lxvd2x 54, %10, %3 \n\t" +- "lxvd2x 47, %11, %2 \n\t" +- "lxvd2x 55, %11, %3 \n\t" +- +- "addi %2, %2, 128 \n\t" +- "addi %3, %3, 128 \n\t" +- +- "addic. %0 , %0 , -16 \n\t" +- "ble 2f \n\t" +- +- ".align 5 \n\t" +- "1: \n\t" +- +- "dcbt %2, %12 \n\t" +- "dcbt %3, %12 \n\t" +- +- "xvmaddadp 32, 40, 48 \n\t" +- "lxvd2x 40, 0, %2 \n\t" +- "lxvd2x 48, 0, %3 \n\t" +- "xvmaddadp 33, 41, 49 \n\t" +- "lxvd2x 41, %5, %2 \n\t" +- "lxvd2x 49, %5, %3 \n\t" +- "xvmaddadp 34, 42, 50 \n\t" +- "lxvd2x 42, %6, %2 \n\t" +- "lxvd2x 50, %6, %3 \n\t" +- "xvmaddadp 35, 43, 51 \n\t" +- "lxvd2x 43, %7, %2 \n\t" +- "lxvd2x 51, %7, %3 \n\t" +- "xvmaddadp 36, 44, 52 \n\t" +- "lxvd2x 44, %8, %2 \n\t" +- "lxvd2x 52, %8, %3 \n\t" +- "xvmaddadp 37, 45, 53 \n\t" +- "lxvd2x 45, %9, %2 \n\t" +- "lxvd2x 53, %9, %3 \n\t" +- "xvmaddadp 38, 46, 54 \n\t" +- "lxvd2x 46, %10, %2 \n\t" +- "lxvd2x 54, %10, %3 \n\t" +- "xvmaddadp 39, 47, 55 \n\t" +- +- "lxvd2x 47, %11, %2 \n\t" +- "lxvd2x 55, %11, %3 \n\t" +- +- +- "addi %2, %2, 128 \n\t" +- "addi %3, %3, 128 \n\t" +- +- "addic. %0 , %0 , -16 \n\t" +- "bgt 1b \n\t" +- +- "2: \n\t" +- +- "xvmaddadp 32, 40, 48 \n\t" +- "xvmaddadp 33, 41, 49 \n\t" +- "xvmaddadp 34, 42, 50 \n\t" +- "xvmaddadp 35, 43, 51 \n\t" +- "xvmaddadp 36, 44, 52 \n\t" +- "xvmaddadp 37, 45, 53 \n\t" +- "xvmaddadp 38, 46, 54 \n\t" +- "xvmaddadp 39, 47, 55 \n\t" +- +- "xvadddp 32, 32, 33 \n\t" +- "xvadddp 34, 34, 35 \n\t" +- "xvadddp 36, 36, 37 \n\t" +- "xvadddp 38, 38, 39 \n\t" +- +- "xvadddp 32, 32, 34 \n\t" +- "xvadddp 36, 36, 38 \n\t" +- +- "xvadddp 32, 32, 36 \n\t" +- +- "xxswapd 33, 32 \n\t" +- +- "xsadddp 32, 32, 33 \n\t" +- +- "stxsdx 32, 0, %4 \n\t" +- +- : +- : +- "r" (i), // 0 +- "r" (n), // 1 +- "r" (x1), // 2 +- "r" (y1), // 3 +- "r" (dot), // 4 +- "r" (o16), // 5 +- "r" (o32), // 6 +- "r" (o48), // 7 +- "r" (o64), // 8 +- "r" (o80), // 9 +- "r" (o96), // 10 +- "r" (o112), // 11 +- "r" (pre) // 12 +- : "cr0", "%0", "%2" , "%3", "memory" +- ); +- +-} +- +- ++ double dot; ++ __vector double t0; ++ __vector double t1; ++ __vector double t2; ++ __vector double t3; ++ ++ __asm__ ++ ( ++ "dcbt 0, %2 \n\t" ++ "dcbt 0, %3 \n\t" ++ ++ "xxlxor 32, 32, 32 \n\t" ++ "xxlxor 33, 33, 33 \n\t" ++ "xxlxor 34, 34, 34 \n\t" ++ "xxlxor 35, 35, 35 \n\t" ++ "xxlxor 36, 36, 36 \n\t" ++ "xxlxor 37, 37, 37 \n\t" ++ "xxlxor 38, 38, 38 \n\t" ++ "xxlxor 39, 39, 39 \n\t" ++ ++ "lxvd2x 40, 0, %2 \n\t" ++ "lxvd2x 48, 0, %3 \n\t" ++ "lxvd2x 41, %10, %2 \n\t" ++ "lxvd2x 49, %10, %3 \n\t" ++ "lxvd2x 42, %11, %2 \n\t" ++ "lxvd2x 50, %11, %3 \n\t" ++ "lxvd2x 43, %12, %2 \n\t" ++ "lxvd2x 51, %12, %3 \n\t" ++ "lxvd2x 44, %13, %2 \n\t" ++ "lxvd2x %x4, %13, %3 \n\t" ++ "lxvd2x 45, %14, %2 \n\t" ++ "lxvd2x %x5, %14, %3 \n\t" ++ "lxvd2x 46, %15, %2 \n\t" ++ "lxvd2x %x6, %15, %3 \n\t" ++ "lxvd2x 47, %16, %2 \n\t" ++ "lxvd2x %x7, %16, %3 \n\t" ++ ++ "addi %2, %2, 128 \n\t" ++ "addi %3, %3, 128 \n\t" ++ ++ "addic. %1, %1, -16 \n\t" ++ "ble 2f \n\t" ++ ++ ".p2align 5 \n" ++ "1: \n\t" ++ ++ "xvmaddadp 32, 40, 48 \n\t" ++ "lxvd2x 40, 0, %2 \n\t" ++ "lxvd2x 48, 0, %3 \n\t" ++ "xvmaddadp 33, 41, 49 \n\t" ++ "lxvd2x 41, %10, %2 \n\t" ++ "lxvd2x 49, %10, %3 \n\t" ++ "xvmaddadp 34, 42, 50 \n\t" ++ "lxvd2x 42, %11, %2 \n\t" ++ "lxvd2x 50, %11, %3 \n\t" ++ "xvmaddadp 35, 43, 51 \n\t" ++ "lxvd2x 43, %12, %2 \n\t" ++ "lxvd2x 51, %12, %3 \n\t" ++ "xvmaddadp 36, 44, %x4 \n\t" ++ "lxvd2x 44, %13, %2 \n\t" ++ "lxvd2x %x4, %13, %3 \n\t" ++ "xvmaddadp 37, 45, %x5 \n\t" ++ "lxvd2x 45, %14, %2 \n\t" ++ "lxvd2x %x5, %14, %3 \n\t" ++ "xvmaddadp 38, 46, %x6 \n\t" ++ "lxvd2x 46, %15, %2 \n\t" ++ "lxvd2x %x6, %15, %3 \n\t" ++ "xvmaddadp 39, 47, %x7 \n\t" ++ "lxvd2x 47, %16, %2 \n\t" ++ "lxvd2x %x7, %16, %3 \n\t" ++ ++ "addi %2, %2, 128 \n\t" ++ "addi %3, %3, 128 \n\t" ++ ++ "addic. %1, %1, -16 \n\t" ++ "bgt 1b \n" ++ ++ "2: \n\t" ++ ++ "xvmaddadp 32, 40, 48 \n\t" ++ "xvmaddadp 33, 41, 49 \n\t" ++ "xvmaddadp 34, 42, 50 \n\t" ++ "xvmaddadp 35, 43, 51 \n\t" ++ "xvmaddadp 36, 44, %x4 \n\t" ++ "xvmaddadp 37, 45, %x5 \n\t" ++ "xvmaddadp 38, 46, %x6 \n\t" ++ "xvmaddadp 39, 47, %x7 \n\t" ++ ++ "xvadddp 32, 32, 33 \n\t" ++ "xvadddp 34, 34, 35 \n\t" ++ "xvadddp 36, 36, 37 \n\t" ++ "xvadddp 38, 38, 39 \n\t" ++ ++ "xvadddp 32, 32, 34 \n\t" ++ "xvadddp 36, 36, 38 \n\t" ++ ++ "xvadddp 32, 32, 36 \n\t" ++ ++ "xxswapd 33, 32 \n\t" ++ ++ "xsadddp %x0, 32, 33 \n" ++ ++ "#dot=%0 n=%1 x=%8=%2 y=%9=%3 o16=%10 o32=%11 o48=%12 o64=%13 o80=%14 o96=%15 o122=%16\n" ++ "#t0=%x4 t1=%x5 t2=%x6 t3=%x7" ++ : ++ "=d" (dot), // 0 ++ "+r" (n), // 1 ++ "+b" (x), // 2 ++ "+b" (y), // 3 ++ "=wa" (t0), // 4 ++ "=wa" (t1), // 5 ++ "=wa" (t2), // 6 ++ "=wa" (t3) // 7 ++ : ++ "m" (*x), ++ "m" (*y), ++ "b" (16), // 10 ++ "b" (32), // 11 ++ "b" (48), // 12 ++ "b" (64), // 13 ++ "b" (80), // 14 ++ "b" (96), // 15 ++ "b" (112) // 16 ++ : ++ "cr0", ++ "vs32","vs33","vs34","vs35","vs36","vs37","vs38","vs39", ++ "vs40","vs41","vs42","vs43","vs44","vs45","vs46","vs47", ++ "vs48","vs49","vs50","vs51" ++ ); ++ ++ return dot; ++} +diff --git a/kernel/power/dgemv_n.c b/kernel/power/dgemv_n.c +index 812d09d..57f9f9e 100644 +--- a/kernel/power/dgemv_n.c ++++ b/kernel/power/dgemv_n.c +@@ -47,18 +47,18 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + #ifndef HAVE_KERNEL_4x4 + +-static void dgemv_kernel_4x4(BLASLONG n, FLOAT **ap, FLOAT *xo, FLOAT *y, FLOAT *alpha) ++static void dgemv_kernel_4x4(BLASLONG n, FLOAT *a_ptr, BLASLONG lda, FLOAT *xo, FLOAT *y, FLOAT alpha) + { + BLASLONG i; +- FLOAT *a0,*a1,*a2,*a3; + FLOAT x[4] __attribute__ ((aligned (16)));; +- a0 = ap[0]; +- a1 = ap[1]; +- a2 = ap[2]; +- a3 = ap[3]; ++ FLOAT *a0 = a_ptr; ++ FLOAT *a1 = a0 + lda; ++ FLOAT *a2 = a1 + lda; ++ FLOAT *a3 = a2 + lda; ++ + + for ( i=0; i<4; i++) +- x[i] = xo[i] * *alpha; ++ x[i] = xo[i] * alpha; + + for ( i=0; i< n; i+=4 ) + { +@@ -73,16 +73,13 @@ static void dgemv_kernel_4x4(BLASLONG n, FLOAT **ap, FLOAT *xo, FLOAT *y, FLOAT + + #ifndef HAVE_KERNEL_4x2 + +-static void dgemv_kernel_4x2(BLASLONG n, FLOAT **ap, FLOAT *xo, FLOAT *y, FLOAT *alpha) ++static void dgemv_kernel_4x2(BLASLONG n, FLOAT *a0, FLOAT *a1, FLOAT *xo, FLOAT *y, FLOAT alpha) + { + BLASLONG i; +- FLOAT *a0,*a1; + FLOAT x[4] __attribute__ ((aligned (16)));; +- a0 = ap[0]; +- a1 = ap[1]; + + for ( i=0; i<2; i++) +- x[i] = xo[i] * *alpha; ++ x[i] = xo[i] * alpha; + + for ( i=0; i< n; i+=4 ) + { +@@ -98,15 +95,13 @@ static void dgemv_kernel_4x2(BLASLONG n, FLOAT **ap, FLOAT *xo, FLOAT *y, FLOAT + + #ifndef HAVE_KERNEL_4x1 + +-static void dgemv_kernel_4x1(BLASLONG n, FLOAT *ap, FLOAT *xo, FLOAT *y, FLOAT *alpha) ++static void dgemv_kernel_4x1(BLASLONG n, FLOAT *a0, FLOAT *xo, FLOAT *y, FLOAT alpha) + { + BLASLONG i; +- FLOAT *a0; + FLOAT x[4] __attribute__ ((aligned (16)));; +- a0 = ap; + + for ( i=0; i<1; i++) +- x[i] = xo[i] * *alpha; ++ x[i] = xo[i] * alpha; + + for ( i=0; i< n; i+=4 ) + { +@@ -141,7 +136,6 @@ int CNAME(BLASLONG m, BLASLONG n, BLASLONG dummy1, FLOAT alpha, FLOAT *a, BLASLO + { + + BLASLONG i; +- BLASLONG j; + FLOAT *a_ptr; + FLOAT *x_ptr; + FLOAT *y_ptr; +@@ -151,13 +145,9 @@ int CNAME(BLASLONG m, BLASLONG n, BLASLONG dummy1, FLOAT alpha, FLOAT *a, BLASLO + BLASLONG m3; + BLASLONG n2; + BLASLONG lda4 = lda << 2; +- FLOAT *ap[4] __attribute__ ((aligned (16)));; + FLOAT xbuffer[8] __attribute__ ((aligned (16)));; +- FLOAT alpha_r[4] __attribute__ ((aligned (16)));; + FLOAT *ybuffer; + +- alpha_r[0] = alpha; +- + if ( m < 1 ) return(0); + if ( n < 1 ) return(0); + +@@ -187,11 +177,6 @@ int CNAME(BLASLONG m, BLASLONG n, BLASLONG dummy1, FLOAT alpha, FLOAT *a, BLASLO + a_ptr = a; + x_ptr = x; + +- ap[0] = a_ptr; +- ap[1] = a_ptr + lda; +- ap[2] = ap[1] + lda; +- ap[3] = ap[2] + lda; +- + if ( inc_y != 1 ) + memset(ybuffer,0,NB*8); + else +@@ -203,18 +188,14 @@ int CNAME(BLASLONG m, BLASLONG n, BLASLONG dummy1, FLOAT alpha, FLOAT *a, BLASLO + + for( i = 0; i < n1 ; i++) + { +- dgemv_kernel_4x4(NB,ap,x_ptr,ybuffer,alpha_r); +- ap[0] += lda4; +- ap[1] += lda4; +- ap[2] += lda4; +- ap[3] += lda4; ++ dgemv_kernel_4x4(NB,a_ptr,lda,x_ptr,ybuffer,alpha); + a_ptr += lda4; + x_ptr += 4; + } + + if ( n2 & 2 ) + { +- dgemv_kernel_4x2(NB,ap,x_ptr,ybuffer,alpha_r); ++ dgemv_kernel_4x2(NB,a_ptr,a_ptr+lda,x_ptr,ybuffer,alpha); + a_ptr += lda*2; + x_ptr += 2; + } +@@ -222,7 +203,7 @@ int CNAME(BLASLONG m, BLASLONG n, BLASLONG dummy1, FLOAT alpha, FLOAT *a, BLASLO + + if ( n2 & 1 ) + { +- dgemv_kernel_4x1(NB,a_ptr,x_ptr,ybuffer,alpha_r); ++ dgemv_kernel_4x1(NB,a_ptr,x_ptr,ybuffer,alpha); + a_ptr += lda; + x_ptr += 1; + +@@ -243,11 +224,7 @@ int CNAME(BLASLONG m, BLASLONG n, BLASLONG dummy1, FLOAT alpha, FLOAT *a, BLASLO + x_ptr += inc_x; + xbuffer[3] = x_ptr[0]; + x_ptr += inc_x; +- dgemv_kernel_4x4(NB,ap,xbuffer,ybuffer,alpha_r); +- ap[0] += lda4; +- ap[1] += lda4; +- ap[2] += lda4; +- ap[3] += lda4; ++ dgemv_kernel_4x4(NB,a_ptr,lda,xbuffer,ybuffer,alpha); + a_ptr += lda4; + } + +@@ -255,7 +232,7 @@ int CNAME(BLASLONG m, BLASLONG n, BLASLONG dummy1, FLOAT alpha, FLOAT *a, BLASLO + { + xbuffer[0] = x_ptr[0]; + x_ptr += inc_x; +- dgemv_kernel_4x1(NB,a_ptr,xbuffer,ybuffer,alpha_r); ++ dgemv_kernel_4x1(NB,a_ptr,xbuffer,ybuffer,alpha); + a_ptr += lda; + + } +diff --git a/kernel/power/dgemv_n_microk_power8.c b/kernel/power/dgemv_n_microk_power8.c +index 9eabe55..5b42bbb 100644 +--- a/kernel/power/dgemv_n_microk_power8.c ++++ b/kernel/power/dgemv_n_microk_power8.c +@@ -35,267 +35,264 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + #define HAVE_KERNEL_4x4 1 + +-static void dgemv_kernel_4x4(BLASLONG n, FLOAT **ap, FLOAT *xo, FLOAT *y, FLOAT *alpha) __attribute__ ((noinline)); +- +-static void dgemv_kernel_4x4(BLASLONG n, FLOAT **ap, FLOAT *xo, FLOAT *y, FLOAT *alpha) ++static void dgemv_kernel_4x4 (long n, double *ap, long lda, double *x, double *y, double alpha) + { +- BLASLONG i=n; +- BLASLONG o8 = 8; +- BLASLONG o16 = 16; +- BLASLONG o24 = 24; +- BLASLONG pre = 384; +- +- FLOAT *a0,*a1,*a2,*a3; +- FLOAT *y1=y+1; +- FLOAT x[4] __attribute__ ((aligned (16)));; +- a0 = ap[0]+1; +- a1 = ap[1]+1; +- a2 = ap[2]+1; +- a3 = ap[3]+1; +- +- x[0]=xo[0] * *alpha; +- x[1]=xo[1] * *alpha; +- x[2]=xo[2] * *alpha; +- x[3]=xo[3] * *alpha; ++ double *a0; ++ double *a1; ++ double *a2; ++ double *a3; ++ ++ __asm__ ++ ( ++ "lxvd2x 34, 0, %9 \n\t" // x0, x1 ++ "lxvd2x 35, %10, %9 \n\t" // x2, x3 ++ "xxspltd 32, %x8, 0 \n\t" // alpha, alpha ++ ++ "sldi %6, %4, 3 \n\t" // lda * sizeof (double) ++ ++ "xvmuldp 34, 34, 32 \n\t" // x0 * alpha, x1 * alpha ++ "xvmuldp 35, 35, 32 \n\t" // x2 * alpha, x3 * alpha ++ ++ "add %4, %3, %6 \n\t" // a1 = a0 + lda ++ "add %6, %6, %6 \n\t" // 2 * lda ++ ++ "xxspltd 32, 34, 0 \n\t" // x0 * alpha, x0 * alpha ++ "xxspltd 33, 34, 1 \n\t" // x1 * alpha, x1 * alpha ++ "xxspltd 34, 35, 0 \n\t" // x2 * alpha, x2 * alpha ++ "xxspltd 35, 35, 1 \n\t" // x3 * alpha, x3 * alpha ++ ++ "add %5, %3, %6 \n\t" // a2 = a0 + 2 * lda ++ "add %6, %4, %6 \n\t" // a3 = a1 + 2 * lda ++ ++ "dcbt 0, %3 \n\t" ++ "dcbt 0, %4 \n\t" ++ "dcbt 0, %5 \n\t" ++ "dcbt 0, %6 \n\t" + ++ "lxvd2x 40, 0, %3 \n\t" // a0[0], a0[1] ++ "lxvd2x 41, %10, %3 \n\t" // a0[2], a0[3] + +- __asm__ __volatile__ +- ( +- "lxvdsx 32, 0 , %1 \n\t" // x0 +- "lxvdsx 33,%3 , %1 \n\t" // x1 +- "lxvdsx 34,%4 , %1 \n\t" // x2 +- "lxvdsx 35,%5 , %1 \n\t" // x3 +- "addi %2 , %2 , -8 \n\t" +- "addi %6 , %6 , -8 \n\t" +- "addi %7 , %7 , -8 \n\t" +- "addi %8 , %8 , -8 \n\t" +- "addi %9 , %9 , -8 \n\t" +- +- "lxvd2x 48, 0, %6 \n\t" // a0[0], a0[1] +- "lxvd2x 49,%4, %6 \n\t" // a0[2], a0[3] +- +- "lxvd2x 50, 0, %7 \n\t" // a1[0], a1[1] +- "lxvd2x 51,%4, %7 \n\t" // a1[2], a1[3] ++ "lxvd2x 42, 0, %4 \n\t" // a1[0], a1[1] ++ "lxvd2x 43, %10, %4 \n\t" // a1[2], a1[3] + +- "lxvd2x 52, 0, %8 \n\t" // a2[0], a2[1] +- "lxvd2x 53,%4, %8 \n\t" // a2[2], a2[3] ++ "lxvd2x 44, 0, %5 \n\t" // a2[0], a2[1] ++ "lxvd2x 45, %10, %5 \n\t" // a2[2], a2[3] + +- "lxvd2x 54, 0, %9 \n\t" // a3[0], a3[1] +- "lxvd2x 55,%4, %9 \n\t" // a3[2], a3[3] ++ "lxvd2x 46, 0, %6 \n\t" // a3[0], a3[1] ++ "lxvd2x 47, %10, %6 \n\t" // a3[2], a3[3] + +- "addi %6, %6, 32 \n\t" +- "addi %7, %7, 32 \n\t" +- "addi %8, %8, 32 \n\t" +- "addi %9, %9, 32 \n\t" ++ "dcbt 0, %2 \n\t" + +- "addic. %0 , %0 , -4 \n\t" +- "ble 2f \n\t" ++ "addi %3, %3, 32 \n\t" ++ "addi %4, %4, 32 \n\t" ++ "addi %5, %5, 32 \n\t" ++ "addi %6, %6, 32 \n\t" + +- ".align 5 \n\t" +- "1: \n\t" ++ "addic. %1, %1, -4 \n\t" ++ "ble 2f \n\t" + +- "dcbt %2, %10 \n\t" ++ ".p2align 5 \n" ++ "1: \n\t" + +- "lxvd2x 40, 0, %2 \n\t" // y0, y1 +- "lxvd2x 41,%4, %2 \n\t" // y2, y3 +- +- "dcbt %6, %10 \n\t" +- "dcbt %7, %10 \n\t" +- "dcbt %8, %10 \n\t" +- "dcbt %9, %10 \n\t" ++ "lxvd2x 36, 0, %2 \n\t" // y0, y1 ++ "lxvd2x 37, %10, %2 \n\t" // y2, y3 + +- "xvmaddadp 40, 48, 32 \n\t" +- "xvmaddadp 41, 49, 32 \n\t" ++ "xvmaddadp 36, 40, 32 \n\t" ++ "xvmaddadp 37, 41, 32 \n\t" + +- "lxvd2x 48, 0, %6 \n\t" // a0[0], a0[1] +- "lxvd2x 49,%4, %6 \n\t" // a0[2], a0[3] ++ "lxvd2x 40, 0, %3 \n\t" // a0[0], a0[1] ++ "lxvd2x 41, %10, %3 \n\t" // a0[2], a0[3] + +- "xvmaddadp 40, 50, 33 \n\t" +- "addi %6, %6, 32 \n\t" +- "xvmaddadp 41, 51, 33 \n\t" ++ "xvmaddadp 36, 42, 33 \n\t" ++ "addi %3, %3, 32 \n\t" ++ "xvmaddadp 37, 43, 33 \n\t" + +- "lxvd2x 50, 0, %7 \n\t" // a1[0], a1[1] +- "lxvd2x 51,%4, %7 \n\t" // a1[2], a1[3] ++ "lxvd2x 42, 0, %4 \n\t" // a1[0], a1[1] ++ "lxvd2x 43, %10, %4 \n\t" // a1[2], a1[3] + +- "xvmaddadp 40, 52, 34 \n\t" +- "addi %7, %7, 32 \n\t" +- "xvmaddadp 41, 53, 34 \n\t" ++ "xvmaddadp 36, 44, 34 \n\t" ++ "addi %4, %4, 32 \n\t" ++ "xvmaddadp 37, 45, 34 \n\t" + +- "lxvd2x 52, 0, %8 \n\t" // a2[0], a2[1] +- "lxvd2x 53,%4, %8 \n\t" // a2[2], a2[3] ++ "lxvd2x 44, 0, %5 \n\t" // a2[0], a2[1] ++ "lxvd2x 45, %10, %5 \n\t" // a2[2], a2[3] + +- "xvmaddadp 40, 54, 35 \n\t" +- "addi %8, %8, 32 \n\t" +- "xvmaddadp 41, 55, 35 \n\t" ++ "xvmaddadp 36, 46, 35 \n\t" ++ "addi %5, %5, 32 \n\t" ++ "xvmaddadp 37, 47, 35 \n\t" + +- "stxvd2x 40, 0, %2 \n\t" // y0, y1 +- "stxvd2x 41,%4, %2 \n\t" // y2, y3 ++ "stxvd2x 36, 0, %2 \n\t" // y0, y1 ++ "stxvd2x 37, %10, %2 \n\t" // y2, y3 + +- "lxvd2x 54, 0, %9 \n\t" // a3[0], a3[1] +- "lxvd2x 55,%4, %9 \n\t" // a3[2], a3[3] ++ "lxvd2x 46, 0, %6 \n\t" // a3[0], a3[1] ++ "lxvd2x 47, %10, %6 \n\t" // a3[2], a3[3] + +- "addi %9, %9, 32 \n\t" +- "addi %2, %2, 32 \n\t" ++ "addi %6, %6, 32 \n\t" ++ "addi %2, %2, 32 \n\t" + +- "addic. %0 , %0 , -4 \n\t" +- "ble 2f \n\t" ++ "addic. %1, %1, -4 \n\t" ++ "ble 2f \n\t" + + +- "lxvd2x 40, 0, %2 \n\t" // y0, y1 +- "lxvd2x 41,%4, %2 \n\t" // y2, y3 +- +- "xvmaddadp 40, 48, 32 \n\t" +- "xvmaddadp 41, 49, 32 \n\t" ++ "lxvd2x 36, 0, %2 \n\t" // y0, y1 ++ "lxvd2x 37, %10, %2 \n\t" // y2, y3 + +- "lxvd2x 48, 0, %6 \n\t" // a0[0], a0[1] +- "lxvd2x 49,%4, %6 \n\t" // a0[2], a0[3] ++ "xvmaddadp 36, 40, 32 \n\t" ++ "xvmaddadp 37, 41, 32 \n\t" + +- "xvmaddadp 40, 50, 33 \n\t" +- "addi %6, %6, 32 \n\t" +- "xvmaddadp 41, 51, 33 \n\t" ++ "lxvd2x 40, 0, %3 \n\t" // a0[0], a0[1] ++ "lxvd2x 41, %10, %3 \n\t" // a0[2], a0[3] + +- "lxvd2x 50, 0, %7 \n\t" // a1[0], a1[1] +- "lxvd2x 51,%4, %7 \n\t" // a1[2], a1[3] ++ "xvmaddadp 36, 42, 33 \n\t" ++ "addi %3, %3, 32 \n\t" ++ "xvmaddadp 37, 43, 33 \n\t" + +- "xvmaddadp 40, 52, 34 \n\t" +- "addi %7, %7, 32 \n\t" +- "xvmaddadp 41, 53, 34 \n\t" ++ "lxvd2x 42, 0, %4 \n\t" // a1[0], a1[1] ++ "lxvd2x 43, %10, %4 \n\t" // a1[2], a1[3] + +- "lxvd2x 52, 0, %8 \n\t" // a2[0], a2[1] +- "lxvd2x 53,%4, %8 \n\t" // a2[2], a2[3] ++ "xvmaddadp 36, 44, 34 \n\t" ++ "addi %4, %4, 32 \n\t" ++ "xvmaddadp 37, 45, 34 \n\t" + +- "xvmaddadp 40, 54, 35 \n\t" +- "addi %8, %8, 32 \n\t" +- "xvmaddadp 41, 55, 35 \n\t" ++ "lxvd2x 44, 0, %5 \n\t" // a2[0], a2[1] ++ "lxvd2x 45, %10, %5 \n\t" // a2[2], a2[3] + +- "stxvd2x 40, 0, %2 \n\t" // y0, y1 +- "stxvd2x 41,%4, %2 \n\t" // y2, y3 ++ "xvmaddadp 36, 46, 35 \n\t" ++ "addi %5, %5, 32 \n\t" ++ "xvmaddadp 37, 47, 35 \n\t" + +- "lxvd2x 54, 0, %9 \n\t" // a3[0], a3[1] +- "lxvd2x 55,%4, %9 \n\t" // a3[2], a3[3] ++ "stxvd2x 36, 0, %2 \n\t" // y0, y1 ++ "stxvd2x 37, %10, %2 \n\t" // y2, y3 + +- "addi %9, %9, 32 \n\t" +- "addi %2, %2, 32 \n\t" ++ "lxvd2x 46, 0, %6 \n\t" // a3[0], a3[1] ++ "lxvd2x 47, %10, %6 \n\t" // a3[2], a3[3] + +- "addic. %0 , %0 , -4 \n\t" +- "ble 2f \n\t" ++ "addi %6, %6, 32 \n\t" ++ "addi %2, %2, 32 \n\t" + ++ "addic. %1, %1, -4 \n\t" ++ "ble 2f \n\t" + +- "lxvd2x 40, 0, %2 \n\t" // y0, y1 +- "lxvd2x 41,%4, %2 \n\t" // y2, y3 +- +- "xvmaddadp 40, 48, 32 \n\t" +- "xvmaddadp 41, 49, 32 \n\t" + +- "lxvd2x 48, 0, %6 \n\t" // a0[0], a0[1] +- "lxvd2x 49,%4, %6 \n\t" // a0[2], a0[3] ++ "lxvd2x 36, 0, %2 \n\t" // y0, y1 ++ "lxvd2x 37, %10, %2 \n\t" // y2, y3 + +- "xvmaddadp 40, 50, 33 \n\t" +- "addi %6, %6, 32 \n\t" +- "xvmaddadp 41, 51, 33 \n\t" ++ "xvmaddadp 36, 40, 32 \n\t" ++ "xvmaddadp 37, 41, 32 \n\t" + +- "lxvd2x 50, 0, %7 \n\t" // a1[0], a1[1] +- "lxvd2x 51,%4, %7 \n\t" // a1[2], a1[3] ++ "lxvd2x 40, 0, %3 \n\t" // a0[0], a0[1] ++ "lxvd2x 41, %10, %3 \n\t" // a0[2], a0[3] + +- "xvmaddadp 40, 52, 34 \n\t" +- "addi %7, %7, 32 \n\t" +- "xvmaddadp 41, 53, 34 \n\t" ++ "xvmaddadp 36, 42, 33 \n\t" ++ "addi %3, %3, 32 \n\t" ++ "xvmaddadp 37, 43, 33 \n\t" + +- "lxvd2x 52, 0, %8 \n\t" // a2[0], a2[1] +- "lxvd2x 53,%4, %8 \n\t" // a2[2], a2[3] ++ "lxvd2x 42, 0, %4 \n\t" // a1[0], a1[1] ++ "lxvd2x 43, %10, %4 \n\t" // a1[2], a1[3] + +- "xvmaddadp 40, 54, 35 \n\t" +- "addi %8, %8, 32 \n\t" +- "xvmaddadp 41, 55, 35 \n\t" ++ "xvmaddadp 36, 44, 34 \n\t" ++ "addi %4, %4, 32 \n\t" ++ "xvmaddadp 37, 45, 34 \n\t" + +- "stxvd2x 40, 0, %2 \n\t" // y0, y1 +- "stxvd2x 41,%4, %2 \n\t" // y2, y3 ++ "lxvd2x 44, 0, %5 \n\t" // a2[0], a2[1] ++ "lxvd2x 45, %10, %5 \n\t" // a2[2], a2[3] + +- "lxvd2x 54, 0, %9 \n\t" // a3[0], a3[1] +- "lxvd2x 55,%4, %9 \n\t" // a3[2], a3[3] ++ "xvmaddadp 36, 46, 35 \n\t" ++ "addi %5, %5, 32 \n\t" ++ "xvmaddadp 37, 47, 35 \n\t" + +- "addi %9, %9, 32 \n\t" +- "addi %2, %2, 32 \n\t" ++ "stxvd2x 36, 0, %2 \n\t" // y0, y1 ++ "stxvd2x 37, %10, %2 \n\t" // y2, y3 + +- "addic. %0 , %0 , -4 \n\t" +- "ble 2f \n\t" ++ "lxvd2x 46, 0, %6 \n\t" // a3[0], a3[1] ++ "lxvd2x 47, %10, %6 \n\t" // a3[2], a3[3] + ++ "addi %6, %6, 32 \n\t" ++ "addi %2, %2, 32 \n\t" + +- "lxvd2x 40, 0, %2 \n\t" // y0, y1 +- "lxvd2x 41,%4, %2 \n\t" // y2, y3 +- +- "xvmaddadp 40, 48, 32 \n\t" +- "xvmaddadp 41, 49, 32 \n\t" ++ "addic. %1, %1, -4 \n\t" ++ "ble 2f \n\t" + +- "lxvd2x 48, 0, %6 \n\t" // a0[0], a0[1] +- "lxvd2x 49,%4, %6 \n\t" // a0[2], a0[3] + +- "xvmaddadp 40, 50, 33 \n\t" +- "addi %6, %6, 32 \n\t" +- "xvmaddadp 41, 51, 33 \n\t" ++ "lxvd2x 36, 0, %2 \n\t" // y0, y1 ++ "lxvd2x 37, %10, %2 \n\t" // y2, y3 + +- "lxvd2x 50, 0, %7 \n\t" // a1[0], a1[1] +- "lxvd2x 51,%4, %7 \n\t" // a1[2], a1[3] ++ "xvmaddadp 36, 40, 32 \n\t" ++ "xvmaddadp 37, 41, 32 \n\t" + +- "xvmaddadp 40, 52, 34 \n\t" +- "addi %7, %7, 32 \n\t" +- "xvmaddadp 41, 53, 34 \n\t" ++ "lxvd2x 40, 0, %3 \n\t" // a0[0], a0[1] ++ "lxvd2x 41, %10, %3 \n\t" // a0[2], a0[3] + +- "lxvd2x 52, 0, %8 \n\t" // a2[0], a2[1] +- "lxvd2x 53,%4, %8 \n\t" // a2[2], a2[3] ++ "xvmaddadp 36, 42, 33 \n\t" ++ "addi %3, %3, 32 \n\t" ++ "xvmaddadp 37, 43, 33 \n\t" + +- "xvmaddadp 40, 54, 35 \n\t" +- "addi %8, %8, 32 \n\t" +- "xvmaddadp 41, 55, 35 \n\t" ++ "lxvd2x 42, 0, %4 \n\t" // a1[0], a1[1] ++ "lxvd2x 43, %10, %4 \n\t" // a1[2], a1[3] + +- "stxvd2x 40, 0, %2 \n\t" // y0, y1 +- "stxvd2x 41,%4, %2 \n\t" // y2, y3 ++ "xvmaddadp 36, 44, 34 \n\t" ++ "addi %4, %4, 32 \n\t" ++ "xvmaddadp 37, 45, 34 \n\t" + +- "lxvd2x 54, 0, %9 \n\t" // a3[0], a3[1] +- "lxvd2x 55,%4, %9 \n\t" // a3[2], a3[3] ++ "lxvd2x 44, 0, %5 \n\t" // a2[0], a2[1] ++ "lxvd2x 45, %10, %5 \n\t" // a2[2], a2[3] + +- "addi %9, %9, 32 \n\t" +- "addi %2, %2, 32 \n\t" ++ "xvmaddadp 36, 46, 35 \n\t" ++ "addi %5, %5, 32 \n\t" ++ "xvmaddadp 37, 47, 35 \n\t" + +- "addic. %0 , %0 , -4 \n\t" +- "bgt 1b \n\t" ++ "stxvd2x 36, 0, %2 \n\t" // y0, y1 ++ "stxvd2x 37, %10, %2 \n\t" // y2, y3 + +- "2: \n\t" ++ "lxvd2x 46, 0, %6 \n\t" // a3[0], a3[1] ++ "lxvd2x 47, %10, %6 \n\t" // a3[2], a3[3] + +- "lxvd2x 40, 0, %2 \n\t" // y0, y1 +- "lxvd2x 41,%4, %2 \n\t" // y2, y3 ++ "addi %6, %6, 32 \n\t" ++ "addi %2, %2, 32 \n\t" + +- "xvmaddadp 40, 48, 32 \n\t" +- "xvmaddadp 41, 49, 32 \n\t" ++ "addic. %1, %1, -4 \n\t" ++ "bgt 1b \n" + +- "xvmaddadp 40, 50, 33 \n\t" +- "xvmaddadp 41, 51, 33 \n\t" ++ "2: \n\t" + +- "xvmaddadp 40, 52, 34 \n\t" +- "xvmaddadp 41, 53, 34 \n\t" ++ "lxvd2x 36, 0, %2 \n\t" // y0, y1 ++ "lxvd2x 37, %10, %2 \n\t" // y2, y3 + +- "xvmaddadp 40, 54, 35 \n\t" +- "xvmaddadp 41, 55, 35 \n\t" ++ "xvmaddadp 36, 40, 32 \n\t" ++ "xvmaddadp 37, 41, 32 \n\t" + +- "stxvd2x 40, 0, %2 \n\t" // y0, y1 +- "stxvd2x 41,%4, %2 \n\t" // y2, y3 ++ "xvmaddadp 36, 42, 33 \n\t" ++ "xvmaddadp 37, 43, 33 \n\t" + +- : +- : +- "r" (i), // 0 +- "r" (x), // 1 +- "r" (y1), // 2 +- "r" (o8), // 3 +- "r" (o16), // 4 +- "r" (o24), // 5 +- "r" (a0), // 6 +- "r" (a1), // 7 +- "r" (a2), // 8 +- "r" (a3), // 9 +- "r" (pre) // 10 +- : "cr0", "%0", "%2" , "%6", "%7", "%8", "%9", "memory" +- ); ++ "xvmaddadp 36, 44, 34 \n\t" ++ "xvmaddadp 37, 45, 34 \n\t" + +-} ++ "xvmaddadp 36, 46, 35 \n\t" ++ "xvmaddadp 37, 47, 35 \n\t" + ++ "stxvd2x 36, 0, %2 \n\t" // y0, y1 ++ "stxvd2x 37, %10, %2 \n" // y2, y3 + ++ "#n=%1 ap=%11 lda=%12 x=%7=%9 y=%0=%2 alpha=%8 o16=%10\n" ++ "#a0=%3 a1=%4 a2=%5 a3=%6" ++ : ++ "=m" (*y), ++ "+r" (n), // 1 ++ "+b" (y), // 2 ++ "=b" (a0), // 3 ++ "=b" (a1), // 4 ++ "=&b" (a2), // 5 ++ "=&b" (a3) // 6 ++ : ++ "m" (*x), ++ "d" (alpha), // 8 ++ "r" (x), // 9 ++ "b" (16), // 10 ++ "3" (ap), // 11 ++ "4" (lda) // 12 ++ : ++ "cr0", ++ "vs32","vs33","vs34","vs35","vs36","vs37", ++ "vs40","vs41","vs42","vs43","vs44","vs45","vs46","vs47" ++ ); ++} +diff --git a/kernel/power/drot.c b/kernel/power/drot.c +index c93f69b..3e10748 100644 +--- a/kernel/power/drot.c ++++ b/kernel/power/drot.c +@@ -46,7 +46,7 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + #ifndef HAVE_KERNEL_16 + +-static void drot_kernel_16(BLASLONG n, FLOAT *x, FLOAT *y, FLOAT *c, FLOAT *s) ++static void drot_kernel_16(BLASLONG n, FLOAT *x, FLOAT *y, FLOAT c, FLOAT s) + { + + BLASLONG i=0; +@@ -56,8 +56,6 @@ static void drot_kernel_16(BLASLONG n, FLOAT *x, FLOAT *y, FLOAT *c, FLOAT *s) + FLOAT y00, y01, y02, y03; + FLOAT *x1=x; + FLOAT *y1=y; +- FLOAT c1=*c; +- FLOAT s1=*s; + + while ( i 0 ) + { +- c1[0]=c; +- c1[1]=c; +- c1[2]=c; +- c1[3]=c; +- s1[0]=s; +- s1[1]=s; +- s1[2]=s; +- s1[3]=s; +- drot_kernel_16(n1, x1, y1, c1, s1); ++ drot_kernel_16(n1, x1, y1, c, s); + i=n1; + } + +diff --git a/kernel/power/drot_microk_power8.c b/kernel/power/drot_microk_power8.c +index 4444ac7..016b776 100644 +--- a/kernel/power/drot_microk_power8.c ++++ b/kernel/power/drot_microk_power8.c +@@ -38,174 +38,176 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + #define HAVE_KERNEL_16 1 + +-static void drot_kernel_16( BLASLONG n, FLOAT *x, FLOAT *y, FLOAT *c, FLOAT *s) __attribute__ ((noinline)); +- +-static void drot_kernel_16( BLASLONG n, FLOAT *x, FLOAT *y, FLOAT *c, FLOAT *s) ++static void drot_kernel_16 (long n, double *x, double *y, double c, double s) + { ++ __vector double t0; ++ __vector double t1; ++ __vector double t2; ++ __vector double t3; ++ __vector double t4; ++ __vector double t5; ++ __vector double t6; ++ __vector double t7; + ++ __asm__ ++ ( ++ "xxspltd 36, %x13, 0 \n\t" // load c to both dwords ++ "xxspltd 37, %x14, 0 \n\t" // load s to both dwords + +- BLASLONG i = n; +- BLASLONG o16 = 16; +- BLASLONG o32 = 32; +- BLASLONG o48 = 48; +- FLOAT *x1=x; +- FLOAT *y1=y; +- FLOAT *x2=x+1; +- FLOAT *y2=y+1; +- +- __asm__ __volatile__ +- ( +- +- "lxsdx 36 , %5, %3 \n\t" // load c +- "lxsdx 37 , %5, %4 \n\t" // load s +- "addi %8 , %8, -8 \n\t" +- "addi %9 , %9, -8 \n\t" +- +- "xxspltd 36 , 36, 0 \n\t" +- "xxspltd 37 , 37, 0 \n\t" +- +- "lxvd2x 32, 0, %1 \n\t" // load x +- "lxvd2x 33, %5, %1 \n\t" +- "lxvd2x 34, %6, %1 \n\t" +- "lxvd2x 35, %7, %1 \n\t" +- +- "lxvd2x 40, 0, %2 \n\t" // load y +- "lxvd2x 41, %5, %2 \n\t" +- "lxvd2x 42, %6, %2 \n\t" +- "lxvd2x 43, %7, %2 \n\t" +- +- "addi %1, %1, 64 \n\t" +- "addi %2, %2, 64 \n\t" +- +- "addic. %0 , %0 , -8 \n\t" +- "ble 2f \n\t" +- +- ".align 5 \n\t" +- "1: \n\t" +- +- "xvmuldp 48, 32, 36 \n\t" // c * x +- "xvmuldp 49, 33, 36 \n\t" +- "xvmuldp 50, 34, 36 \n\t" +- "xvmuldp 51, 35, 36 \n\t" +- +- "xvmuldp 56, 40, 36 \n\t" // c * y +- "xvmuldp 57, 41, 36 \n\t" +- "xvmuldp 58, 42, 36 \n\t" +- "xvmuldp 59, 43, 36 \n\t" +- +- "xvmuldp 52, 32, 37 \n\t" // s * x +- "xvmuldp 53, 33, 37 \n\t" +- +- "lxvd2x 32, 0, %1 \n\t" // load x +- "lxvd2x 33, %5, %1 \n\t" +- +- "xvmuldp 54, 34, 37 \n\t" +- "xvmuldp 55, 35, 37 \n\t" +- +- "lxvd2x 34, %6, %1 \n\t" +- "lxvd2x 35, %7, %1 \n\t" +- +- "xvmuldp 60, 40, 37 \n\t" // s * y +- "xvmuldp 61, 41, 37 \n\t" +- +- "lxvd2x 40, 0, %2 \n\t" // load y +- "lxvd2x 41, %5, %2 \n\t" +- +- "xvmuldp 62, 42, 37 \n\t" +- "xvmuldp 63, 43, 37 \n\t" +- +- "lxvd2x 42, %6, %2 \n\t" +- "lxvd2x 43, %7, %2 \n\t" +- +- "xvadddp 48, 48 , 60 \n\t" // c * x + s * y +- "xvadddp 49, 49 , 61 \n\t" // c * x + s * y +- +- "addi %1, %1, 64 \n\t" +- "addi %2, %2, 64 \n\t" +- +- "xvadddp 50, 50 , 62 \n\t" // c * x + s * y +- "xvadddp 51, 51 , 63 \n\t" // c * x + s * y +- +- "xvsubdp 56, 56 , 52 \n\t" // c * y - s * x +- "xvsubdp 57, 57 , 53 \n\t" // c * y - s * x +- "xvsubdp 58, 58 , 54 \n\t" // c * y - s * x +- "xvsubdp 59, 59 , 55 \n\t" // c * y - s * x +- +- "stxvd2x 48, 0, %8 \n\t" // store x +- "stxvd2x 49, %5, %8 \n\t" +- "stxvd2x 50, %6, %8 \n\t" +- "stxvd2x 51, %7, %8 \n\t" +- +- "stxvd2x 56, 0, %9 \n\t" // store y +- "stxvd2x 57, %5, %9 \n\t" +- "stxvd2x 58, %6, %9 \n\t" +- "stxvd2x 59, %7, %9 \n\t" +- +- "addi %8, %8, 64 \n\t" +- "addi %9, %9, 64 \n\t" +- +- "addic. %0 , %0 , -8 \n\t" +- "bgt 1b \n\t" +- +- "2: \n\t" +- +- "xvmuldp 48, 32, 36 \n\t" // c * x +- "xvmuldp 49, 33, 36 \n\t" +- "xvmuldp 50, 34, 36 \n\t" +- "xvmuldp 51, 35, 36 \n\t" +- +- "xvmuldp 56, 40, 36 \n\t" // c * y +- "xvmuldp 57, 41, 36 \n\t" +- "xvmuldp 58, 42, 36 \n\t" +- "xvmuldp 59, 43, 36 \n\t" +- +- "xvmuldp 52, 32, 37 \n\t" // s * x +- "xvmuldp 53, 33, 37 \n\t" +- "xvmuldp 54, 34, 37 \n\t" +- "xvmuldp 55, 35, 37 \n\t" +- +- "xvmuldp 60, 40, 37 \n\t" // s * y +- "xvmuldp 61, 41, 37 \n\t" +- "xvmuldp 62, 42, 37 \n\t" +- "xvmuldp 63, 43, 37 \n\t" +- +- "xvadddp 48, 48 , 60 \n\t" // c * x + s * y +- "xvadddp 49, 49 , 61 \n\t" // c * x + s * y +- "xvadddp 50, 50 , 62 \n\t" // c * x + s * y +- "xvadddp 51, 51 , 63 \n\t" // c * x + s * y +- +- "xvsubdp 56, 56 , 52 \n\t" // c * y - s * x +- "xvsubdp 57, 57 , 53 \n\t" // c * y - s * x +- "xvsubdp 58, 58 , 54 \n\t" // c * y - s * x +- "xvsubdp 59, 59 , 55 \n\t" // c * y - s * x +- +- "stxvd2x 48, 0, %8 \n\t" // store x +- "stxvd2x 49, %5, %8 \n\t" +- "stxvd2x 50, %6, %8 \n\t" +- "stxvd2x 51, %7, %8 \n\t" ++ "lxvd2x 32, 0, %3 \n\t" // load x ++ "lxvd2x 33, %15, %3 \n\t" ++ "lxvd2x 34, %16, %3 \n\t" ++ "lxvd2x 35, %17, %3 \n\t" + +- "stxvd2x 56, 0, %9 \n\t" // store y +- "stxvd2x 57, %5, %9 \n\t" +- "stxvd2x 58, %6, %9 \n\t" +- "stxvd2x 59, %7, %9 \n\t" ++ "lxvd2x 48, 0, %4 \n\t" // load y ++ "lxvd2x 49, %15, %4 \n\t" ++ "lxvd2x 50, %16, %4 \n\t" ++ "lxvd2x 51, %17, %4 \n\t" + ++ "addi %3, %3, 64 \n\t" ++ "addi %4, %4, 64 \n\t" + ++ "addic. %2, %2, -8 \n\t" ++ "ble 2f \n\t" + +- : +- : +- "r" (i), // 0 +- "r" (x1), // 1 +- "r" (y1), // 2 +- "r" (c), // 3 +- "r" (s), // 4 +- "r" (o16), // 5 +- "r" (o32), // 6 +- "r" (o48), // 7 +- "r" (x2), // 8 +- "r" (y2) // 9 +- : "cr0", "%0", "%1" , "%2", "%8", "%9", "memory" +- ); ++ ".p2align 5 \n" ++ "1: \n\t" + +-} ++ "xvmuldp 40, 32, 36 \n\t" // c * x ++ "xvmuldp 41, 33, 36 \n\t" ++ "xvmuldp 42, 34, 36 \n\t" ++ "xvmuldp 43, 35, 36 \n\t" + ++ "xvmuldp %x5, 48, 36 \n\t" // c * y ++ "xvmuldp %x6, 49, 36 \n\t" ++ "xvmuldp %x7, 50, 36 \n\t" ++ "xvmuldp %x8, 51, 36 \n\t" + ++ "xvmuldp 44, 32, 37 \n\t" // s * x ++ "xvmuldp 45, 33, 37 \n\t" ++ ++ "lxvd2x 32, 0, %3 \n\t" // load x ++ "lxvd2x 33, %15, %3 \n\t" ++ ++ "xvmuldp 46, 34, 37 \n\t" ++ "xvmuldp 47, 35, 37 \n\t" ++ ++ "lxvd2x 34, %16, %3 \n\t" ++ "lxvd2x 35, %17, %3 \n\t" ++ ++ "xvmuldp %x9, 48, 37 \n\t" // s * y ++ "xvmuldp %x10, 49, 37 \n\t" ++ ++ "lxvd2x 48, 0, %4 \n\t" // load y ++ "lxvd2x 49, %15, %4 \n\t" ++ ++ "xvmuldp %x11, 50, 37 \n\t" ++ "xvmuldp %x12, 51, 37 \n\t" ++ ++ "lxvd2x 50, %16, %4 \n\t" ++ "lxvd2x 51, %17, %4 \n\t" ++ ++ "xvadddp 40, 40, %x9 \n\t" // c * x + s * y ++ "xvadddp 41, 41, %x10 \n\t" // c * x + s * y ++ ++ "addi %3, %3, -64 \n\t" ++ "addi %4, %4, -64 \n\t" ++ ++ "xvadddp 42, 42, %x11 \n\t" // c * x + s * y ++ "xvadddp 43, 43, %x12 \n\t" // c * x + s * y ++ ++ "xvsubdp %x5, %x5, 44 \n\t" // c * y - s * x ++ "xvsubdp %x6, %x6, 45 \n\t" // c * y - s * x ++ "xvsubdp %x7, %x7, 46 \n\t" // c * y - s * x ++ "xvsubdp %x8, %x8, 47 \n\t" // c * y - s * x ++ ++ "stxvd2x 40, 0, %3 \n\t" // store x ++ "stxvd2x 41, %15, %3 \n\t" ++ "stxvd2x 42, %16, %3 \n\t" ++ "stxvd2x 43, %17, %3 \n\t" ++ ++ "stxvd2x %x5, 0, %4 \n\t" // store y ++ "stxvd2x %x6, %15, %4 \n\t" ++ "stxvd2x %x7, %16, %4 \n\t" ++ "stxvd2x %x8, %17, %4 \n\t" ++ ++ "addi %3, %3, 128 \n\t" ++ "addi %4, %4, 128 \n\t" ++ ++ "addic. %2, %2, -8 \n\t" ++ "bgt 1b \n" ++ ++ "2: \n\t" ++ ++ "xvmuldp 40, 32, 36 \n\t" // c * x ++ "xvmuldp 41, 33, 36 \n\t" ++ "xvmuldp 42, 34, 36 \n\t" ++ "xvmuldp 43, 35, 36 \n\t" ++ ++ "xvmuldp %x5, 48, 36 \n\t" // c * y ++ "xvmuldp %x6, 49, 36 \n\t" ++ "xvmuldp %x7, 50, 36 \n\t" ++ "xvmuldp %x8, 51, 36 \n\t" ++ ++ "xvmuldp 44, 32, 37 \n\t" // s * x ++ "xvmuldp 45, 33, 37 \n\t" ++ "xvmuldp 46, 34, 37 \n\t" ++ "xvmuldp 47, 35, 37 \n\t" ++ ++ "xvmuldp %x9, 48, 37 \n\t" // s * y ++ "xvmuldp %x10, 49, 37 \n\t" ++ "xvmuldp %x11, 50, 37 \n\t" ++ "xvmuldp %x12, 51, 37 \n\t" ++ ++ "addi %3, %3, -64 \n\t" ++ "addi %4, %4, -64 \n\t" ++ ++ "xvadddp 40, 40, %x9 \n\t" // c * x + s * y ++ "xvadddp 41, 41, %x10 \n\t" // c * x + s * y ++ "xvadddp 42, 42, %x11 \n\t" // c * x + s * y ++ "xvadddp 43, 43, %x12 \n\t" // c * x + s * y ++ ++ "xvsubdp %x5, %x5, 44 \n\t" // c * y - s * x ++ "xvsubdp %x6, %x6, 45 \n\t" // c * y - s * x ++ "xvsubdp %x7, %x7, 46 \n\t" // c * y - s * x ++ "xvsubdp %x8, %x8, 47 \n\t" // c * y - s * x ++ ++ "stxvd2x 40, 0, %3 \n\t" // store x ++ "stxvd2x 41, %15, %3 \n\t" ++ "stxvd2x 42, %16, %3 \n\t" ++ "stxvd2x 43, %17, %3 \n\t" ++ ++ "stxvd2x %x5, 0, %4 \n\t" // store y ++ "stxvd2x %x6, %15, %4 \n\t" ++ "stxvd2x %x7, %16, %4 \n\t" ++ "stxvd2x %x8, %17, %4 \n" ++ ++ "#n=%2 x=%0=%3 y=%1=%4 c=%13 s=%14 o16=%15 o32=%16 o48=%17\n" ++ "#t0=%x5 t1=%x6 t2=%x7 t3=%x8 t4=%x9 t5=%x10 t6=%x11 t7=%x12" ++ : ++ "+m" (*x), ++ "+m" (*y), ++ "+r" (n), // 2 ++ "+b" (x), // 3 ++ "+b" (y), // 4 ++ "=wa" (t0), // 5 ++ "=wa" (t1), // 6 ++ "=wa" (t2), // 7 ++ "=wa" (t3), // 8 ++ "=wa" (t4), // 9 ++ "=wa" (t5), // 10 ++ "=wa" (t6), // 11 ++ "=wa" (t7) // 12 ++ : ++ "d" (c), // 13 ++ "d" (s), // 14 ++ "b" (16), // 15 ++ "b" (32), // 16 ++ "b" (48) // 17 ++ : ++ "cr0", ++ "vs32","vs33","vs34","vs35","vs36","vs37", ++ "vs40","vs41","vs42","vs43","vs44","vs45","vs46","vs47", ++ "vs48","vs49","vs50","vs51" ++ ); ++} +diff --git a/kernel/power/dscal.c b/kernel/power/dscal.c +index c62a563..f32dc4b 100644 +--- a/kernel/power/dscal.c ++++ b/kernel/power/dscal.c +@@ -41,11 +41,10 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + #if !defined(HAVE_KERNEL_8) + +-static void dscal_kernel_8( BLASLONG n, FLOAT *da , FLOAT *x ) ++static void dscal_kernel_8 (BLASLONG n, FLOAT *x, FLOAT alpha) + { + + BLASLONG i; +- FLOAT alpha = *da; + + for( i=0; i 0 ) + { +- FLOAT alpha[2]; +- alpha[0]=da; +- alpha[1]=da; +- dscal_kernel_8_zero(n1 , alpha , x); ++ dscal_kernel_8_zero(n1, x); + j=n1; + } + +@@ -123,10 +119,7 @@ int CNAME(BLASLONG n, BLASLONG dummy0, BLASLONG dummy1, FLOAT da, FLOAT *x, BLAS + BLASLONG n1 = n & -16; + if ( n1 > 0 ) + { +- FLOAT alpha[2]; +- alpha[0]=da; +- alpha[1]=da; +- dscal_kernel_8(n1 , alpha , x); ++ dscal_kernel_8(n1, x, da); + j=n1; + } + while(j < n) +diff --git a/kernel/power/dscal_microk_power8.c b/kernel/power/dscal_microk_power8.c +index d90c3d8..04898eb 100644 +--- a/kernel/power/dscal_microk_power8.c ++++ b/kernel/power/dscal_microk_power8.c +@@ -35,185 +35,149 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + #define HAVE_KERNEL_8 1 + +-static void dscal_kernel_8( BLASLONG n, FLOAT *alpha, FLOAT *x) __attribute__ ((noinline)); +- +-static void dscal_kernel_8( BLASLONG n, FLOAT *alpha, FLOAT *x) ++static void dscal_kernel_8 (long n, double *x, double alpha) + { +- +- +- BLASLONG i = n; +- BLASLONG o16 = 16; +- BLASLONG o32 = 32; +- BLASLONG o48 = 48; +- BLASLONG o64 = 64; +- BLASLONG o80 = 80; +- BLASLONG o96 = 96; +- BLASLONG o112 = 112; +- FLOAT *x1=x; +- FLOAT *x2=x+1; +- BLASLONG pre = 384; +- +- __asm__ __volatile__ +- ( +- +- "lxsdx 33, 0, %3 \n\t" +- "xxspltd 32, 33, 0 \n\t" +- "addi %1, %1, -8 \n\t" +- +- "dcbt %2, %4 \n\t" +- +- "lxvd2x 40, 0, %2 \n\t" +- "lxvd2x 41, %5, %2 \n\t" +- "lxvd2x 42, %6, %2 \n\t" +- "lxvd2x 43, %7, %2 \n\t" +- "lxvd2x 44, %8, %2 \n\t" +- "lxvd2x 45, %9, %2 \n\t" +- "lxvd2x 46, %10, %2 \n\t" +- "lxvd2x 47, %11, %2 \n\t" +- +- "addi %2, %2, 128 \n\t" +- +- "addic. %0 , %0 , -16 \n\t" +- "ble 2f \n\t" +- +- ".align 5 \n\t" +- "1: \n\t" +- +- "dcbt %2, %4 \n\t" +- +- "xvmuldp 48, 40, 32 \n\t" +- "xvmuldp 49, 41, 32 \n\t" +- "lxvd2x 40, 0, %2 \n\t" +- "lxvd2x 41, %5, %2 \n\t" +- "xvmuldp 50, 42, 32 \n\t" +- "xvmuldp 51, 43, 32 \n\t" +- "lxvd2x 42, %6, %2 \n\t" +- "lxvd2x 43, %7, %2 \n\t" +- "xvmuldp 52, 44, 32 \n\t" +- "xvmuldp 53, 45, 32 \n\t" +- "lxvd2x 44, %8, %2 \n\t" +- "lxvd2x 45, %9, %2 \n\t" +- "xvmuldp 54, 46, 32 \n\t" +- "xvmuldp 55, 47, 32 \n\t" +- "lxvd2x 46, %10, %2 \n\t" +- "lxvd2x 47, %11, %2 \n\t" +- +- "stxvd2x 48, 0, %1 \n\t" +- "stxvd2x 49, %5, %1 \n\t" +- "stxvd2x 50, %6, %1 \n\t" +- "stxvd2x 51, %7, %1 \n\t" +- "stxvd2x 52, %8, %1 \n\t" +- "stxvd2x 53, %9, %1 \n\t" +- "stxvd2x 54, %10, %1 \n\t" +- "stxvd2x 55, %11, %1 \n\t" +- +- "addi %1, %1, 128 \n\t" +- "addi %2, %2, 128 \n\t" +- +- "addic. %0 , %0 , -16 \n\t" +- "bgt 1b \n\t" +- +- "2: \n\t" +- +- "xvmuldp 48, 40, 32 \n\t" +- "xvmuldp 49, 41, 32 \n\t" +- "xvmuldp 50, 42, 32 \n\t" +- "xvmuldp 51, 43, 32 \n\t" +- "xvmuldp 52, 44, 32 \n\t" +- "xvmuldp 53, 45, 32 \n\t" +- "xvmuldp 54, 46, 32 \n\t" +- "xvmuldp 55, 47, 32 \n\t" +- +- "stxvd2x 48, 0, %1 \n\t" +- "stxvd2x 49, %5, %1 \n\t" +- "stxvd2x 50, %6, %1 \n\t" +- "stxvd2x 51, %7, %1 \n\t" +- "stxvd2x 52, %8, %1 \n\t" +- "stxvd2x 53, %9, %1 \n\t" +- "stxvd2x 54, %10, %1 \n\t" +- "stxvd2x 55, %11, %1 \n\t" +- +- : +- : +- "r" (i), // 0 +- "r" (x2), // 1 +- "r" (x1), // 2 +- "r" (alpha), // 3 +- "r" (pre), // 4 +- "r" (o16), // 5 +- "r" (o32), // 6 +- "r" (o48), // 7 +- "r" (o64), // 8 +- "r" (o80), // 9 +- "r" (o96), // 10 +- "r" (o112) // 11 +- : "cr0", "%0", "%2" , "%1", "memory" +- ); +- +-} +- +- +-static void dscal_kernel_8_zero( BLASLONG n, FLOAT *alpha, FLOAT *x) __attribute__ ((noinline)); +- +-static void dscal_kernel_8_zero( BLASLONG n, FLOAT *alpha, FLOAT *x) ++ __asm__ ++ ( ++ "dcbt 0, %2 \n\t" ++ ++ "xxspltd %x3, %x3, 0 \n\t" ++ ++ "lxvd2x 32, 0, %2 \n\t" ++ "lxvd2x 33, %4, %2 \n\t" ++ "lxvd2x 34, %5, %2 \n\t" ++ "lxvd2x 35, %6, %2 \n\t" ++ "lxvd2x 36, %7, %2 \n\t" ++ "lxvd2x 37, %8, %2 \n\t" ++ "lxvd2x 38, %9, %2 \n\t" ++ "lxvd2x 39, %10, %2 \n\t" ++ ++ "addi %2, %2, 128 \n\t" ++ ++ "addic. %1, %1, -16 \n\t" ++ "ble 2f \n\t" ++ ++ ".p2align 5 \n" ++ "1: \n\t" ++ ++ "xvmuldp 40, 32, %x3 \n\t" ++ "xvmuldp 41, 33, %x3 \n\t" ++ "lxvd2x 32, 0, %2 \n\t" ++ "lxvd2x 33, %4, %2 \n\t" ++ "xvmuldp 42, 34, %x3 \n\t" ++ "xvmuldp 43, 35, %x3 \n\t" ++ "lxvd2x 34, %5, %2 \n\t" ++ "lxvd2x 35, %6, %2 \n\t" ++ "xvmuldp 44, 36, %x3 \n\t" ++ "xvmuldp 45, 37, %x3 \n\t" ++ "lxvd2x 36, %7, %2 \n\t" ++ "lxvd2x 37, %8, %2 \n\t" ++ "xvmuldp 46, 38, %x3 \n\t" ++ "xvmuldp 47, 39, %x3 \n\t" ++ "lxvd2x 38, %9, %2 \n\t" ++ "lxvd2x 39, %10, %2 \n\t" ++ ++ "addi %2, %2, -128 \n\t" ++ ++ "stxvd2x 40, 0, %2 \n\t" ++ "stxvd2x 41, %4, %2 \n\t" ++ "stxvd2x 42, %5, %2 \n\t" ++ "stxvd2x 43, %6, %2 \n\t" ++ "stxvd2x 44, %7, %2 \n\t" ++ "stxvd2x 45, %8, %2 \n\t" ++ "stxvd2x 46, %9, %2 \n\t" ++ "stxvd2x 47, %10, %2 \n\t" ++ ++ "addi %2, %2, 256 \n\t" ++ ++ "addic. %1, %1, -16 \n\t" ++ "bgt 1b \n" ++ ++ "2: \n\t" ++ ++ "xvmuldp 40, 32, %x3 \n\t" ++ "xvmuldp 41, 33, %x3 \n\t" ++ "xvmuldp 42, 34, %x3 \n\t" ++ "xvmuldp 43, 35, %x3 \n\t" ++ ++ "addi %2, %2, -128 \n\t" ++ ++ "xvmuldp 44, 36, %x3 \n\t" ++ "xvmuldp 45, 37, %x3 \n\t" ++ "xvmuldp 46, 38, %x3 \n\t" ++ "xvmuldp 47, 39, %x3 \n\t" ++ ++ "stxvd2x 40, 0, %2 \n\t" ++ "stxvd2x 41, %4, %2 \n\t" ++ "stxvd2x 42, %5, %2 \n\t" ++ "stxvd2x 43, %6, %2 \n\t" ++ "stxvd2x 44, %7, %2 \n\t" ++ "stxvd2x 45, %8, %2 \n\t" ++ "stxvd2x 46, %9, %2 \n\t" ++ "stxvd2x 47, %10, %2 \n" ++ ++ "#n=%1 alpha=%3 x=%0=%2 o16=%4 o32=%5 o48=%6 o64=%7 o80=%8 o96=%9 o112=%10" ++ : ++ "+m" (*x), ++ "+r" (n), // 1 ++ "+b" (x) // 2 ++ : ++ "d" (alpha), // 3 ++ "b" (16), // 4 ++ "b" (32), // 5 ++ "b" (48), // 6 ++ "b" (64), // 7 ++ "b" (80), // 8 ++ "b" (96), // 9 ++ "b" (112) // 10 ++ : ++ "cr0", ++ "vs32","vs33","vs34","vs35","vs36","vs37","vs38","vs39", ++ "vs40","vs41","vs42","vs43","vs44","vs45","vs46","vs47" ++ ); ++} ++ ++ ++static void dscal_kernel_8_zero (long n, double *x) + { +- +- +- BLASLONG i = n; +- BLASLONG o16 = 16; +- BLASLONG o32 = 32; +- BLASLONG o48 = 48; +- BLASLONG o64 = 64; +- BLASLONG o80 = 80; +- BLASLONG o96 = 96; +- BLASLONG o112 = 112; +- FLOAT *x1=x; +- FLOAT *x2=x+1; +- BLASLONG pre = 384; +- +- __asm__ __volatile__ +- ( +- +- "xxlxor 32 , 32 , 32 \n\t" +- "addi %1, %1, -8 \n\t" +- +- +- ".align 5 \n\t" +- "1: \n\t" +- +- "stxvd2x 32, 0, %1 \n\t" +- "stxvd2x 32, %5, %1 \n\t" +- "stxvd2x 32, %6, %1 \n\t" +- "stxvd2x 32, %7, %1 \n\t" +- "stxvd2x 32, %8, %1 \n\t" +- "stxvd2x 32, %9, %1 \n\t" +- "stxvd2x 32, %10, %1 \n\t" +- "stxvd2x 32, %11, %1 \n\t" +- +- "addi %1, %1, 128 \n\t" +- +- "addic. %0 , %0 , -16 \n\t" +- "bgt 1b \n\t" +- +- "2: \n\t" +- +- : +- : +- "r" (i), // 0 +- "r" (x2), // 1 +- "r" (x1), // 2 +- "r" (alpha), // 3 +- "r" (pre), // 4 +- "r" (o16), // 5 +- "r" (o32), // 6 +- "r" (o48), // 7 +- "r" (o64), // 8 +- "r" (o80), // 9 +- "r" (o96), // 10 +- "r" (o112) // 11 +- : "cr0", "%0", "%2" , "%1", "memory" +- ); +- +-} +- +- ++ __vector double t0; ++ ++ __asm__ ++ ( ++ "xxlxor %x3, %x3, %x3 \n\t" ++ ++ ".p2align 5 \n" ++ "1: \n\t" ++ ++ "stxvd2x %x3, 0, %2 \n\t" ++ "stxvd2x %x3, %4, %2 \n\t" ++ "stxvd2x %x3, %5, %2 \n\t" ++ "stxvd2x %x3, %6, %2 \n\t" ++ "stxvd2x %x3, %7, %2 \n\t" ++ "stxvd2x %x3, %8, %2 \n\t" ++ "stxvd2x %x3, %9, %2 \n\t" ++ "stxvd2x %x3, %10, %2 \n\t" ++ ++ "addi %2, %2, 128 \n\t" ++ ++ "addic. %1, %1, -16 \n\t" ++ "bgt 1b \n" ++ ++ "#n=%1 x=%0=%2 t0=%x3 o16=%4 o32=%5 o48=%6 o64=%7 o80=%8 o96=%9 o112=%10" ++ : ++ "=m" (*x), ++ "+r" (n), // 1 ++ "+b" (x), // 2 ++ "=wa" (t0) // 3 ++ : ++ "b" (16), // 4 ++ "b" (32), // 5 ++ "b" (48), // 6 ++ "b" (64), // 7 ++ "b" (80), // 8 ++ "b" (96), // 9 ++ "b" (112) // 10 ++ : ++ "cr0" ++ ); ++} +diff --git a/kernel/power/dswap_microk_power8.c b/kernel/power/dswap_microk_power8.c +index 77747c3..31eff34 100644 +--- a/kernel/power/dswap_microk_power8.c ++++ b/kernel/power/dswap_microk_power8.c +@@ -35,146 +35,124 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + #define HAVE_KERNEL_32 1 + +-static void dswap_kernel_32( BLASLONG n, FLOAT *x, FLOAT *y) __attribute__ ((noinline)); +- +-static void dswap_kernel_32( BLASLONG n, FLOAT *x, FLOAT *y) ++static void dswap_kernel_32 (long n, double *x, double *y) + { +- +- +- BLASLONG i = n; +- BLASLONG o16 = 16; +- BLASLONG o32 = 32; +- BLASLONG o48 = 48; +- BLASLONG o64 = 64; +- BLASLONG o80 = 80; +- BLASLONG o96 = 96; +- BLASLONG o112 = 112; +- FLOAT *x1=x; +- FLOAT *y1=y; +- FLOAT *x2=x+1; +- FLOAT *y2=y+1; +- BLASLONG pre = 384; +- BLASLONG alpha=0; +- +- __asm__ __volatile__ +- ( +- +- "addi %3, %3, -8 \n\t" +- "addi %4, %4, -8 \n\t" +- +- ".align 5 \n\t" +- "1: \n\t" +- +- "lxvd2x 32, 0, %2 \n\t" +- "lxvd2x 33, %5, %2 \n\t" +- "lxvd2x 34, %6, %2 \n\t" +- "lxvd2x 35, %7, %2 \n\t" +- "lxvd2x 36, %8, %2 \n\t" +- "lxvd2x 37, %9, %2 \n\t" +- "lxvd2x 38, %10, %2 \n\t" +- "lxvd2x 39, %11, %2 \n\t" +- +- "addi %2, %2, 128 \n\t" +- +- "lxvd2x 40, 0, %2 \n\t" +- "lxvd2x 41, %5, %2 \n\t" +- "lxvd2x 42, %6, %2 \n\t" +- "lxvd2x 43, %7, %2 \n\t" +- "lxvd2x 44, %8, %2 \n\t" +- "lxvd2x 45, %9, %2 \n\t" +- "lxvd2x 46, %10, %2 \n\t" +- "lxvd2x 47, %11, %2 \n\t" +- +- "addi %2, %2, 128 \n\t" +- +- "lxvd2x 48, 0, %1 \n\t" +- "lxvd2x 49, %5, %1 \n\t" +- "lxvd2x 50, %6, %1 \n\t" +- "lxvd2x 51, %7, %1 \n\t" +- "lxvd2x 52, %8, %1 \n\t" +- "lxvd2x 53, %9, %1 \n\t" +- "lxvd2x 54, %10, %1 \n\t" +- "lxvd2x 55, %11, %1 \n\t" +- +- "addi %1, %1, 128 \n\t" +- +- "lxvd2x 56, 0, %1 \n\t" +- "lxvd2x 57, %5, %1 \n\t" +- "lxvd2x 58, %6, %1 \n\t" +- "lxvd2x 59, %7, %1 \n\t" +- "lxvd2x 60, %8, %1 \n\t" +- "lxvd2x 61, %9, %1 \n\t" +- "lxvd2x 62, %10, %1 \n\t" +- "lxvd2x 63, %11, %1 \n\t" +- +- "addi %1, %1, 128 \n\t" +- +- "stxvd2x 32, 0, %3 \n\t" +- "stxvd2x 33, %5, %3 \n\t" +- "stxvd2x 34, %6, %3 \n\t" +- "stxvd2x 35, %7, %3 \n\t" +- "stxvd2x 36, %8, %3 \n\t" +- "stxvd2x 37, %9, %3 \n\t" +- "stxvd2x 38, %10, %3 \n\t" +- "stxvd2x 39, %11, %3 \n\t" +- +- "addi %3, %3, 128 \n\t" +- +- "stxvd2x 40, 0, %3 \n\t" +- "stxvd2x 41, %5, %3 \n\t" +- "stxvd2x 42, %6, %3 \n\t" +- "stxvd2x 43, %7, %3 \n\t" +- "stxvd2x 44, %8, %3 \n\t" +- "stxvd2x 45, %9, %3 \n\t" +- "stxvd2x 46, %10, %3 \n\t" +- "stxvd2x 47, %11, %3 \n\t" +- +- "addi %3, %3, 128 \n\t" +- +- "stxvd2x 48, 0, %4 \n\t" +- "stxvd2x 49, %5, %4 \n\t" +- "stxvd2x 50, %6, %4 \n\t" +- "stxvd2x 51, %7, %4 \n\t" +- "stxvd2x 52, %8, %4 \n\t" +- "stxvd2x 53, %9, %4 \n\t" +- "stxvd2x 54, %10, %4 \n\t" +- "stxvd2x 55, %11, %4 \n\t" +- +- "addi %4, %4, 128 \n\t" +- +- "stxvd2x 56, 0, %4 \n\t" +- "stxvd2x 57, %5, %4 \n\t" +- "stxvd2x 58, %6, %4 \n\t" +- "stxvd2x 59, %7, %4 \n\t" +- "stxvd2x 60, %8, %4 \n\t" +- "stxvd2x 61, %9, %4 \n\t" +- "stxvd2x 62, %10, %4 \n\t" +- "stxvd2x 63, %11, %4 \n\t" +- +- "addi %4, %4, 128 \n\t" +- +- "addic. %0 , %0 , -32 \n\t" +- "bgt 1b \n\t" +- +- "2: \n\t" +- +- : +- : +- "r" (i), // 0 +- "r" (y1), // 1 +- "r" (x1), // 2 +- "r" (y2), // 3 +- "r" (x2), // 4 +- "r" (o16), // 5 +- "r" (o32), // 6 +- "r" (o48), // 7 +- "r" (o64), // 8 +- "r" (o80), // 9 +- "r" (o96), // 10 +- "r" (o112) // 11 +- : "cr0", "%0", "%2" , "%1", "%3", "%4", "memory" +- ); +- +-} +- +- ++ __asm__ ++ ( ++ ".p2align 5 \n" ++ "1: \n\t" ++ ++ "lxvd2x 32, 0, %4 \n\t" ++ "lxvd2x 33, %5, %4 \n\t" ++ "lxvd2x 34, %6, %4 \n\t" ++ "lxvd2x 35, %7, %4 \n\t" ++ "lxvd2x 36, %8, %4 \n\t" ++ "lxvd2x 37, %9, %4 \n\t" ++ "lxvd2x 38, %10, %4 \n\t" ++ "lxvd2x 39, %11, %4 \n\t" ++ ++ "addi %4, %4, 128 \n\t" ++ ++ "lxvd2x 40, 0, %4 \n\t" ++ "lxvd2x 41, %5, %4 \n\t" ++ "lxvd2x 42, %6, %4 \n\t" ++ "lxvd2x 43, %7, %4 \n\t" ++ "lxvd2x 44, %8, %4 \n\t" ++ "lxvd2x 45, %9, %4 \n\t" ++ "lxvd2x 46, %10, %4 \n\t" ++ "lxvd2x 47, %11, %4 \n\t" ++ ++ "addi %4, %4, -128 \n\t" ++ ++ "lxvd2x 48, 0, %3 \n\t" ++ "lxvd2x 49, %5, %3 \n\t" ++ "lxvd2x 50, %6, %3 \n\t" ++ "lxvd2x 51, %7, %3 \n\t" ++ "lxvd2x 0, %8, %3 \n\t" ++ "lxvd2x 1, %9, %3 \n\t" ++ "lxvd2x 2, %10, %3 \n\t" ++ "lxvd2x 3, %11, %3 \n\t" ++ ++ "addi %3, %3, 128 \n\t" ++ ++ "lxvd2x 4, 0, %3 \n\t" ++ "lxvd2x 5, %5, %3 \n\t" ++ "lxvd2x 6, %6, %3 \n\t" ++ "lxvd2x 7, %7, %3 \n\t" ++ "lxvd2x 8, %8, %3 \n\t" ++ "lxvd2x 9, %9, %3 \n\t" ++ "lxvd2x 10, %10, %3 \n\t" ++ "lxvd2x 11, %11, %3 \n\t" ++ ++ "addi %3, %3, -128 \n\t" ++ ++ "stxvd2x 32, 0, %3 \n\t" ++ "stxvd2x 33, %5, %3 \n\t" ++ "stxvd2x 34, %6, %3 \n\t" ++ "stxvd2x 35, %7, %3 \n\t" ++ "stxvd2x 36, %8, %3 \n\t" ++ "stxvd2x 37, %9, %3 \n\t" ++ "stxvd2x 38, %10, %3 \n\t" ++ "stxvd2x 39, %11, %3 \n\t" ++ ++ "addi %3, %3, 128 \n\t" ++ ++ "stxvd2x 40, 0, %3 \n\t" ++ "stxvd2x 41, %5, %3 \n\t" ++ "stxvd2x 42, %6, %3 \n\t" ++ "stxvd2x 43, %7, %3 \n\t" ++ "stxvd2x 44, %8, %3 \n\t" ++ "stxvd2x 45, %9, %3 \n\t" ++ "stxvd2x 46, %10, %3 \n\t" ++ "stxvd2x 47, %11, %3 \n\t" ++ ++ "addi %3, %3, 128 \n\t" ++ ++ "stxvd2x 48, 0, %4 \n\t" ++ "stxvd2x 49, %5, %4 \n\t" ++ "stxvd2x 50, %6, %4 \n\t" ++ "stxvd2x 51, %7, %4 \n\t" ++ "stxvd2x 0, %8, %4 \n\t" ++ "stxvd2x 1, %9, %4 \n\t" ++ "stxvd2x 2, %10, %4 \n\t" ++ "stxvd2x 3, %11, %4 \n\t" ++ ++ "addi %4, %4, 128 \n\t" ++ ++ "stxvd2x 4, 0, %4 \n\t" ++ "stxvd2x 5, %5, %4 \n\t" ++ "stxvd2x 6, %6, %4 \n\t" ++ "stxvd2x 7, %7, %4 \n\t" ++ "stxvd2x 8, %8, %4 \n\t" ++ "stxvd2x 9, %9, %4 \n\t" ++ "stxvd2x 10, %10, %4 \n\t" ++ "stxvd2x 11, %11, %4 \n\t" ++ ++ "addi %4, %4, 128 \n\t" ++ ++ "addic. %2, %2, -32 \n\t" ++ "bgt 1b \n" ++ ++ "#n=%2 x=%0=%3 y=%1=%4 o16=%5 o32=%6 o48=%7 o64=%8 o80=%9 o96=%10 o112=%11" ++ : ++ "+m" (*x), ++ "+m" (*y), ++ "+r" (n), // 2 ++ "+b" (x), // 3 ++ "+b" (y) // 4 ++ : ++ "b" (16), // 5 ++ "b" (32), // 6 ++ "b" (48), // 7 ++ "b" (64), // 8 ++ "b" (80), // 9 ++ "b" (96), // 10 ++ "b" (112) // 11 ++ : ++ "cr0", ++ "vs32","vs33","vs34","vs35","vs36","vs37","vs38","vs39", ++ "vs40","vs41","vs42","vs43","vs44","vs45","vs46","vs47", ++ "vs48","vs49","vs50","vs51","vs0","vs1","vs2","vs3", ++ "vs4","vs5","vs6","vs7","vs8","vs9","vs10","vs11" ++ ); ++} +diff --git a/kernel/power/sasum.c b/kernel/power/sasum.c +index 43311f2..fb10b1d 100644 +--- a/kernel/power/sasum.c ++++ b/kernel/power/sasum.c +@@ -38,7 +38,7 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + #if defined(DOUBLE) + +-#define ABS fabs ++#error supports float only + + #else + +@@ -53,7 +53,7 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + #ifndef HAVE_KERNEL_32 + +-static void sasum_kernel_32(BLASLONG n, FLOAT *x1, FLOAT *svec) ++static FLOAT sasum_kernel_32(BLASLONG n, FLOAT *x1) + { + + BLASLONG i=0; +@@ -92,11 +92,7 @@ static void sasum_kernel_32(BLASLONG n, FLOAT *x1, FLOAT *svec) + + } + +- svec[0] = sum0+sum1+sum2+sum3; +- svec[1] = 0.0; +- svec[2] = 0.0; +- svec[3] = 0.0; +- ++ return sum0+sum1+sum2+sum3; + } + + #endif +@@ -105,7 +101,6 @@ FLOAT CNAME(BLASLONG n, FLOAT *x, BLASLONG inc_x) + { + BLASLONG i=0; + FLOAT sumf = 0.0; +- FLOAT svec[4] __attribute__ ((aligned (16)));; + BLASLONG n1; + + if (n <= 0 || inc_x <= 0) return(sumf); +@@ -117,8 +112,7 @@ FLOAT CNAME(BLASLONG n, FLOAT *x, BLASLONG inc_x) + if ( n1 > 0 ) + { + +- sasum_kernel_32(n1, x, svec); +- sumf = svec[0] + svec[1]+svec[2]+svec[3]; ++ sumf = sasum_kernel_32(n1, x); + i=n1; + } + +diff --git a/kernel/power/sasum_microk_power8.c b/kernel/power/sasum_microk_power8.c +index 847fffe..25a969d 100644 +--- a/kernel/power/sasum_microk_power8.c ++++ b/kernel/power/sasum_microk_power8.c +@@ -34,144 +34,145 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + **************************************************************************************/ + + #define HAVE_KERNEL_32 1 +-static void sasum_kernel_32( BLASLONG n, FLOAT *x, FLOAT *svec) __attribute__ ((noinline)); + +-static void sasum_kernel_32( BLASLONG n, FLOAT *x, FLOAT *svec) ++static float sasum_kernel_32 (long n, float *x) + { +- +- +- BLASLONG i = n; +- BLASLONG o16 = 16; +- BLASLONG o32 = 32; +- BLASLONG o48 = 48; +- BLASLONG o64 = 64; +- BLASLONG o80 = 80; +- BLASLONG o96 = 96; +- BLASLONG o112 = 112; +- FLOAT *x1=x; +- BLASLONG pre = 384; +- +- __asm__ __volatile__ +- ( +- +- "dcbt %2 , %4 \n\t" +- +- "xxlxor 32,32,32 \n\t" +- "xxlxor 33,33,33 \n\t" +- "xxlxor 34,34,34 \n\t" +- "xxlxor 35,35,35 \n\t" +- "xxlxor 36,36,36 \n\t" +- "xxlxor 37,37,37 \n\t" +- "xxlxor 38,38,38 \n\t" +- "xxlxor 39,39,39 \n\t" +- +- "lxvw4x 40, 0, %2 \n\t" +- "lxvw4x 41, %5, %2 \n\t" +- "lxvw4x 42, %6, %2 \n\t" +- "lxvw4x 43, %7, %2 \n\t" +- "lxvw4x 44, %8, %2 \n\t" +- "lxvw4x 45, %9, %2 \n\t" +- "lxvw4x 46, %10, %2 \n\t" +- "lxvw4x 47, %11, %2 \n\t" +- +- "addi %2, %2, 128 \n\t" +- +- "addic. %0 , %0 , -32 \n\t" +- "ble 2f \n\t" +- +- ".align 5 \n\t" +- "1: \n\t" +- +- "dcbt %2 , %4 \n\t" +- +- "xvabssp 48, 40 \n\t" +- "xvabssp 49, 41 \n\t" +- "xvabssp 50, 42 \n\t" +- "xvabssp 51, 43 \n\t" +- +- "lxvw4x 40, 0, %2 \n\t" +- "lxvw4x 41, %5, %2 \n\t" +- +- "xvabssp 52, 44 \n\t" +- "xvabssp 53, 45 \n\t" +- +- "lxvw4x 42, %6, %2 \n\t" +- "lxvw4x 43, %7, %2 \n\t" +- +- "xvabssp 54, 46 \n\t" +- "xvabssp 55, 47 \n\t" +- +- "lxvw4x 44, %8, %2 \n\t" +- "lxvw4x 45, %9, %2 \n\t" +- +- "xvaddsp 32, 32, 48 \n\t" +- "xvaddsp 33, 33, 49 \n\t" +- +- "lxvw4x 46, %10, %2 \n\t" +- "lxvw4x 47, %11, %2 \n\t" +- +- "xvaddsp 34, 34, 50 \n\t" +- "xvaddsp 35, 35, 51 \n\t" +- "addi %2, %2, 128 \n\t" +- "xvaddsp 36, 36, 52 \n\t" +- "xvaddsp 37, 37, 53 \n\t" +- "addic. %0 , %0 , -32 \n\t" +- "xvaddsp 38, 38, 54 \n\t" +- "xvaddsp 39, 39, 55 \n\t" +- +- "bgt 1b \n\t" +- +- "2: \n\t" +- +- +- "xvabssp 48, 40 \n\t" +- "xvabssp 49, 41 \n\t" +- "xvabssp 50, 42 \n\t" +- "xvabssp 51, 43 \n\t" +- "xvabssp 52, 44 \n\t" +- "xvabssp 53, 45 \n\t" +- "xvabssp 54, 46 \n\t" +- "xvabssp 55, 47 \n\t" +- +- "xvaddsp 32, 32, 48 \n\t" +- "xvaddsp 33, 33, 49 \n\t" +- "xvaddsp 34, 34, 50 \n\t" +- "xvaddsp 35, 35, 51 \n\t" +- "xvaddsp 36, 36, 52 \n\t" +- "xvaddsp 37, 37, 53 \n\t" +- "xvaddsp 38, 38, 54 \n\t" +- "xvaddsp 39, 39, 55 \n\t" +- +- "xvaddsp 32, 32, 33 \n\t" +- "xvaddsp 34, 34, 35 \n\t" +- "xvaddsp 36, 36, 37 \n\t" +- "xvaddsp 38, 38, 39 \n\t" +- +- "xvaddsp 32, 32, 34 \n\t" +- "xvaddsp 36, 36, 38 \n\t" +- +- "xvaddsp 32, 32, 36 \n\t" +- +- +- "stxvw4x 32, 0, %3 \n\t" +- +- : +- : +- "r" (i), // 0 +- "r" (n), // 1 +- "r" (x1), // 2 +- "r" (svec), // 3 +- "r" (pre), // 4 +- "r" (o16), // 5 +- "r" (o32), // 6 +- "r" (o48), // 7 +- "r" (o64), // 8 +- "r" (o80), // 9 +- "r" (o96), // 10 +- "r" (o112) // 11 +- : "cr0", "%0", "%2", "memory" +- ); +- +-} +- +- ++ float sum; ++ __vector float t0; ++ __vector float t1; ++ __vector float t2; ++ __vector float t3; ++ ++ __asm__ ++ ( ++ "dcbt 0, %2 \n\t" ++ ++ "xxlxor 32, 32, 32 \n\t" ++ "xxlxor 33, 33, 33 \n\t" ++ "xxlxor 34, 34, 34 \n\t" ++ "xxlxor 35, 35, 35 \n\t" ++ "xxlxor 36, 36, 36 \n\t" ++ "xxlxor 37, 37, 37 \n\t" ++ "xxlxor 38, 38, 38 \n\t" ++ "xxlxor 39, 39, 39 \n\t" ++ ++ "lxvw4x 40, 0, %2 \n\t" ++ "lxvw4x 41, %8, %2 \n\t" ++ "lxvw4x 42, %9, %2 \n\t" ++ "lxvw4x 43, %10, %2 \n\t" ++ "lxvw4x 44, %11, %2 \n\t" ++ "lxvw4x 45, %12, %2 \n\t" ++ "lxvw4x 46, %13, %2 \n\t" ++ "lxvw4x 47, %14, %2 \n\t" ++ ++ "addi %2, %2, 128 \n\t" ++ ++ "addic. %1, %1, -32 \n\t" ++ "ble 2f \n\t" ++ ++ ".p2align 5 \n" ++ "1: \n\t" ++ ++ "xvabssp 48, 40 \n\t" ++ "xvabssp 49, 41 \n\t" ++ "xvabssp 50, 42 \n\t" ++ "xvabssp 51, 43 \n\t" ++ ++ "lxvw4x 40, 0, %2 \n\t" ++ "lxvw4x 41, %8, %2 \n\t" ++ ++ "xvabssp %x3, 44 \n\t" ++ "xvabssp %x4, 45 \n\t" ++ ++ "lxvw4x 42, %9, %2 \n\t" ++ "lxvw4x 43, %10, %2 \n\t" ++ ++ "xvabssp %x5, 46 \n\t" ++ "xvabssp %x6, 47 \n\t" ++ ++ "lxvw4x 44, %11, %2 \n\t" ++ "lxvw4x 45, %12, %2 \n\t" ++ ++ "xvaddsp 32, 32, 48 \n\t" ++ "xvaddsp 33, 33, 49 \n\t" ++ ++ "lxvw4x 46, %13, %2 \n\t" ++ "lxvw4x 47, %14, %2 \n\t" ++ ++ "xvaddsp 34, 34, 50 \n\t" ++ "xvaddsp 35, 35, 51 \n\t" ++ "addi %2, %2, 128 \n\t" ++ "xvaddsp 36, 36, %x3 \n\t" ++ "xvaddsp 37, 37, %x4 \n\t" ++ "addic. %1, %1, -32 \n\t" ++ "xvaddsp 38, 38, %x5 \n\t" ++ "xvaddsp 39, 39, %x6 \n\t" ++ ++ "bgt 1b \n" ++ ++ "2: \n\t" ++ ++ "xvabssp 48, 40 \n\t" ++ "xvabssp 49, 41 \n\t" ++ "xvabssp 50, 42 \n\t" ++ "xvabssp 51, 43 \n\t" ++ "xvabssp %x3, 44 \n\t" ++ "xvabssp %x4, 45 \n\t" ++ "xvabssp %x5, 46 \n\t" ++ "xvabssp %x6, 47 \n\t" ++ ++ "xvaddsp 32, 32, 48 \n\t" ++ "xvaddsp 33, 33, 49 \n\t" ++ "xvaddsp 34, 34, 50 \n\t" ++ "xvaddsp 35, 35, 51 \n\t" ++ "xvaddsp 36, 36, %x3 \n\t" ++ "xvaddsp 37, 37, %x4 \n\t" ++ "xvaddsp 38, 38, %x5 \n\t" ++ "xvaddsp 39, 39, %x6 \n\t" ++ ++ "xvaddsp 32, 32, 33 \n\t" ++ "xvaddsp 34, 34, 35 \n\t" ++ "xvaddsp 36, 36, 37 \n\t" ++ "xvaddsp 38, 38, 39 \n\t" ++ ++ "xvaddsp 32, 32, 34 \n\t" ++ "xvaddsp 36, 36, 38 \n\t" ++ ++ "xvaddsp 32, 32, 36 \n\t" ++ ++ "xxsldwi 33, 32, 32, 2 \n\t" ++ "xvaddsp 32, 32, 33 \n\t" ++ ++ "xxsldwi 33, 32, 32, 1 \n\t" ++ "xvaddsp 32, 32, 33 \n\t" ++ ++ "xscvspdp %0, 32 \n" ++ ++ "#n=%1 x=%3=%2 sum=%0 o16=%8 o32=%9 o48=%10 o64=%11 o80=%12 o96=%13 o112=%14\n" ++ "#t0=%x3 t1=%x4 t2=%x5 t3=%x6" ++ : ++ "=f" (sum), // 0 ++ "+r" (n), // 1 ++ "+b" (x), // 2 ++ "=wa" (t0), // 3 ++ "=wa" (t1), // 4 ++ "=wa" (t2), // 5 ++ "=wa" (t3) // 6 ++ : ++ "m" (*x), ++ "b" (16), // 8 ++ "b" (32), // 9 ++ "b" (48), // 10 ++ "b" (64), // 11 ++ "b" (80), // 12 ++ "b" (96), // 13 ++ "b" (112) // 14 ++ : ++ "cr0", ++ "vs32","vs33","vs34","vs35","vs36","vs37","vs38","vs39", ++ "vs40","vs41","vs42","vs43","vs44","vs45","vs46","vs47", ++ "vs48","vs49","vs50","vs51" ++ ); ++ ++ return sum; ++} +diff --git a/kernel/power/scopy_microk_power8.c b/kernel/power/scopy_microk_power8.c +index 2e08e35..444a6d4 100644 +--- a/kernel/power/scopy_microk_power8.c ++++ b/kernel/power/scopy_microk_power8.c +@@ -35,97 +35,78 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + #define HAVE_KERNEL_32 1 + +-static void scopy_kernel_32( BLASLONG n, FLOAT *x, FLOAT *y) __attribute__ ((noinline)); +- +-static void scopy_kernel_32( BLASLONG n, FLOAT *x, FLOAT *y) ++static void scopy_kernel_32 (long n, float *x, float *y) + { +- +- +- BLASLONG i = n; +- BLASLONG o16 = 16; +- BLASLONG o32 = 32; +- BLASLONG o48 = 48; +- BLASLONG o64 = 64; +- BLASLONG o80 = 80; +- BLASLONG o96 = 96; +- BLASLONG o112 = 112; +- FLOAT *x1=x; +- FLOAT *y1=y; +- BLASLONG pre = 384; +- BLASLONG alpha=0; +- +- __asm__ __volatile__ +- ( +- +- "lxvw4x 40, 0, %2 \n\t" +- "lxvw4x 41, %5, %2 \n\t" +- "lxvw4x 42, %6, %2 \n\t" +- "lxvw4x 43, %7, %2 \n\t" +- "lxvw4x 44, %8, %2 \n\t" +- "lxvw4x 45, %9, %2 \n\t" +- "lxvw4x 46, %10, %2 \n\t" +- "lxvw4x 47, %11, %2 \n\t" +- +- "addi %2, %2, 128 \n\t" +- +- "addic. %0 , %0 , -32 \n\t" +- "ble 2f \n\t" +- +- ".align 5 \n\t" +- "1: \n\t" +- +- "stxvw4x 40, 0, %1 \n\t" +- "stxvw4x 41, %5, %1 \n\t" +- "lxvw4x 40, 0, %2 \n\t" +- "lxvw4x 41, %5, %2 \n\t" +- "stxvw4x 42, %6, %1 \n\t" +- "stxvw4x 43, %7, %1 \n\t" +- "lxvw4x 42, %6, %2 \n\t" +- "lxvw4x 43, %7, %2 \n\t" +- "stxvw4x 44, %8, %1 \n\t" +- "stxvw4x 45, %9, %1 \n\t" +- "lxvw4x 44, %8, %2 \n\t" +- "lxvw4x 45, %9, %2 \n\t" +- "stxvw4x 46, %10, %1 \n\t" +- "stxvw4x 47, %11, %1 \n\t" +- "lxvw4x 46, %10, %2 \n\t" +- "lxvw4x 47, %11, %2 \n\t" +- +- +- "addi %1, %1, 128 \n\t" +- "addi %2, %2, 128 \n\t" +- +- "addic. %0 , %0 , -32 \n\t" +- "bgt 1b \n\t" +- +- "2: \n\t" +- +- "stxvw4x 40, 0, %1 \n\t" +- "stxvw4x 41, %5, %1 \n\t" +- "stxvw4x 42, %6, %1 \n\t" +- "stxvw4x 43, %7, %1 \n\t" +- "stxvw4x 44, %8, %1 \n\t" +- "stxvw4x 45, %9, %1 \n\t" +- "stxvw4x 46, %10, %1 \n\t" +- "stxvw4x 47, %11, %1 \n\t" +- +- : +- : +- "r" (i), // 0 +- "r" (y1), // 1 +- "r" (x1), // 2 +- "r" (alpha), // 3 +- "r" (pre), // 4 +- "r" (o16), // 5 +- "r" (o32), // 6 +- "r" (o48), // 7 +- "r" (o64), // 8 +- "r" (o80), // 9 +- "r" (o96), // 10 +- "r" (o112) // 11 +- : "cr0", "%0", "%2" , "%1", "memory" +- ); +- +-} +- +- ++ __asm__ ++ ( ++ "lxvw4x 40, 0, %2 \n\t" ++ "lxvw4x 41, %5, %2 \n\t" ++ "lxvw4x 42, %6, %2 \n\t" ++ "lxvw4x 43, %7, %2 \n\t" ++ "lxvw4x 44, %8, %2 \n\t" ++ "lxvw4x 45, %9, %2 \n\t" ++ "lxvw4x 46, %10, %2 \n\t" ++ "lxvw4x 47, %11, %2 \n\t" ++ ++ "addi %2, %2, 128 \n\t" ++ ++ "addic. %1, %1, -32 \n\t" ++ "ble 2f \n\t" ++ ++ ".p2align 5 \n" ++ "1: \n\t" ++ ++ "stxvw4x 40, 0, %3 \n\t" ++ "stxvw4x 41, %5, %3 \n\t" ++ "lxvw4x 40, 0, %2 \n\t" ++ "lxvw4x 41, %5, %2 \n\t" ++ "stxvw4x 42, %6, %3 \n\t" ++ "stxvw4x 43, %7, %3 \n\t" ++ "lxvw4x 42, %6, %2 \n\t" ++ "lxvw4x 43, %7, %2 \n\t" ++ "stxvw4x 44, %8, %3 \n\t" ++ "stxvw4x 45, %9, %3 \n\t" ++ "lxvw4x 44, %8, %2 \n\t" ++ "lxvw4x 45, %9, %2 \n\t" ++ "stxvw4x 46, %10, %3 \n\t" ++ "stxvw4x 47, %11, %3 \n\t" ++ "lxvw4x 46, %10, %2 \n\t" ++ "lxvw4x 47, %11, %2 \n\t" ++ ++ "addi %3, %3, 128 \n\t" ++ "addi %2, %2, 128 \n\t" ++ ++ "addic. %1, %1, -32 \n\t" ++ "bgt 1b \n" ++ ++ "2: \n\t" ++ ++ "stxvw4x 40, 0, %3 \n\t" ++ "stxvw4x 41, %5, %3 \n\t" ++ "stxvw4x 42, %6, %3 \n\t" ++ "stxvw4x 43, %7, %3 \n\t" ++ "stxvw4x 44, %8, %3 \n\t" ++ "stxvw4x 45, %9, %3 \n\t" ++ "stxvw4x 46, %10, %3 \n\t" ++ "stxvw4x 47, %11, %3 \n" ++ ++ "#n=%1 x=%4=%2 y=%0=%3 o16=%5 o32=%6 o48=%7 o64=%8 o80=%9 o96=%10 o112=%11" ++ : ++ "=m" (*y), ++ "+r" (n), // 1 ++ "+b" (x), // 2 ++ "+b" (y) // 3 ++ : ++ "m" (*x), ++ "b" (16), // 5 ++ "b" (32), // 6 ++ "b" (48), // 7 ++ "b" (64), // 8 ++ "b" (80), // 9 ++ "b" (96), // 10 ++ "b" (112) // 11 ++ : ++ "cr0", ++ "vs40","vs41","vs42","vs43","vs44","vs45","vs46","vs47" ++ ); ++} +diff --git a/kernel/power/sdot.c b/kernel/power/sdot.c +index 52fb1fe..31f4734 100644 +--- a/kernel/power/sdot.c ++++ b/kernel/power/sdot.c +@@ -42,7 +42,7 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + #ifndef HAVE_KERNEL_16 + +-static void sdot_kernel_16(BLASLONG n, FLOAT *x, FLOAT *y, FLOAT *d) ++static FLOAT sdot_kernel_16(BLASLONG n, FLOAT *x, FLOAT *y) + { + BLASLONG register i = 0; + FLOAT dot = 0.0; +@@ -61,8 +61,7 @@ static void sdot_kernel_16(BLASLONG n, FLOAT *x, FLOAT *y, FLOAT *d) + i+=8 ; + + } +- *d += dot; +- ++ return dot; + } + + #endif +@@ -82,8 +81,7 @@ FLOAT CNAME(BLASLONG n, FLOAT *x, BLASLONG inc_x, FLOAT *y, BLASLONG inc_y) + BLASLONG n1 = n & -32; + + if ( n1 ) +- sdot_kernel_16(n1, x, y , &dot ); +- ++ dot = sdot_kernel_16(n1, x, y); + + i = n1; + while(i < n) +diff --git a/kernel/power/sdot_microk_power8.c b/kernel/power/sdot_microk_power8.c +index 6dd588a..7f7ccfa 100644 +--- a/kernel/power/sdot_microk_power8.c ++++ b/kernel/power/sdot_microk_power8.c +@@ -34,146 +34,142 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + **************************************************************************************/ + + #define HAVE_KERNEL_16 1 +-static void sdot_kernel_16( BLASLONG n, FLOAT *x, FLOAT *y , FLOAT *dot) __attribute__ ((noinline)); + +-static void sdot_kernel_16( BLASLONG n, FLOAT *x, FLOAT *y, FLOAT *dot) ++static float sdot_kernel_16 (long n, float *x, float *y) + { +- +- +- BLASLONG i = n; +- BLASLONG o16 = 16; +- BLASLONG o32 = 32; +- BLASLONG o48 = 48; +- BLASLONG o64 = 64; +- BLASLONG o80 = 80; +- BLASLONG o96 = 96; +- BLASLONG o112 = 112; +- FLOAT *x1=x; +- FLOAT *y1=y; +- BLASLONG pre = 384; +- FLOAT tempdot[4]; +- +- +- __asm__ __volatile__ +- ( +- "xxlxor 32,32,32 \n\t" +- "xxlxor 33,33,33 \n\t" +- "xxlxor 34,34,34 \n\t" +- "xxlxor 35,35,35 \n\t" +- "xxlxor 36,36,36 \n\t" +- "xxlxor 37,37,37 \n\t" +- "xxlxor 38,38,38 \n\t" +- "xxlxor 39,39,39 \n\t" +- +- "dcbt %2, %12 \n\t" +- "dcbt %3, %12 \n\t" +- +- "lxvw4x 40, 0, %2 \n\t" +- "lxvw4x 48, 0, %3 \n\t" +- "lxvw4x 41, %5, %2 \n\t" +- "lxvw4x 49, %5, %3 \n\t" +- "lxvw4x 42, %6, %2 \n\t" +- "lxvw4x 50, %6, %3 \n\t" +- "lxvw4x 43, %7, %2 \n\t" +- "lxvw4x 51, %7, %3 \n\t" +- "lxvw4x 44, %8, %2 \n\t" +- "lxvw4x 52, %8, %3 \n\t" +- "lxvw4x 45, %9, %2 \n\t" +- "lxvw4x 53, %9, %3 \n\t" +- "lxvw4x 46, %10, %2 \n\t" +- "lxvw4x 54, %10, %3 \n\t" +- "lxvw4x 47, %11, %2 \n\t" +- "lxvw4x 55, %11, %3 \n\t" +- +- "addi %2, %2, 128 \n\t" +- "addi %3, %3, 128 \n\t" +- +- "addic. %0 , %0 , -32 \n\t" +- "ble 2f \n\t" +- +- ".align 5 \n\t" +- "1: \n\t" +- +- "dcbt %2, %12 \n\t" +- "dcbt %3, %12 \n\t" +- +- "xvmaddasp 32, 40, 48 \n\t" +- "lxvw4x 40, 0, %2 \n\t" +- "lxvw4x 48, 0, %3 \n\t" +- "xvmaddasp 33, 41, 49 \n\t" +- "lxvw4x 41, %5, %2 \n\t" +- "lxvw4x 49, %5, %3 \n\t" +- "xvmaddasp 34, 42, 50 \n\t" +- "lxvw4x 42, %6, %2 \n\t" +- "lxvw4x 50, %6, %3 \n\t" +- "xvmaddasp 35, 43, 51 \n\t" +- "lxvw4x 43, %7, %2 \n\t" +- "lxvw4x 51, %7, %3 \n\t" +- "xvmaddasp 36, 44, 52 \n\t" +- "lxvw4x 44, %8, %2 \n\t" +- "lxvw4x 52, %8, %3 \n\t" +- "xvmaddasp 37, 45, 53 \n\t" +- "lxvw4x 45, %9, %2 \n\t" +- "lxvw4x 53, %9, %3 \n\t" +- "xvmaddasp 38, 46, 54 \n\t" +- "lxvw4x 46, %10, %2 \n\t" +- "lxvw4x 54, %10, %3 \n\t" +- "xvmaddasp 39, 47, 55 \n\t" +- +- "lxvw4x 47, %11, %2 \n\t" +- "lxvw4x 55, %11, %3 \n\t" +- +- +- "addi %2, %2, 128 \n\t" +- "addi %3, %3, 128 \n\t" +- +- "addic. %0 , %0 , -32 \n\t" +- "bgt 1b \n\t" +- +- "2: \n\t" +- +- "xvmaddasp 32, 40, 48 \n\t" +- "xvmaddasp 33, 41, 49 \n\t" +- "xvmaddasp 34, 42, 50 \n\t" +- "xvmaddasp 35, 43, 51 \n\t" +- "xvmaddasp 36, 44, 52 \n\t" +- "xvmaddasp 37, 45, 53 \n\t" +- "xvmaddasp 38, 46, 54 \n\t" +- "xvmaddasp 39, 47, 55 \n\t" +- +- "xvaddsp 32, 32 , 33 \n\t" +- "xvaddsp 34, 34 , 35 \n\t" +- "xvaddsp 36, 36 , 37 \n\t" +- "xvaddsp 38, 38 , 39 \n\t" +- +- "xvaddsp 32, 32 , 34 \n\t" +- "xvaddsp 36, 36 , 38 \n\t" +- +- "xvaddsp 32, 32 , 36 \n\t" +- +- "stxvw4x 32, 0 , %4 \n\t" +- +- : +- : +- "r" (i), // 0 +- "r" (n), // 1 +- "r" (x1), // 2 +- "r" (y1), // 3 +- "r" (tempdot), // 4 +- "r" (o16), // 5 +- "r" (o32), // 6 +- "r" (o48), // 7 +- "r" (o64), // 8 +- "r" (o80), // 9 +- "r" (o96), // 10 +- "r" (o112), // 11 +- "r" (pre) // 12 +- : "cr0", "%0", "%2" , "%3", "memory" +- ); +- +- *dot = tempdot[0] + tempdot[1] + tempdot[2] + tempdot[3]; +- +- +-} +- +- ++ float dot; ++ __vector float t0; ++ __vector float t1; ++ __vector float t2; ++ __vector float t3; ++ ++ __asm__ ++ ( ++ "dcbt 0, %2 \n\t" ++ "dcbt 0, %3 \n\t" ++ ++ "xxlxor 32, 32, 32 \n\t" ++ "xxlxor 33, 33, 33 \n\t" ++ "xxlxor 34, 34, 34 \n\t" ++ "xxlxor 35, 35, 35 \n\t" ++ "xxlxor 36, 36, 36 \n\t" ++ "xxlxor 37, 37, 37 \n\t" ++ "xxlxor 38, 38, 38 \n\t" ++ "xxlxor 39, 39, 39 \n\t" ++ ++ "lxvw4x 40, 0, %2 \n\t" ++ "lxvw4x 48, 0, %3 \n\t" ++ "lxvw4x 41, %10, %2 \n\t" ++ "lxvw4x 49, %10, %3 \n\t" ++ "lxvw4x 42, %11, %2 \n\t" ++ "lxvw4x 50, %11, %3 \n\t" ++ "lxvw4x 43, %12, %2 \n\t" ++ "lxvw4x 51, %12, %3 \n\t" ++ "lxvw4x 44, %13, %2 \n\t" ++ "lxvw4x %x4, %13, %3 \n\t" ++ "lxvw4x 45, %14, %2 \n\t" ++ "lxvw4x %x5, %14, %3 \n\t" ++ "lxvw4x 46, %15, %2 \n\t" ++ "lxvw4x %x6, %15, %3 \n\t" ++ "lxvw4x 47, %16, %2 \n\t" ++ "lxvw4x %x7, %16, %3 \n\t" ++ ++ "addi %2, %2, 128 \n\t" ++ "addi %3, %3, 128 \n\t" ++ ++ "addic. %1, %1, -32 \n\t" ++ "ble 2f \n\t" ++ ++ ".p2align 5 \n" ++ "1: \n\t" ++ ++ "xvmaddasp 32, 40, 48 \n\t" ++ "lxvw4x 40, 0, %2 \n\t" ++ "lxvw4x 48, 0, %3 \n\t" ++ "xvmaddasp 33, 41, 49 \n\t" ++ "lxvw4x 41, %10, %2 \n\t" ++ "lxvw4x 49, %10, %3 \n\t" ++ "xvmaddasp 34, 42, 50 \n\t" ++ "lxvw4x 42, %11, %2 \n\t" ++ "lxvw4x 50, %11, %3 \n\t" ++ "xvmaddasp 35, 43, 51 \n\t" ++ "lxvw4x 43, %12, %2 \n\t" ++ "lxvw4x 51, %12, %3 \n\t" ++ "xvmaddasp 36, 44, %x4 \n\t" ++ "lxvw4x 44, %13, %2 \n\t" ++ "lxvw4x %x4, %13, %3 \n\t" ++ "xvmaddasp 37, 45, %x5 \n\t" ++ "lxvw4x 45, %14, %2 \n\t" ++ "lxvw4x %x5, %14, %3 \n\t" ++ "xvmaddasp 38, 46, %x6 \n\t" ++ "lxvw4x 46, %15, %2 \n\t" ++ "lxvw4x %x6, %15, %3 \n\t" ++ "xvmaddasp 39, 47, %x7 \n\t" ++ "lxvw4x 47, %16, %2 \n\t" ++ "lxvw4x %x7, %16, %3 \n\t" ++ ++ "addi %2, %2, 128 \n\t" ++ "addi %3, %3, 128 \n\t" ++ ++ "addic. %1, %1, -32 \n\t" ++ "bgt 1b \n" ++ ++ "2: \n\t" ++ ++ "xvmaddasp 32, 40, 48 \n\t" ++ "xvmaddasp 33, 41, 49 \n\t" ++ "xvmaddasp 34, 42, 50 \n\t" ++ "xvmaddasp 35, 43, 51 \n\t" ++ "xvmaddasp 36, 44, %x4 \n\t" ++ "xvmaddasp 37, 45, %x5 \n\t" ++ "xvmaddasp 38, 46, %x6 \n\t" ++ "xvmaddasp 39, 47, %x7 \n\t" ++ ++ "xvaddsp 32, 32, 33 \n\t" ++ "xvaddsp 34, 34, 35 \n\t" ++ "xvaddsp 36, 36, 37 \n\t" ++ "xvaddsp 38, 38, 39 \n\t" ++ ++ "xvaddsp 32, 32, 34 \n\t" ++ "xvaddsp 36, 36, 38 \n\t" ++ ++ "xvaddsp 32, 32, 36 \n\t" ++ ++ "xxsldwi 33, 32, 32, 2 \n\t" ++ "xvaddsp 32, 32, 33 \n\t" ++ ++ "xxsldwi 33, 32, 32, 1 \n\t" ++ "xvaddsp 32, 32, 33 \n\t" ++ ++ "xscvspdp %x0, 32 \n" ++ ++ "#dot=%0 n=%1 x=%8=%2 y=%9=%3 o16=%10 o32=%11 o48=%12 o64=%13 o80=%14 o96=%15 o122=%16\n" ++ "#t0=%x4 t1=%x5 t2=%x6 t3=%x7" ++ : ++ "=f" (dot), // 0 ++ "+r" (n), // 1 ++ "+b" (x), // 2 ++ "+b" (y), // 3 ++ "=wa" (t0), // 4 ++ "=wa" (t1), // 5 ++ "=wa" (t2), // 6 ++ "=wa" (t3) // 7 ++ : ++ "m" (*x), ++ "m" (*y), ++ "b" (16), // 10 ++ "b" (32), // 11 ++ "b" (48), // 12 ++ "b" (64), // 13 ++ "b" (80), // 14 ++ "b" (96), // 15 ++ "b" (112) // 16 ++ : ++ "cr0", ++ "vs32","vs33","vs34","vs35","vs36","vs37","vs38","vs39", ++ "vs40","vs41","vs42","vs43","vs44","vs45","vs46","vs47", ++ "vs48","vs49","vs50","vs51" ++ ); ++ ++ return dot; ++} +diff --git a/kernel/power/srot.c b/kernel/power/srot.c +index d464846..d2910ff 100644 +--- a/kernel/power/srot.c ++++ b/kernel/power/srot.c +@@ -46,7 +46,7 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + #ifndef HAVE_KERNEL_16 + +-static void srot_kernel_16(BLASLONG n, FLOAT *x, FLOAT *y, FLOAT *c, FLOAT *s) ++static void srot_kernel_16(BLASLONG n, FLOAT *x, FLOAT *y, FLOAT c, FLOAT s) + { + + BLASLONG i=0; +@@ -56,8 +56,6 @@ static void srot_kernel_16(BLASLONG n, FLOAT *x, FLOAT *y, FLOAT *c, FLOAT *s) + FLOAT y00, y01, y02, y03; + FLOAT *x1=x; + FLOAT *y1=y; +- FLOAT c1=*c; +- FLOAT s1=*s; + + while ( i 0 ) + { +- c1[0]=c; +- c1[1]=c; +- c1[2]=c; +- c1[3]=c; +- s1[0]=s; +- s1[1]=s; +- s1[2]=s; +- s1[3]=s; +- srot_kernel_16(n1, x1, y1, c1, s1); ++ srot_kernel_16(n1, x1, y1, c, s); + i=n1; + } + +diff --git a/kernel/power/srot_microk_power8.c b/kernel/power/srot_microk_power8.c +index ade6550..0a18c16 100644 +--- a/kernel/power/srot_microk_power8.c ++++ b/kernel/power/srot_microk_power8.c +@@ -38,171 +38,179 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + #define HAVE_KERNEL_16 1 + +-static void srot_kernel_16( BLASLONG n, FLOAT *x, FLOAT *y, FLOAT *c, FLOAT *s) __attribute__ ((noinline)); +- +-static void srot_kernel_16( BLASLONG n, FLOAT *x, FLOAT *y, FLOAT *c, FLOAT *s) ++static void srot_kernel_16 (long n, float *x, float *y, float c, float s) + { ++ __vector float t0; ++ __vector float t1; ++ __vector float t2; ++ __vector float t3; ++ __vector float t4; ++ __vector float t5; ++ __vector float t6; ++ __vector float t7; + ++ __asm__ ++ ( ++ "xscvdpspn 36, %x13 \n\t" // load c to all words ++ "xxspltw 36, 36, 0 \n\t" + +- BLASLONG i = n; +- BLASLONG o16 = 16; +- BLASLONG o32 = 32; +- BLASLONG o48 = 48; +- FLOAT *x1=x; +- FLOAT *y1=y; +- FLOAT *x2=x+1; +- FLOAT *y2=y+1; +- +- __asm__ __volatile__ +- ( +- +- "lxvw4x 36 , 0, %3 \n\t" // load c +- "lxvw4x 37 , 0, %4 \n\t" // load s +- "addi %8 , %8, -4 \n\t" +- "addi %9 , %9, -4 \n\t" +- +- "lxvw4x 32, 0, %1 \n\t" // load x +- "lxvw4x 33, %5, %1 \n\t" +- "lxvw4x 34, %6, %1 \n\t" +- "lxvw4x 35, %7, %1 \n\t" +- +- "lxvw4x 40, 0, %2 \n\t" // load y +- "lxvw4x 41, %5, %2 \n\t" +- "lxvw4x 42, %6, %2 \n\t" +- "lxvw4x 43, %7, %2 \n\t" +- +- "addi %1, %1, 64 \n\t" +- "addi %2, %2, 64 \n\t" +- +- "addic. %0 , %0 , -16 \n\t" +- "ble 2f \n\t" +- +- ".align 5 \n\t" +- "1: \n\t" +- +- "xvmulsp 48, 32, 36 \n\t" // c * x +- "xvmulsp 49, 33, 36 \n\t" +- "xvmulsp 50, 34, 36 \n\t" +- "xvmulsp 51, 35, 36 \n\t" +- +- "xvmulsp 56, 40, 36 \n\t" // c * y +- "xvmulsp 57, 41, 36 \n\t" +- "xvmulsp 58, 42, 36 \n\t" +- "xvmulsp 59, 43, 36 \n\t" +- +- "xvmulsp 52, 32, 37 \n\t" // s * x +- "xvmulsp 53, 33, 37 \n\t" +- +- "lxvw4x 32, 0, %1 \n\t" // load x +- "lxvw4x 33, %5, %1 \n\t" +- +- "xvmulsp 54, 34, 37 \n\t" +- "xvmulsp 55, 35, 37 \n\t" +- +- "lxvw4x 34, %6, %1 \n\t" +- "lxvw4x 35, %7, %1 \n\t" +- +- "xvmulsp 60, 40, 37 \n\t" // s * y +- "xvmulsp 61, 41, 37 \n\t" +- +- "lxvw4x 40, 0, %2 \n\t" // load y +- "lxvw4x 41, %5, %2 \n\t" +- +- "xvmulsp 62, 42, 37 \n\t" +- "xvmulsp 63, 43, 37 \n\t" +- +- "lxvw4x 42, %6, %2 \n\t" +- "lxvw4x 43, %7, %2 \n\t" +- +- "xvaddsp 48, 48 , 60 \n\t" // c * x + s * y +- "xvaddsp 49, 49 , 61 \n\t" // c * x + s * y +- +- "addi %1, %1, 64 \n\t" +- "addi %2, %2, 64 \n\t" +- +- "xvaddsp 50, 50 , 62 \n\t" // c * x + s * y +- "xvaddsp 51, 51 , 63 \n\t" // c * x + s * y +- +- "xvsubsp 56, 56 , 52 \n\t" // c * y - s * x +- "xvsubsp 57, 57 , 53 \n\t" // c * y - s * x +- "xvsubsp 58, 58 , 54 \n\t" // c * y - s * x +- "xvsubsp 59, 59 , 55 \n\t" // c * y - s * x +- +- "stxvw4x 48, 0, %8 \n\t" // store x +- "stxvw4x 49, %5, %8 \n\t" +- "stxvw4x 50, %6, %8 \n\t" +- "stxvw4x 51, %7, %8 \n\t" +- +- "stxvw4x 56, 0, %9 \n\t" // store y +- "stxvw4x 57, %5, %9 \n\t" +- "stxvw4x 58, %6, %9 \n\t" +- "stxvw4x 59, %7, %9 \n\t" +- +- "addi %8, %8, 64 \n\t" +- "addi %9, %9, 64 \n\t" +- +- "addic. %0 , %0 , -16 \n\t" +- "bgt 1b \n\t" +- +- "2: \n\t" +- +- "xvmulsp 48, 32, 36 \n\t" // c * x +- "xvmulsp 49, 33, 36 \n\t" +- "xvmulsp 50, 34, 36 \n\t" +- "xvmulsp 51, 35, 36 \n\t" +- +- "xvmulsp 56, 40, 36 \n\t" // c * y +- "xvmulsp 57, 41, 36 \n\t" +- "xvmulsp 58, 42, 36 \n\t" +- "xvmulsp 59, 43, 36 \n\t" +- +- "xvmulsp 52, 32, 37 \n\t" // s * x +- "xvmulsp 53, 33, 37 \n\t" +- "xvmulsp 54, 34, 37 \n\t" +- "xvmulsp 55, 35, 37 \n\t" +- +- "xvmulsp 60, 40, 37 \n\t" // s * y +- "xvmulsp 61, 41, 37 \n\t" +- "xvmulsp 62, 42, 37 \n\t" +- "xvmulsp 63, 43, 37 \n\t" +- +- "xvaddsp 48, 48 , 60 \n\t" // c * x + s * y +- "xvaddsp 49, 49 , 61 \n\t" // c * x + s * y +- "xvaddsp 50, 50 , 62 \n\t" // c * x + s * y +- "xvaddsp 51, 51 , 63 \n\t" // c * x + s * y +- +- "xvsubsp 56, 56 , 52 \n\t" // c * y - s * x +- "xvsubsp 57, 57 , 53 \n\t" // c * y - s * x +- "xvsubsp 58, 58 , 54 \n\t" // c * y - s * x +- "xvsubsp 59, 59 , 55 \n\t" // c * y - s * x ++ "xscvdpspn 37, %x14 \n\t" // load s to all words ++ "xxspltw 37, 37, 0 \n\t" + +- "stxvw4x 48, 0, %8 \n\t" // store x +- "stxvw4x 49, %5, %8 \n\t" +- "stxvw4x 50, %6, %8 \n\t" +- "stxvw4x 51, %7, %8 \n\t" ++ "lxvw4x 32, 0, %3 \n\t" // load x ++ "lxvw4x 33, %15, %3 \n\t" ++ "lxvw4x 34, %16, %3 \n\t" ++ "lxvw4x 35, %17, %3 \n\t" + +- "stxvw4x 56, 0, %9 \n\t" // store y +- "stxvw4x 57, %5, %9 \n\t" +- "stxvw4x 58, %6, %9 \n\t" +- "stxvw4x 59, %7, %9 \n\t" ++ "lxvw4x 48, 0, %4 \n\t" // load y ++ "lxvw4x 49, %15, %4 \n\t" ++ "lxvw4x 50, %16, %4 \n\t" ++ "lxvw4x 51, %17, %4 \n\t" + ++ "addi %3, %3, 64 \n\t" ++ "addi %4, %4, 64 \n\t" + ++ "addic. %2, %2, -16 \n\t" ++ "ble 2f \n\t" + +- : +- : +- "r" (i), // 0 +- "r" (x1), // 1 +- "r" (y1), // 2 +- "r" (c), // 3 +- "r" (s), // 4 +- "r" (o16), // 5 +- "r" (o32), // 6 +- "r" (o48), // 7 +- "r" (x2), // 8 +- "r" (y2) // 9 +- : "cr0", "%0", "%1" , "%2", "%8", "%9", "memory" +- ); ++ ".p2align 5 \n" ++ "1: \n\t" + +-} ++ "xvmulsp 40, 32, 36 \n\t" // c * x ++ "xvmulsp 41, 33, 36 \n\t" ++ "xvmulsp 42, 34, 36 \n\t" ++ "xvmulsp 43, 35, 36 \n\t" + ++ "xvmulsp %x5, 48, 36 \n\t" // c * y ++ "xvmulsp %x6, 49, 36 \n\t" ++ "xvmulsp %x7, 50, 36 \n\t" ++ "xvmulsp %x8, 51, 36 \n\t" + ++ "xvmulsp 44, 32, 37 \n\t" // s * x ++ "xvmulsp 45, 33, 37 \n\t" ++ ++ "lxvw4x 32, 0, %3 \n\t" // load x ++ "lxvw4x 33, %15, %3 \n\t" ++ ++ "xvmulsp 46, 34, 37 \n\t" ++ "xvmulsp 47, 35, 37 \n\t" ++ ++ "lxvw4x 34, %16, %3 \n\t" ++ "lxvw4x 35, %17, %3 \n\t" ++ ++ "xvmulsp %x9, 48, 37 \n\t" // s * y ++ "xvmulsp %x10, 49, 37 \n\t" ++ ++ "lxvw4x 48, 0, %4 \n\t" // load y ++ "lxvw4x 49, %15, %4 \n\t" ++ ++ "xvmulsp %x11, 50, 37 \n\t" ++ "xvmulsp %x12, 51, 37 \n\t" ++ ++ "lxvw4x 50, %16, %4 \n\t" ++ "lxvw4x 51, %17, %4 \n\t" ++ ++ "xvaddsp 40, 40, %x9 \n\t" // c * x + s * y ++ "xvaddsp 41, 41, %x10 \n\t" // c * x + s * y ++ ++ "addi %3, %3, -64 \n\t" ++ "addi %4, %4, -64 \n\t" ++ ++ "xvaddsp 42, 42, %x11 \n\t" // c * x + s * y ++ "xvaddsp 43, 43, %x12 \n\t" // c * x + s * y ++ ++ "xvsubsp %x5, %x5, 44 \n\t" // c * y - s * x ++ "xvsubsp %x6, %x6, 45 \n\t" // c * y - s * x ++ "xvsubsp %x7, %x7, 46 \n\t" // c * y - s * x ++ "xvsubsp %x8, %x8, 47 \n\t" // c * y - s * x ++ ++ "stxvw4x 40, 0, %3 \n\t" // store x ++ "stxvw4x 41, %15, %3 \n\t" ++ "stxvw4x 42, %16, %3 \n\t" ++ "stxvw4x 43, %17, %3 \n\t" ++ ++ "stxvw4x %x5, 0, %4 \n\t" // store y ++ "stxvw4x %x6, %15, %4 \n\t" ++ "stxvw4x %x7, %16, %4 \n\t" ++ "stxvw4x %x8, %17, %4 \n\t" ++ ++ "addi %3, %3, 128 \n\t" ++ "addi %4, %4, 128 \n\t" ++ ++ "addic. %2, %2, -16 \n\t" ++ "bgt 1b \n" ++ ++ "2: \n\t" ++ ++ "xvmulsp 40, 32, 36 \n\t" // c * x ++ "xvmulsp 41, 33, 36 \n\t" ++ "xvmulsp 42, 34, 36 \n\t" ++ "xvmulsp 43, 35, 36 \n\t" ++ ++ "xvmulsp %x5, 48, 36 \n\t" // c * y ++ "xvmulsp %x6, 49, 36 \n\t" ++ "xvmulsp %x7, 50, 36 \n\t" ++ "xvmulsp %x8, 51, 36 \n\t" ++ ++ "xvmulsp 44, 32, 37 \n\t" // s * x ++ "xvmulsp 45, 33, 37 \n\t" ++ "xvmulsp 46, 34, 37 \n\t" ++ "xvmulsp 47, 35, 37 \n\t" ++ ++ "xvmulsp %x9, 48, 37 \n\t" // s * y ++ "xvmulsp %x10, 49, 37 \n\t" ++ "xvmulsp %x11, 50, 37 \n\t" ++ "xvmulsp %x12, 51, 37 \n\t" ++ ++ "addi %3, %3, -64 \n\t" ++ "addi %4, %4, -64 \n\t" ++ ++ "xvaddsp 40, 40, %x9 \n\t" // c * x + s * y ++ "xvaddsp 41, 41, %x10 \n\t" // c * x + s * y ++ "xvaddsp 42, 42, %x11 \n\t" // c * x + s * y ++ "xvaddsp 43, 43, %x12 \n\t" // c * x + s * y ++ ++ "xvsubsp %x5, %x5, 44 \n\t" // c * y - s * x ++ "xvsubsp %x6, %x6, 45 \n\t" // c * y - s * x ++ "xvsubsp %x7, %x7, 46 \n\t" // c * y - s * x ++ "xvsubsp %x8, %x8, 47 \n\t" // c * y - s * x ++ ++ "stxvw4x 40, 0, %3 \n\t" // store x ++ "stxvw4x 41, %15, %3 \n\t" ++ "stxvw4x 42, %16, %3 \n\t" ++ "stxvw4x 43, %17, %3 \n\t" ++ ++ "stxvw4x %x5, 0, %4 \n\t" // store y ++ "stxvw4x %x6, %15, %4 \n\t" ++ "stxvw4x %x7, %16, %4 \n\t" ++ "stxvw4x %x8, %17, %4 \n" ++ ++ "#n=%2 x=%0=%3 y=%1=%4 c=%13 s=%14 o16=%15 o32=%16 o48=%17\n" ++ "#t0=%x5 t1=%x6 t2=%x7 t3=%x8 t4=%x9 t5=%x10 t6=%x11 t7=%x12" ++ : ++ "+m" (*x), ++ "+m" (*y), ++ "+r" (n), // 2 ++ "+b" (x), // 3 ++ "+b" (y), // 4 ++ "=wa" (t0), // 5 ++ "=wa" (t1), // 6 ++ "=wa" (t2), // 7 ++ "=wa" (t3), // 8 ++ "=wa" (t4), // 9 ++ "=wa" (t5), // 10 ++ "=wa" (t6), // 11 ++ "=wa" (t7) // 12 ++ : ++ "f" (c), // 13 ++ "f" (s), // 14 ++ "b" (16), // 15 ++ "b" (32), // 16 ++ "b" (48) // 17 ++ : ++ "cr0", ++ "vs32","vs33","vs34","vs35","vs36","vs37", ++ "vs40","vs41","vs42","vs43","vs44","vs45","vs46","vs47", ++ "vs48","vs49","vs50","vs51" ++ ); ++} +diff --git a/kernel/power/sscal.c b/kernel/power/sscal.c +index c6ef5e9..bd5cdc4 100644 +--- a/kernel/power/sscal.c ++++ b/kernel/power/sscal.c +@@ -42,11 +42,10 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + #if !defined(HAVE_KERNEL_16) + +-static void sscal_kernel_16( BLASLONG n, FLOAT *da , FLOAT *x ) ++static void sscal_kernel_16 (BLASLONG n, FLOAT *x, FLOAT alpha) + { + + BLASLONG i; +- FLOAT alpha = *da; + + for( i=0; i 0 ) + { +- alpha[0]=da; +- alpha[1]=da; +- alpha[2]=da; +- alpha[3]=da; +- sscal_kernel_16_zero(n1 , alpha , x); ++ sscal_kernel_16_zero(n1, x); + j=n1; + } + +@@ -127,11 +121,7 @@ int CNAME(BLASLONG n, BLASLONG dummy0, BLASLONG dummy1, FLOAT da, FLOAT *x, BLAS + BLASLONG n1 = n & -32; + if ( n1 > 0 ) + { +- alpha[0]=da; +- alpha[1]=da; +- alpha[2]=da; +- alpha[3]=da; +- sscal_kernel_16(n1 , alpha , x); ++ sscal_kernel_16(n1, x, da); + j=n1; + } + while(j < n) +diff --git a/kernel/power/sscal_microk_power8.c b/kernel/power/sscal_microk_power8.c +index 963cec7..49862a3 100644 +--- a/kernel/power/sscal_microk_power8.c ++++ b/kernel/power/sscal_microk_power8.c +@@ -35,184 +35,150 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + #define HAVE_KERNEL_16 1 + +-static void sscal_kernel_16( BLASLONG n, FLOAT *alpha, FLOAT *x) __attribute__ ((noinline)); +- +-static void sscal_kernel_16( BLASLONG n, FLOAT *alpha, FLOAT *x) ++static void sscal_kernel_16 (long n, float *x, float alpha) + { +- +- +- BLASLONG i = n; +- BLASLONG o16 = 16; +- BLASLONG o32 = 32; +- BLASLONG o48 = 48; +- BLASLONG o64 = 64; +- BLASLONG o80 = 80; +- BLASLONG o96 = 96; +- BLASLONG o112 = 112; +- FLOAT *x1=x; +- FLOAT *x2=x+1; +- BLASLONG pre = 384; +- +- __asm__ __volatile__ +- ( +- +- "lxvw4x 32, 0, %3 \n\t" +- "addi %1, %1, -4 \n\t" +- +- "dcbt %2, %4 \n\t" +- +- "lxvw4x 40, 0, %2 \n\t" +- "lxvw4x 41, %5, %2 \n\t" +- "lxvw4x 42, %6, %2 \n\t" +- "lxvw4x 43, %7, %2 \n\t" +- "lxvw4x 44, %8, %2 \n\t" +- "lxvw4x 45, %9, %2 \n\t" +- "lxvw4x 46, %10, %2 \n\t" +- "lxvw4x 47, %11, %2 \n\t" +- +- "addi %2, %2, 128 \n\t" +- +- "addic. %0 , %0 , -32 \n\t" +- "ble 2f \n\t" +- +- ".align 5 \n\t" +- "1: \n\t" +- +- "dcbt %2, %4 \n\t" +- +- "xvmulsp 48, 40, 32 \n\t" +- "xvmulsp 49, 41, 32 \n\t" +- "lxvw4x 40, 0, %2 \n\t" +- "lxvw4x 41, %5, %2 \n\t" +- "xvmulsp 50, 42, 32 \n\t" +- "xvmulsp 51, 43, 32 \n\t" +- "lxvw4x 42, %6, %2 \n\t" +- "lxvw4x 43, %7, %2 \n\t" +- "xvmulsp 52, 44, 32 \n\t" +- "xvmulsp 53, 45, 32 \n\t" +- "lxvw4x 44, %8, %2 \n\t" +- "lxvw4x 45, %9, %2 \n\t" +- "xvmulsp 54, 46, 32 \n\t" +- "xvmulsp 55, 47, 32 \n\t" +- "lxvw4x 46, %10, %2 \n\t" +- "lxvw4x 47, %11, %2 \n\t" +- +- "stxvw4x 48, 0, %1 \n\t" +- "stxvw4x 49, %5, %1 \n\t" +- "stxvw4x 50, %6, %1 \n\t" +- "stxvw4x 51, %7, %1 \n\t" +- "stxvw4x 52, %8, %1 \n\t" +- "stxvw4x 53, %9, %1 \n\t" +- "stxvw4x 54, %10, %1 \n\t" +- "stxvw4x 55, %11, %1 \n\t" +- +- "addi %1, %1, 128 \n\t" +- "addi %2, %2, 128 \n\t" +- +- "addic. %0 , %0 , -32 \n\t" +- "bgt 1b \n\t" +- +- "2: \n\t" +- +- "xvmulsp 48, 40, 32 \n\t" +- "xvmulsp 49, 41, 32 \n\t" +- "xvmulsp 50, 42, 32 \n\t" +- "xvmulsp 51, 43, 32 \n\t" +- "xvmulsp 52, 44, 32 \n\t" +- "xvmulsp 53, 45, 32 \n\t" +- "xvmulsp 54, 46, 32 \n\t" +- "xvmulsp 55, 47, 32 \n\t" +- +- "stxvw4x 48, 0, %1 \n\t" +- "stxvw4x 49, %5, %1 \n\t" +- "stxvw4x 50, %6, %1 \n\t" +- "stxvw4x 51, %7, %1 \n\t" +- "stxvw4x 52, %8, %1 \n\t" +- "stxvw4x 53, %9, %1 \n\t" +- "stxvw4x 54, %10, %1 \n\t" +- "stxvw4x 55, %11, %1 \n\t" +- +- : +- : +- "r" (i), // 0 +- "r" (x2), // 1 +- "r" (x1), // 2 +- "r" (alpha), // 3 +- "r" (pre), // 4 +- "r" (o16), // 5 +- "r" (o32), // 6 +- "r" (o48), // 7 +- "r" (o64), // 8 +- "r" (o80), // 9 +- "r" (o96), // 10 +- "r" (o112) // 11 +- : "cr0", "%0", "%2" , "%1", "memory" +- ); +- +-} +- +- +-static void sscal_kernel_16_zero( BLASLONG n, FLOAT *alpha, FLOAT *x) __attribute__ ((noinline)); +- +-static void sscal_kernel_16_zero( BLASLONG n, FLOAT *alpha, FLOAT *x) ++ __asm__ ++ ( ++ "dcbt 0, %2 \n\t" ++ ++ "xscvdpspn %x3, %x3 \n\t" ++ "xxspltw %x3, %x3, 0 \n\t" ++ ++ "lxvw4x 32, 0, %2 \n\t" ++ "lxvw4x 33, %4, %2 \n\t" ++ "lxvw4x 34, %5, %2 \n\t" ++ "lxvw4x 35, %6, %2 \n\t" ++ "lxvw4x 36, %7, %2 \n\t" ++ "lxvw4x 37, %8, %2 \n\t" ++ "lxvw4x 38, %9, %2 \n\t" ++ "lxvw4x 39, %10, %2 \n\t" ++ ++ "addi %2, %2, 128 \n\t" ++ ++ "addic. %1, %1, -32 \n\t" ++ "ble 2f \n\t" ++ ++ ".p2align 5 \n" ++ "1: \n\t" ++ ++ "xvmulsp 40, 32, %x3 \n\t" ++ "xvmulsp 41, 33, %x3 \n\t" ++ "lxvw4x 32, 0, %2 \n\t" ++ "lxvw4x 33, %4, %2 \n\t" ++ "xvmulsp 42, 34, %x3 \n\t" ++ "xvmulsp 43, 35, %x3 \n\t" ++ "lxvw4x 34, %5, %2 \n\t" ++ "lxvw4x 35, %6, %2 \n\t" ++ "xvmulsp 44, 36, %x3 \n\t" ++ "xvmulsp 45, 37, %x3 \n\t" ++ "lxvw4x 36, %7, %2 \n\t" ++ "lxvw4x 37, %8, %2 \n\t" ++ "xvmulsp 46, 38, %x3 \n\t" ++ "xvmulsp 47, 39, %x3 \n\t" ++ "lxvw4x 38, %9, %2 \n\t" ++ "lxvw4x 39, %10, %2 \n\t" ++ ++ "addi %2, %2, -128 \n\t" ++ ++ "stxvw4x 40, 0, %2 \n\t" ++ "stxvw4x 41, %4, %2 \n\t" ++ "stxvw4x 42, %5, %2 \n\t" ++ "stxvw4x 43, %6, %2 \n\t" ++ "stxvw4x 44, %7, %2 \n\t" ++ "stxvw4x 45, %8, %2 \n\t" ++ "stxvw4x 46, %9, %2 \n\t" ++ "stxvw4x 47, %10, %2 \n\t" ++ ++ "addi %2, %2, 256 \n\t" ++ ++ "addic. %1, %1, -32 \n\t" ++ "bgt 1b \n" ++ ++ "2: \n\t" ++ ++ "xvmulsp 40, 32, %x3 \n\t" ++ "xvmulsp 41, 33, %x3 \n\t" ++ "xvmulsp 42, 34, %x3 \n\t" ++ "xvmulsp 43, 35, %x3 \n\t" ++ ++ "addi %2, %2, -128 \n\t" ++ ++ "xvmulsp 44, 36, %x3 \n\t" ++ "xvmulsp 45, 37, %x3 \n\t" ++ "xvmulsp 46, 38, %x3 \n\t" ++ "xvmulsp 47, 39, %x3 \n\t" ++ ++ "stxvw4x 40, 0, %2 \n\t" ++ "stxvw4x 41, %4, %2 \n\t" ++ "stxvw4x 42, %5, %2 \n\t" ++ "stxvw4x 43, %6, %2 \n\t" ++ "stxvw4x 44, %7, %2 \n\t" ++ "stxvw4x 45, %8, %2 \n\t" ++ "stxvw4x 46, %9, %2 \n\t" ++ "stxvw4x 47, %10, %2 \n" ++ ++ "#n=%1 alpha=%3 x=%0=%2 o16=%4 o32=%5 o48=%6 o64=%7 o80=%8 o96=%9 o112=%10" ++ : ++ "+m" (*x), ++ "+r" (n), // 1 ++ "+b" (x), // 2 ++ "+f" (alpha) // 3 ++ : ++ "b" (16), // 4 ++ "b" (32), // 5 ++ "b" (48), // 6 ++ "b" (64), // 7 ++ "b" (80), // 8 ++ "b" (96), // 9 ++ "b" (112) // 10 ++ : ++ "cr0", ++ "vs32","vs33","vs34","vs35","vs36","vs37","vs38","vs39", ++ "vs40","vs41","vs42","vs43","vs44","vs45","vs46","vs47" ++ ); ++} ++ ++ ++static void sscal_kernel_16_zero (long n, float *x) + { +- +- +- BLASLONG i = n; +- BLASLONG o16 = 16; +- BLASLONG o32 = 32; +- BLASLONG o48 = 48; +- BLASLONG o64 = 64; +- BLASLONG o80 = 80; +- BLASLONG o96 = 96; +- BLASLONG o112 = 112; +- FLOAT *x1=x; +- FLOAT *x2=x+1; +- BLASLONG pre = 384; +- +- __asm__ __volatile__ +- ( +- +- "xxlxor 32 , 32 , 32 \n\t" +- "addi %1, %1, -4 \n\t" +- +- +- ".align 5 \n\t" +- "1: \n\t" +- +- "stxvw4x 32, 0, %1 \n\t" +- "stxvw4x 32, %5, %1 \n\t" +- "stxvw4x 32, %6, %1 \n\t" +- "stxvw4x 32, %7, %1 \n\t" +- "stxvw4x 32, %8, %1 \n\t" +- "stxvw4x 32, %9, %1 \n\t" +- "stxvw4x 32, %10, %1 \n\t" +- "stxvw4x 32, %11, %1 \n\t" +- +- "addi %1, %1, 128 \n\t" +- +- "addic. %0 , %0 , -32 \n\t" +- "bgt 1b \n\t" +- +- "2: \n\t" +- +- : +- : +- "r" (i), // 0 +- "r" (x2), // 1 +- "r" (x1), // 2 +- "r" (alpha), // 3 +- "r" (pre), // 4 +- "r" (o16), // 5 +- "r" (o32), // 6 +- "r" (o48), // 7 +- "r" (o64), // 8 +- "r" (o80), // 9 +- "r" (o96), // 10 +- "r" (o112) // 11 +- : "cr0", "%0", "%2" , "%1", "memory" +- ); +- +-} +- +- ++ __vector float t0; ++ ++ __asm__ ++ ( ++ "xxlxor %x3, %x3, %x3 \n\t" ++ ++ ".p2align 5 \n" ++ "1: \n\t" ++ ++ "stxvw4x %x3, 0, %2 \n\t" ++ "stxvw4x %x3, %4, %2 \n\t" ++ "stxvw4x %x3, %5, %2 \n\t" ++ "stxvw4x %x3, %6, %2 \n\t" ++ "stxvw4x %x3, %7, %2 \n\t" ++ "stxvw4x %x3, %8, %2 \n\t" ++ "stxvw4x %x3, %9, %2 \n\t" ++ "stxvw4x %x3, %10, %2 \n\t" ++ ++ "addi %2, %2, 128 \n\t" ++ ++ "addic. %1, %1, -32 \n\t" ++ "bgt 1b \n" ++ ++ "#n=%1 x=%0=%2 t0=%x3 o16=%4 o32=%5 o48=%6 o64=%7 o80=%8 o96=%9 o112=%10" ++ : ++ "=m" (*x), ++ "+r" (n), // 1 ++ "+b" (x), // 2 ++ "=wa" (t0) // 3 ++ : ++ "b" (16), // 4 ++ "b" (32), // 5 ++ "b" (48), // 6 ++ "b" (64), // 7 ++ "b" (80), // 8 ++ "b" (96), // 9 ++ "b" (112) // 10 ++ : ++ "cr0" ++ ); ++} +diff --git a/kernel/power/sswap_microk_power8.c b/kernel/power/sswap_microk_power8.c +index c48e743..d44f167 100644 +--- a/kernel/power/sswap_microk_power8.c ++++ b/kernel/power/sswap_microk_power8.c +@@ -35,102 +35,74 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + #define HAVE_KERNEL_32 1 + +-static void sswap_kernel_32( BLASLONG n, FLOAT *x, FLOAT *y) __attribute__ ((noinline)); +- +-static void sswap_kernel_32( BLASLONG n, FLOAT *x, FLOAT *y) ++static void sswap_kernel_32 (long n, float *x, float *y) + { +- +- +- BLASLONG i = n; +- BLASLONG o16 = 16; +- BLASLONG o32 = 32; +- BLASLONG o48 = 48; +- BLASLONG o64 = 64; +- BLASLONG o80 = 80; +- BLASLONG o96 = 96; +- BLASLONG o112 = 112; +- FLOAT *x1=x; +- FLOAT *y1=y; +- FLOAT *x2=x+1; +- FLOAT *y2=y+1; +- BLASLONG pre = 384; +- BLASLONG alpha=0; +- +- __asm__ __volatile__ +- ( +- +- "addi %3, %3, -4 \n\t" +- "addi %4, %4, -4 \n\t" +- +- ".align 5 \n\t" +- "1: \n\t" +- +- "lxvw4x 32, 0, %2 \n\t" +- "lxvw4x 33, %5, %2 \n\t" +- "lxvw4x 34, %6, %2 \n\t" +- "lxvw4x 35, %7, %2 \n\t" +- "lxvw4x 36, %8, %2 \n\t" +- "lxvw4x 37, %9, %2 \n\t" +- "lxvw4x 38, %10, %2 \n\t" +- "lxvw4x 39, %11, %2 \n\t" +- +- "addi %2, %2, 128 \n\t" +- +- "lxvw4x 48, 0, %1 \n\t" +- "lxvw4x 49, %5, %1 \n\t" +- "lxvw4x 50, %6, %1 \n\t" +- "lxvw4x 51, %7, %1 \n\t" +- "lxvw4x 52, %8, %1 \n\t" +- "lxvw4x 53, %9, %1 \n\t" +- "lxvw4x 54, %10, %1 \n\t" +- "lxvw4x 55, %11, %1 \n\t" +- +- "addi %1, %1, 128 \n\t" +- +- "stxvw4x 32, 0, %3 \n\t" +- "stxvw4x 33, %5, %3 \n\t" +- "stxvw4x 34, %6, %3 \n\t" +- "stxvw4x 35, %7, %3 \n\t" +- "stxvw4x 36, %8, %3 \n\t" +- "stxvw4x 37, %9, %3 \n\t" +- "stxvw4x 38, %10, %3 \n\t" +- "stxvw4x 39, %11, %3 \n\t" +- +- "addi %3, %3, 128 \n\t" +- +- "stxvw4x 48, 0, %4 \n\t" +- "stxvw4x 49, %5, %4 \n\t" +- "stxvw4x 50, %6, %4 \n\t" +- "stxvw4x 51, %7, %4 \n\t" +- "stxvw4x 52, %8, %4 \n\t" +- "stxvw4x 53, %9, %4 \n\t" +- "stxvw4x 54, %10, %4 \n\t" +- "stxvw4x 55, %11, %4 \n\t" +- +- "addi %4, %4, 128 \n\t" +- +- "addic. %0 , %0 , -32 \n\t" +- "bgt 1b \n\t" +- +- "2: \n\t" +- +- : +- : +- "r" (i), // 0 +- "r" (y1), // 1 +- "r" (x1), // 2 +- "r" (y2), // 3 +- "r" (x2), // 4 +- "r" (o16), // 5 +- "r" (o32), // 6 +- "r" (o48), // 7 +- "r" (o64), // 8 +- "r" (o80), // 9 +- "r" (o96), // 10 +- "r" (o112) // 11 +- : "cr0", "%0", "%2" , "%1", "%3", "%4", "memory" +- ); +- +-} +- +- ++ __asm__ ++ ( ++ ".p2align 5 \n" ++ "1: \n\t" ++ ++ "lxvw4x 32, 0, %4 \n\t" ++ "lxvw4x 33, %5, %4 \n\t" ++ "lxvw4x 34, %6, %4 \n\t" ++ "lxvw4x 35, %7, %4 \n\t" ++ "lxvw4x 36, %8, %4 \n\t" ++ "lxvw4x 37, %9, %4 \n\t" ++ "lxvw4x 38, %10, %4 \n\t" ++ "lxvw4x 39, %11, %4 \n\t" ++ ++ "lxvw4x 40, 0, %3 \n\t" ++ "lxvw4x 41, %5, %3 \n\t" ++ "lxvw4x 42, %6, %3 \n\t" ++ "lxvw4x 43, %7, %3 \n\t" ++ "lxvw4x 44, %8, %3 \n\t" ++ "lxvw4x 45, %9, %3 \n\t" ++ "lxvw4x 46, %10, %3 \n\t" ++ "lxvw4x 47, %11, %3 \n\t" ++ ++ "stxvw4x 32, 0, %3 \n\t" ++ "stxvw4x 33, %5, %3 \n\t" ++ "stxvw4x 34, %6, %3 \n\t" ++ "stxvw4x 35, %7, %3 \n\t" ++ "stxvw4x 36, %8, %3 \n\t" ++ "stxvw4x 37, %9, %3 \n\t" ++ "stxvw4x 38, %10, %3 \n\t" ++ "stxvw4x 39, %11, %3 \n\t" ++ ++ "addi %3, %3, 128 \n\t" ++ ++ "stxvw4x 40, 0, %4 \n\t" ++ "stxvw4x 41, %5, %4 \n\t" ++ "stxvw4x 42, %6, %4 \n\t" ++ "stxvw4x 43, %7, %4 \n\t" ++ "stxvw4x 44, %8, %4 \n\t" ++ "stxvw4x 45, %9, %4 \n\t" ++ "stxvw4x 46, %10, %4 \n\t" ++ "stxvw4x 47, %11, %4 \n\t" ++ ++ "addi %4, %4, 128 \n\t" ++ ++ "addic. %2, %2, -32 \n\t" ++ "bgt 1b \n" ++ ++ "#n=%2 x=%0=%3 y=%1=%4 o16=%5 o32=%6 o48=%7 o64=%8 o80=%9 o96=%10 o112=%11" ++ : ++ "+m" (*x), ++ "+m" (*y), ++ "+r" (n), // 2 ++ "+b" (x), // 3 ++ "+b" (y) // 4 ++ : ++ "b" (16), // 5 ++ "b" (32), // 6 ++ "b" (48), // 7 ++ "b" (64), // 8 ++ "b" (80), // 9 ++ "b" (96), // 10 ++ "b" (112) // 11 ++ : ++ "cr0", ++ "vs32","vs33","vs34","vs35","vs36","vs37","vs38","vs39", ++ "vs40","vs41","vs42","vs43","vs44","vs45","vs46","vs47" ++ ); ++} +diff --git a/kernel/power/zasum.c b/kernel/power/zasum.c +index abd6ec0..0b6b87d 100644 +--- a/kernel/power/zasum.c ++++ b/kernel/power/zasum.c +@@ -53,7 +53,7 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + #ifndef HAVE_KERNEL_8 + +-static void zasum_kernel_8(BLASLONG n, FLOAT *x1, FLOAT *svec) ++static FLOAT zasum_kernel_8(BLASLONG n, FLOAT *x1) + { + + BLASLONG i=0; +@@ -92,9 +92,7 @@ static void zasum_kernel_8(BLASLONG n, FLOAT *x1, FLOAT *svec) + + } + +- svec[0] = sum0+sum1+sum2+sum3; +- svec[1] = 0.0; +- ++ return sum0+sum1+sum2+sum3; + } + + #endif +@@ -104,7 +102,6 @@ FLOAT CNAME(BLASLONG n, FLOAT *x, BLASLONG inc_x) + BLASLONG i=0; + BLASLONG ip=0; + FLOAT sumf = 0.0; +- FLOAT svec[2] __attribute__ ((aligned (16)));; + BLASLONG n1; + BLASLONG inc_x2; + +@@ -117,8 +114,7 @@ FLOAT CNAME(BLASLONG n, FLOAT *x, BLASLONG inc_x) + if ( n1 > 0 ) + { + +- zasum_kernel_8(n1, x, svec); +- sumf = svec[0] + svec[1]; ++ sumf = zasum_kernel_8(n1, x); + i=n1; + ip=2*n1; + } +diff --git a/kernel/power/zasum_microk_power8.c b/kernel/power/zasum_microk_power8.c +index b9f6c0a..8236690 100644 +--- a/kernel/power/zasum_microk_power8.c ++++ b/kernel/power/zasum_microk_power8.c +@@ -34,144 +34,140 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + **************************************************************************************/ + + #define HAVE_KERNEL_8 1 +-static void zasum_kernel_8( BLASLONG n, FLOAT *x, FLOAT *svec) __attribute__ ((noinline)); + +-static void zasum_kernel_8( BLASLONG n, FLOAT *x, FLOAT *svec) ++static double zasum_kernel_8 (long n, double *x) + { +- +- +- BLASLONG i = n; +- BLASLONG o16 = 16; +- BLASLONG o32 = 32; +- BLASLONG o48 = 48; +- BLASLONG o64 = 64; +- BLASLONG o80 = 80; +- BLASLONG o96 = 96; +- BLASLONG o112 = 112; +- FLOAT *x1=x; +- BLASLONG pre = 384; +- +- __asm__ __volatile__ +- ( +- +- "dcbt %2 , %4 \n\t" +- +- "xxlxor 32,32,32 \n\t" +- "xxlxor 33,33,33 \n\t" +- "xxlxor 34,34,34 \n\t" +- "xxlxor 35,35,35 \n\t" +- "xxlxor 36,36,36 \n\t" +- "xxlxor 37,37,37 \n\t" +- "xxlxor 38,38,38 \n\t" +- "xxlxor 39,39,39 \n\t" +- +- "lxvd2x 40, 0, %2 \n\t" +- "lxvd2x 41, %5, %2 \n\t" +- "lxvd2x 42, %6, %2 \n\t" +- "lxvd2x 43, %7, %2 \n\t" +- "lxvd2x 44, %8, %2 \n\t" +- "lxvd2x 45, %9, %2 \n\t" +- "lxvd2x 46, %10, %2 \n\t" +- "lxvd2x 47, %11, %2 \n\t" +- +- "addi %2, %2, 128 \n\t" +- +- "addic. %0 , %0 , -8 \n\t" +- "ble 2f \n\t" +- +- ".align 5 \n\t" +- "1: \n\t" +- +- "dcbt %2 , %4 \n\t" +- +- "xvabsdp 48, 40 \n\t" +- "xvabsdp 49, 41 \n\t" +- "xvabsdp 50, 42 \n\t" +- "xvabsdp 51, 43 \n\t" +- +- "lxvd2x 40, 0, %2 \n\t" +- "lxvd2x 41, %5, %2 \n\t" +- +- "xvabsdp 52, 44 \n\t" +- "xvabsdp 53, 45 \n\t" +- +- "lxvd2x 42, %6, %2 \n\t" +- "lxvd2x 43, %7, %2 \n\t" +- +- "xvabsdp 54, 46 \n\t" +- "xvabsdp 55, 47 \n\t" +- +- "lxvd2x 44, %8, %2 \n\t" +- "lxvd2x 45, %9, %2 \n\t" +- +- "xvadddp 32, 32, 48 \n\t" +- "xvadddp 33, 33, 49 \n\t" +- +- "lxvd2x 46, %10, %2 \n\t" +- "lxvd2x 47, %11, %2 \n\t" +- +- "xvadddp 34, 34, 50 \n\t" +- "xvadddp 35, 35, 51 \n\t" +- "addi %2, %2, 128 \n\t" +- "xvadddp 36, 36, 52 \n\t" +- "xvadddp 37, 37, 53 \n\t" +- "addic. %0 , %0 , -8 \n\t" +- "xvadddp 38, 38, 54 \n\t" +- "xvadddp 39, 39, 55 \n\t" +- +- "bgt 1b \n\t" +- +- "2: \n\t" +- +- +- "xvabsdp 48, 40 \n\t" +- "xvabsdp 49, 41 \n\t" +- "xvabsdp 50, 42 \n\t" +- "xvabsdp 51, 43 \n\t" +- "xvabsdp 52, 44 \n\t" +- "xvabsdp 53, 45 \n\t" +- "xvabsdp 54, 46 \n\t" +- "xvabsdp 55, 47 \n\t" +- +- "xvadddp 32, 32, 48 \n\t" +- "xvadddp 33, 33, 49 \n\t" +- "xvadddp 34, 34, 50 \n\t" +- "xvadddp 35, 35, 51 \n\t" +- "xvadddp 36, 36, 52 \n\t" +- "xvadddp 37, 37, 53 \n\t" +- "xvadddp 38, 38, 54 \n\t" +- "xvadddp 39, 39, 55 \n\t" +- +- "xvadddp 32, 32, 33 \n\t" +- "xvadddp 34, 34, 35 \n\t" +- "xvadddp 36, 36, 37 \n\t" +- "xvadddp 38, 38, 39 \n\t" +- +- "xvadddp 32, 32, 34 \n\t" +- "xvadddp 36, 36, 38 \n\t" +- +- "xvadddp 32, 32, 36 \n\t" +- +- +- "stxvd2x 32, 0, %3 \n\t" +- +- : +- : +- "r" (i), // 0 +- "r" (n), // 1 +- "r" (x1), // 2 +- "r" (svec), // 3 +- "r" (pre), // 4 +- "r" (o16), // 5 +- "r" (o32), // 6 +- "r" (o48), // 7 +- "r" (o64), // 8 +- "r" (o80), // 9 +- "r" (o96), // 10 +- "r" (o112) // 11 +- : "cr0", "%0", "%2", "memory" +- ); +- +-} +- +- ++ double sum; ++ __vector double t0; ++ __vector double t1; ++ __vector double t2; ++ __vector double t3; ++ ++ __asm__ ++ ( ++ "dcbt 0, %2 \n\t" ++ ++ "xxlxor 32, 32, 32 \n\t" ++ "xxlxor 33, 33, 33 \n\t" ++ "xxlxor 34, 34, 34 \n\t" ++ "xxlxor 35, 35, 35 \n\t" ++ "xxlxor 36, 36, 36 \n\t" ++ "xxlxor 37, 37, 37 \n\t" ++ "xxlxor 38, 38, 38 \n\t" ++ "xxlxor 39, 39, 39 \n\t" ++ ++ "lxvd2x 40, 0, %2 \n\t" ++ "lxvd2x 41, %8, %2 \n\t" ++ "lxvd2x 42, %9, %2 \n\t" ++ "lxvd2x 43, %10, %2 \n\t" ++ "lxvd2x 44, %11, %2 \n\t" ++ "lxvd2x 45, %12, %2 \n\t" ++ "lxvd2x 46, %13, %2 \n\t" ++ "lxvd2x 47, %14, %2 \n\t" ++ ++ "addi %2, %2, 128 \n\t" ++ ++ "addic. %1, %1, -8 \n\t" ++ "ble 2f \n\t" ++ ++ ".p2align 5 \n" ++ "1: \n\t" ++ ++ "xvabsdp 48, 40 \n\t" ++ "xvabsdp 49, 41 \n\t" ++ "xvabsdp 50, 42 \n\t" ++ "xvabsdp 51, 43 \n\t" ++ ++ "lxvd2x 40, 0, %2 \n\t" ++ "lxvd2x 41, %8, %2 \n\t" ++ ++ "xvabsdp %x3, 44 \n\t" ++ "xvabsdp %x4, 45 \n\t" ++ ++ "lxvd2x 42, %9, %2 \n\t" ++ "lxvd2x 43, %10, %2 \n\t" ++ ++ "xvabsdp %x5, 46 \n\t" ++ "xvabsdp %x6, 47 \n\t" ++ ++ "lxvd2x 44, %11, %2 \n\t" ++ "lxvd2x 45, %12, %2 \n\t" ++ ++ "xvadddp 32, 32, 48 \n\t" ++ "xvadddp 33, 33, 49 \n\t" ++ ++ "lxvd2x 46, %13, %2 \n\t" ++ "lxvd2x 47, %14, %2 \n\t" ++ ++ "xvadddp 34, 34, 50 \n\t" ++ "xvadddp 35, 35, 51 \n\t" ++ "addi %2, %2, 128 \n\t" ++ "xvadddp 36, 36, %x3 \n\t" ++ "xvadddp 37, 37, %x4 \n\t" ++ "addic. %1, %1, -8 \n\t" ++ "xvadddp 38, 38, %x5 \n\t" ++ "xvadddp 39, 39, %x6 \n\t" ++ ++ "bgt 1b \n" ++ ++ "2: \n\t" ++ ++ "xvabsdp 48, 40 \n\t" ++ "xvabsdp 49, 41 \n\t" ++ "xvabsdp 50, 42 \n\t" ++ "xvabsdp 51, 43 \n\t" ++ "xvabsdp %x3, 44 \n\t" ++ "xvabsdp %x4, 45 \n\t" ++ "xvabsdp %x5, 46 \n\t" ++ "xvabsdp %x6, 47 \n\t" ++ ++ "xvadddp 32, 32, 48 \n\t" ++ "xvadddp 33, 33, 49 \n\t" ++ "xvadddp 34, 34, 50 \n\t" ++ "xvadddp 35, 35, 51 \n\t" ++ "xvadddp 36, 36, %x3 \n\t" ++ "xvadddp 37, 37, %x4 \n\t" ++ "xvadddp 38, 38, %x5 \n\t" ++ "xvadddp 39, 39, %x6 \n\t" ++ ++ "xvadddp 32, 32, 33 \n\t" ++ "xvadddp 34, 34, 35 \n\t" ++ "xvadddp 36, 36, 37 \n\t" ++ "xvadddp 38, 38, 39 \n\t" ++ ++ "xvadddp 32, 32, 34 \n\t" ++ "xvadddp 36, 36, 38 \n\t" ++ ++ "xvadddp 32, 32, 36 \n\t" ++ ++ "xxswapd 33, 32 \n\t" ++ "xsadddp %x0, 32, 33 \n" ++ ++ "#n=%1 x=%3=%2 sum=%0 o16=%8 o32=%9 o48=%10 o64=%11 o80=%12 o96=%13 o112=%14\n" ++ "#t0=%x3 t1=%x4 t2=%x5 t3=%x6" ++ : ++ "=d" (sum), // 0 ++ "+r" (n), // 1 ++ "+b" (x), // 2 ++ "=wa" (t0), // 3 ++ "=wa" (t1), // 4 ++ "=wa" (t2), // 5 ++ "=wa" (t3) // 6 ++ : ++ "m" (*x), ++ "b" (16), // 8 ++ "b" (32), // 9 ++ "b" (48), // 10 ++ "b" (64), // 11 ++ "b" (80), // 12 ++ "b" (96), // 13 ++ "b" (112) // 14 ++ : ++ "cr0", ++ "vs32","vs33","vs34","vs35","vs36","vs37","vs38","vs39", ++ "vs40","vs41","vs42","vs43","vs44","vs45","vs46","vs47", ++ "vs48","vs49","vs50","vs51" ++ ); ++ ++ return sum; ++} +diff --git a/kernel/power/zaxpy.c b/kernel/power/zaxpy.c +index 0ee0c1b..dd7ab6c 100644 +--- a/kernel/power/zaxpy.c ++++ b/kernel/power/zaxpy.c +@@ -78,7 +78,6 @@ int CNAME(BLASLONG n, BLASLONG dummy0, BLASLONG dummy1, FLOAT da_r, FLOAT da_i, + { + BLASLONG i=0; + BLASLONG ix=0,iy=0; +- FLOAT da[4]; + + if ( n <= 0 ) return(0); + +@@ -89,11 +88,7 @@ int CNAME(BLASLONG n, BLASLONG dummy0, BLASLONG dummy1, FLOAT da_r, FLOAT da_i, + + if ( n1 ) + { +- da[0] = da_r; +- da[1] = da_r; +- da[2] = da_i; +- da[3] = da_i; +- zaxpy_kernel_4(n1, x, y , da ); ++ zaxpy_kernel_4 (n1, x, y, da_r, da_i); + ix = 2 * n1; + } + i = n1; +diff --git a/kernel/power/zaxpy_microk_power8.c b/kernel/power/zaxpy_microk_power8.c +index c8a529f..124614f 100644 +--- a/kernel/power/zaxpy_microk_power8.c ++++ b/kernel/power/zaxpy_microk_power8.c +@@ -35,216 +35,225 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + #define HAVE_KERNEL_4 1 +-static void zaxpy_kernel_4( BLASLONG n, FLOAT *x, FLOAT *y , FLOAT *alpha) __attribute__ ((noinline)); +- +-static void zaxpy_kernel_4( BLASLONG n, FLOAT *x, FLOAT *y, FLOAT *alpha) ++static void zaxpy_kernel_4 (long n, double *x, double *y, ++ double alpha_r, double alpha_i) + { +- +- +- BLASLONG i = n; +- BLASLONG o16 = 16; +- BLASLONG o32 = 32; +- BLASLONG o48 = 48; +- FLOAT *x1=x; +- FLOAT *y1=y; +- FLOAT *y2=y+1; +- BLASLONG pre = 384; +- + #if !defined(CONJ) +- FLOAT mvec[2] = { -1.0, 1.0 }; ++ static const double mvec[2] = { -1.0, 1.0 }; + #else +- FLOAT mvec[2] = { 1.0, -1.0 }; ++ static const double mvec[2] = { 1.0, -1.0 }; + #endif +- +- +- __asm__ __volatile__ +- ( +- +- "lxsdx 34, 0 , %4 \n\t" // alpha_r +- "lxsdx 35, %5, %4 \n\t" // alpha_i +- "xxspltd 32, 34, 0 \n\t" +- "xxspltd 33, 35, 0 \n\t" +- +- "lxvd2x 36, 0, %9 \n\t" // mvec ++ const double *mvecp = mvec; ++ ++ __vector double t0; ++ __vector double t1; ++ __vector double t2; ++ __vector double t3; ++ __vector double t4; ++ __vector double t5; ++ __vector double t6; ++ __vector double t7; ++ __vector double t8; ++ __vector double t9; ++ __vector double t10; ++ __vector double t11; ++ long ytmp; ++ ++ __asm__ ++ ( ++ "xxspltd 32, %x19, 0 \n\t" // alpha_r ++ "xxspltd 33, %x20, 0 \n\t" // alpha_i ++ ++ "lxvd2x 36, 0, %21 \n\t" // mvec + + #if !defined(CONJ) +- "xvmuldp 33, 33 , 36 \n\t" // alpha_i * mvec ++ "xvmuldp 33, 33, 36 \n\t" // alpha_i * mvec + #else +- "xvmuldp 32, 32 , 36 \n\t" // alpha_r * mvec ++ "xvmuldp 32, 32, 36 \n\t" // alpha_r * mvec + #endif + +- "addi %8, %8, -8 \n\t" +- +- "dcbt %2, %10 \n\t" +- "dcbt %3, %10 \n\t" +- +- +- "lxvd2x 40, 0, %2 \n\t" // x0 +- "lxvd2x 41, %5, %2 \n\t" // x1 +- "lxvd2x 42, %6, %2 \n\t" // x2 +- "lxvd2x 43, %7, %2 \n\t" // x3 +- +- "lxvd2x 48, 0, %3 \n\t" // y0 +- "lxvd2x 49, %5, %3 \n\t" // y1 +- "lxvd2x 50, %6, %3 \n\t" // y2 +- "lxvd2x 51, %7, %3 \n\t" // y3 +- +- "xxswapd 56, 40 \n\t" // exchange real and imag part +- "xxswapd 57, 41 \n\t" // exchange real and imag part +- "xxswapd 58, 42 \n\t" // exchange real and imag part +- "xxswapd 59, 43 \n\t" // exchange real and imag part +- +- "addi %2, %2, 64 \n\t" +- "addi %3, %3, 64 \n\t" +- +- "lxvd2x 44, 0, %2 \n\t" // x4 +- "lxvd2x 45, %5, %2 \n\t" // x5 +- "lxvd2x 46, %6, %2 \n\t" // x6 +- "lxvd2x 47, %7, %2 \n\t" // x7 +- +- "lxvd2x 52, 0, %3 \n\t" // y4 +- "lxvd2x 53, %5, %3 \n\t" // y5 +- "lxvd2x 54, %6, %3 \n\t" // y6 +- "lxvd2x 55, %7, %3 \n\t" // y7 +- +- "xxswapd 60, 44 \n\t" // exchange real and imag part +- "xxswapd 61, 45 \n\t" // exchange real and imag part +- "xxswapd 62, 46 \n\t" // exchange real and imag part +- "xxswapd 63, 47 \n\t" // exchange real and imag part +- +- "addi %2, %2, 64 \n\t" +- "addi %3, %3, 64 \n\t" +- +- "addic. %0 , %0 , -8 \n\t" +- "ble 2f \n\t" +- +- ".align 5 \n\t" +- "1: \n\t" +- +- "dcbt %2, %10 \n\t" +- "dcbt %3, %10 \n\t" +- +- "xvmaddadp 48, 40, 32 \n\t" // alpha_r * x0_r , alpha_r * x0_i +- "xvmaddadp 49, 41, 32 \n\t" +- "lxvd2x 40, 0, %2 \n\t" // x0 +- "lxvd2x 41, %5, %2 \n\t" // x1 +- "xvmaddadp 50, 42, 32 \n\t" +- "xvmaddadp 51, 43, 32 \n\t" +- "lxvd2x 42, %6, %2 \n\t" // x2 +- "lxvd2x 43, %7, %2 \n\t" // x3 +- +- "xvmaddadp 52, 44, 32 \n\t" +- "addi %2, %2, 64 \n\t" +- "xvmaddadp 53, 45, 32 \n\t" +- "lxvd2x 44, 0, %2 \n\t" // x4 +- "lxvd2x 45, %5, %2 \n\t" // x5 +- "xvmaddadp 54, 46, 32 \n\t" +- "xvmaddadp 55, 47, 32 \n\t" +- "lxvd2x 46, %6, %2 \n\t" // x6 +- "lxvd2x 47, %7, %2 \n\t" // x7 +- +- "xvmaddadp 48, 56, 33 \n\t" // alpha_i * x0_i , alpha_i * x0_r +- "addi %2, %2, 64 \n\t" +- "xvmaddadp 49, 57, 33 \n\t" +- "xvmaddadp 50, 58, 33 \n\t" +- "xvmaddadp 51, 59, 33 \n\t" +- +- "xvmaddadp 52, 60, 33 \n\t" +- "xvmaddadp 53, 61, 33 \n\t" +- "xvmaddadp 54, 62, 33 \n\t" +- "xvmaddadp 55, 63, 33 \n\t" +- +- "stxvd2x 48, 0, %8 \n\t" +- "stxvd2x 49, %5, %8 \n\t" +- "stxvd2x 50, %6, %8 \n\t" +- "stxvd2x 51, %7, %8 \n\t" +- +- "addi %8, %8, 64 \n\t" +- +- "stxvd2x 52, 0, %8 \n\t" +- "stxvd2x 53, %5, %8 \n\t" +- "stxvd2x 54, %6, %8 \n\t" +- "stxvd2x 55, %7, %8 \n\t" +- +- "addi %8, %8, 64 \n\t" +- +- "xxswapd 56, 40 \n\t" // exchange real and imag part +- "xxswapd 57, 41 \n\t" // exchange real and imag part +- "lxvd2x 48, 0, %3 \n\t" // y0 +- "lxvd2x 49, %5, %3 \n\t" // y1 +- "xxswapd 58, 42 \n\t" // exchange real and imag part +- "xxswapd 59, 43 \n\t" // exchange real and imag part +- "lxvd2x 50, %6, %3 \n\t" // y2 +- "lxvd2x 51, %7, %3 \n\t" // y3 +- +- "xxswapd 60, 44 \n\t" // exchange real and imag part +- "addi %3, %3, 64 \n\t" +- "xxswapd 61, 45 \n\t" // exchange real and imag part +- "lxvd2x 52, 0, %3 \n\t" // y4 +- "lxvd2x 53, %5, %3 \n\t" // y5 +- "xxswapd 62, 46 \n\t" // exchange real and imag part +- "xxswapd 63, 47 \n\t" // exchange real and imag part +- "lxvd2x 54, %6, %3 \n\t" // y6 +- "lxvd2x 55, %7, %3 \n\t" // y7 +- +- "addi %3, %3, 64 \n\t" +- +- "addic. %0 , %0 , -8 \n\t" +- "bgt 1b \n\t" +- +- "2: \n\t" +- +- "xvmaddadp 48, 40, 32 \n\t" // alpha_r * x0_r , alpha_r * x0_i +- "xvmaddadp 49, 41, 32 \n\t" +- "xvmaddadp 50, 42, 32 \n\t" +- "xvmaddadp 51, 43, 32 \n\t" +- +- "xvmaddadp 52, 44, 32 \n\t" +- "xvmaddadp 53, 45, 32 \n\t" +- "xvmaddadp 54, 46, 32 \n\t" +- "xvmaddadp 55, 47, 32 \n\t" +- +- "xvmaddadp 48, 56, 33 \n\t" // alpha_i * x0_i , alpha_i * x0_r +- "xvmaddadp 49, 57, 33 \n\t" +- "xvmaddadp 50, 58, 33 \n\t" +- "xvmaddadp 51, 59, 33 \n\t" +- +- "xvmaddadp 52, 60, 33 \n\t" +- "xvmaddadp 53, 61, 33 \n\t" +- "xvmaddadp 54, 62, 33 \n\t" +- "xvmaddadp 55, 63, 33 \n\t" +- +- +- "stxvd2x 48, 0, %8 \n\t" +- "stxvd2x 49, %5, %8 \n\t" +- "stxvd2x 50, %6, %8 \n\t" +- "stxvd2x 51, %7, %8 \n\t" +- +- "addi %8, %8, 64 \n\t" +- +- "stxvd2x 52, 0, %8 \n\t" +- "stxvd2x 53, %5, %8 \n\t" +- "stxvd2x 54, %6, %8 \n\t" +- "stxvd2x 55, %7, %8 \n\t" +- +- "addi %8, %8, 64 \n\t" +- +- : +- : +- "r" (i), // 0 +- "r" (n), // 1 +- "r" (x1), // 2 +- "r" (y1), // 3 +- "r" (alpha), // 4 +- "r" (o16), // 5 +- "r" (o32), // 6 +- "r" (o48), // 7 +- "r" (y2), // 8 +- "r" (mvec), // 9 +- "r" (pre) // 10 +- : "cr0", "%0", "%2" , "%3", "%8", "memory" +- ); +- +-} +- +- ++ "mr %16, %3 \n\t" ++ "dcbt 0, %2 \n\t" ++ "dcbt 0, %3 \n\t" ++ ++ ++ "lxvd2x 40, 0, %2 \n\t" // x0 ++ "lxvd2x 41, %22, %2 \n\t" // x1 ++ "lxvd2x 42, %23, %2 \n\t" // x2 ++ "lxvd2x 43, %24, %2 \n\t" // x3 ++ ++ "lxvd2x 48, 0, %3 \n\t" // y0 ++ "lxvd2x 49, %22, %3 \n\t" // y1 ++ "lxvd2x 50, %23, %3 \n\t" // y2 ++ "lxvd2x 51, %24, %3 \n\t" // y3 ++ ++ "xxswapd %x8, 40 \n\t" // exchange real and imag part ++ "xxswapd %x9, 41 \n\t" // exchange real and imag part ++ "xxswapd %x10, 42 \n\t" // exchange real and imag part ++ "xxswapd %x11, 43 \n\t" // exchange real and imag part ++ ++ "addi %2, %2, 64 \n\t" ++ "addi %3, %3, 64 \n\t" ++ ++ "lxvd2x 44, 0, %2 \n\t" // x4 ++ "lxvd2x 45, %22, %2 \n\t" // x5 ++ "lxvd2x 46, %23, %2 \n\t" // x6 ++ "lxvd2x 47, %24, %2 \n\t" // x7 ++ ++ "lxvd2x %x4, 0, %3 \n\t" // y4 ++ "lxvd2x %x5, %22, %3 \n\t" // y5 ++ "lxvd2x %x6, %23, %3 \n\t" // y6 ++ "lxvd2x %x7, %24, %3 \n\t" // y7 ++ ++ "xxswapd %x12, 44 \n\t" // exchange real and imag part ++ "xxswapd %x13, 45 \n\t" // exchange real and imag part ++ "xxswapd %x14, 46 \n\t" // exchange real and imag part ++ "xxswapd %x15, 47 \n\t" // exchange real and imag part ++ ++ "addi %2, %2, 64 \n\t" ++ "addi %3, %3, 64 \n\t" ++ ++ "addic. %1, %1, -8 \n\t" ++ "ble 2f \n\t" ++ ++ ".p2align 5 \n" ++ "1: \n\t" ++ ++ "xvmaddadp 48, 40, 32 \n\t" // alpha_r * x0_r , alpha_r * x0_i ++ "xvmaddadp 49, 41, 32 \n\t" ++ "lxvd2x 40, 0, %2 \n\t" // x0 ++ "lxvd2x 41, %22, %2 \n\t" // x1 ++ "xvmaddadp 50, 42, 32 \n\t" ++ "xvmaddadp 51, 43, 32 \n\t" ++ "lxvd2x 42, %23, %2 \n\t" // x2 ++ "lxvd2x 43, %24, %2 \n\t" // x3 ++ ++ "xvmaddadp %x4, 44, 32 \n\t" ++ "addi %2, %2, 64 \n\t" ++ "xvmaddadp %x5, 45, 32 \n\t" ++ "lxvd2x 44, 0, %2 \n\t" // x4 ++ "lxvd2x 45, %22, %2 \n\t" // x5 ++ "xvmaddadp %x6, 46, 32 \n\t" ++ "xvmaddadp %x7, 47, 32 \n\t" ++ "lxvd2x 46, %23, %2 \n\t" // x6 ++ "lxvd2x 47, %24, %2 \n\t" // x7 ++ ++ "xvmaddadp 48, %x8, 33 \n\t" // alpha_i * x0_i , alpha_i * x0_r ++ "addi %2, %2, 64 \n\t" ++ "xvmaddadp 49, %x9, 33 \n\t" ++ "xvmaddadp 50, %x10, 33 \n\t" ++ "xvmaddadp 51, %x11, 33 \n\t" ++ ++ "xvmaddadp %x4, %x12, 33 \n\t" ++ "xvmaddadp %x5, %x13, 33 \n\t" ++ "xvmaddadp %x6, %x14, 33 \n\t" ++ "xvmaddadp %x7, %x15, 33 \n\t" ++ ++ "stxvd2x 48, 0, %16 \n\t" ++ "stxvd2x 49, %22, %16 \n\t" ++ "stxvd2x 50, %23, %16 \n\t" ++ "stxvd2x 51, %24, %16 \n\t" ++ ++ "addi %16, %16, 64 \n\t" ++ ++ "stxvd2x %x4, 0, %16 \n\t" ++ "stxvd2x %x5, %22, %16 \n\t" ++ "stxvd2x %x6, %23, %16 \n\t" ++ "stxvd2x %x7, %24, %16 \n\t" ++ ++ "addi %16, %16, 64 \n\t" ++ ++ "xxswapd %x8, 40 \n\t" // exchange real and imag part ++ "xxswapd %x9, 41 \n\t" // exchange real and imag part ++ "lxvd2x 48, 0, %3 \n\t" // y0 ++ "lxvd2x 49, %22, %3 \n\t" // y1 ++ "xxswapd %x10, 42 \n\t" // exchange real and imag part ++ "xxswapd %x11, 43 \n\t" // exchange real and imag part ++ "lxvd2x 50, %23, %3 \n\t" // y2 ++ "lxvd2x 51, %24, %3 \n\t" // y3 ++ ++ "xxswapd %x12, 44 \n\t" // exchange real and imag part ++ "addi %3, %3, 64 \n\t" ++ "xxswapd %x13, 45 \n\t" // exchange real and imag part ++ "lxvd2x %x4, 0, %3 \n\t" // y4 ++ "lxvd2x %x5, %22, %3 \n\t" // y5 ++ "xxswapd %x14, 46 \n\t" // exchange real and imag part ++ "xxswapd %x15, 47 \n\t" // exchange real and imag part ++ "lxvd2x %x6, %23, %3 \n\t" // y6 ++ "lxvd2x %x7, %24, %3 \n\t" // y7 ++ ++ "addi %3, %3, 64 \n\t" ++ ++ "addic. %1, %1, -8 \n\t" ++ "bgt 1b \n" ++ ++ "2: \n\t" ++ ++ "xvmaddadp 48, 40, 32 \n\t" // alpha_r * x0_r , alpha_r * x0_i ++ "xvmaddadp 49, 41, 32 \n\t" ++ "xvmaddadp 50, 42, 32 \n\t" ++ "xvmaddadp 51, 43, 32 \n\t" ++ ++ "xvmaddadp %x4, 44, 32 \n\t" ++ "xvmaddadp %x5, 45, 32 \n\t" ++ "xvmaddadp %x6, 46, 32 \n\t" ++ "xvmaddadp %x7, 47, 32 \n\t" ++ ++ "xvmaddadp 48, %x8, 33 \n\t" // alpha_i * x0_i , alpha_i * x0_r ++ "xvmaddadp 49, %x9, 33 \n\t" ++ "xvmaddadp 50, %x10, 33 \n\t" ++ "xvmaddadp 51, %x11, 33 \n\t" ++ ++ "xvmaddadp %x4, %x12, 33 \n\t" ++ "xvmaddadp %x5, %x13, 33 \n\t" ++ "xvmaddadp %x6, %x14, 33 \n\t" ++ "xvmaddadp %x7, %x15, 33 \n\t" ++ ++ "stxvd2x 48, 0, %16 \n\t" ++ "stxvd2x 49, %22, %16 \n\t" ++ "stxvd2x 50, %23, %16 \n\t" ++ "stxvd2x 51, %24, %16 \n\t" ++ ++ "addi %16, %16, 64 \n\t" ++ ++ "stxvd2x %x4, 0, %16 \n\t" ++ "stxvd2x %x5, %22, %16 \n\t" ++ "stxvd2x %x6, %23, %16 \n\t" ++ "stxvd2x %x7, %24, %16 \n" ++ ++ "#n=%1 x=%17=%2 y=%0=%3 alpha=(%19,%20) mvecp=%18=%16 o16=%22 o32=%23 o48=%24 ytmp=%16\n" ++ "#t0=%x4 t1=%x5 t2=%x6 t3=%x7 t4=%x8 t5=%x9 t6=%x10 t7=%x11 t8=%x12 t9=%x13 t10=%x14 t11=%x15" ++ : ++ "+m" (*y), ++ "+r" (n), // 1 ++ "+b" (x), // 2 ++ "+b" (y), // 3 ++ "=wa" (t0), // 4 ++ "=wa" (t1), // 5 ++ "=wa" (t2), // 6 ++ "=wa" (t3), // 7 ++ "=wa" (t4), // 8 ++ "=wa" (t5), // 9 ++ "=wa" (t6), // 10 ++ "=wa" (t7), // 11 ++ "=wa" (t8), // 12 ++ "=wa" (t9), // 13 ++ "=wa" (t10), // 14 ++ "=wa" (t11), // 15 ++ "=b" (ytmp) // 16 ++ : ++ "m" (*x), ++ "m" (*mvecp), ++ "d" (alpha_r), // 19 ++ "d" (alpha_i), // 20 ++ "16" (mvecp), // 21 ++ "b" (16), // 22 ++ "b" (32), // 23 ++ "b" (48) // 24 ++ : ++ "cr0", ++ "vs32","vs33","vs34","vs35","vs36","vs37","vs38","vs39", ++ "vs40","vs41","vs42","vs43","vs44","vs45","vs46","vs47", ++ "vs48","vs49","vs50","vs51" ++ ); ++} +diff --git a/kernel/power/zcopy_microk_power8.c b/kernel/power/zcopy_microk_power8.c +index 73abe08..5ca34b6 100644 +--- a/kernel/power/zcopy_microk_power8.c ++++ b/kernel/power/zcopy_microk_power8.c +@@ -35,140 +35,121 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + #define HAVE_KERNEL_16 1 + +-static void zcopy_kernel_16( BLASLONG n, FLOAT *x, FLOAT *y) __attribute__ ((noinline)); +- +-static void zcopy_kernel_16( BLASLONG n, FLOAT *x, FLOAT *y) ++static void zcopy_kernel_16 (long n, FLOAT *x, FLOAT *y) + { +- +- +- BLASLONG i = n; +- BLASLONG o16 = 16; +- BLASLONG o32 = 32; +- BLASLONG o48 = 48; +- BLASLONG o64 = 64; +- BLASLONG o80 = 80; +- BLASLONG o96 = 96; +- BLASLONG o112 = 112; +- FLOAT *x1=x; +- FLOAT *y1=y; +- BLASLONG pre = 384; +- BLASLONG alpha=0; +- +- __asm__ __volatile__ +- ( +- +- "lxvd2x 40, 0, %2 \n\t" +- "lxvd2x 41, %5, %2 \n\t" +- "lxvd2x 42, %6, %2 \n\t" +- "lxvd2x 43, %7, %2 \n\t" +- "lxvd2x 44, %8, %2 \n\t" +- "lxvd2x 45, %9, %2 \n\t" +- "lxvd2x 46, %10, %2 \n\t" +- "lxvd2x 47, %11, %2 \n\t" +- +- "addi %2, %2, 128 \n\t" +- +- "lxvd2x 50, 0, %2 \n\t" +- "lxvd2x 51, %5, %2 \n\t" +- "lxvd2x 52, %6, %2 \n\t" +- "lxvd2x 53, %7, %2 \n\t" +- "lxvd2x 54, %8, %2 \n\t" +- "lxvd2x 55, %9, %2 \n\t" +- "lxvd2x 56, %10, %2 \n\t" +- "lxvd2x 57, %11, %2 \n\t" +- +- "addi %2, %2, 128 \n\t" +- +- "addic. %0 , %0 , -16 \n\t" +- "ble 2f \n\t" +- +- ".align 5 \n\t" +- "1: \n\t" +- +- "stxvd2x 40, 0, %1 \n\t" +- "stxvd2x 41, %5, %1 \n\t" +- "lxvd2x 40, 0, %2 \n\t" +- "lxvd2x 41, %5, %2 \n\t" +- "stxvd2x 42, %6, %1 \n\t" +- "stxvd2x 43, %7, %1 \n\t" +- "lxvd2x 42, %6, %2 \n\t" +- "lxvd2x 43, %7, %2 \n\t" +- "stxvd2x 44, %8, %1 \n\t" +- "stxvd2x 45, %9, %1 \n\t" +- "lxvd2x 44, %8, %2 \n\t" +- "lxvd2x 45, %9, %2 \n\t" +- "stxvd2x 46, %10, %1 \n\t" +- "stxvd2x 47, %11, %1 \n\t" +- "lxvd2x 46, %10, %2 \n\t" +- "lxvd2x 47, %11, %2 \n\t" +- +- +- "addi %1, %1, 128 \n\t" +- "addi %2, %2, 128 \n\t" +- +- "stxvd2x 50, 0, %1 \n\t" +- "stxvd2x 51, %5, %1 \n\t" +- "lxvd2x 50, 0, %2 \n\t" +- "lxvd2x 51, %5, %2 \n\t" +- "stxvd2x 52, %6, %1 \n\t" +- "stxvd2x 53, %7, %1 \n\t" +- "lxvd2x 52, %6, %2 \n\t" +- "lxvd2x 53, %7, %2 \n\t" +- "stxvd2x 54, %8, %1 \n\t" +- "stxvd2x 55, %9, %1 \n\t" +- "lxvd2x 54, %8, %2 \n\t" +- "lxvd2x 55, %9, %2 \n\t" +- "stxvd2x 56, %10, %1 \n\t" +- "stxvd2x 57, %11, %1 \n\t" +- "lxvd2x 56, %10, %2 \n\t" +- "lxvd2x 57, %11, %2 \n\t" +- +- "addi %1, %1, 128 \n\t" +- "addi %2, %2, 128 \n\t" +- +- "addic. %0 , %0 , -16 \n\t" +- "bgt 1b \n\t" +- +- "2: \n\t" +- +- "stxvd2x 40, 0, %1 \n\t" +- "stxvd2x 41, %5, %1 \n\t" +- "stxvd2x 42, %6, %1 \n\t" +- "stxvd2x 43, %7, %1 \n\t" +- "stxvd2x 44, %8, %1 \n\t" +- "stxvd2x 45, %9, %1 \n\t" +- "stxvd2x 46, %10, %1 \n\t" +- "stxvd2x 47, %11, %1 \n\t" +- +- "addi %1, %1, 128 \n\t" +- +- "stxvd2x 50, 0, %1 \n\t" +- "stxvd2x 51, %5, %1 \n\t" +- "stxvd2x 52, %6, %1 \n\t" +- "stxvd2x 53, %7, %1 \n\t" +- "stxvd2x 54, %8, %1 \n\t" +- "stxvd2x 55, %9, %1 \n\t" +- "stxvd2x 56, %10, %1 \n\t" +- "stxvd2x 57, %11, %1 \n\t" +- +- +- : +- : +- "r" (i), // 0 +- "r" (y1), // 1 +- "r" (x1), // 2 +- "r" (alpha), // 3 +- "r" (pre), // 4 +- "r" (o16), // 5 +- "r" (o32), // 6 +- "r" (o48), // 7 +- "r" (o64), // 8 +- "r" (o80), // 9 +- "r" (o96), // 10 +- "r" (o112) // 11 +- : "cr0", "%0", "%2" , "%1", "memory" +- ); +- +-} +- +- ++ __asm__ ++ ( ++ "lxvd2x 32, 0, %2 \n\t" ++ "lxvd2x 33, %5, %2 \n\t" ++ "lxvd2x 34, %6, %2 \n\t" ++ "lxvd2x 35, %7, %2 \n\t" ++ "lxvd2x 36, %8, %2 \n\t" ++ "lxvd2x 37, %9, %2 \n\t" ++ "lxvd2x 38, %10, %2 \n\t" ++ "lxvd2x 39, %11, %2 \n\t" ++ ++ "addi %2, %2, 128 \n\t" ++ ++ "lxvd2x 40, 0, %2 \n\t" ++ "lxvd2x 41, %5, %2 \n\t" ++ "lxvd2x 42, %6, %2 \n\t" ++ "lxvd2x 43, %7, %2 \n\t" ++ "lxvd2x 44, %8, %2 \n\t" ++ "lxvd2x 45, %9, %2 \n\t" ++ "lxvd2x 46, %10, %2 \n\t" ++ "lxvd2x 47, %11, %2 \n\t" ++ ++ "addi %2, %2, 128 \n\t" ++ ++ "addic. %1, %1, -16 \n\t" ++ "ble 2f \n\t" ++ ++ ".p2align 5 \n" ++ "1: \n\t" ++ ++ "stxvd2x 32, 0, %3 \n\t" ++ "stxvd2x 33, %5, %3 \n\t" ++ "lxvd2x 32, 0, %2 \n\t" ++ "lxvd2x 33, %5, %2 \n\t" ++ "stxvd2x 34, %6, %3 \n\t" ++ "stxvd2x 35, %7, %3 \n\t" ++ "lxvd2x 34, %6, %2 \n\t" ++ "lxvd2x 35, %7, %2 \n\t" ++ "stxvd2x 36, %8, %3 \n\t" ++ "stxvd2x 37, %9, %3 \n\t" ++ "lxvd2x 36, %8, %2 \n\t" ++ "lxvd2x 37, %9, %2 \n\t" ++ "stxvd2x 38, %10, %3 \n\t" ++ "stxvd2x 39, %11, %3 \n\t" ++ "lxvd2x 38, %10, %2 \n\t" ++ "lxvd2x 39, %11, %2 \n\t" ++ ++ "addi %3, %3, 128 \n\t" ++ "addi %2, %2, 128 \n\t" ++ ++ "stxvd2x 40, 0, %3 \n\t" ++ "stxvd2x 41, %5, %3 \n\t" ++ "lxvd2x 40, 0, %2 \n\t" ++ "lxvd2x 41, %5, %2 \n\t" ++ "stxvd2x 42, %6, %3 \n\t" ++ "stxvd2x 43, %7, %3 \n\t" ++ "lxvd2x 42, %6, %2 \n\t" ++ "lxvd2x 43, %7, %2 \n\t" ++ "stxvd2x 44, %8, %3 \n\t" ++ "stxvd2x 45, %9, %3 \n\t" ++ "lxvd2x 44, %8, %2 \n\t" ++ "lxvd2x 45, %9, %2 \n\t" ++ "stxvd2x 46, %10, %3 \n\t" ++ "stxvd2x 47, %11, %3 \n\t" ++ "lxvd2x 46, %10, %2 \n\t" ++ "lxvd2x 47, %11, %2 \n\t" ++ ++ "addi %3, %3, 128 \n\t" ++ "addi %2, %2, 128 \n\t" ++ ++ "addic. %1, %1, -16 \n\t" ++ "bgt 1b \n" ++ ++ "2: \n\t" ++ ++ "stxvd2x 32, 0, %3 \n\t" ++ "stxvd2x 33, %5, %3 \n\t" ++ "stxvd2x 34, %6, %3 \n\t" ++ "stxvd2x 35, %7, %3 \n\t" ++ "stxvd2x 36, %8, %3 \n\t" ++ "stxvd2x 37, %9, %3 \n\t" ++ "stxvd2x 38, %10, %3 \n\t" ++ "stxvd2x 39, %11, %3 \n\t" ++ ++ "addi %3, %3, 128 \n\t" ++ ++ "stxvd2x 40, 0, %3 \n\t" ++ "stxvd2x 41, %5, %3 \n\t" ++ "stxvd2x 42, %6, %3 \n\t" ++ "stxvd2x 43, %7, %3 \n\t" ++ "stxvd2x 44, %8, %3 \n\t" ++ "stxvd2x 45, %9, %3 \n\t" ++ "stxvd2x 46, %10, %3 \n\t" ++ "stxvd2x 47, %11, %3 \n" ++ ++ "#n=%1 x=%4=%2 y=%0=%3 o16=%5 o32=%6 o48=%7 o64=%8 o80=%9 o96=%10 o112=%11" ++ : ++ "=m" (*y), ++ "+r" (n), // 1 ++ "+b" (x), // 2 ++ "+b" (y) // 3 ++ : ++ "m" (*x), ++ "b" (16), // 5 ++ "b" (32), // 6 ++ "b" (48), // 7 ++ "b" (64), // 8 ++ "b" (80), // 9 ++ "b" (96), // 10 ++ "b" (112) // 11 ++ : ++ "cr0", ++ "vs32","vs33","vs34","vs35","vs36","vs37","vs38","vs39", ++ "vs40","vs41","vs42","vs43","vs44","vs45","vs46","vs47" ++ ); ++} +diff --git a/kernel/power/zdot.c b/kernel/power/zdot.c +index bc1a95e..b83f832 100644 +--- a/kernel/power/zdot.c ++++ b/kernel/power/zdot.c +@@ -43,8 +43,6 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + #ifndef HAVE_KERNEL_8 + +-static void zdot_kernel_8(BLASLONG n, FLOAT *x, FLOAT *y, FLOAT *d) __attribute__ ((noinline)); +- + static void zdot_kernel_8(BLASLONG n, FLOAT *x, FLOAT *y, FLOAT *d) + { + BLASLONG register i = 0; +diff --git a/kernel/power/zdot_microk_power8.c b/kernel/power/zdot_microk_power8.c +index 296d3d4..71078b6 100644 +--- a/kernel/power/zdot_microk_power8.c ++++ b/kernel/power/zdot_microk_power8.c +@@ -34,186 +34,174 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + **************************************************************************************/ + + #define HAVE_KERNEL_8 1 +-static void zdot_kernel_8( BLASLONG n, FLOAT *x, FLOAT *y , FLOAT *dot) __attribute__ ((noinline)); + +-static void zdot_kernel_8( BLASLONG n, FLOAT *x, FLOAT *y, FLOAT *dot) ++static void zdot_kernel_8 (long n, double *x, double *y, double *dot) + { +- +- +- BLASLONG i = n; +- BLASLONG o16 = 16; +- BLASLONG o32 = 32; +- BLASLONG o48 = 48; +- FLOAT *x1=x; +- FLOAT *y1=y; +- BLASLONG pre = 384; +- +- __asm__ __volatile__ +- ( +- "xxlxor 32,32,32 \n\t" +- "xxlxor 33,33,33 \n\t" +- "xxlxor 34,34,34 \n\t" +- "xxlxor 35,35,35 \n\t" +- "xxlxor 36,36,36 \n\t" +- "xxlxor 37,37,37 \n\t" +- "xxlxor 38,38,38 \n\t" +- "xxlxor 39,39,39 \n\t" +- +- "dcbt %2, %8 \n\t" +- "dcbt %3, %8 \n\t" +- +- "lxvd2x 40, 0, %2 \n\t" // x0_r, x0_i +- "lxvd2x 48, 0, %3 \n\t" // y0_r, y0_i +- "lxvd2x 41, %5, %2 \n\t" // x1_r, x1_i +- "lxvd2x 49, %5, %3 \n\t" // y1_r, y1_i +- "lxvd2x 42, %6, %2 \n\t" // x2_r, x2_i +- "lxvd2x 50, %6, %3 \n\t" // y2_r, y2_i +- "lxvd2x 43, %7, %2 \n\t" // x3_r, x3_i +- "lxvd2x 51, %7, %3 \n\t" // y3_r, y3_i +- +- "xxswapd 52,48 \n\t" // y0_i, y0_r +- "xxswapd 53,49 \n\t" // y1_i, y1_r +- "xxswapd 54,50 \n\t" // y2_i, y2_r +- "xxswapd 55,51 \n\t" // y3_i, y3_r +- +- "addi %2, %2, 64 \n\t" +- "addi %3, %3, 64 \n\t" +- +- +- "lxvd2x 44, 0, %2 \n\t" // x0_r, x0_i +- "lxvd2x 56, 0, %3 \n\t" // y0_r, y0_i +- "lxvd2x 45, %5, %2 \n\t" // x1_r, x1_i +- "lxvd2x 57, %5, %3 \n\t" // y1_r, y1_i +- "lxvd2x 46, %6, %2 \n\t" // x2_r, x2_i +- "lxvd2x 58, %6, %3 \n\t" // y2_r, y2_i +- "lxvd2x 47, %7, %2 \n\t" // x3_r, x3_i +- "lxvd2x 59, %7, %3 \n\t" // y3_r, y3_i +- +- "xxswapd 60,56 \n\t" // y0_i, y0_r +- "xxswapd 61,57 \n\t" // y1_i, y1_r +- "xxswapd 62,58 \n\t" // y2_i, y2_r +- "xxswapd 63,59 \n\t" // y3_i, y3_r +- +- "addi %2, %2, 64 \n\t" +- "addi %3, %3, 64 \n\t" +- +- "addic. %0 , %0 , -8 \n\t" +- "ble 2f \n\t" +- +- ".align 5 \n\t" +- "1: \n\t" +- +- "dcbt %2, %8 \n\t" +- "dcbt %3, %8 \n\t" +- +- "xvmaddadp 32, 40, 48 \n\t" // x0_r * y0_r , x0_i * y0_i +- "lxvd2x 48, 0, %3 \n\t" // y0_r, y0_i +- "xvmaddadp 34, 41, 49 \n\t" // x1_r * y1_r , x1_i * y1_i +- "lxvd2x 49, %5, %3 \n\t" // y1_r, y1_i +- +- "xvmaddadp 36, 42, 50 \n\t" // x2_r * y2_r , x2_i * y2_i +- "lxvd2x 50, %6, %3 \n\t" // y2_r, y2_i +- "xvmaddadp 38, 43, 51 \n\t" // x3_r * y3_r , x3_i * y3_i +- "lxvd2x 51, %7, %3 \n\t" // y3_r, y3_i +- +- "xvmaddadp 33, 40, 52 \n\t" // x0_r * y0_i , x0_i * y0_r +- "lxvd2x 40, 0, %2 \n\t" // x0_r, x0_i +- "xvmaddadp 35, 41, 53 \n\t" // x1_r * y1_i , x1_i * y1_r +- "lxvd2x 41, %5, %2 \n\t" // x1_r, x1_i +- +- "xvmaddadp 37, 42, 54 \n\t" // x2_r * y2_i , x2_i * y2_r +- "lxvd2x 42, %6, %2 \n\t" // x2_r, x2_i +- "xvmaddadp 39, 43, 55 \n\t" // x3_r * y3_i , x3_i * y3_r +- "lxvd2x 43, %7, %2 \n\t" // x3_r, x3_i +- +- "xxswapd 52,48 \n\t" // y0_i, y0_r +- "xxswapd 53,49 \n\t" // y1_i, y1_r +- +- "addi %2, %2, 64 \n\t" +- "addi %3, %3, 64 \n\t" +- +- "xxswapd 54,50 \n\t" // y2_i, y2_r +- "xxswapd 55,51 \n\t" // y3_i, y3_r +- +- "xvmaddadp 32, 44, 56 \n\t" // x0_r * y0_r , x0_i * y0_i +- "lxvd2x 56, 0, %3 \n\t" // y0_r, y0_i +- "xvmaddadp 34, 45, 57 \n\t" // x1_r * y1_r , x1_i * y1_i +- "lxvd2x 57, %5, %3 \n\t" // y1_r, y1_i +- "xvmaddadp 36, 46, 58 \n\t" // x2_r * y2_r , x2_i * y2_i +- "lxvd2x 58, %6, %3 \n\t" // y2_r, y2_i +- "xvmaddadp 38, 47, 59 \n\t" // x3_r * y3_r , x3_i * y3_i +- "lxvd2x 59, %7, %3 \n\t" // y3_r, y3_i +- +- "xvmaddadp 33, 44, 60 \n\t" // x0_r * y0_i , x0_i * y0_r +- "lxvd2x 44, 0, %2 \n\t" // x0_r, x0_i +- "xvmaddadp 35, 45, 61 \n\t" // x1_r * y1_i , x1_i * y1_r +- "lxvd2x 45, %5, %2 \n\t" // x1_r, x1_i +- "xvmaddadp 37, 46, 62 \n\t" // x2_r * y2_i , x2_i * y2_r +- "lxvd2x 46, %6, %2 \n\t" // x2_r, x2_i +- "xvmaddadp 39, 47, 63 \n\t" // x3_r * y3_i , x3_i * y3_r +- "lxvd2x 47, %7, %2 \n\t" // x3_r, x3_i +- +- "xxswapd 60,56 \n\t" // y0_i, y0_r +- "xxswapd 61,57 \n\t" // y1_i, y1_r +- +- "addi %2, %2, 64 \n\t" +- "addi %3, %3, 64 \n\t" +- +- "xxswapd 62,58 \n\t" // y2_i, y2_r +- "xxswapd 63,59 \n\t" // y3_i, y3_r +- +- "addic. %0 , %0 , -8 \n\t" +- "bgt 1b \n\t" +- +- "2: \n\t" +- +- "xvmaddadp 32, 40, 48 \n\t" // x0_r * y0_r , x0_i * y0_i +- "xvmaddadp 34, 41, 49 \n\t" // x1_r * y1_r , x1_i * y1_i +- "xvmaddadp 36, 42, 50 \n\t" // x2_r * y2_r , x2_i * y2_i +- "xvmaddadp 38, 43, 51 \n\t" // x3_r * y3_r , x3_i * y3_i +- +- "xvmaddadp 33, 40, 52 \n\t" // x0_r * y0_i , x0_i * y0_r +- "xvmaddadp 35, 41, 53 \n\t" // x1_r * y1_i , x1_i * y1_r +- "xvmaddadp 37, 42, 54 \n\t" // x2_r * y2_i , x2_i * y2_r +- "xvmaddadp 39, 43, 55 \n\t" // x3_r * y3_i , x3_i * y3_r +- +- "xvmaddadp 32, 44, 56 \n\t" // x0_r * y0_r , x0_i * y0_i +- "xvmaddadp 34, 45, 57 \n\t" // x1_r * y1_r , x1_i * y1_i +- "xvmaddadp 36, 46, 58 \n\t" // x2_r * y2_r , x2_i * y2_i +- "xvmaddadp 38, 47, 59 \n\t" // x3_r * y3_r , x3_i * y3_i +- +- "xvmaddadp 33, 44, 60 \n\t" // x0_r * y0_i , x0_i * y0_r +- "xvmaddadp 35, 45, 61 \n\t" // x1_r * y1_i , x1_i * y1_r +- "xvmaddadp 37, 46, 62 \n\t" // x2_r * y2_i , x2_i * y2_r +- "xvmaddadp 39, 47, 63 \n\t" // x3_r * y3_i , x3_i * y3_r +- +- +- "xvadddp 32, 32, 34 \n\t" +- "xvadddp 36, 36, 38 \n\t" +- +- "xvadddp 33, 33, 35 \n\t" +- "xvadddp 37, 37, 39 \n\t" +- +- "xvadddp 32, 32, 36 \n\t" +- "xvadddp 33, 33, 37 \n\t" +- +- "stxvd2x 32, 0, %4 \n\t" +- "stxvd2x 33, %5, %4 \n\t" +- +- : +- : +- "r" (i), // 0 +- "r" (n), // 1 +- "r" (x1), // 2 +- "r" (y1), // 3 +- "r" (dot), // 4 +- "r" (o16), // 5 +- "r" (o32), // 6 +- "r" (o48), // 7 +- "r" (pre) // 8 +- : "cr0", "%0", "%2" , "%3", "memory" +- ); +- +-} +- +- ++ __asm__ ++ ( ++ "dcbt 0, %2 \n\t" ++ "dcbt 0, %3 \n\t" ++ ++ "xxlxor 32, 32, 32 \n\t" ++ "xxlxor 33, 33, 33 \n\t" ++ "xxlxor 34, 34, 34 \n\t" ++ "xxlxor 35, 35, 35 \n\t" ++ "xxlxor 36, 36, 36 \n\t" ++ "xxlxor 37, 37, 37 \n\t" ++ "xxlxor 38, 38, 38 \n\t" ++ "xxlxor 39, 39, 39 \n\t" ++ ++ "lxvd2x 40, 0, %2 \n\t" // x0_r, x0_i ++ "lxvd2x 48, 0, %3 \n\t" // y0_r, y0_i ++ "lxvd2x 41, %7, %2 \n\t" // x1_r, x1_i ++ "lxvd2x 49, %7, %3 \n\t" // y1_r, y1_i ++ "lxvd2x 42, %8, %2 \n\t" // x2_r, x2_i ++ "lxvd2x 50, %8, %3 \n\t" // y2_r, y2_i ++ "lxvd2x 43, %9, %2 \n\t" // x3_r, x3_i ++ "lxvd2x 51, %9, %3 \n\t" // y3_r, y3_i ++ ++ "xxswapd 0, 48 \n\t" // y0_i, y0_r ++ "xxswapd 1, 49 \n\t" // y1_i, y1_r ++ "xxswapd 2, 50 \n\t" // y2_i, y2_r ++ "xxswapd 3, 51 \n\t" // y3_i, y3_r ++ ++ "addi %2, %2, 64 \n\t" ++ "addi %3, %3, 64 \n\t" ++ ++ "lxvd2x 44, 0, %2 \n\t" // x0_r, x0_i ++ "lxvd2x 4, 0, %3 \n\t" // y0_r, y0_i ++ "lxvd2x 45, %7, %2 \n\t" // x1_r, x1_i ++ "lxvd2x 5, %7, %3 \n\t" // y1_r, y1_i ++ "lxvd2x 46, %8, %2 \n\t" // x2_r, x2_i ++ "lxvd2x 6, %8, %3 \n\t" // y2_r, y2_i ++ "lxvd2x 47, %9, %2 \n\t" // x3_r, x3_i ++ "lxvd2x 7, %9, %3 \n\t" // y3_r, y3_i ++ ++ "xxswapd 8, 4 \n\t" // y0_i, y0_r ++ "xxswapd 9, 5 \n\t" // y1_i, y1_r ++ "xxswapd 10, 6 \n\t" // y2_i, y2_r ++ "xxswapd 11, 7 \n\t" // y3_i, y3_r ++ ++ "addi %2, %2, 64 \n\t" ++ "addi %3, %3, 64 \n\t" ++ ++ "addic. %1, %1, -8 \n\t" ++ "ble 2f \n\t" ++ ++ ".p2align 5 \n" ++ "1: \n\t" ++ ++ "xvmaddadp 32, 40, 48 \n\t" // x0_r * y0_r , x0_i * y0_i ++ "lxvd2x 48, 0, %3 \n\t" // y0_r, y0_i ++ "xvmaddadp 34, 41, 49 \n\t" // x1_r * y1_r , x1_i * y1_i ++ "lxvd2x 49, %7, %3 \n\t" // y1_r, y1_i ++ ++ "xvmaddadp 36, 42, 50 \n\t" // x2_r * y2_r , x2_i * y2_i ++ "lxvd2x 50, %8, %3 \n\t" // y2_r, y2_i ++ "xvmaddadp 38, 43, 51 \n\t" // x3_r * y3_r , x3_i * y3_i ++ "lxvd2x 51, %9, %3 \n\t" // y3_r, y3_i ++ ++ "xvmaddadp 33, 40, 0 \n\t" // x0_r * y0_i , x0_i * y0_r ++ "lxvd2x 40, 0, %2 \n\t" // x0_r, x0_i ++ "xvmaddadp 35, 41, 1 \n\t" // x1_r * y1_i , x1_i * y1_r ++ "lxvd2x 41, %7, %2 \n\t" // x1_r, x1_i ++ ++ "xvmaddadp 37, 42, 2 \n\t" // x2_r * y2_i , x2_i * y2_r ++ "lxvd2x 42, %8, %2 \n\t" // x2_r, x2_i ++ "xvmaddadp 39, 43, 3 \n\t" // x3_r * y3_i , x3_i * y3_r ++ "lxvd2x 43, %9, %2 \n\t" // x3_r, x3_i ++ ++ "xxswapd 0,48 \n\t" // y0_i, y0_r ++ "xxswapd 1,49 \n\t" // y1_i, y1_r ++ ++ "addi %2, %2, 64 \n\t" ++ "addi %3, %3, 64 \n\t" ++ ++ "xxswapd 2,50 \n\t" // y2_i, y2_r ++ "xxswapd 3,51 \n\t" // y3_i, y3_r ++ ++ "xvmaddadp 32, 44, 4 \n\t" // x0_r * y0_r , x0_i * y0_i ++ "lxvd2x 4, 0, %3 \n\t" // y0_r, y0_i ++ "xvmaddadp 34, 45, 5 \n\t" // x1_r * y1_r , x1_i * y1_i ++ "lxvd2x 5, %7, %3 \n\t" // y1_r, y1_i ++ "xvmaddadp 36, 46, 6 \n\t" // x2_r * y2_r , x2_i * y2_i ++ "lxvd2x 6, %8, %3 \n\t" // y2_r, y2_i ++ "xvmaddadp 38, 47, 7 \n\t" // x3_r * y3_r , x3_i * y3_i ++ "lxvd2x 7, %9, %3 \n\t" // y3_r, y3_i ++ ++ "xvmaddadp 33, 44, 8 \n\t" // x0_r * y0_i , x0_i * y0_r ++ "lxvd2x 44, 0, %2 \n\t" // x0_r, x0_i ++ "xvmaddadp 35, 45, 9 \n\t" // x1_r * y1_i , x1_i * y1_r ++ "lxvd2x 45, %7, %2 \n\t" // x1_r, x1_i ++ "xvmaddadp 37, 46, 10 \n\t" // x2_r * y2_i , x2_i * y2_r ++ "lxvd2x 46, %8, %2 \n\t" // x2_r, x2_i ++ "xvmaddadp 39, 47, 11 \n\t" // x3_r * y3_i , x3_i * y3_r ++ "lxvd2x 47, %9, %2 \n\t" // x3_r, x3_i ++ ++ "xxswapd 8,4 \n\t" // y0_i, y0_r ++ "xxswapd 9,5 \n\t" // y1_i, y1_r ++ ++ "addi %2, %2, 64 \n\t" ++ "addi %3, %3, 64 \n\t" ++ ++ "xxswapd 10,6 \n\t" // y2_i, y2_r ++ "xxswapd 11,7 \n\t" // y3_i, y3_r ++ ++ "addic. %1, %1, -8 \n\t" ++ "bgt 1b \n" ++ ++ "2: \n\t" ++ ++ "xvmaddadp 32, 40, 48 \n\t" // x0_r * y0_r , x0_i * y0_i ++ "xvmaddadp 34, 41, 49 \n\t" // x1_r * y1_r , x1_i * y1_i ++ "xvmaddadp 36, 42, 50 \n\t" // x2_r * y2_r , x2_i * y2_i ++ "xvmaddadp 38, 43, 51 \n\t" // x3_r * y3_r , x3_i * y3_i ++ ++ "xvmaddadp 33, 40, 0 \n\t" // x0_r * y0_i , x0_i * y0_r ++ "xvmaddadp 35, 41, 1 \n\t" // x1_r * y1_i , x1_i * y1_r ++ "xvmaddadp 37, 42, 2 \n\t" // x2_r * y2_i , x2_i * y2_r ++ "xvmaddadp 39, 43, 3 \n\t" // x3_r * y3_i , x3_i * y3_r ++ ++ "xvmaddadp 32, 44, 4 \n\t" // x0_r * y0_r , x0_i * y0_i ++ "xvmaddadp 34, 45, 5 \n\t" // x1_r * y1_r , x1_i * y1_i ++ "xvmaddadp 36, 46, 6 \n\t" // x2_r * y2_r , x2_i * y2_i ++ "xvmaddadp 38, 47, 7 \n\t" // x3_r * y3_r , x3_i * y3_i ++ ++ "xvmaddadp 33, 44, 8 \n\t" // x0_r * y0_i , x0_i * y0_r ++ "xvmaddadp 35, 45, 9 \n\t" // x1_r * y1_i , x1_i * y1_r ++ "xvmaddadp 37, 46, 10 \n\t" // x2_r * y2_i , x2_i * y2_r ++ "xvmaddadp 39, 47, 11 \n\t" // x3_r * y3_i , x3_i * y3_r ++ ++ "xvadddp 32, 32, 34 \n\t" ++ "xvadddp 36, 36, 38 \n\t" ++ ++ "xvadddp 33, 33, 35 \n\t" ++ "xvadddp 37, 37, 39 \n\t" ++ ++ "xvadddp 32, 32, 36 \n\t" ++ "xvadddp 33, 33, 37 \n\t" ++ ++ "stxvd2x 32, 0, %6 \n\t" ++ "stxvd2x 33, %7, %6 \n" ++ ++ "#n=%1 x=%4=%2 y=%5=%3 dot=%0=%6 o16=%7 o32=%8 o48=%9" ++ : ++ "=m" (*dot), ++ "+r" (n), // 1 ++ "+b" (x), // 2 ++ "+b" (y) // 3 ++ : ++ "m" (*x), ++ "m" (*y), ++ "b" (dot), // 6 ++ "b" (16), // 7 ++ "b" (32), // 8 ++ "b" (48) // 9 ++ : ++ "cr0", ++ "vs32","vs33","vs34","vs35","vs36","vs37","vs38","vs39", ++ "vs40","vs41","vs42","vs43","vs44","vs45","vs46","vs47", ++ "vs48","vs49","vs50","vs51","vs0","vs1","vs2","vs3", ++ "vs4","vs5","vs6","vs7","vs8","vs9","vs10","vs11" ++ ); ++} +diff --git a/kernel/power/zscal.c b/kernel/power/zscal.c +index 410fc98..14d677f 100644 +--- a/kernel/power/zscal.c ++++ b/kernel/power/zscal.c +@@ -47,15 +47,15 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + #ifndef HAVE_KERNEL_8 + +-static void zscal_kernel_8(BLASLONG n, FLOAT *x, FLOAT *alpha) ++static void zscal_kernel_8(BLASLONG n, FLOAT *x, FLOAT da_r, FLOAT da_i) + { + + BLASLONG i=0; + FLOAT *x1=x; +- FLOAT alpha_r1=alpha[0]; +- FLOAT alpha_r2=alpha[1]; +- FLOAT alpha_i1=alpha[2]; +- FLOAT alpha_i2=alpha[3]; ++ FLOAT alpha_r1=da_r; ++ FLOAT alpha_r2=da_r; ++ FLOAT alpha_i1=-da_i; ++ FLOAT alpha_i2=da_i; + FLOAT temp00, temp01, temp10, temp11, temp20, temp21, temp30, temp31; + FLOAT x0_r, x0_i, x1_r, x1_i, x2_r, x2_i, x3_r, x3_i; + +@@ -116,7 +116,6 @@ int CNAME(BLASLONG n, BLASLONG dummy0, BLASLONG dummy1, FLOAT da_r,FLOAT da_i, F + BLASLONG inc_x2; + BLASLONG ip = 0; + FLOAT temp; +- FLOAT alpha[4] __attribute__ ((aligned (16)));; + BLASLONG n1; + + if ( n <= 0 ) +@@ -147,11 +146,7 @@ int CNAME(BLASLONG n, BLASLONG dummy0, BLASLONG dummy1, FLOAT da_r,FLOAT da_i, F + n1 = n & -8; + if ( n1 > 0 ) + { +- alpha[0] = da_r; +- alpha[1] = da_r; +- alpha[2] = -da_i; +- alpha[3] = da_i; +- zscal_kernel_8(n1, x, alpha); ++ zscal_kernel_8(n1, x, da_r, da_i); + i=n1; + ip = n1 * 2; + +diff --git a/kernel/power/zscal_microk_power8.c b/kernel/power/zscal_microk_power8.c +index 5e09d8d..aba9029 100644 +--- a/kernel/power/zscal_microk_power8.c ++++ b/kernel/power/zscal_microk_power8.c +@@ -38,187 +38,202 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + #define HAVE_KERNEL_8 1 + +-static void zscal_kernel_8( BLASLONG n, FLOAT *x, FLOAT *alpha) __attribute__ ((noinline)); +- +-static void zscal_kernel_8( BLASLONG n, FLOAT *x, FLOAT *alpha) ++static void zscal_kernel_8 (long n, double *x, double alpha_r, double alpha_i) + { +- +- +- BLASLONG i = n; +- BLASLONG o16 = 16; +- BLASLONG o32 = 32; +- BLASLONG o48 = 48; +- BLASLONG o64 = 64; +- BLASLONG o80 = 80; +- BLASLONG o96 = 96; +- BLASLONG o112 = 112; +- FLOAT *x1=x; +- FLOAT *x2=x+1; +- BLASLONG pre = 384; +- +- __asm__ __volatile__ +- ( +- +- "lxvd2x 32, 0, %3 \n\t" // alpha_r , alpha_r +- "lxvd2x 33, %5, %3 \n\t" // -alpha_i , alpha_i +- "addi %1, %1, -8 \n\t" +- +- "dcbt %2, %4 \n\t" +- +- "lxvd2x 40, 0, %2 \n\t" // x0_r, x0_i +- "lxvd2x 41, %5, %2 \n\t" +- "lxvd2x 42, %6, %2 \n\t" +- "lxvd2x 43, %7, %2 \n\t" +- "lxvd2x 44, %8, %2 \n\t" +- "lxvd2x 45, %9, %2 \n\t" +- "lxvd2x 46, %10, %2 \n\t" +- "lxvd2x 47, %11, %2 \n\t" +- +- "addi %2, %2, 128 \n\t" +- +- "addic. %0 , %0 , -8 \n\t" +- "ble 2f \n\t" +- +- ".align 5 \n\t" +- "1: \n\t" +- +- "dcbt %2, %4 \n\t" +- +- "xvmuldp 48, 40, 32 \n\t" // x0_r * alpha_r, x0_i * alpha_r +- "xvmuldp 49, 41, 32 \n\t" +- "xvmuldp 50, 42, 32 \n\t" +- "xvmuldp 51, 43, 32 \n\t" +- "xvmuldp 52, 44, 32 \n\t" +- "xvmuldp 53, 45, 32 \n\t" +- "xvmuldp 54, 46, 32 \n\t" +- "xvmuldp 55, 47, 32 \n\t" +- +- "xxswapd 56, 40 \n\t" +- "xxswapd 57, 41 \n\t" +- "xxswapd 58, 42 \n\t" +- "xxswapd 59, 43 \n\t" +- "xxswapd 60, 44 \n\t" +- "xxswapd 61, 45 \n\t" +- "xxswapd 62, 46 \n\t" +- "xxswapd 63, 47 \n\t" +- +- "xvmuldp 56, 56, 33 \n\t" // x0_i * -alpha_i, x0_r * alpha_i +- "xvmuldp 57, 57, 33 \n\t" +- +- "lxvd2x 40, 0, %2 \n\t" // x0_r, x0_i +- "lxvd2x 41, %5, %2 \n\t" +- +- "xvmuldp 58, 58, 33 \n\t" +- "xvmuldp 59, 59, 33 \n\t" +- +- "lxvd2x 42, %6, %2 \n\t" +- "lxvd2x 43, %7, %2 \n\t" +- +- "xvmuldp 60, 60, 33 \n\t" +- "xvmuldp 61, 61, 33 \n\t" +- +- "lxvd2x 44, %8, %2 \n\t" +- "lxvd2x 45, %9, %2 \n\t" +- +- "xvmuldp 62, 62, 33 \n\t" +- "xvmuldp 63, 63, 33 \n\t" +- +- "lxvd2x 46, %10, %2 \n\t" +- "lxvd2x 47, %11, %2 \n\t" +- +- "xvadddp 48, 48 , 56 \n\t" +- "xvadddp 49, 49 , 57 \n\t" +- "xvadddp 50, 50 , 58 \n\t" +- "xvadddp 51, 51 , 59 \n\t" +- +- "stxvd2x 48, 0, %1 \n\t" +- "stxvd2x 49, %5, %1 \n\t" +- +- "xvadddp 52, 52 , 60 \n\t" +- "xvadddp 53, 53 , 61 \n\t" +- +- "stxvd2x 50, %6, %1 \n\t" +- "stxvd2x 51, %7, %1 \n\t" +- +- "xvadddp 54, 54 , 62 \n\t" +- "xvadddp 55, 55 , 63 \n\t" +- +- "stxvd2x 52, %8, %1 \n\t" +- "stxvd2x 53, %9, %1 \n\t" +- "stxvd2x 54, %10, %1 \n\t" +- "stxvd2x 55, %11, %1 \n\t" +- +- "addi %1, %1, 128 \n\t" +- "addi %2, %2, 128 \n\t" +- +- "addic. %0 , %0 , -8 \n\t" +- "bgt 1b \n\t" +- +- "2: \n\t" +- +- "xvmuldp 48, 40, 32 \n\t" // x0_r * alpha_r, x0_i * alpha_r +- "xvmuldp 49, 41, 32 \n\t" +- "xvmuldp 50, 42, 32 \n\t" +- "xvmuldp 51, 43, 32 \n\t" +- "xvmuldp 52, 44, 32 \n\t" +- "xvmuldp 53, 45, 32 \n\t" +- "xvmuldp 54, 46, 32 \n\t" +- "xvmuldp 55, 47, 32 \n\t" +- +- "xxswapd 56, 40 \n\t" +- "xxswapd 57, 41 \n\t" +- "xxswapd 58, 42 \n\t" +- "xxswapd 59, 43 \n\t" +- "xxswapd 60, 44 \n\t" +- "xxswapd 61, 45 \n\t" +- "xxswapd 62, 46 \n\t" +- "xxswapd 63, 47 \n\t" +- +- "xvmuldp 56, 56, 33 \n\t" // x0_i * -alpha_i, x0_r * alpha_i +- "xvmuldp 57, 57, 33 \n\t" +- "xvmuldp 58, 58, 33 \n\t" +- "xvmuldp 59, 59, 33 \n\t" +- "xvmuldp 60, 60, 33 \n\t" +- "xvmuldp 61, 61, 33 \n\t" +- "xvmuldp 62, 62, 33 \n\t" +- "xvmuldp 63, 63, 33 \n\t" +- +- "xvadddp 48, 48 , 56 \n\t" +- "xvadddp 49, 49 , 57 \n\t" +- "xvadddp 50, 50 , 58 \n\t" +- "xvadddp 51, 51 , 59 \n\t" +- "xvadddp 52, 52 , 60 \n\t" +- "xvadddp 53, 53 , 61 \n\t" +- "xvadddp 54, 54 , 62 \n\t" +- "xvadddp 55, 55 , 63 \n\t" +- +- "stxvd2x 48, 0, %1 \n\t" +- "stxvd2x 49, %5, %1 \n\t" +- "stxvd2x 50, %6, %1 \n\t" +- "stxvd2x 51, %7, %1 \n\t" +- "stxvd2x 52, %8, %1 \n\t" +- "stxvd2x 53, %9, %1 \n\t" +- "stxvd2x 54, %10, %1 \n\t" +- "stxvd2x 55, %11, %1 \n\t" +- +- +- : +- : +- "r" (i), // 0 +- "r" (x2), // 1 +- "r" (x1), // 2 +- "r" (alpha), // 3 +- "r" (pre), // 4 +- "r" (o16), // 5 +- "r" (o32), // 6 +- "r" (o48), // 7 +- "r" (o64), // 8 +- "r" (o80), // 9 +- "r" (o96), // 10 +- "r" (o112) // 11 +- : "cr0", "%0", "%2" , "%1", "memory" +- ); +- +-} +- +- ++ __vector double t0; ++ __vector double t1; ++ __vector double t2; ++ __vector double t3; ++ __vector double t4; ++ __vector double t5; ++ __vector double t6; ++ __vector double t7; ++ __vector double t8; ++ __vector double t9; ++ __vector double t10; ++ __vector double t11; ++ ++ __asm__ ++ ( ++ "dcbt 0, %2 \n\t" ++ ++ "xsnegdp 33, %x16 \n\t" // -alpha_i ++ "xxspltd 32, %x15, 0 \n\t" // alpha_r , alpha_r ++ "xxmrghd 33, 33, %x16 \n\t" // -alpha_i , alpha_i ++ ++ "lxvd2x 40, 0, %2 \n\t" // x0_r, x0_i ++ "lxvd2x 41, %17, %2 \n\t" ++ "lxvd2x 42, %18, %2 \n\t" ++ "lxvd2x 43, %19, %2 \n\t" ++ "lxvd2x 44, %20, %2 \n\t" ++ "lxvd2x 45, %21, %2 \n\t" ++ "lxvd2x 46, %22, %2 \n\t" ++ "lxvd2x 47, %23, %2 \n\t" ++ ++ "addi %2, %2, 128 \n\t" ++ ++ "addic. %1, %1, -8 \n\t" ++ "ble 2f \n\t" ++ ++ ".p2align 5 \n" ++ "1: \n\t" ++ ++ "xvmuldp 48, 40, 32 \n\t" // x0_r * alpha_r, x0_i * alpha_r ++ "xvmuldp 49, 41, 32 \n\t" ++ "xvmuldp 50, 42, 32 \n\t" ++ "xvmuldp 51, 43, 32 \n\t" ++ "xvmuldp %x3, 44, 32 \n\t" ++ "xvmuldp %x4, 45, 32 \n\t" ++ "xvmuldp %x5, 46, 32 \n\t" ++ "xvmuldp %x6, 47, 32 \n\t" ++ ++ "xxswapd %x7, 40 \n\t" ++ "xxswapd %x8, 41 \n\t" ++ "xxswapd %x9, 42 \n\t" ++ "xxswapd %x10, 43 \n\t" ++ "xxswapd %x11, 44 \n\t" ++ "xxswapd %x12, 45 \n\t" ++ "xxswapd %x13, 46 \n\t" ++ "xxswapd %x14, 47 \n\t" ++ ++ "xvmuldp %x7, %x7, 33 \n\t" // x0_i * -alpha_i, x0_r * alpha_i ++ "xvmuldp %x8, %x8, 33 \n\t" ++ ++ "lxvd2x 40, 0, %2 \n\t" // x0_r, x0_i ++ "lxvd2x 41, %17, %2 \n\t" ++ ++ "xvmuldp %x9, %x9, 33 \n\t" ++ "xvmuldp %x10, %x10, 33 \n\t" ++ ++ "lxvd2x 42, %18, %2 \n\t" ++ "lxvd2x 43, %19, %2 \n\t" ++ ++ "xvmuldp %x11, %x11, 33 \n\t" ++ "xvmuldp %x12, %x12, 33 \n\t" ++ ++ "lxvd2x 44, %20, %2 \n\t" ++ "lxvd2x 45, %21, %2 \n\t" ++ ++ "xvmuldp %x13, %x13, 33 \n\t" ++ "xvmuldp %x14, %x14, 33 \n\t" ++ ++ "lxvd2x 46, %22, %2 \n\t" ++ "lxvd2x 47, %23, %2 \n\t" ++ ++ "addi %2, %2, -128 \n\t" ++ ++ "xvadddp 48, 48, %x7 \n\t" ++ "xvadddp 49, 49, %x8 \n\t" ++ "xvadddp 50, 50, %x9 \n\t" ++ "xvadddp 51, 51, %x10 \n\t" ++ ++ "stxvd2x 48, 0, %2 \n\t" ++ "stxvd2x 49, %17, %2 \n\t" ++ ++ "xvadddp %x3, %x3, %x11 \n\t" ++ "xvadddp %x4, %x4, %x12 \n\t" ++ ++ "stxvd2x 50, %18, %2 \n\t" ++ "stxvd2x 51, %19, %2 \n\t" ++ ++ "xvadddp %x5, %x5, %x13 \n\t" ++ "xvadddp %x6, %x6, %x14 \n\t" ++ ++ "stxvd2x %x3, %20, %2 \n\t" ++ "stxvd2x %x4, %21, %2 \n\t" ++ "stxvd2x %x5, %22, %2 \n\t" ++ "stxvd2x %x6, %23, %2 \n\t" ++ ++ "addi %2, %2, 256 \n\t" ++ ++ "addic. %1, %1, -8 \n\t" ++ "bgt 1b \n" ++ ++ "2: \n\t" ++ ++ "xvmuldp 48, 40, 32 \n\t" // x0_r * alpha_r, x0_i * alpha_r ++ "xvmuldp 49, 41, 32 \n\t" ++ "xvmuldp 50, 42, 32 \n\t" ++ "xvmuldp 51, 43, 32 \n\t" ++ "xvmuldp %x3, 44, 32 \n\t" ++ "xvmuldp %x4, 45, 32 \n\t" ++ "xvmuldp %x5, 46, 32 \n\t" ++ "xvmuldp %x6, 47, 32 \n\t" ++ ++ "xxswapd %x7, 40 \n\t" ++ "xxswapd %x8, 41 \n\t" ++ "xxswapd %x9, 42 \n\t" ++ "xxswapd %x10, 43 \n\t" ++ "xxswapd %x11, 44 \n\t" ++ "xxswapd %x12, 45 \n\t" ++ "xxswapd %x13, 46 \n\t" ++ "xxswapd %x14, 47 \n\t" ++ ++ "addi %2, %2, -128 \n\t" ++ ++ "xvmuldp %x7, %x7, 33 \n\t" // x0_i * -alpha_i, x0_r * alpha_i ++ "xvmuldp %x8, %x8, 33 \n\t" ++ "xvmuldp %x9, %x9, 33 \n\t" ++ "xvmuldp %x10, %x10, 33 \n\t" ++ "xvmuldp %x11, %x11, 33 \n\t" ++ "xvmuldp %x12, %x12, 33 \n\t" ++ "xvmuldp %x13, %x13, 33 \n\t" ++ "xvmuldp %x14, %x14, 33 \n\t" ++ ++ "xvadddp 48, 48, %x7 \n\t" ++ "xvadddp 49, 49, %x8 \n\t" ++ "xvadddp 50, 50, %x9 \n\t" ++ "xvadddp 51, 51, %x10 \n\t" ++ ++ "stxvd2x 48, 0, %2 \n\t" ++ "stxvd2x 49, %17, %2 \n\t" ++ ++ "xvadddp %x3, %x3, %x11 \n\t" ++ "xvadddp %x4, %x4, %x12 \n\t" ++ ++ "stxvd2x 50, %18, %2 \n\t" ++ "stxvd2x 51, %19, %2 \n\t" ++ ++ "xvadddp %x5, %x5, %x13 \n\t" ++ "xvadddp %x6, %x6, %x14 \n\t" ++ ++ "stxvd2x %x3, %20, %2 \n\t" ++ "stxvd2x %x4, %21, %2 \n\t" ++ "stxvd2x %x5, %22, %2 \n\t" ++ "stxvd2x %x6, %23, %2 \n" ++ ++ "#n=%1 x=%0=%2 alpha=(%15,%16) o16=%17 o32=%18 o48=%19 o64=%20 o80=%21 o96=%22 o112=%23\n" ++ "#t0=%x3 t1=%x4 t2=%x5 t3=%x6 t4=%x7 t5=%x8 t6=%x9 t7=%x10 t8=%x11 t9=%x12 t10=%x13 t11=%x14" ++ : ++ "+m" (*x), ++ "+r" (n), // 1 ++ "+b" (x), // 2 ++ "=wa" (t0), // 3 ++ "=wa" (t1), // 4 ++ "=wa" (t2), // 5 ++ "=wa" (t3), // 6 ++ "=wa" (t4), // 7 ++ "=wa" (t5), // 8 ++ "=wa" (t6), // 9 ++ "=wa" (t7), // 10 ++ "=wa" (t8), // 11 ++ "=wa" (t9), // 12 ++ "=wa" (t10), // 13 ++ "=wa" (t11) // 14 ++ : ++ "d" (alpha_r), // 15 ++ "d" (alpha_i), // 16 ++ "b" (16), // 17 ++ "b" (32), // 18 ++ "b" (48), // 19 ++ "b" (64), // 20 ++ "b" (80), // 21 ++ "b" (96), // 22 ++ "b" (112) // 23 ++ : ++ "cr0", ++ "vs32","vs33","vs34","vs35","vs36","vs37","vs38","vs39", ++ "vs40","vs41","vs42","vs43","vs44","vs45","vs46","vs47", ++ "vs48","vs49","vs50","vs51" ++ ); ++} +diff --git a/kernel/power/zswap_microk_power8.c b/kernel/power/zswap_microk_power8.c +index 9e56237..54391ba 100644 +--- a/kernel/power/zswap_microk_power8.c ++++ b/kernel/power/zswap_microk_power8.c +@@ -35,146 +35,123 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + #define HAVE_KERNEL_16 1 + +-static void zswap_kernel_16( BLASLONG n, FLOAT *x, FLOAT *y) __attribute__ ((noinline)); +- +-static void zswap_kernel_16( BLASLONG n, FLOAT *x, FLOAT *y) ++static void ++zswap_kernel_16 (long n, double *x, double *y) + { +- +- +- BLASLONG i = n; +- BLASLONG o16 = 16; +- BLASLONG o32 = 32; +- BLASLONG o48 = 48; +- BLASLONG o64 = 64; +- BLASLONG o80 = 80; +- BLASLONG o96 = 96; +- BLASLONG o112 = 112; +- FLOAT *x1=x; +- FLOAT *y1=y; +- FLOAT *x2=x+1; +- FLOAT *y2=y+1; +- BLASLONG pre = 384; +- BLASLONG alpha=0; +- +- __asm__ __volatile__ +- ( +- +- "addi %3, %3, -8 \n\t" +- "addi %4, %4, -8 \n\t" +- +- ".align 5 \n\t" +- "1: \n\t" +- +- "lxvd2x 32, 0, %2 \n\t" +- "lxvd2x 33, %5, %2 \n\t" +- "lxvd2x 34, %6, %2 \n\t" +- "lxvd2x 35, %7, %2 \n\t" +- "lxvd2x 36, %8, %2 \n\t" +- "lxvd2x 37, %9, %2 \n\t" +- "lxvd2x 38, %10, %2 \n\t" +- "lxvd2x 39, %11, %2 \n\t" +- +- "addi %2, %2, 128 \n\t" +- +- "lxvd2x 40, 0, %2 \n\t" +- "lxvd2x 41, %5, %2 \n\t" +- "lxvd2x 42, %6, %2 \n\t" +- "lxvd2x 43, %7, %2 \n\t" +- "lxvd2x 44, %8, %2 \n\t" +- "lxvd2x 45, %9, %2 \n\t" +- "lxvd2x 46, %10, %2 \n\t" +- "lxvd2x 47, %11, %2 \n\t" +- +- "addi %2, %2, 128 \n\t" +- +- "lxvd2x 48, 0, %1 \n\t" +- "lxvd2x 49, %5, %1 \n\t" +- "lxvd2x 50, %6, %1 \n\t" +- "lxvd2x 51, %7, %1 \n\t" +- "lxvd2x 52, %8, %1 \n\t" +- "lxvd2x 53, %9, %1 \n\t" +- "lxvd2x 54, %10, %1 \n\t" +- "lxvd2x 55, %11, %1 \n\t" +- +- "addi %1, %1, 128 \n\t" +- +- "lxvd2x 56, 0, %1 \n\t" +- "lxvd2x 57, %5, %1 \n\t" +- "lxvd2x 58, %6, %1 \n\t" +- "lxvd2x 59, %7, %1 \n\t" +- "lxvd2x 60, %8, %1 \n\t" +- "lxvd2x 61, %9, %1 \n\t" +- "lxvd2x 62, %10, %1 \n\t" +- "lxvd2x 63, %11, %1 \n\t" +- +- "addi %1, %1, 128 \n\t" +- +- "stxvd2x 32, 0, %3 \n\t" +- "stxvd2x 33, %5, %3 \n\t" +- "stxvd2x 34, %6, %3 \n\t" +- "stxvd2x 35, %7, %3 \n\t" +- "stxvd2x 36, %8, %3 \n\t" +- "stxvd2x 37, %9, %3 \n\t" +- "stxvd2x 38, %10, %3 \n\t" +- "stxvd2x 39, %11, %3 \n\t" +- +- "addi %3, %3, 128 \n\t" +- +- "stxvd2x 40, 0, %3 \n\t" +- "stxvd2x 41, %5, %3 \n\t" +- "stxvd2x 42, %6, %3 \n\t" +- "stxvd2x 43, %7, %3 \n\t" +- "stxvd2x 44, %8, %3 \n\t" +- "stxvd2x 45, %9, %3 \n\t" +- "stxvd2x 46, %10, %3 \n\t" +- "stxvd2x 47, %11, %3 \n\t" +- +- "addi %3, %3, 128 \n\t" +- +- "stxvd2x 48, 0, %4 \n\t" +- "stxvd2x 49, %5, %4 \n\t" +- "stxvd2x 50, %6, %4 \n\t" +- "stxvd2x 51, %7, %4 \n\t" +- "stxvd2x 52, %8, %4 \n\t" +- "stxvd2x 53, %9, %4 \n\t" +- "stxvd2x 54, %10, %4 \n\t" +- "stxvd2x 55, %11, %4 \n\t" +- +- "addi %4, %4, 128 \n\t" +- +- "stxvd2x 56, 0, %4 \n\t" +- "stxvd2x 57, %5, %4 \n\t" +- "stxvd2x 58, %6, %4 \n\t" +- "stxvd2x 59, %7, %4 \n\t" +- "stxvd2x 60, %8, %4 \n\t" +- "stxvd2x 61, %9, %4 \n\t" +- "stxvd2x 62, %10, %4 \n\t" +- "stxvd2x 63, %11, %4 \n\t" +- +- "addi %4, %4, 128 \n\t" +- +- "addic. %0 , %0 , -16 \n\t" +- "bgt 1b \n\t" +- +- "2: \n\t" +- +- : +- : +- "r" (i), // 0 +- "r" (y1), // 1 +- "r" (x1), // 2 +- "r" (y2), // 3 +- "r" (x2), // 4 +- "r" (o16), // 5 +- "r" (o32), // 6 +- "r" (o48), // 7 +- "r" (o64), // 8 +- "r" (o80), // 9 +- "r" (o96), // 10 +- "r" (o112) // 11 +- : "cr0", "%0", "%2" , "%1", "%3", "%4", "memory" +- ); +- +-} +- +- ++ __asm__ ++ ( ++ ".p2align 5 \n" ++ "1: \n\t" ++ "lxvd2x 32, 0, %4 \n\t" ++ "lxvd2x 33, %5, %4 \n\t" ++ "lxvd2x 34, %6, %4 \n\t" ++ "lxvd2x 35, %7, %4 \n\t" ++ "lxvd2x 36, %8, %4 \n\t" ++ "lxvd2x 37, %9, %4 \n\t" ++ "lxvd2x 38, %10, %4 \n\t" ++ "lxvd2x 39, %11, %4 \n\t" ++ ++ "addi %4, %4, 128 \n\t" ++ ++ "lxvd2x 40, 0, %4 \n\t" ++ "lxvd2x 41, %5, %4 \n\t" ++ "lxvd2x 42, %6, %4 \n\t" ++ "lxvd2x 43, %7, %4 \n\t" ++ "lxvd2x 44, %8, %4 \n\t" ++ "lxvd2x 45, %9, %4 \n\t" ++ "lxvd2x 46, %10, %4 \n\t" ++ "lxvd2x 47, %11, %4 \n\t" ++ ++ "addi %4, %4, -128 \n\t" ++ ++ "lxvd2x 48, 0, %3 \n\t" ++ "lxvd2x 49, %5, %3 \n\t" ++ "lxvd2x 50, %6, %3 \n\t" ++ "lxvd2x 51, %7, %3 \n\t" ++ "lxvd2x 0, %8, %3 \n\t" ++ "lxvd2x 1, %9, %3 \n\t" ++ "lxvd2x 2, %10, %3 \n\t" ++ "lxvd2x 3, %11, %3 \n\t" ++ ++ "addi %3, %3, 128 \n\t" ++ ++ "lxvd2x 4, 0, %3 \n\t" ++ "lxvd2x 5, %5, %3 \n\t" ++ "lxvd2x 6, %6, %3 \n\t" ++ "lxvd2x 7, %7, %3 \n\t" ++ "lxvd2x 8, %8, %3 \n\t" ++ "lxvd2x 9, %9, %3 \n\t" ++ "lxvd2x 10, %10, %3 \n\t" ++ "lxvd2x 11, %11, %3 \n\t" ++ ++ "addi %3, %3, -128 \n\t" ++ ++ "stxvd2x 32, 0, %3 \n\t" ++ "stxvd2x 33, %5, %3 \n\t" ++ "stxvd2x 34, %6, %3 \n\t" ++ "stxvd2x 35, %7, %3 \n\t" ++ "stxvd2x 36, %8, %3 \n\t" ++ "stxvd2x 37, %9, %3 \n\t" ++ "stxvd2x 38, %10, %3 \n\t" ++ "stxvd2x 39, %11, %3 \n\t" ++ ++ "addi %3, %3, 128 \n\t" ++ ++ "stxvd2x 40, 0, %3 \n\t" ++ "stxvd2x 41, %5, %3 \n\t" ++ "stxvd2x 42, %6, %3 \n\t" ++ "stxvd2x 43, %7, %3 \n\t" ++ "stxvd2x 44, %8, %3 \n\t" ++ "stxvd2x 45, %9, %3 \n\t" ++ "stxvd2x 46, %10, %3 \n\t" ++ "stxvd2x 47, %11, %3 \n\t" ++ ++ "addi %3, %3, 128 \n\t" ++ ++ "stxvd2x 48, 0, %4 \n\t" ++ "stxvd2x 49, %5, %4 \n\t" ++ "stxvd2x 50, %6, %4 \n\t" ++ "stxvd2x 51, %7, %4 \n\t" ++ "stxvd2x 0, %8, %4 \n\t" ++ "stxvd2x 1, %9, %4 \n\t" ++ "stxvd2x 2, %10, %4 \n\t" ++ "stxvd2x 3, %11, %4 \n\t" ++ ++ "addi %4, %4, 128 \n\t" ++ ++ "stxvd2x 4, 0, %4 \n\t" ++ "stxvd2x 5, %5, %4 \n\t" ++ "stxvd2x 6, %6, %4 \n\t" ++ "stxvd2x 7, %7, %4 \n\t" ++ "stxvd2x 8, %8, %4 \n\t" ++ "stxvd2x 9, %9, %4 \n\t" ++ "stxvd2x 10, %10, %4 \n\t" ++ "stxvd2x 11, %11, %4 \n\t" ++ ++ "addi %4, %4, 128 \n\t" ++ "addic. %2, %2, -16 \n\t" ++ "bgt 1b \n" ++ ++ "#n=%2 x=%0=%3 y=%1=%4 o16=%5 o32=%6 o48=%7 o64=%8 o80=%9 o96=%10 o112=%11" ++ : ++ "+m" (*x), ++ "+m" (*y), ++ "+r" (n), // 2 ++ "+b" (x), // 3 ++ "+b" (y) // 4 ++ : ++ "b" (16), // 5 ++ "b" (32), // 6 ++ "b" (48), // 7 ++ "b" (64), // 8 ++ "b" (80), // 9 ++ "b" (96), // 10 ++ "b" (112) // 11 ++ : ++ "cr0", ++ "vs32","vs33","vs34","vs35","vs36","vs37","vs38","vs39", ++ "vs40","vs41","vs42","vs43","vs44","vs45","vs46","vs47", ++ "vs48","vs49","vs50","vs51","vs0","vs1","vs2","vs3", ++ "vs4","vs5","vs6","vs7","vs8","vs9","vs10","vs11" ++ ); ++} From d1cd951981f002ee444447ddf8b3d28e2ea8ce07 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Sun, 19 Mar 2017 09:06:11 -0400 Subject: [PATCH 0222/1534] Revert "Add patch to set `-O2` for suitesparse build (#20165)" This reverts commit 145eae8c28d627eb1e81c5d965db200ab49ff75d. This was actually a bug in the power kernels in OpenBLAS, not a GCC or SuiteSparse problem --- deps/patches/SuiteSparse-O2.patch | 11 ----------- deps/suitesparse.mk | 7 +------ 2 files changed, 1 insertion(+), 17 deletions(-) delete mode 100644 deps/patches/SuiteSparse-O2.patch diff --git a/deps/patches/SuiteSparse-O2.patch b/deps/patches/SuiteSparse-O2.patch deleted file mode 100644 index 7f2144f21261e..0000000000000 --- a/deps/patches/SuiteSparse-O2.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- SuiteSparse_config/SuiteSparse_config.mk 2014-12-22 14:21:00.000000000 -0800 -+++ SuiteSparse_config/SuiteSparse_config.mk 2017-01-20 15:17:43.000000000 -0800 -@@ -69,7 +69,7 @@ - # C and C++ compiler flags. The first three are standard for *.c and *.cpp - # Add -DNTIMER if you do use any timing routines (otherwise -lrt is required). - # CF = $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -O3 -fexceptions -fPIC -DNTIMER -- CF = $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -O3 -fexceptions -fPIC -+ CF = $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -O2 -fexceptions -fPIC - # for the MKL BLAS: - # CF = $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -O3 -fexceptions -fPIC -I$(MKLROOT)/include -D_GNU_SOURCE - # with no optimization: diff --git a/deps/suitesparse.mk b/deps/suitesparse.mk index 8baf6014eaf23..90b237628175e 100644 --- a/deps/suitesparse.mk +++ b/deps/suitesparse.mk @@ -37,17 +37,12 @@ $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/SuiteSparse-winclang.patch-applied: $ cd $(dir $@) && patch -p0 < $(SRCDIR)/patches/SuiteSparse-winclang.patch echo 1 > $@ -$(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/SuiteSparse-O2.patch-applied: $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/SuiteSparse-winclang.patch-applied - cd $(dir $@) && patch -p0 < $(SRCDIR)/patches/SuiteSparse-O2.patch - echo 1 > $@ - - ifeq ($(USE_SYSTEM_BLAS), 0) $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/build-compiled: | $(build_prefix)/manifest/openblas else ifeq ($(USE_SYSTEM_LAPACK), 0) $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/build-compiled: | $(build_prefix)/manifest/lapack endif -$(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/build-compiled: $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/source-extracted $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/SuiteSparse-O2.patch-applied +$(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/build-compiled: $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/source-extracted $(BUILDDIR)/SuiteSparse-$(SUITESPARSE_VER)/SuiteSparse-winclang.patch-applied $(MAKE) -C $(dir $<) library $(SUITESPARSE_MFLAGS) echo 1 > $@ From a365da4c6c7246c95fcd5cd8d7b1baf1bffaf1ff Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Sun, 19 Mar 2017 08:41:25 -0500 Subject: [PATCH 0223/1534] Respect format width for milliseconds (#21070) Fixes #21001 --- base/dates/io.jl | 12 ++++++------ test/dates/io.jl | 9 +++++++++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/base/dates/io.jl b/base/dates/io.jl index c87013c43068f..608d509ec4c64 100644 --- a/base/dates/io.jl +++ b/base/dates/io.jl @@ -154,15 +154,15 @@ end function format(io, d::DatePart{'s'}, dt) ms = millisecond(dt) - if ms == 0 - write(io, '0') - elseif ms % 100 == 0 - write(io, dec(div(ms, 100), 1)) + if ms % 100 == 0 + str = dec(div(ms, 100), 1) elseif ms % 10 == 0 - write(io, dec(div(ms, 10), 2)) + str = dec(div(ms, 10), 2) else - write(io, dec(ms, 3)) + str = dec(ms, 3) end + + write(io, rpad(str, d.width, '0')) end ### Delimiters diff --git a/test/dates/io.jl b/test/dates/io.jl index 8564265d880cf..a27fd23711f74 100644 --- a/test/dates/io.jl +++ b/test/dates/io.jl @@ -420,3 +420,12 @@ end @test Dates.Date("Apr 01 2014", "uuu dd yyyy") == Dates.Date(2014, 4, 1) @test_throws ArgumentError Dates.Date("Apr 01 xx 2014", "uuu dd zz yyyy") @test_throws ArgumentError Dates.Date("Apr 01 xx 2014", "uuu dd yyyy") + +# Issue 21001 +for (ms, str) in zip([0, 1, 20, 300, 450, 678], ["0", "001", "02", "3", "45", "678"]) + dt = DateTime(2000, 1, 1, 0, 0, 0, ms) + @test Dates.format(dt, "s") == str + @test Dates.format(dt, "ss") == rpad(str, 2, '0') + @test Dates.format(dt, "sss") == rpad(str, 3, '0') + @test Dates.format(dt, "ssss") == rpad(str, 4, '0') +end From c180f728701d6a60296f6cd32e5b6ca779ea229e Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Sat, 4 Feb 2017 06:01:19 -0800 Subject: [PATCH 0224/1534] wrap long lines in base/linalg/lu.jl line breaks in definitions of stridedarray aliases and a couple lines in test/parse.jl --- base/linalg/lu.jl | 73 ++++++++++++++++++++++++++++++++--------------- base/sysimg.jl | 12 ++++++-- test/parse.jl | 7 +++-- 3 files changed, 64 insertions(+), 28 deletions(-) diff --git a/base/linalg/lu.jl b/base/linalg/lu.jl index 854c774160bb1..ff5d3202a8130 100644 --- a/base/linalg/lu.jl +++ b/base/linalg/lu.jl @@ -78,7 +78,9 @@ function generic_lufact!{T,Pivot}(A::StridedMatrix{T}, ::Type{Val{Pivot}} = Val{ end # floating point types doesn't have to be promoted for LU, but should default to pivoting -lufact{T<:AbstractFloat}(A::Union{AbstractMatrix{T},AbstractMatrix{Complex{T}}}, pivot::Union{Type{Val{false}}, Type{Val{true}}} = Val{true}) = lufact!(copy(A), pivot) +lufact{T<:AbstractFloat}(A::Union{AbstractMatrix{T}, AbstractMatrix{Complex{T}}}, + pivot::Union{Type{Val{false}}, Type{Val{true}}} = Val{true}) = + lufact!(copy(A), pivot) # for all other types we must promote to a type which is stable under division """ @@ -232,23 +234,41 @@ function show(io::IO, C::LU) show(io, C[:U]) end -A_ldiv_B!{T<:BlasFloat}(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) = @assertnonsingular LAPACK.getrs!('N', A.factors, A.ipiv, B) A.info -A_ldiv_B!(A::LU{<:Any,<:StridedMatrix}, b::StridedVector) = A_ldiv_B!(UpperTriangular(A.factors), A_ldiv_B!(UnitLowerTriangular(A.factors), b[ipiv2perm(A.ipiv, length(b))])) -A_ldiv_B!(A::LU{<:Any,<:StridedMatrix}, B::StridedMatrix) = A_ldiv_B!(UpperTriangular(A.factors), A_ldiv_B!(UnitLowerTriangular(A.factors), B[ipiv2perm(A.ipiv, size(B, 1)),:])) - -At_ldiv_B!{T<:BlasFloat}(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) = @assertnonsingular LAPACK.getrs!('T', A.factors, A.ipiv, B) A.info -At_ldiv_B!(A::LU{<:Any,<:StridedMatrix}, b::StridedVector) = At_ldiv_B!(UnitLowerTriangular(A.factors), At_ldiv_B!(UpperTriangular(A.factors), b))[invperm(ipiv2perm(A.ipiv, length(b)))] -At_ldiv_B!(A::LU{<:Any,<:StridedMatrix}, B::StridedMatrix) = At_ldiv_B!(UnitLowerTriangular(A.factors), At_ldiv_B!(UpperTriangular(A.factors), B))[invperm(ipiv2perm(A.ipiv, size(B,1))),:] - -Ac_ldiv_B!{T<:Real}(F::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) = At_ldiv_B!(F, B) -Ac_ldiv_B!{T<:BlasComplex}(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) = @assertnonsingular LAPACK.getrs!('C', A.factors, A.ipiv, B) A.info -Ac_ldiv_B!(A::LU{<:Any,<:StridedMatrix}, b::StridedVector) = Ac_ldiv_B!(UnitLowerTriangular(A.factors), Ac_ldiv_B!(UpperTriangular(A.factors), b))[invperm(ipiv2perm(A.ipiv, length(b)))] -Ac_ldiv_B!(A::LU{<:Any,<:StridedMatrix}, B::StridedMatrix) = Ac_ldiv_B!(UnitLowerTriangular(A.factors), Ac_ldiv_B!(UpperTriangular(A.factors), B))[invperm(ipiv2perm(A.ipiv, size(B,1))),:] - -At_ldiv_Bt{T<:BlasFloat}(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) = @assertnonsingular LAPACK.getrs!('T', A.factors, A.ipiv, transpose(B)) A.info +A_ldiv_B!{T<:BlasFloat}(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) = + @assertnonsingular LAPACK.getrs!('N', A.factors, A.ipiv, B) A.info +A_ldiv_B!(A::LU{<:Any,<:StridedMatrix}, b::StridedVector) = + A_ldiv_B!(UpperTriangular(A.factors), + A_ldiv_B!(UnitLowerTriangular(A.factors), b[ipiv2perm(A.ipiv, length(b))])) +A_ldiv_B!(A::LU{<:Any,<:StridedMatrix}, B::StridedMatrix) = + A_ldiv_B!(UpperTriangular(A.factors), + A_ldiv_B!(UnitLowerTriangular(A.factors), B[ipiv2perm(A.ipiv, size(B, 1)),:])) + +At_ldiv_B!{T<:BlasFloat}(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) = + @assertnonsingular LAPACK.getrs!('T', A.factors, A.ipiv, B) A.info +At_ldiv_B!(A::LU{<:Any,<:StridedMatrix}, b::StridedVector) = + At_ldiv_B!(UnitLowerTriangular(A.factors), + At_ldiv_B!(UpperTriangular(A.factors), b))[invperm(ipiv2perm(A.ipiv, length(b)))] +At_ldiv_B!(A::LU{<:Any,<:StridedMatrix}, B::StridedMatrix) = + At_ldiv_B!(UnitLowerTriangular(A.factors), + At_ldiv_B!(UpperTriangular(A.factors), B))[invperm(ipiv2perm(A.ipiv, size(B,1))),:] + +Ac_ldiv_B!{T<:Real}(F::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) = + At_ldiv_B!(F, B) +Ac_ldiv_B!{T<:BlasComplex}(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) = + @assertnonsingular LAPACK.getrs!('C', A.factors, A.ipiv, B) A.info +Ac_ldiv_B!(A::LU{<:Any,<:StridedMatrix}, b::StridedVector) = + Ac_ldiv_B!(UnitLowerTriangular(A.factors), + Ac_ldiv_B!(UpperTriangular(A.factors), b))[invperm(ipiv2perm(A.ipiv, length(b)))] +Ac_ldiv_B!(A::LU{<:Any,<:StridedMatrix}, B::StridedMatrix) = + Ac_ldiv_B!(UnitLowerTriangular(A.factors), + Ac_ldiv_B!(UpperTriangular(A.factors), B))[invperm(ipiv2perm(A.ipiv, size(B,1))),:] + +At_ldiv_Bt{T<:BlasFloat}(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) = + @assertnonsingular LAPACK.getrs!('T', A.factors, A.ipiv, transpose(B)) A.info At_ldiv_Bt(A::LU, B::StridedVecOrMat) = At_ldiv_B(A, transpose(B)) -Ac_ldiv_Bc{T<:BlasComplex}(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) = @assertnonsingular LAPACK.getrs!('C', A.factors, A.ipiv, ctranspose(B)) A.info +Ac_ldiv_Bc{T<:BlasComplex}(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) = + @assertnonsingular LAPACK.getrs!('C', A.factors, A.ipiv, ctranspose(B)) A.info Ac_ldiv_Bc(A::LU, B::StridedVecOrMat) = Ac_ldiv_B(A, ctranspose(B)) function det{T}(A::LU{T}) @@ -284,10 +304,13 @@ function logabsdet{T}(A::LU{T}) # return log(abs(det)) and sign(det) abs_det, s end -inv!(A::LU{<:BlasFloat,<:StridedMatrix}) = @assertnonsingular LAPACK.getri!(A.factors, A.ipiv) A.info -inv(A::LU{<:BlasFloat,<:StridedMatrix}) = inv!(LU(copy(A.factors), copy(A.ipiv), copy(A.info))) +inv!(A::LU{<:BlasFloat,<:StridedMatrix}) = + @assertnonsingular LAPACK.getri!(A.factors, A.ipiv) A.info +inv(A::LU{<:BlasFloat,<:StridedMatrix}) = + inv!(LU(copy(A.factors), copy(A.ipiv), copy(A.info))) -cond(A::LU{<:BlasFloat,<:StridedMatrix}, p::Number) = inv(LAPACK.gecon!(p == 1 ? '1' : 'I', A.factors, norm((A[:L]*A[:U])[A[:p],:], p))) +cond(A::LU{<:BlasFloat,<:StridedMatrix}, p::Number) = + inv(LAPACK.gecon!(p == 1 ? '1' : 'I', A.factors, norm((A[:L]*A[:U])[A[:p],:], p))) cond(A::LU, p::Number) = norm(A[:L]*A[:U],p)*norm(inv(A),p) # Tridiagonal @@ -528,8 +551,12 @@ function convert{T}(::Type{Tridiagonal}, F::Base.LinAlg.LU{T,Tridiagonal{T}}) end return Tridiagonal(dl, d, du) end -convert{T}(::Type{AbstractMatrix}, F::Base.LinAlg.LU{T,Tridiagonal{T}}) = convert(Tridiagonal, F) -convert{T}(::Type{AbstractArray}, F::Base.LinAlg.LU{T,Tridiagonal{T}}) = convert(AbstractMatrix, F) -convert{T}(::Type{Matrix}, F::Base.LinAlg.LU{T,Tridiagonal{T}}) = convert(Array, convert(AbstractArray, F)) -convert{T}(::Type{Array}, F::Base.LinAlg.LU{T,Tridiagonal{T}}) = convert(Matrix, F) +convert{T}(::Type{AbstractMatrix}, F::Base.LinAlg.LU{T,Tridiagonal{T}}) = + convert(Tridiagonal, F) +convert{T}(::Type{AbstractArray}, F::Base.LinAlg.LU{T,Tridiagonal{T}}) = + convert(AbstractMatrix, F) +convert{T}(::Type{Matrix}, F::Base.LinAlg.LU{T,Tridiagonal{T}}) = + convert(Array, convert(AbstractArray, F)) +convert{T}(::Type{Array}, F::Base.LinAlg.LU{T,Tridiagonal{T}}) = + convert(Matrix, F) full{T}(F::Base.LinAlg.LU{T,Tridiagonal{T}}) = convert(AbstractArray, F) diff --git a/base/sysimg.jl b/base/sysimg.jl index b6f5beed2d5e6..ece631fff9dca 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -142,9 +142,15 @@ using .Iterators: Flatten, product # for generators # Definition of StridedArray StridedReshapedArray{T,N,A<:DenseArray} = ReshapedArray{T,N,A} -StridedArray{T,N,A<:Union{DenseArray,StridedReshapedArray},I<:Tuple{Vararg{Union{RangeIndex, AbstractCartesianIndex}}}} = Union{DenseArray{T,N}, SubArray{T,N,A,I}, StridedReshapedArray{T,N}} -StridedVector{T,A<:Union{DenseArray,StridedReshapedArray},I<:Tuple{Vararg{Union{RangeIndex, AbstractCartesianIndex}}}} = Union{DenseArray{T,1}, SubArray{T,1,A,I}, StridedReshapedArray{T,1}} -StridedMatrix{T,A<:Union{DenseArray,StridedReshapedArray},I<:Tuple{Vararg{Union{RangeIndex, AbstractCartesianIndex}}}} = Union{DenseArray{T,2}, SubArray{T,2,A,I}, StridedReshapedArray{T,2}} +StridedArray{T,N,A<:Union{DenseArray,StridedReshapedArray}, + I<:Tuple{Vararg{Union{RangeIndex, AbstractCartesianIndex}}}} = + Union{DenseArray{T,N}, SubArray{T,N,A,I}, StridedReshapedArray{T,N}} +StridedVector{T,A<:Union{DenseArray,StridedReshapedArray}, + I<:Tuple{Vararg{Union{RangeIndex, AbstractCartesianIndex}}}} = + Union{DenseArray{T,1}, SubArray{T,1,A,I}, StridedReshapedArray{T,1}} +StridedMatrix{T,A<:Union{DenseArray,StridedReshapedArray}, + I<:Tuple{Vararg{Union{RangeIndex, AbstractCartesianIndex}}}} = + Union{DenseArray{T,2}, SubArray{T,2,A,I}, StridedReshapedArray{T,2}} StridedVecOrMat{T} = Union{StridedVector{T}, StridedMatrix{T}} # For OS specific stuff diff --git a/test/parse.jl b/test/parse.jl index 7fbda2b1f1317..e94b6f6b25397 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -246,7 +246,8 @@ for T in vcat(subtypes(Signed), subtypes(Unsigned)) # Test that the entire input string appears in error messages let s = " false true " - result = @test_throws ArgumentError get(Base.tryparse_internal(Bool, s, start(s), endof(s), 0, true)) + result = @test_throws(ArgumentError, + get(Base.tryparse_internal(Bool, s, start(s), endof(s), 0, true))) @test result.value.msg == "invalid Bool representation: $(repr(s))" end @@ -418,7 +419,9 @@ end Expr(Symbol("&&"), :c, :d)) # issue #11988 -- normalize \r and \r\n in literal strings to \n -@test "foo\nbar" == parse("\"\"\"\r\nfoo\r\nbar\"\"\"") == parse("\"\"\"\nfoo\nbar\"\"\"") == parse("\"\"\"\rfoo\rbar\"\"\"") == parse("\"foo\r\nbar\"") == parse("\"foo\rbar\"") == parse("\"foo\nbar\"") +@test "foo\nbar" == parse("\"\"\"\r\nfoo\r\nbar\"\"\"") == + parse("\"\"\"\nfoo\nbar\"\"\"") == parse("\"\"\"\rfoo\rbar\"\"\"") == + parse("\"foo\r\nbar\"") == parse("\"foo\rbar\"") == parse("\"foo\nbar\"") @test '\r' == first("\r") == first("\r\n") # still allow explicit \r # issue #14561 - generating 0-method generic function def From f46875fdce5c94969a35d8bb23020ee17240e540 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Tue, 21 Feb 2017 19:40:40 -0800 Subject: [PATCH 0225/1534] wrap long lines in base/abstractarray.jl --- base/abstractarray.jl | 81 +++++++++++++++++++++++++++++++------------ 1 file changed, 58 insertions(+), 23 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 5ec677a2db340..f9ab3fef45982 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -20,7 +20,8 @@ julia> size(A,3,2) ``` """ size{T,N}(t::AbstractArray{T,N}, d) = d <= N ? size(t)[d] : 1 -size{N}(x, d1::Integer, d2::Integer, dx::Vararg{Integer, N}) = (size(x, d1), size(x, d2), ntuple(k->size(x, dx[k]), Val{N})...) +size{N}(x, d1::Integer, d2::Integer, dx::Vararg{Integer, N}) = + (size(x, d1), size(x, d2), ntuple(k->size(x, dx[k]), Val{N})...) """ indices(A, d) @@ -381,7 +382,10 @@ function checkbounds_indices(::Type{Bool}, IA::Tuple, I::Tuple) checkindex(Bool, IA[1], I[1]) & checkbounds_indices(Bool, tail(IA), tail(I)) end checkbounds_indices(::Type{Bool}, ::Tuple{}, ::Tuple{}) = true -checkbounds_indices(::Type{Bool}, ::Tuple{}, I::Tuple{Any}) = (@_inline_meta; checkindex(Bool, 1:1, I[1])) +function checkbounds_indices(::Type{Bool}, ::Tuple{}, I::Tuple{Any}) + @_inline_meta + checkindex(Bool, 1:1, I[1]) +end function checkbounds_indices(::Type{Bool}, ::Tuple{}, I::Tuple) @_inline_meta checkindex(Bool, 1:1, I[1]) & checkbounds_indices(Bool, (), tail(I)) @@ -412,7 +416,8 @@ function checkbounds_linear_indices(::Type{Bool}, IA::Tuple{Vararg{OneTo}}, i::U partial_linear_indexing_warning_lookup(length(IA)) true end -function checkbounds_linear_indices(::Type{Bool}, IA::Tuple{AbstractUnitRange,Vararg{AbstractUnitRange}}, i::Union{Slice,Colon}) +function checkbounds_linear_indices(::Type{Bool}, + IA::Tuple{AbstractUnitRange,Vararg{AbstractUnitRange}}, i::Union{Slice,Colon}) partial_linear_indexing_warning_lookup(length(IA)) true end @@ -437,7 +442,8 @@ julia> checkindex(Bool,1:20,21) false ``` """ -checkindex(::Type{Bool}, inds::AbstractUnitRange, i) = throw(ArgumentError("unable to check bounds for indices of type $(typeof(i))")) +checkindex(::Type{Bool}, inds::AbstractUnitRange, i) = + throw(ArgumentError("unable to check bounds for indices of type $(typeof(i))")) checkindex(::Type{Bool}, inds::AbstractUnitRange, i::Real) = (first(inds) <= i) & (i <= last(inds)) checkindex(::Type{Bool}, inds::AbstractUnitRange, ::Colon) = true checkindex(::Type{Bool}, inds::AbstractUnitRange, ::Slice) = true @@ -636,7 +642,8 @@ copy!(dest::AbstractArray, src::AbstractArray) = function copy!(::IndexStyle, dest::AbstractArray, ::IndexStyle, src::AbstractArray) destinds, srcinds = linearindices(dest), linearindices(src) - isempty(srcinds) || (first(srcinds) ∈ destinds && last(srcinds) ∈ destinds) || throw(BoundsError(dest, srcinds)) + isempty(srcinds) || (first(srcinds) ∈ destinds && last(srcinds) ∈ destinds) || + throw(BoundsError(dest, srcinds)) @inbounds for i in srcinds dest[i] = src[i] end @@ -645,7 +652,8 @@ end function copy!(::IndexStyle, dest::AbstractArray, ::IndexCartesian, src::AbstractArray) destinds, srcinds = linearindices(dest), linearindices(src) - isempty(srcinds) || (first(srcinds) ∈ destinds && last(srcinds) ∈ destinds) || throw(BoundsError(dest, srcinds)) + isempty(srcinds) || (first(srcinds) ∈ destinds && last(srcinds) ∈ destinds) || + throw(BoundsError(dest, srcinds)) i = 0 @inbounds for a in src dest[i+=1] = a @@ -846,7 +854,10 @@ end # a data Ref. they just map the array element type to the pointer type for # convenience in cases that work. pointer{T}(x::AbstractArray{T}) = unsafe_convert(Ptr{T}, x) -pointer{T}(x::AbstractArray{T}, i::Integer) = (@_inline_meta; unsafe_convert(Ptr{T},x) + (i-first(linearindices(x)))*elsize(x)) +function pointer{T}(x::AbstractArray{T}, i::Integer) + @_inline_meta + unsafe_convert(Ptr{T},x) + (i-first(linearindices(x)))*elsize(x) +end ## Approach: # We only define one fallback method on getindex for all argument types. @@ -869,12 +880,15 @@ function unsafe_getindex(A::AbstractArray, I...) r end -error_if_canonical_indexing(::IndexLinear, A::AbstractArray, ::Int) = error("indexing not defined for ", typeof(A)) -error_if_canonical_indexing{T,N}(::IndexCartesian, A::AbstractArray{T,N}, ::Vararg{Int, N}) = error("indexing not defined for ", typeof(A)) +error_if_canonical_indexing(::IndexLinear, A::AbstractArray, ::Int) = + error("indexing not defined for ", typeof(A)) +error_if_canonical_indexing{T,N}(::IndexCartesian, A::AbstractArray{T,N}, ::Vararg{Int, N}) = + error("indexing not defined for ", typeof(A)) error_if_canonical_indexing(::IndexStyle, ::AbstractArray, ::Any...) = nothing ## Internal definitions -_getindex(::IndexStyle, A::AbstractArray, I...) = error("indexing $(typeof(A)) with types $(typeof(I)) is not supported") +_getindex(::IndexStyle, A::AbstractArray, I...) = + error("indexing $(typeof(A)) with types $(typeof(I)) is not supported") ## IndexLinear Scalar indexing: canonical method is one Int _getindex(::IndexLinear, A::AbstractArray, i::Int) = (@_propagate_inbounds_meta; getindex(A, i)) @@ -892,14 +906,20 @@ _to_linear_index(A::AbstractArray) = 1 # TODO: DEPRECATE FOR #14770 _to_linear_index(A::AbstractArray, I::Int...) = (@_inline_meta; sub2ind(A, I...)) # TODO: DEPRECATE FOR #14770 ## IndexCartesian Scalar indexing: Canonical method is full dimensionality of Ints -_getindex(::IndexCartesian, A::AbstractArray) = (@_propagate_inbounds_meta; getindex(A, _to_subscript_indices(A)...)) +function _getindex(::IndexCartesian, A::AbstractArray) + @_propagate_inbounds_meta + getindex(A, _to_subscript_indices(A)...) +end function _getindex(::IndexCartesian, A::AbstractArray, I::Int...) @_inline_meta @boundscheck checkbounds(A, I...) # generally _to_subscript_indices requires bounds checking @inbounds r = getindex(A, _to_subscript_indices(A, I...)...) r end -_getindex{T,N}(::IndexCartesian, A::AbstractArray{T,N}, I::Vararg{Int, N}) = (@_propagate_inbounds_meta; getindex(A, I...)) +function _getindex{T,N}(::IndexCartesian, A::AbstractArray{T,N}, I::Vararg{Int, N}) + @_propagate_inbounds_meta + getindex(A, I...) +end _to_subscript_indices(A::AbstractArray, i::Int) = (@_inline_meta; _unsafe_ind2sub(A, i)) _to_subscript_indices{T,N}(A::AbstractArray{T,N}) = (@_inline_meta; fill_to_length((), 1, Val{N})) # TODO: DEPRECATE FOR #14770 _to_subscript_indices{T}(A::AbstractArray{T,0}) = () # TODO: REMOVE FOR #14770 @@ -920,7 +940,8 @@ function __to_subscript_indices(A::AbstractArray, ::Tuple{Vararg{OneTo}}, J::Tup end # After the partial linear indexing deprecation is removed, this next method can # become the new normal. For now, it's limited to non-OneTo arrays. -function __to_subscript_indices(A::AbstractArray, ::Tuple{AbstractUnitRange,Vararg{AbstractUnitRange}}, J::Tuple, Jrem::Tuple{}) +function __to_subscript_indices(A::AbstractArray, + ::Tuple{AbstractUnitRange,Vararg{AbstractUnitRange}}, J::Tuple, Jrem::Tuple{}) @_inline_meta (J..., map(first, tail(_remaining_size(J, indices(A))))...) end @@ -944,7 +965,8 @@ function unsafe_setindex!(A::AbstractArray, v, I...) r end ## Internal defitions -_setindex!(::IndexStyle, A::AbstractArray, v, I...) = error("indexing $(typeof(A)) with types $(typeof(I)) is not supported") +_setindex!(::IndexStyle, A::AbstractArray, v, I...) = + error("indexing $(typeof(A)) with types $(typeof(I)) is not supported") ## IndexLinear Scalar indexing _setindex!(::IndexLinear, A::AbstractArray, v, i::Int) = (@_propagate_inbounds_meta; setindex!(A, v, i)) @@ -957,8 +979,14 @@ function _setindex!(::IndexLinear, A::AbstractArray, v, I::Int...) end # IndexCartesian Scalar indexing -_setindex!{T,N}(::IndexCartesian, A::AbstractArray{T,N}, v, I::Vararg{Int, N}) = (@_propagate_inbounds_meta; setindex!(A, v, I...)) -_setindex!(::IndexCartesian, A::AbstractArray, v) = (@_propagate_inbounds_meta; setindex!(A, v, _to_subscript_indices(A)...)) +function _setindex!{T,N}(::IndexCartesian, A::AbstractArray{T,N}, v, I::Vararg{Int, N}) + @_propagate_inbounds_meta + setindex!(A, v, I...) +end +function _setindex!(::IndexCartesian, A::AbstractArray, v) + @_propagate_inbounds_meta + setindex!(A, v, _to_subscript_indices(A)...) +end function _setindex!(::IndexCartesian, A::AbstractArray, v, I::Int...) @_inline_meta @boundscheck checkbounds(A, I...) @@ -968,7 +996,8 @@ end ## get (getindex with a default value) ## -RangeVecIntList{A<:AbstractVector{Int}} = Union{Tuple{Vararg{Union{Range, AbstractVector{Int}}}}, AbstractVector{UnitRange{Int}}, AbstractVector{Range{Int}}, AbstractVector{A}} +RangeVecIntList{A<:AbstractVector{Int}} = Union{Tuple{Vararg{Union{Range, AbstractVector{Int}}}}, + AbstractVector{UnitRange{Int}}, AbstractVector{Range{Int}}, AbstractVector{A}} get(A::AbstractArray, i::Integer, default) = checkbounds(Bool, A, i) ? A[i] : default get(A::AbstractArray, I::Tuple{}, default) = similar(A, typeof(default), 0) @@ -1002,7 +1031,8 @@ function get!{T}(X::AbstractArray{T}, A::AbstractArray, I::RangeVecIntList, defa X end -get(A::AbstractArray, I::RangeVecIntList, default) = get!(similar(A, typeof(default), index_shape(I...)), A, I, default) +get(A::AbstractArray, I::RangeVecIntList, default) = + get!(similar(A, typeof(default), index_shape(I...)), A, I, default) ## structured matrix methods ## replace_in_print_matrix(A::AbstractMatrix,i::Integer,j::Integer,s::AbstractString) = s @@ -1152,7 +1182,8 @@ end _cshp(tail(dims), (out..., next), tail(shape), tail(nshape)) end -_cs(d, concat, a, b) = concat ? (a + b) : (a == b ? a : throw(DimensionMismatch(string("mismatch in dimension ", d, " (expected ", a, " got ", b, ")")))) +_cs(d, concat, a, b) = concat ? (a + b) : (a == b ? a : throw(DimensionMismatch(string( + "mismatch in dimension ", d, " (expected ", a, " got ", b, ")")))) dims2cat{n}(::Type{Val{n}}) = ntuple(i -> (i == n), Val{n}) dims2cat(dims) = ntuple(i -> (i in dims), maximum(dims)) @@ -1544,7 +1575,8 @@ sub2ind(dims::DimsInteger, I::Integer...) = (@_inline_meta; _sub2ind(dims, 1, 1, sub2ind(inds::Indices, I::Integer...) = (@_inline_meta; _sub2ind(inds, 1, 1, I...)) # In 1d, there's a question of whether we're doing cartesian indexing # or linear indexing. Support only the former. -sub2ind(inds::Indices{1}, I::Integer...) = throw(ArgumentError("Linear indexing is not defined for one-dimensional arrays")) +sub2ind(inds::Indices{1}, I::Integer...) = + throw(ArgumentError("Linear indexing is not defined for one-dimensional arrays")) sub2ind(inds::Tuple{OneTo}, I::Integer...) = (@_inline_meta; _sub2ind(inds, 1, 1, I...)) # only OneTo is safe sub2ind(inds::Tuple{OneTo}, i::Integer) = i @@ -1593,7 +1625,8 @@ julia> ind2sub((3,4),4) """ ind2sub(dims::DimsInteger, ind::Integer) = (@_inline_meta; _ind2sub(dims, ind-1)) ind2sub(inds::Indices, ind::Integer) = (@_inline_meta; _ind2sub(inds, ind-1)) -ind2sub(inds::Indices{1}, ind::Integer) = throw(ArgumentError("Linear indexing is not defined for one-dimensional arrays")) +ind2sub(inds::Indices{1}, ind::Integer) = + throw(ArgumentError("Linear indexing is not defined for one-dimensional arrays")) ind2sub(inds::Tuple{OneTo}, ind::Integer) = (ind,) _ind2sub(::Tuple{}, ind) = (ind+1,) @@ -1617,8 +1650,10 @@ _div(ind, r::AbstractUnitRange) = (d = unsafe_length(r); (div(ind, d), first(r), function sub2ind{T<:Integer}(inds::Indices{1}, I1::AbstractVector{T}, I::AbstractVector{T}...) throw(ArgumentError("Linear indexing is not defined for one-dimensional arrays")) end -sub2ind{T<:Integer}(inds::Tuple{OneTo}, I1::AbstractVector{T}, I::AbstractVector{T}...) = _sub2ind_vecs(inds, I1, I...) -sub2ind{T<:Integer}(inds::Union{DimsInteger,Indices}, I1::AbstractVector{T}, I::AbstractVector{T}...) = _sub2ind_vecs(inds, I1, I...) +sub2ind{T<:Integer}(inds::Tuple{OneTo}, I1::AbstractVector{T}, I::AbstractVector{T}...) = + _sub2ind_vecs(inds, I1, I...) +sub2ind{T<:Integer}(inds::Union{DimsInteger,Indices}, I1::AbstractVector{T}, I::AbstractVector{T}...) = + _sub2ind_vecs(inds, I1, I...) function _sub2ind_vecs(inds, I::AbstractVector...) I1 = I[1] Iinds = indices1(I1) From c358aed4f6c773d10389cd4ff228011f1f69505a Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Fri, 24 Feb 2017 12:39:30 -0800 Subject: [PATCH 0226/1534] 4 space indent in go_benchmark.jl --- test/perf/kernel/go_benchmark.jl | 618 ++++++++++++++++--------------- 1 file changed, 310 insertions(+), 308 deletions(-) diff --git a/test/perf/kernel/go_benchmark.jl b/test/perf/kernel/go_benchmark.jl index b39383257583d..53ebec7fe988e 100644 --- a/test/perf/kernel/go_benchmark.jl +++ b/test/perf/kernel/go_benchmark.jl @@ -21,18 +21,18 @@ const BLACK_TERRITORY = 4 const UNKNOWN = 5 mutable struct XorRand - state::UInt32 + state::UInt32 end function xor_srand(rand::XorRand, seed::UInt32) - rand.state = seed + rand.state = seed end function xor_randn(rand::XorRand, n::UInt32) - rand.state ⊻= rand.state << 13 - rand.state ⊻= rand.state >> 17 - rand.state ⊻= rand.state << 5 - rand.state % n + rand.state ⊻= rand.state << 13 + rand.state ⊻= rand.state >> 17 + rand.state ⊻= rand.state << 5 + rand.state % n end xor_randn(rand::XorRand, n::Int) = convert(Int, xor_randn(rand, convert(UInt32, n))) @@ -43,42 +43,42 @@ const deltaj = (0, 0, -1, 1) neighbor(i::Int, j::Int, k::Int) = (i + deltai[k], j + deltaj[k]) mutable struct Board - size::Int - komi::Float64 + size::Int + komi::Float64 - # Board represented by a 1D array. The first board_size*board_size - # elements are used. Vertices are indexed row by row, starting with 0 - # in the upper left corner. - board::Matrix{Int} + # Board represented by a 1D array. The first board_size*board_size + # elements are used. Vertices are indexed row by row, starting with 0 + # in the upper left corner. + board::Matrix{Int} - # Stones are linked together in a circular list for each string. - next_stone::Matrix{Int} + # Stones are linked together in a circular list for each string. + next_stone::Matrix{Int} - # Storage for final status computations. - final_status::Matrix{Int} + # Storage for final status computations. + final_status::Matrix{Int} - # Point which would be an illegal ko recapture. - ko_i::Int - ko_j::Int + # Point which would be an illegal ko recapture. + ko_i::Int + ko_j::Int - # xor-shift random number generator. - rand::XorRand + # xor-shift random number generator. + rand::XorRand - function Board(n::Int) - init(new(), n, convert(UInt32, 2463534242)) - end + function Board(n::Int) + init(new(), n, convert(UInt32, 2463534242)) + end end function init(board::Board, n::Int, seed::UInt32) - board.size = n - board.komi = 0.0 - board.board = zeros(Int, n, n) - board.next_stone = zeros(Int, n, n) - board.final_status = zeros(Int, n, n) - board.ko_i = 0 - board.ko_j = 0 - board.rand = XorRand(seed) - board + board.size = n + board.komi = 0.0 + board.board = zeros(Int, n, n) + board.next_stone = zeros(Int, n, n) + board.final_status = zeros(Int, n, n) + board.ko_i = 0 + board.ko_j = 0 + board.rand = XorRand(seed) + board end getindex(board::Board, pos::Int) = board.board[pos] @@ -91,261 +91,263 @@ POS(board::Board, i::Int, j::Int) = (j - 1) * board.size + i IJ(board::Board, pos::Int) = (1 + mod((pos - 1), board.size), 1 + fld(pos - 1, board.size)) function set_komi(board::Board, komi::Float64) - board.komi = komi + board.komi = komi end function set_random_seed(board::Board, seed::UInt32) - xor_srand(board.rand, seed) + xor_srand(board.rand, seed) end function clear(board::Board) - board.board[:] = EMPTY + board.board[:] = EMPTY end is_pass_move(i::Int, j::Int) = i == 0 && j == 0 function on_board(board::Board, i::Int, j::Int) - i >= 1 && i <= board.size && j >= 1 && j <= board.size + i >= 1 && i <= board.size && j >= 1 && j <= board.size end function legal_move(board::Board, i::Int, j::Int, color::Int) - other = other_color(color) + other = other_color(color) - # Pass is always legal. - if is_pass_move(i, j) - return true - end + # Pass is always legal. + if is_pass_move(i, j) + return true + end - # Already occupied. - if board[i, j] != EMPTY - return false - end + # Already occupied. + if board[i, j] != EMPTY + return false + end - # Illegal ko recapture. It is not illegal to fill the ko so we must - # check the color of at least one neighbor. - if i == board.ko_i && j == board.ko_j && ((on_board(board, i - 1, j) && board[i - 1, j] == other) || (on_board(board, i + 1, j) && board[i + 1, j] == other)) - return false - end + # Illegal ko recapture. It is not illegal to fill the ko so we must + # check the color of at least one neighbor. + if i == board.ko_i && j == board.ko_j && + ((on_board(board, i - 1, j) && board[i - 1, j] == other) || + (on_board(board, i + 1, j) && board[i + 1, j] == other)) + return false + end - true + true end # Does the string at (i, j) have any more liberty than the one at (libi, libj)? function has_additional_liberty(board::Board, i::Int, j::Int, libi::Int, libj::Int) - start = POS(board, i, j) - pos = start - while true - (ai, aj) = IJ(board, pos) - for k = 1:4 - (bi, bj) = neighbor(ai, aj, k) - if on_board(board, bi, bj) && board[bi, bj] == EMPTY && (bi != libi || bj != libj) - return true - end - end + start = POS(board, i, j) + pos = start + while true + (ai, aj) = IJ(board, pos) + for k = 1:4 + (bi, bj) = neighbor(ai, aj, k) + if on_board(board, bi, bj) && board[bi, bj] == EMPTY && (bi != libi || bj != libj) + return true + end + end - pos = board.next_stone[pos] - if pos == start - break + pos = board.next_stone[pos] + if pos == start + break + end end - end - false + false end # Does (ai, aj) provide a liberty for a stone at (i, j)? function provides_liberty(board::Board, ai::Int, aj::Int, i::Int, j::Int, color::Int) - # A vertex off the board does not provide a liberty. - if !on_board(board, ai, aj) - return false - end - - # An empty vertex IS a liberty. - if board[ai, aj] == EMPTY - return true - end - - # A friendly string provides a liberty to (i, j) if it currently - # has more liberties than the one at (i, j). - if board[ai, aj] == color - return has_additional_liberty(board, ai, aj, i, j) - end - - # An unfriendly string provides a liberty if and only if it is - # captured, i.e. if it currently only has the liberty at (i, j). - !has_additional_liberty(board, ai, aj, i, j) + # A vertex off the board does not provide a liberty. + if !on_board(board, ai, aj) + return false + end + + # An empty vertex IS a liberty. + if board[ai, aj] == EMPTY + return true + end + + # A friendly string provides a liberty to (i, j) if it currently + # has more liberties than the one at (i, j). + if board[ai, aj] == color + return has_additional_liberty(board, ai, aj, i, j) + end + + # An unfriendly string provides a liberty if and only if it is + # captured, i.e. if it currently only has the liberty at (i, j). + !has_additional_liberty(board, ai, aj, i, j) end # Is a move at ij suicide for color? function suicide(board::Board, i::Int, j::Int, color::Int) - for k = 1:4 - if provides_liberty(board, neighbor(i, j, k)..., i, j, color) - return false + for k = 1:4 + if provides_liberty(board, neighbor(i, j, k)..., i, j, color) + return false + end end - end - true + true end # Remove a string from the board array. There is no need to modify # the next_stone array since this only matters where there are # stones present and the entire string is removed. function remove_string(board::Board, i::Int, j::Int) - start = POS(board, i, j) - pos = start - removed = 0 - while true - board.board[pos] = EMPTY - removed += 1 - pos = board.next_stone[pos] - if pos == start - break + start = POS(board, i, j) + pos = start + removed = 0 + while true + board.board[pos] = EMPTY + removed += 1 + pos = board.next_stone[pos] + if pos == start + break + end end - end - removed + removed end # Do two vertices belong to the same string? It is required that both # pos1 and pos2 point to vertices with stones. function same_string(board::Board, pos1::Int, pos2::Int) - pos = pos1 - while true - if pos == pos2 - return true - end - pos = board.next_stone[pos] - if pos == pos1 - break + pos = pos1 + while true + if pos == pos2 + return true + end + pos = board.next_stone[pos] + if pos == pos1 + break + end end - end - false + false end # Play at (i, j) for color. No legality check is done here. We need # to properly update the board array, the next_stone array, and the # ko point. function play_move(board::Board, i::Int, j::Int, color::Int) - pos = POS(board, i, j) - captured_stones = 0 - - # Reset the ko point. - board.ko_i = 0 - board.ko_j = 0 + pos = POS(board, i, j) + captured_stones = 0 - # Nothing more happens if the move was a pass. - if is_pass_move(i, j) - return - end + # Reset the ko point. + board.ko_i = 0 + board.ko_j = 0 - # If the move is a suicide we only need to remove the adjacent - # friendly stones. - if suicide(board, i, j, color) - for k = 1:4 - (ai, aj) = neighbor(i, j, k) - if on_board(board, ai, aj) && board[ai, aj] == color - remove_string(board, ai, aj) - end + # Nothing more happens if the move was a pass. + if is_pass_move(i, j) + return end - return - end - - # Not suicide. Remove captured opponent strings. - for k = 1:4 - (ai, aj) = neighbor(i, j, k) - if on_board(board, ai, aj) && board[ai, aj] == other_color(color) && !has_additional_liberty(board, ai, aj, i, j) - captured_stones += remove_string(board, ai, aj) + + # If the move is a suicide we only need to remove the adjacent + # friendly stones. + if suicide(board, i, j, color) + for k = 1:4 + (ai, aj) = neighbor(i, j, k) + if on_board(board, ai, aj) && board[ai, aj] == color + remove_string(board, ai, aj) + end + end + return end - end - - # Put down the new stone. Initially build a single stone string by - # setting next_stone[pos] pointing to itself. - board.board[pos] = color - board.next_stone[pos] = pos - - # If we have friendly neighbor strings we need to link the strings - # together. - for k = 1:4 - (ai, aj) = neighbor(i, j, k) - pos2 = POS(board, ai, aj) - # Make sure that the stones are not already linked together. This - # may happen if the same string neighbors the new stone in more - # than one direction. - if on_board(board, ai, aj) && board[pos2] == color && !same_string(board, pos, pos2) - # The strings are linked together simply by swapping the - # next_stone pointers. - (board.next_stone[pos], board.next_stone[pos2]) = (board.next_stone[pos2], board.next_stone[pos]) + + # Not suicide. Remove captured opponent strings. + for k = 1:4 + (ai, aj) = neighbor(i, j, k) + if on_board(board, ai, aj) && board[ai, aj] == other_color(color) && !has_additional_liberty(board, ai, aj, i, j) + captured_stones += remove_string(board, ai, aj) + end end - end - - # If we have captured exactly one stone and the new string is a - # single stone it may have been a ko capture. - if captured_stones == 1 && board.next_stone[pos] == pos - # Check whether the new string has exactly one liberty. If so it - # would be an illegal ko capture to play there immediately. We - # know that there must be a liberty immediately adjacent to the - # new stone since we captured one stone. + + # Put down the new stone. Initially build a single stone string by + # setting next_stone[pos] pointing to itself. + board.board[pos] = color + board.next_stone[pos] = pos + + # If we have friendly neighbor strings we need to link the strings + # together. for k = 1:4 - (ai, aj) = neighbor(i, j, k) - if on_board(board, ai, aj) && board[ai, aj] == EMPTY - if !has_additional_liberty(board, i, j, ai, aj) - board.ko_i = ai - board.ko_j = aj + (ai, aj) = neighbor(i, j, k) + pos2 = POS(board, ai, aj) + # Make sure that the stones are not already linked together. This + # may happen if the same string neighbors the new stone in more + # than one direction. + if on_board(board, ai, aj) && board[pos2] == color && !same_string(board, pos, pos2) + # The strings are linked together simply by swapping the + # next_stone pointers. + (board.next_stone[pos], board.next_stone[pos2]) = (board.next_stone[pos2], board.next_stone[pos]) + end + end + + # If we have captured exactly one stone and the new string is a + # single stone it may have been a ko capture. + if captured_stones == 1 && board.next_stone[pos] == pos + # Check whether the new string has exactly one liberty. If so it + # would be an illegal ko capture to play there immediately. We + # know that there must be a liberty immediately adjacent to the + # new stone since we captured one stone. + for k = 1:4 + (ai, aj) = neighbor(i, j, k) + if on_board(board, ai, aj) && board[ai, aj] == EMPTY + if !has_additional_liberty(board, i, j, ai, aj) + board.ko_i = ai + board.ko_j = aj + end + break + end end - break - end end - end end # Generate a move. function generate_move(board::Board, color::Int) - moves = zeros(Int, 2, board.size * board.size) - num_moves = 0 - - for ai = 1:board.size, aj = 1:board.size - # Consider moving at (ai, aj) if it is legal and not suicide. - if legal_move(board, ai, aj, color) && !suicide(board, ai, aj, color) - # Further require the move not to be suicide for the opponent... - if !suicide(board, ai, aj, other_color(color)) - num_moves += 1 - moves[:,num_moves] = [ai, aj] - else - # ...however, if the move captures at least one stone, - # consider it anyway. - for k = 1:4 - (bi, bj) = neighbor(ai, aj, k) - if on_board(board, bi, bj) && board[bi, bj] == other_color(color) - num_moves += 1 - moves[:,num_moves] = [ai, aj] - break - end + moves = zeros(Int, 2, board.size * board.size) + num_moves = 0 + + for ai = 1:board.size, aj = 1:board.size + # Consider moving at (ai, aj) if it is legal and not suicide. + if legal_move(board, ai, aj, color) && !suicide(board, ai, aj, color) + # Further require the move not to be suicide for the opponent... + if !suicide(board, ai, aj, other_color(color)) + num_moves += 1 + moves[:,num_moves] = [ai, aj] + else + # ...however, if the move captures at least one stone, + # consider it anyway. + for k = 1:4 + (bi, bj) = neighbor(ai, aj, k) + if on_board(board, bi, bj) && board[bi, bj] == other_color(color) + num_moves += 1 + moves[:,num_moves] = [ai, aj] + break + end + end + end end - end end - end - - # Choose one of the considered moves randomly with uniform - # distribution. (Strictly speaking the moves with smaller 1D - # coordinates tend to have a very slightly higher probability to be - # chosen, but for all practical purposes we get a uniform - # distribution.) - if num_moves > 0 - move = moves[:,1 + xor_randn(board.rand, num_moves)] - return (move[1], move[2]) - else - # But pass if no move was considered. - return (0, 0) - end + + # Choose one of the considered moves randomly with uniform + # distribution. (Strictly speaking the moves with smaller 1D + # coordinates tend to have a very slightly higher probability to be + # chosen, but for all practical purposes we get a uniform + # distribution.) + if num_moves > 0 + move = moves[:,1 + xor_randn(board.rand, num_moves)] + return (move[1], move[2]) + else + # But pass if no move was considered. + return (0, 0) + end end # Set a final status value for an entire string. function set_final_status_string(board::Board, pos::Int, status::Int) - start = pos - while true - board.final_status[pos] = status - pos = board.next_stone[pos] - if pos == start - break + start = pos + while true + board.final_status[pos] = status + pos = board.next_stone[pos] + if pos == start + break + end end - end end @@ -372,113 +374,113 @@ end # that will not happen. # function compute_final_status(board::Board) - board.final_status[:] = UNKNOWN - - for i = 1:board.size, j = 1:board.size - if board[i, j] == EMPTY - for k = 1:4 - (ai, aj) = neighbor(i, j, k) - if !on_board(board, ai, aj) - continue - end - # When the game is finished, we know for sure that (ai, aj) - # contains a stone. The move generation algorithm would - # never leave two adjacent empty vertices. Check the number - # of liberties to decide its status, unless it's known - # already. - # - # If we should be called in a non-final position, just make - # sure we don't call set_final_status_string() on an empty - # vertex. - pos = POS(board, ai, aj) - if board.final_status[ai, aj] == UNKNOWN - if board[ai, aj] != EMPTY - if has_additional_liberty(board, ai, aj, i, j) - set_final_status_string(board, pos, ALIVE) - else - set_final_status_string(board, pos, DEAD) + board.final_status[:] = UNKNOWN + + for i = 1:board.size, j = 1:board.size + if board[i, j] == EMPTY + for k = 1:4 + (ai, aj) = neighbor(i, j, k) + if !on_board(board, ai, aj) + continue + end + # When the game is finished, we know for sure that (ai, aj) + # contains a stone. The move generation algorithm would + # never leave two adjacent empty vertices. Check the number + # of liberties to decide its status, unless it's known + # already. + # + # If we should be called in a non-final position, just make + # sure we don't call set_final_status_string() on an empty + # vertex. + pos = POS(board, ai, aj) + if board.final_status[ai, aj] == UNKNOWN + if board[ai, aj] != EMPTY + if has_additional_liberty(board, ai, aj, i, j) + set_final_status_string(board, pos, ALIVE) + else + set_final_status_string(board, pos, DEAD) + end + end + end + # Set the final status of the pos vertex to either black + # or white territory. + if board.final_status[i, j] == UNKNOWN + if (board.final_status[ai, aj] == ALIVE) ⊻ (board[ai, aj] == WHITE) + board.final_status[i, j] = BLACK_TERRITORY + else + board.final_status[i, j] = WHITE_TERRITORY + end + end end - end end - # Set the final status of the pos vertex to either black - # or white territory. - if board.final_status[i, j] == UNKNOWN - if (board.final_status[ai, aj] == ALIVE) ⊻ (board[ai, aj] == WHITE) - board.final_status[i, j] = BLACK_TERRITORY - else - board.final_status[i, j] = WHITE_TERRITORY - end - end - end end - end end get_final_status(board::Board, i::Int, j::Int) = board.final_status[i, j] function compute_score(board::Board) - score = board.komi - compute_final_status(board) - for i = 1:board.size, j = 1:board.size - status = get_final_status(board, i, j) - if status == BLACK_TERRITORY - score -= 1.0 - elseif status == WHITE_TERRITORY - score += 1.0 - elseif (status == ALIVE) ⊻ (board[i, j] == WHITE) - score -= 1.0 - else - score += 1.0 + score = board.komi + compute_final_status(board) + for i = 1:board.size, j = 1:board.size + status = get_final_status(board, i, j) + if status == BLACK_TERRITORY + score -= 1.0 + elseif status == WHITE_TERRITORY + score += 1.0 + elseif (status == ALIVE) ⊻ (board[i, j] == WHITE) + score -= 1.0 + else + score += 1.0 + end end - end - score + score end function benchmark(num_games_per_point::Int) - random_seed = convert(UInt32, 1) - board_size = 9 - komi = 0.5 - - board = Board(board_size) - set_komi(board, komi) - set_random_seed(board, random_seed) - - for i = 1:board.size, j = 1:board.size - white_wins = 0 - black_wins = 0 - for k = 1:num_games_per_point - passes = 0 - num_moves = 1 - color = WHITE - clear(board) - play_move(board, i, j, BLACK) - while passes < 3 && num_moves < 600 - (movei, movej) = generate_move(board, color) - play_move(board, movei, movej, color) - if is_pass_move(movei, movej) - passes += 1 - else - passes = 0 - end - num_moves += 1 - color = other_color(color) - end - if passes == 3 - if compute_score(board) > 0 - white_wins += 1 - else - black_wins += 1 + random_seed = convert(UInt32, 1) + board_size = 9 + komi = 0.5 + + board = Board(board_size) + set_komi(board, komi) + set_random_seed(board, random_seed) + + for i = 1:board.size, j = 1:board.size + white_wins = 0 + black_wins = 0 + for k = 1:num_games_per_point + passes = 0 + num_moves = 1 + color = WHITE + clear(board) + play_move(board, i, j, BLACK) + while passes < 3 && num_moves < 600 + (movei, movej) = generate_move(board, color) + play_move(board, movei, movej, color) + if is_pass_move(movei, movej) + passes += 1 + else + passes = 0 + end + num_moves += 1 + color = other_color(color) + end + if passes == 3 + if compute_score(board) > 0 + white_wins += 1 + else + black_wins += 1 + end + end end - end +# @printf("%d %d %f\n", i - 1, j - 1, black_wins / (black_wins + white_wins)) end -# @printf("%d %d %f\n", i - 1, j - 1, black_wins / (black_wins + white_wins)) - end end function main(args) - n = 10 - if length(args) > 0 - n = parse(Int, args[1]) - end - @time benchmark(n) + n = 10 + if length(args) > 0 + n = parse(Int, args[1]) + end + @time benchmark(n) end From b0b5b00b16d252c83fc54d22df4c769d499e0ed7 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Thu, 16 Mar 2017 06:58:00 -0700 Subject: [PATCH 0227/1534] put comments at the same indentation level as code in base/linalg/givens.jl --- base/linalg/givens.jl | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/base/linalg/givens.jl b/base/linalg/givens.jl index 9100331761e5b..dc98cfece3bd8 100644 --- a/base/linalg/givens.jl +++ b/base/linalg/givens.jl @@ -170,31 +170,29 @@ function givensAlgorithm{T<:AbstractFloat}(f::Complex{T}, g::Complex{T}) f2 = abs2(fs) g2 = abs2(gs) if f2 <= max(g2, oneunit(T))*safmin - - # This is a rare case: F is very small. - + # This is a rare case: F is very small. if f == 0 cs = zero(T) r = complex(hypot(real(g), imag(g))) - # do complex/real division explicitly with two real divisions + # do complex/real division explicitly with two real divisions d = hypot(real(gs), imag(gs)) sn = complex(real(gs)/d, -imag(gs)/d) return cs, sn, r end f2s = hypot(real(fs), imag(fs)) - # g2 and g2s are accurate - # g2 is at least safmin, and g2s is at least safmn2 + # g2 and g2s are accurate + # g2 is at least safmin, and g2s is at least safmn2 g2s = sqrt(g2) - # error in cs from underflow in f2s is at most - # unfl / safmn2 .lt. sqrt(unfl*eps) .lt. eps - # if max(g2,one)=g2, then f2 .lt. g2*safmin, - # and so cs .lt. sqrt(safmin) - # if max(g2,one)=one, then f2 .lt. safmin - # and so cs .lt. sqrt(safmin)/safmn2 = sqrt(eps) - # therefore, cs = f2s/g2s / sqrt( 1 + (f2s/g2s)**2 ) = f2s/g2s + # error in cs from underflow in f2s is at most + # unfl / safmn2 .lt. sqrt(unfl*eps) .lt. eps + # if max(g2,one)=g2, then f2 .lt. g2*safmin, + # and so cs .lt. sqrt(safmin) + # if max(g2,one)=one, then f2 .lt. safmin + # and so cs .lt. sqrt(safmin)/safmn2 = sqrt(eps) + # therefore, cs = f2s/g2s / sqrt( 1 + (f2s/g2s)**2 ) = f2s/g2s cs = f2s/g2s - # make sure abs(ff) = 1 - # do complex/real division explicitly with 2 real divisions + # make sure abs(ff) = 1 + # do complex/real division explicitly with 2 real divisions if abs1(f) > 1 d = hypot(real(f), imag(f)) ff = complex(real(f)/d, imag(f)/d) @@ -207,17 +205,15 @@ function givensAlgorithm{T<:AbstractFloat}(f::Complex{T}, g::Complex{T}) sn = ff*complex(real(gs)/g2s, -imag(gs)/g2s) r = cs*f + sn*g else - - # This is the most common case. - # Neither F2 nor F2/G2 are less than SAFMIN - # F2S cannot overflow, and it is accurate - + # This is the most common case. + # Neither F2 nor F2/G2 are less than SAFMIN + # F2S cannot overflow, and it is accurate f2s = sqrt(onepar + g2/f2) - # do the f2s(real)*fs(complex) multiply with two real multiplies + # do the f2s(real)*fs(complex) multiply with two real multiplies r = complex(f2s*real(fs), f2s*imag(fs)) cs = onepar/f2s d = f2 + g2 - # do complex/real division explicitly with two real divisions + # do complex/real division explicitly with two real divisions sn = complex(real(r)/d, imag(r)/d) sn *= conj(gs) if count != 0 From f0a4ca78fcb11afa59fb26583cdd495cd758181c Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Thu, 16 Mar 2017 07:06:48 -0700 Subject: [PATCH 0228/1534] empty line before jldoctest openers in base/reflection.jl --- base/reflection.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/base/reflection.jl b/base/reflection.jl index d4ff5fe571998..26384404d3e4b 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -18,6 +18,7 @@ module_name(m::Module) = ccall(:jl_module_name, Ref{Symbol}, (Any,), m) module_parent(m::Module) -> Module Get a module's enclosing `Module`. `Main` is its own parent, as is `LastMain` after `workspace()`. + ```jldoctest julia> module_parent(Main) Main @@ -279,6 +280,7 @@ end Base.parameter_upper_bound(t::UnionAll, idx) Determine the upper bound of a type parameter in the underlying type. E.g.: + ```jldoctest julia> struct Foo{T<:AbstractFloat, N} x::Tuple{T, N} @@ -951,6 +953,7 @@ defined, this returns `false`. For parametric types, `allow_bottom_tparams` controls whether `Union{}` is considered a valid intersection of type parameters. For example: + ```jldoctest julia> foo(x::Complex{<:Integer}) = 1 foo (generic function with 1 method) From f538cbd95ade1da56866731fa1e93b0b7c53b611 Mon Sep 17 00:00:00 2001 From: Amit Murthy Date: Mon, 20 Mar 2017 12:43:24 +0530 Subject: [PATCH 0229/1534] Throw an exception for invalid hostnames in addprocs. (#21021) * throw an exception for invalid hostnames in addprocs. --- base/distributed/cluster.jl | 48 ++++++++++++++++++++++++--- base/distributed/managers.jl | 2 +- test/distributed_exec.jl | 64 +++++++++++++++++++++++++++++++++++- 3 files changed, 108 insertions(+), 6 deletions(-) diff --git a/base/distributed/cluster.jl b/base/distributed/cluster.jl index d307382dc4884..9b91ecc8bb74b 100644 --- a/base/distributed/cluster.jl +++ b/base/distributed/cluster.jl @@ -210,12 +210,46 @@ end # The master process uses this to connect to the worker and subsequently # setup a all-to-all network. function read_worker_host_port(io::IO) - while true - conninfo = readline(io) + t0 = time() + + # Wait at most for JULIA_WORKER_TIMEOUT seconds to read host:port + # info from the worker + timeout = worker_timeout() + + # We expect the first line to contain the host:port string. However, as + # the worker may be launched via ssh or a cluster manager like SLURM, + # ignore any informational / warning lines printed by the launch command. + # If we do not find the host:port string in the first 1000 lines, treat it + # as an error. + + ntries = 1000 + while ntries > 0 + readtask = @schedule readline(io) + yield() + while !istaskdone(readtask) && ((time() - t0) < timeout) + sleep(0.05) + end + !istaskdone(readtask) && break + + conninfo = wait(readtask) + if conninfo == "" && !isopen(io) + error("Unable to read host:port string from worker. Launch command exited with error?") + end + + ntries -= 1 bind_addr, port = parse_connection_info(conninfo) if bind_addr != "" return bind_addr, port end + + # TODO: Identify root cause and report a better actionable error. + # Also print unmatched lines? + end + close(io) + if ntries > 0 + error("Timed out waiting to read host:port string from worker.") + else + error("Unexpected output from worker launch command. Host:port string not found.") end end @@ -404,8 +438,14 @@ function create_worker(manager, wconfig) # initiate a connect. Does not wait for connection completion in case of TCP. w = Worker() + local r_s, w_s + try + (r_s, w_s) = connect(manager, w.id, wconfig) + catch e + deregister_worker(w.id) + rethrow(e) + end - (r_s, w_s) = connect(manager, w.id, wconfig) w = Worker(w.id, r_s, w_s, manager; config=wconfig) # install a finalizer to perform cleanup if necessary finalizer(w, (w)->if myid() == 1 manage(w.manager, w.id, w.config, :finalize) end) @@ -806,7 +846,7 @@ function deregister_worker(pg, pid) end end - if myid() == 1 + if myid() == 1 && isdefined(w, :config) # Notify the cluster manager of this workers death manage(w.manager, w.id, w.config, :deregister) if PGRP.topology != :all_to_all diff --git a/base/distributed/managers.jl b/base/distributed/managers.jl index be3ddd337b34a..bf66ead246bcd 100644 --- a/base/distributed/managers.jl +++ b/base/distributed/managers.jl @@ -201,7 +201,7 @@ function launch_on_machine(manager::SSHManager, machine, cnt, params, launched, # detach launches the command in a new process group, allowing it to outlive # the initial julia process (Ctrl-C and teardown methods are handled through messages) - # for the launched porcesses. + # for the launched processes. io, pobj = open(pipeline(detach(cmd), stderr=STDERR), "r") wconfig = WorkerConfig() diff --git a/test/distributed_exec.jl b/test/distributed_exec.jl index 4a90015c89934..ca77ab2fd433a 100644 --- a/test/distributed_exec.jl +++ b/test/distributed_exec.jl @@ -1269,19 +1269,81 @@ end if DoFullTest pids=addprocs(4); @test_throws ErrorException rmprocs(pids; waitfor=0.001); - rmprocs(pids) + # wait for workers to be removed + while any(x -> (x in procs()), pids) + sleep(0.1) + end end # Test addprocs/rmprocs from master node only for f in [ ()->addprocs(1), ()->rmprocs(workers()) ] try remotecall_fetch(f, id_other) + error("Unexpected") catch ex @test isa(ex, RemoteException) @test ex.captured.ex.msg == "Only process 1 can add and remove workers" end end +# Test the following addprocs error conditions +# - invalid host name - github issue #20372 +# - julia exe exiting with an error +# - timeout reading host:port from worker STDOUT +# - host:port not found in worker STDOUT in the first 1000 lines + +struct ErrorSimulator <: ClusterManager + mode +end + +function Base.launch(manager::ErrorSimulator, params::Dict, launched::Array, c::Condition) + exename = params[:exename] + dir = params[:dir] + + cmd = `$(Base.julia_cmd(exename)) --startup-file=no` + if manager.mode == :timeout + cmd = `$cmd -e "sleep(10)"` + elseif manager.mode == :ntries + cmd = `$cmd -e "[println(x) for x in 1:1001]"` + elseif manager.mode == :exit + cmd = `$cmd -e "exit(-1)"` + else + error("Unknown mode") + end + io, pobj = open(pipeline(detach(setenv(cmd, dir=dir)); stderr=STDERR), "r") + + wconfig = WorkerConfig() + wconfig.process = pobj + wconfig.io = io + push!(launched, wconfig) + notify(c) +end + +testruns = Any[] + +if DoFullTest + append!(testruns, [(()->addprocs(["errorhost20372"]), "Unable to read host:port string from worker. Launch command exited with error?", ())]) +end + +append!(testruns, [ + (()->addprocs(ErrorSimulator(:exit)), "Unable to read host:port string from worker. Launch command exited with error?", ()), + (()->addprocs(ErrorSimulator(:ntries)), "Unexpected output from worker launch command. Host:port string not found.", ()), + (()->addprocs(ErrorSimulator(:timeout)), "Timed out waiting to read host:port string from worker.", ("JULIA_WORKER_TIMEOUT"=>"1",)) +]) + +for (addp_testf, expected_errstr, env) in testruns + try + withenv(env...) do + addp_testf() + end + error("Unexpected") + catch ex + @test isa(ex, CompositeException) + @test ex.exceptions[1].ex.msg == expected_errstr + end +end + + # Auto serialization of globals from Main. # bitstypes global v1 = 1 From 8c091c8539c7c4f13a130d2c36b78e8d23323861 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Sat, 4 Feb 2017 05:44:43 -0800 Subject: [PATCH 0230/1534] clean up some one-liners in string functions remove unnecessary spaces inside [] in contains doctest fix nonstandard indentation in utf8proc tests top level testset in a file under test/ should be redundant now fix some typos and grammar in a few comments add some spaces in arnoldi tests combine sentences instead of starting one with And change bitstype to primitive bits type in simd-types docs fix plural subtypes fix plural or other types fix retrhow and unsatifiable typos in base/pkg/resolve.jl code highlighting in types manual section --- base/inference.jl | 2 +- base/linalg/triangular.jl | 2 +- base/pkg/resolve.jl | 4 +- base/reduce.jl | 2 +- base/shell.jl | 2 +- base/strings/util.jl | 14 +++---- doc/src/manual/calling-c-and-fortran-code.md | 6 +-- doc/src/manual/methods.md | 2 +- doc/src/manual/parallel-computing.md | 2 +- doc/src/manual/types.md | 8 ++-- doc/src/stdlib/simd-types.md | 2 +- src/codegen.cpp | 10 ++--- src/dump.c | 2 +- src/gc.c | 2 +- src/typemap.c | 2 +- test/libgit2-online.jl | 4 -- test/libgit2.jl | 4 +- test/linalg/arnoldi.jl | 39 ++++++++++---------- test/unicode/utf8proc.jl | 20 +++++----- 19 files changed, 62 insertions(+), 67 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index b96b26d22b3e5..db9c435095fb3 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -4768,7 +4768,7 @@ function void_use_elim_pass!(sv::InferenceState) return !effect_free(ex, sv.src, sv.mod, false) elseif (isa(ex, GotoNode) || isa(ex, LineNumberNode) || isa(ex, NewvarNode) || isa(ex, Symbol) || isa(ex, LabelNode)) - # This is a list of special type handled by the compiler + # This is a list of special types handled by the compiler return true end return false diff --git a/base/linalg/triangular.jl b/base/linalg/triangular.jl index 79c0d426bb226..e8c42211743bd 100644 --- a/base/linalg/triangular.jl +++ b/base/linalg/triangular.jl @@ -1583,7 +1583,7 @@ for (f, g) in ((:\, :A_ldiv_B!), (:Ac_ldiv_B, :Ac_ldiv_B!), (:At_ldiv_B, :At_ldi end end end -### Multiplication with triangle to the rigth and hence lhs cannot be transposed. +### Multiplication with triangle to the right and hence lhs cannot be transposed. for (f, g) in ((:*, :A_mul_B!), (:A_mul_Bc, :A_mul_Bc!), (:A_mul_Bt, :A_mul_Bt!)) mat != :AbstractVector && @eval begin function ($f)(A::$mat, B::AbstractTriangular) diff --git a/base/pkg/resolve.jl b/base/pkg/resolve.jl index 6f59b96a7fe50..84bcf42ff21f6 100644 --- a/base/pkg/resolve.jl +++ b/base/pkg/resolve.jl @@ -26,7 +26,7 @@ function resolve(reqs::Requires, deps::Dict{String,Dict{VersionNumber,Available} try sol = maxsum(graph, msgs) catch err - isa(err, UnsatError) || retrhow(err) + isa(err, UnsatError) || rethrow(err) p = interface.pkgs[err.info] # TODO: build tools to analyze the problem, and suggest to use them here. msg = @@ -35,7 +35,7 @@ function resolve(reqs::Requires, deps::Dict{String,Dict{VersionNumber,Available} The problem was detected when trying to find a feasible version for package $p. However, this only means that package $p is involved in an - unsatifiable or difficult dependency relation, and the root of + unsatisfiable or difficult dependency relation, and the root of the problem may be elsewhere. """ if msgs.num_nondecimated != graph.np diff --git a/base/reduce.jl b/base/reduce.jl index 8aa76b7ac5535..4aaf7c8952b1a 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -637,7 +637,7 @@ const ∈ = in Returns `true` if there is at least one element `y` in `itr` such that `fun(y,x)` is `true`. ```jldoctest -julia> vec = [ 10, 100, 200 ] +julia> vec = [10, 100, 200] 3-element Array{Int64,1}: 10 100 diff --git a/base/shell.jl b/base/shell.jl index fee255181225d..234d6a8428a5f 100644 --- a/base/shell.jl +++ b/base/shell.jl @@ -129,7 +129,7 @@ function shell_split(s::AbstractString) parsed = shell_parse(s, false)[1] args = String[] for arg in parsed - push!(args, string(arg...)) + push!(args, string(arg...)) end args end diff --git a/base/strings/util.jl b/base/strings/util.jl index d38bacbc759b2..d4c1431b072ba 100644 --- a/base/strings/util.jl +++ b/base/strings/util.jl @@ -21,7 +21,7 @@ function startswith(a::AbstractString, b::AbstractString) while !done(a,i) && !done(b,i) c, i = next(a,i) d, j = next(b,j) - if c != d return false end + (c != d) && (return false) end done(b,i) end @@ -48,7 +48,7 @@ function endswith(a::AbstractString, b::AbstractString) while a1 <= i && b1 <= j c = a[i] d = b[j] - if c != d return false end + (c != d) && (return false) i = prevind(a,i) j = prevind(b,j) end @@ -90,9 +90,9 @@ julia> chomp("Hello\\n") """ function chomp(s::AbstractString) i = endof(s) - if (i < 1 || s[i] != '\n') return SubString(s, 1, i) end + (i < 1 || s[i] != '\n') && (return SubString(s, 1, i)) j = prevind(s,i) - if (j < 1 || s[j] != '\r') return SubString(s, 1, i-1) end + (j < 1 || s[j] != '\r') && (return SubString(s, 1, i-1)) return SubString(s, 1, j-1) end function chomp(s::String) @@ -197,7 +197,7 @@ strip(s::AbstractString, chars::Chars) = lstrip(rstrip(s, chars), chars) function lpad(s::AbstractString, n::Integer, p::AbstractString=" ") m = n - strwidth(s) - if m <= 0; return s; end + (m <= 0) && (return s) l = strwidth(p) if l==1 return string(p^m, s) @@ -210,7 +210,7 @@ end function rpad(s::AbstractString, n::Integer, p::AbstractString=" ") m = n - strwidth(s) - if m <= 0; return s; end + (m <= 0) && (return s) l = strwidth(p) if l==1 return string(s, p^m) @@ -286,7 +286,7 @@ function _split(str::AbstractString, splitter, limit::Integer, keep_empty::Bool, end i = k end - if k <= j; k = nextind(str,j) end + (k <= j) && (k = nextind(str,j)) r = search(str,splitter,k) j, k = first(r), nextind(str,last(r)) end diff --git a/doc/src/manual/calling-c-and-fortran-code.md b/doc/src/manual/calling-c-and-fortran-code.md index 1ce2f564c0972..e6fc2ee62a8c5 100644 --- a/doc/src/manual/calling-c-and-fortran-code.md +++ b/doc/src/manual/calling-c-and-fortran-code.md @@ -269,7 +269,7 @@ First, a review of some relevant Julia type terminology: | `T{A}` | `Vector{Int}` | "Type Parameter" :: A specialization of a type (typically used for dispatch or storage optimization). | | | | "TypeVar" :: The `T` in the type parameter declaration is referred to as a TypeVar (short for type variable). | | `primitive type` | `Int`, `Float64` | "Primitive Type" :: A type with no fields, but a size. It is stored and defined by-value. | -| `struct` | `Pair{Int, Int}` | "Struct" :: A type with all fields defined to be constant. It is defined by-value. And may be stored with a type-tag. | +| `struct` | `Pair{Int, Int}` | "Struct" :: A type with all fields defined to be constant. It is defined by-value, and may be stored with a type-tag. | | | `Complex128` (`isbits`) | "Is-Bits" :: A `primitive type`, or a `struct` type where all fields are other `isbits` types. It is defined by-value, and is stored without a type-tag. | | `struct ...; end` | `nothing` | "Singleton" :: a Leaf Type or Struct with no fields. | | `(...)` or `tuple(...)` | `(1, 2, 3)` | "Tuple" :: an immutable data-structure similar to an anonymous struct type, or a constant array. Represented as either an array or a struct. | @@ -847,8 +847,8 @@ case, the expression must evaluate to a `Ptr`, which will be used as the address function to call. This behavior occurs when the first [`ccall`](@ref) argument contains references to non-constants, such as local variables, function arguments, or non-constant globals. -For example, you might lookup the function via `dlsym`, then cache it in a global variable for -that session. For example: +For example, you might look up the function via `dlsym`, then cache it in a global +variable for that session. For example: ```julia macro dlsym(func, lib) diff --git a/doc/src/manual/methods.md b/doc/src/manual/methods.md index 4317e9ace8cdf..6f03e442989bb 100644 --- a/doc/src/manual/methods.md +++ b/doc/src/manual/methods.md @@ -827,7 +827,7 @@ end # other padding methods go here function myfilter(A, kernel, ::NoPad) - # Here's the "real" implementation of the core computation + # Here's the "real" implementation of the core computation end ``` diff --git a/doc/src/manual/parallel-computing.md b/doc/src/manual/parallel-computing.md index a986fa00f1b0e..ed465297c25c6 100644 --- a/doc/src/manual/parallel-computing.md +++ b/doc/src/manual/parallel-computing.md @@ -928,7 +928,7 @@ Next, define the kernel: julia> @everywhere function advection_chunk!(q, u, irange, jrange, trange) @show (irange, jrange, trange) # display so we can see what's happening for t in trange, j in jrange, i in irange - q[i,j,t+1] = q[i,j,t] + u[i,j,t] + q[i,j,t+1] = q[i,j,t] + u[i,j,t] end q end diff --git a/doc/src/manual/types.md b/doc/src/manual/types.md index 2928db8be59df..6e5ed12fd99cc 100644 --- a/doc/src/manual/types.md +++ b/doc/src/manual/types.md @@ -972,7 +972,7 @@ The slightly odd feature of these declarations as compared to typical parametric is that the type parameter `T` is not used in the definition of the type itself -- it is just an abstract tag, essentially defining an entire family of types with identical structure, differentiated only by their type parameter. Thus, `Ptr{Float64}` and `Ptr{Int64}` are distinct types, even though -they have identical representations. And of course, all specific pointer types are subtype of +they have identical representations. And of course, all specific pointer types are subtypes of the umbrella `Ptr` type: ```jldoctest @@ -988,7 +988,7 @@ true We have said that a parametric type like `Ptr` acts as a supertype of all its instances (`Ptr{Int64}` etc.). How does this work? `Ptr` itself cannot be a normal data type, since without knowing the type of the referenced data the type clearly cannot be used for memory operations. -The answer is that `Ptr` (or other parametric type like `Array`) is a different kind of type called a +The answer is that `Ptr` (or other parametric types like `Array`) is a different kind of type called a `UnionAll` type. Such a type expresses the *iterated union* of types for all values of some parameter. `UnionAll` types are usually written using the keyword `where`. For example `Ptr` could be more @@ -1056,8 +1056,8 @@ element type. Sometimes it is convenient to introduce a new name for an already expressible type. This can be done with a simple assignment statement. -For example, UInt is aliased to either UInt32 or UInt64 as is appropriate for the size of pointers -on the system: +For example, `UInt` is aliased to either `UInt32` or `UInt64` as is appropriate +for the size of pointers on the system: ```julia # 32-bit system: diff --git a/doc/src/stdlib/simd-types.md b/doc/src/stdlib/simd-types.md index e35c443948707..7da49c924b32e 100644 --- a/doc/src/stdlib/simd-types.md +++ b/doc/src/stdlib/simd-types.md @@ -10,7 +10,7 @@ end ``` It has a special compilation rule: a homogeneous tuple of `VecElement{T}` maps to an LLVM `vector` -type when `T` is a bitstype and the tuple length is in the set {2-6,8-10,16}. +type when `T` is a primitive bits type and the tuple length is in the set {2-6,8-10,16}. At `-O3`, the compiler *might* automatically vectorize operations on such tuples. For example, the following program, when compiled with `julia -O3` generates two SIMD addition instructions diff --git a/src/codegen.cpp b/src/codegen.cpp index 0a270f14dcf3d..b4f33810c93db 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -778,7 +778,7 @@ static inline jl_cgval_t update_julia_type(const jl_cgval_t &v, jl_value_t *typ, return jl_cgval_t(v.V, v.gcroot, true, typ, NULL); } else { - // type mismatch (there wasn't any boxed values in the union) + // type mismatch (there weren't any boxed values in the union) CreateTrap(builder); return jl_cgval_t(); } @@ -885,7 +885,7 @@ static jl_cgval_t convert_julia_type(const jl_cgval_t &v, jl_value_t *typ, jl_co return jl_cgval_t(v.V, v.gcroot, true, typ, NULL); } else { - // type mismatch: there wasn't any boxed values in the union + // type mismatch: there weren't any boxed values in the union CreateTrap(builder); return jl_cgval_t(); } @@ -3515,7 +3515,7 @@ static jl_cgval_t emit_local(jl_value_t *slotload, jl_codectx_t *ctx) if (!vi.isVolatile || vi.value.constant || !vi.value.V) { v = vi.value; if (vi.pTIndex) - v.TIndex = builder.CreateLoad(vi.pTIndex); + v.TIndex = builder.CreateLoad(vi.pTIndex); } else { // copy value to a non-volatile location @@ -3528,7 +3528,7 @@ static jl_cgval_t emit_local(jl_value_t *slotload, jl_codectx_t *ctx) builder.CreateStore(unbox, slot); Value *tindex = NULL; if (vi.pTIndex) - tindex = builder.CreateLoad(vi.pTIndex, /*volatile*/true); + tindex = builder.CreateLoad(vi.pTIndex, /*volatile*/true); v = mark_julia_slot(slot, vi.value.typ, tindex, tbaa_stack); } if (vi.boxroot == NULL) @@ -3542,7 +3542,7 @@ static jl_cgval_t emit_local(jl_value_t *slotload, jl_codectx_t *ctx) Value *boxed = builder.CreateLoad(vi.boxroot, vi.isVolatile); Value *box_isnull; if (vi.usedUndef) - box_isnull = builder.CreateICmpNE(boxed, V_null); + box_isnull = builder.CreateICmpNE(boxed, V_null); if (vi.pTIndex) { // value is either boxed in the stack slot, or unboxed in value // as indicated by testing (pTIndex & 0x80) diff --git a/src/dump.c b/src/dump.c index c8c0364e8828f..dc9a97ed7961f 100644 --- a/src/dump.c +++ b/src/dump.c @@ -2698,7 +2698,7 @@ JL_DLLEXPORT int jl_save_incremental(const char *fname, jl_array_t *worklist) #ifndef NDEBUG // skip the performance optimizations of jl_types_equal and just use subtyping directly -// ones of these types is invalid - that's why we're doing the recache type operation +// one of these types is invalid - that's why we're doing the recache type operation static int jl_invalid_types_equal(jl_datatype_t *a, jl_datatype_t *b) { return jl_subtype((jl_value_t*)a, (jl_value_t*)b) && jl_subtype((jl_value_t*)b, (jl_value_t*)a); diff --git a/src/gc.c b/src/gc.c index f23a3a8de3608..471669a4afee9 100644 --- a/src/gc.c +++ b/src/gc.c @@ -501,7 +501,7 @@ STATIC_INLINE void gc_queue_big_marked(jl_ptls_t ptls, bigval_t *hdr, } // `gc_setmark_tag` can be called concurrently on multiple threads. -// In all cases, the functions atomically sets the mark bits and returns +// In all cases, the function atomically sets the mark bits and returns // the GC bits set as well as if the tag was unchanged by this thread. // All concurrent calls on the same object are guaranteed to be setting the // bits to the same value. diff --git a/src/typemap.c b/src/typemap.c index eb5ee8aefcfd0..5274b7e96d697 100644 --- a/src/typemap.c +++ b/src/typemap.c @@ -1006,7 +1006,7 @@ jl_typemap_entry_t *jl_typemap_insert(union jl_typemap_t *cache, jl_value_t *par newrec->max_world = max_world; // compute the complexity of this type signature newrec->va = jl_is_va_tuple((jl_datatype_t*)ttype); - newrec->issimplesig = !jl_is_unionall(type); // a TypeVar environment needs an complex matching test + newrec->issimplesig = !jl_is_unionall(type); // a TypeVar environment needs a complex matching test newrec->isleafsig = newrec->issimplesig && !newrec->va; // entirely leaf types don't need to be sorted JL_GC_PUSH1(&newrec); assert(jl_is_tuple_type(ttype)); diff --git a/test/libgit2-online.jl b/test/libgit2-online.jl index 590555a8958c9..b8ad3069f2954 100644 --- a/test/libgit2-online.jl +++ b/test/libgit2-online.jl @@ -1,7 +1,5 @@ # This file is a part of Julia. License is MIT: http://julialang.org/license -@testset "libgit2-online" begin - ######### # TESTS # ######### @@ -34,5 +32,3 @@ mktempdir() do dir end end end - -end diff --git a/test/libgit2.jl b/test/libgit2.jl index fb4c18a5e65b8..2ebbdd6e47eb0 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -481,7 +481,7 @@ mktempdir() do dir @test length(status) != 0 @test_throws BoundsError status[0] @test_throws BoundsError status[length(status)+1] - #we've added a file - show that it is new + # we've added a file - show that it is new @test status[1].status == LibGit2.Consts.STATUS_WT_NEW close(repo_file) finally @@ -635,7 +635,7 @@ mktempdir() do dir fetch_heads = LibGit2.fetchheads(repo) @test fetch_heads[1].name == "refs/heads/master" - @test fetch_heads[1].ismerge == true #we just merged master + @test fetch_heads[1].ismerge == true # we just merged master @test fetch_heads[2].name == "refs/heads/test_branch" @test fetch_heads[2].ismerge == false @test fetch_heads[3].name == "refs/tags/tag2" diff --git a/test/linalg/arnoldi.jl b/test/linalg/arnoldi.jl index 0b66a85c713e9..b5da8bfb8c979 100644 --- a/test/linalg/arnoldi.jl +++ b/test/linalg/arnoldi.jl @@ -88,7 +88,6 @@ let A6965 = [ -1.0 0.0 0.0 0.0 0.0 0.0 7.0 1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 -1.0 8.0 ] - d, = eigs(A6965,which=:SM,nev=2,ncv=4,tol=eps()) @test d[1] ≈ 2.5346936860350002 @test real(d[2]) ≈ 2.6159972444834976 @@ -105,48 +104,48 @@ end # Example from Quantum Information Theory import Base: size, issymmetric, ishermitian -mutable struct CPM{T<:Base.LinAlg.BlasFloat}<:AbstractMatrix{T} # completely positive map +mutable struct CPM{T<:Base.LinAlg.BlasFloat} <: AbstractMatrix{T} # completely positive map kraus::Array{T,3} # kraus operator representation end -size(Phi::CPM)=(size(Phi.kraus,1)^2,size(Phi.kraus,3)^2) -issymmetric(Phi::CPM)=false -ishermitian(Phi::CPM)=false +size(Phi::CPM) = (size(Phi.kraus,1)^2,size(Phi.kraus,3)^2) +issymmetric(Phi::CPM) = false +ishermitian(Phi::CPM) = false import Base: A_mul_B! function A_mul_B!{T<:Base.LinAlg.BlasFloat}(rho2::StridedVector{T},Phi::CPM{T},rho::StridedVector{T}) - rho=reshape(rho,(size(Phi.kraus,3),size(Phi.kraus,3))) - rho1=zeros(T,(size(Phi.kraus,1),size(Phi.kraus,1))) - for s=1:size(Phi.kraus,2) - As=view(Phi.kraus,:,s,:) - rho1+=As*rho*As' + rho = reshape(rho,(size(Phi.kraus,3),size(Phi.kraus,3))) + rho1 = zeros(T,(size(Phi.kraus,1),size(Phi.kraus,1))) + for s = 1:size(Phi.kraus,2) + As = view(Phi.kraus,:,s,:) + rho1 += As*rho*As' end return copy!(rho2,rho1) end let # Generate random isometry - (Q,R)=qr(randn(100,50)) - Q=reshape(Q,(50,2,50)) + (Q,R) = qr(randn(100,50)) + Q = reshape(Q,(50,2,50)) # Construct trace-preserving completely positive map from this - Phi=CPM(copy(Q)) + Phi = CPM(copy(Q)) (d,v,nconv,numiter,numop,resid) = eigs(Phi,nev=1,which=:LM) # Properties: largest eigenvalue should be 1, largest eigenvector, when reshaped as matrix # should be a Hermitian positive definite matrix (up to an arbitrary phase) @test d[1] ≈ 1. # largest eigenvalue should be 1. - v=reshape(v,(50,50)) # reshape to matrix - v/=trace(v) # factor out arbitrary phase + v = reshape(v,(50,50)) # reshape to matrix + v /= trace(v) # factor out arbitrary phase @test vecnorm(imag(v)) ≈ 0. # it should be real - v=real(v) + v = real(v) # @test vecnorm(v-v')/2 ≈ 0. # it should be Hermitian # Since this fails sometimes (numerical precision error),this test is commented out - v=(v+v')/2 + v = (v+v')/2 @test isposdef(v) # Repeat with starting vector (d2,v2,nconv2,numiter2,numop2,resid2) = eigs(Phi,nev=1,which=:LM,v0=reshape(v,(2500,))) - v2=reshape(v2,(50,50)) - v2/=trace(v2) - @test numiter2 Date: Tue, 21 Feb 2017 21:30:06 -0800 Subject: [PATCH 0231/1534] rename oid to oid_ptr in fetchhead_foreach_callback add a few spaces after # comment openers spell out acronyms in compiler devdocs make spacing more conventional in test/replutil.jl --- base/libgit2/callbacks.jl | 5 +++-- base/libgit2/rebase.jl | 2 +- base/linalg/triangular.jl | 2 +- doc/src/devdocs/compiler.md | 4 ++-- test/linalg/lq.jl | 2 +- test/replutil.jl | 20 +++++--------------- test/sparse/sparsevector.jl | 8 ++++---- 7 files changed, 17 insertions(+), 26 deletions(-) diff --git a/base/libgit2/callbacks.jl b/base/libgit2/callbacks.jl index 41d01594dfb6a..225612afd8031 100644 --- a/base/libgit2/callbacks.jl +++ b/base/libgit2/callbacks.jl @@ -248,9 +248,10 @@ function credentials_callback(libgit2credptr::Ptr{Ptr{Void}}, url_ptr::Cstring, end function fetchhead_foreach_callback(ref_name::Cstring, remote_url::Cstring, - oid::Ptr{GitHash}, is_merge::Cuint, payload::Ptr{Void}) + oid_ptr::Ptr{GitHash}, is_merge::Cuint, payload::Ptr{Void}) fhead_vec = unsafe_pointer_to_objref(payload)::Vector{FetchHead} - push!(fhead_vec, FetchHead(unsafe_string(ref_name), unsafe_string(remote_url), unsafe_load(oid), is_merge == 1)) + push!(fhead_vec, FetchHead(unsafe_string(ref_name), unsafe_string(remote_url), + unsafe_load(oid_ptr), is_merge == 1)) return Cint(0) end diff --git a/base/libgit2/rebase.jl b/base/libgit2/rebase.jl index 8a740497013af..7c4ef40c18a85 100644 --- a/base/libgit2/rebase.jl +++ b/base/libgit2/rebase.jl @@ -46,7 +46,7 @@ end function Base.show(io::IO, rb::GitRebase) println(io, "GitRebase:") println(io, "Number: ", count(rb)) - println(io, "Currently performing operation: ",current(rb)+1) + println(io, "Currently performing operation: ", current(rb)+1) end """ diff --git a/base/linalg/triangular.jl b/base/linalg/triangular.jl index e8c42211743bd..53dc720c2138c 100644 --- a/base/linalg/triangular.jl +++ b/base/linalg/triangular.jl @@ -475,7 +475,7 @@ for (t, uploc, isunitc) in ((:LowerTriangular, 'L', 'N'), return inv(LAPACK.trcon!('O', $uploc, $isunitc, A.data)) elseif p == Inf return inv(LAPACK.trcon!('I', $uploc, $isunitc, A.data)) - else #use fallback + else # use fallback return cond(full(A), p) end end diff --git a/doc/src/devdocs/compiler.md b/doc/src/devdocs/compiler.md index 5b4f0fd7fe3bb..d9dd69e5e3b41 100644 --- a/doc/src/devdocs/compiler.md +++ b/doc/src/devdocs/compiler.md @@ -18,7 +18,7 @@ ensuring they are valid both for the current runtime and after deserialization. When emitted into the object file, these globals are stored as references in a large `gvals` table. This allows the deserializer to reference them by index, -and implement a custom manual GOT-like mechanism to restore them. +and implement a custom manual mechanism similar to a Global Offset Table (GOT) to restore them. Function pointers are handled similarly. They are stored as values in a large `fvals` table. @@ -28,7 +28,7 @@ Note that extern functions are handled separately, with names, via the usual symbol resolution mechanism in the linker. Note too that ccall functions are also handled separately, -via a manual GOT + PLT. +via a manual GOT and Procedure Linkage Table (PLT). ## Representation of Intermediate Values diff --git a/test/linalg/lq.jl b/test/linalg/lq.jl index 8329d02877cd8..6b27927b8c9dc 100644 --- a/test/linalg/lq.jl +++ b/test/linalg/lq.jl @@ -80,7 +80,7 @@ bimg = randn(n,2)/2 @test_throws DimensionMismatch Ac_mul_B(q,ones(eltya,n+2,n+2)) @test_throws DimensionMismatch ones(eltyb,n+2,n+2)*q if isa(a, DenseArray) && isa(b, DenseArray) - #use this to test 2nd branch in mult code + # use this to test 2nd branch in mult code pad_a = vcat(eye(a), a) pad_b = hcat(eye(b), b) @test pad_a*q ≈ pad_a*full(q,thin=false) atol=100ε diff --git a/test/replutil.jl b/test/replutil.jl index 8d00670c63d1d..468aa48aa3fdd 100644 --- a/test/replutil.jl +++ b/test/replutil.jl @@ -503,27 +503,17 @@ let method_error = MethodError(EnclosingModule.AbstractTypeNoConstructors, ()) # Test that it shows a special message when no constructors have been defined by the user. - @test sprint( - showerror, - method_error - ) == "MethodError: no constructors have been defined for $(EnclosingModule.AbstractTypeNoConstructors)" + @test sprint(showerror, method_error) == + "MethodError: no constructors have been defined for $(EnclosingModule.AbstractTypeNoConstructors)" # Does it go back to previous behaviour when there *is* at least # one constructor defined? EnclosingModule.AbstractTypeNoConstructors(x, y) = x + y - @test startswith(sprint( - showerror, - method_error - ), "MethodError: no method matching $(EnclosingModule.AbstractTypeNoConstructors)()" - ) + @test startswith(sprint(showerror, method_error), + "MethodError: no method matching $(EnclosingModule.AbstractTypeNoConstructors)()") # Test that the 'default' sysimg.jl method is not displayed. - @test !contains(sprint( - showerror, - method_error - ), - "where T at sysimg.jl" - ) + @test !contains(sprint(showerror, method_error), "where T at sysimg.jl") # Test that tab-completion will not show the 'default' sysimg.jl method. for method_string in Base.REPLCompletions.complete_methods(:(EnclosingModule.AbstractTypeNoConstructors())) diff --git a/test/sparse/sparsevector.jl b/test/sparse/sparsevector.jl index c79a556e59c66..1a7ac162b2b09 100644 --- a/test/sparse/sparsevector.jl +++ b/test/sparse/sparsevector.jl @@ -1080,13 +1080,13 @@ s14046 = sprand(5, 1.0) @test 2*s14046 == s14046 + s14046 # Issue 14589 -#test vectors with no zero elements +# test vectors with no zero elements x = sparsevec(1:7, [3., 2., -1., 1., -2., -3., 3.], 7) @test collect(sort(x)) == sort(collect(x)) -#test vectors with all zero elements +# test vectors with all zero elements x = sparsevec(Int64[], Float64[], 7) @test collect(sort(x)) == sort(collect(x)) -#test vector with sparsity approx 1/2 +# test vector with sparsity approx 1/2 x = sparsevec(1:7, [3., 2., -1., 1., -2., -3., 3.], 15) @test collect(sort(x)) == sort(collect(x)) # apply three distinct tranformations where zeros sort into start/middle/end @@ -1094,7 +1094,7 @@ x = sparsevec(1:7, [3., 2., -1., 1., -2., -3., 3.], 15) @test collect(sort(x, by=sign)) == sort(collect(x), by=sign) @test collect(sort(x, by=inv)) == sort(collect(x), by=inv) -#fill! +# fill! for Tv in [Float32, Float64, Int64, Int32, Complex128] for Ti in [Int16, Int32, Int64, BigInt] sptypes = (SparseMatrixCSC{Tv, Ti}, SparseVector{Tv, Ti}) From a6acbd53e7d6e6757858182723d4964006ac68d4 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Thu, 16 Mar 2017 10:33:51 -0700 Subject: [PATCH 0232/1534] use === for comparison to nothing --- test/boundscheck_exec.jl | 2 +- test/libgit2.jl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/boundscheck_exec.jl b/test/boundscheck_exec.jl index da04b49b9e60e..c8d41f184bd55 100644 --- a/test/boundscheck_exec.jl +++ b/test/boundscheck_exec.jl @@ -204,7 +204,7 @@ function V1() end if bc_opt == bc_default || bc_opt == bc_off - @test V1() == nothing + @test V1() === nothing else @test_throws BoundsError V1() end diff --git a/test/libgit2.jl b/test/libgit2.jl index 2ebbdd6e47eb0..96e098e529e68 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -93,8 +93,8 @@ end @testset "scp-like syntax, no port" begin m = match(LibGit2.URL_REGEX, "server:1234/repo") @test m[:scheme] === nothing - @test m[:user] == nothing - @test m[:password] == nothing + @test m[:user] === nothing + @test m[:password] === nothing @test m[:host] == "server" @test m[:port] === nothing @test m[:path] == "1234/repo" From 64a4fe7132934b15ad1272a63863aa1a3d005398 Mon Sep 17 00:00:00 2001 From: Martin Holters Date: Mon, 20 Mar 2017 10:05:07 +0100 Subject: [PATCH 0233/1534] Use `typejoin` of the field types for `eltype` of heterogeneous `Tuple`s --- base/tuple.jl | 9 +++++++++ test/tuple.jl | 7 ++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/base/tuple.jl b/base/tuple.jl index b3799e57d6fba..e96e3ab06db97 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -63,6 +63,15 @@ first(t::Tuple) = t[1] eltype(::Type{Tuple{}}) = Bottom eltype(::Type{<:Tuple{Vararg{E}}}) where {E} = E +function eltype(t::Type{<:Tuple}) + @_pure_meta + t´ = unwrap_unionall(t) + r = Union{} + for ti in t´.parameters + r = typejoin(r, unwrapva(ti)) + end + return rewrap_unionall(r, t) +end # version of tail that doesn't throw on empty tuples (used in array indexing) safe_tail(t::Tuple) = tail(t) diff --git a/test/tuple.jl b/test/tuple.jl index 20ccbe348587c..8a2e3de09275b 100644 --- a/test/tuple.jl +++ b/test/tuple.jl @@ -65,8 +65,13 @@ end @test eltype((1,2,3)) === Int @test eltype((1.0,2.0,3.0)) <: AbstractFloat @test eltype((true, false)) === Bool -@test eltype((1,2.0, false)) === Any +@test eltype((1, 2.0, false)) === typejoin(Int, Float64, Bool) @test eltype(()) === Union{} +@test eltype(Tuple{Int, Float64, Vararg{Bool}}) === typejoin(Int, Float64, Bool) +@test eltype(Tuple{Int, T, Vararg{Bool}} where T <: AbstractFloat) === + typejoin(Int, AbstractFloat, Bool) +@test eltype(Tuple{Int, Bool, Vararg{T}} where T <: AbstractFloat) === + typejoin(Int, AbstractFloat, Bool) begin local foo From da53d717ebdcacef2f712b6cb9c8ba6bbf97b64e Mon Sep 17 00:00:00 2001 From: Martin Holters Date: Mon, 20 Mar 2017 17:24:24 +0100 Subject: [PATCH 0234/1534] Move `rewrap_unionall` in `eltype(::Type{<:Tuple})` --- base/tuple.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/tuple.jl b/base/tuple.jl index e96e3ab06db97..ec4bcbf2434a4 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -68,9 +68,9 @@ function eltype(t::Type{<:Tuple}) t´ = unwrap_unionall(t) r = Union{} for ti in t´.parameters - r = typejoin(r, unwrapva(ti)) + r = typejoin(r, rewrap_unionall(unwrapva(ti), t)) end - return rewrap_unionall(r, t) + return r end # version of tail that doesn't throw on empty tuples (used in array indexing) From a108f059cbfa8eae9e8a844c8c4bb2e06a13aa3a Mon Sep 17 00:00:00 2001 From: Amit Murthy Date: Mon, 20 Mar 2017 22:09:02 +0530 Subject: [PATCH 0235/1534] Improve task switching times (#21111) --- base/event.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/event.jl b/base/event.jl index 0d455ebf18195..940340ec162c4 100644 --- a/base/event.jl +++ b/base/event.jl @@ -76,7 +76,7 @@ end ## scheduler and work queue -global const Workqueue = Any[] +global const Workqueue = Task[] function enq_work(t::Task) t.state == :runnable || error("schedule: Task not runnable") From dd5a7ac4beb11492a48ba5eb0a3207630bc3bf76 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Mon, 20 Mar 2017 11:50:31 -0500 Subject: [PATCH 0236/1534] Only create file upon wget success --- base/interactiveutil.jl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/base/interactiveutil.jl b/base/interactiveutil.jl index a966d50fb3864..dd5727b83dc53 100644 --- a/base/interactiveutil.jl +++ b/base/interactiveutil.jl @@ -587,7 +587,12 @@ else end end if downloadcmd == :wget - run(`wget -O $filename $url`) + try + run(`wget -O $filename $url`) + catch + rm(filename) # wget always creates a file + rethrow() + end elseif downloadcmd == :curl run(`curl -L -f -o $filename $url`) elseif downloadcmd == :fetch From 4b71891a3a8b4810f5b75d47e8ed86c056efc2b5 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Mon, 20 Mar 2017 19:32:28 +0000 Subject: [PATCH 0237/1534] Fix typo in inference --- base/inference.jl | 2 +- test/inference.jl | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index b96b26d22b3e5..be1e16ba7d8cf 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -1796,7 +1796,7 @@ function abstract_call(f::ANY, fargs::Union{Tuple{},Vector{Any}}, argtypes::Vect if isa(argtypes[2], Const) && isa(argtypes[3], Const) svecval = argtypes[2].val idx = argtypes[3].val - if isa(idx, Int) && 1 <= idx <= length(svecval) & + if isa(idx, Int) && 1 <= idx <= length(svecval) && isassigned(svecval, idx) return Const(getindex(svecval, idx)) end diff --git a/test/inference.jl b/test/inference.jl index dfc4bf8d4375e..3864b72725b69 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -707,4 +707,8 @@ err20033(x::Float64...) = prod(x) @test bcast_eltype_20033(err20033, [1]) === Union{} @test Base.return_types(bcast_eltype_20033, (typeof(err20033), Vector{Int},)) == Any[Type{Union{}}] # return_type on builtins -@test Core.Inference.return_type(tuple, Tuple{Int,Int8,Int}) === Tuple{Int,Int8,Int} \ No newline at end of file +@test Core.Inference.return_type(tuple, Tuple{Int,Int8,Int}) === Tuple{Int,Int8,Int} + +# Inference of constant svecs +@eval fsvecinf() = $(QuoteNode(Core.svec(Tuple{Int,Int}, Int)))[1] +@test Core.Inference.return_type(fsvecinf, Tuple{}) == Type{Tuple{Int,Int}} From 2894595306aa9fd74e41d2f92af093df8bbe4f94 Mon Sep 17 00:00:00 2001 From: Fabio Cardeal Date: Fri, 3 Mar 2017 20:44:21 -0300 Subject: [PATCH 0238/1534] Improve performance of skipchars for small inputs This mostly solves the problem, now the function is only significantly (2x) slower when there are no characters to skip, otherwise it's mostly the same for 1 or 2 characters and faster for 3 or more. Also improve the tests a little. --- base/iostream.jl | 2 +- test/iostream.jl | 22 +++++++++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/base/iostream.jl b/base/iostream.jl index 0fa45aea98954..e6a56b24ee477 100644 --- a/base/iostream.jl +++ b/base/iostream.jl @@ -327,7 +327,7 @@ function skipchars(io::IOStream, pred; linecomment=nothing) if c === linecomment readline(io) elseif !pred(c) - seek(io,position(io)-sizeof(string(c))) + skip(io, -codelen(c)) break end end diff --git a/test/iostream.jl b/test/iostream.jl index 3ca501aa8e4ab..1b817ce26d2b6 100644 --- a/test/iostream.jl +++ b/test/iostream.jl @@ -4,15 +4,15 @@ mktemp() do path, file function append_to_file(str) mark(file) - println(file, str) + print(file, str) flush(file) reset(file) end # test it doesn't error on eof - @test skipchars(file, isspace) == file + @test eof(skipchars(file, isspace)) - # test if it correctly skips + # test it correctly skips append_to_file(" ") @test eof(skipchars(file, isspace)) @@ -22,12 +22,20 @@ mktemp() do path, file # test it stops at the appropriate time append_to_file(" not a space") - @test skipchars(file, isspace) == file - @test !eof(file) && read(file, Char) == 'n' + @test !eof(skipchars(file, isspace)) + @test read(file, Char) == 'n' # test it correctly ignores the contents of comment lines append_to_file(" #not a space \n not a space") - @test skipchars(file, isspace, linecomment='#') == file - @test !eof(file) && read(file, Char) == 'n' + @test !eof(skipchars(file, isspace, linecomment='#')) + @test read(file, Char) == 'n' + + # test it correctly handles unicode + for (byte,char) in zip(1:4, ('@','߷','࿊','𐋺')) + append_to_file("abcdef$char") + @test Base.codelen(char) == byte + @test !eof(skipchars(file, isalpha)) + @test read(file, Char) == char + end end From 91f32751730eaa4e9104d431b13cd249c5a367dc Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 20 Mar 2017 19:52:29 -0700 Subject: [PATCH 0239/1534] fix #21088, missing `widenconst` in `return_type` (#21115) --- base/inference.jl | 2 ++ test/inference.jl | 3 +++ 2 files changed, 5 insertions(+) diff --git a/base/inference.jl b/base/inference.jl index f67f614806977..30c9181369dbf 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -5372,6 +5372,8 @@ function return_type(f::ANY, t::ANY) rt = builtin_tfunction(f, Any[t.parameters...], nothing, params) if isa(rt, TypeVar) rt = rt.ub + else + rt = widenconst(rt) end else for m in _methods(f, t, -1, params.world) diff --git a/test/inference.jl b/test/inference.jl index 3864b72725b69..bb0ba052e1652 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -709,6 +709,9 @@ err20033(x::Float64...) = prod(x) # return_type on builtins @test Core.Inference.return_type(tuple, Tuple{Int,Int8,Int}) === Tuple{Int,Int8,Int} +# issue #21088 +@test Core.Inference.return_type(typeof, Tuple{Int}) == Type{Int} + # Inference of constant svecs @eval fsvecinf() = $(QuoteNode(Core.svec(Tuple{Int,Int}, Int)))[1] @test Core.Inference.return_type(fsvecinf, Tuple{}) == Type{Tuple{Int,Int}} From 4752d246105ec7c9114efa51fd15ce7cb4e950e9 Mon Sep 17 00:00:00 2001 From: Martin Holters Date: Tue, 21 Mar 2017 08:51:57 +0100 Subject: [PATCH 0240/1534] Handle `Union` of `Tuple`s in `eltype(::Type{<:Tuple})` --- base/tuple.jl | 1 + test/tuple.jl | 1 + 2 files changed, 2 insertions(+) diff --git a/base/tuple.jl b/base/tuple.jl index ec4bcbf2434a4..3b45f812fc0b6 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -65,6 +65,7 @@ eltype(::Type{Tuple{}}) = Bottom eltype(::Type{<:Tuple{Vararg{E}}}) where {E} = E function eltype(t::Type{<:Tuple}) @_pure_meta + t isa Union && return typejoin(eltype(t.a), eltype(t.b)) t´ = unwrap_unionall(t) r = Union{} for ti in t´.parameters diff --git a/test/tuple.jl b/test/tuple.jl index 8a2e3de09275b..70f08a30f667a 100644 --- a/test/tuple.jl +++ b/test/tuple.jl @@ -72,6 +72,7 @@ end typejoin(Int, AbstractFloat, Bool) @test eltype(Tuple{Int, Bool, Vararg{T}} where T <: AbstractFloat) === typejoin(Int, AbstractFloat, Bool) +@test eltype(Union{Tuple{Int, Float64}, Tuple{Vararg{Bool}}}) === typejoin(Int, Float64, Bool) begin local foo From 9b1477b943cbfca6d4b255dbbb828a345c254ae1 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 17 Mar 2017 19:57:00 -0400 Subject: [PATCH 0241/1534] fix #21074, constant fold more expressions --- base/inference.jl | 30 +++++++++++++----------------- test/inline.jl | 9 +++++++++ 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 30c9181369dbf..04b5d675364e6 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -3348,15 +3348,8 @@ const _pure_builtins = Any[tuple, svec, fieldtype, apply_type, ===, isa, typeof, # known effect-free calls (might not be affect-free) const _pure_builtins_volatile = Any[getfield, arrayref] -function is_pure_builtin(f::ANY) - if contains_is(_pure_builtins, f) - return true - end - if contains_is(_pure_builtins_volatile, f) - return true - end - if isa(f,IntrinsicFunction) - if !(f === Intrinsics.pointerref || # this one is volatile +function is_pure_intrinsic(f::IntrinsicFunction) + return !(f === Intrinsics.pointerref || # this one is volatile f === Intrinsics.pointerset || # this one is never effect-free f === Intrinsics.llvmcall || # this one is never effect-free f === Intrinsics.checked_trunc_sint || @@ -3368,13 +3361,13 @@ function is_pure_builtin(f::ANY) f === Intrinsics.check_top_bit || f === Intrinsics.sqrt_llvm || f === Intrinsics.cglobal) # cglobal throws an error for symbol-not-found - return true - end - end - if f === return_type - return true - end - return false +end + +function is_pure_builtin(f::ANY) + return (contains_is(_pure_builtins, f) || + contains_is(_pure_builtins_volatile, f) || + (isa(f,IntrinsicFunction) && is_pure_intrinsic(f)) || + f === return_type) end function statement_effect_free(e::ANY, src::CodeInfo, mod::Module) @@ -3690,7 +3683,10 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference istopfunction(topmod, f, :typejoin) || istopfunction(topmod, f, :isbits) || istopfunction(topmod, f, :promote_type) || - (f === Core.kwfunc && length(argexprs) == 2)) + (f === Core.kwfunc && length(argexprs) == 2) || + contains_is(_pure_builtins, f) || + (f === getfield && effect_free(e, sv.src, sv.mod, false)) || + (isa(f,IntrinsicFunction) && is_pure_intrinsic(f))) return inline_as_constant(e.typ.val, argexprs, sv, nothing) end end diff --git a/test/inline.jl b/test/inline.jl index 9920ccd84cd8a..ef4c2f948d892 100644 --- a/test/inline.jl +++ b/test/inline.jl @@ -79,3 +79,12 @@ f18948() = (local bar::Int64; bar=1.5) g18948() = (local bar::Int32; bar=0x80000000) @test_throws InexactError f18948() @test_throws InexactError g18948() + +# issue #21074 +struct s21074 + x::Tuple{Int, Int} +end +@eval f21074() = $(s21074((1,2))).x[1] +let (src, _) = code_typed(f21074, ())[1] + @test src.code[1] == Expr(:return, QuoteNode(1)) +end From 2feb10b71382d240051cf8d720cb6ecb66ebf507 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sat, 18 Mar 2017 17:28:17 -0400 Subject: [PATCH 0242/1534] also for #21074, improve `getfield_elim_pass!` to handle more kinds of values --- base/inference.jl | 28 +++++++++++++++++++--------- test/inline.jl | 7 ++++++- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 04b5d675364e6..8d4ce15d08737 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -5064,15 +5064,25 @@ function _getfield_elim_pass!(e::Expr, sv::InferenceState) end end end - elseif isa(e1,Tuple) && isa(j,Int) && (1 <= j <= length(e1)) - e1j = e1[j] - if !(isa(e1j,Number) || isa(e1j,AbstractString) || isa(e1j,Tuple) || - isa(e1j,Type)) - e1j = QuoteNode(e1j) - end - return e1j - elseif isa(e1,QuoteNode) && isa(e1.value,Tuple) && isa(j,Int) && (1 <= j <= length(e1.value)) - return QuoteNode(e1.value[j]) + elseif isa(e1, GlobalRef) || isa(e1, Symbol) || isa(e1, Slot) || isa(e1, SSAValue) + # non-self-quoting value + else + if isa(e1, QuoteNode) + e1 = e1.value + end + if isimmutable(e1) + if isa(j, QuoteNode) + j = j.value + end + if isdefined(e1, j) + e1j = getfield(e1, j) + if !(isa(e1j,Number) || isa(e1j,AbstractString) || isa(e1j,Tuple) || + isa(e1j,Type)) + e1j = QuoteNode(e1j) + end + return e1j + end + end end end return e diff --git a/test/inline.jl b/test/inline.jl index ef4c2f948d892..a213f26e50ab0 100644 --- a/test/inline.jl +++ b/test/inline.jl @@ -84,7 +84,12 @@ g18948() = (local bar::Int32; bar=0x80000000) struct s21074 x::Tuple{Int, Int} end +@inline Base.getindex(v::s21074, i::Integer) = v.x[i] @eval f21074() = $(s21074((1,2))).x[1] let (src, _) = code_typed(f21074, ())[1] - @test src.code[1] == Expr(:return, QuoteNode(1)) + @test src.code[1] == Expr(:return, 1) +end +@eval g21074() = $(s21074((1,2)))[1] +let (src, _) = code_typed(g21074, ())[1] + @test src.code[1] == Expr(:return, 1) end From aa573314df73c00d4c7850280309ca87debbf148 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 20 Mar 2017 16:48:02 -0400 Subject: [PATCH 0243/1534] fix a bug in the t-func for `nfields` --- base/inference.jl | 2 +- test/inference.jl | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/base/inference.jl b/base/inference.jl index 8d4ce15d08737..3c0835ddcc74d 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -548,7 +548,7 @@ add_tfunc(nfields, 1, 1, isa(x,Conditional) && return Const(nfields(Bool)) if isType(x) isleaftype(x.parameters[1]) && return Const(nfields(x.parameters[1])) - elseif isa(x,DataType) && !x.abstract && !(x.name === Tuple.name && isvatuple(x)) + elseif isa(x,DataType) && !x.abstract && !(x.name === Tuple.name && isvatuple(x)) && x !== DataType return Const(length(x.types)) end return Int diff --git a/test/inference.jl b/test/inference.jl index bb0ba052e1652..788dfd6f8eddf 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -715,3 +715,8 @@ err20033(x::Float64...) = prod(x) # Inference of constant svecs @eval fsvecinf() = $(QuoteNode(Core.svec(Tuple{Int,Int}, Int)))[1] @test Core.Inference.return_type(fsvecinf, Tuple{}) == Type{Tuple{Int,Int}} + +# nfields tfunc on `DataType` +let f = ()->Val{nfields(DataType[Int][1])} + @test f() == Val{0} +end From 48d69d43abd00e45bee3114c6c6d24e1d3949aab Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 20 Mar 2017 16:48:41 -0400 Subject: [PATCH 0244/1534] fix a bug in `getfield` t-func on invalid calls --- base/inference.jl | 3 +++ test/inference.jl | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/base/inference.jl b/base/inference.jl index 3c0835ddcc74d..500159d42bf7b 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -777,6 +777,9 @@ function getfield_tfunc(s00::ANY, name) if isa(sv, Module) && isa(nv, Symbol) return abstract_eval_global(sv, nv) end + if !(isa(nv,Symbol) || isa(nv,Int)) + return Bottom + end if (isa(sv, SimpleVector) || isimmutable(sv)) && isdefined(sv, nv) return abstract_eval_constant(getfield(sv, nv)) end diff --git a/test/inference.jl b/test/inference.jl index 788dfd6f8eddf..23f24982ab468 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -720,3 +720,7 @@ err20033(x::Float64...) = prod(x) let f = ()->Val{nfields(DataType[Int][1])} @test f() == Val{0} end + +# inference on invalid getfield call +@eval _getfield_with_string_() = getfield($(1=>2), "") +@test Base.return_types(_getfield_with_string_, ()) == Any[Union{}] From 2e1f30bc608501ab5ae279d5c53de96fec73e0e7 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 20 Mar 2017 16:49:13 -0400 Subject: [PATCH 0245/1534] improve constant folding of SimpleVector length and `nfields` --- base/inference.jl | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 500159d42bf7b..998446b7d75a7 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -1818,6 +1818,10 @@ function abstract_call(f::ANY, fargs::Union{Tuple{},Vector{Any}}, argtypes::Vect return t1===Bottom ? Bottom : Tuple{t1, Int} end end + elseif la==2 && argtypes[2] ⊑ SimpleVector && istopfunction(tm, f, :length) + if isa(argtypes[2], Const) + return Const(length(argtypes[2].val)) + end end atype = argtypes_to_type(argtypes) @@ -3346,7 +3350,7 @@ function exprtype(x::ANY, src::CodeInfo, mod::Module) end # known affect-free calls (also effect-free) -const _pure_builtins = Any[tuple, svec, fieldtype, apply_type, ===, isa, typeof, UnionAll] +const _pure_builtins = Any[tuple, svec, fieldtype, apply_type, ===, isa, typeof, UnionAll, nfields] # known effect-free calls (might not be affect-free) const _pure_builtins_volatile = Any[getfield, arrayref] @@ -3422,7 +3426,7 @@ function effect_free(e::ANY, src::CodeInfo, mod::Module, allow_volatile::Bool) if Const(:uid) ⊑ exprtype(ea[3], src, mod) return false # DataType uid field can change end - elseif !isa(typ, DataType) || typ.mutable || typ.abstract + elseif typ !== SimpleVector && (!isa(typ, DataType) || typ.mutable || typ.abstract) return false end end @@ -3860,6 +3864,8 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference force_infer = true end end + elseif la == 2 && method.name == :length && atypes[2] ⊑ SimpleVector + force_infer = true end end end @@ -3879,7 +3885,7 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference # or existing inferred code info frame = nothing # Union{Void, InferenceState} src = nothing # Union{Void, CodeInfo} - if force_infer && isa(atypes[3], Const) + if force_infer && la>2 && isa(atypes[3], Const) # Since we inferred this with the information that atypes[3]::Const, # must inline with that same information. # We do that by overriding the argument type, @@ -5073,9 +5079,13 @@ function _getfield_elim_pass!(e::Expr, sv::InferenceState) if isa(e1, QuoteNode) e1 = e1.value end - if isimmutable(e1) + if isimmutable(e1) || isa(e1,SimpleVector) + # SimpleVector length field is immutable if isa(j, QuoteNode) j = j.value + if !(isa(j,Int) || isa(j,Symbol)) + return e + end end if isdefined(e1, j) e1j = getfield(e1, j) From 297bfc5d762451bb4b8e3f0d5c029e58dc87ac2c Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 21 Mar 2017 12:13:33 -0400 Subject: [PATCH 0246/1534] fix some issues around inlining constants avoid inlining large constants --- base/inference.jl | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 998446b7d75a7..98715619f38ae 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -6,6 +6,8 @@ import Core: _apply, svec, apply_type, Builtin, IntrinsicFunction, MethodInstanc const MAX_TYPEUNION_LEN = 3 const MAX_TYPE_DEPTH = 8 +const MAX_INLINE_CONST_SIZE = 256 + struct InferenceParams world::UInt @@ -3500,7 +3502,14 @@ function inline_as_constant(val::ANY, argexprs, sv::InferenceState, invoke_data: push!(stmts, invoke_texpr) end end - return (QuoteNode(val), stmts) + if !is_self_quoting(val) + val = QuoteNode(val) + end + return (val, stmts) +end + +function is_self_quoting(x::ANY) + return isa(x,Number) || isa(x,AbstractString) || isa(x,Tuple) || isa(x,Type) end function countunionsplit(atypes::Vector{Any}) @@ -3686,15 +3695,17 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference # special-case inliners for known pure functions that compute types if sv.params.inlining if isa(e.typ, Const) # || isconstType(e.typ) + val = e.typ.val if (f === apply_type || f === fieldtype || f === typeof || f === (===) || istopfunction(topmod, f, :typejoin) || istopfunction(topmod, f, :isbits) || istopfunction(topmod, f, :promote_type) || (f === Core.kwfunc && length(argexprs) == 2) || - contains_is(_pure_builtins, f) || - (f === getfield && effect_free(e, sv.src, sv.mod, false)) || - (isa(f,IntrinsicFunction) && is_pure_intrinsic(f))) - return inline_as_constant(e.typ.val, argexprs, sv, nothing) + (isbits(val) && Core.sizeof(val) <= MAX_INLINE_CONST_SIZE && + (contains_is(_pure_builtins, f) || + (f === getfield && effect_free(e, sv.src, sv.mod, false)) || + (isa(f,IntrinsicFunction) && is_pure_intrinsic(f))))) + return inline_as_constant(val, argexprs, sv, nothing) end end end @@ -4473,7 +4484,10 @@ function inlining_pass(e::Expr, sv::InferenceState, stmts, ins) if isa(aarg,Expr) && (is_known_call(aarg, tuple, sv.src, sv.mod) || is_known_call(aarg, svec, sv.src, sv.mod)) # apply(f,tuple(x,y,...)) => f(x,y,...) newargs[i-2] = aarg.args[2:end] - elseif isa(aarg, Tuple) + elseif isa(aarg, Tuple) || (isa(aarg, QuoteNode) && isa(aarg.value, Tuple)) + if isa(aarg, QuoteNode) + aarg = aarg.value + end newargs[i-2] = Any[ QuoteNode(x) for x in aarg ] elseif isa(t, DataType) && t.name === Tuple.name && !isvatuple(t) && length(t.parameters) <= sv.params.MAX_TUPLE_SPLAT @@ -5089,8 +5103,7 @@ function _getfield_elim_pass!(e::Expr, sv::InferenceState) end if isdefined(e1, j) e1j = getfield(e1, j) - if !(isa(e1j,Number) || isa(e1j,AbstractString) || isa(e1j,Tuple) || - isa(e1j,Type)) + if !is_self_quoting(e1j) e1j = QuoteNode(e1j) end return e1j From 1d79a036dfc5af7cce2b9f52ef484b1481ac0101 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 21 Mar 2017 13:04:22 -0400 Subject: [PATCH 0247/1534] fix unary `<:` and `>:` call syntax --- src/julia-syntax.scm | 2 +- test/parse.jl | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index c7ae4e9fdbde5..da8af6d56f48d 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -1586,7 +1586,7 @@ ;; convert an operator parsed as (op a b) to (call op a b) (define (syntactic-op-to-call e) - `(call ,(car e) ,(expand-forms (cadr e)) ,(expand-forms (caddr e)))) + `(call ,(car e) ,@(map expand-forms (cdr e)))) ;; wrap `expr` in a function appropriate for consuming values from given ranges (define (func-for-generator-ranges expr range-exprs) diff --git a/test/parse.jl b/test/parse.jl index f74f81c57d361..9c809743c90ef 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -1056,3 +1056,5 @@ macro make_f21054(T) end @eval @make_f21054 $Array @test isa(f21054, Function) +g21054(>:) = >:2 +@test g21054(-) == -2 From 3bdfeef0579a9be7e2b6336235d77d5366e805ba Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Tue, 21 Mar 2017 14:56:58 -0400 Subject: [PATCH 0248/1534] fix FFTW crash after set_num_threads --- base/fft/FFTW.jl | 28 +++++++++++++--------------- test/fft.jl | 8 ++++++++ 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/base/fft/FFTW.jl b/base/fft/FFTW.jl index 6bd73247cbbe1..3b90329b99456 100644 --- a/base/fft/FFTW.jl +++ b/base/fft/FFTW.jl @@ -128,23 +128,21 @@ end # Threads -let initialized = false - global set_num_threads - function set_num_threads(nthreads::Integer) - if !initialized - # must re-initialize FFTW if any FFTW routines have been called - ccall((:fftw_cleanup,libfftw), Void, ()) - ccall((:fftwf_cleanup,libfftwf), Void, ()) - stat = ccall((:fftw_init_threads,libfftw), Int32, ()) - statf = ccall((:fftwf_init_threads,libfftwf), Int32, ()) - if stat == 0 || statf == 0 - error("could not initialize FFTW threads") - end - initialized = true +const threads_initialized = Ref(false) +function set_num_threads(nthreads::Integer) + if !threads_initialized[] + # must forget wisdom if any FFTW routines have been called + # (don't call fftw_cleanup, since that would invalidate existing plans) + forget_wisdom() + stat = ccall((:fftw_init_threads,libfftw), Int32, ()) + statf = ccall((:fftwf_init_threads,libfftwf), Int32, ()) + if stat == 0 || statf == 0 + error("could not initialize FFTW threads") end - ccall((:fftw_plan_with_nthreads,libfftw), Void, (Int32,), nthreads) - ccall((:fftwf_plan_with_nthreads,libfftwf), Void, (Int32,), nthreads) + threads_initialized[] = true end + ccall((:fftw_plan_with_nthreads,libfftw), Void, (Int32,), nthreads) + ccall((:fftwf_plan_with_nthreads,libfftwf), Void, (Int32,), nthreads) end # pointer type for fftw_plan (opaque pointer) diff --git a/test/fft.jl b/test/fft.jl index b55ccbe25a1cb..90623aae3470e 100644 --- a/test/fft.jl +++ b/test/fft.jl @@ -1,5 +1,13 @@ # This file is a part of Julia. License is MIT: http://julialang.org/license +# issue #19892 +# (test this first to make sure it happens before set_num_threads) +let a = randn(10^5,1), p1 = plan_rfft(a) + FFTW.set_num_threads(2) + p2 = plan_rfft(a) + @test p1*a ≈ p2*a +end + # fft a = rand(8) + im*rand(8) @test norm(ifft(fft(a)) - a) < 1e-8 From 2873c0e0d64a8097e87e9393f5e15b50d3b6ade7 Mon Sep 17 00:00:00 2001 From: Stefan Karpinski Date: Thu, 16 Mar 2017 11:04:52 -0400 Subject: [PATCH 0249/1534] cosmetic: add a couple of newlines at file ends --- test/dates/accessors.jl | 2 +- test/linalg/rowvector.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/dates/accessors.jl b/test/dates/accessors.jl index 3ce9048f3b1b3..2abfc649d745b 100644 --- a/test/dates/accessors.jl +++ b/test/dates/accessors.jl @@ -205,4 +205,4 @@ tr = [b, b, b, b, b, b, b, b, b, b] @test Dates.second.(tr) == repmat([3], 10) @test Dates.millisecond.(tr) == repmat([4], 10) @test Dates.microsecond.(tr) == repmat([5], 10) -@test Dates.nanosecond.(tr) == repmat([6], 10) \ No newline at end of file +@test Dates.nanosecond.(tr) == repmat([6], 10) diff --git a/test/linalg/rowvector.jl b/test/linalg/rowvector.jl index 011a17992eb68..8bd6e5c91e333 100644 --- a/test/linalg/rowvector.jl +++ b/test/linalg/rowvector.jl @@ -267,4 +267,4 @@ end @testset "ambiguity between * methods with RowVectors and ConjRowVectors (#20971)" begin @test RowVector(ConjArray(ones(4))) * ones(4) == 4 -end \ No newline at end of file +end From 214206a07e9f404cc7604b725361e3b37dadb74b Mon Sep 17 00:00:00 2001 From: Stefan Karpinski Date: Thu, 16 Mar 2017 11:06:11 -0400 Subject: [PATCH 0250/1534] rename allow_bottom(_tparams)? => ambiguous_bottom --- base/reflection.jl | 8 ++++---- base/test.jl | 8 ++++---- test/ambiguous.jl | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/base/reflection.jl b/base/reflection.jl index 26384404d3e4b..9e2796811f208 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -943,7 +943,7 @@ function method_exists(f::ANY, t::ANY, world=typemax(UInt)) end """ - isambiguous(m1, m2, [allow_bottom_tparams=true]) -> Bool + isambiguous(m1, m2, [ambiguous_bottom=true]) -> Bool Determine whether two methods `m1` and `m2` (typically of the same function) are ambiguous. This test is performed in the context of @@ -951,7 +951,7 @@ other methods of the same function; in isolation, `m1` and `m2` might be ambiguous, but if a third method resolving the ambiguity has been defined, this returns `false`. -For parametric types, `allow_bottom_tparams` controls whether +For parametric types, `ambiguous_bottom` controls whether `Union{}` is considered a valid intersection of type parameters. For example: ```jldoctest @@ -973,10 +973,10 @@ julia> Base.isambiguous(m1, m2, false) false ``` """ -function isambiguous(m1::Method, m2::Method, allow_bottom_tparams::Bool=true) +function isambiguous(m1::Method, m2::Method, ambiguous_bottom::Bool=true) ti = typeintersect(m1.sig, m2.sig) ti === Bottom && return false - if !allow_bottom_tparams + if !ambiguous_bottom has_bottom_parameter(ti) && return false end ml = _methods_by_ftype(ti, -1, typemax(UInt)) diff --git a/base/test.jl b/base/test.jl index 95bbd0f6f44be..57bb272026e01 100644 --- a/base/test.jl +++ b/base/test.jl @@ -1117,18 +1117,18 @@ function test_approx_eq_modphase{S<:Real,T<:Real}( end """ - detect_ambiguities(mod1, mod2...; imported=false, allow_bottom=true) + detect_ambiguities(mod1, mod2...; imported=false, ambiguous_bottom=true) Returns a vector of `(Method,Method)` pairs of ambiguous methods defined in the specified modules. Use `imported=true` if you wish to also test functions that were imported into these modules from elsewhere. -`allow_bottom` controls whether ambiguities triggered only by +`ambiguous_bottom` controls whether ambiguities triggered only by `Union{}` type parameters are included; in most cases you probably want to set this to `false`. See [`Base.isambiguous`](@ref). """ -function detect_ambiguities(mods...; imported::Bool=false, allow_bottom::Bool=true) +function detect_ambiguities(mods...; imported::Bool=false, ambiguous_bottom::Bool=true) function sortdefs(m1, m2) ord12 = m1.file < m2.file if !ord12 && (m1.file == m2.file) @@ -1150,7 +1150,7 @@ function detect_ambiguities(mods...; imported::Bool=false, allow_bottom::Bool=tr for m in mt if m.ambig !== nothing for m2 in m.ambig - if Base.isambiguous(m, m2, allow_bottom) + if Base.isambiguous(m, m2, ambiguous_bottom) push!(ambs, sortdefs(m, m2)) end end diff --git a/test/ambiguous.jl b/test/ambiguous.jl index 1e97b6e564680..41ace6ea007ae 100644 --- a/test/ambiguous.jl +++ b/test/ambiguous.jl @@ -134,7 +134,7 @@ ambs = detect_ambiguities(Ambig5) # Test that Core and Base are free of ambiguities # TODO jb/subtype: we now detect a lot more -@test_broken detect_ambiguities(Core, Base; imported=true, allow_bottom=false) == [] +@test_broken detect_ambiguities(Core, Base; imported=true, ambiguous_bottom=false) == [] # not using isempty so this prints more information when it fails amb_1(::Int8, ::Int) = 1 From fd531dc982561ae7520220bc74ece27ae6be4180 Mon Sep 17 00:00:00 2001 From: Stefan Karpinski Date: Thu, 16 Mar 2017 11:28:32 -0400 Subject: [PATCH 0251/1534] isambiguous: make ambiguous_bottom a keyword argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This matches detect_ambiguities – yes, isambiguous is unexported, but we know people will still use it and we may as well have consistent signatures here. --- base/reflection.jl | 13 +++++++------ base/test.jl | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/base/reflection.jl b/base/reflection.jl index 9e2796811f208..66b2b6158791e 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -943,7 +943,7 @@ function method_exists(f::ANY, t::ANY, world=typemax(UInt)) end """ - isambiguous(m1, m2, [ambiguous_bottom=true]) -> Bool + isambiguous(m1, m2; ambiguous_bottom=true) -> Bool Determine whether two methods `m1` and `m2` (typically of the same function) are ambiguous. This test is performed in the context of @@ -951,8 +951,9 @@ other methods of the same function; in isolation, `m1` and `m2` might be ambiguous, but if a third method resolving the ambiguity has been defined, this returns `false`. -For parametric types, `ambiguous_bottom` controls whether -`Union{}` is considered a valid intersection of type parameters. For example: +For parametric types, the `ambiguous_bottom` keyword argument controls whether +`Union{}` counts as an ambiguous intersection of type parameters – when `true`, +it is considered ambiguous, when `false` it is not. For example: ```jldoctest julia> foo(x::Complex{<:Integer}) = 1 @@ -966,14 +967,14 @@ julia> m1, m2 = collect(methods(foo)); julia> typeintersect(m1.sig, m2.sig) Tuple{#foo,Complex{Union{}}} -julia> Base.isambiguous(m1, m2, true) +julia> Base.isambiguous(m1, m2, ambiguous_bottom=true) true -julia> Base.isambiguous(m1, m2, false) +julia> Base.isambiguous(m1, m2, ambiguous_bottom=false) false ``` """ -function isambiguous(m1::Method, m2::Method, ambiguous_bottom::Bool=true) +function isambiguous(m1::Method, m2::Method; ambiguous_bottom::Bool=true) ti = typeintersect(m1.sig, m2.sig) ti === Bottom && return false if !ambiguous_bottom diff --git a/base/test.jl b/base/test.jl index 57bb272026e01..9c791aecbe311 100644 --- a/base/test.jl +++ b/base/test.jl @@ -1150,7 +1150,7 @@ function detect_ambiguities(mods...; imported::Bool=false, ambiguous_bottom::Boo for m in mt if m.ambig !== nothing for m2 in m.ambig - if Base.isambiguous(m, m2, ambiguous_bottom) + if Base.isambiguous(m, m2, ambiguous_bottom=ambiguous_bottom) push!(ambs, sortdefs(m, m2)) end end From 6969660e874390edfe16ebb54604d5db411e872e Mon Sep 17 00:00:00 2001 From: Stefan Karpinski Date: Tue, 21 Mar 2017 14:59:33 -0400 Subject: [PATCH 0252/1534] deprecate old arguments to isambiguous, detect_ambiguities --- base/deprecated.jl | 7 +++++++ base/test.jl | 10 +++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index 086e03949e09a..3524b4f1f28a6 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -107,6 +107,13 @@ macro deprecate_binding(old, new, export_old=true) Expr(:call, :deprecate, Expr(:quote, old))) end +# BEGIN 0.6-alpha deprecations (delete when 0.6 is released) + +@deprecate isambiguous(m1::Method, m2::Method, b::Bool) isambiguous(m1, m2, ambiguous_bottom=b) false +# TODO: delete allow_bottom keyword code in Base.Test.detect_ambiguities + +# END 0.6-alpha deprecations + # BEGIN 0.6 deprecations const _oldstyle_array_vcat_ = false diff --git a/base/test.jl b/base/test.jl index 9c791aecbe311..b8b0199634ac8 100644 --- a/base/test.jl +++ b/base/test.jl @@ -1128,7 +1128,15 @@ elsewhere. `Union{}` type parameters are included; in most cases you probably want to set this to `false`. See [`Base.isambiguous`](@ref). """ -function detect_ambiguities(mods...; imported::Bool=false, ambiguous_bottom::Bool=true) +function detect_ambiguities(mods...; + imported::Bool = false, + ambiguous_bottom::Bool = true, + allow_bottom::Union{Bool,Void} = nothing + ) + if allow_bottom != nothing + Base.depwarn("the `allow_bottom` keyword to detect_ambiguities has been renamed to `ambiguous_bottom`", :detect_ambiguities) + ambiguous_bottom = allow_bottom + end function sortdefs(m1, m2) ord12 = m1.file < m2.file if !ord12 && (m1.file == m2.file) From f3e73c0f3592c65b693e60b7b5871c277f235ae9 Mon Sep 17 00:00:00 2001 From: Stefan Karpinski Date: Tue, 21 Mar 2017 15:21:56 -0400 Subject: [PATCH 0253/1534] test ambiguous_bottom options to isambiguous, detect_ambiguities --- test/ambiguous.jl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/ambiguous.jl b/test/ambiguous.jl index 41ace6ea007ae..53081e36f9819 100644 --- a/test/ambiguous.jl +++ b/test/ambiguous.jl @@ -134,6 +134,7 @@ ambs = detect_ambiguities(Ambig5) # Test that Core and Base are free of ambiguities # TODO jb/subtype: we now detect a lot more +@test !isempty(detect_ambiguities(Core, Base; imported=true, ambiguous_bottom=true)) @test_broken detect_ambiguities(Core, Base; imported=true, ambiguous_bottom=false) == [] # not using isempty so this prints more information when it fails @@ -222,4 +223,15 @@ catch err end end +module Ambig9 +f(x::Complex{<:Integer}) = 1 +f(x::Complex{<:Rational}) = 2 +end +@test !Base.isambiguous(methods(Ambig9.f)..., ambiguous_bottom=false) +@test Base.isambiguous(methods(Ambig9.f)..., ambiguous_bottom=true) +@test Base.isambiguous(methods(Ambig9.f)...) +@test length(detect_ambiguities(Ambig9, ambiguous_bottom=false)) == 0 +@test length(detect_ambiguities(Ambig9, ambiguous_bottom=true)) == 1 +@test length(detect_ambiguities(Ambig9)) == 1 + nothing # don't return a module from the remote include From e2d9d5c4a3e8187b8493b8f3fc81b0a583798d85 Mon Sep 17 00:00:00 2001 From: Stefan Karpinski Date: Tue, 21 Mar 2017 15:34:16 -0400 Subject: [PATCH 0254/1534] swap default for ambiguous_bottom from true to false --- base/reflection.jl | 4 ++-- base/test.jl | 4 ++-- test/ambiguous.jl | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/base/reflection.jl b/base/reflection.jl index 66b2b6158791e..d0a36396c04bb 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -943,7 +943,7 @@ function method_exists(f::ANY, t::ANY, world=typemax(UInt)) end """ - isambiguous(m1, m2; ambiguous_bottom=true) -> Bool + isambiguous(m1, m2; ambiguous_bottom=false) -> Bool Determine whether two methods `m1` and `m2` (typically of the same function) are ambiguous. This test is performed in the context of @@ -974,7 +974,7 @@ julia> Base.isambiguous(m1, m2, ambiguous_bottom=false) false ``` """ -function isambiguous(m1::Method, m2::Method; ambiguous_bottom::Bool=true) +function isambiguous(m1::Method, m2::Method; ambiguous_bottom::Bool=false) ti = typeintersect(m1.sig, m2.sig) ti === Bottom && return false if !ambiguous_bottom diff --git a/base/test.jl b/base/test.jl index b8b0199634ac8..fa639f97b3863 100644 --- a/base/test.jl +++ b/base/test.jl @@ -1117,7 +1117,7 @@ function test_approx_eq_modphase{S<:Real,T<:Real}( end """ - detect_ambiguities(mod1, mod2...; imported=false, ambiguous_bottom=true) + detect_ambiguities(mod1, mod2...; imported=false, ambiguous_bottom=false) Returns a vector of `(Method,Method)` pairs of ambiguous methods defined in the specified modules. Use `imported=true` if you wish to @@ -1130,7 +1130,7 @@ want to set this to `false`. See [`Base.isambiguous`](@ref). """ function detect_ambiguities(mods...; imported::Bool = false, - ambiguous_bottom::Bool = true, + ambiguous_bottom::Bool = false, allow_bottom::Union{Bool,Void} = nothing ) if allow_bottom != nothing diff --git a/test/ambiguous.jl b/test/ambiguous.jl index 53081e36f9819..2b1ad51c8d721 100644 --- a/test/ambiguous.jl +++ b/test/ambiguous.jl @@ -229,9 +229,9 @@ f(x::Complex{<:Rational}) = 2 end @test !Base.isambiguous(methods(Ambig9.f)..., ambiguous_bottom=false) @test Base.isambiguous(methods(Ambig9.f)..., ambiguous_bottom=true) -@test Base.isambiguous(methods(Ambig9.f)...) +@test !Base.isambiguous(methods(Ambig9.f)...) @test length(detect_ambiguities(Ambig9, ambiguous_bottom=false)) == 0 @test length(detect_ambiguities(Ambig9, ambiguous_bottom=true)) == 1 -@test length(detect_ambiguities(Ambig9)) == 1 +@test length(detect_ambiguities(Ambig9)) == 0 nothing # don't return a module from the remote include From 51a54805971ac8b45375b39dc45d85bb32f65035 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 21 Mar 2017 16:03:07 -0400 Subject: [PATCH 0255/1534] fix #21118, subtyping issue with diagonal variable with abstract lower bound In `Tuple{Vararg{T}} where T`, `T` is diagonal. In the case in this issue, type intersection was giving such a variable an abstract lower bound. That was wrong, but it also created a type that could not be subtyped properly since the given bound on the variable contradicted the requirement that it be concrete. So for now at least, given e.g. `Tuple{T,T} where T>:Real`, simply drop the diagonal-concrete rule. --- src/subtype.c | 23 ++++++++++++++++------- test/subtype.jl | 12 ++++++++++++ 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/subtype.c b/src/subtype.c index f4b6290b3764d..dffa3ded7604b 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -423,6 +423,13 @@ static int is_leaf_bound(jl_value_t *v) return !jl_is_type(v) && !jl_is_typevar(v); } +static int is_leaf_typevar(jl_value_t *v) +{ + if (jl_is_typevar(v)) + return is_leaf_typevar(((jl_tvar_t*)v)->lb); + return is_leaf_bound(v); +} + static jl_value_t *widen_Type(jl_value_t *t) { if (jl_is_type_type(t) && !jl_is_typevar(jl_tparam0(t))) @@ -481,6 +488,7 @@ static int subtype_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_t *e, int8 // multiple union members), consider the value unknown. if (!oldval || !jl_is_typevar(oldval) || !jl_is_long(val)) e->envout[e->envidx] = val; + // TODO: substitute the value (if any) of this variable into previous envout entries } } else { @@ -492,7 +500,8 @@ static int subtype_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_t *e, int8 // ( Tuple{Int, Int} <: Tuple{T, T} where T) but // !( Tuple{Int, String} <: Tuple{T, T} where T) // Then check concreteness by checking that the lower bound is not an abstract type. - if (ans && (vb.concrete || (!vb.occurs_inv && vb.occurs_cov > 1))) { + if (ans && (vb.concrete || (!vb.occurs_inv && vb.occurs_cov > 1)) && + is_leaf_typevar((jl_value_t*)u->var)) { if (jl_is_typevar(vb.lb)) { // TODO test case that demonstrates the need for this? /* @@ -1340,14 +1349,14 @@ static jl_value_t *intersect_unionall_(jl_value_t *t, jl_unionall_t *u, jl_stenv else { res = intersect(u->body, t, e, param); } - vb->concrete |= (!vb->occurs_inv && vb->occurs_cov > 1); + vb->concrete |= (!vb->occurs_inv && vb->occurs_cov > 1 && is_leaf_typevar((jl_value_t*)u->var)); // handle the "diagonal dispatch" rule, which says that a type var occurring more // than once, and only in covariant position, is constrained to concrete types. E.g. // ( Tuple{Int, Int} <: Tuple{T, T} where T) but // !( Tuple{Int, String} <: Tuple{T, T} where T) // Then check concreteness by checking that the lower bound is not an abstract type. - if (res != jl_bottom_type && (vb->concrete || (!vb->occurs_inv && vb->occurs_cov > 1))) { + if (res != jl_bottom_type && vb->concrete) { if (jl_is_typevar(vb->lb)) { } else if (!is_leaf_bound(vb->lb)) { @@ -1725,8 +1734,6 @@ static jl_value_t *intersect(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int pa record_var_occurrence(lookup(e, (jl_tvar_t*)y), e, param); return intersect_var((jl_tvar_t*)y, x, e, 1, param); } - if (y == (jl_value_t*)jl_any_type) return x; - if (x == (jl_value_t*)jl_any_type) return y; if (!jl_has_free_typevars(x) && !jl_has_free_typevars(y)) { if (jl_subtype(x, y)) return x; if (jl_subtype(y, x)) return y; @@ -1743,6 +1750,8 @@ static jl_value_t *intersect(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int pa return intersect_unionall(y, (jl_unionall_t*)x, e, 0, param); return intersect_union(x, (jl_uniontype_t*)y, e, 1, param); } + if (y == (jl_value_t*)jl_any_type) return x; + if (x == (jl_value_t*)jl_any_type) return y; if (jl_is_unionall(x)) { if (jl_is_unionall(y)) { jl_value_t *a=NULL, *b=jl_bottom_type, *res=NULL; @@ -1802,11 +1811,11 @@ static jl_value_t *intersect(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int pa if (ii == jl_bottom_type) return jl_bottom_type; if (jl_is_typevar(xp1)) { jl_varbinding_t *xb = lookup(e, (jl_tvar_t*)xp1); - if (xb) xb->concrete = 1; + if (xb && is_leaf_typevar((jl_value_t*)xb->var)) xb->concrete = 1; } if (jl_is_typevar(yp1)) { jl_varbinding_t *yb = lookup(e, (jl_tvar_t*)yp1); - if (yb) yb->concrete = 1; + if (yb && is_leaf_typevar((jl_value_t*)yb->var)) yb->concrete = 1; } JL_GC_PUSH2(&ii, &i2); // Vararg{T,N} <: Vararg{T2,N2}; equate N and N2 diff --git a/test/subtype.jl b/test/subtype.jl index bf4462bbca663..1c9da31f3f987 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -112,6 +112,10 @@ function test_diagonal() @test issub_strict(Tuple{Int, Int}, (@UnionAll T Tuple{Union{T,String}, T})) + + # don't consider a diagonal variable concrete if it already has an abstract lower bound + @test isequal_type(Tuple{Vararg{A}} where A>:Integer, + Tuple{Vararg{A}} where A>:Integer) end # level 3: UnionAll @@ -867,6 +871,14 @@ function test_intersection() I, E = intersection_env(Tuple{Ref{Integer},Int,Any}, Tuple{Ref{Z},Z,Z} where Z) @test isequal_type(I, Tuple{Ref{Integer},Int,Integer}) @test E[1] == Integer + + # issue #21118 + A = Tuple{Ref, Vararg{Any}} + B = Tuple{Vararg{Union{Z,Ref,Void}}} where Z<:Union{Ref,Void} + @test B <: _type_intersect(A, B) + @testintersect(Tuple{Int,Any,Vararg{A}} where A>:Integer, + Tuple{Any,Int,Vararg{A}} where A>:Integer, + Tuple{Int,Int,Vararg{A}} where A>:Integer) end function test_intersection_properties() From 7ce49250a3bc556d238e199abed04961633546fd Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Tue, 21 Mar 2017 20:30:54 -0700 Subject: [PATCH 0256/1534] OSX: Add both RPATH entries to `julia`, don't overwrite See https://github.com/JuliaLang/julia/commit/30ba746f0dfd731d91f554c0e50e92c84c9ff451#commitcomment-21430419 for more details --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9c0b67f6e03f1..7ae826525d65f 100644 --- a/Makefile +++ b/Makefile @@ -401,7 +401,7 @@ ifneq ($(private_libdir_rel),$(build_private_libdir_rel)) ifeq ($(OS), Darwin) for julia in $(DESTDIR)$(bindir)/julia* ; do \ install_name_tool -rpath @executable_path/$(build_private_libdir_rel) @executable_path/$(private_libdir_rel) $$julia; \ - install_name_tool -rpath @executable_path/$(build_libdir_rel) @executable_path/$(libdir_rel) $$julia; \ + install_name_tool -add_rpath @executable_path/$(build_libdir_rel) @executable_path/$(libdir_rel) $$julia; \ done else ifeq ($(OS), Linux) for julia in $(DESTDIR)$(bindir)/julia* ; do \ From decead16d0dc0a11f6cda09045371fa1a9f462ff Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Mon, 20 Mar 2017 12:03:36 -0500 Subject: [PATCH 0257/1534] Add tests for download --- .travis.yml | 2 +- appveyor.yml | 2 +- test/download.jl | 26 ++++++++++++++++++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 test/download.jl diff --git a/.travis.yml b/.travis.yml index 13f60015e5c17..e8445b240c913 100644 --- a/.travis.yml +++ b/.travis.yml @@ -128,7 +128,7 @@ script: - export JULIA_CPU_CORES=2 && export JULIA_TEST_MAXRSS_MB=600 && cd /tmp/julia/share/julia/test && /tmp/julia/bin/julia --check-bounds=yes runtests.jl $TESTSTORUN && - /tmp/julia/bin/julia --check-bounds=yes runtests.jl libgit2-online pkg + /tmp/julia/bin/julia --check-bounds=yes runtests.jl libgit2-online download pkg - cd `dirname $TRAVIS_BUILD_DIR` && mv julia2 julia && rm -f julia/deps/scratch/libgit2-*/CMakeFiles/CMakeOutput.log # uncomment the following if failures are suspected to be due to the out-of-memory killer diff --git a/appveyor.yml b/appveyor.yml index be29747bf7d14..b7bdb2e3e50fc 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -56,4 +56,4 @@ test_script: - usr\bin\julia -e "versioninfo()" - usr\bin\julia --precompiled=no -e "true" - cd test && ..\usr\bin\julia --check-bounds=yes runtests.jl all && - ..\usr\bin\julia --check-bounds=yes runtests.jl libgit2-online pkg + ..\usr\bin\julia --check-bounds=yes runtests.jl libgit2-online download pkg diff --git a/test/download.jl b/test/download.jl new file mode 100644 index 0000000000000..317179f172dbd --- /dev/null +++ b/test/download.jl @@ -0,0 +1,26 @@ +# This file is a part of Julia. License is MIT: http://julialang.org/license + +mktempdir() do temp_dir + # Download a file + file = joinpath(temp_dir, "ip") + @test download("http://httpbin.org/ip", file) == file + @test isfile(file) + @test !isempty(read(file)) + + # Download an empty file + empty_file = joinpath(temp_dir, "empty") + @test download("http://httpbin.org/status/200", empty_file) == empty_file + + # Windows and older versions of curl do not create the empty file (https://github.com/curl/curl/issues/183) + @test !isfile(empty_file) || isempty(read(empty_file)) + + # Make sure that failed downloads do not leave files around + missing_file = joinpath(temp_dir, "missing") + @test_throws ErrorException download("http://httpbin.org/status/404", missing_file) + @test !isfile(missing_file) + + # Use a TEST-NET (192.0.2.0/24) address which shouldn't be bound + invalid_host_file = joinpath(temp_dir, "invalid_host") + @test_throws ErrorException download("http://192.0.2.1", invalid_host_file) + @test !isfile(invalid_host_file) +end From 9713576e28ddaea882e4fabd8a0dc643b3d9b22c Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 22 Mar 2017 14:25:55 -0400 Subject: [PATCH 0258/1534] fix #21132, intersection hang due to x == Pair{x} constraint --- src/subtype.c | 39 ++++++++++++++++++++++++++++++--------- test/subtype.jl | 5 +++++ 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/subtype.c b/src/subtype.c index dffa3ded7604b..7039be27a5dd3 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -1133,6 +1133,8 @@ static int try_subtype_in_env(jl_value_t *a, jl_value_t *b, jl_stenv_t *e) return ret; } +static int var_occurs_inside(jl_value_t *v, jl_tvar_t *var, int inside, int want_inv); + static jl_value_t *intersect_var(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int8_t R, int param) { jl_varbinding_t *bb = lookup(e, b); @@ -1152,6 +1154,22 @@ static jl_value_t *intersect_var(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int return jl_bottom_type; } if (ub != (jl_value_t*)b) { + if (jl_has_free_typevars(ub)) { + // constraint X == Ref{X} is unsatisfiable. also check variables set equal to X. + if (var_occurs_inside(ub, b, 0, 0)) { + JL_GC_POP(); + return jl_bottom_type; + } + jl_varbinding_t *btemp = e->vars; + while (btemp != NULL) { + if (btemp->lb == (jl_value_t*)b && btemp->ub == (jl_value_t*)b && + var_occurs_inside(ub, btemp->var, 0, 0)) { + JL_GC_POP(); + return jl_bottom_type; + } + btemp = btemp->prev; + } + } bb->ub = ub; bb->lb = ub; } @@ -1216,28 +1234,31 @@ static jl_value_t *intersect_var(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int return ii; } -static int var_occurs_invariant(jl_value_t *v, jl_tvar_t *var, int inv) +// test whether `var` occurs inside constructors. `want_inv` tests only inside +// invariant constructors. `inside` means we are currently inside a constructor of the +// requested kind. +static int var_occurs_inside(jl_value_t *v, jl_tvar_t *var, int inside, int want_inv) { if (v == (jl_value_t*)var) { - return inv; + return inside; } else if (jl_is_uniontype(v)) { - return var_occurs_invariant(((jl_uniontype_t*)v)->a, var, inv) || - var_occurs_invariant(((jl_uniontype_t*)v)->b, var, inv); + return var_occurs_inside(((jl_uniontype_t*)v)->a, var, inside, want_inv) || + var_occurs_inside(((jl_uniontype_t*)v)->b, var, inside, want_inv); } else if (jl_is_unionall(v)) { jl_unionall_t *ua = (jl_unionall_t*)v; if (ua->var == var) return 0; - if (var_occurs_invariant(ua->var->lb, var, inv) || var_occurs_invariant(ua->var->ub, var, inv)) + if (var_occurs_inside(ua->var->lb, var, inside, want_inv) || var_occurs_inside(ua->var->ub, var, inside, want_inv)) return 1; - return var_occurs_invariant(ua->body, var, inv); + return var_occurs_inside(ua->body, var, inside, want_inv); } else if (jl_is_datatype(v)) { size_t i; - int invar = inv || !jl_is_tuple_type(v); + int ins = inside || !want_inv || !jl_is_tuple_type(v); for (i=0; i < jl_nparams(v); i++) { - if (var_occurs_invariant(jl_tparam(v,i), var, invar)) + if (var_occurs_inside(jl_tparam(v,i), var, ins, want_inv)) return 1; } } @@ -1254,7 +1275,7 @@ static jl_value_t *finish_unionall(jl_value_t *res, jl_varbinding_t *vb, jl_sten // given x<:T<:x, substitute x for T varval = vb->ub; } - else if (!var_occurs_invariant(res, vb->var, 0) && is_leaf_bound(vb->ub)) { + else if (!var_occurs_inside(res, vb->var, 0, 1) && is_leaf_bound(vb->ub)) { // replace T<:x with x in covariant position when possible varval = vb->ub; } diff --git a/test/subtype.jl b/test/subtype.jl index 1c9da31f3f987..bd209e66d33da 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -879,6 +879,11 @@ function test_intersection() @testintersect(Tuple{Int,Any,Vararg{A}} where A>:Integer, Tuple{Any,Int,Vararg{A}} where A>:Integer, Tuple{Int,Int,Vararg{A}} where A>:Integer) + + # issue #21132 + @testintersect(Pair{L,Tuple{L,Pair{L,HL}}} where {L,HL}, + Pair{R,Tuple{Pair{R,HR},R}} where {R,HR}, + Bottom) # X == Pair{X,...} is not satisfiable end function test_intersection_properties() From 3d126b8c06121d266ba86236b226429de66513e7 Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Wed, 22 Mar 2017 15:56:24 -0400 Subject: [PATCH 0259/1534] Fix stride for vectors in BLAS.ger! and BLAS.trsv! (#21125) Fixes #21122 --- base/linalg/blas.jl | 4 ++-- test/blas.jl | 13 +++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/base/linalg/blas.jl b/base/linalg/blas.jl index d31d415f88291..8b52ffffa3595 100644 --- a/base/linalg/blas.jl +++ b/base/linalg/blas.jl @@ -891,7 +891,7 @@ for (fname, elty) in ((:dtrsv_,:Float64), (Ptr{UInt8}, Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}), &uplo, &trans, &diag, &n, - A, &max(1,stride(A,2)), x, &1) + A, &max(1,stride(A,2)), x, &stride(x, 1)) x end function trsv(uplo::Char, trans::Char, diag::Char, A::StridedMatrix{$elty}, x::StridedVector{$elty}) @@ -924,7 +924,7 @@ for (fname, elty) in ((:dger_,:Float64), Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}), &m, &n, &α, x, - &1, y, &1, A, + &stride(x, 1), y, &stride(y, 1), A, &max(1,stride(A,2))) A end diff --git a/test/blas.jl b/test/blas.jl index 5d07b89309890..780b62dab46fc 100644 --- a/test/blas.jl +++ b/test/blas.jl @@ -116,15 +116,16 @@ srand(100) @testset "trsv" begin A = triu(rand(elty,n,n)) - x = rand(elty,n) - @test A\x ≈ BLAS.trsv('U','N','N',A,x) - @test_throws DimensionMismatch BLAS.trsv('U','N','N',A,ones(elty,n+1)) + @testset "Vector and SubVector" for x in (rand(elty, n), view(rand(elty,2n),1:2:2n)) + @test A\x ≈ BLAS.trsv('U','N','N',A,x) + @test_throws DimensionMismatch BLAS.trsv('U','N','N',A,ones(elty,n+1)) + end end - @testset "ger, her, syr" begin + @testset "ger, her, syr" for x in (rand(elty, n), view(rand(elty,2n), 1:2:2n)), + y in (rand(elty,n), view(rand(elty,3n), 1:3:3n)) + A = rand(elty,n,n) α = rand(elty) - x = rand(elty,n) - y = rand(elty,n) @test BLAS.ger!(α,x,y,copy(A)) ≈ A + α*x*y' @test_throws DimensionMismatch BLAS.ger!(α,ones(elty,n+1),y,copy(A)) From ddaf4a60032cf2186c33f177a1ca27bd73e74e9a Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 21 Mar 2017 17:47:08 -0400 Subject: [PATCH 0260/1534] add devdocs on "diagonal" types [ci skip] --- doc/src/devdocs/types.md | 142 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 139 insertions(+), 3 deletions(-) diff --git a/doc/src/devdocs/types.md b/doc/src/devdocs/types.md index 2b86fb6becdcf..93a5c914c55cd 100644 --- a/doc/src/devdocs/types.md +++ b/doc/src/devdocs/types.md @@ -73,12 +73,12 @@ type, we could write `Array{T,2} where T`, which is the union of `Array{T,2}` fo Such a type is represented by a `UnionAll` object, which contains a variable (`T` in this example, of type `TypeVar`), and a wrapped type (`Array{T,2}` in this example). -Consider the following methods:: +Consider the following methods: ```julia f1(A::Array) = 1 f2(A::Array{Int}) = 2 -f3(A::Array{T}) where T<:Any = 3 +f3(A::Array{T}) where {T<:Any} = 3 f4(A::Array{Any}) = 4 ``` @@ -315,7 +315,143 @@ Ptr{Void} @0x00007f5998a04370 so `Tuple == Tuple{Vararg{Any}}` is indeed the primary type. -## Introduction to the internal machinery: `jltypes.c` +## Diagonal types + +Consider the type `Tuple{T,T} where T`. +A method with this signature would look like: + +```julia +f(x::T, y::T) where {T} = ... +``` + +According to the usual interpretation of a `UnionAll` type, this `T` ranges over all +types, including `Any`, so this type should be equivalent to `Tuple{Any,Any}`. +However, this interpretation causes some practical problems. + +First, a value of `T` needs to be available inside the method definition. +For a call like `f(1, 1.0)`, it's not clear what `T` should be. +It could be `Union{Int,Float64}`, or perhaps `Real`. +Intuitively, we expect the declaration `x::T` to mean `T === typeof(x)`. +To make sure that invariant holds, we need `typeof(x) === typeof(y) === T` in this method. +That implies the method should only be called for arguments of the exact same type. + +It turns out that being able to dispatch on whether two values have the same type +is very useful (this is used by the promotion system for example), so we have +multiple reasons to want a different interpretation of `Tuple{T,T} where T`. +To make this work we add the following rule to subtyping: if a variable occurs +more than once in covariant position, it is restricted to ranging over only concrete +types. +("Covariant position" means that only `Tuple` and `Union` types occur between an +occurrence of a variable and the `UnionAll` type that introduces it.) +Such variables are called "diagonal variables" or "concrete variables". + +So for example, `Tuple{T,T} where T` can be seen as +`Union{Tuple{Int8,Int8}, Tuple{Int16,Int16}, ...}`, where `T` ranges over all +concrete types. +This gives rise to some interesting subtyping results. +For example `Tuple{Real,Real}` is not a subtype of `Tuple{T,T} where T`, because +it includes some types like `Tuple{Int8,Int16}` where the two elements have +different types. +`Tuple{Real,Real}` and `Tuple{T,T} where T` have the non-trivial intersection +`Tuple{T,T} where T<:Real`. +However, `Tuple{Real}` *is* a subtype of `Tuple{T} where T`, because in that case +`T` occurs only once and so is not diagonal. + +Next consider a signature like the following: + +```julia +f(a::Array{T}, x::T, y::T) where {T} = ... +``` + +In this case, `T` occurs in invariant position inside `Array{T}`. +That means whatever type of array is passed unambiguously determines +the value of `T` --- we say `T` has an *equality constraint* on it. +Therefore in this case the diagonal rule is not really necessary, since +the array determines `T` and we can then allow `x` and `y` to be of +any subtypes of `T`. +So variables that occur in invariant position are never considered diagonal. +This choice of behavior is slightly controversial --- some feel this definition +should be written as + +```julia +f(a::Array{T}, x::S, y::S) where {T, S<:T} = ... +``` + +to clarify whether `x` and `y` need to have the same type. +In this version of the signature they would, or we could introduce a third variable for +the type of `y` if `x` and `y` can have different types. + +The next complication is the interaction of unions and diagonal variables, e.g. + +```julia +f(x::Union{Void,T}, y::T) where {T} = ... +``` + +Consider what this declaration means. +`y` has type `T`. `x` then can have either the same type `T`, or else be of type `Void`. +So all of the following calls should match: + +```julia +f(1, 1) +f("", "") +f(2.0, 2.0) +f(nothing, 1) +f(nothing, "") +f(nothing, 2.0) +``` + +These examples are telling us something: when `x` is `nothing::Void`, there are no +extra constraints on `y`. +It is as if the method signature had `y::Any`. +This means that whether a variable is diagonal is not a static property based on +where it appears in a type. +Rather, it depends on where a variable appears when the subtyping algorithm *uses* it. +When `x` has type `Void`, we don't need to use the `T` in `Union{Void,T}`, so `T` +does not "occur". +Indeed, we have the following type equivalence: + +```julia +(Tuple{Union{Void,T},T} where T) == Union{Tuple{Void,Any}, Tuple{T,T} where T} +``` + +## Subtyping diagonal variables + +The subtyping algorithm for diagonal variables has two components: +(1) identifying variable occurrences, and (2) ensuring that diagonal +variables range over concrete types only. + +The first task is accomplished by keeping counters `occurs_inv` and `occurs_cov` +(in `src/subtype.c`) for each variable in the environment, tracking the number +of invariant and covariant occurrences, respectively. +A variable is diagonal when `occurs_inv == 0 && occurs_cov > 1`. + +The second task is accomplished by imposing a condition on a variable's lower bound. +As the subtyping algorithm runs, it narrows the bounds of each variable +(raising lower bounds and lowering upper bounds) to keep track of the +range of variable values for which the subtype relation would hold. +When we are done evaluating the body of a `UnionAll` type whose variable is diagonal, +we look at the final values of the bounds. +Since the variable must be concrete, a contradiction occurs if its lower bound +could not be a subtype of a concrete type. +For example, an abstract type like `AbstractArray` cannot be a subtype of a concrete +type, but a concrete type like `Int` can be, and the empty type `Bottom` can be as well. +If a lower bound fails this test the algorithm stops with the answer `false`. + +For example, in the problem `Tuple{Int,String} <: Tuple{T,T} where T`, we derive that +this would be true if `T` were a supertype of `Union{Int,String}`. +However, `Union{Int,String}` is an abstract type, so the relation does not hold. + +This concreteness test is done by the function `is_leaf_bound`. +Note that this test is slightly different from `jl_is_leaf_type`, since it also returns +`true` for `Bottom`. +Currently this function is heuristic, and does not catch all possible concrete types. +The difficulty is that whether a lower bound is concrete might depend on the values +of other type variable bounds. +For example, `Vector{T}` is equivalent to the concrete type `Vector{Int}` only if +both the upper and lower bounds of `T` equal `Int`. +We have not yet worked out a complete algorithm for this. + +## Introduction to the internal machinery Most operations for dealing with types are found in the files `jltypes.c` and `subtype.c`. A good way to start is to watch subtyping in action. From 8e7404f80ec30b4b2f7291f26f9857946b621623 Mon Sep 17 00:00:00 2001 From: Iblis Lin Date: Thu, 23 Mar 2017 15:38:23 +0800 Subject: [PATCH 0261/1534] test/socket: wait_with_timeout to provide more debugging info --- test/socket.jl | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/test/socket.jl b/test/socket.jl index fc55c0f82cb35..70bc4a03c505e 100644 --- a/test/socket.jl +++ b/test/socket.jl @@ -253,16 +253,27 @@ let bind(s, ip"0.0.0.0", 2000, reuseaddr = true, enable_broadcast = true) s end + + function wait_with_timeout(recvs) + TIMEOUT_VAL = 3 # seconds + t0 = time() + recvs_check = copy(recvs) + while ((length(filter!(t->!istaskdone(t), recvs_check)) > 0) + && (time() - t0 < TIMEOUT_VAL)) + sleep(0.05) + end + length(recvs_check) > 0 && error("timeout") + map(wait, recvs) + end + a, b, c = [create_socket() for i = 1:3] try # bsd family do not allow broadcasting to ip"255.255.255.255" # or ip"127.255.255.255" @static if !is_bsd() || is_apple() - @sync begin - send(c, bcastdst, 2000, "hello") - recvs = [@async @test String(recv(s)) == "hello" for s in (a, b)] - map(wait, recvs) - end + send(c, bcastdst, 2000, "hello") + recvs = [@async @test String(recv(s)) == "hello" for s in (a, b)] + wait_with_timeout(recvs) end catch e if isa(e, Base.UVError) && Base.uverrorname(e) == "EPERM" From 2a5b3d8fd717d2276ecae7ea832ab62b2758fb6e Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Thu, 23 Mar 2017 06:13:15 -0700 Subject: [PATCH 0262/1534] Immediately expand JULIAHOME in Makefile (#21140) --- examples/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Makefile b/examples/Makefile index 66d7210adfc91..8f9ba2b87bc73 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -1,4 +1,4 @@ -JULIAHOME = $(abspath ..) +JULIAHOME := $(abspath ..) include $(JULIAHOME)/Make.inc FLAGS = -Wall -Wno-strict-aliasing -fno-omit-frame-pointer \ From 0889cdfabd747dddb65f6cee0e3041aca6e8699f Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 23 Mar 2017 12:13:55 -0400 Subject: [PATCH 0263/1534] fix whitelist of expression heads in `lambda-optimize-vars!` `decl` and `ssavalue` were omitted by mistake. This helps #15276. --- src/julia-syntax.scm | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index da8af6d56f48d..ea639e5e21c80 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -2895,21 +2895,21 @@ f(x) = yt(x) (lambda (e) (or (atom? e) (memq (car e) '(quote top core line inert local local-def unnecessary - meta inbounds boundscheck simdloop + meta inbounds boundscheck simdloop decl implicit-global global globalref outerref - const = null method call)))) + const = null method call ssavalue)))) (lam:body lam)))) (unused (map cadr (filter (lambda (x) (memq (car x) '(method =))) leading)))) - ;; TODO: reorder leading statements to put assignments where the RHS is - ;; `simple-atom?` at the top. - (for-each (lambda (e) - (set! unused (filter (lambda (v) (not (expr-uses-var e v))) - unused)) - (if (and (memq (car e) '(method =)) (memq (cadr e) unused)) - (let ((v (assq (cadr e) vi))) - (if v (vinfo:set-never-undef! v #t))))) - leading))) + ;; TODO: reorder leading statements to put assignments where the RHS is + ;; `simple-atom?` at the top. + (for-each (lambda (e) + (set! unused (filter (lambda (v) (not (expr-uses-var e v))) + unused)) + (if (and (memq (car e) '(method =)) (memq (cadr e) unused)) + (let ((v (assq (cadr e) vi))) + (if v (vinfo:set-never-undef! v #t))))) + leading))) (for-each (lambda (v) (if (and (vinfo:sa v) (vinfo:never-undef v)) (set-car! (cddr v) (logand (caddr v) (lognot 5))))) From e2f5701b5d893c1a2a972b76e8abd4d21960d04b Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 6 Mar 2017 01:23:30 -0500 Subject: [PATCH 0264/1534] compress AST in memory, not just on disk sysimg size will be exactly the same, but seems to be pretty significant savings in memory and initial GC time (about 10% on each) --- base/inference.jl | 58 +++++------ base/methodshow.jl | 18 ++-- base/reflection.jl | 12 +-- base/serialize.jl | 1 + base/show.jl | 16 ++-- doc/src/devdocs/ast.md | 6 +- doc/src/devdocs/debuggingtips.md | 2 +- src/codegen.cpp | 54 +++++++---- src/dump.c | 160 ++++++++++++++++++++++++++----- src/interpreter.c | 20 ++-- src/jltypes.c | 10 +- src/julia.h | 15 ++- src/julia_internal.h | 9 +- src/method.c | 23 +++-- test/inference.jl | 10 +- 15 files changed, 269 insertions(+), 145 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 98715619f38ae..4c05e9f6e4f32 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -278,23 +278,19 @@ end # create copies of the CodeInfo definition, and any fields that type-inference might modify # TODO: post-inference see if we can swap back to the original arrays function get_source(li::MethodInstance) - src = ccall(:jl_copy_code_info, Ref{CodeInfo}, (Any,), li.def.source) - if isa(src.code, Array{UInt8,1}) - src.code = ccall(:jl_uncompress_ast, Any, (Any, Any), li.def, src.code) + if isa(li.def.source, Array{UInt8,1}) + src = ccall(:jl_uncompress_ast, Any, (Any, Any), li.def, li.def.source) else + src = ccall(:jl_copy_code_info, Ref{CodeInfo}, (Any,), li.def.source) src.code = copy_exprargs(src.code) + src.slotnames = copy(src.slotnames) + src.slotflags = copy(src.slotflags) end - src.slotnames = copy(src.slotnames) - src.slotflags = copy(src.slotflags) return src end function get_staged(li::MethodInstance) - src = ccall(:jl_code_for_staged, Any, (Any,), li)::CodeInfo - if isa(src.code, Array{UInt8,1}) - src.code = ccall(:jl_uncompress_ast, Any, (Any, Any), li.def, src.code) - end - return src + return ccall(:jl_code_for_staged, Any, (Any,), li)::CodeInfo end @@ -1579,7 +1575,7 @@ function pure_eval_call(f::ANY, argtypes::ANY, atype::ANY, sv::InferenceState) meth = meth[1]::SimpleVector method = meth[3]::Method # TODO: check pure on the inferred thunk - if method.isstaged || !method.source.pure + if method.isstaged || !method.pure return false end @@ -3027,7 +3023,7 @@ function finish(me::InferenceState) end if me.const_api # use constant calling convention - inferred_result = inferred_const + inferred_result = nothing else inferred_result = me.src end @@ -3040,7 +3036,7 @@ function finish(me::InferenceState) inferred_result = nothing else # compress code for non-toplevel thunks - inferred_result.code = ccall(:jl_compress_ast, Any, (Any, Any), me.linfo.def, inferred_result.code) + inferred_result = ccall(:jl_compress_ast, Any, (Any, Any), me.linfo.def, inferred_result) end end end @@ -3827,10 +3823,10 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference if f === return_type if isconstType(e.typ) return inline_as_constant(e.typ.parameters[1], argexprs, sv, invoke_data) - elseif isa(e.typ,Const) + elseif isa(e.typ, Const) return inline_as_constant(e.typ.val, argexprs, sv, invoke_data) end - elseif method.source.pure && isa(e.typ,Const) && e.typ.actual + elseif method.pure && isa(e.typ, Const) && e.typ.actual return inline_as_constant(e.typ.val, argexprs, sv, invoke_data) end end @@ -3889,14 +3885,14 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference if linfo.jlcall_api == 2 # in this case function can be inlined to a constant add_backedge(linfo, sv) - return inline_as_constant(linfo.inferred, argexprs, sv, invoke_data) + return inline_as_constant(linfo.inferred_const, argexprs, sv, invoke_data) end # see if the method has a current InferenceState frame # or existing inferred code info frame = nothing # Union{Void, InferenceState} - src = nothing # Union{Void, CodeInfo} - if force_infer && la>2 && isa(atypes[3], Const) + inferred = nothing # Union{Void, CodeInfo} + if force_infer && la > 2 && isa(atypes[3], Const) # Since we inferred this with the information that atypes[3]::Const, # must inline with that same information. # We do that by overriding the argument type, @@ -3909,9 +3905,9 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference frame.stmt_types[1][3] = VarState(atypes[3], false) typeinf_loop(frame) else - if isdefined(linfo, :inferred) && isa(linfo.inferred, CodeInfo) && (linfo.inferred::CodeInfo).inferred + if isdefined(linfo, :inferred) && linfo.inferred !== nothing # use cache - src = linfo.inferred + inferred = linfo.inferred elseif linfo.inInference # use WIP frame = typeinf_active(linfo) @@ -3928,7 +3924,7 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference if isa(frame, InferenceState) frame = frame::InferenceState linfo = frame.linfo - src = frame.src + inferred = frame.src if frame.const_api # handle like jlcall_api == 2 if frame.inferred || !frame.cached add_backedge(frame.linfo, sv) @@ -3949,19 +3945,23 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference end # check that the code is inlineable - isa(src, CodeInfo) || return invoke_NF(argexprs0, e.typ, atypes, sv, - atype_unlimited, invoke_data) - src = src::CodeInfo - ast = src.code - if !src.inferred || !src.inlineable + if inferred === nothing + src_inferred = src_inlineable = false + else + src_inferred = ccall(:jl_ast_flag_inferred, Bool, (Any,), inferred) + src_inlineable = ccall(:jl_ast_flag_inlineable, Bool, (Any,), inferred) + end + if !src_inferred || !src_inlineable return invoke_NF(argexprs0, e.typ, atypes, sv, atype_unlimited, invoke_data) end - if !isa(ast, Array{Any,1}) - ast = ccall(:jl_uncompress_ast, Any, (Any, Any), method, ast) + if isa(inferred, CodeInfo) + src = inferred + ast = copy_exprargs(inferred.code) else - ast = copy_exprargs(ast) + src = ccall(:jl_uncompress_ast, Any, (Any, Any), method, inferred)::CodeInfo + ast = src.code end ast = ast::Array{Any,1} diff --git a/base/methodshow.jl b/base/methodshow.jl index 95623a477b542..8ae16639561a6 100644 --- a/base/methodshow.jl +++ b/base/methodshow.jl @@ -49,15 +49,11 @@ function arg_decl_parts(m::Method) push!(tv, sig.var) sig = sig.body end - if isdefined(m, :source) - src = m.source - else - src = nothing - end file = m.file line = m.line - if src !== nothing && src.slotnames !== nothing - argnames = src.slotnames[1:m.nargs] + if isdefined(m, :source) + argnames = Vector{Any}(m.nargs) + ccall(:jl_fill_argnames, Void, (Any, Any), m.source, argnames) show_env = ImmutableDict{Symbol, Any}() for t in tv show_env = ImmutableDict(show_env, :unionall_env => t) @@ -75,14 +71,14 @@ function kwarg_decl(m::Method, kwtype::DataType) kwli = ccall(:jl_methtable_lookup, Any, (Any, Any, UInt), kwtype.name.mt, sig, max_world(m)) if kwli !== nothing kwli = kwli::Method - src = kwli.source - kws = filter(x->!('#' in string(x)), src.slotnames[kwli.nargs+1:end]) + src = uncompressed_ast(kwli, kwli.source) + kws = filter(x -> !('#' in string(x)), src.slotnames[(kwli.nargs + 1):end]) # ensure the kwarg... is always printed last. The order of the arguments are not # necessarily the same as defined in the function i = findfirst(x -> endswith(string(x), "..."), kws) - i==0 && return kws + i == 0 && return kws push!(kws, kws[i]) - return deleteat!(kws,i) + return deleteat!(kws, i) end return () end diff --git a/base/reflection.jl b/base/reflection.jl index d0a36396c04bb..44fad1bd4601c 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -483,8 +483,7 @@ Returns an array of lowered ASTs for the methods matching the given generic func """ function code_lowered(f::ANY, t::ANY=Tuple) asts = map(methods(f, t)) do m - m = m::Method - return uncompressed_ast(m, m.source) + return uncompressed_ast(m::Method) end return asts end @@ -641,13 +640,8 @@ end isempty(mt::MethodTable) = (mt.defs === nothing) uncompressed_ast(m::Method) = uncompressed_ast(m, m.source) -function uncompressed_ast(m::Method, s::CodeInfo) - if isa(s.code, Array{UInt8,1}) - s = ccall(:jl_copy_code_info, Ref{CodeInfo}, (Any,), s) - s.code = ccall(:jl_uncompress_ast, Array{Any,1}, (Any, Any), m, s.code) - end - return s -end +uncompressed_ast(m::Method, s::CodeInfo) = s +uncompressed_ast(m::Method, s::Array{UInt8,1}) = ccall(:jl_uncompress_ast, Any, (Any, Any), m, s)::CodeInfo # this type mirrors jl_cghooks_t (documented in julia.h) struct CodegenHooks diff --git a/base/serialize.jl b/base/serialize.jl index b6008df568ccc..6fe0fa731d835 100644 --- a/base/serialize.jl +++ b/base/serialize.jl @@ -650,6 +650,7 @@ function deserialize(s::AbstractSerializer, ::Type{Method}) meth.isva = isva # TODO: compress template meth.source = template + meth.pure = template.pure if isstaged linfo = ccall(:jl_new_method_instance_uninit, Ref{Core.MethodInstance}, ()) linfo.specTypes = Tuple diff --git a/base/show.jl b/base/show.jl index 340da4bd02c4e..b6bac9a6f5694 100644 --- a/base/show.jl +++ b/base/show.jl @@ -323,17 +323,13 @@ end function show(io::IO, src::CodeInfo) # Fix slot names and types in function body print(io, "CodeInfo(") - if isa(src.code, Array{Any,1}) - lambda_io = IOContext(io, :SOURCEINFO => src) - if src.slotnames !== nothing - lambda_io = IOContext(lambda_io, :SOURCE_SLOTNAMES => sourceinfo_slotnames(src)) - end - body = Expr(:body) - body.args = src.code - show(lambda_io, body) - else - print(io, "") + lambda_io = IOContext(io, :SOURCEINFO => src) + if src.slotnames !== nothing + lambda_io = IOContext(lambda_io, :SOURCE_SLOTNAMES => sourceinfo_slotnames(src)) end + body = Expr(:body) + body.args = src.code + show(lambda_io, body) print(io, ")") end diff --git a/doc/src/devdocs/ast.md b/doc/src/devdocs/ast.md index bacb91e1bd0e3..f5f0c39770096 100644 --- a/doc/src/devdocs/ast.md +++ b/doc/src/devdocs/ast.md @@ -214,14 +214,14 @@ A unique'd container describing the shared metadata for a single method. * `source` - The original source code (compressed). + The original source code (usually compressed). * `roots` Pointers to non-AST things that have been interpolated into the AST, required by compression of the AST, type-inference, or the generation of native code. - * `nargs`, `isva`, `called`, `isstaged` + * `nargs`, `isva`, `called`, `isstaged`, `pure` Descriptive bit-fields for the source code of this Method. @@ -288,7 +288,7 @@ A temporary container for holding lowered source code. * `code` - An `Any` array of statements, or a `UInt8` array with a compressed representation of the code. + An `Any` array of statements * `slotnames` diff --git a/doc/src/devdocs/debuggingtips.md b/doc/src/devdocs/debuggingtips.md index ba87f03c2a642..2cdddf58b6bc3 100644 --- a/doc/src/devdocs/debuggingtips.md +++ b/doc/src/devdocs/debuggingtips.md @@ -29,7 +29,7 @@ While the addresses of many variables, like singletons, can be be useful to prin there are a number of additional variables (see julia.h for a complete list) that are even more useful. - * (when in `jl_apply_generic`) `f->linfo` and `jl_uncompress_ast(f->linfo, f->linfo->ast)` :: for + * (when in `jl_apply_generic`) `mfunc` and `jl_uncompress_ast(mfunc->def, mfunc->code)` :: for figuring out a bit about the call-stack * `jl_lineno` and `jl_filename` :: for figuring out what line in a test to go start debugging from (or figure out how far into a file has been parsed) diff --git a/src/codegen.cpp b/src/codegen.cpp index b4f33810c93db..eef9359502789 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1145,6 +1145,8 @@ jl_llvm_functions_t jl_compile_linfo(jl_method_instance_t **pli, jl_code_info_t // we waited at the lock). if (li->def == NULL) { src = (jl_code_info_t*)li->inferred; + if (src && (jl_value_t*)src != jl_nothing) + src = jl_uncompress_ast(li->def, (jl_array_t*)src); if (decls.functionObject != NULL || !src || !jl_is_code_info(src) || li->jlcall_api == 2) { goto locked_out; } @@ -1159,6 +1161,8 @@ jl_llvm_functions_t jl_compile_linfo(jl_method_instance_t **pli, jl_code_info_t // see if it is inferred src = (jl_code_info_t*)li->inferred; if (src) { + if ((jl_value_t*)src != jl_nothing) + src = jl_uncompress_ast(li->def, (jl_array_t*)src); if (!jl_is_code_info(src)) { src = jl_type_infer(pli, world, 0); li = *pli; @@ -1176,6 +1180,10 @@ jl_llvm_functions_t jl_compile_linfo(jl_method_instance_t **pli, jl_code_info_t // decl (unless compile fails), even if jlcall_api == 2 goto locked_out; } + else { + if ((jl_value_t*)src != jl_nothing) + src = jl_uncompress_ast(li->def, (jl_array_t*)src); + } assert(jl_is_code_info(src)); // Step 2: setup global state @@ -1241,14 +1249,25 @@ jl_llvm_functions_t jl_compile_linfo(jl_method_instance_t **pli, jl_code_info_t jl_finalize_module(m.release(), !toplevel); } - if (world && li->jlcall_api != 2) { - // if not inlineable, code won't be needed again - if (JL_DELETE_NON_INLINEABLE && jl_options.debug_level <= 1 && - li->def && li->inferred && jl_is_code_info(li->inferred) && - !((jl_code_info_t*)li->inferred)->inlineable && - li != li->def->unspecialized && !imaging_mode) { - li->inferred = jl_nothing; - } + // if not inlineable, code won't be needed again + if (JL_DELETE_NON_INLINEABLE && + // don't delete code when debugging level >= 2 + jl_options.debug_level <= 1 && + // don't delete toplevel code + li->def && + // don't change inferred state + li->inferred && + // and there is something to delete (test this before calling jl_ast_flag_inlineable) + li->inferred != jl_nothing && + // don't delete the code for the generator + li != li->def->generator && + // don't delete inlineable code, unless it is constant + (li->jlcall_api == 2 || !jl_ast_flag_inlineable((jl_array_t*)li->inferred)) && + // don't delete code when generating a precompile file + !imaging_mode && + // don't delete code when it's not actually directly being used + world) { + li->inferred = jl_nothing; } // Step 6: Done compiling: Restore global state @@ -1413,7 +1432,7 @@ jl_generic_fptr_t jl_generate_fptr(jl_method_instance_t *li, void *_F, size_t wo // and return its fptr instead if (!unspec) unspec = jl_get_unspecialized(li); // get-or-create the unspecialized version to cache the result - jl_code_info_t *src = unspec->def->isstaged ? jl_code_for_staged(unspec) : unspec->def->source; + jl_code_info_t *src = unspec->def->isstaged ? jl_code_for_staged(unspec) : (jl_code_info_t*)unspec->def->source; fptr.fptr = unspec->fptr; fptr.jlcall_api = unspec->jlcall_api; if (fptr.fptr && fptr.jlcall_api) { @@ -1547,11 +1566,14 @@ void *jl_get_llvmf_defn(jl_method_instance_t *linfo, size_t world, bool getwrapp jl_code_info_t *src = (jl_code_info_t*)linfo->inferred; JL_GC_PUSH1(&src); - if (!src || !jl_is_code_info(src)) { + if (!src || (jl_value_t*)src == jl_nothing) { src = jl_type_infer(&linfo, world, 0); if (!src) - src = linfo->def->isstaged ? jl_code_for_staged(linfo) : linfo->def->source; + src = linfo->def->isstaged ? jl_code_for_staged(linfo) : (jl_code_info_t*)linfo->def->source; } + if (!src || (jl_value_t*)src == jl_nothing) + jl_error("source not found for function"); + src = jl_uncompress_ast(linfo->def, (jl_array_t*)src); // Backup the info for the nested compile JL_LOCK(&codegen_lock); @@ -1634,7 +1656,7 @@ void *jl_get_llvmf_decl(jl_method_instance_t *linfo, size_t world, bool getwrapp jl_code_info_t *src = NULL; src = jl_type_infer(&linfo, world, 0); if (!src) { - src = linfo->def->isstaged ? jl_code_for_staged(linfo) : linfo->def->source; + src = linfo->def->isstaged ? jl_code_for_staged(linfo) : (jl_code_info_t*)linfo->def->source; } decls = jl_compile_linfo(&linfo, src, world, ¶ms); linfo->functionObjectsDecls = decls; @@ -3287,8 +3309,8 @@ static jl_cgval_t emit_invoke(jl_expr_t *ex, jl_codectx_t *ctx) assert(jl_is_method_instance(li)); jl_llvm_functions_t decls = jl_compile_linfo(&li, NULL, ctx->world, ctx->params); if (li->jlcall_api == 2) { - assert(li->inferred); - return mark_julia_const(li->inferred); + assert(li->inferred_const); + return mark_julia_const(li->inferred_const); } if (decls.functionObject) { int jlcall_api = jl_jlcall_api(decls.functionObject); @@ -4468,7 +4490,7 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t Function *gf_thunk = NULL; if (specsig) { if (lam->jlcall_api == 2) { - retval = mark_julia_const(lam->inferred); + retval = mark_julia_const(lam->inferred_const); } else { assert(theFptr); @@ -5032,8 +5054,6 @@ static std::unique_ptr emit_function( jl_codectx_t ctx = {}; JL_GC_PUSH2(&ctx.code, &ctx.roots); ctx.code = (jl_array_t*)src->code; - if (!jl_typeis(ctx.code, jl_array_any_type)) - ctx.code = jl_uncompress_ast(lam->def, ctx.code); //jl_static_show(JL_STDOUT, (jl_value_t*)ast); //jl_printf(JL_STDOUT, "\n"); diff --git a/src/dump.c b/src/dump.c index dc9a97ed7961f..9da66acb95e84 100644 --- a/src/dump.c +++ b/src/dump.c @@ -199,8 +199,8 @@ static void write_float64(ios_t *s, double x) // --- Static Compile --- -#define jl_serialize_value(s, v) jl_serialize_value_(s,(jl_value_t*)(v)) -static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v); +#define jl_serialize_value(s, v) jl_serialize_value_((s), (jl_value_t*)(v), 0) +static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_literal); static jl_value_t *jl_deserialize_value(jl_serializer_state *s, jl_value_t **loc); static jl_value_t ***sysimg_gvars = NULL; static void **sysimg_fvars = NULL; @@ -711,7 +711,7 @@ static int literal_val_id(jl_serializer_state *s, jl_value_t *v) return jl_array_len(s->tree_literal_values) - 1; } -static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v) +static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_literal) { if (v == NULL) { write_uint8(s->s, Null_tag); @@ -734,7 +734,7 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v) if (s->mode == MODE_AST) { // compressing tree - if (!is_ast_node(v)) { + if (!as_literal && !is_ast_node(v)) { writetag(s->s, (jl_value_t*)LiteralVal_tag); int id = literal_val_id(s, v); assert(id >= 0 && id < UINT16_MAX); @@ -927,6 +927,7 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v) write_int8(s->s, m->called); write_int32(s->s, m->nargs); write_int8(s->s, m->isva); + write_int8(s->s, m->pure); jl_serialize_value(s, (jl_value_t*)m->module); jl_serialize_value(s, (jl_value_t*)m->sparam_syms); jl_serialize_value(s, (jl_value_t*)m->roots); @@ -1667,6 +1668,7 @@ static jl_value_t *jl_deserialize_value_method(jl_serializer_state *s, jl_value_ m->called = read_int8(s->s); m->nargs = read_int32(s->s); m->isva = read_int8(s->s); + m->pure = read_int8(s->s); m->module = (jl_module_t*)jl_deserialize_value(s, (jl_value_t**)&m->module); jl_gc_wb(m, m->module); m->sparam_syms = (jl_svec_t*)jl_deserialize_value(s, (jl_value_t**)&m->sparam_syms); @@ -1674,7 +1676,7 @@ static jl_value_t *jl_deserialize_value_method(jl_serializer_state *s, jl_value_ m->roots = (jl_array_t*)jl_deserialize_value(s, (jl_value_t**)&m->roots); if (m->roots) jl_gc_wb(m, m->roots); - m->source = (jl_code_info_t*)jl_deserialize_value(s, (jl_value_t**)&m->source); + m->source = jl_deserialize_value(s, &m->source); if (m->source) jl_gc_wb(m, m->source); m->unspecialized = (jl_method_instance_t*)jl_deserialize_value(s, (jl_value_t**)&m->unspecialized); @@ -2581,15 +2583,16 @@ JL_DLLEXPORT void jl_restore_system_image_data(const char *buf, size_t len) JL_SIGATOMIC_END(); } -JL_DLLEXPORT jl_array_t *jl_compress_ast(jl_method_t *m, jl_array_t *ast) +JL_DLLEXPORT jl_array_t *jl_compress_ast(jl_method_t *m, jl_code_info_t *code) { JL_TIMING(AST_COMPRESS); JL_LOCK(&m->writelock); // protect the roots array (Might GC) assert(jl_is_method(m)); - assert(jl_is_array(ast)); + assert(jl_is_code_info(code)); ios_t dest; ios_mem(&dest, 0); int en = jl_gc_enable(0); // Might GC + size_t i; if (m->roots == NULL) { m->roots = jl_alloc_vec_any(0); @@ -2600,16 +2603,33 @@ JL_DLLEXPORT jl_array_t *jl_compress_ast(jl_method_t *m, jl_array_t *ast) m->roots, m->module, jl_get_ptls_states() }; - size_t i, nstmts = jl_array_len(ast); - assert(nstmts < INT32_MAX); - write_int32(&dest, nstmts); - for (i = 0; i < nstmts; i++) { - jl_serialize_value(&s, jl_array_ptr_ref(ast, i)); + + uint8_t flags = (code->inferred << 3) + | (code->inlineable << 2) + | (code->propagate_inbounds << 1) + | (code->pure << 0); + write_uint8(s.s, flags); + + size_t nsyms = jl_array_len(code->slotnames); + assert(nsyms >= m->nargs && nsyms < INT32_MAX); // required by generated functions + write_int32(s.s, nsyms); + for (i = 0; i < nsyms; i++) { + jl_sym_t *name = (jl_sym_t*)jl_array_ptr_ref(code->slotnames, i); + assert(jl_is_symbol(name)); + char *namestr = jl_symbol_name(name); + size_t namelen = strlen(namestr); + ios_write(s.s, namestr, namelen + 1); // include nul-byte } - //jl_printf(JL_STDERR, "%d bytes, %d values\n", dest.size, vals->length); + size_t nf = jl_datatype_nfields(jl_code_info_type); + for (i = 0; i < nf - 5; i++) { + jl_serialize_value_(&s, jl_get_nth_field((jl_value_t*)code, i), 1); + } + ios_putc('\0', s.s); + ios_flush(s.s); jl_array_t *v = jl_take_buffer(&dest); + ios_close(s.s); if (jl_array_len(m->roots) == 0) { m->roots = NULL; } @@ -2620,17 +2640,21 @@ JL_DLLEXPORT jl_array_t *jl_compress_ast(jl_method_t *m, jl_array_t *ast) return v; } -JL_DLLEXPORT jl_array_t *jl_uncompress_ast(jl_method_t *m, jl_array_t *data) +JL_DLLEXPORT jl_code_info_t *jl_uncompress_ast(jl_method_t *m, jl_array_t *data) { + if (jl_is_code_info(data)) + return (jl_code_info_t*)data; JL_TIMING(AST_UNCOMPRESS); + jl_ptls_t ptls = jl_get_ptls_states(); JL_LOCK(&m->writelock); // protect the roots array (Might GC) assert(jl_is_method(m)); - assert(jl_is_array(data)); - jl_array_t *bytes = (jl_array_t*)data; + assert(jl_typeis(data, jl_array_uint8_type)); + assert(jl_array_len(data) > 2 && ((uint8_t*)data->data)[jl_array_len(data) - 1] == 0); + size_t i; ios_t src; ios_mem(&src, 0); - ios_setbuf(&src, (char*)bytes->data, jl_array_len(bytes), 0); - src.size = jl_array_len(bytes); + ios_setbuf(&src, (char*)data->data, jl_array_len(data), 0); + src.size = jl_array_len(data); int en = jl_gc_enable(0); // Might GC jl_serializer_state s = { &src, MODE_AST, @@ -2638,16 +2662,102 @@ JL_DLLEXPORT jl_array_t *jl_uncompress_ast(jl_method_t *m, jl_array_t *data) jl_get_ptls_states() }; - size_t i, nstmts = read_int32(&src); - jl_array_t *ast = jl_alloc_vec_any(nstmts); - JL_GC_PUSH1(&ast); - for (i = 0; i < nstmts; i++) { - jl_array_ptr_set(ast, i, jl_deserialize_value(&s, NULL)); - } + jl_code_info_t *code = + (jl_code_info_t*)jl_gc_alloc(ptls, sizeof(jl_code_info_t), + jl_code_info_type); + uint8_t flags = read_uint8(s.s); + code->inferred = !!(flags & (1 << 3)); + code->inlineable = !!(flags & (1 << 2)); + code->propagate_inbounds = !!(flags & (1 << 1)); + code->pure = !!(flags & (1 << 0)); + + size_t nslots = read_int32(&src); + jl_array_t *syms = jl_alloc_vec_any(nslots); + code->slotnames = syms; + for (i = 0; i < nslots; i++) { + char *namestr = s.s->buf + s.s->bpos; + size_t namelen = strlen(namestr); + jl_sym_t *name = jl_symbol_n(namestr, namelen); + jl_array_ptr_set(syms, i, name); + ios_skip(s.s, namelen + 1); + } + + size_t nf = jl_datatype_nfields(jl_code_info_type); + for (i = 0; i < nf - 5; i++) { + assert(jl_field_isptr(jl_code_info_type, i)); + jl_value_t **fld = (jl_value_t**)((char*)jl_data_ptr(code) + jl_field_offset(jl_code_info_type, i)); + *fld = jl_deserialize_value(&s, fld); + } + + assert(ios_getc(s.s) == '\0' && ios_getc(s.s) == -1); + ios_close(s.s); + JL_GC_PUSH1(&code); jl_gc_enable(en); JL_UNLOCK(&m->writelock); // Might GC JL_GC_POP(); - return ast; + return code; +} + +JL_DLLEXPORT uint8_t jl_ast_flag_inferred(jl_array_t *data) +{ + if (jl_is_code_info(data)) + return ((jl_code_info_t*)data)->inferred; + assert(jl_typeis(data, jl_array_uint8_type)); + assert(jl_array_len(data) > 2 && ((uint8_t*)data->data)[jl_array_len(data) - 1] == 0); + uint8_t flags = ((uint8_t*)data->data)[0]; + return !!(flags & (1 << 3)); +} + +JL_DLLEXPORT uint8_t jl_ast_flag_inlineable(jl_array_t *data) +{ + if (jl_is_code_info(data)) + return ((jl_code_info_t*)data)->inlineable; + assert(jl_typeis(data, jl_array_uint8_type)); + assert(jl_array_len(data) > 2 && ((uint8_t*)data->data)[jl_array_len(data) - 1] == 0); + uint8_t flags = ((uint8_t*)data->data)[0]; + return !!(flags & (1 << 2)); +} + +JL_DLLEXPORT uint8_t jl_ast_flag_pure(jl_array_t *data) +{ + if (jl_is_code_info(data)) + return ((jl_code_info_t*)data)->pure; + assert(jl_typeis(data, jl_array_uint8_type)); + assert(jl_array_len(data) > 2 && ((uint8_t*)data->data)[jl_array_len(data) - 1] == 0); + uint8_t flags = ((uint8_t*)data->data)[0]; + return !!(flags & (1 << 0)); +} + +JL_DLLEXPORT void jl_fill_argnames(jl_array_t *data, jl_array_t *names) +{ + size_t i, nargs = jl_array_len(names); + if (jl_is_code_info(data)) { + jl_code_info_t *func = (jl_code_info_t*)data; + assert(jl_array_len(func->slotnames) >= nargs); + for (i = 0; i < nargs; i++) { + jl_value_t *name = jl_array_ptr_ref(func->slotnames, i); + jl_array_ptr_set(names, i, name); + } + } + else { + uint8_t *d = (uint8_t*)data->data; +#ifndef NDEBUG + assert(jl_typeis(data, jl_array_uint8_type)); + int b3 = d[1]; + int b2 = d[2]; + int b1 = d[3]; + int b0 = d[4]; + int nslots = b0 | (b1<<8) | (b2<<16) | (b3<<24); + assert(nslots >= nargs); +#endif + char *namestr = (char*)d + 5; + for (i = 0; i < nargs; i++) { + size_t namelen = strlen(namestr); + jl_sym_t *name = jl_symbol_n(namestr, namelen); + jl_array_ptr_set(names, i, name); + namestr += namelen + 1; + } + } } JL_DLLEXPORT int jl_save_incremental(const char *fname, jl_array_t *worklist) diff --git a/src/interpreter.c b/src/interpreter.c index e724aa172e583..c1cf9036f5ef8 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -635,24 +635,28 @@ static jl_value_t *eval_body(jl_array_t *stmts, interpreter_state *s, int start, jl_value_t *jl_interpret_call(jl_method_instance_t *lam, jl_value_t **args, uint32_t nargs) { if (lam->jlcall_api == 2) - return lam->inferred; + return lam->inferred_const; jl_code_info_t *src = (jl_code_info_t*)lam->inferred; - if (src == NULL || !jl_is_code_info(src)) { + if (!src || (jl_value_t*)src == jl_nothing) { if (lam->def->isstaged) { src = jl_code_for_staged(lam); lam->inferred = (jl_value_t*)src; jl_gc_wb(lam, src); } else { - src = lam->def->source; + src = (jl_code_info_t*)lam->def->source; } } - jl_array_t *stmts = src->code; - if (!jl_typeis(stmts, jl_array_any_type)) { - stmts = jl_uncompress_ast(lam->def, stmts); - src->code = stmts; - jl_gc_wb(src, stmts); + if (src && (jl_value_t*)src != jl_nothing) { + src = jl_uncompress_ast(lam->def, (jl_array_t*)src); + lam->inferred = (jl_value_t*)src; + jl_gc_wb(lam, src); + } + if (!src || !jl_is_code_info(src)) { + jl_error("source missing for method called in interpreter"); } + + jl_array_t *stmts = src->code; assert(jl_typeis(stmts, jl_array_any_type)); jl_value_t **locals; JL_GC_PUSHARGS(locals, jl_source_nslots(src) + jl_source_nssavalues(src) + 2); diff --git a/src/jltypes.c b/src/jltypes.c index 037fbfaf21dd2..46ee7ed55eba2 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -1828,18 +1828,18 @@ void jl_init_types(void) jl_symbol("code"), jl_symbol("slottypes"), jl_symbol("ssavaluetypes"), - jl_symbol("slotnames"), jl_symbol("slotflags"), + jl_symbol("slotnames"), jl_symbol("inferred"), jl_symbol("inlineable"), jl_symbol("propagate_inbounds"), jl_symbol("pure")), jl_svec(9, + jl_array_any_type, jl_any_type, jl_any_type, - jl_any_type, - jl_array_any_type, jl_array_uint8_type, + jl_array_any_type, jl_bool_type, jl_bool_type, jl_bool_type, @@ -1869,7 +1869,7 @@ void jl_init_types(void) jl_symbol("called"), jl_symbol("isva"), jl_symbol("isstaged"), - jl_symbol("needs_sparam_vals_ducttape")), + jl_symbol("pure")), jl_svec(20, jl_sym_type, jl_module_type, @@ -1881,7 +1881,7 @@ void jl_init_types(void) jl_any_type, // Union{Array, Void} jl_any_type, // TypeMap jl_simplevector_type, - jl_code_info_type, + jl_any_type, jl_any_type, // jl_method_instance_type jl_any_type, // jl_method_instance_type jl_array_any_type, diff --git a/src/julia.h b/src/julia.h index 58ce43257e5ac..724c5d8c82f4e 100644 --- a/src/julia.h +++ b/src/julia.h @@ -208,11 +208,11 @@ typedef struct _jl_llvm_functions_t { // This type describes a single function body typedef struct _jl_code_info_t { - jl_array_t *code; // compressed uint8 array, or Any array of statements + jl_array_t *code; // Any array of statements jl_value_t *slottypes; // types of variable slots (or `nothing`) jl_value_t *ssavaluetypes; // types of ssa values (or count of them) - jl_array_t *slotnames; // names of local variables jl_array_t *slotflags; // local var bit flags + jl_array_t *slotnames; // names of local variables uint8_t inferred; uint8_t inlineable; uint8_t propagate_inbounds; @@ -240,7 +240,7 @@ typedef struct _jl_method_t { union jl_typemap_t specializations; jl_svec_t *sparam_syms; // symbols giving static parameter names - jl_code_info_t *source; // original code template, null for builtins + jl_value_t *source; // original code template (jl_code_info_t, but may be compressed), null for builtins struct _jl_method_instance_t *unspecialized; // unspecialized executable method instance, or null struct _jl_method_instance_t *generator; // executable code-generating function if isstaged jl_array_t *roots; // pointers in generated code (shared to reduce memory), or null @@ -254,6 +254,7 @@ typedef struct _jl_method_t { int32_t called; // bit flags: whether each of the first 8 arguments is called uint8_t isva; uint8_t isstaged; + uint8_t pure; // hidden fields: uint8_t traced; @@ -1383,8 +1384,12 @@ JL_DLLEXPORT void jl_register_newmeth_tracer(void (*callback)(jl_method_t *trace // AST access JL_DLLEXPORT jl_value_t *jl_copy_ast(jl_value_t *expr); -JL_DLLEXPORT jl_array_t *jl_compress_ast(jl_method_t *m, jl_array_t *ast); -JL_DLLEXPORT jl_array_t *jl_uncompress_ast(jl_method_t *m, jl_array_t *data); +JL_DLLEXPORT jl_array_t *jl_compress_ast(jl_method_t *m, jl_code_info_t *code); +JL_DLLEXPORT jl_code_info_t *jl_uncompress_ast(jl_method_t *m, jl_array_t *data); +JL_DLLEXPORT uint8_t jl_ast_flag_inferred(jl_array_t *data); +JL_DLLEXPORT uint8_t jl_ast_flag_inlineable(jl_array_t *data); +JL_DLLEXPORT uint8_t jl_ast_flag_pure(jl_array_t *data); +JL_DLLEXPORT void jl_fill_argnames(jl_array_t *data, jl_array_t *names); JL_DLLEXPORT int jl_is_operator(char *sym); JL_DLLEXPORT int jl_operator_precedence(char *sym); diff --git a/src/julia_internal.h b/src/julia_internal.h index ceff5aa311952..b5d5139bcced4 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -283,7 +283,7 @@ STATIC_INLINE jl_value_t *jl_compile_method_internal(jl_generic_fptr_t *fptr, jl_method_instance_t *meth) { if (meth->jlcall_api == 2) - return jl_assume(meth->inferred); + return jl_assume(meth->inferred_const); fptr->fptr = meth->fptr; fptr->jlcall_api = meth->jlcall_api; if (__unlikely(fptr->fptr == NULL || fptr->jlcall_api == 0)) { @@ -293,7 +293,7 @@ STATIC_INLINE jl_value_t *jl_compile_method_internal(jl_generic_fptr_t *fptr, if (!F) // ask codegen to try to turn it into llvm code F = jl_compile_for_dispatch(&meth, world).functionObject; if (meth->jlcall_api == 2) - return jl_assume(meth->inferred); + return jl_assume(meth->inferred_const); // if it hasn't been inferred, try using the unspecialized meth cache instead if (!meth->inferred) { fptr->fptr = meth->unspecialized_ducttape; @@ -303,7 +303,7 @@ STATIC_INLINE jl_value_t *jl_compile_method_internal(jl_generic_fptr_t *fptr, fptr->fptr = meth->def->unspecialized->fptr; fptr->jlcall_api = meth->def->unspecialized->jlcall_api; if (fptr->jlcall_api == 2) { - return jl_assume(meth->def->unspecialized->inferred); + return jl_assume(meth->def->unspecialized->inferred_const); } } } @@ -312,7 +312,7 @@ STATIC_INLINE jl_value_t *jl_compile_method_internal(jl_generic_fptr_t *fptr, // ask codegen to make the fptr *fptr = jl_generate_fptr(meth, F, world); if (fptr->jlcall_api == 2) - return jl_assume(meth->inferred); + return jl_assume(meth->inferred_const); } } return NULL; @@ -641,7 +641,6 @@ void jl_critical_error(int sig, bt_context_t *context, uintptr_t *bt_data, size_ JL_DLLEXPORT void jl_raise_debugger(void); int jl_getFunctionInfo(jl_frame_t **frames, uintptr_t pointer, int skipC, int noInline); JL_DLLEXPORT void jl_gdblookup(uintptr_t ip); -jl_value_t *jl_uncompress_ast_(jl_method_instance_t*, jl_value_t*, int); // *to is NULL or malloc'd pointer, from is allowed to be NULL STATIC_INLINE char *jl_copy_str(char **to, const char *from) { diff --git a/src/method.c b/src/method.c index f6349122fd78c..1c6177d52bdc3 100644 --- a/src/method.c +++ b/src/method.c @@ -261,7 +261,6 @@ JL_DLLEXPORT jl_code_info_t *jl_code_for_staged(jl_method_instance_t *linfo) JL_TIMING(STAGED_FUNCTION); jl_tupletype_t *tt = (jl_tupletype_t*)linfo->specTypes; jl_svec_t *env = linfo->sparam_vals; - size_t i, l; jl_expr_t *ex = NULL; jl_value_t *linenum = NULL; jl_svec_t *sparam_vals = env; @@ -286,11 +285,9 @@ JL_DLLEXPORT jl_code_info_t *jl_code_for_staged(jl_method_instance_t *linfo) ex = jl_exprn(lambda_sym, 2); - int nargs = linfo->def->nargs; - jl_array_t *argnames = jl_alloc_vec_any(nargs); + jl_array_t *argnames = jl_alloc_vec_any(linfo->def->nargs); jl_array_ptr_set(ex->args, 0, argnames); - for (i = 0; i < nargs; i++) - jl_array_ptr_set(argnames, i, jl_array_ptr_ref(linfo->def->source->slotnames, i)); + jl_fill_argnames((jl_array_t*)linfo->def->source, argnames); jl_expr_t *scopeblock = jl_exprn(jl_symbol("scope-block"), 1); jl_array_ptr_set(ex->args, 1, scopeblock); @@ -325,6 +322,7 @@ JL_DLLEXPORT jl_code_info_t *jl_code_for_staged(jl_method_instance_t *linfo) } jl_array_t *stmts = (jl_array_t*)func->code; + size_t i, l; for (i = 0, l = jl_array_len(stmts); i < l; i++) { jl_array_ptr_set(stmts, i, jl_resolve_globals(jl_array_ptr_ref(stmts, i), linfo->def->module, env)); } @@ -380,10 +378,11 @@ static void jl_method_set_source(jl_method_t *m, jl_code_info_t *src) called |= (1 << (j - 1)); } m->called = called; + m->pure = src->pure; jl_array_t *copy = NULL; jl_svec_t *sparam_vars = jl_outer_unionall_vars(m->sig); - JL_GC_PUSH2(©, &sparam_vars); + JL_GC_PUSH3(©, &sparam_vars, &src); assert(jl_typeis(src->code, jl_array_any_type)); jl_array_t *stmts = (jl_array_t*)src->code; size_t i, n = jl_array_len(stmts); @@ -404,10 +403,11 @@ static void jl_method_set_source(jl_method_t *m, jl_code_info_t *src) } jl_array_ptr_set(copy, i, st); } - copy = jl_compress_ast(m, copy); - m->source = jl_copy_code_info(src); + src = jl_copy_code_info(src); + src->code = copy; + jl_gc_wb(src, copy); + m->source = (jl_value_t*)jl_compress_ast(m, src); jl_gc_wb(m, m->source); - m->source->code = copy; JL_GC_POP(); } @@ -495,9 +495,8 @@ extern int jl_boot_file_loaded; void print_func_loc(JL_STREAM *s, jl_method_t *m); -void jl_check_static_parameter_conflicts(jl_method_t *m, jl_svec_t *t) +static void jl_check_static_parameter_conflicts(jl_method_t *m, jl_code_info_t *src, jl_svec_t *t) { - jl_code_info_t *src = m->source; size_t nvars = jl_array_len(src->slotnames); size_t i, n = jl_svec_len(t); @@ -647,7 +646,7 @@ JL_DLLEXPORT void jl_method_def(jl_svec_t *argdata, m->line); } - jl_check_static_parameter_conflicts(m, tvars); + jl_check_static_parameter_conflicts(m, f, tvars); size_t i, na = jl_svec_len(atypes); for (i = 0; i < na; i++) { diff --git a/test/inference.jl b/test/inference.jl index 23f24982ab468..b2ede24f10803 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -411,10 +411,10 @@ Base.@pure function fpure(a=rand(); b=rand()) end gpure() = fpure() gpure(x::Irrational) = fpure(x) -@test which(fpure, ()).source.pure -@test which(fpure, (typeof(pi),)).source.pure -@test !which(gpure, ()).source.pure -@test !which(gpure, (typeof(pi),)).source.pure +@test which(fpure, ()).pure +@test which(fpure, (typeof(pi),)).pure +@test !which(gpure, ()).pure +@test !which(gpure, (typeof(pi),)).pure @test @code_typed(gpure())[1].pure @test @code_typed(gpure(π))[1].pure @test gpure() == gpure() == gpure() @@ -422,7 +422,7 @@ gpure(x::Irrational) = fpure(x) # Make sure @pure works for functions using the new syntax Base.@pure (fpure2(x::T) where T) = T -@test which(fpure2, (Int64,)).source.pure +@test which(fpure2, (Int64,)).pure # issue #10880 function cat10880(a, b) From 52f04d2d91e89af1616e14cf807b3508ccc8eae1 Mon Sep 17 00:00:00 2001 From: Amit Murthy Date: Thu, 23 Mar 2017 23:55:11 +0530 Subject: [PATCH 0265/1534] Improve task switching performance on unbuffered channels (#21120) Improve task switching performance on unbuffered channels --- base/asyncmap.jl | 2 +- base/channels.jl | 63 +++++++++++++++++++++++++++++++++--------------- 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/base/asyncmap.jl b/base/asyncmap.jl index f8a789a653fae..fcfeedd24d0be 100644 --- a/base/asyncmap.jl +++ b/base/asyncmap.jl @@ -206,7 +206,7 @@ function setup_chnl_and_tasks(exec_func, ntasks, batch_size=nothing) chnl = Channel(0) worker_tasks = [] foreach(_ -> start_worker_task!(worker_tasks, exec_func, chnl, batch_size), 1:nt) - + yield() return (chnl, worker_tasks) end diff --git a/base/channels.jl b/base/channels.jl index 9f6850c84f9d5..7f9ae1f9c3708 100644 --- a/base/channels.jl +++ b/base/channels.jl @@ -27,7 +27,9 @@ mutable struct Channel{T} <: AbstractChannel sz_max::Int # maximum size of channel # Used when sz_max == 0, i.e., an unbuffered channel. - takers::Array{Condition} + takers::Array{Task} + putters::Array{Task} + waiters::Int function Channel{T}(sz::Float64) where T if sz == Inf @@ -40,7 +42,7 @@ mutable struct Channel{T} <: AbstractChannel if sz < 0 throw(ArgumentError("Channel size must be either 0, a positive integer or Inf")) end - new(Condition(), Condition(), :open, Nullable{Exception}(), Array{T}(0), sz, Array{Condition}(0)) + new(Condition(), Condition(), :open, Nullable{Exception}(), Array{T}(0), sz, Array{Task}(0), Array{Task}(0), 0) end # deprecated empty constructor @@ -269,12 +271,20 @@ function put_buffered(c::Channel, v) end function put_unbuffered(c::Channel, v) - while length(c.takers) == 0 - notify(c.cond_take, nothing, true, false) # Required to handle wait() on 0-sized channels - wait(c.cond_put) + if length(c.takers) == 0 + push!(c.putters, current_task()) + c.waiters > 0 && notify(c.cond_take, nothing, false, false) + + try + wait() + catch ex + filter!(x->x!=current_task(), c.putters) + rethrow(ex) + end end - cond_taker = shift!(c.takers) - notify(cond_taker, v, false, false) > 0 && yield() + taker = shift!(c.takers) + schedule(current_task()) + yieldto(taker, v) v end @@ -313,20 +323,19 @@ end shift!(c::Channel) = take!(c) # 0-size channel -function take_unbuffered(c::Channel) +function take_unbuffered(c::Channel{T}) where T check_channel_state(c) - cond_taker = Condition() - push!(c.takers, cond_taker) - notify(c.cond_put, nothing, false, false) + push!(c.takers, current_task()) try - return wait(cond_taker) - catch e - if isa(e, InterruptException) - # remove self from the list of takers - filter!(x -> x != cond_taker, c.takers) + if length(c.putters) > 0 + putter = shift!(c.putters) + return yieldto(putter)::T else - rethrow(e) + return wait()::T end + catch ex + filter!(x->x!=current_task(), c.takers) + rethrow(ex) end end @@ -340,9 +349,10 @@ For unbuffered channels returns `true` if there are tasks waiting on a [`put!`](@ref). """ isready(c::Channel) = n_avail(c) > 0 -n_avail(c::Channel) = isbuffered(c) ? length(c.data) : n_waiters(c.cond_put) +n_avail(c::Channel) = isbuffered(c) ? length(c.data) : length(c.putters) -function wait(c::Channel) +wait(c::Channel) = isbuffered(c) ? wait_impl(c) : wait_unbuffered(c) +function wait_impl(c::Channel) while !isready(c) check_channel_state(c) wait(c.cond_take) @@ -350,10 +360,23 @@ function wait(c::Channel) nothing end +function wait_unbuffered(c::Channel) + c.waiters += 1 + try + wait_impl(c) + finally + c.waiters -= 1 + end + nothing +end + function notify_error(c::Channel, err) notify_error(c.cond_take, err) notify_error(c.cond_put, err) - foreach(x->notify_error(x, err), c.takers) + + # release tasks on a `wait()/yielto()` call (on unbuffered channels) + waiters = filter!(t->(t.state == :runnable), vcat(c.takers, c.putters)) + foreach(t->schedule(t, err; error=true), waiters) end notify_error(c::Channel) = notify_error(c, get(c.excp)) From 9736ab9b2b85be5553a04adb6afb7732d1689c58 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 23 Mar 2017 14:57:24 -0400 Subject: [PATCH 0266/1534] some fixes for compiling the runtime code as c++ --- src/gc.c | 6 ++++-- src/interpreter.c | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/gc.c b/src/gc.c index 471669a4afee9..411510710d7ca 100644 --- a/src/gc.c +++ b/src/gc.c @@ -604,8 +604,10 @@ STATIC_INLINE void gc_setmark(jl_ptls_t ptls, jl_taggedvalue_t *o, } } -inline void gc_setmark_buf(jl_ptls_t ptls, void *o, - uint8_t mark_mode, size_t minsz) +#ifndef __cplusplus +inline +#endif +void gc_setmark_buf(jl_ptls_t ptls, void *o, uint8_t mark_mode, size_t minsz) { jl_taggedvalue_t *buf = jl_astaggedvalue(o); uintptr_t tag = buf->header; diff --git a/src/interpreter.c b/src/interpreter.c index e724aa172e583..7d054ecc2a14e 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -116,12 +116,13 @@ static int equiv_type(jl_datatype_t *dta, jl_datatype_t *dtb) jl_field_count(dta) == jl_field_count(dtb))) return 0; jl_value_t *a=NULL, *b=NULL; + int ok = 1; + size_t i, nf = jl_field_count(dta); JL_GC_PUSH2(&a, &b); a = jl_rewrap_unionall((jl_value_t*)dta->super, dta->name->wrapper); b = jl_rewrap_unionall((jl_value_t*)dtb->super, dtb->name->wrapper); if (!jl_types_equal(a, b)) goto no; - int ok = 1; JL_TRY { a = jl_apply_type(dtb->name->wrapper, jl_svec_data(dta->parameters), jl_nparams(dta)); } @@ -142,7 +143,6 @@ static int equiv_type(jl_datatype_t *dta, jl_datatype_t *dtb) b = ub->body; } assert(jl_is_datatype(a) && jl_is_datatype(b)); - size_t i, nf = jl_field_count(dta); for (i=0; i < nf; i++) { jl_value_t *ta = jl_svecref(((jl_datatype_t*)a)->types, i); jl_value_t *tb = jl_svecref(((jl_datatype_t*)b)->types, i); From e976e63cc791411b1e7d88b7ca705e87e10d8574 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Thu, 23 Mar 2017 14:22:17 -0700 Subject: [PATCH 0267/1534] reenable Core+Base ambiguity detection (#20986) * Resolve ambiguity between cat (git-cat-file and other) methods. * Reenable the Core+Base ambiguity detection test. --- base/libgit2/libgit2.jl | 2 +- test/ambiguous.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/base/libgit2/libgit2.jl b/base/libgit2/libgit2.jl index 6f5f9bebbb34e..8ccf350274bd7 100644 --- a/base/libgit2/libgit2.jl +++ b/base/libgit2/libgit2.jl @@ -496,7 +496,7 @@ reset!(repo::GitRepo, id::GitHash, mode::Cint = Consts.RESET_MIXED) = reset!(repo, GitObject(repo, id), mode) """ git cat-file """ -function cat(repo::GitRepo, spec) +function cat(repo::GitRepo, spec::Union{AbstractString,AbstractGitHash}) obj = GitObject(repo, spec) if isa(obj, GitBlob) content(obj) diff --git a/test/ambiguous.jl b/test/ambiguous.jl index 2b1ad51c8d721..312f4ec6ce65d 100644 --- a/test/ambiguous.jl +++ b/test/ambiguous.jl @@ -135,7 +135,7 @@ ambs = detect_ambiguities(Ambig5) # Test that Core and Base are free of ambiguities # TODO jb/subtype: we now detect a lot more @test !isempty(detect_ambiguities(Core, Base; imported=true, ambiguous_bottom=true)) -@test_broken detect_ambiguities(Core, Base; imported=true, ambiguous_bottom=false) == [] +@test detect_ambiguities(Core, Base; imported=true, ambiguous_bottom=false) == [] # not using isempty so this prints more information when it fails amb_1(::Int8, ::Int) = 1 From f7947963f7b635aecde99889c357dac945eef0ed Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 24 Feb 2017 17:04:13 -0500 Subject: [PATCH 0268/1534] improve `precompile` mechanism a bit - improve static_show to readably print a much larger set of types - add TRACE_COMPILE option to print `precompile` calls --- src/gf.c | 15 ++++++++++--- src/julia.h | 1 + src/module.c | 20 +++++++---------- src/options.h | 1 + src/rtutils.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++---- 5 files changed, 78 insertions(+), 19 deletions(-) diff --git a/src/gf.c b/src/gf.c index 5651e279d1c18..7518b47c6885d 100644 --- a/src/gf.c +++ b/src/gf.c @@ -259,9 +259,11 @@ jl_code_info_t *jl_type_infer(jl_method_instance_t **pli, size_t world, int forc fargs[1] = (jl_value_t*)li; fargs[2] = jl_box_ulong(world); #ifdef TRACE_INFERENCE - jl_printf(JL_STDERR,"inference on "); - jl_static_show_func_sig(JL_STDERR, (jl_value_t*)li->specTypes); - jl_printf(JL_STDERR, "\n"); + if (li->specTypes != (jl_value_t*)jl_emptytuple_type) { + jl_printf(JL_STDERR,"inference on "); + jl_static_show_func_sig(JL_STDERR, (jl_value_t*)li->specTypes); + jl_printf(JL_STDERR, "\n"); + } #endif jl_get_ptls_states()->world_age = jl_typeinf_world; jl_svec_t *linfo_src_rettype = (jl_svec_t*)jl_apply(fargs, 3); @@ -1041,6 +1043,13 @@ static jl_method_instance_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_datatype JL_GC_POP(); return NULL; } +#ifdef TRACE_COMPILE + if (!jl_has_free_typevars((jl_value_t*)tt)) { + jl_printf(JL_STDERR, "precompile("); + jl_static_show(JL_STDERR, (jl_value_t*)tt); + jl_printf(JL_STDERR, ")\n"); + } +#endif sig = join_tsig(tt, entry->sig); jl_method_instance_t *nf; if (!cache) { diff --git a/src/julia.h b/src/julia.h index 58ce43257e5ac..3fc5abb60d1fe 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1231,6 +1231,7 @@ JL_DLLEXPORT void jl_module_import(jl_module_t *to, jl_module_t *from, JL_DLLEXPORT void jl_module_importall(jl_module_t *to, jl_module_t *from); JL_DLLEXPORT void jl_module_export(jl_module_t *from, jl_sym_t *s); JL_DLLEXPORT int jl_is_imported(jl_module_t *m, jl_sym_t *s); +JL_DLLEXPORT int jl_module_exports_p(jl_module_t *m, jl_sym_t *var); JL_DLLEXPORT jl_module_t *jl_new_main_module(void); JL_DLLEXPORT void jl_add_standard_imports(jl_module_t *m); STATIC_INLINE jl_function_t *jl_get_function(jl_module_t *m, const char *name) diff --git a/src/module.c b/src/module.c index 9c0492a99b3ee..4225ce5eaa0f9 100644 --- a/src/module.c +++ b/src/module.c @@ -261,9 +261,8 @@ static int eq_bindings(jl_binding_t *a, jl_binding_t *b) // does module m explicitly import s? JL_DLLEXPORT int jl_is_imported(jl_module_t *m, jl_sym_t *s) { - jl_binding_t **bp = (jl_binding_t**)ptrhash_bp(&m->bindings, s); - jl_binding_t *bto = *bp; - return (bto != HT_NOTFOUND && bto->imported); + jl_binding_t *b = (jl_binding_t*)ptrhash_get(&m->bindings, s); + return (b != HT_NOTFOUND && b->imported); } // NOTE: we use explici since explicit is a C++ keyword @@ -411,23 +410,20 @@ JL_DLLEXPORT int jl_boundp(jl_module_t *m, jl_sym_t *var) JL_DLLEXPORT int jl_defines_or_exports_p(jl_module_t *m, jl_sym_t *var) { - jl_binding_t **bp = (jl_binding_t**)ptrhash_bp(&m->bindings, var); - if (*bp == HT_NOTFOUND) return 0; - return (*bp)->exportp || (*bp)->owner==m; + jl_binding_t *b = (jl_binding_t*)ptrhash_get(&m->bindings, var); + return b != HT_NOTFOUND && (b->exportp || b->owner==m); } JL_DLLEXPORT int jl_module_exports_p(jl_module_t *m, jl_sym_t *var) { - jl_binding_t **bp = (jl_binding_t**)ptrhash_bp(&m->bindings, var); - if (*bp == HT_NOTFOUND) return 0; - return (*bp)->exportp; + jl_binding_t *b = (jl_binding_t*)ptrhash_get(&m->bindings, var); + return b != HT_NOTFOUND && b->exportp; } JL_DLLEXPORT int jl_binding_resolved_p(jl_module_t *m, jl_sym_t *var) { - jl_binding_t **bp = (jl_binding_t**)ptrhash_bp(&m->bindings, var); - if (*bp == HT_NOTFOUND) return 0; - return (*bp)->owner != NULL; + jl_binding_t *b = (jl_binding_t*)ptrhash_get(&m->bindings, var); + return b != HT_NOTFOUND && b->owner != NULL; } JL_DLLEXPORT jl_value_t *jl_get_global(jl_module_t *m, jl_sym_t *var) diff --git a/src/options.h b/src/options.h index 93d1f8fb76939..f285e32855065 100644 --- a/src/options.h +++ b/src/options.h @@ -89,6 +89,7 @@ // print all signatures type inference is invoked on //#define TRACE_INFERENCE +//#define TRACE_COMPILE // print all generic method dispatches (excludes inlined and specialized call // sites). this generally prints too much output to be useful. diff --git a/src/rtutils.c b/src/rtutils.c index 5ab199eb9e233..7c84842e7eb14 100644 --- a/src/rtutils.c +++ b/src/rtutils.c @@ -481,6 +481,8 @@ struct recur_list { static size_t jl_static_show_x(JL_STREAM *out, jl_value_t *v, struct recur_list *depth); +JL_DLLEXPORT int jl_id_start_char(uint32_t wc); + // `v` might be pointing to a field inlined in a structure therefore // `jl_typeof(v)` may not be the same with `vt` and only `vt` should be // used to determine the type of the value. @@ -526,11 +528,49 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt } else if (vt == jl_datatype_type) { jl_datatype_t *dv = (jl_datatype_t*)v; - if (dv->name->module != jl_core_module) { + jl_sym_t *globname = dv->name->mt != NULL ? dv->name->mt->name : NULL; + int globfunc = 0; + if (globname && !strchr(jl_symbol_name(globname), '#') && + !strchr(jl_symbol_name(globname), '@') && + jl_binding_resolved_p(dv->name->module, globname)) { + jl_binding_t *b = jl_get_binding(dv->name->module, globname); + if (b && jl_typeof(b->value) == v) + globfunc = 1; + } + jl_sym_t *sym = globfunc ? globname : dv->name->name; + char *sn = jl_symbol_name(sym); + int hidden = !globfunc && strchr(sn, '#'); + size_t i = 0; + int quote = 0; + if (hidden) { + n += jl_printf(out, "getfield("); + } + else if (globfunc) { + n += jl_printf(out, "typeof("); + } + if (dv->name->module != jl_core_module || !jl_module_exports_p(jl_core_module, sym)) { n += jl_static_show_x(out, (jl_value_t*)dv->name->module, depth); - n += jl_printf(out, "."); + if (!hidden) { + n += jl_printf(out, "."); + if (globfunc && !jl_id_start_char(u8_nextchar(sn, &i))) { + n += jl_printf(out, ":("); + quote = 1; + } + } + } + if (hidden) { + n += jl_printf(out, ", Symbol(\""); + n += jl_printf(out, "%s", sn); + n += jl_printf(out, "\"))"); + } + else { + n += jl_printf(out, "%s", sn); + if (globfunc) { + n += jl_printf(out, ")"); + if (quote) + n += jl_printf(out, ")"); + } } - n += jl_printf(out, "%s", jl_symbol_name(dv->name->name)); if (dv->parameters && (jl_value_t*)dv != dv->name->wrapper && (jl_has_free_typevars(v) || (jl_value_t*)dv != (jl_value_t*)jl_tuple_type)) { @@ -602,6 +642,9 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt jl_uv_puts(out, jl_string_data(v), jl_string_len(v)); n += jl_string_len(v); n += jl_printf(out, "\""); } + else if (v == jl_bottom_type) { + n += jl_printf(out, "Union{}"); + } else if (vt == jl_uniontype_type) { n += jl_printf(out, "Union{"); while (jl_is_uniontype(v)) { @@ -662,7 +705,16 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt n += jl_printf(out, "%s", jl_symbol_name(m->name)); } else if (vt == jl_sym_type) { - n += jl_printf(out, ":%s", jl_symbol_name((jl_sym_t*)v)); + char *sn = jl_symbol_name((jl_sym_t*)v); + // TODO check for valid identifier + int quoted = strchr(sn, '/') && strcmp(sn, "/") && strcmp(sn, "//") && strcmp(sn, "//="); + if (quoted) + n += jl_printf(out, "Symbol(\""); + else + n += jl_printf(out, ":"); + n += jl_printf(out, "%s", sn); + if (quoted) + n += jl_printf(out, "\")"); } else if (vt == jl_ssavalue_type) { n += jl_printf(out, "SSAValue(%" PRIuPTR ")", From ae18dae69f8826cda8595a40b423ea4824eb24fe Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Fri, 24 Mar 2017 09:18:38 -0500 Subject: [PATCH 0269/1534] Restrict mapslices to only reuse StridedArray slices (#21133) Fix #21123. --- base/abstractarray.jl | 35 ++++++++++++++++------------------- test/arrayops.jl | 13 ++++++++----- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index f9ab3fef45982..92a27271693a4 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -1790,9 +1790,15 @@ function mapslices(f, A::AbstractArray, dims::AbstractVector) idx[d] = Slice(indices(A, d)) end + # Apply the function to the first slice in order to determine the next steps Aslice = A[idx...] r1 = f(Aslice) - safe_for_reuse = isa(r1, Number) || (isa(r1, AbstractArray) && eltype(r1) <: Number) + # In some cases, we can re-use the first slice for a dramatic performance + # increase. The slice itself must be mutable and the result cannot contain + # any mutable containers. The following errs on the side of being overly + # strict (#18570 & #21123). + safe_for_reuse = isa(Aslice, StridedArray) && + (isa(r1, Number) || (isa(r1, AbstractArray) && eltype(r1) <: Number)) # determine result size and allocate Rsize = copy(dimsA) @@ -1815,33 +1821,24 @@ function mapslices(f, A::AbstractArray, dims::AbstractVector) R[ridx...] = r1 - isfirst = true nidx = length(otherdims) if safe_for_reuse # when f returns an array, R[ridx...] = f(Aslice) line copies elements, # so we can reuse Aslice - for I in CartesianRange(itershape) - if isfirst - isfirst = false # skip the first element, we already handled it - else - for i in 1:nidx - idx[otherdims[i]] = ridx[otherdims[i]] = I.I[i] - end - _unsafe_getindex!(Aslice, A, idx...) - R[ridx...] = f(Aslice) + for I in Iterators.drop(CartesianRange(itershape), 1) # skip the first element, we already handled it + for i in 1:nidx + idx[otherdims[i]] = ridx[otherdims[i]] = I.I[i] end + _unsafe_getindex!(Aslice, A, idx...) + R[ridx...] = f(Aslice) end else # we can't guarantee safety (#18524), so allocate new storage for each slice - for I in CartesianRange(itershape) - if isfirst - isfirst = false - else - for i in 1:nidx - idx[otherdims[i]] = ridx[otherdims[i]] = I.I[i] - end - R[ridx...] = f(A[idx...]) + for I in Iterators.drop(CartesianRange(itershape), 1) + for i in 1:nidx + idx[otherdims[i]] = ridx[otherdims[i]] = I.I[i] end + R[ridx...] = f(A[idx...]) end end diff --git a/test/arrayops.jl b/test/arrayops.jl index 37c91750830b6..0c849a5368f62 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -951,6 +951,14 @@ end m = mapslices(x->fill!(x, 0), o, 2) @test m == zeros(3, 4) @test o == ones(3, 4) + + # issue #18524 + m = mapslices(x->tuple(x), [1 2; 3 4], 1) + @test m[1,1] == ([1,3],) + @test m[1,2] == ([2,4],) + + # issue #21123 + mapslices(nnz, speye(3), 1) == [1, 1, 1] end @testset "single multidimensional index" begin @@ -1006,11 +1014,6 @@ end @test m == zeros(3, 4) @test o == ones(3, 4) - # issue #18524 - m = mapslices(x->tuple(x), [1 2; 3 4], 1) - @test m[1,1] == ([1,3],) - @test m[1,2] == ([2,4],) - asr = sortrows(a, rev=true) @test lexless(asr[2,:],asr[1,:]) @test lexless(asr[3,:],asr[2,:]) From 5153f5b6b0bbd2d2d664c1fe471aa5a788bd1bcd Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 24 Mar 2017 15:00:42 -0400 Subject: [PATCH 0270/1534] fix #21147, lowering of keyword args with chained static parameters --- src/julia-syntax.scm | 14 +++++++++++--- test/keywordargs.jl | 7 +++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index ea639e5e21c80..5ab1dec350f57 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -468,9 +468,17 @@ ;; call with unsorted keyword args. this sorts and re-dispatches. ,(method-def-expr- name - (filter ;; remove sparams that don't occur, to avoid printing the warning twice - (lambda (s) (expr-contains-eq (car s) (cons 'list argl))) - positional-sparams) + ;; remove sparams that don't occur, to avoid printing the warning twice + (let loop ((filtered '()) + (params positional-sparams)) + (cond ((null? params) + (reverse! filtered)) + ((or (expr-contains-eq (caar params) (cons 'list argl)) + (any (lambda (v) (expr-contains-eq (caar params) v)) + (cdr params))) + (loop (cons (car params) filtered) (cdr params))) + (else + (loop filtered (cdr params))))) `((|::| ;; if there are optional positional args, we need to be able to reference the function name ,(if (any kwarg? pargl) (gensy) UNUSED) diff --git a/test/keywordargs.jl b/test/keywordargs.jl index e3806fc87509f..5cb556b3a11c7 100644 --- a/test/keywordargs.jl +++ b/test/keywordargs.jl @@ -258,3 +258,10 @@ let x = T20804(4) @test x() == 14 @test x(x=8) == 12 end + +# issue #21147 +function f21147(f::Tuple{A}; kwargs...) where {B,A<:Tuple{B}} + return B +end +@test f21147(((1,),)) === Int +@test f21147(((1,),), k = 2) === Int From 70bb32f5203baa2ff32cb7b320eeaaf2c815b968 Mon Sep 17 00:00:00 2001 From: Stefan Karpinski Date: Fri, 24 Mar 2017 20:36:56 -0400 Subject: [PATCH 0271/1534] rename Core.BottomType => Core.TypeofBottom (#21057) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The old name sounds like an alias for `Bottom = Union{}` rather than `Type{Bottom} == typeof(Bottom)`. (This last should hold but currently doesn't – see #21016.) --- NEWS.md | 2 +- base/docs/basedocs.jl | 7 +++++++ base/serialize.jl | 2 +- base/show.jl | 2 +- doc/src/devdocs/types.md | 8 ++++---- src/builtins.c | 2 +- src/codegen.cpp | 8 ++++---- src/dump.c | 4 ++-- src/jltypes.c | 8 ++++---- src/julia.h | 4 ++-- src/subtype.c | 2 +- test/core.jl | 2 +- test/subtype.jl | 4 ++-- 13 files changed, 31 insertions(+), 24 deletions(-) diff --git a/NEWS.md b/NEWS.md index 9b6c0b5c4f8b6..da5ccd9ff7169 100644 --- a/NEWS.md +++ b/NEWS.md @@ -173,7 +173,7 @@ This section lists changes that do not have deprecation warnings. as `UnionAll` types instead of `DataType`s ([#18457]). * `Union` types have two fields, `a` and `b`, instead of a single `types` field. - The empty type `Union{}` is represented by a singleton of type `BottomType` ([#18457]). + The empty type `Union{}` is represented by a singleton of type `TypeofBottom` ([#18457]). * The type `NTuple{N}` now refers to tuples where every element has the same type (since it is shorthand for `NTuple{N,T} where T`). To get the old behavior of matching diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index 3b8a35cbd0ca0..f67777940bca1 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -674,6 +674,13 @@ generation specialization for that field. """ ANY +""" + Core.TypeofBottom + +The singleton type containing only the value `Union{}`. +""" +Core.TypeofBottom + """ DevNull diff --git a/base/serialize.jl b/base/serialize.jl index 6fe0fa731d835..4fd98dd00e2d8 100644 --- a/base/serialize.jl +++ b/base/serialize.jl @@ -32,7 +32,7 @@ const TAGS = Any[ Module, #=UndefRefTag=#Symbol, Task, String, Float16, SimpleVector, #=BackrefTag=#Symbol, Method, GlobalRef, UnionAll, - (), Bool, Any, :Any, Bottom, Core.BottomType, :reserved22, Type, + (), Bool, Any, :Any, Bottom, Core.TypeofBottom, :reserved22, Type, :Array, :TypeVar, :Box, :lambda, :body, :return, :call, Symbol("::"), :(=), :null, :gotoifnot, :A, :B, :C, :M, :N, :T, :S, :X, :Y, diff --git a/base/show.jl b/base/show.jl index b6bac9a6f5694..40ac09f544530 100644 --- a/base/show.jl +++ b/base/show.jl @@ -183,7 +183,7 @@ function show(io::IO, x::Core.IntrinsicFunction) print(io, unsafe_string(name)) end -show(io::IO, ::Core.BottomType) = print(io, "Union{}") +show(io::IO, ::Core.TypeofBottom) = print(io, "Union{}") function show(io::IO, x::Union) print(io, "Union") diff --git a/doc/src/devdocs/types.md b/doc/src/devdocs/types.md index 93a5c914c55cd..dd95329d08e17 100644 --- a/doc/src/devdocs/types.md +++ b/doc/src/devdocs/types.md @@ -92,12 +92,12 @@ julia> dump(Array) UnionAll var: TypeVar name: Symbol T - lb: Core.BottomType Union{} + lb: Core.TypeofBottom Union{} ub: Any body: UnionAll var: TypeVar name: Symbol N - lb: Core.BottomType Union{} + lb: Core.TypeofBottom Union{} ub: Any body: Array{T,N} <: DenseArray{T,N} ``` @@ -178,12 +178,12 @@ TypeName wrapper: UnionAll var: TypeVar name: Symbol T - lb: Core.BottomType Union{} + lb: Core.TypeofBottom Union{} ub: Any body: UnionAll var: TypeVar name: Symbol N - lb: Core.BottomType Union{} + lb: Core.TypeofBottom Union{} ub: Any body: Array{T,N} <: DenseArray{T,N} cache: SimpleVector diff --git a/src/builtins.c b/src/builtins.c index 4d40c470a04c8..12a1b7b43e70e 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -1102,7 +1102,7 @@ void jl_init_primitives(void) add_builtin("TypeVar", (jl_value_t*)jl_tvar_type); add_builtin("UnionAll", (jl_value_t*)jl_unionall_type); add_builtin("Union", (jl_value_t*)jl_uniontype_type); - add_builtin("BottomType", (jl_value_t*)jl_bottomtype_type); + add_builtin("TypeofBottom", (jl_value_t*)jl_typeofbottom_type); add_builtin("Tuple", (jl_value_t*)jl_anytuple_type); add_builtin("Vararg", (jl_value_t*)jl_vararg_type); add_builtin("SimpleVector", (jl_value_t*)jl_simplevector_type); diff --git a/src/codegen.cpp b/src/codegen.cpp index eef9359502789..b14f023062575 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -674,8 +674,8 @@ static inline jl_cgval_t ghostValue(jl_value_t *typ) { if (typ == jl_bottom_type) return jl_cgval_t(); // Undef{} - if (typ == (jl_value_t*)jl_bottomtype_type) { - // normalize BottomType to Type{Union{}} + if (typ == (jl_value_t*)jl_typeofbottom_type) { + // normalize TypeofBottom to Type{Union{}} typ = (jl_value_t*)jl_wrap_Type(jl_bottom_type); } if (jl_is_type_type(typ)) { @@ -870,8 +870,8 @@ static void jl_rethrow_with_add(const char *fmt, ...) // given a value marked with type `v.typ`, compute the mapping and/or boxing to return a value of type `typ` static jl_cgval_t convert_julia_type(const jl_cgval_t &v, jl_value_t *typ, jl_codectx_t *ctx, bool needsroot = true) { - if (typ == (jl_value_t*)jl_bottomtype_type) - return ghostValue(typ); // normalize BottomType to Type{Union{}} + if (typ == (jl_value_t*)jl_typeofbottom_type) + return ghostValue(typ); // normalize TypeofBottom to Type{Union{}} if (v.typ == typ || v.typ == jl_bottom_type || jl_egal(v.typ, typ)) return v; // fast-path Type *T = julia_type_to_llvm(typ); diff --git a/src/dump.c b/src/dump.c index 9da66acb95e84..64d21ee2e04a0 100644 --- a/src/dump.c +++ b/src/dump.c @@ -3209,7 +3209,7 @@ void jl_init_serializer(void) jl_voidpointer_type, jl_newvarnode_type, jl_abstractstring_type, jl_array_symbol_type, jl_anytuple_type, jl_tparam0(jl_anytuple_type), jl_emptytuple_type, jl_array_uint8_type, jl_symbol_type->name, - jl_ssavalue_type->name, jl_tuple_typename, jl_code_info_type, jl_bottomtype_type, + jl_ssavalue_type->name, jl_tuple_typename, jl_code_info_type, jl_typeofbottom_type, ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_ref_type))->name, jl_pointer_typename, jl_simplevector_type->name, jl_datatype_type->name, jl_uniontype_type->name, jl_array_typename, jl_expr_type->name, @@ -3222,7 +3222,7 @@ void jl_init_serializer(void) jl_abstractslot_type->name, jl_slotnumber_type->name, jl_unionall_type->name, jl_intrinsic_type->name, jl_task_type->name, jl_labelnode_type->name, jl_linenumbernode_type->name, jl_builtin_type->name, jl_gotonode_type->name, - jl_quotenode_type->name, jl_globalref_type->name, jl_bottomtype_type->name, + jl_quotenode_type->name, jl_globalref_type->name, jl_typeofbottom_type->name, jl_string_type->name, jl_abstractstring_type->name, ptls->root_task, diff --git a/src/jltypes.c b/src/jltypes.c index 46ee7ed55eba2..6593c479de2e0 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -45,7 +45,7 @@ jl_datatype_t *jl_datatype_type; jl_datatype_t *jl_function_type; jl_datatype_t *jl_builtin_type; -jl_datatype_t *jl_bottomtype_type; +jl_datatype_t *jl_typeofbottom_type; jl_value_t *jl_bottom_type; jl_unionall_t *jl_abstractarray_type; jl_unionall_t *jl_densearray_type; @@ -1616,10 +1616,10 @@ void jl_init_types(void) jl_void_type->instance = jl_nothing; jl_datatype_t *type_type = (jl_datatype_t*)jl_type_type; - jl_bottomtype_type = jl_new_datatype(jl_symbol("BottomType"), type_type, jl_emptysvec, + jl_typeofbottom_type = jl_new_datatype(jl_symbol("TypeofBottom"), type_type, jl_emptysvec, jl_emptysvec, jl_emptysvec, 0, 0, 0); - jl_bottom_type = jl_new_struct(jl_bottomtype_type); - jl_bottomtype_type->instance = jl_bottom_type; + jl_bottom_type = jl_new_struct(jl_typeofbottom_type); + jl_typeofbottom_type->instance = jl_bottom_type; jl_uniontype_type = jl_new_datatype(jl_symbol("Union"), type_type, jl_emptysvec, jl_svec(2, jl_symbol("a"), jl_symbol("b")), diff --git a/src/julia.h b/src/julia.h index 724c5d8c82f4e..699134f06b859 100644 --- a/src/julia.h +++ b/src/julia.h @@ -467,7 +467,7 @@ typedef struct { // constants and type objects ------------------------------------------------- // kinds -extern JL_DLLEXPORT jl_datatype_t *jl_bottomtype_type; +extern JL_DLLEXPORT jl_datatype_t *jl_typeofbottom_type; extern JL_DLLEXPORT jl_datatype_t *jl_datatype_type; extern JL_DLLEXPORT jl_datatype_t *jl_uniontype_type; extern JL_DLLEXPORT jl_datatype_t *jl_unionall_type; @@ -874,7 +874,7 @@ JL_DLLEXPORT int jl_subtype(jl_value_t *a, jl_value_t *b); STATIC_INLINE int jl_is_kind(jl_value_t *v) { return (v==(jl_value_t*)jl_uniontype_type || v==(jl_value_t*)jl_datatype_type || - v==(jl_value_t*)jl_unionall_type || v==(jl_value_t*)jl_bottomtype_type); + v==(jl_value_t*)jl_unionall_type || v==(jl_value_t*)jl_typeofbottom_type); } STATIC_INLINE int jl_is_type(jl_value_t *v) diff --git a/src/subtype.c b/src/subtype.c index 7039be27a5dd3..d38695e0b53a7 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -1649,7 +1649,7 @@ static jl_value_t *intersect_type_type(jl_value_t *x, jl_value_t *y, jl_stenv_t if (!jl_is_typevar(p0)) return (jl_typeof(p0) == y) ? x : jl_bottom_type; if (!jl_is_kind(y)) return jl_bottom_type; - if (y == (jl_value_t*)jl_bottomtype_type && ((jl_tvar_t*)p0)->lb == jl_bottom_type) + if (y == (jl_value_t*)jl_typeofbottom_type && ((jl_tvar_t*)p0)->lb == jl_bottom_type) return (jl_value_t*)jl_wrap_Type(jl_bottom_type); if (((jl_tvar_t*)p0)->ub == (jl_value_t*)jl_any_type) return y; diff --git a/test/core.jl b/test/core.jl index f90962824d88a..4a85c2ab98e67 100644 --- a/test/core.jl +++ b/test/core.jl @@ -4769,7 +4769,7 @@ end x::Array{T} where T<:Integer end -let a = Array{Core.BottomType, 1}(2) +let a = Array{Core.TypeofBottom, 1}(2) @test a[1] == Union{} @test a == [Union{}, Union{}] end diff --git a/test/subtype.jl b/test/subtype.jl index bd209e66d33da..6dc034a72fb48 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -807,8 +807,8 @@ function test_intersection() @test typeintersect(Union{DataType,Int}, Type) === DataType @test typeintersect(Union{DataType,Int}, Type{T} where T) === DataType - # since BottomType is a singleton we can deduce its intersection with Type{...} - @testintersect(Core.BottomType, (Type{T} where T<:Tuple), Type{Union{}}) + # since TypeofBottom is a singleton we can deduce its intersection with Type{...} + @testintersect(Core.TypeofBottom, (Type{T} where T<:Tuple), Type{Union{}}) @testintersect((Type{Tuple{Vararg{T}}} where T), Type{Tuple}, Bottom) @testintersect(Tuple{Type{S}, Tuple{Any, Vararg{Any}}} where S<:Tuple{Any, Vararg{Any}}, From 0152278ddc2820e2c7c82c1b1bdf1ebd708ccb56 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 14 Mar 2017 14:12:21 -0400 Subject: [PATCH 0272/1534] fix part of #21016, specificity of `TypeofBottom` --- src/jltypes.c | 2 ++ src/subtype.c | 8 +++++--- test/core.jl | 11 ++++++++++- test/subtype.jl | 3 +++ 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/jltypes.c b/src/jltypes.c index 6593c479de2e0..032d992b06298 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -1660,6 +1660,8 @@ void jl_init_types(void) jl_type_typename->wrapper = jl_new_struct(jl_unionall_type, tttvar, (jl_value_t*)jl_type_type); jl_type_type = (jl_unionall_t*)jl_type_typename->wrapper; + jl_typeofbottom_type->super = jl_wrap_Type(jl_bottom_type); + jl_emptytuple_type = jl_apply_tuple_type(jl_emptysvec); jl_emptytuple_type->uid = jl_assign_type_uid(); jl_emptytuple = jl_gc_alloc(ptls, 0, jl_emptytuple_type); diff --git a/src/subtype.c b/src/subtype.c index d38695e0b53a7..fa95439428b58 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -776,7 +776,7 @@ static int subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param) } return 0; } - if (jl_is_type_type(y) && !jl_is_type_type(x)) { + if (jl_is_type_type(y) && !jl_is_type_type(x) && x != (jl_value_t*)jl_typeofbottom_type) { jl_value_t *tp0 = jl_tparam0(yd); if (!jl_is_typevar(tp0)) return 0; @@ -789,7 +789,7 @@ static int subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param) } else { e->invdepth++; - ans = forall_exists_equal(x, jl_tparam0(yd), e); + ans = forall_exists_equal(x, tp0, e); e->invdepth--; } return ans; @@ -2337,12 +2337,14 @@ static int type_morespecific_(jl_value_t *a, jl_value_t *b, int invariant, jl_ty if (jl_is_type_type(a) && !invariant) { jl_value_t *tp0a = jl_tparam0(a); if (jl_is_typevar(tp0a)) { + if (b == (jl_value_t*)jl_typeofbottom_type) + return 0; jl_value_t *ub = ((jl_tvar_t*)tp0a)->ub; if (jl_is_kind(b) && !jl_subtype((jl_value_t*)jl_any_type, ub)) return 1; } else { - if (jl_isa(tp0a, b)) + if (jl_isa(tp0a, b) || (tp0a == jl_bottom_type && jl_subtype(b, (jl_value_t*)jl_type_type))) return 1; } } diff --git a/test/core.jl b/test/core.jl index 4a85c2ab98e67..1a6837dc62ed1 100644 --- a/test/core.jl +++ b/test/core.jl @@ -21,7 +21,13 @@ f47{T}(x::Vector{Vector{T}}) = 0 @test_throws TypeError (Array{T} where T<:Vararg{Int,2}) # issue #8652 -args_morespecific(a, b) = ccall(:jl_type_morespecific, Cint, (Any,Any), a, b) != 0 +function args_morespecific(a, b) + sp = (ccall(:jl_type_morespecific, Cint, (Any,Any), a, b) != 0) + if sp # make sure morespecific(a,b) implies !morespecific(b,a) + @test ccall(:jl_type_morespecific, Cint, (Any,Any), b, a) == 0 + end + return sp +end let a = Tuple{Type{T1}, T1} where T1<:Integer b2 = Tuple{Type{T2}, Integer} where T2<:Integer @@ -65,6 +71,9 @@ _z_z_z_(::Int, c...) = 3 @test args_morespecific(Tuple{1,T} where T, Tuple{Any}) +# issue #21016 +@test args_morespecific(Tuple{IO, Core.TypeofBottom}, Tuple{IO, Type{T}} where T<:Number) + # with bound varargs _bound_vararg_specificity_1{T,N}(::Type{Array{T,N}}, d::Vararg{Int, N}) = 0 diff --git a/test/subtype.jl b/test/subtype.jl index 6dc034a72fb48..a4e92372be232 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -457,6 +457,9 @@ function test_Type() # issue #20476 @test issub(Tuple{Type{Union{Type{UInt32}, Type{UInt64}}}, Type{UInt32}}, Tuple{Type{T},T} where T) + + @test isequal_type(Core.TypeofBottom, Type{Union{}}) + @test issub(Core.TypeofBottom, Type{T} where T<:Real) end # old subtyping tests from test/core.jl From dfd8fc1f9067a4ec78dfdab0b36089842a10bab9 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sat, 25 Mar 2017 00:44:39 -0400 Subject: [PATCH 0273/1534] fix a method cache matching issue with Type{T} This is needed to avoid confusing `Type{A{B}}` and `Type{A{B} where B}`. In the future, this can be improved by not using `Type{ }` to dispatch types with free variables. --- src/typemap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/typemap.c b/src/typemap.c index 5274b7e96d697..0119678b92584 100644 --- a/src/typemap.c +++ b/src/typemap.c @@ -59,7 +59,7 @@ static int sig_match_by_type_simple(jl_value_t **types, size_t n, jl_tupletype_t return 0; } else { - if (!jl_types_equal(jl_tparam0(a), tp0)) + if (!(jl_typeof(jl_tparam0(a)) == jl_typeof(tp0) && jl_types_equal(jl_tparam0(a), tp0))) return 0; } } @@ -142,7 +142,7 @@ static inline int sig_match_simple(jl_value_t **args, size_t n, jl_value_t **sig return 0; } else { - if (a!=tp0 && !jl_types_equal(a,tp0)) + if (a!=tp0 && !(jl_typeof(a) == jl_typeof(tp0) && jl_types_equal(a,tp0))) return 0; } } From dae8fd8142356ed12c0a796bd37b502eb8bbc6d1 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 24 Mar 2017 16:43:26 -0400 Subject: [PATCH 0274/1534] add `serialize` for `Bottom` to ensure no `Type{<:T}` methods override it --- base/serialize.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/base/serialize.jl b/base/serialize.jl index 4fd98dd00e2d8..4210ff6130809 100644 --- a/base/serialize.jl +++ b/base/serialize.jl @@ -87,6 +87,7 @@ const DATATYPE_TAG = sertag(DataType) const TYPENAME_TAG = sertag(TypeName) const INT_TAG = sertag(Int) const GLOBALREF_TAG = sertag(GlobalRef) +const BOTTOM_TAG = sertag(Bottom) writetag(s::IO, tag) = write(s, UInt8(tag)) @@ -515,6 +516,8 @@ function serialize(s::AbstractSerializer, n::Int) write(s.io, n) end +serialize(s::AbstractSerializer, ::Type{Bottom}) = write_as_tag(s.io, BOTTOM_TAG) + serialize(s::AbstractSerializer, x::ANY) = serialize_any(s, x) function serialize_any(s::AbstractSerializer, x::ANY) From bd66c280b525a722763139041b1637fc46a74ec9 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sat, 25 Mar 2017 01:16:14 -0400 Subject: [PATCH 0275/1534] preserve identities of type wrappers in serializer. fixes #20324 --- base/serialize.jl | 44 ++++++++++++++++++++++++++++++++++++++++++++ test/serialize.jl | 13 +++++++++++++ 2 files changed, 57 insertions(+) diff --git a/base/serialize.jl b/base/serialize.jl index 4210ff6130809..df85a9659874b 100644 --- a/base/serialize.jl +++ b/base/serialize.jl @@ -88,6 +88,7 @@ const TYPENAME_TAG = sertag(TypeName) const INT_TAG = sertag(Int) const GLOBALREF_TAG = sertag(GlobalRef) const BOTTOM_TAG = sertag(Bottom) +const UNIONALL_TAG = sertag(UnionAll) writetag(s::IO, tag) = write(s, UInt8(tag)) @@ -518,6 +519,24 @@ end serialize(s::AbstractSerializer, ::Type{Bottom}) = write_as_tag(s.io, BOTTOM_TAG) +function serialize(s::AbstractSerializer, u::UnionAll) + writetag(s.io, UNIONALL_TAG) + n = 0; t = u + while isa(t, UnionAll) + t = t.body + n += 1 + end + if isa(t, DataType) && t === unwrap_unionall(t.name.wrapper) + write(s.io, UInt8(1)) + write(s.io, Int16(n)) + serialize(s, t) + else + write(s.io, UInt8(0)) + serialize(s, u.var) + serialize(s, u.body) + end +end + serialize(s::AbstractSerializer, x::ANY) = serialize_any(s, x) function serialize_any(s::AbstractSerializer, x::ANY) @@ -857,6 +876,31 @@ function deserialize_datatype(s::AbstractSerializer) deserialize(s, t) end +function deserialize(s::AbstractSerializer, ::Type{UnionAll}) + form = read(s.io, UInt8) + if form == 0 + var = deserialize(s) + body = deserialize(s) + return UnionAll(var, body) + else + n = read(s.io, Int16) + t = deserialize(s)::DataType + w = t.name.wrapper + k = 0 + while isa(w, UnionAll) + w = w.body + k += 1 + end + w = t.name.wrapper + k -= n + while k > 0 + w = w.body + k -= 1 + end + return w + end +end + function deserialize(s::AbstractSerializer, ::Type{Task}) t = Task(()->nothing) deserialize_cycle(s, t) diff --git a/test/serialize.jl b/test/serialize.jl index 76c19a7402d65..63aac82a3f55e 100644 --- a/test/serialize.jl +++ b/test/serialize.jl @@ -444,3 +444,16 @@ let a = ['T', 'e', 's', 't'] seek(f,0) @test deserialize(f) === :β end + +# issue #20324 +struct T20324{T} + x::T +end +let x = T20324[T20324(1) for i = 1:2] + b = IOBuffer() + serialize(b, x) + seekstart(b) + y = deserialize(b) + @test isa(y,Vector{T20324}) + @test y == x +end From 315ad9263ede35b527cb8723ad8f900550914ac2 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Sat, 25 Mar 2017 08:15:39 -0400 Subject: [PATCH 0276/1534] Run test/ambiguous.jl first works around #21160, hang in test that started happening when #20986 was merged --- base/channels.jl | 2 +- test/ambiguous.jl | 6 +++--- test/choosetests.jl | 12 ++++++++++-- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/base/channels.jl b/base/channels.jl index 7f9ae1f9c3708..28943d28922f5 100644 --- a/base/channels.jl +++ b/base/channels.jl @@ -374,7 +374,7 @@ function notify_error(c::Channel, err) notify_error(c.cond_take, err) notify_error(c.cond_put, err) - # release tasks on a `wait()/yielto()` call (on unbuffered channels) + # release tasks on a `wait()/yieldto()` call (on unbuffered channels) waiters = filter!(t->(t.state == :runnable), vcat(c.takers, c.putters)) foreach(t->schedule(t, err; error=true), waiters) end diff --git a/test/ambiguous.jl b/test/ambiguous.jl index 312f4ec6ce65d..43afcafc98c21 100644 --- a/test/ambiguous.jl +++ b/test/ambiguous.jl @@ -133,10 +133,10 @@ ambs = detect_ambiguities(Ambig5) @test length(ambs) == 2 # Test that Core and Base are free of ambiguities -# TODO jb/subtype: we now detect a lot more -@test !isempty(detect_ambiguities(Core, Base; imported=true, ambiguous_bottom=true)) -@test detect_ambiguities(Core, Base; imported=true, ambiguous_bottom=false) == [] # not using isempty so this prints more information when it fails +@test detect_ambiguities(Core, Base; imported=true, ambiguous_bottom=false) == [] +# some ambiguities involving Union{} type parameters are expected, but not required +@test !isempty(detect_ambiguities(Core, Base; imported=true, ambiguous_bottom=true)) amb_1(::Int8, ::Int) = 1 amb_1(::Integer, x) = 2 diff --git a/test/choosetests.jl b/test/choosetests.jl index c693ecdcaecba..1c820e38a7fce 100644 --- a/test/choosetests.jl +++ b/test/choosetests.jl @@ -46,7 +46,7 @@ function choosetests(choices = []) end if Base.USE_GPL_LIBS - testnames = [testnames, "fft", "dsp"; ] + append!(testnames, ["fft", "dsp"]) end if isdir(joinpath(JULIA_HOME, Base.DOCDIR, "examples")) @@ -115,7 +115,7 @@ function choosetests(choices = []) prepend!(tests, sparsetests) end - #do subarray before sparse but after linalg + # do subarray before sparse but after linalg if "subarray" in skip_tests filter!(x -> x != "subarray", tests) elseif "subarray" in tests @@ -143,6 +143,14 @@ function choosetests(choices = []) prepend!(tests, linalgtests) end + # do ambiguous first to avoid failing if ambiguities are introduced by other tests + if "ambiguous" in skip_tests + filter!(x -> x != "ambiguous", tests) + elseif "ambiguous" in tests + filter!(x -> x != "ambiguous", tests) + prepend!(tests, ["ambiguous"]) + end + net_required_for = ["socket", "distributed", "libgit2"] net_on = true try From f177e822d5c971b65b02cde210c67ad1eddbd19e Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sat, 25 Mar 2017 12:16:09 -0400 Subject: [PATCH 0277/1534] fix other part of #21147, optional instead of keyword args --- src/julia-syntax.scm | 29 +++++++++++++++-------------- test/keywordargs.jl | 5 +++++ 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 5ab1dec350f57..5f1912abe0848 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -469,16 +469,7 @@ ,(method-def-expr- name ;; remove sparams that don't occur, to avoid printing the warning twice - (let loop ((filtered '()) - (params positional-sparams)) - (cond ((null? params) - (reverse! filtered)) - ((or (expr-contains-eq (caar params) (cons 'list argl)) - (any (lambda (v) (expr-contains-eq (caar params) v)) - (cdr params))) - (loop (cons (car params) filtered) (cdr params))) - (else - (loop filtered (cdr params))))) + (filter-sparams (cons 'list argl) positional-sparams) `((|::| ;; if there are optional positional args, we need to be able to reference the function name ,(if (any kwarg? pargl) (gensy) UNUSED) @@ -564,16 +555,26 @@ (cdr body)) '())) +;; keep only sparams used by `expr` or other sparams +(define (filter-sparams expr sparams) + (let loop ((filtered '()) + (params sparams)) + (cond ((null? params) + (reverse! filtered)) + ((or (expr-contains-eq (caar params) expr) + (any (lambda (v) (expr-contains-eq (caar params) v)) + (cdr params))) + (loop (cons (car params) filtered) (cdr params))) + (else + (loop filtered (cdr params)))))) + (define (optional-positional-defs name sparams req opt dfl body isstaged overall-argl rett) (let ((prologue (extract-method-prologue body))) `(block ,@(map (lambda (n) (let* ((passed (append req (list-head opt n))) ;; only keep static parameters used by these arguments - (sp (filter (lambda (sp) - (contains (lambda (e) (eq? e (car sp))) - passed)) - sparams)) + (sp (filter-sparams (cons 'list passed) sparams)) (vals (list-tail dfl n)) (absent (list-tail opt n)) ;; absent arguments (body diff --git a/test/keywordargs.jl b/test/keywordargs.jl index 5cb556b3a11c7..5045cff21a8cc 100644 --- a/test/keywordargs.jl +++ b/test/keywordargs.jl @@ -265,3 +265,8 @@ function f21147(f::Tuple{A}; kwargs...) where {B,A<:Tuple{B}} end @test f21147(((1,),)) === Int @test f21147(((1,),), k = 2) === Int +function g21147(f::Tuple{A}, k = 2) where {B,A<:Tuple{B}} + return B +end +@test g21147(((1,),)) === Int +@test g21147(((1,),), 2) === Int From fb312c40aa25e492c71648ecdc124af73a09993a Mon Sep 17 00:00:00 2001 From: Alexey Stukalov Date: Sat, 25 Mar 2017 23:14:56 +0100 Subject: [PATCH 0278/1534] Fix mapreduce_impl() for 1-element range (#19325) * fix mapreduce_impl() for 1-element range * mapreduce_impl() type stability tests * wrap long lines * mapreduce_impl(): add @inbounds ifirst:ilast should be a valid A indices range (checked by the caller) * reduce code duplication in _mapreduce() - let mapreduce_impl() handle all but empty collection cases - don't test mapreduce_impl() directly - extend mapreduce() tests with empty/long collections * mapreduce_impl(f, min/max): don't skip NaNs - update mapreduce_impl(f, min/max) to 0.6 behaviour of treating NaNs, also stop scanning the array once NaN is detected - add NaN minimum/maximum() tests for 2-element and long arrays * mapreduce(f, op): don't apply @inbounds for `f` * clarify how mapreduce_impl() should be used --- base/reduce.jl | 59 ++++++++++++++++++++------------------------------ test/reduce.jl | 37 ++++++++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 37 deletions(-) diff --git a/base/reduce.jl b/base/reduce.jl index 4aaf7c8952b1a..e68def11e1284 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -167,15 +167,25 @@ foldr(op, itr) = mapfoldr(identity, op, itr) ## reduce & mapreduce +# `mapreduce_impl()` is called by `mapreduce()` (via `_mapreduce()`, when `A` +# supports linear indexing) and does actual calculations (for `A[ifirst:ilast]` subset). +# For efficiency, no parameter validity checks are done, it's the caller responsibility. +# `ifirst:ilast` range is assumed to be a valid non-empty subset of `A` indices. + +# This is a generic implementation of `mapreduce_impl()`, +# certain `op` (e.g. `min` and `max`) may have their own specialized versions. function mapreduce_impl(f, op, A::AbstractArray, ifirst::Integer, ilast::Integer, blksize::Int=pairwise_blocksize(f, op)) - if ifirst + blksize > ilast + if ifirst == ilast + @inbounds a1 = A[ifirst] + return r_promote(op, f(a1)) + elseif ifirst + blksize > ilast # sequential portion - fx1 = r_promote(op, f(A[ifirst])) - fx2 = r_promote(op, f(A[ifirst + 1])) - v = op(fx1, fx2) + @inbounds a1 = A[ifirst] + @inbounds a2 = A[ifirst+1] + v = op(r_promote(op, f(a1)), r_promote(op, f(a2))) @simd for i = ifirst + 2 : ilast - @inbounds Ai = A[i] - v = op(v, f(Ai)) + @inbounds ai = A[i] + v = op(v, f(ai)) end return v else @@ -250,26 +260,8 @@ _mapreduce(f, op, A::AbstractArray) = _mapreduce(f, op, IndexStyle(A), A) function _mapreduce{T}(f, op, ::IndexLinear, A::AbstractArray{T}) inds = linearindices(A) - n = length(inds) - @inbounds begin - if n == 0 - return mr_empty(f, op, T) - elseif n == 1 - return r_promote(op, f(A[inds[1]])) - elseif n < 16 - fx1 = r_promote(op, f(A[inds[1]])) - fx2 = r_promote(op, f(A[inds[2]])) - s = op(fx1, fx2) - i = inds[2] - while i < last(inds) - Ai = A[i+=1] - s = op(s, f(Ai)) - end - return s - else - return mapreduce_impl(f, op, A, first(inds), last(inds)) - end - end + length(inds) > 0 ? mapreduce_impl(f, op, A, first(inds), last(inds)) : + mr_empty(f, op, T) end _mapreduce(f, op, ::IndexCartesian, A::AbstractArray) = mapfoldl(f, op, A) @@ -415,17 +407,12 @@ function mapreduce_impl(f, op::Union{typeof(scalarmax), typeof(min)}, A::AbstractArray, first::Int, last::Int) # locate the first non NaN number - v = f(A[first]) + @inbounds a1 = A[first] + v = f(a1) i = first + 1 - while v != v && i <= last - @inbounds Ai = A[i] - v = f(Ai) - i += 1 - end - while i <= last - @inbounds Ai = A[i] - x = f(Ai) - v = op(v, x) + while (v == v) && (i <= last) + @inbounds ai = A[i] + v = op(v, f(ai)) i += 1 end v diff --git a/test/reduce.jl b/test/reduce.jl index 87bd3361cfe2a..9bd2130a6c5bb 100644 --- a/test/reduce.jl +++ b/test/reduce.jl @@ -26,7 +26,7 @@ @test Base.mapfoldr(abs2, -, 2:5) == -14 @test Base.mapfoldr(abs2, -, 10, 2:5) == -4 -# reduce & mapreduce +# reduce @test reduce(+, Int64[]) === Int64(0) # In reference to issue #20144 (PR #20160) @test reduce(+, Int16[]) === Int32(0) @test reduce((x,y)->"($x+$y)", 9:11) == "((9+10)+11)" @@ -34,9 +34,32 @@ @test reduce(+, 1000, 1:5) == (1000 + 1 + 2 + 3 + 4 + 5) @test reduce(+,1) == 1 +# mapreduce @test mapreduce(-, +, [-10 -9 -3]) == ((10 + 9) + 3) @test mapreduce((x)->x[1:3], (x,y)->"($x+$y)", ["abcd", "efgh", "01234"]) == "((abc+efg)+012)" +# mapreduce() for 1- 2- and n-sized blocks (PR #19325) +@test mapreduce(-, +, [-10]) == 10 +@test mapreduce(abs2, +, [-9, -3]) == 81 + 9 +@test mapreduce(-, +, [-9, -3, -4, 8, -2]) == (9 + 3 + 4 - 8 + 2) +@test mapreduce(-, +, collect(linspace(1.0, 10000.0, 10000))) == -50005000.0 +# mapreduce() type stability +@test typeof(mapreduce(*, +, Int8[10])) === + typeof(mapreduce(*, +, Int8[10, 11])) === + typeof(mapreduce(*, +, Int8[10, 11, 12, 13])) +@test typeof(mapreduce(*, +, Float32[10.0])) === + typeof(mapreduce(*, +, Float32[10, 11])) === + typeof(mapreduce(*, +, Float32[10, 11, 12, 13])) +# mapreduce() type stability when f supports empty collections +@test typeof(mapreduce(abs, +, Int8[])) === + typeof(mapreduce(abs, +, Int8[10])) === + typeof(mapreduce(abs, +, Int8[10, 11])) === + typeof(mapreduce(abs, +, Int8[10, 11, 12, 13])) +@test typeof(mapreduce(abs, +, Float32[])) === + typeof(mapreduce(abs, +, Float32[10])) === + typeof(mapreduce(abs, +, Float32[10, 11])) === + typeof(mapreduce(abs, +, Float32[10, 11, 12, 13])) + # sum @test sum(Int8[]) === Int32(0) @@ -146,6 +169,10 @@ prod2(itr) = invoke(prod, Tuple{Any}, itr) @test isnan(minimum([NaN])) @test isequal(extrema([NaN]), (NaN, NaN)) +@test isnan(maximum([NaN, 2.])) +@test isnan(minimum([NaN, 2.])) +@test isequal(extrema([NaN, 2.]), (NaN,NaN)) + @test isnan(maximum([NaN, 2., 3.])) @test isnan(minimum([NaN, 2., 3.])) @test isequal(extrema([NaN, 2., 3.]), (NaN,NaN)) @@ -154,6 +181,14 @@ prod2(itr) = invoke(prod, Tuple{Any}, itr) @test isnan(minimum([4., 3., NaN, 5., 2.])) @test isequal(extrema([4., 3., NaN, 5., 2.]), (NaN,NaN)) + # test long arrays +@test isnan(maximum([NaN; 1.:10000.])) +@test isnan(maximum([1.:10000.; NaN])) +@test isnan(minimum([NaN; 1.:10000.])) +@test isnan(minimum([1.:10000.; NaN])) +@test isequal(extrema([1.:10000.; NaN]), (NaN,NaN)) +@test isequal(extrema([NaN; 1.:10000.]), (NaN,NaN)) + @test maximum(abs2, 3:7) == 49 @test minimum(abs2, 3:7) == 9 From e3e912ab76a2e150e7ed28a2bfb51df8be333347 Mon Sep 17 00:00:00 2001 From: Chris Foster Date: Sun, 26 Mar 2017 13:08:26 +1000 Subject: [PATCH 0279/1534] DefaultTestSet tests for test_broken and test_skip (#21086) * DefaultTestSet tests for test_broken and test_skip Check that test_broken and test_skip do not result in an exception. Already fixed in 8982605 - "Rework test framework", but present in julia-0.5 (see #21008). * Cleanup: use isa rather than typeof --- test/test.jl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/test.jl b/test/test.jl index cdd45a37ff980..36ca3498929fb 100644 --- a/test/test.jl +++ b/test/test.jl @@ -257,6 +257,18 @@ end @test counter_17462_pre == 3 @test counter_17462_post == 1 +# Issue #21008 +ts = try + @testset "@test_broken and @test_skip should not give an exception" begin + @test_broken false + @test_skip true + @test_skip false + end +catch + nothing # Shouldn't get here +end +@test ts isa Base.Test.DefaultTestSet + # now we're done running tests with DefaultTestSet so we can go back to STDOUT redirect_stdout(OLD_STDOUT) redirect_stderr(OLD_STDERR) From 2f02df964be00669a568c499335acc7fe2a7b41d Mon Sep 17 00:00:00 2001 From: m-j-w Date: Sun, 26 Mar 2017 22:42:32 +0200 Subject: [PATCH 0280/1534] Correct anchors in README.md (#21166) * Move manual anchors in README.md below headlines. Alternative approach to make GitHub correctly render the `README.md` headlines by simply moving the manual anchors to below the headlines. Since current manual anchors are uppercase, this keeps external links valid. * Remove manual HTML anchors from README.md. The `README.md` is currently rendered incorrectly on GitHub since it includes manual HTML anchors for headlines. However, since several years, GitHub automatically includes these anchors. Considering the anchors in the README.md have been added some six years ago, the GitHub feature is probably younger. This removes all the manual anchors, for which all match the exact headline pattern anyway, except the following which differ slightly: - `` - `` - `` If referenced from somewher externally, these would need to be updated. Links within this README to anchors are also corrected. The automatically generated anchors on GitHub follow the pattern of replacing all spaces with `-` and everything being lowercase, e.g. `## This is a Title` automatically gets the anchor equivalent to `` to be referenced in markdown with `[Link to a title](#this-is-a-title)`. --- README.md | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 43e19ece0f37e..05c022f575aee 100644 --- a/README.md +++ b/README.md @@ -11,14 +11,12 @@ Windows: [![Build status](https://ci.appveyor.com/api/projects/status/dvial98s5v Code Coverage: [![Coverage Status](https://coveralls.io/repos/JuliaLang/julia/badge.svg?branch=master)](https://coveralls.io/r/JuliaLang/julia?branch=master) [![codecov.io](http://codecov.io/github/JuliaLang/julia/coverage.svg?branch=master)](http://codecov.io/github/JuliaLang/julia?branch=master) - ## The Julia Language Julia is a high-level, high-performance dynamic language for technical computing. The main homepage for Julia can be found at [julialang.org](http://julialang.org/). This is the GitHub repository of Julia source code, including instructions for compiling and installing Julia, below. - ## Resources - **Homepage:** @@ -36,14 +34,12 @@ This is the GitHub repository of Julia source code, including instructions for c New developers may find the notes in [CONTRIBUTING](https://github.com/JuliaLang/julia/blob/master/CONTRIBUTING.md) helpful to start contributing to the Julia codebase. ### External Resources - - [**StackOverflow**](https://stackoverflow.com/questions/tagged/julia-lang) - [**Youtube**](https://www.youtube.com/channel/UC9IuUwwE2xdjQUT_LMLONoA) - [**Twitter**](https://twitter.com/JuliaLanguage) - [**Meetup**](http://julia.meetup.com/) - ## Currently Supported Platforms - **Linux** @@ -53,10 +49,9 @@ New developers may find the notes in [CONTRIBUTING](https://github.com/JuliaLang All systems are supported with both x86/64 (64-bit) and x86 (32-bit, except MacOS) architectures. Support for [ARM](https://github.com/JuliaLang/julia/blob/master/README.arm.md), AARCH64, and POWER8 (little-endian) has been added recently. - ## Source Download and Compilation -First, make sure you have all the [required dependencies](#Required-Build-Tools-External-Libraries) installed. +First, make sure you have all the [required dependencies](#required-build-tools-and-external-libraries) installed. Then, acquire the source code by cloning the git repository: git clone git://github.com/JuliaLang/julia.git @@ -72,7 +67,7 @@ By default you will be building the latest unstable version of Julia. However, m git checkout release-0.5 Now run `make` to build the `julia` executable. To perform a parallel build, use `make -j N` and supply the maximum number of concurrent processes. (See [Platform Specific Build Notes](https://github.com/JuliaLang/julia#platform-specific-build-notes) for details.) -When compiled the first time, it will automatically download and build its [external dependencies](#Required-Build-Tools-External-Libraries). +When compiled the first time, it will automatically download and build its [external dependencies](#required-build-tools-and-external-libraries). This takes a while, but only has to be done once. If the defaults in the build do not work for you, and you need to set specific make parameters, you can save them in `Make.user`. The build will automatically check for the existence of `Make.user` and use it if it exists. Building Julia requires 1.5GiB of disk space and approximately 700MiB of virtual memory. @@ -171,12 +166,10 @@ latest version. - ## Uninstalling Julia Julia does not install anything outside the directory it was cloned into. Julia can be completely uninstalled by deleting this directory. Julia packages are installed in `~/.julia` by default, and can be uninstalled by deleting `~/.julia`. - ## Platform-Specific Build Notes ### Linux @@ -186,7 +179,7 @@ Julia does not install anything outside the directory it was cloned into. Julia * GCC version 4.7 or later is required to build Julia. * To use external shared libraries not in the system library search path, set `USE_SYSTEM_XXX=1` and `LDFLAGS=-Wl,-rpath,/path/to/dir/contains/libXXX.so` in `Make.user`. * Instead of setting `LDFLAGS`, putting the library directory into the environment variable `LD_LIBRARY_PATH` (at both compile and run time) also works. -* See also the [external dependencies](#Required-Build-Tools-External-Libraries). +* See also the [external dependencies](#required-build-tools-and-external-libraries). #### Architecture Customization @@ -199,7 +192,7 @@ You can also set `MARCH=native` for a maximum-performance build customized for t #### Ubuntu -The [julia-deps PPA](https://launchpad.net/~staticfloat/+archive/julia-deps/) contains updated packages for Julia dependencies if you want to use system libraries instead of having them downloaded and built during the build process. See [System Provided Libraries](#System-Provided-Libraries). +The [julia-deps PPA](https://launchpad.net/~staticfloat/+archive/julia-deps/) contains updated packages for Julia dependencies if you want to use system libraries instead of having them downloaded and built during the build process. See [System Provided Libraries](#system-provided-libraries). #### RHEL/CentOS 6 @@ -255,7 +248,6 @@ In order to build Julia on Windows, see [README.windows](https://github.com/Juli Julia can be developed in an isolated Vagrant environment. See [the Vagrant README](https://github.com/JuliaLang/julia/blob/master/contrib/vagrant/README.md) for details. - ## Required Build Tools and External Libraries Building Julia requires that the following software be installed: @@ -333,7 +325,6 @@ Julia uses the following external libraries, which are automatically downloaded [mbedtls]: https://tls.mbed.org/ [pkg-config]: https://www.freedesktop.org/wiki/Software/pkg-config/ - ### System Provided Libraries If you already have one or more of these packages installed on your system, you can prevent Julia from compiling duplicates of these libraries by passing `USE_SYSTEM_...=1` to `make` or adding the line to `Make.user`. The complete list of possible flags can be found in `Make.inc`. @@ -365,7 +356,6 @@ Add the following to the `Make.user` file: It is highly recommended to start with a fresh clone of the Julia repository. - ## Source Code Organization The Julia source code is organized as follows: @@ -382,7 +372,6 @@ The Julia source code is organized as follows: ui/ source for various front ends usr/ binaries and shared libraries loaded by Julia's standard libraries - ## Binary Installation If you would rather not compile the latest Julia from source, platform-specific tarballs with pre-compiled binaries are also [available for download](http://julialang.org/downloads/). @@ -420,7 +409,6 @@ The following distributions include julia, but the versions may be out of date d * [MacPorts](https://trac.macports.org/browser/trunk/dports/lang/julia/Portfile) * [OS X Homebrew Tap](https://github.com/staticfloat/homebrew-julia/) - ## Editor and Terminal Setup Currently, Julia editing mode support is available for a number of From 55f44179b9f9c75f8587c19f62cc17f031f5e3fd Mon Sep 17 00:00:00 2001 From: Alexey Stukalov Date: Mon, 27 Mar 2017 02:01:56 +0200 Subject: [PATCH 0281/1534] handle small (<16) arrays by _mapreduce() (#21167) --- base/reduce.jl | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/base/reduce.jl b/base/reduce.jl index e68def11e1284..b8ab9f5a18a3d 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -260,8 +260,25 @@ _mapreduce(f, op, A::AbstractArray) = _mapreduce(f, op, IndexStyle(A), A) function _mapreduce{T}(f, op, ::IndexLinear, A::AbstractArray{T}) inds = linearindices(A) - length(inds) > 0 ? mapreduce_impl(f, op, A, first(inds), last(inds)) : - mr_empty(f, op, T) + n = length(inds) + if n == 0 + return mr_empty(f, op, T) + elseif n == 1 + @inbounds a1 = A[inds[1]] + return r_promote(op, f(a1)) + elseif n < 16 # process short array here, avoid mapreduce_impl() compilation + @inbounds i = inds[1] + @inbounds a1 = A[i] + @inbounds a2 = A[i+=1] + s = op(r_promote(op, f(a1)), r_promote(op, f(a2))) + while i < last(inds) + @inbounds Ai = A[i+=1] + s = op(s, f(Ai)) + end + return s + else + return mapreduce_impl(f, op, A, first(inds), last(inds)) + end end _mapreduce(f, op, ::IndexCartesian, A::AbstractArray) = mapfoldl(f, op, A) From 46df7878dfdcbf4158f93f93592b451cdb1b5ee6 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Mon, 27 Mar 2017 10:56:24 +0100 Subject: [PATCH 0282/1534] deprecate use of cat with LibGit2 objects --- base/deprecated.jl | 11 ++++++++++- base/libgit2/libgit2.jl | 12 +----------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index 3524b4f1f28a6..56d281665804a 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1138,8 +1138,17 @@ end @deprecate revparse(repo::GitRepo, objname::AbstractString) GitObject(repo, objname) false @deprecate object(repo::GitRepo, te::GitTreeEntry) GitObject(repo, te) false @deprecate commit(ann::GitAnnotated) GitHash(ann) false - @deprecate cat{T<:GitObject}(repo::GitRepo, ::Type{T}, object::AbstractString) cat(repo, object) @deprecate lookup(repo::GitRepo, oid::GitHash) GitBlob(repo, oid) false + function Base.cat{T<:GitObject}(repo::GitRepo, ::Type{T}, object::AbstractString) + Base.depwarn("cat(repo::GitRepo, T, spec) is deprecated, use content(T(repo, spec))", :cat) + try + return content(GitBlob(repo, spec)) + catch e + isa(e, LibGit2.GitError) && return nothing + rethrow(e) + end + end + Base.cat(repo::GitRepo, object::AbstractString) = cat(repo, GitBlob, object) end # when this deprecation is deleted, remove all calls to it, and all diff --git a/base/libgit2/libgit2.jl b/base/libgit2/libgit2.jl index 8ccf350274bd7..e05b5f3fd5bc7 100644 --- a/base/libgit2/libgit2.jl +++ b/base/libgit2/libgit2.jl @@ -2,7 +2,7 @@ module LibGit2 -import Base: merge!, cat, == +import Base: merge!, == export with, GitRepo, GitConfig @@ -495,16 +495,6 @@ Equivalent to `git reset [--soft | --mixed | --hard] `. reset!(repo::GitRepo, id::GitHash, mode::Cint = Consts.RESET_MIXED) = reset!(repo, GitObject(repo, id), mode) -""" git cat-file """ -function cat(repo::GitRepo, spec::Union{AbstractString,AbstractGitHash}) - obj = GitObject(repo, spec) - if isa(obj, GitBlob) - content(obj) - else - nothing - end -end - """ git rev-list --count """ function revcount(repo::GitRepo, fst::AbstractString, snd::AbstractString) fst_id = revparseid(repo, fst) From caff424ef73c130466be633815be25b9708c30e7 Mon Sep 17 00:00:00 2001 From: Jane Herriman Date: Mon, 27 Mar 2017 05:55:30 -0700 Subject: [PATCH 0283/1534] Augment sort.jl documentation with doctests (#18923) --- base/sort.jl | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/base/sort.jl b/base/sort.jl index 78330f425d8cc..6f014276f09ee 100644 --- a/base/sort.jl +++ b/base/sort.jl @@ -72,6 +72,9 @@ true julia> issorted([(1, "b"), (2, "a")], by = x -> x[2]) false + +julia> issorted([(1, "b"), (2, "a")], by = x -> x[2], rev=true) +true ``` """ issorted(itr; @@ -742,6 +745,28 @@ end Sort the rows of matrix `A` lexicographically. See [`sort!`](@ref) for a description of possible keyword arguments. + +# Examples + +```jldoctest +julia> sortrows([7 3 5; -1 6 4; 9 -2 8]) +3×3 Array{Int64,2}: + -1 6 4 + 7 3 5 + 9 -2 8 + +julia> sortrows([7 3 5; -1 6 4; 9 -2 8], lt=(x,y)->isless(x[2],y[2])) +3×3 Array{Int64,2}: + 9 -2 8 + 7 3 5 + -1 6 4 + +julia> sortrows([7 3 5; -1 6 4; 9 -2 8], rev=true) +3×3 Array{Int64,2}: + 9 -2 8 + 7 3 5 + -1 6 4 +``` """ function sortrows(A::AbstractMatrix; kws...) inds = indices(A,1) @@ -760,6 +785,28 @@ end Sort the columns of matrix `A` lexicographically. See [`sort!`](@ref) for a description of possible keyword arguments. + +# Examples + +```jldoctest +julia> sortcols([7 3 5; 6 -1 -4; 9 -2 8]) +3×3 Array{Int64,2}: + 3 5 7 + -1 -4 6 + -2 8 9 + +julia> sortcols([7 3 5; 6 -1 -4; 9 -2 8], alg=InsertionSort, lt=(x,y)->isless(x[2],y[2])) +3×3 Array{Int64,2}: + 5 3 7 + -4 -1 6 + 8 -2 9 + +julia> sortcols([7 3 5; 6 -1 -4; 9 -2 8], rev=true) +3×3 Array{Int64,2}: + 7 5 3 + 6 -4 -1 + 9 8 -2 +``` """ function sortcols(A::AbstractMatrix; kws...) inds = indices(A,2) From f65b8aba9abb9f0bd0f2da5fba8cc3eb1475cef1 Mon Sep 17 00:00:00 2001 From: Helge Eichhorn Date: Mon, 27 Mar 2017 15:16:08 +0200 Subject: [PATCH 0284/1534] Fix doc system part of #21016 (#21036) * Breakage. * Teach doc system to handle 'where'. * Add parameters to signature. * Add test and continue to use Union. * Fix missing docstrings. * Address comments. * use newest Documenter, DocStringExtensions --- base/docs/Docs.jl | 29 ++++++++++++++++++----------- doc/REQUIRE | 6 +++--- doc/src/stdlib/arrays.md | 2 +- doc/src/stdlib/dates.md | 2 +- test/docs.jl | 40 +++++++++++++++++++++++++++++++++++++++- 5 files changed, 62 insertions(+), 17 deletions(-) diff --git a/base/docs/Docs.jl b/base/docs/Docs.jl index 5c112ea32f698..2e7a47946a464 100644 --- a/base/docs/Docs.jl +++ b/base/docs/Docs.jl @@ -78,7 +78,7 @@ function initmeta(m::Module = current_module()) nothing end -function signature(expr::Expr) +function signature!(tv, expr::Expr) if isexpr(expr, [:call, :macrocall]) sig = :(Union{Tuple{}}) for arg in expr.args[2:end] @@ -88,16 +88,26 @@ function signature(expr::Expr) end push!(sig.args[end].args, argtype(arg)) end - tv = typevars(expr) + if isexpr(expr.args[1], :curly) && isempty(tv) + append!(tv, tvar.(expr.args[1].args[2:end])) + end + for i = length(tv):-1:1 + push!(sig.args, :(Tuple{$(tv[i].args[1])})) + end for i = length(tv):-1:1 sig = Expr(:where, sig, tv[i]) end sig + elseif isexpr(expr, :where) + append!(tv, tvar.(expr.args[2:end])) + signature!(tv, expr.args[1]) else - signature(expr.args[1]) + signature!(tv, expr.args[1]) end end -signature(other) = :(Union{}) +signature!(tv, other) = :(Union{}) +signature(expr::Expr) = signature!([], expr) +signature(other) = signature!([], other) function argtype(expr::Expr) isexpr(expr, :(::)) && return expr.args[end] @@ -106,11 +116,8 @@ function argtype(expr::Expr) end argtype(other) = :Any -function typevars(expr::Expr) - isexpr(expr, :curly) && return expr.args[2:end] - typevars(expr.args[1]) -end -typevars(::Symbol) = [] +tvar(x::Expr) = x +tvar(s::Symbol) = :($s <: Any) # Docsystem types. # ================ @@ -195,7 +202,7 @@ is stored as `Tuple{Any, Any}` in the `MultiDoc` while f{T}(x::T, y = ?) = ... -is stored as `Union{Tuple{T}, Tuple{T, Any}}`. +is stored as `Union{Tuple{T, Any}, Tuple{T}} where T`. Note: The `Function`/`DataType` object's signature is always `Union{}`. """ @@ -627,7 +634,7 @@ isquotedmacrocall(x) = isexpr(x.args[1].value, :macrocall, 1) # Simple expressions / atoms the may be documented. isbasicdoc(x) = isexpr(x, :.) || isa(x, Union{QuoteNode, Symbol}) -is_signature(x) = isexpr(x, :call) || (isexpr(x, :(::), 2) && isexpr(x.args[1], :call)) +is_signature(x) = isexpr(x, :call) || (isexpr(x, :(::), 2) && isexpr(x.args[1], :call)) || isexpr(x, :where) function docm(meta, ex, define = true) # Some documented expressions may be decorated with macro calls which obscure the actual diff --git a/doc/REQUIRE b/doc/REQUIRE index aef596ad84444..04046565e012b 100644 --- a/doc/REQUIRE +++ b/doc/REQUIRE @@ -1,3 +1,3 @@ -Compat 0.20.0 0.20.0+ -DocStringExtensions 0.3.1 0.3.1+ -Documenter 0.9.1 0.9.1+ +Compat 0.21.0 0.21.0+ +DocStringExtensions 0.3.2 0.3.2+ +Documenter 0.9.2 0.9.2+ diff --git a/doc/src/stdlib/arrays.md b/doc/src/stdlib/arrays.md index 87c06ac591ebb..cb3468061dbc4 100644 --- a/doc/src/stdlib/arrays.md +++ b/doc/src/stdlib/arrays.md @@ -147,7 +147,7 @@ Base.sum_kbn Base.Random.randperm Base.invperm Base.isperm -Base.permute!{T}(::Any, ::AbstractArray{T, 1}) +Base.permute!(::Any, ::AbstractVector) Base.ipermute! Base.Random.randcycle Base.Random.shuffle diff --git a/doc/src/stdlib/dates.md b/doc/src/stdlib/dates.md index 2b9df1820bdad..64b27a37c4b52 100644 --- a/doc/src/stdlib/dates.md +++ b/doc/src/stdlib/dates.md @@ -117,7 +117,7 @@ Base.Dates.toprev(::Function, ::Base.Dates.TimeType) ```@docs Base.Dates.Period(::Any) -Base.Dates.CompoundPeriod{P <: Base.Dates.Period}(::Array{P,1}) +Base.Dates.CompoundPeriod(::Vector{<:Base.Dates.Period}) Base.Dates.default ``` diff --git a/test/docs.jl b/test/docs.jl index 21467e68ffae5..d851b662215da 100644 --- a/test/docs.jl +++ b/test/docs.jl @@ -602,7 +602,7 @@ Base.collect{T}(::Type{EmptyType{T}}) = "borked" end let fd = meta(I12515)[@var(Base.collect)] - @test fd.order[1] == (Tuple{Type{I12515.EmptyType{T}}} where T) + @test fd.order[1] == (Union{Tuple{Type{I12515.EmptyType{T}}}, Tuple{T}} where T) end # PR #12593 @@ -959,3 +959,41 @@ dynamic_test.x = "test 2" @test Text("docstring1") ≠ Text("docstring2") @test hash(Text("docstring1")) ≠ hash(Text("docstring2")) @test hash(Text("docstring")) ≠ hash(HTML("docstring")) + +# issue 21016 +module I21016 + +struct Struct{T} +end + +"String 1" +function Struct{T}(arg1) where T<:Float64 +end + +"String 2" +function Struct{T}(arg1) where T +end + +"String 3" +function Struct{T}(arg1) where Integer <: T <: Real +end + +"String 4" +function Struct{T}(arg1) where T >: Int +end + +end + +@test docstrings_equal( + @doc(I21016.Struct), + doc""" + String 1 + + String 2 + + String 3 + + String 4 + """ +) + From 0c5128f0a1974a4094a940bcb02a9b2a57e992bf Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Mon, 27 Mar 2017 09:40:20 -0400 Subject: [PATCH 0285/1534] Use separate build dirs for mbedtls depending on USE_GPL_LIBS prevents cmake from complaining when you switch sources for the same build dir --- deps/mbedtls.mk | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/deps/mbedtls.mk b/deps/mbedtls.mk index f1f7b88d3ec3b..4199c947779ab 100644 --- a/deps/mbedtls.mk +++ b/deps/mbedtls.mk @@ -36,19 +36,19 @@ $(SRCDIR)/srccache/$(MBEDTLS_SRC)/source-extracted: $(SRCDIR)/srccache/$(MBEDTLS $(SRCDIR)/srccache/$(MBEDTLS_SRC)/mbedtls-ssl.h.patch-applied: $(SRCDIR)/srccache/$(MBEDTLS_SRC)/source-extracted cd $(SRCDIR)/srccache/$(MBEDTLS_SRC)/include/mbedtls && patch -p0 -f < $(SRCDIR)/patches/mbedtls-ssl.h.patch echo 1 > $@ -$(BUILDDIR)/mbedtls-$(MBEDTLS_VER)/build-configured: $(SRCDIR)/srccache/$(MBEDTLS_SRC)/mbedtls-ssl.h.patch-applied +$(BUILDDIR)/$(MBEDTLS_SRC)/build-configured: $(SRCDIR)/srccache/$(MBEDTLS_SRC)/mbedtls-ssl.h.patch-applied -$(BUILDDIR)/mbedtls-$(MBEDTLS_VER)/build-configured: $(SRCDIR)/srccache/$(MBEDTLS_SRC)/source-extracted +$(BUILDDIR)/$(MBEDTLS_SRC)/build-configured: $(SRCDIR)/srccache/$(MBEDTLS_SRC)/source-extracted mkdir -p $(dir $@) cd $(dir $@) && \ $(CMAKE) $(dir $<) $(MBEDTLS_OPTS) echo 1 > $@ -$(BUILDDIR)/mbedtls-$(MBEDTLS_VER)/build-compiled: $(BUILDDIR)/mbedtls-$(MBEDTLS_VER)/build-configured +$(BUILDDIR)/$(MBEDTLS_SRC)/build-compiled: $(BUILDDIR)/$(MBEDTLS_SRC)/build-configured $(MAKE) -C $(dir $<) echo 1 > $@ -$(BUILDDIR)/mbedtls-$(MBEDTLS_VER)/build-checked: $(BUILDDIR)/mbedtls-$(MBEDTLS_VER)/build-compiled +$(BUILDDIR)/$(MBEDTLS_SRC)/build-checked: $(BUILDDIR)/$(MBEDTLS_SRC)/build-compiled ifeq ($(OS),$(BUILD_OS)) $(MAKE) -C $(dir $@) test endif @@ -67,7 +67,7 @@ define MBEDTLS_INSTALL endef endif $(eval $(call staged-install, \ - mbedtls,mbedtls-$(MBEDTLS_VER), \ + mbedtls,$(MBEDTLS_SRC), \ MBEDTLS_INSTALL,,, \ $$(INSTALL_NAME_CMD)libmbedx509.$$(SHLIB_EXT) $$(build_shlibdir)/libmbedx509.$$(SHLIB_EXT) && \ $$(INSTALL_NAME_CMD)libmbedtls.$$(SHLIB_EXT) $$(build_shlibdir)/libmbedtls.$$(SHLIB_EXT) && \ @@ -78,20 +78,20 @@ $(eval $(call staged-install, \ clean-mbedtls: - -rm $(BUILDDIR)/mbedtls-$(MBEDTLS_VER)/build-configured \ - $(BUILDDIR)/mbedtls-$(MBEDTLS_VER)/build-compiled - -$(MAKE) -C $(BUILDDIR)/mbedtls-$(MBEDTLS_VER) clean + -rm $(BUILDDIR)/$(MBEDTLS_SRC)/build-configured \ + $(BUILDDIR)/$(MBEDTLS_SRC)/build-compiled + -$(MAKE) -C $(BUILDDIR)/$(MBEDTLS_SRC) clean distclean-mbedtls: -rm -rf $(SRCDIR)/srccache/$(MBEDTLS_SRC).tgz \ $(SRCDIR)/srccache/$(MBEDTLS_SRC) \ - $(BUILDDIR)/mbedtls-$(MBEDTLS_VER) + $(BUILDDIR)/$(MBEDTLS_SRC) get-mbedtls: $(SRCDIR)/srccache/$(MBEDTLS_SRC).tgz extract-mbedtls: $(SRCDIR)/srccache/$(MBEDTLS_SRC)/source-extracted -configure-mbedtls: $(BUILDDIR)/mbedtls-$(MBEDTLS_VER)/build-configured -compile-mbedtls: $(BUILDDIR)/mbedtls-$(MBEDTLS_VER)/build-compiled +configure-mbedtls: $(BUILDDIR)/$(MBEDTLS_SRC)/build-configured +compile-mbedtls: $(BUILDDIR)/$(MBEDTLS_SRC)/build-compiled # tests disabled since they are known to fail fastcheck-mbedtls: #check-mbedtls -check-mbedtls: $(BUILDDIR)/mbedtls-$(MBEDTLS_VER)/build-checked +check-mbedtls: $(BUILDDIR)/$(MBEDTLS_SRC)/build-checked From 86d56239bb3a9cc6e6687958c578578b957dd8a2 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Mon, 27 Mar 2017 09:41:00 -0400 Subject: [PATCH 0286/1534] Fix doctest line numbers --- base/channels.jl | 4 ++-- base/reduce.jl | 2 +- doc/src/manual/strings.md | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/base/channels.jl b/base/channels.jl index 28943d28922f5..9c5d2290c4251 100644 --- a/base/channels.jl +++ b/base/channels.jl @@ -190,8 +190,8 @@ julia> take!(c) julia> put!(c,1); ERROR: foo Stacktrace: - [1] check_channel_state(::Channel{Any}) at ./channels.jl:125 - [2] put!(::Channel{Any}, ::Int64) at ./channels.jl:256 + [1] check_channel_state(::Channel{Any}) at ./channels.jl:127 + [2] put!(::Channel{Any}, ::Int64) at ./channels.jl:258 ``` """ function bind(c::Channel, task::Task) diff --git a/base/reduce.jl b/base/reduce.jl index b8ab9f5a18a3d..188d9c52eff9a 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -169,7 +169,7 @@ foldr(op, itr) = mapfoldr(identity, op, itr) # `mapreduce_impl()` is called by `mapreduce()` (via `_mapreduce()`, when `A` # supports linear indexing) and does actual calculations (for `A[ifirst:ilast]` subset). -# For efficiency, no parameter validity checks are done, it's the caller responsibility. +# For efficiency, no parameter validity checks are done, it's the caller's responsibility. # `ifirst:ilast` range is assumed to be a valid non-empty subset of `A` indices. # This is a generic implementation of `mapreduce_impl()`, diff --git a/doc/src/manual/strings.md b/doc/src/manual/strings.md index 352b0a1e70b0c..bbf29c24f4609 100644 --- a/doc/src/manual/strings.md +++ b/doc/src/manual/strings.md @@ -515,7 +515,7 @@ false julia> contains("Xylophon", 'o') ERROR: MethodError: no method matching contains(::String, ::Char) Closest candidates are: - contains(!Matched::Function, ::Any, !Matched::Any) at reduce.jl:660 + contains(!Matched::Function, ::Any, !Matched::Any) at reduce.jl:664 contains(::AbstractString, !Matched::AbstractString) at strings/search.jl:378 ``` From 575c9793170c90c091acafccb19c4e91d969f5a3 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Mon, 27 Mar 2017 09:41:36 -0400 Subject: [PATCH 0287/1534] run code signing script in contrib/prepare_release.sh if present --- contrib/prepare_release.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/contrib/prepare_release.sh b/contrib/prepare_release.sh index 1a0aee5b9db75..f0c1dd037b2cd 100755 --- a/contrib/prepare_release.sh +++ b/contrib/prepare_release.sh @@ -56,8 +56,11 @@ curl -L -o julia-$version-win32.exe \ $julianightlies/winnt/x86/$majmin/julia-$majminpatch-$shashort-win32.exe cp julia-$version-win32.exe julia-$majmin-latest-win32.exe -echo "Note: if windows code signing is not working on the buildbots, then the" -echo "checksums need to be re-calculated after the binaries are manually signed!" +if [ -e codesign.sh ]; then + # code signing needs to run on windows, script is not checked in since it + # hard-codes a few things. TODO: see if signtool.exe can run in wine + ./codesign.sh +fi shasum -a 256 julia-$version* | grep -v -e sha256 -e md5 -e asc > julia-$version.sha256 md5sum julia-$version* | grep -v -e sha256 -e md5 -e asc > julia-$version.md5 From 58f9f204e1088405876806a20ff6080a1123c34b Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 27 Mar 2017 14:17:24 -0400 Subject: [PATCH 0288/1534] fix #21178, lowering of static params with `<:T` syntax --- src/julia-syntax.scm | 19 ++++++++++--------- test/core.jl | 5 +++++ 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 5f1912abe0848..612310f9d8951 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -228,15 +228,16 @@ ;; extract static parameter names from a (method ...) expression (define (method-expr-static-parameters m) - (if (eq? (car (caddr m)) 'block) - (let ((lst '())) - (pattern-replace - (pattern-set - (pattern-lambda (= v (call (core (-/ TypeVar)) (quote T) ...)) - (begin (set! lst (cons T lst)) __))) - (butlast (cdr (caddr m)))) - (reverse! lst)) - '())) + (let ((type-ex (caddr m))) + (if (eq? (car type-ex) 'block) + ;; extract ssavalue labels of sparams from the svec-of-sparams argument to `method` + (let ((sp-ssavals (cddr (last (last type-ex))))) + (map (lambda (a) ;; extract T from (= v (call (core TypeVar) (quote T) ...)) + (cadr (caddr (caddr a)))) + (filter (lambda (e) + (and (pair? e) (eq? (car e) '=) (member (cadr e) sp-ssavals))) + (cdr type-ex)))) + '()))) ;; expressions of the form a.b.c... where everything is a symbol (define (sym-ref? e) diff --git a/test/core.jl b/test/core.jl index 1a6837dc62ed1..445a1fec4f5df 100644 --- a/test/core.jl +++ b/test/core.jl @@ -4782,3 +4782,8 @@ let a = Array{Core.TypeofBottom, 1}(2) @test a[1] == Union{} @test a == [Union{}, Union{}] end + +# issue #21178 +struct F21178{A,B} end +b21178(::F1,::F2) where {B1,B2,F1<:F21178{B1,<:Any},F2<:F21178{B2}} = F1,F2,B1,B2 +@test b21178(F21178{1,2}(),F21178{1,2}()) == (F21178{1,2}, F21178{1,2}, 1, 1) From 70a5624da52dd50b6957be004884503aff27ab3f Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 27 Mar 2017 17:19:56 -0400 Subject: [PATCH 0289/1534] fix #20671, slowdown loading SIUnits This adds a fast path to intersection that helps when we have a type with lots of parameters that just need to be matched up 1-to-1 with parameters of another type. Also fixes a bug in intersection uncovered by this test case. --- src/subtype.c | 22 +++++++++++++++++----- test/subtype.jl | 12 ++++++++++++ 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/subtype.c b/src/subtype.c index fa95439428b58..0bbd5278c5d52 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -1148,8 +1148,12 @@ static jl_value_t *intersect_var(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int jl_value_t *root=NULL; jl_savedenv_t se; if (param == 2) { jl_value_t *ub = R ? intersect_ufirst(a, bb->ub, e, d) : intersect_ufirst(bb->ub, a, e, d); - JL_GC_PUSH1(&ub); - if (!subtype_in_env(bb->lb, a, e)) { + JL_GC_PUSH2(&ub, &root); + save_env(e, &root, &se); + int issub = subtype_in_env(bb->lb, ub, e); + restore_env(e, root, &se); + free(se.buf); + if (!issub) { JL_GC_POP(); return jl_bottom_type; } @@ -1219,6 +1223,9 @@ static jl_value_t *intersect_var(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int } return ub; } + else if (bb->ub == bb->lb) { + return ub; + } root = NULL; JL_GC_PUSH2(&root, &ub); save_env(e, &root, &se); @@ -1326,9 +1333,14 @@ static jl_value_t *finish_unionall(jl_value_t *res, jl_varbinding_t *vb, jl_sten } } else { - varval = root = (jl_value_t*)jl_new_typevar(vb->var->name, vb->lb, vb->ub); - res = jl_instantiate_unionall((jl_unionall_t*)res, root); - res = jl_new_struct(jl_unionall_type, (jl_tvar_t*)root, res); + if (vb->lb != vb->var->lb || vb->ub != vb->var->ub) { + varval = root = (jl_value_t*)jl_new_typevar(vb->var->name, vb->lb, vb->ub); + res = jl_instantiate_unionall((jl_unionall_t*)res, root); + res = jl_new_struct(jl_unionall_type, (jl_tvar_t*)root, res); + } + else { + varval = (jl_value_t*)vb->var; + } } } diff --git a/test/subtype.jl b/test/subtype.jl index a4e92372be232..93962697141c3 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -622,6 +622,10 @@ abstract type AbstractTriangular{T,S<:AbstractMatrix} <: AbstractMatrix{T} end struct UpperTriangular{T,S<:AbstractMatrix} <: AbstractTriangular{T,S} end struct UnitUpperTriangular{T,S<:AbstractMatrix} <: AbstractTriangular{T,S} end +immutable SIQ20671{T<:Number,m,kg,s,A,K,mol,cd,rad,sr} <: Number + val::T +end + function test_intersection() @testintersect(Vector{Float64}, Vector{Union{Float64,Float32}}, Bottom) @@ -887,6 +891,14 @@ function test_intersection() @testintersect(Pair{L,Tuple{L,Pair{L,HL}}} where {L,HL}, Pair{R,Tuple{Pair{R,HR},R}} where {R,HR}, Bottom) # X == Pair{X,...} is not satisfiable + + # issue #20671 --- this just took too long + @testintersect(Tuple{Type{SIQ20671{T, mT, kgT, sT, AT, KT, molT, cdT, radT, srT}}, + SIQ20671{S, mS, kgS, sS, AS, KS, molS, cdS, radS, srS}} where {T, mT, kgT, sT, AT, KT, molT, cdT, radT, srT, + S, mS, kgS, sS, AS, KS, molS, cdS, radS, srS}, + Tuple{Type{T}, T} where T, + Tuple{Type{SIQ20671{T,mS,kgS,sS,AS,KS,molS,cdS,radS,srS}}, + SIQ20671{T,mS,kgS,sS,AS,KS,molS,cdS,radS,srS}} where {T,mS,kgS,sS,AS,KS,molS,cdS,radS,srS}) end function test_intersection_properties() From 348b5afa5851e2e7eba7bc77dc6c57c996599dd4 Mon Sep 17 00:00:00 2001 From: kshyatt Date: Mon, 27 Mar 2017 16:27:51 -0700 Subject: [PATCH 0290/1534] Various missing git tests --- test/libgit2.jl | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/libgit2.jl b/test/libgit2.jl index 96e098e529e68..6444138eb55db 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -199,12 +199,20 @@ mktempdir() do dir @test isa(remote, LibGit2.GitRemote) @test sprint(show, remote) == "GitRemote:\nRemote name: upstream url: $repo_url" @test LibGit2.isattached(repo) + LibGit2.set_remote_url(repo, "", remote="upstream") + remote = LibGit2.get(LibGit2.GitRemote, repo, branch) + @test sprint(show, remote) == "GitRemote:\nRemote name: upstream url: " + close(remote) + LibGit2.set_remote_url(cache_repo, repo_url, remote="upstream") + remote = LibGit2.get(LibGit2.GitRemote, repo, branch) + @test sprint(show, remote) == "GitRemote:\nRemote name: upstream url: $repo_url" close(remote) remote = LibGit2.GitRemoteAnon(repo, repo_url) @test LibGit2.url(remote) == repo_url @test LibGit2.name(remote) == "" @test isa(remote, LibGit2.GitRemote) + close(remote) finally close(repo) end @@ -318,11 +326,13 @@ mktempdir() do dir end @test LibGit2.is_ancestor_of(string(commit_oid1), string(commit_oid2), repo) @test LibGit2.iscommit(string(commit_oid1), repo) + @test !LibGit2.iscommit(string(commit_oid1)*"fake", repo) @test LibGit2.iscommit(string(commit_oid2), repo) # lookup commits cmt = LibGit2.GitCommit(repo, commit_oid1) try + @test LibGit2.Consts.OBJECT(typeof(cmt)) == LibGit2.Consts.OBJ_COMMIT @test commit_oid1 == LibGit2.GitHash(cmt) short_oid1 = LibGit2.GitShortHash(string(commit_oid1)) @test hex(commit_oid1) == hex(short_oid1) @@ -520,12 +530,14 @@ mktempdir() do dir tree = LibGit2.GitTree(repo, "HEAD^{tree}") @test isa(tree, LibGit2.GitTree) @test isa(LibGit2.GitObject(repo, "HEAD^{tree}"), LibGit2.GitTree) + @test LibGit2.Consts.OBJECT(typeof(tree)) == LibGit2.Consts.OBJ_TREE @test count(tree) == 1 tree_str = sprint(show, tree) @test tree_str == "GitTree:\nOwner: $(LibGit2.repository(tree))\nNumber of entries: 1\n" @test_throws BoundsError tree[0] @test_throws BoundsError tree[2] tree_entry = tree[1] + @test LibGit2.filemode(tree_entry) == 33188 te_str = sprint(show, tree_entry) @test te_str == "GitTreeEntry:\nEntry name: testfile\nEntry type: Base.LibGit2.GitBlob\nEntry OID: $(LibGit2.entryid(tree_entry))\n" blob = LibGit2.GitBlob(tree_entry) @@ -720,6 +732,7 @@ mktempdir() do dir @test idx_entry !== nothing idx_entry_str = sprint(show, idx_entry) @test idx_entry_str == "IndexEntry($(string(idx_entry.id)))" + @test LibGit2.stage(idx_entry) == 0 i = find("zzz", idx) @test isnull(i) From 9163e67c96dfe4b66057f8207e6be61ce42f7273 Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Mon, 27 Mar 2017 21:38:14 -0500 Subject: [PATCH 0291/1534] Add missing test for mapslices (#21181) Followup from #21133 * Update arrayops.jl --- test/arrayops.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/arrayops.jl b/test/arrayops.jl index 0c849a5368f62..4ad942d900bba 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -958,7 +958,7 @@ end @test m[1,2] == ([2,4],) # issue #21123 - mapslices(nnz, speye(3), 1) == [1, 1, 1] + @test mapslices(nnz, speye(3), 1) == [1 1 1] end @testset "single multidimensional index" begin From e678e673527046b77dd5a88e768a3f5fc9448d31 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 28 Mar 2017 10:33:51 +0200 Subject: [PATCH 0292/1534] ensure ShellExecuteW only gets compiled on windows rather than depending on DCE to delete this code after inference --- base/interactiveutil.jl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/base/interactiveutil.jl b/base/interactiveutil.jl index 1d569265a3773..12663bb92363a 100644 --- a/base/interactiveutil.jl +++ b/base/interactiveutil.jl @@ -61,9 +61,10 @@ function edit(path::AbstractString, line::Integer=0) end if is_windows() && name == "open" - systemerror(:edit, ccall((:ShellExecuteW,"shell32"), stdcall, Int, - (Ptr{Void}, Cwstring, Cwstring, Ptr{Void}, Ptr{Void}, Cint), - C_NULL, "open", path, C_NULL, C_NULL, 10) ≤ 32) + @static is_windows() && # don't emit this ccall on other platforms + systemerror(:edit, ccall((:ShellExecuteW, "shell32"), stdcall, Int, + (Ptr{Void}, Cwstring, Cwstring, Ptr{Void}, Ptr{Void}, Cint), + C_NULL, "open", path, C_NULL, C_NULL, 10) ≤ 32) elseif background spawn(pipeline(cmd, stderr=STDERR)) else From a159ac568473b65575aea4b5f57a2ba97626ca92 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 28 Mar 2017 10:34:47 +0200 Subject: [PATCH 0293/1534] dump: ensure jlcall_api is cleared if we don't load the fptr from the sysimg --- src/dump.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/dump.c b/src/dump.c index 64d21ee2e04a0..6e87b833a68f9 100644 --- a/src/dump.c +++ b/src/dump.c @@ -422,7 +422,15 @@ static void jl_update_all_fptrs(void) { //jl_printf(JL_STDOUT, "delayed_fptrs_n: %d\n", delayed_fptrs_n); void **fvars = sysimg_fvars; - if (fvars == 0) return; + if (fvars == NULL) { + size_t i; + for (i = 0; i < delayed_fptrs_n; i++) { + jl_method_instance_t *li = delayed_fptrs[i].li; + assert(li->jlcall_api && li->jlcall_api != 2); + li->jlcall_api = 0; + } + return; + } // jl_fptr_to_llvm needs to decompress some ASTs, therefore this needs to be NULL // to skip trying to restore GlobalVariable pointers in jl_deserialize_gv sysimg_gvars = NULL; @@ -431,7 +439,7 @@ static void jl_update_all_fptrs(void) jl_method_instance_t **linfos = (jl_method_instance_t**)malloc(sizeof(jl_method_instance_t*) * sysimg_fvars_max); for (i = 0; i < delayed_fptrs_n; i++) { jl_method_instance_t *li = delayed_fptrs[i].li; - assert(li->def); + assert(li->def && li->jlcall_api && li->jlcall_api != 2); int32_t cfunc = delayed_fptrs[i].cfunc - 1; if (cfunc >= 0) { jl_fptr_to_llvm((jl_fptr_t)fvars[cfunc], li, 1); From 48c40219aebf28e4d764b853d9e8a5a9293c5ac5 Mon Sep 17 00:00:00 2001 From: Martin Holters Date: Tue, 28 Mar 2017 12:50:49 +0200 Subject: [PATCH 0294/1534] =?UTF-8?q?Fix=20`=E2=8A=91(a::Const,=20b::Parti?= =?UTF-8?q?alTypeVar)`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For `isa(a, Const) && !isa(b, Const)`, `⊑` assumed `b` to be a type, leading to an error if `b` was a `PartialTypeVar`. Fixed by using `widenconst(b)`. --- base/inference.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/inference.jl b/base/inference.jl index 4c05e9f6e4f32..d604a9a8f3419 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -2097,7 +2097,7 @@ function ⊑(a::ANY, b::ANY) if isa(b, Const) return a.val === b.val end - return isa(a.val, b) + return isa(a.val, widenconst(b)) elseif isa(b, Const) return a === Bottom elseif !(isa(a, Type) || isa(a, TypeVar)) || From bb1facc0a47bdc72472585aec6a9c87fabed85ba Mon Sep 17 00:00:00 2001 From: Martin Holters Date: Tue, 28 Mar 2017 13:05:17 +0200 Subject: [PATCH 0295/1534] Use `TypeVar`s in `limit_type_depth` in `Union`s in invariant position Using `Any` for depth-limited `Union` members is only correct in covariant position, otherwise a `TypeVar` has be be introduced. --- base/inference.jl | 8 +++++++- test/inference.jl | 5 +++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/base/inference.jl b/base/inference.jl index d604a9a8f3419..65cf9bd02f256 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -670,7 +670,13 @@ end function limit_type_depth(t::ANY, d::Int, cov::Bool, vars::Vector{TypeVar}=TypeVar[]) if isa(t,Union) if d > MAX_TYPE_DEPTH - return Any + if cov + return Any + else + var = TypeVar(:_) + push!(vars, var) + return var + end end return Union{limit_type_depth(t.a, d+1, cov, vars), limit_type_depth(t.b, d+1, cov, vars)} diff --git a/test/inference.jl b/test/inference.jl index b2ede24f10803..0bd563a24b75c 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -655,6 +655,11 @@ let A = 1:2, z = zip(A, A, A, A, A, A, A, A, A, A, A, A) @test z isa Core.Inference.limit_type_depth(typeof(z), 0) @test start(z) == (1, (1, (1, (1, (1, (1, (1, (1, (1, (1, (1, 1))))))))))) end +# introduce TypeVars in Unions in invariant position +let T = Val{Val{Val{Union{Int8,Int16,Int32,Int64,UInt8,UInt16,UInt32,UInt64}}}} + #TODO: this test hits an assertion (see #21191) + #@test T <: Core.Inference.limit_type_depth(T, 0) +end # issue #20704 f20704(::Int) = 1 From 407995adcdbc3a0b397b2fb36319fcfc1a2e6b8f Mon Sep 17 00:00:00 2001 From: felix Date: Tue, 28 Mar 2017 14:37:32 +0200 Subject: [PATCH 0296/1534] document x % T (#20759) --- base/int.jl | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/base/int.jl b/base/int.jl index 56a4645275e29..c00dc6111bbfd 100644 --- a/base/int.jl +++ b/base/int.jl @@ -359,6 +359,21 @@ for to in BitInteger_types, from in (BitInteger_types..., Bool) end end +""" + rem(x::Integer, T<:Integer) + mod(x::Integer, T<:Integer) + %(x::Integer, T<:Integer) + +Find `y::T` such that `x` ≡ `y` (mod n), where n is the number of integers representable +in `T`, and `y` is an integer in `[typemin(T),typemax(T)]`. + +```jldoctest +julia> 129 % Int8 +-127 +``` +""" +rem, mod + rem{T<:Integer}(x::T, ::Type{T}) = x rem(x::Integer, ::Type{Bool}) = ((x & 1) != 0) mod{T<:Integer}(x::Integer, ::Type{T}) = rem(x, T) From e8a022a80723e15b87b20aeea5b383b484cb9b87 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Tue, 28 Mar 2017 14:54:59 +0100 Subject: [PATCH 0297/1534] add support for AbstractGitHash --- base/deprecated.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index 56d281665804a..7649120d70e2a 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1139,7 +1139,7 @@ end @deprecate object(repo::GitRepo, te::GitTreeEntry) GitObject(repo, te) false @deprecate commit(ann::GitAnnotated) GitHash(ann) false @deprecate lookup(repo::GitRepo, oid::GitHash) GitBlob(repo, oid) false - function Base.cat{T<:GitObject}(repo::GitRepo, ::Type{T}, object::AbstractString) + function Base.cat{T<:GitObject}(repo::GitRepo, ::Type{T}, object::Union{AbstractString,AbstractGitHash}) Base.depwarn("cat(repo::GitRepo, T, spec) is deprecated, use content(T(repo, spec))", :cat) try return content(GitBlob(repo, spec)) @@ -1148,7 +1148,7 @@ end rethrow(e) end end - Base.cat(repo::GitRepo, object::AbstractString) = cat(repo, GitBlob, object) + Base.cat(repo::GitRepo, object::Union{AbstractString,AbstractGitHash}) = cat(repo, GitBlob, object) end # when this deprecation is deleted, remove all calls to it, and all From 378ed8a75a690f5e5b6cb04201a563533d64d452 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Tue, 28 Mar 2017 10:05:58 -0400 Subject: [PATCH 0298/1534] updated fix for #19892 (FFTW threads initialization) (#21169) * updated fix for #19892; initialize FFTW threads the first time the planner is called (#21127 incorrectly prevented threads from being used at all) * add test for #21163 --- base/fft/FFTW.jl | 46 ++++++++++++++++++++++++++++++++-------------- test/fft.jl | 8 ++++++-- 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/base/fft/FFTW.jl b/base/fft/FFTW.jl index 3b90329b99456..712f7e6ebe850 100644 --- a/base/fft/FFTW.jl +++ b/base/fft/FFTW.jl @@ -84,6 +84,27 @@ alignment_of(A::FakeArray) = Int32(0) ## Julia wrappers around FFTW functions +# _init_() must be called before any FFTW planning routine. +# -- Once FFTW is split into its own module, this can be called +# in the module __init__(), but for now we must call it lazily +# in every routine that might initialize the FFTW planner. +# -- This initializes FFTW's threads support (defaulting to 1 thread). +# If this isn't called before the FFTW planner is created, then +# FFTW's threads algorithms won't be registered or used at all. +# (Previously, we called fftw_cleanup, but this invalidated existing +# plans, causing issue #19892.) +const threads_initialized = Ref(false) +function _init_() + if !threads_initialized[] + stat = ccall((:fftw_init_threads,libfftw), Int32, ()) + statf = ccall((:fftwf_init_threads,libfftwf), Int32, ()) + if stat == 0 || statf == 0 + error("could not initialize FFTW threads") + end + threads_initialized[] = true + end +end + # Wisdom # Import and export wisdom to/from a single file for all precisions, @@ -96,6 +117,7 @@ alignment_of(A::FakeArray) = Int32(0) # FFTW's api/import-wisdom-from-file.c file]. function export_wisdom(fname::AbstractString) + _init_() f = ccall(:fopen, Ptr{Void}, (Cstring,Cstring), fname, :w) systemerror("could not open wisdom file $fname for writing", f == C_NULL) ccall((:fftw_export_wisdom_to_file,libfftw), Void, (Ptr{Void},), f) @@ -105,6 +127,7 @@ function export_wisdom(fname::AbstractString) end function import_wisdom(fname::AbstractString) + _init_() f = ccall(:fopen, Ptr{Void}, (Cstring,Cstring), fname, :r) systemerror("could not open wisdom file $fname for reading", f == C_NULL) if ccall((:fftw_import_wisdom_from_file,libfftw),Int32,(Ptr{Void},),f)==0|| @@ -115,6 +138,7 @@ function import_wisdom(fname::AbstractString) end function import_system_wisdom() + _init_() if ccall((:fftw_import_system_wisdom,libfftw), Int32, ()) == 0 || ccall((:fftwf_import_system_wisdom,libfftwf), Int32, ()) == 0 error("failed to import system wisdom") @@ -122,25 +146,15 @@ function import_system_wisdom() end function forget_wisdom() + _init_() ccall((:fftw_forget_wisdom,libfftw), Void, ()) ccall((:fftwf_forget_wisdom,libfftwf), Void, ()) end # Threads -const threads_initialized = Ref(false) function set_num_threads(nthreads::Integer) - if !threads_initialized[] - # must forget wisdom if any FFTW routines have been called - # (don't call fftw_cleanup, since that would invalidate existing plans) - forget_wisdom() - stat = ccall((:fftw_init_threads,libfftw), Int32, ()) - statf = ccall((:fftwf_init_threads,libfftwf), Int32, ()) - if stat == 0 || statf == 0 - error("could not initialize FFTW threads") - end - threads_initialized[] = true - end + _init_() ccall((:fftw_plan_with_nthreads,libfftw), Void, (Int32,), nthreads) ccall((:fftwf_plan_with_nthreads,libfftwf), Void, (Int32,), nthreads) end @@ -154,11 +168,15 @@ const PlanPtr = Ptr{fftw_plan_struct} const NO_TIMELIMIT = -1.0 # from fftw3.h -set_timelimit(precision::fftwTypeDouble,seconds) = +function set_timelimit(precision::fftwTypeDouble,seconds) + _init_() ccall((:fftw_set_timelimit,libfftw), Void, (Float64,), seconds) +end -set_timelimit(precision::fftwTypeSingle,seconds) = +function set_timelimit(precision::fftwTypeSingle,seconds) + _init_() ccall((:fftwf_set_timelimit,libfftwf), Void, (Float64,), seconds) +end # Array alignment mod 16: # FFTW plans may depend on the alignment of the array mod 16 bytes, diff --git a/test/fft.jl b/test/fft.jl index 90623aae3470e..db165ba93b5ef 100644 --- a/test/fft.jl +++ b/test/fft.jl @@ -2,10 +2,14 @@ # issue #19892 # (test this first to make sure it happens before set_num_threads) -let a = randn(10^5,1), p1 = plan_rfft(a) +let a = randn(10^5,1), p1 = plan_rfft(a, flags=FFTW.ESTIMATE) FFTW.set_num_threads(2) - p2 = plan_rfft(a) + p2 = plan_rfft(a, flags=FFTW.ESTIMATE) @test p1*a ≈ p2*a + # make sure threads are actually being used for p2 + # (tests #21163). + @test !contains(string(p1), "dft-thr") + @test contains(string(p2), "dft-thr") end # fft From fb670345366611421b2e04212289d44f69b75096 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 28 Mar 2017 11:15:28 -0400 Subject: [PATCH 0299/1534] fix #21172, `a = f(x) = 1` --- src/julia-syntax.scm | 31 ++++++++++++++++++------------- test/core.jl | 5 +++++ 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 612310f9d8951..f70368039b002 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -1830,20 +1830,23 @@ '= (lambda (e) (define lhs (cadr e)) - (cond - ((and (pair? lhs) - (or (eq? (car lhs) 'call) + (define (function-lhs? lhs) + (and (pair? lhs) + (or (and (eq? (car lhs) 'comparison) (length= lhs 4)) + (eq? (car lhs) 'call) (eq? (car lhs) 'where) (and (eq? (car lhs) '|::|) (pair? (cadr lhs)) - (eq? (car (cadr lhs)) 'call)))) - (expand-forms (cons 'function (cdr e)))) - ((and (pair? lhs) - (eq? (car lhs) 'comparison) - (length= lhs 4)) - ;; allow defining functions that use comparison syntax - (expand-forms (list* 'function - `(call ,(caddr lhs) ,(cadr lhs) ,(cadddr lhs)) (cddr e)))) + (eq? (car (cadr lhs)) 'call))))) + (define (assignment-to-function lhs e) ;; convert '= expr to 'function expr + (if (eq? (car lhs) 'comparison) + ;; allow defining functions that use comparison syntax + (list* 'function + `(call ,(caddr lhs) ,(cadr lhs) ,(cadddr lhs)) (cddr e)) + (cons 'function (cdr e)))) + (cond + ((function-lhs? lhs) + (expand-forms (assignment-to-function lhs e))) ((and (pair? lhs) (eq? (car lhs) 'curly)) (expand-typealias (cadr e) (caddr e))) @@ -1851,11 +1854,13 @@ ;; chain of assignments - convert a=b=c to `b=c; a=c` (let loop ((lhss (list lhs)) (rhs (caddr e))) - (if (assignment? rhs) + (if (and (assignment? rhs) (not (function-lhs? (cadr rhs)))) (loop (cons (cadr rhs) lhss) (caddr rhs)) (let ((rr (if (symbol-like? rhs) rhs (make-ssavalue)))) (expand-forms - `(block ,.(if (eq? rr rhs) '() `((= ,rr ,rhs))) + `(block ,.(if (eq? rr rhs) '() `((= ,rr ,(if (assignment? rhs) + (assignment-to-function (cadr rhs) rhs) + rhs)))) ,@(map (lambda (l) `(= ,l ,rr)) lhss) (unnecessary ,rr))))))) diff --git a/test/core.jl b/test/core.jl index 445a1fec4f5df..f3c42b0875cfb 100644 --- a/test/core.jl +++ b/test/core.jl @@ -4787,3 +4787,8 @@ end struct F21178{A,B} end b21178(::F1,::F2) where {B1,B2,F1<:F21178{B1,<:Any},F2<:F21178{B2}} = F1,F2,B1,B2 @test b21178(F21178{1,2}(),F21178{1,2}()) == (F21178{1,2}, F21178{1,2}, 1, 1) + +# issue #21172 +a21172 = f21172(x) = 2x +@test f21172(8) == 16 +@test a21172 === f21172 From 2211e0314ebec11a1d8272f3ed201cf9c6d3d771 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Tue, 28 Mar 2017 12:29:14 -0400 Subject: [PATCH 0300/1534] access Cmd elements as an array of strings --- base/process.jl | 8 ++++++++ doc/src/manual/running-external-programs.md | 12 ++++++++++++ test/spawn.jl | 11 +++++++++++ 3 files changed, 31 insertions(+) diff --git a/base/process.jl b/base/process.jl index cd15390ca42d6..1b2961ac625c3 100644 --- a/base/process.jl +++ b/base/process.jl @@ -805,3 +805,11 @@ wait(x::Process) = if !process_exited(x); stream_wait(x, x.exitnotify); end wait(x::ProcessChain) = for p in x.processes; wait(p); end show(io::IO, p::Process) = print(io, "Process(", p.cmd, ", ", process_status(p), ")") + +# allow the elements of the Cmd to be accessed as an array or iterator +for f in (:length, :endof, :start, :eachindex, :eltype, :first, :last) + @eval $f(cmd::Cmd) = $f(cmd.exec) +end +for f in (:next, :done, :getindex) + @eval $f(cmd::Cmd, i) = $f(cmd.exec, i) +end diff --git a/doc/src/manual/running-external-programs.md b/doc/src/manual/running-external-programs.md index a179d9f5d006b..dbeef5f23969f 100644 --- a/doc/src/manual/running-external-programs.md +++ b/doc/src/manual/running-external-programs.md @@ -60,6 +60,18 @@ julia> open(`less`, "w", STDOUT) do io 3 ``` +The program name and the individual arguments in a command can be accessed +and iterated over as if the command were an array of strings: +```jldoctest +julia> collect(`echo "foo bar"`) +2-element Array{String,1}: + "echo" + "foo bar" + +julia> `echo "foo bar"`[2] +"foo bar" +``` + ## [Interpolation](@id command-interpolation) Suppose you want to do something a bit more complicated and use the name of a file in the variable diff --git a/test/spawn.jl b/test/spawn.jl index 8b7582b191ad0..87d9bf169d85e 100644 --- a/test/spawn.jl +++ b/test/spawn.jl @@ -466,3 +466,14 @@ end Base.showerror(io::IO, e::Error19864) = print(io, "correct19864") throw(Error19864())'`), stderr=catcmd)) == "ERROR: correct19864" + +# accessing the command elements as an array or iterator: +let c = `ls -l "foo bar"` + @test collect(c) == ["ls", "-l", "foo bar"] + @test first(c) == "ls" == c[1] + @test last(c) == "foo bar" == c[3] == c[end] + @test c[1:2] == ["ls", "-l"] + @test eltype(c) == String + @test length(c) == 3 + @test eachindex(c) == 1:3 +end From 5560ea3c46188c588ff73f0b4f38a0c99ac73698 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Tue, 28 Mar 2017 12:33:31 -0400 Subject: [PATCH 0301/1534] whitespace --- doc/src/manual/running-external-programs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/manual/running-external-programs.md b/doc/src/manual/running-external-programs.md index dbeef5f23969f..36e624f9f08f1 100644 --- a/doc/src/manual/running-external-programs.md +++ b/doc/src/manual/running-external-programs.md @@ -65,7 +65,7 @@ and iterated over as if the command were an array of strings: ```jldoctest julia> collect(`echo "foo bar"`) 2-element Array{String,1}: - "echo" + "echo" "foo bar" julia> `echo "foo bar"`[2] From 7492483826c746b4038a42eb9f05e2e4bc2f43bf Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 28 Mar 2017 14:03:56 -0400 Subject: [PATCH 0302/1534] handle unicode space characters in `parse` for `Bool` --- base/parse.jl | 4 ++-- test/parse.jl | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/base/parse.jl b/base/parse.jl index 7d31ea955019f..493410e2fd87f 100644 --- a/base/parse.jl +++ b/base/parse.jl @@ -140,10 +140,10 @@ function tryparse_internal(::Type{Bool}, sbuff::Union{String,SubString}, # Ignore leading and trailing whitespace while isspace(sbuff[startpos]) && startpos <= endpos - startpos += 1 + startpos = nextind(sbuff, startpos) end while isspace(sbuff[endpos]) && endpos >= startpos - endpos -= 1 + endpos = prevind(sbuff, endpos) end len = endpos - startpos + 1 diff --git a/test/parse.jl b/test/parse.jl index 9c809743c90ef..79b7f97a36afa 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -276,6 +276,9 @@ for T in vcat(subtypes(Signed), subtypes(Unsigned)) @test parse(Float64, ".5 " ) == 0.5 end +@test parse(Bool, "\u202f true") === true +@test parse(Bool, "\u202f false") === false + parsebin(s) = parse(Int,s,2) parseoct(s) = parse(Int,s,8) parsehex(s) = parse(Int,s,16) From 98518bf3ab8b0234b826b568118d2499ffc123f0 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 28 Mar 2017 14:32:44 -0400 Subject: [PATCH 0303/1534] fix #21180, regression in `readcsv` with quoted unicode fields --- base/datafmt.jl | 2 +- test/datafmt.jl | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/base/datafmt.jl b/base/datafmt.jl index 541ec089488d2..08a4c99cfac7a 100644 --- a/base/datafmt.jl +++ b/base/datafmt.jl @@ -238,7 +238,7 @@ function store_cell{T}(dlmstore::DLMStore{T}, row::Int, col::Int, end if quoted startpos += 1 - endpos -= 1 + endpos = prevind(sbuff, endpos) end if drow > 0 diff --git a/test/datafmt.jl b/test/datafmt.jl index 9057c1790872f..dc9ba1856fd25 100644 --- a/test/datafmt.jl +++ b/test/datafmt.jl @@ -272,3 +272,8 @@ let fn = tempname() readdlm(fn)[] == "Julia" rm(fn) end + +# issue #21180 +let data = "\"721\",\"1438\",\"1439\",\"…\",\"1\"" + @test readcsv(IOBuffer(data)) == Any[721 1438 1439 "…" 1] +end From defab5a93c75221079d842c11506b05424300f53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Tue, 28 Mar 2017 21:47:36 +0200 Subject: [PATCH 0304/1534] Add iszero method with Irrational argument --- base/irrationals.jl | 1 + test/numbers.jl | 3 +++ 2 files changed, 4 insertions(+) diff --git a/base/irrationals.jl b/base/irrationals.jl index 55390ac126738..bad1521e71ce9 100644 --- a/base/irrationals.jl +++ b/base/irrationals.jl @@ -95,6 +95,7 @@ end <=(x::Rational, y::Irrational) = x < y isfinite(::Irrational) = true +iszero(::Irrational) = false hash(x::Irrational, h::UInt) = 3*object_id(x) - h diff --git a/test/numbers.jl b/test/numbers.jl index f926085912ba3..a7c800e033f9c 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -2949,6 +2949,9 @@ end end end @test !iszero(nextfloat(BigFloat(0))) + for x in (π, e, γ, catalan, φ) + @test !iszero(x) + end # Array reduction @test !iszero([0, 1, 2, 3]) From 3bb1b565bd2a9c7b962bd4523db6b89201e762d7 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 28 Mar 2017 21:42:35 +0200 Subject: [PATCH 0305/1534] don't make corrupted copies of singleton objects during AST deserialization this corruption will now be detected when finalizing the sysimg with an assertion --- src/dump.c | 46 ++++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/src/dump.c b/src/dump.c index 64d21ee2e04a0..08e31148a9163 100644 --- a/src/dump.c +++ b/src/dump.c @@ -694,9 +694,10 @@ static int is_ast_node(jl_value_t *v) { // TODO: this accidentally copies QuoteNode(Expr(...)) and QuoteNode(svec(...)) return jl_is_symbol(v) || jl_is_slot(v) || jl_is_ssavalue(v) || - jl_is_expr(v) || jl_is_newvarnode(v) || jl_is_svec(v) || jl_is_tuple(v) || - jl_is_uniontype(v) || jl_is_int32(v) || jl_is_int64(v) || - jl_is_bool(v) || jl_is_quotenode(v) || jl_is_gotonode(v) || + jl_is_uniontype(v) || jl_is_expr(v) || jl_is_newvarnode(v) || + jl_is_svec(v) || jl_is_tuple(v) || ((jl_datatype_t*)jl_typeof(v))->instance || + jl_is_int32(v) || jl_is_int64(v) || jl_is_bool(v) || + jl_is_quotenode(v) || jl_is_gotonode(v) || jl_is_labelnode(v) || jl_is_linenode(v) || jl_is_globalref(v); } @@ -1057,6 +1058,7 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li jl_serialize_value(s, t); return; } + assert(!t->instance && "detected singleton construction corruption"); if (t->size <= 255) { writetag(s->s, (jl_value_t*)SmallDataType_tag); write_uint8(s->s, t->size); @@ -1853,18 +1855,19 @@ static jl_value_t *jl_deserialize_value_globalref(jl_serializer_state *s) static jl_value_t *jl_deserialize_value_singleton(jl_serializer_state *s, jl_value_t **loc) { - int usetable = (s->mode != MODE_AST); + if (s->mode == MODE_AST) { + jl_datatype_t *dt = (jl_datatype_t*)jl_deserialize_value(s, NULL); + return dt->instance; + } jl_value_t *v = (jl_value_t*)jl_gc_alloc(s->ptls, 0, NULL); - if (usetable) { - uintptr_t pos = backref_list.len; - arraylist_push(&backref_list, (void*)v); - if (s->mode == MODE_MODULE) { - // TODO: optimize the case where the value can easily be obtained - // from an external module (tag == 6) as dt->instance - assert(loc != NULL && loc != HT_NOTFOUND); - arraylist_push(&flagref_list, loc); - arraylist_push(&flagref_list, (void*)pos); - } + uintptr_t pos = backref_list.len; + arraylist_push(&backref_list, (void*)v); + if (s->mode == MODE_MODULE) { + // TODO: optimize the case where the value can easily be obtained + // from an external module (tag == 6) as dt->instance + assert(loc != NULL && loc != HT_NOTFOUND); + arraylist_push(&flagref_list, loc); + arraylist_push(&flagref_list, (void*)pos); } jl_datatype_t *dt = (jl_datatype_t*)jl_deserialize_value(s, (jl_value_t**)HT_NOTFOUND); // no loc, since if dt is replaced, then dt->instance would be also jl_set_typeof(v, dt); @@ -2346,14 +2349,21 @@ static void jl_init_restored_modules(jl_array_t *init_order) static void jl_prune_type_cache(jl_svec_t *cache) { size_t l = jl_svec_len(cache), ins = 0, i; - for(i=0; i < l; i++) { + for (i = 0; i < l; i++) { jl_value_t *ti = jl_svecref(cache, i); - if (ti == NULL) break; + if (ti == NULL) + break; if (ptrhash_get(&backref_table, ti) != HT_NOTFOUND || jl_get_llvm_gv(ti) != 0) jl_svecset(cache, ins++, ti); + else if (jl_is_datatype(ti)) { + jl_value_t *singleton = ((jl_datatype_t*)ti)->instance; + if (singleton && (ptrhash_get(&backref_table, singleton) != HT_NOTFOUND || jl_get_llvm_gv(singleton) != 0)) + jl_svecset(cache, ins++, ti); + } + } + if (i > ins) { + memset(&jl_svec_data(cache)[ins], 0, (i - ins) * sizeof(jl_value_t*)); } - if (i > ins) - memset(&jl_svec_data(cache)[ins], 0, (i-ins)*sizeof(jl_value_t*)); } static void jl_save_system_image_to_stream(ios_t *f) From d221f15c7b8bd085e3f8b780dbf441563e01fe7b Mon Sep 17 00:00:00 2001 From: getzdan Date: Tue, 28 Mar 2017 23:54:12 +0300 Subject: [PATCH 0306/1534] Update datafmt.jl Use `endof` instead of `length` as `colval` expects byte index. --- base/datafmt.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/datafmt.jl b/base/datafmt.jl index 541ec089488d2..8ec1b0460bb42 100644 --- a/base/datafmt.jl +++ b/base/datafmt.jl @@ -263,7 +263,7 @@ function store_cell{T}(dlmstore::DLMStore{T}, row::Int, col::Int, # fill data if quoted && _chrinstr(sbuff, UInt8('"'), startpos, endpos) unescaped = replace(SubString(sbuff, startpos, endpos), r"\"\"", "\"") - fail = colval(unescaped, 1, length(unescaped), cells, drow, col) + fail = colval(unescaped, 1, endof(unescaped), cells, drow, col) else fail = colval(sbuff, startpos, endpos, cells, drow, col) end @@ -282,7 +282,7 @@ function store_cell{T}(dlmstore::DLMStore{T}, row::Int, col::Int, # fill header if quoted && _chrinstr(sbuff, UInt8('"'), startpos, endpos) unescaped = replace(SubString(sbuff, startpos, endpos), r"\"\"", "\"") - colval(unescaped, 1, length(unescaped), dlmstore.hdr, 1, col) + colval(unescaped, 1, endof(unescaped), dlmstore.hdr, 1, col) else colval(sbuff, startpos, endpos, dlmstore.hdr, 1, col) end From b19f6bde89df4a784e382c5dab5fcbe6a3eea589 Mon Sep 17 00:00:00 2001 From: getzdan Date: Wed, 29 Mar 2017 00:17:40 +0300 Subject: [PATCH 0307/1534] Add test to for fix --- test/datafmt.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/datafmt.jl b/test/datafmt.jl index 9057c1790872f..9ca1e75fd1395 100644 --- a/test/datafmt.jl +++ b/test/datafmt.jl @@ -272,3 +272,8 @@ let fn = tempname() readdlm(fn)[] == "Julia" rm(fn) end + +# issue #21207 +let data = "\"1\",\"灣\"\"灣灣灣灣\",\"3\"" + @test readcsv(IOBuffer(data)) == Any[1 "灣\"灣灣灣灣" 3] +end From 78afb6a2b01302777e2b07b4437950c7477488e0 Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Tue, 28 Mar 2017 14:17:59 -0700 Subject: [PATCH 0308/1534] Correct notation used in the rem/mod docstring (#21198) * Correct notation used in rem/mod docstring * Fix build warning about overwritten docstring for rem --- base/int.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/base/int.jl b/base/int.jl index c00dc6111bbfd..ab472260cbb59 100644 --- a/base/int.jl +++ b/base/int.jl @@ -360,9 +360,9 @@ for to in BitInteger_types, from in (BitInteger_types..., Bool) end """ - rem(x::Integer, T<:Integer) - mod(x::Integer, T<:Integer) - %(x::Integer, T<:Integer) + rem(x::Integer, T::Type{<:Integer}) + mod(x::Integer, T::Type{<:Integer}) + %(x::Integer, T::Type{<:Integer}) Find `y::T` such that `x` ≡ `y` (mod n), where n is the number of integers representable in `T`, and `y` is an integer in `[typemin(T),typemax(T)]`. @@ -372,7 +372,7 @@ julia> 129 % Int8 -127 ``` """ -rem, mod +function rem(x::Integer, T::Type) end, function mod(x::Integer, T::Type) end rem{T<:Integer}(x::T, ::Type{T}) = x rem(x::Integer, ::Type{Bool}) = ((x & 1) != 0) From 820a9d8d781ef259e26eb40ba33cfac341057b66 Mon Sep 17 00:00:00 2001 From: kshyatt Date: Tue, 28 Mar 2017 15:20:02 -0700 Subject: [PATCH 0309/1534] More tests for GitConfig --- test/libgit2.jl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/libgit2.jl b/test/libgit2.jl index 6444138eb55db..1b76641046cfb 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -57,6 +57,14 @@ end @test sig3.email == sig.email end +@testset "Default config" begin + #for now just see that this works + cfg = LibGit2.GitConfig() + @test isa(cfg, LibGit2.GitConfig) + LibGit2.set!(cfg, "fake.property", "AAAA") + LibGit2.getconfig("fake.property", "") == "AAAA" +end + @testset "Git URL parsing" begin @testset "HTTPS URL" begin m = match(LibGit2.URL_REGEX, "https://user:pass@server.com:80/org/project.git") @@ -430,6 +438,8 @@ mktempdir() do dir sig = LibGit2.Signature(repo) @test sig.name == "AAAA" @test sig.email == "BBBB@BBBB.COM" + @test LibGit2.getconfig(repo, "user.name", "") == "AAAA" + @test LibGit2.getconfig(cache_repo, "user.name", "") == "AAAA" end finally close(repo) From 3e489a5ed13519fd8a99ac1c31af5ab82ad2ef9e Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 28 Mar 2017 20:07:13 -0400 Subject: [PATCH 0310/1534] improve codegen of `setfield!` with constant integer index --- src/codegen.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index b14f023062575..49ad65e66ec24 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -2973,10 +2973,20 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, else if (f==jl_builtin_setfield && nargs==3) { jl_datatype_t *sty = (jl_datatype_t*)expr_type(args[1], ctx); rt1 = (jl_value_t*)sty; - if (jl_is_structtype(sty) && sty != jl_module_type && - jl_is_quotenode(args[2]) && jl_is_symbol(jl_fieldref(args[2],0))) { - size_t idx = jl_field_index(sty, - (jl_sym_t*)jl_fieldref(args[2],0), 0); + if (jl_is_structtype(sty) && sty != jl_module_type) { + size_t idx = (size_t)-1; + if (jl_is_quotenode(args[2]) && jl_is_symbol(jl_fieldref(args[2],0))) { + idx = jl_field_index(sty, (jl_sym_t*)jl_fieldref(args[2],0), 0); + } + else if (jl_is_long(args[2]) || (jl_is_quotenode(args[2]) && jl_is_long(jl_fieldref(args[2],0)))) { + ssize_t i; + if (jl_is_long(args[2])) + i = jl_unbox_long(args[2]); + else + i = jl_unbox_long(jl_fieldref(args[2],0)); + if (i > 0 && i <= jl_datatype_nfields(sty)) + idx = i-1; + } if (idx != (size_t)-1) { jl_value_t *ft = jl_svecref(sty->types, idx); jl_value_t *rhst = expr_type(args[3], ctx); @@ -2991,7 +3001,6 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, } } } - // TODO: faster code for integer index } else if (f==jl_builtin_nfields && nargs==1) { From 31e2c9ac7f102b458eb1e57eaa40bcdc9c7ada92 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Wed, 29 Mar 2017 02:19:31 -0700 Subject: [PATCH 0311/1534] Fix bug in merge! and add test (#21213) --- base/libgit2/merge.jl | 2 +- test/libgit2.jl | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/base/libgit2/merge.jl b/base/libgit2/merge.jl index 9031c2bf75fc1..cf5ab1040babd 100644 --- a/base/libgit2/merge.jl +++ b/base/libgit2/merge.jl @@ -71,7 +71,7 @@ function merge!(repo::GitRepo, anns::Vector{GitAnnotated}; @check ccall((:git_merge, :libgit2), Cint, (Ptr{Void}, Ptr{Ptr{Void}}, Csize_t, Ptr{MergeOptions}, Ptr{CheckoutOptions}), - repo.ptr, anns, anns_size, + repo.ptr, map(x->x.ptr, anns), anns_size, Ref(merge_opts), Ref(checkout_opts)) info("Review and commit merged changes.") return true diff --git a/test/libgit2.jl b/test/libgit2.jl index 6444138eb55db..fc7af0df9df30 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -884,6 +884,25 @@ mktempdir() do dir end end + @testset "merge" begin + repo = LibGit2.GitRepo(test_repo) + try + LibGit2.branch!(repo, "branch/merge_a") + + a_head = LibGit2.head_oid(repo) + open(joinpath(LibGit2.path(repo),"merge_file1"),"w") do f + write(f, "111\n") + end + LibGit2.add!(repo, "merge_file1") + LibGit2.commit(repo, "add merge_file1") + + a_head_ann = LibGit2.GitAnnotated(repo, "branch/a") + @test LibGit2.merge!(repo, [a_head_ann]) #merge returns true if successful + finally + close(repo) + end + end + @testset "Transact test repository" begin repo = LibGit2.GitRepo(test_repo) try From 46b60992c11abef23e3768819642b01580277e6d Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Wed, 29 Mar 2017 02:19:52 -0700 Subject: [PATCH 0312/1534] Add a test for aborting a rebase (#21209) --- test/libgit2.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/libgit2.jl b/test/libgit2.jl index fc7af0df9df30..f2309e64a3912 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -868,6 +868,7 @@ mktempdir() do dir LibGit2.add!(repo, "file6") LibGit2.commit(repo, "add file6") + pre_abort_head = LibGit2.head_oid(repo) # Rebase type head_ann = LibGit2.GitAnnotated(repo, "branch/a") upst_ann = LibGit2.GitAnnotated(repo, "master") @@ -879,6 +880,10 @@ mktempdir() do dir @test rbo_str == "RebaseOperation($(string(rbo.id)))\nOperation type: REBASE_OPERATION_PICK\n" rb_str = sprint(show, rb) @test rb_str == "GitRebase:\nNumber: 2\nCurrently performing operation: 1\n" + + # test rebase abort + LibGit2.abort(rb) + @test LibGit2.head_oid(repo) == pre_abort_head finally close(repo) end From 2d3a6172b47328f4ed6384fc270bd4b34ed2a448 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Wed, 29 Mar 2017 11:23:10 +0200 Subject: [PATCH 0313/1534] Support Rational and Irrational arguments for exp10 (#21199) --- base/math.jl | 2 +- test/math.jl | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/base/math.jl b/base/math.jl index cc239cab8f298..3831ed2831961 100644 --- a/base/math.jl +++ b/base/math.jl @@ -291,7 +291,7 @@ end # TODO: GNU libc has exp10 as an extension; should openlibm? exp10(x::Float64) = 10.0^x exp10(x::Float32) = 10.0f0^x -exp10(x::Integer) = exp10(float(x)) +exp10(x::Real) = exp10(float(x)) # utility for converting NaN return to DomainError # the branch in nan_dom_err prevents its callers from inlining, so be sure to force it diff --git a/test/math.jl b/test/math.jl index ca5b2912cfc94..372bcf0e10a24 100644 --- a/test/math.jl +++ b/test/math.jl @@ -246,6 +246,8 @@ end end end @test exp10(5) ≈ exp10(5.0) +@test exp10(50//10) ≈ exp10(5.0) +@test log10(exp10(e)) ≈ e @test exp2(Float16(2.)) ≈ exp2(2.) @test log(e) == 1 From 1eb51b659ead69d134a000f4b25fdb4a948561d7 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Wed, 29 Mar 2017 10:24:24 +0100 Subject: [PATCH 0314/1534] null pointer checks are unnecessary: API should never return valid pointers with an error (#21174) --- base/libgit2/repository.jl | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/base/libgit2/repository.jl b/base/libgit2/repository.jl index a991fb806baf8..151c5c1e56af0 100644 --- a/base/libgit2/repository.jl +++ b/base/libgit2/repository.jl @@ -7,14 +7,8 @@ Opens a git repository at `path`. """ function GitRepo(path::AbstractString) repo_ptr_ptr = Ref{Ptr{Void}}(C_NULL) - err = ccall((:git_repository_open, :libgit2), Cint, - (Ptr{Ptr{Void}}, Cstring), repo_ptr_ptr, path) - if err != Int(Error.GIT_OK) - if repo_ptr_ptr[] != C_NULL - close(GitRepo(repo_ptr_ptr[])) - end - throw(Error.GitError(err)) - end + @check ccall((:git_repository_open, :libgit2), Cint, + (Ptr{Ptr{Void}}, Cstring), repo_ptr_ptr, path) return GitRepo(repo_ptr_ptr[]) end @@ -27,15 +21,9 @@ user must be a member of a special access group to read `path`). function GitRepoExt(path::AbstractString, flags::Cuint = Cuint(Consts.REPOSITORY_OPEN_DEFAULT)) separator = @static is_windows() ? ";" : ":" repo_ptr_ptr = Ref{Ptr{Void}}(C_NULL) - err = ccall((:git_repository_open_ext, :libgit2), Cint, - (Ptr{Ptr{Void}}, Cstring, Cuint, Cstring), + @check ccall((:git_repository_open_ext, :libgit2), Cint, + (Ptr{Ptr{Void}}, Cstring, Cuint, Cstring), repo_ptr_ptr, path, flags, separator) - if err != Int(Error.GIT_OK) - if repo_ptr_ptr[] != C_NULL - close(GitRepo(repo_ptr_ptr[])) - end - throw(Error.GitError(err)) - end return GitRepo(repo_ptr_ptr[]) end From da63bfe68f4ab785c0062297ff3cedfb919918e3 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Wed, 29 Mar 2017 09:00:53 -0700 Subject: [PATCH 0315/1534] Revert "Add a test for aborting a rebase (#21209)" (#21220) This reverts commit 46b60992c11abef23e3768819642b01580277e6d. --- test/libgit2.jl | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/libgit2.jl b/test/libgit2.jl index f2309e64a3912..fc7af0df9df30 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -868,7 +868,6 @@ mktempdir() do dir LibGit2.add!(repo, "file6") LibGit2.commit(repo, "add file6") - pre_abort_head = LibGit2.head_oid(repo) # Rebase type head_ann = LibGit2.GitAnnotated(repo, "branch/a") upst_ann = LibGit2.GitAnnotated(repo, "master") @@ -880,10 +879,6 @@ mktempdir() do dir @test rbo_str == "RebaseOperation($(string(rbo.id)))\nOperation type: REBASE_OPERATION_PICK\n" rb_str = sprint(show, rb) @test rb_str == "GitRebase:\nNumber: 2\nCurrently performing operation: 1\n" - - # test rebase abort - LibGit2.abort(rb) - @test LibGit2.head_oid(repo) == pre_abort_head finally close(repo) end From d266f922519d5a7981737a52e448a4ee951a266a Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Wed, 29 Mar 2017 17:19:17 -0400 Subject: [PATCH 0316/1534] Fix rem/mod doc (#21223) --- base/int.jl | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/base/int.jl b/base/int.jl index ab472260cbb59..870742b939482 100644 --- a/base/int.jl +++ b/base/int.jl @@ -359,20 +359,24 @@ for to in BitInteger_types, from in (BitInteger_types..., Bool) end end -""" - rem(x::Integer, T::Type{<:Integer}) - mod(x::Integer, T::Type{<:Integer}) - %(x::Integer, T::Type{<:Integer}) - -Find `y::T` such that `x` ≡ `y` (mod n), where n is the number of integers representable -in `T`, and `y` is an integer in `[typemin(T),typemax(T)]`. - -```jldoctest -julia> 129 % Int8 --127 -``` -""" -function rem(x::Integer, T::Type) end, function mod(x::Integer, T::Type) end +# @doc isn't available when running in Core at this point. +# Tuple syntax for documention two function signatures at the same time +# doesn't work either at this point. +isdefined(Main, :Base) && for fname in (:mod, :rem) + @eval @doc """ + rem(x::Integer, T::Type{<:Integer}) + mod(x::Integer, T::Type{<:Integer}) + %(x::Integer, T::Type{<:Integer}) + + Find `y::T` such that `x` ≡ `y` (mod n), where n is the number of integers representable + in `T`, and `y` is an integer in `[typemin(T),typemax(T)]`. + + ```jldoctest + julia> 129 % Int8 + -127 + ``` + """ -> $fname(x::Integer, T::Type{<:Integer}) +end rem{T<:Integer}(x::T, ::Type{T}) = x rem(x::Integer, ::Type{Bool}) = ((x & 1) != 0) From 182d8e89d84b562b436fca62b6a0d3f22fde8eae Mon Sep 17 00:00:00 2001 From: kshyatt Date: Wed, 29 Mar 2017 15:47:17 -0700 Subject: [PATCH 0317/1534] Two minitests for show --- test/show.jl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/show.jl b/test/show.jl index 819e559a95604..e70904452b64b 100644 --- a/test/show.jl +++ b/test/show.jl @@ -544,6 +544,11 @@ let io = IOBuffer() @test String(take!(io)) == "[1, 2]" end +let io = IOBuffer() + ioc = IOContext(io, :limit => true) + @test sprint(show, ioc) == "IOContext($(sprint(show, ioc.io)))" +end + # PR 17117 # test show array let s = IOBuffer(Array{UInt8}(0), true, true) @@ -663,3 +668,5 @@ let m = which(T20332{Int}(), (Int,)), # test that this doesn't throw an error @test contains(repr(mi), "MethodInstance for") end + +@test sprint(show, Main) == "Main" From c0e4c24c9e3830896f4fa208dac6817ce2529304 Mon Sep 17 00:00:00 2001 From: Simon Kornblith Date: Wed, 29 Mar 2017 21:11:18 -0400 Subject: [PATCH 0318/1534] Make cor work again for complex input (#21205) Also fix inconsistency in `cov` of vectors. Fixes #21093 --- base/statistics.jl | 38 ++++++++++++++++++++++++-------------- test/statistics.jl | 18 ++++++++++++++++++ 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/base/statistics.jl b/base/statistics.jl index 16528d73bd600..12bf64921a026 100644 --- a/base/statistics.jl +++ b/base/statistics.jl @@ -307,7 +307,7 @@ _vmean(x::AbstractMatrix, vardim::Int) = mean(x, vardim) unscaled_covzm(x::AbstractVector) = sum(abs2, x) unscaled_covzm(x::AbstractMatrix, vardim::Int) = (vardim == 1 ? _conj(x'x) : x * x') -unscaled_covzm(x::AbstractVector, y::AbstractVector) = dot(x, y) +unscaled_covzm(x::AbstractVector, y::AbstractVector) = dot(y, x) unscaled_covzm(x::AbstractVector, y::AbstractMatrix, vardim::Int) = (vardim == 1 ? At_mul_B(x, _conj(y)) : At_mul_Bt(x, _conj(y))) unscaled_covzm(x::AbstractMatrix, y::AbstractVector, vardim::Int) = @@ -362,9 +362,10 @@ cov(X::AbstractMatrix) = cov(X, 1, true) """ cov(x, y[, corrected=true]) -Compute the covariance between the vectors `x` and `y`. If `corrected` is `true` (the default) -then the sum is scaled with `n-1`, whereas the sum is scaled with `n` if `corrected` is `false` -where `n = length(x) = length(y)`. +Compute the covariance between the vectors `x` and `y`. If `corrected` is `true` (the +default), computes ``\\frac{1}{n-1}\\sum_{i=1}^n (x_i-\\bar x) (y_i-\\bar y)^*`` where +``*`` denotes the complex conjugate and `n = length(x) = length(y)`. If `corrected` is +`false`, computes ``\frac{1}{n}\sum_{i=1}^n (x_i-\\bar x) (y_i-\\bar y)^*``. """ cov(x::AbstractVector, y::AbstractVector, corrected::Bool) = covm(x, Base.mean(x), y, Base.mean(y), corrected) @@ -388,6 +389,14 @@ cov(X::AbstractMatrix, Y::AbstractMatrix) = cov(X, Y, 1, true) ##### correlation ##### +""" + clampcor(x) + +Clamp a real correlation to between -1 and 1, leaving complex correlations unchanged +""" +clampcor(x::Real) = clamp(x, -1, 1) +clampcor(x) = x + # cov2cor! function cov2cor!{T}(C::AbstractMatrix{T}, xsd::AbstractArray) @@ -395,11 +404,11 @@ function cov2cor!{T}(C::AbstractMatrix{T}, xsd::AbstractArray) size(C) == (nx, nx) || throw(DimensionMismatch("inconsistent dimensions")) for j = 1:nx for i = 1:j-1 - C[i,j] = C[j,i] + C[i,j] = C[j,i]' end C[j,j] = oneunit(T) for i = j+1:nx - C[i,j] = clamp(C[i,j] / (xsd[i] * xsd[j]), -1, 1) + C[i,j] = clampcor(C[i,j] / (xsd[i] * xsd[j])) end end return C @@ -409,7 +418,7 @@ function cov2cor!(C::AbstractMatrix, xsd::Number, ysd::AbstractArray) length(ysd) == ny || throw(DimensionMismatch("inconsistent dimensions")) for (j, y) in enumerate(ysd) # fixme (iter): here and in all `cov2cor!` we assume that `C` is efficiently indexed by integers for i in 1:nx - C[i,j] = clamp(C[i, j] / (xsd * y), -1, 1) + C[i,j] = clampcor(C[i, j] / (xsd * y)) end end return C @@ -419,7 +428,7 @@ function cov2cor!(C::AbstractMatrix, xsd::AbstractArray, ysd::Number) length(xsd) == nx || throw(DimensionMismatch("inconsistent dimensions")) for j in 1:ny for (i, x) in enumerate(xsd) - C[i,j] = clamp(C[i,j] / (x * ysd), -1, 1) + C[i,j] = clampcor(C[i,j] / (x * ysd)) end end return C @@ -430,7 +439,7 @@ function cov2cor!(C::AbstractMatrix, xsd::AbstractArray, ysd::AbstractArray) throw(DimensionMismatch("inconsistent dimensions")) for (i, x) in enumerate(xsd) for (j, y) in enumerate(ysd) - C[i,j] = clamp(C[i,j] / (x * y), -1, 1) + C[i,j] = clampcor(C[i,j] / (x * y)) end end return C @@ -461,11 +470,11 @@ function corm(x::AbstractVector, mx::Number, y::AbstractVector, my::Number) @inbounds begin # Initialize the accumulators - xx = zero(sqrt(x[1] * x[1])) - yy = zero(sqrt(y[1] * y[1])) - xy = zero(xx * yy) + xx = zero(sqrt(abs2(x[1]))) + yy = zero(sqrt(abs2(y[1]))) + xy = zero(x[1] * y[1]') - @simd for i = 1:n + @simd for i in eachindex(x, y) xi = x[i] - mx yi = y[i] - my xx += abs2(xi) @@ -473,8 +482,9 @@ function corm(x::AbstractVector, mx::Number, y::AbstractVector, my::Number) xy += xi * yi' end end - return clamp(xy / max(xx, yy) / sqrt(min(xx, yy) / max(xx, yy)), -1, 1) + return clampcor(xy / max(xx, yy) / sqrt(min(xx, yy) / max(xx, yy))) end + corm(x::AbstractVecOrMat, xmean, y::AbstractVecOrMat, ymean, vardim::Int=1) = corzm(x .- xmean, y .- ymean, vardim) diff --git a/test/statistics.jl b/test/statistics.jl index 802c02f427ba5..d6fd138ae7951 100644 --- a/test/statistics.jl +++ b/test/statistics.jl @@ -348,6 +348,24 @@ let v = varm([1.0+2.0im], 0; corrected = false) @test isa(v, Float64) end +# cov and cor of complex arrays (issue #21093) +x = [2.7 - 3.3im, 0.9 + 5.4im, 0.1 + 0.2im, -1.7 - 5.8im, 1.1 + 1.9im] +y = [-1.7 - 1.6im, -0.2 + 6.5im, 0.8 - 10.0im, 9.1 - 3.4im, 2.7 - 5.5im] +@test cov(x, y) ≈ 4.8365 - 12.119im +@test cov(y, x) ≈ 4.8365 + 12.119im +@test cov(x, reshape(y, :, 1)) ≈ reshape([4.8365 - 12.119im], 1, 1) +@test cov(reshape(x, :, 1), y) ≈ reshape([4.8365 - 12.119im], 1, 1) +@test cov(reshape(x, :, 1), reshape(y, :, 1)) ≈ reshape([4.8365 - 12.119im], 1, 1) +@test cov([x y]) ≈ [21.779 4.8365-12.119im; + 4.8365+12.119im 54.548] +@test cor(x, y) ≈ 0.14032104449218274 - 0.35160772008699703im +@test cor(y, x) ≈ 0.14032104449218274 + 0.35160772008699703im +@test cor(x, reshape(y, :, 1)) ≈ reshape([0.14032104449218274 - 0.35160772008699703im], 1, 1) +@test cor(reshape(x, :, 1), y) ≈ reshape([0.14032104449218274 - 0.35160772008699703im], 1, 1) +@test cor(reshape(x, :, 1), reshape(y, :, 1)) ≈ reshape([0.14032104449218274 - 0.35160772008699703im], 1, 1) +@test cor([x y]) ≈ [1.0 0.14032104449218274-0.35160772008699703im + 0.14032104449218274+0.35160772008699703im 1.0] + # Issue #17153 and PR #17154 let a = rand(10,10) b = deepcopy(a) From 6659b59fee30232c77cefbba1848b958041f5c61 Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Thu, 30 Mar 2017 03:46:52 -0400 Subject: [PATCH 0319/1534] Fix build with LLVM master. (#21194) In LLVMFPtoInt signature of convertToInteger now expects a MutableArrayRef. AttributeSet -> AttributeList --- src/APInt-C.cpp | 4 ++++ src/ccall.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++++-- src/codegen.cpp | 13 +++++++++++++ src/llvm-ptls.cpp | 14 ++++++++++++++ 4 files changed, 75 insertions(+), 2 deletions(-) diff --git a/src/APInt-C.cpp b/src/APInt-C.cpp index 6c29d7e9ced40..07868aee1506d 100644 --- a/src/APInt-C.cpp +++ b/src/APInt-C.cpp @@ -352,7 +352,11 @@ void LLVMFPtoInt(unsigned numbits, integerPart *pa, unsigned onumbits, integerPa APFloat::roundingMode rounding_mode = APFloat::rmNearestTiesToEven; unsigned nbytes = RoundUpToAlignment(onumbits, integerPartWidth) / host_char_bit; integerPart *parts = (integerPart*)alloca(nbytes); +#if JL_LLVM_VERSION >= 50000 + APFloat::opStatus status = a.convertToInteger(MutableArrayRef(parts, nbytes), onumbits, isSigned, rounding_mode, &isVeryExact); +#else APFloat::opStatus status = a.convertToInteger(parts, onumbits, isSigned, rounding_mode, &isVeryExact); +#endif memcpy(pr, parts, onumbytes); if (isExact) *isExact = (status == APFloat::opOK); diff --git a/src/ccall.cpp b/src/ccall.cpp index 37215e94ba992..c80ad39ce9d50 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -206,13 +206,22 @@ static Value *runtime_sym_lookup(PointerType *funcptype, const char *f_lib, // all the arguments without writing assembly directly. // This doesn't matter too much in reality since a single function is usually // not called with multiple signatures. +#if JL_LLVM_VERSION >= 50000 +static DenseMap,GlobalVariable*>> allPltMap; // Emit a "PLT" entry that will be lazily initialized // when being called the first time. -static GlobalVariable *emit_plt_thunk(Module *M, FunctionType *functype, const AttributeSet &attrs, +static GlobalVariable *emit_plt_thunk(Module *M, FunctionType *functype, +#if JL_LLVM_VERSION >= 50000 + const AttributeList &attrs, +#else + const AttributeSet &attrs, +#endif CallingConv::ID cc, const char *f_lib, const char *f_name, GlobalVariable *libptrgv, GlobalVariable *llvmgv, void *symaddr, bool runtime_lib) @@ -260,7 +269,11 @@ static GlobalVariable *emit_plt_thunk(Module *M, FunctionType *functype, const A // NoReturn function can trigger LLVM verifier error when declared as // MustTail since other passes might replace the `ret` with // `unreachable` (LLVM should probably accept `unreachable`). +#if JL_LLVM_VERSION >= 50000 + if (attrs.hasAttribute(AttributeList::FunctionIndex, +#else if (attrs.hasAttribute(AttributeSet::FunctionIndex, +#endif Attribute::NoReturn)) { builder.CreateUnreachable(); } @@ -291,7 +304,12 @@ static GlobalVariable *emit_plt_thunk(Module *M, FunctionType *functype, const A return got; } -static Value *emit_plt(FunctionType *functype, const AttributeSet &attrs, +static Value *emit_plt(FunctionType *functype, +#if JL_LLVM_VERSION >= 50000 + const AttributeList &attrs, +#else + const AttributeSet &attrs, +#endif CallingConv::ID cc, const char *f_lib, const char *f_name) { assert(imaging_mode); @@ -1211,7 +1229,11 @@ class function_sig_t { std::vector fargt_isboxed; // vector of whether the llvm output type is a Julia-box for each argument (vararg is the last item, if applicable) Type *fargt_vasig = NULL; // ABI coercion type for vararg list std::vector byRefList; // vector of "byref" parameters (vararg is the last item, if applicable) +#if JL_LLVM_VERSION >= 50000 + AttributeList attributes; // vector of function call site attributes (vararg is the last item, if applicable) +#else AttributeSet attributes; // vector of function call site attributes (vararg is the last item, if applicable) +#endif Type *lrt; // input parameter of the llvm return type (from julia_struct_to_llvm) bool retboxed; // input parameter indicating whether lrt is jl_value_t* Type *prt; // out parameter of the llvm return type for the function signature @@ -1252,7 +1274,11 @@ std::string generate_func_sig() size_t nargt = jl_svec_len(at); assert(rt && !jl_is_abstract_ref_type(rt)); +#if JL_LLVM_VERSION >= 50000 + std::vector paramattrs; +#else std::vector paramattrs; +#endif std::unique_ptr abi; if (llvmcall) abi.reset(new ABI_LLVMLayout()); @@ -1275,7 +1301,11 @@ std::string generate_func_sig() retattrs.addAttribute(Attribute::StructRet); #endif retattrs.addAttribute(Attribute::NoAlias); +#if JL_LLVM_VERSION >= 50000 + paramattrs.push_back(AttributeList::get(jl_LLVMContext, 1, retattrs)); +#else paramattrs.push_back(AttributeSet::get(jl_LLVMContext, 1, retattrs)); +#endif fargt_sig.push_back(PointerType::get(lrt, 0)); sret = 1; prt = lrt; @@ -1357,7 +1387,11 @@ std::string generate_func_sig() do { // for each arg for which this type applies, add the appropriate LLVM parameter attributes if (i < nargs) { // if vararg, the last declared arg type may not have a corresponding arg value +#if JL_LLVM_VERSION >= 50000 + AttributeList params = AttributeList::get(jl_LLVMContext, i + sret + 1, ab); +#else AttributeSet params = AttributeSet::get(jl_LLVMContext, i + sret + 1, ab); +#endif paramattrs.push_back(params); } i++; @@ -1365,13 +1399,21 @@ std::string generate_func_sig() } for (i = 0; i < nargs + sret; ++i) { +#if JL_LLVM_VERSION >= 50000 + const AttributeList &as = paramattrs.at(i); +#else const AttributeSet &as = paramattrs.at(i); +#endif if (!as.isEmpty()) attributes = attributes.addAttributes(jl_LLVMContext, i + 1, as); } if (rt == jl_bottom_type) { attributes = attributes.addAttribute(jl_LLVMContext, +#if JL_LLVM_VERSION >= 50000 + AttributeList::FunctionIndex, +#else AttributeSet::FunctionIndex, +#endif Attribute::NoReturn); } return ""; diff --git a/src/codegen.cpp b/src/codegen.cpp index 49ad65e66ec24..210ca52284752 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -5253,10 +5253,16 @@ static std::unique_ptr emit_function( // i686 Windows (which uses a 4-byte-aligned stack) AttrBuilder *attr = new AttrBuilder(); attr->addStackAlignmentAttr(16); +#if JL_LLVM_VERSION >= 50000 + f->addAttributes(AttributeList::FunctionIndex, + AttributeList::get(f->getContext(), + AttributeList::FunctionIndex, *attr)); +#else f->addAttributes(AttributeSet::FunctionIndex, AttributeSet::get(f->getContext(), AttributeSet::FunctionIndex, *attr)); #endif +#endif #if defined(_OS_WINDOWS_) && defined(_CPU_X86_64_) && JL_LLVM_VERSION >= 30500 f->setHasUWTable(); // force NeedsWinEH #endif @@ -6904,10 +6910,17 @@ static void init_julia_llvm_env(Module *m) "jl_array_data_owner", m); jlarray_data_owner_func->setAttributes( jlarray_data_owner_func->getAttributes() +#if JL_LLVM_VERSION >= 50000 + .addAttribute(jlarray_data_owner_func->getContext(), + AttributeList::FunctionIndex, Attribute::ReadOnly) + .addAttribute(jlarray_data_owner_func->getContext(), + AttributeList::FunctionIndex, Attribute::NoUnwind)); +#else .addAttribute(jlarray_data_owner_func->getContext(), AttributeSet::FunctionIndex, Attribute::ReadOnly) .addAttribute(jlarray_data_owner_func->getContext(), AttributeSet::FunctionIndex, Attribute::NoUnwind)); +#endif add_named_global(jlarray_data_owner_func, jl_array_data_owner); gcroot_func = diff --git a/src/llvm-ptls.cpp b/src/llvm-ptls.cpp index 12286e7a6fe0a..8452b1428159f 100644 --- a/src/llvm-ptls.cpp +++ b/src/llvm-ptls.cpp @@ -102,10 +102,17 @@ void LowerPTLS::runOnFunction(LLVMContext &ctx, Module &M, Function *F, LoadInst *getter = new LoadInst(GV, "", ptlsStates); getter->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_const); ptlsStates->setCalledFunction(getter); +#if JL_LLVM_VERSION >= 50000 + ptlsStates->addAttribute(AttributeList::FunctionIndex, + Attribute::ReadNone); + ptlsStates->addAttribute(AttributeList::FunctionIndex, + Attribute::NoUnwind); +#else ptlsStates->addAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone); ptlsStates->addAttribute(AttributeSet::FunctionIndex, Attribute::NoUnwind); +#endif } #if JL_LLVM_VERSION >= 30700 else if (jl_tls_offset != -1) { @@ -160,10 +167,17 @@ void LowerPTLS::runOnFunction(LLVMContext &ctx, Module &M, Function *F, } #endif else { +#if JL_LLVM_VERSION >= 50000 + ptlsStates->addAttribute(AttributeList::FunctionIndex, + Attribute::ReadNone); + ptlsStates->addAttribute(AttributeList::FunctionIndex, + Attribute::NoUnwind); +#else ptlsStates->addAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone); ptlsStates->addAttribute(AttributeSet::FunctionIndex, Attribute::NoUnwind); +#endif } #else ptlsStates->replaceAllUsesWith(M.getNamedValue("jl_tls_states")); From 0ae9e97a24ec3129ed50c954dbce65e6d6f2279b Mon Sep 17 00:00:00 2001 From: kshyatt Date: Thu, 30 Mar 2017 11:08:16 -0700 Subject: [PATCH 0320/1534] Add tests for internal fastforward merge methods --- test/libgit2.jl | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/test/libgit2.jl b/test/libgit2.jl index 147f2d28950dd..eb46f77cea37e 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -619,6 +619,40 @@ mktempdir() do dir end end + # TO DO: add more tests for various merge + # preference options + @testset "Fastforward merges" begin + path = joinpath(dir, "Example.FF") + repo = LibGit2.clone(cache_repo, path) + try + oldhead = LibGit2.head_oid(repo) + LibGit2.branch!(repo, "branch/ff_a") + open(joinpath(LibGit2.path(repo),"ff_file1"),"w") do f + write(f, "111\n") + end + LibGit2.add!(repo, "ff_file1") + LibGit2.commit(repo, "add ff_file1") + + open(joinpath(LibGit2.path(repo),"ff_file2"),"w") do f + write(f, "222\n") + end + LibGit2.add!(repo, "ff_file2") + LibGit2.commit(repo, "add ff_file2") + LibGit2.branch!(repo, "master") + # switch back, now try to ff-merge the changes + # from branch/a + + upst_ann = LibGit2.GitAnnotated(repo, "branch/ff_a") + head_ann = LibGit2.GitAnnotated(repo, "master") + + # ff merge them + @test LibGit2.merge!(repo, [upst_ann], true) + @test LibGit2.is_ancestor_of(string(oldhead), string(LibGit2.head_oid(repo)), repo) + finally + close(repo) + end + end + @testset "Fetch from cache repository" begin repo = LibGit2.GitRepo(test_repo) try From 9baadbf5367038943a0299ea86e26e6330b912cd Mon Sep 17 00:00:00 2001 From: Ranjan Anantharaman Date: Fri, 31 Mar 2017 02:41:03 +0530 Subject: [PATCH 0321/1534] Fix bug in backsolve of sparse hermitian matrices (#21165) --- base/sparse/linalg.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/sparse/linalg.jl b/base/sparse/linalg.jl index 6884421febf0b..389c5376cabf1 100644 --- a/base/sparse/linalg.jl +++ b/base/sparse/linalg.jl @@ -864,7 +864,7 @@ function (\)(A::SparseMatrixCSC, B::AbstractVecOrMat) return UpperTriangular(A) \ B end if ishermitian(A) - Hermitian(A) \ B + return Hermitian(A) \ B end return lufact(A) \ B else From c86ac62abcd73ec0111f0c932f5d35a53b5a34a1 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 30 Mar 2017 18:11:21 -0400 Subject: [PATCH 0322/1534] fix #21168, `f.[1,2,3]` should be an error --- src/ast.scm | 10 +++++++--- src/julia-syntax.scm | 9 ++++++--- test/parse.jl | 4 ++++ 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/ast.scm b/src/ast.scm index 7b3626bea3656..29408af897439 100644 --- a/src/ast.scm +++ b/src/ast.scm @@ -28,9 +28,12 @@ ((atom? e) (string e)) ((eq? (car e) '|.|) (string (deparse (cadr e)) '|.| - (if (and (pair? (caddr e)) (memq (caaddr e) '(quote inert))) - (deparse (cadr (caddr e))) - (string #\( (deparse (caddr e)) #\))))) + (cond ((and (pair? (caddr e)) (memq (caaddr e) '(quote inert))) + (deparse (cadr (caddr e)))) + ((and (pair? (caddr e)) (eq? (caaddr e) 'copyast)) + (deparse (cadr (cadr (caddr e))))) + (else + (string #\( (deparse (caddr e)) #\)))))) ((memq (car e) '(... |'| |.'|)) (string (deparse (cadr e)) (car e))) ((or (syntactic-op? (car e)) (eq? (car e) '|<:|) (eq? (car e) '|>:|)) @@ -91,6 +94,7 @@ ((function for while) (deparse-block (string (car e) " " (deparse (cadr e))) (block-stmts (caddr e)))) + ((copyast) (deparse (cadr e))) (else (string e)))))) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index f70368039b002..ad6d7a4bd8c93 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -1694,9 +1694,12 @@ `(fuse ,(to-lambda f args kws) ,args_)))) (if (and (pair? e) (eq? (car e) '|.|)) (let ((f (cadr e)) (x (caddr e))) - (if (or (eq? (car x) 'quote) (eq? (car x) 'inert) (eq? (car x) '$)) - `(call (core getfield) ,f ,x) - (make-fuse f (cdr x)))) + (cond ((or (eq? (car x) 'quote) (eq? (car x) 'inert) (eq? (car x) '$)) + `(call (core getfield) ,f ,x)) + ((eq? (car x) 'tuple) + (make-fuse f (cdr x))) + (else + (error (string "invalid syntax " (deparse e)))))) (if (and (pair? e) (eq? (car e) 'call) (dotop? (cadr e))) (make-fuse (undotop (cadr e)) (cddr e)) e))) diff --git a/test/parse.jl b/test/parse.jl index 79b7f97a36afa..8fc8d6a1f1d4f 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -1061,3 +1061,7 @@ end @test isa(f21054, Function) g21054(>:) = >:2 @test g21054(-) == -2 + +# issue #21168 +@test expand(:(a.[1])) == Expr(:error, "invalid syntax a.[1]") +@test expand(:(a.{1})) == Expr(:error, "invalid syntax a.{1}") From cded1dbc0194342bb977f7cfe387badc3b4cd7f7 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Thu, 30 Mar 2017 17:28:53 -0700 Subject: [PATCH 0323/1534] Add methods to add refspecs and tests to view fetchspecs (#21227) * Add methods to add refspecs and tests to view fetchspecs * Add docs * fix explicity typo and very minor wording tweak --- base/libgit2/remote.jl | 55 ++++++++++++++++++++++++++++++++++++++++++ test/libgit2.jl | 6 +++++ 2 files changed, 61 insertions(+) diff --git a/base/libgit2/remote.jl b/base/libgit2/remote.jl index 4ba586ea862d6..8951fb079f758 100644 --- a/base/libgit2/remote.jl +++ b/base/libgit2/remote.jl @@ -103,6 +103,54 @@ function push_refspecs(rmt::GitRemote) res end +""" + add_fetch!(repo::GitRepo, rmt::GitRemote, fetch_spec::String) + +Add a *fetch* refspec for the specified `rmt`. This refspec will contain +information about which branch(es) to fetch from. + +# Example +```julia +julia> LibGit2.add_fetch!(repo, remote, "upstream"); + +julia> LibGit2.fetch_refspecs(remote) +String["+refs/heads/*:refs/remotes/upstream/*"] +``` +""" +function add_fetch!(repo::GitRepo, rmt::GitRemote, fetch_spec::String) + @check ccall((:git_remote_add_fetch, :libgit2), Cint, + (Ptr{Void}, Cstring, Cstring), repo.ptr, + name(rmt), fetch_spec) +end + +""" + add_push!(repo::GitRepo, rmt::GitRemote, push_spec::String) + +Add a *push* refspec for the specified `rmt`. This refspec will contain +information about which branch(es) to push to. + +# Example +```julia +julia> LibGit2.add_push!(repo, remote, "refs/heads/master"); + +julia> remote = LibGit2.get(LibGit2.GitRemote, repo, branch); + +julia> LibGit2.push_refspecs(remote) +String["refs/heads/master"] +``` + +!!! note + You may need to [`close`](@ref) and reopen the `GitRemote` + in question after updating its push refspecs in order for + the change to take effect and for calls to [`push`](@ref) + to work. +""" +function add_push!(repo::GitRepo, rmt::GitRemote, push_spec::String) + @check ccall((:git_remote_add_push, :libgit2), Cint, + (Ptr{Void}, Cstring, Cstring), repo.ptr, + name(rmt), push_spec) +end + """ fetch(rmt::GitRemote, refspecs; options::FetchOptions=FetchOptions(), msg="") @@ -129,6 +177,13 @@ determine which remote branch(es) to push to. The keyword arguments are: * `force`: if `true`, a force-push will occur, disregarding conflicts. * `options`: determines the options for the push, e.g. which proxy headers to use. + +!!! note + You can add information about the push refspecs in two other ways: by setting + an option in the repository's `GitConfig` (with `push.default` as the key) or + by calling [`add_push!`](@ref). Otherwise you will need to explicitly specify + a push refspec in the call to `push` for it to have any effect, like so: + `LibGit2.push(repo, refspecs=["refs/heads/master"])`. """ function push(rmt::GitRemote, refspecs::Vector{<:AbstractString}; force::Bool = false, options::PushOptions = PushOptions()) diff --git a/test/libgit2.jl b/test/libgit2.jl index 147f2d28950dd..655ef7684483a 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -214,6 +214,12 @@ mktempdir() do dir LibGit2.set_remote_url(cache_repo, repo_url, remote="upstream") remote = LibGit2.get(LibGit2.GitRemote, repo, branch) @test sprint(show, remote) == "GitRemote:\nRemote name: upstream url: $repo_url" + LibGit2.add_fetch!(repo, remote, "upstream") + @test LibGit2.fetch_refspecs(remote) == String["+refs/heads/*:refs/remotes/upstream/*"] + LibGit2.add_push!(repo, remote, "refs/heads/master") + close(remote) + remote = LibGit2.get(LibGit2.GitRemote, repo, branch) + @test LibGit2.push_refspecs(remote) == String["refs/heads/master"] close(remote) remote = LibGit2.GitRemoteAnon(repo, repo_url) From bd84fa1bad1e08b5c368999aa9b07e4382f54910 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Fri, 31 Mar 2017 05:58:56 -0700 Subject: [PATCH 0324/1534] Tag 0.6.0-pre.beta (#21232) --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 400d7dd6ed0c7..dda172758e203 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.6.0-pre.alpha +0.6.0-pre.beta From e06ff562c3401f16f4b379a8542df3f3f6db4e55 Mon Sep 17 00:00:00 2001 From: kshyatt Date: Thu, 30 Mar 2017 11:30:21 -0700 Subject: [PATCH 0325/1534] Non-ff merge test --- test/libgit2.jl | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/test/libgit2.jl b/test/libgit2.jl index eb46f77cea37e..afca452af4109 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -624,6 +624,10 @@ mktempdir() do dir @testset "Fastforward merges" begin path = joinpath(dir, "Example.FF") repo = LibGit2.clone(cache_repo, path) + # need to set this for merges to succeed + cfg = LibGit2.GitConfig(repo) + LibGit2.set!(cfg, "user.name", "AAAA") + LibGit2.set!(cfg, "user.email", "BBBB@BBBB.COM") try oldhead = LibGit2.head_oid(repo) LibGit2.branch!(repo, "branch/ff_a") @@ -653,6 +657,45 @@ mktempdir() do dir end end + @testset "Merges" begin + path = joinpath(dir, "Example.Merge") + repo = LibGit2.clone(cache_repo, path) + # need to set this for merges to succeed + cfg = LibGit2.GitConfig(repo) + LibGit2.set!(cfg, "user.name", "AAAA") + LibGit2.set!(cfg, "user.email", "BBBB@BBBB.COM") + try + oldhead = LibGit2.head_oid(repo) + LibGit2.branch!(repo, "branch/merge_a") + open(joinpath(LibGit2.path(repo),"file1"),"w") do f + write(f, "111\n") + end + LibGit2.add!(repo, "file1") + LibGit2.commit(repo, "add file1") + + # switch back, add a commit, try to merge + # from branch/merge_a + LibGit2.branch!(repo, "master") + + open(joinpath(LibGit2.path(repo), "file2"), "w") do f + write(f, "222\n") + end + LibGit2.add!(repo, "file2") + LibGit2.commit(repo, "add file2") + + upst_ann = LibGit2.GitAnnotated(repo, "branch/merge_a") + head_ann = LibGit2.GitAnnotated(repo, "master") + + # (fail to) merge them because we can't fastforward + @test !LibGit2.merge!(repo, [upst_ann], true) + # merge them now that we allow non-ff + @test LibGit2.merge!(repo, [upst_ann], false) + @test LibGit2.is_ancestor_of(string(oldhead), string(LibGit2.head_oid(repo)), repo) + finally + close(repo) + end + end + @testset "Fetch from cache repository" begin repo = LibGit2.GitRepo(test_repo) try From 769b9d713a365c6d230c58974f632474d7506f39 Mon Sep 17 00:00:00 2001 From: kshyatt Date: Fri, 31 Mar 2017 14:37:07 -0700 Subject: [PATCH 0326/1534] Add a test for GitRemote ctor with refspec --- test/libgit2.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/libgit2.jl b/test/libgit2.jl index 655ef7684483a..8a6bb4f782bcf 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -221,6 +221,11 @@ mktempdir() do dir remote = LibGit2.get(LibGit2.GitRemote, repo, branch) @test LibGit2.push_refspecs(remote) == String["refs/heads/master"] close(remote) + # constructor with a refspec + remote = LibGit2.GitRemote(repo, "upstream2", repo_url, "upstream") + @test sprint(show, remote) == "GitRemote:\nRemote name: upstream2 url: $repo_url" + @test LibGit2.fetch_refspecs(remote) == String["upstream"] + close(remote) remote = LibGit2.GitRemoteAnon(repo, repo_url) @test LibGit2.url(remote) == repo_url From 553c9205901310b994fddf16b99ec657ee817089 Mon Sep 17 00:00:00 2001 From: kshyatt Date: Fri, 31 Mar 2017 16:18:08 -0700 Subject: [PATCH 0327/1534] Tests for cleanup and branch deletion --- test/libgit2.jl | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/libgit2.jl b/test/libgit2.jl index 655ef7684483a..47256e0960f8e 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -162,6 +162,7 @@ mktempdir() do dir commit_oid3 = LibGit2.GitHash() master_branch = "master" test_branch = "test_branch" + test_branch2 = "test_branch_two" tag1 = "tag1" tag2 = "tag2" @@ -252,6 +253,14 @@ mktempdir() do dir @test typeof(e) == LibGit2.GitError @test startswith(sprint(show,e),"GitError(Code:ENOTFOUND, Class:OS, Failed to resolve path") end + path = joinpath(dir, "Example.BareTwo") + repo = LibGit2.init(path, true) + try + #just to see if this works + LibGit2.cleanup(repo) + finally + close(repo) + end end end @@ -416,6 +425,16 @@ mktempdir() do dir finally close(tbref) end + @test isnull(LibGit2.lookup_branch(repo, test_branch2, true)) + LibGit2.branch!(repo, test_branch2; set_head=false) + tbref = Base.get(LibGit2.lookup_branch(repo, test_branch2, false)) + try + @test LibGit2.shortname(tbref) == test_branch2 + LibGit2.delete_branch(tbref) + @test isnull(LibGit2.lookup_branch(repo, test_branch2, true)) + finally + close(tbref) + end finally close(brref) end From ad6675856d6c62144abf116d706b21333c373b72 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Sat, 1 Apr 2017 10:17:48 +0700 Subject: [PATCH 0328/1534] document that srand() returns the passed RNG --- base/random.jl | 2 +- test/random.jl | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/base/random.jl b/base/random.jl index 074cd1cbc7bc3..01912627a784c 100644 --- a/base/random.jl +++ b/base/random.jl @@ -220,7 +220,7 @@ end ## srand() """ - srand([rng=GLOBAL_RNG], [seed]) + srand([rng=GLOBAL_RNG], [seed]) -> rng Reseed the random number generator. If a `seed` is provided, the RNG will give a reproducible sequence of numbers, otherwise Julia will get entropy from the system. For diff --git a/test/random.jl b/test/random.jl index 90a126a05d996..daa698baea0d5 100644 --- a/test/random.jl +++ b/test/random.jl @@ -479,3 +479,18 @@ let seed = rand(UInt32, 10) resize!(seed, 4) @test r.seed != seed end + +# srand(rng, ...) returns rng (#21248) +let g = Base.Random.GLOBAL_RNG, + m = MersenneTwister(0) + @test srand() === g + @test srand(rand(UInt)) === g + @test srand(rand(UInt32, rand(1:10))) === g + @test srand(@__FILE__) === g + @test srand(@__FILE__, rand(1:10)) === g + @test srand(m) === m + @test srand(m, rand(UInt)) === m + @test srand(m, rand(UInt32, rand(1:10))) === m + @test srand(m, rand(1:10)) === m + @test srand(m, @__FILE__, rand(1:10)) === m +end From 8d82fc6df2aa6e76445a3901d4cd161e33fec6eb Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Sat, 1 Apr 2017 11:01:20 +0700 Subject: [PATCH 0329/1534] document the numeric argument in srand(rng, filename, n=4) --- base/random.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/base/random.jl b/base/random.jl index 01912627a784c..a8d70e35b0db3 100644 --- a/base/random.jl +++ b/base/random.jl @@ -221,12 +221,13 @@ end """ srand([rng=GLOBAL_RNG], [seed]) -> rng + srand([rng=GLOBAL_RNG], filename, n=4) -> rng Reseed the random number generator. If a `seed` is provided, the RNG will give a reproducible sequence of numbers, otherwise Julia will get entropy from the system. For `MersenneTwister`, the `seed` may be a non-negative integer, a vector of `UInt32` integers -or a filename, in which case the seed is read from a file. `RandomDevice` does not support -seeding. +or a filename, in which case the seed is read from a file (`4n` bytes are read from the file, +where `n` is an optional argument). `RandomDevice` does not support seeding. """ srand(r::MersenneTwister) = srand(r, make_seed()) srand(r::MersenneTwister, n::Integer) = srand(r, make_seed(n)) From e664f52c5a0f9d9eaf7dd07b147e6e309ccfa4ce Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Sat, 1 Apr 2017 11:52:51 +0700 Subject: [PATCH 0330/1534] extend the definition of x % T for T == BigInt --- base/gmp.jl | 2 ++ base/int.jl | 8 +++++--- test/int.jl | 6 ++++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/base/gmp.jl b/base/gmp.jl index 5e339929b88cc..aa3e088c9afb1 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -178,6 +178,8 @@ function rem{T<:Union{Unsigned,Signed}}(x::BigInt, ::Type{T}) x.size < 0 ? -u : u end +rem(x::Integer, ::Type{BigInt}) = convert(BigInt, x) + function convert{T<:Unsigned}(::Type{T}, x::BigInt) if sizeof(T) < sizeof(Limb) convert(T, convert(Limb,x)) diff --git a/base/int.jl b/base/int.jl index 870742b939482..88b20efc85995 100644 --- a/base/int.jl +++ b/base/int.jl @@ -364,12 +364,14 @@ end # doesn't work either at this point. isdefined(Main, :Base) && for fname in (:mod, :rem) @eval @doc """ - rem(x::Integer, T::Type{<:Integer}) - mod(x::Integer, T::Type{<:Integer}) - %(x::Integer, T::Type{<:Integer}) + rem(x::Integer, T::Type{<:Integer}) -> T + mod(x::Integer, T::Type{<:Integer}) -> T + %(x::Integer, T::Type{<:Integer}) -> T Find `y::T` such that `x` ≡ `y` (mod n), where n is the number of integers representable in `T`, and `y` is an integer in `[typemin(T),typemax(T)]`. + If `T` can represent any integer (e.g. `T == BigInt`), then this operation corresponds to + a conversion to `T`. ```jldoctest julia> 129 % Int8 diff --git a/test/int.jl b/test/int.jl index 00708302a21a1..09291a3b18bb6 100644 --- a/test/int.jl +++ b/test/int.jl @@ -201,3 +201,9 @@ end @test unsafe_trunc(Int8, -127) === Int8(-127) @test unsafe_trunc(Int8, -128) === Int8(-128) @test unsafe_trunc(Int8, -129) === Int8(127) + +# Test x % T returns a T +for T in [Base.BitInteger_types..., BigInt], + U in [Base.BitInteger_types..., BigInt] + @test typeof(rand(U(0):U(127)) % T) === T +end From 4776d9ad5539f2b509c2c6622dcedc88e7e18b14 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sat, 1 Apr 2017 11:57:14 -0500 Subject: [PATCH 0331/1534] More fixes for non-1 arrays --- base/abstractarray.jl | 2 +- base/array.jl | 18 +++++++++++------- test/offsetarray.jl | 10 ++++++++++ 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 92a27271693a4..3d81227c56f8b 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -124,7 +124,7 @@ julia> length(A) length(t::AbstractArray) = (@_inline_meta; prod(size(t))) _length(A::AbstractArray) = (@_inline_meta; prod(map(unsafe_length, indices(A)))) # circumvent missing size _length(A) = (@_inline_meta; length(A)) -endof(a::AbstractArray) = (@_inline_meta; length(a)) +endof(a::AbstractArray) = (@_inline_meta; last(linearindices(a))) first(a::AbstractArray) = a[first(eachindex(a))] """ diff --git a/base/array.jl b/base/array.jl index 5de013272a606..55e21377a3fec 100644 --- a/base/array.jl +++ b/base/array.jl @@ -1040,26 +1040,30 @@ function =={T<:BitInteger}(a::Array{T,1}, b::Array{T,1}) :memcmp, Int32, (Ptr{T}, Ptr{T}, UInt), a, b, sizeof(T) * len) end -function reverse(A::AbstractVector, s=1, n=length(A)) +function reverse(A::AbstractVector, s=first(linearindices(A)), n=last(linearindices(A))) B = similar(A) - for i = 1:s-1 + for i = first(linearindices(A)):s-1 B[i] = A[i] end for i = s:n B[i] = A[n+s-i] end - for i = n+1:length(A) + for i = n+1:last(linearindices(A)) B[i] = A[i] end return B end -reverseind(a::AbstractVector, i::Integer) = length(a) + 1 - i +function reverseind(a::AbstractVector, i::Integer) + li = linearindices(a) + first(li) + last(li) - i +end -function reverse!(v::AbstractVector, s=1, n=length(v)) +function reverse!(v::AbstractVector, s=first(linearindices(v)), n=last(linearindices(v))) + liv = linearindices(v) if n <= s # empty case; ok - elseif !(1 ≤ s ≤ endof(v)) + elseif !(first(liv) ≤ s ≤ last(liv)) throw(BoundsError(v, s)) - elseif !(1 ≤ n ≤ endof(v)) + elseif !(first(liv) ≤ n ≤ last(liv)) throw(BoundsError(v, n)) end r = n diff --git a/test/offsetarray.jl b/test/offsetarray.jl index 3d9e1355b9b27..8fffbe70bb1f0 100644 --- a/test/offsetarray.jl +++ b/test/offsetarray.jl @@ -278,8 +278,18 @@ am = map(identity, a) # other functions v = OffsetArray(v0, (-3,)) +@test endof(v) == 1 @test v ≈ v @test indices(v') === (Base.OneTo(1),-2:1) +rv = reverse(v) +@test indices(rv) == indices(v) +@test rv[1] == v[-2] +@test rv[0] == v[-1] +@test rv[-1] == v[0] +@test rv[-2] == v[1] +cv = copy(v) +@test reverse!(cv) == rv + A = OffsetArray(rand(4,4), (-3,5)) @test A ≈ A @test indices(A') === (6:9, -2:1) From f5e5ea53d9d0db8e154197cfc8f551a1f445e532 Mon Sep 17 00:00:00 2001 From: kshyatt Date: Wed, 29 Mar 2017 14:33:19 -0700 Subject: [PATCH 0332/1534] Remove extraneous x^Val methods and add tests --- base/gmp.jl | 3 --- base/irrationals.jl | 1 - base/math.jl | 2 +- base/mpfr.jl | 3 --- test/float16.jl | 1 + test/math.jl | 1 + 6 files changed, 3 insertions(+), 8 deletions(-) diff --git a/base/gmp.jl b/base/gmp.jl index 5e339929b88cc..8c4a14102689e 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -443,9 +443,6 @@ end ^(x::Integer, y::BigInt ) = bigint_pow(BigInt(x), y) ^(x::Bool , y::BigInt ) = Base.power_by_squaring(x, y) -# override default inlining of x^2 and x^3 etc. -^{p}(x::BigInt, ::Type{Val{p}}) = x^p - function powermod(x::BigInt, p::BigInt, m::BigInt) r = BigInt() ccall((:__gmpz_powm, :libgmp), Void, diff --git a/base/irrationals.jl b/base/irrationals.jl index 55390ac126738..1d61d426a4f2f 100644 --- a/base/irrationals.jl +++ b/base/irrationals.jl @@ -212,7 +212,6 @@ catalan for T in (Irrational, Rational, Integer, Number) ^(::Irrational{:e}, x::T) = exp(x) end -^{p}(::Irrational{:e}, ::Type{Val{p}}) = exp(p) log(::Irrational{:e}) = 1 # use 1 to correctly promote expressions like log(x)/log(e) log(::Irrational{:e}, x::Number) = log(x) diff --git a/base/math.jl b/base/math.jl index 3831ed2831961..4901c7baa5466 100644 --- a/base/math.jl +++ b/base/math.jl @@ -698,7 +698,7 @@ end @inline ^(x::Float64, y::Integer) = x ^ Float64(y) @inline ^(x::Float32, y::Integer) = x ^ Float32(y) @inline ^(x::Float16, y::Integer) = Float16(Float32(x) ^ Float32(y)) -@inline ^{p}(x::Float16, ::Type{Val{p}}) = Float16(Float32(x) ^ Val{p}) +@inline literal_pow{p}(::typeof(^), x::Float16, ::Type{Val{p}}) = Float16(literal_pow(^,Float32(x),Val{p})) function angle_restrict_symm(theta) const P1 = 4 * 7.8539812564849853515625e-01 diff --git a/base/mpfr.jl b/base/mpfr.jl index 18529931004a4..808de3a0ca3c7 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -504,9 +504,6 @@ end ^(x::BigFloat, y::Integer) = typemin(Clong) <= y <= typemax(Clong) ? x^Clong(y) : x^BigInt(y) ^(x::BigFloat, y::Unsigned) = typemin(Culong) <= y <= typemax(Culong) ? x^Culong(y) : x^BigInt(y) -# override default inlining of x^2 etc. -^{p}(x::BigFloat, ::Type{Val{p}}) = x^p - for f in (:exp, :exp2, :exp10, :expm1, :cosh, :sinh, :tanh, :sech, :csch, :coth, :cbrt) @eval function $f(x::BigFloat) z = BigFloat() diff --git a/test/float16.jl b/test/float16.jl index 85356aa2cdb95..10e741336c53c 100644 --- a/test/float16.jl +++ b/test/float16.jl @@ -61,6 +61,7 @@ g = Float16(1.) @test f*g === Float16(2f0) @test f/g === Float16(2f0) @test f^g === Float16(2f0) +@test f^1 === Float16(2f0) @test f^-g === Float16(0.5f0) @test f + 2 === Float16(4f0) diff --git a/test/math.jl b/test/math.jl index 372bcf0e10a24..2dab2c3f07278 100644 --- a/test/math.jl +++ b/test/math.jl @@ -128,6 +128,7 @@ end yi = 4 @testset "Random values" begin @test x^y ≈ big(x)^big(y) + @test x^1 === x @test x^yi ≈ big(x)^yi @test acos(x) ≈ acos(big(x)) @test acosh(1+x) ≈ acosh(big(1+x)) From f91182a5891d7a55572363285dd291bdb44ca4dc Mon Sep 17 00:00:00 2001 From: Sebastian Pfitzner Date: Sun, 2 Apr 2017 10:41:59 +0200 Subject: [PATCH 0333/1534] improve error message for unescape_string --- base/strings/io.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/base/strings/io.jl b/base/strings/io.jl index 124a865daa00e..bd89cf98d77ba 100644 --- a/base/strings/io.jl +++ b/base/strings/io.jl @@ -299,7 +299,8 @@ function unescape_string(io, s::AbstractString) i = j end if k == 1 - throw(ArgumentError("\\x used with no following hex digits in $(repr(s))")) + throw(ArgumentError("invalid $(m == 2 ? "hex (\\x)" : + "unicode (\\u)") escape sequence used in $(repr(s))")) end if m == 2 # \x escape sequence write(io, UInt8(n)) From d3cfcd40419ea01e1e6a4a9e3eb050062d36c37d Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Wed, 22 Feb 2017 10:58:28 -0600 Subject: [PATCH 0334/1534] Create test helper challenge_prompt Useful for testing Julia functions which prompt for user input. Note that the fake PTY and new process are necessary to support user input that uses the `getpass` function. --- test/TestHelpers.jl | 66 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 63 insertions(+), 3 deletions(-) diff --git a/test/TestHelpers.jl b/test/TestHelpers.jl index c7393ba0f09a8..538e6a07a3d8a 100644 --- a/test/TestHelpers.jl +++ b/test/TestHelpers.jl @@ -20,6 +20,10 @@ Base.Terminals.raw!(t::FakeTerminal, raw::Bool) = t.raw = raw Base.Terminals.size(t::FakeTerminal) = (24, 80) function open_fake_pty() + @static if is_windows() + error("Unable to create a fake PTY in Windows") + end + const O_RDWR = Base.Filesystem.JL_O_RDWR const O_NOCTTY = Base.Filesystem.JL_O_NOCTTY @@ -41,9 +45,65 @@ end function with_fake_pty(f) slave, master = open_fake_pty() - f(slave, master) - ccall(:close,Cint,(Cint,),slave) # XXX: this causes the kernel to throw away all unread data on the pty - close(master) + try + f(slave, master) + finally + ccall(:close,Cint,(Cint,),slave) # XXX: this causes the kernel to throw away all unread data on the pty + close(master) + end +end + +function challenge_prompt(code::AbstractString, challenges; timeout::Integer=10, debug::Bool=true) + output_file = tempname() + wrapped_code = """ + open("$output_file", "w") do fp + serialize(fp, begin $code end) + end + """ + cmd = `$(Base.julia_cmd()) --startup-file=no -e $wrapped_code` + try + challenge_prompt(cmd, challenges, timeout=timeout, debug=debug) + return open(output_file, "r") do fp + deserialize(fp) + end + finally + isfile(output_file) && rm(output_file) + end + return nothing +end + +function challenge_prompt(cmd::Cmd, challenges; timeout::Integer=10, debug::Bool=true) + function format_output(output) + debug ? "Process output found:\n\"\"\"\n$(readstring(seekstart(out)))\n\"\"\"" : "" + end + out = IOBuffer() + with_fake_pty() do slave, master + p = spawn(detach(cmd), slave, slave, slave) + # Kill the process if it takes too long. Typically occurs when process is waiting for input + @async begin + sleep(timeout) + kill(p) + close(master) + end + try + for (challenge, response) in challenges + process_exited(p) && error("Too few prompts. $(format_output(out))") + + write(out, readuntil(master, challenge)) + if !isopen(master) + error("Could not locate challenge: \"$challenge\". $(format_output(out))") + end + write(master, response) + end + wait(p) + finally + kill(p) + end + # Determine if the process was explicitly killed + killed = process_exited(p) && (p.exitcode != 0 || p.termsignal != 0) + killed && error("Too many prompts. $(format_output(out))") + end + nothing end # OffsetArrays (arrays with indexing that doesn't start at 1) From dfa1a83d2e1d8cc4d2de3a31080ca0e409b0dd36 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Wed, 22 Feb 2017 12:12:28 -0600 Subject: [PATCH 0335/1534] Test framework for LibGit2 credential callback --- base/libgit2/callbacks.jl | 53 +++++++++++++++++++++++++++++++++++++++ base/libgit2/types.jl | 26 ++++++++++++++----- 2 files changed, 73 insertions(+), 6 deletions(-) diff --git a/base/libgit2/callbacks.jl b/base/libgit2/callbacks.jl index 225612afd8031..e1fb48e844b80 100644 --- a/base/libgit2/callbacks.jl +++ b/base/libgit2/callbacks.jl @@ -261,3 +261,56 @@ mirror_cb() = cfunction(mirror_callback, Cint, (Ptr{Ptr{Void}}, Ptr{Void}, Cstri credentials_cb() = cfunction(credentials_callback, Cint, (Ptr{Ptr{Void}}, Cstring, Cstring, Cuint, Ptr{Void})) "C function pointer for `fetchhead_foreach_callback`" fetchhead_foreach_cb() = cfunction(fetchhead_foreach_callback, Cint, (Cstring, Cstring, Ptr{GitHash}, Cuint, Ptr{Void})) + +""" +Emulates the LibGit2 credential loop to allows testing of the credential_callback function +without having to authenticate against a real server. +""" +function credential_loop( + valid_credential::AbstractCredentials, + url::AbstractString, + user::AbstractString, + allowed_types::UInt32) + cb = credentials_cb() + libgitcred_ptr_ptr = Ref{Ptr{Void}}(C_NULL) + cache = CachedCredentials() + payload_ptr = Ref(Nullable{AbstractCredentials}(cache)) + + # Number of times credentials were authenticated against. With the real LibGit2 + # credential loop this would be how many times we sent credentials to the remote. + num_authentications = 0 + + # Emulate how LibGit2 uses the credential callback by repeatedly calling the function + # until we find valid credentials or an exception is raised. + err = Cint(0) + while err == 0 + err = ccall(cb, Cint, (Ptr{Ptr{Void}}, Cstring, Cstring, Cuint, Ptr{Void}), + libgitcred_ptr_ptr, url, isempty(user) ? C_NULL : user, allowed_types, pointer_from_objref(payload_ptr)) + num_authentications += 1 + + # Check if the callback provided us with valid credentials + if length(cache.cred) == 1 && first(values(cache.cred)) == valid_credential + break + end + + if num_authentications > 50 + error("Credential callback seems to be caught in an infinite loop") + end + end + + return err, num_authentications +end + +function credential_loop( + valid_credential::UserPasswordCredentials, + url::AbstractString, + user::AbstractString="") + credential_loop(valid_credential, url, user, 0x000001) +end + +function credential_loop( + valid_credential::SSHCredentials, + url::AbstractString, + user::AbstractString="") + credential_loop(valid_credential, url, user, 0x000046) +end diff --git a/base/libgit2/types.jl b/base/libgit2/types.jl index cec1e28081e5e..73e0532676c94 100644 --- a/base/libgit2/types.jl +++ b/base/libgit2/types.jl @@ -670,32 +670,46 @@ function securezero!(cred::UserPasswordCredentials) return cred end +function Base.:(==)(a::UserPasswordCredentials, b::UserPasswordCredentials) + a.user == b.user && a.pass == b.pass +end + "SSH credentials type" mutable struct SSHCredentials <: AbstractCredentials user::String pass::String - pubkey::String prvkey::String + pubkey::String usesshagent::String # used for ssh-agent authentication prompt_if_incorrect::Bool # Whether to allow interactive prompting if the credentials are incorrect count::Int - - function SSHCredentials(u::AbstractString,p::AbstractString,prompt_if_incorrect::Bool=false) - c = new(u,p,"","","Y",prompt_if_incorrect,3) + function SSHCredentials(u::AbstractString,p::AbstractString,prvkey::AbstractString,pubkey::AbstractString,prompt_if_incorrect::Bool=false) + c = new(u,p,prvkey,pubkey,"Y",prompt_if_incorrect,3) finalizer(c, securezero!) return c end - SSHCredentials(prompt_if_incorrect::Bool=false) = SSHCredentials("","",prompt_if_incorrect) + SSHCredentials(u::AbstractString,p::AbstractString,prompt_if_incorrect::Bool=false) = SSHCredentials(u,p,prompt_if_incorrect) + SSHCredentials(prompt_if_incorrect::Bool=false) = SSHCredentials("","","","",prompt_if_incorrect) end + function securezero!(cred::SSHCredentials) securezero!(cred.user) securezero!(cred.pass) - securezero!(cred.pubkey) securezero!(cred.prvkey) + securezero!(cred.pubkey) cred.count = 0 return cred end +function Base.:(==)(a::SSHCredentials, b::SSHCredentials) + return ( + a.user == b.user && + a.pass == b.pass && + a.prvkey == b.prvkey && + a.pubkey == b.pubkey + ) +end + "Credentials that support caching" mutable struct CachedCredentials <: AbstractCredentials cred::Dict{String,AbstractCredentials} From 8fe28a16debea36a910af332aa8776c99aa7100a Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Wed, 22 Feb 2017 13:40:16 -0600 Subject: [PATCH 0336/1534] Add LibGit2 HTTPS credential prompt tests --- test/libgit2.jl | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/test/libgit2.jl b/test/libgit2.jl index 6a1050a23815a..b8acbeaf8f0a1 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -1,7 +1,7 @@ # This file is a part of Julia. License is MIT: http://julialang.org/license isdefined(Main, :TestHelpers) || @eval Main include(joinpath(dirname(@__FILE__), "TestHelpers.jl")) -using TestHelpers +import TestHelpers: challenge_prompt const LIBGIT2_MIN_VER = v"0.23.0" @@ -1091,6 +1091,45 @@ mktempdir() do dir @test creds.pass == creds_pass end + # The following tests require that we can fake a TTY so that we can provide passwords + # which use the `getpass` function. At the moment we can only fake this on UNIX based + # systems. + if is_unix() + @testset "HTTPS credential prompt" begin + url = "https://github.com/test/package.jl" + + valid_username = "julia" + valid_password = randstring(16) + + https_cmd = """ + valid_cred = LibGit2.UserPasswordCredentials("$valid_username", "$valid_password") + err, auth_attempts = LibGit2.credential_loop(valid_cred, "$url") + (err < 0 ? LibGit2.GitError(err) : err, auth_attempts) + """ + + # User provides a valid username and password + challenges = [ + "Username for 'https://github.com':" => "$valid_username\n", + "Password for 'https://$valid_username@github.com':" => "$valid_password\n", + ] + err, auth_attempts = challenge_prompt(https_cmd, challenges) + @test err == 0 + @test auth_attempts == 1 + + # User repeatedly chooses invalid username/password until the prompt limit is + # reached + challenges = [ + "Username for 'https://github.com':" => "foo\n", + "Password for 'https://foo@github.com':" => "bar\n", + "Username for 'https://github.com' [foo]:" => "$valid_username\n", + "Password for 'https://$valid_username@github.com':" => "$valid_password\n", + ] + err, auth_attempts = challenge_prompt(https_cmd, challenges) + @test err == 0 + @test auth_attempts == 5 + end + end + #= temporarily disabled until working on the buildbots, ref https://github.com/JuliaLang/julia/pull/17651#issuecomment-238211150 @testset "SSH" begin sshd_command = "" From 8dab22e5f8bfdf46e144560a4a8996d4472aee18 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Wed, 22 Feb 2017 13:18:53 -0600 Subject: [PATCH 0337/1534] Add LibGit2 SSH credential prompt tests --- base/libgit2/callbacks.jl | 10 +-- test/libgit2.jl | 119 ++++++++++++++++++++++++++++++ test/libgit2/invalid | 27 +++++++ test/libgit2/invalid.pub | 1 + test/libgit2/valid | 27 +++++++ test/libgit2/valid-passphrase | 30 ++++++++ test/libgit2/valid-passphrase.pub | 1 + test/libgit2/valid.pub | 1 + 8 files changed, 207 insertions(+), 9 deletions(-) create mode 100644 test/libgit2/invalid create mode 100644 test/libgit2/invalid.pub create mode 100644 test/libgit2/valid create mode 100644 test/libgit2/valid-passphrase create mode 100644 test/libgit2/valid-passphrase.pub create mode 100644 test/libgit2/valid.pub diff --git a/base/libgit2/callbacks.jl b/base/libgit2/callbacks.jl index e1fb48e844b80..c3e9d4c7b6e36 100644 --- a/base/libgit2/callbacks.jl +++ b/base/libgit2/callbacks.jl @@ -28,16 +28,8 @@ function authenticate_ssh(creds::SSHCredentials, libgit2credptr::Ptr{Ptr{Void}}, username_ptr, schema, host) isusedcreds = checkused!(creds) - errcls, errmsg = Error.last_error() - if errcls != Error.None - # Check if we used ssh-agent - if creds.usesshagent == "U" - creds.usesshagent = "E" # reported ssh-agent error, disables ssh agent use for the future - end - end - # first try ssh-agent if credentials support its usage - if creds.usesshagent == "Y" || creds.usesshagent == "U" + if creds.usesshagent == "Y" err = ccall((:git_cred_ssh_key_from_agent, :libgit2), Cint, (Ptr{Ptr{Void}}, Cstring), libgit2credptr, username_ptr) creds.usesshagent = "U" # used ssh-agent only one time diff --git a/test/libgit2.jl b/test/libgit2.jl index b8acbeaf8f0a1..a7e2a22810f40 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -1095,6 +1095,125 @@ mktempdir() do dir # which use the `getpass` function. At the moment we can only fake this on UNIX based # systems. if is_unix() + @testset "SSH credential prompt" begin + url = "git@github.com/test/package.jl" + + key_dir = joinpath(dirname(@__FILE__), "libgit2") + valid_key = joinpath(key_dir, "valid") + invalid_key = joinpath(key_dir, "invalid") + valid_p_key = joinpath(key_dir, "valid-passphrase") + passphrase = "secret" + + ssh_cmd = """ + valid_cred = LibGit2.SSHCredentials("git", "", "$valid_key", "$valid_key.pub") + err, auth_attempts = LibGit2.credential_loop(valid_cred, "$url", "git") + (err < 0 ? LibGit2.GitError(err) : err, auth_attempts) + """ + + ssh_p_cmd = """ + valid_cred = LibGit2.SSHCredentials("git", "$passphrase", "$valid_p_key", "$valid_p_key.pub") + err, auth_attempts = LibGit2.credential_loop(valid_cred, "$url", "git") + (err < 0 ? LibGit2.GitError(err) : err, auth_attempts) + """ + + # Note: We cannot use the default ~/.ssh/id_rsa for tests since we cannot be + # sure a users will actually have these files. Instead we will use the ENV + # variables to set the default values. + + # Default credentials are valid + withenv("SSH_KEY_PATH" => valid_key) do + err, auth_attempts = challenge_prompt(ssh_cmd, []) + @test err == 0 + @test auth_attempts == 2 + end + + # Default credentials are valid but requires a passphrase + withenv("SSH_KEY_PATH" => valid_p_key) do + challenges = [ + "Passphrase for $valid_p_key:" => "$passphrase\n", + ] + err, auth_attempts = challenge_prompt(ssh_p_cmd, challenges) + @test err == 0 + @test auth_attempts == 2 + + # User mistypes passphrase. + # Note: In reality LibGit2 will raise an error upon using the invalid SSH + # credentials. Since we don't control the internals of LibGit2 though they + # could also just re-call the credential callback like they do for HTTP. + challenges = [ + "Passphrase for $valid_p_key:" => "foo\n", + # "Private key location for 'git@github.com' [$valid_p_key]:" => "\n", + "Passphrase for $valid_p_key:" => "$passphrase\n", + ] + err, auth_attempts = challenge_prompt(ssh_p_cmd, challenges) + @test err == 0 + @test auth_attempts == 6 + end + + withenv("SSH_KEY_PATH" => valid_p_key, "SSH_KEY_PASS" => passphrase) do + err, auth_attempts = challenge_prompt(ssh_p_cmd, []) + @test err == 0 + @test auth_attempts == 2 + end + + # TODO: Tests are currently broken. Credential callback prompts for: + # "Passphrase for :" + #= + # Explicitly setting these env variables to be empty means the user will be + # given a prompt with no defaults set. + withenv("SSH_KEY_PATH" => "", "SSH_PUB_KEY_PATH" => "") do + # User provides valid credentials + challenges = [ + "Private key location for 'git@github.com':" => "$valid_key\n", + ] + err, auth_attempts = challenge_prompt(ssh_cmd, challenges) + @test err == 0 + @test auth_attempts == 2 + + # User provides valid credentials that requires a passphrase + challenges = [ + "Private key location for 'git@github.com':" => "$valid_p_key\n", + "Passphrase for $valid_p_key:" => "$passphrase\n", + ] + err, auth_attempts = challenge_prompt(ssh_p_cmd, challenges) + @test err == 0 + @test auth_attempts == 2 + end + =# + + # TODO: Tests are currently broken. Credential callback currently infinite loops + # and never prompts user to change private keys. + #= + # Explicitly setting these env variables to an existing but invalid key pair + # means the user will be given a prompt with that defaults to the given values. + withenv("SSH_KEY_PATH" => invalid_key, "SSH_PUB_KEY_PATH" => invalid_key * ".pub") do + challenges = [ + "Private key location for 'git@github.com' [$invalid_key]:" => "$valid_key\n", + ] + err, auth_attempts = challenge_prompt(ssh_cmd, challenges) + @test err == 0 + @test auth_attempts == 2 + end + =# + + # TODO: Tests are currently broken. Credential callback currently infinite loops + # and never prompts user to change private keys. + #= + withenv("SSH_KEY_PATH" => valid_key, "SSH_PUB_KEY_PATH" => valid_key * ".public") do + @test !isfile(ENV["SSH_PUB_KEY_PATH"]) + + # User explicitly sets the SSH_PUB_KEY_PATH incorrectly. + challenges = [ + "Private key location for 'git@github.com' [$valid_key]:" => "\n" + "Public key location for 'git@github.com':" => "$valid_key.pub\n" + ] + err, auth_attempts = challenge_prompt(ssh_cmd, challenges) + @test err == 0 + @test auth_attempts == 2 + end + =# + end + @testset "HTTPS credential prompt" begin url = "https://github.com/test/package.jl" diff --git a/test/libgit2/invalid b/test/libgit2/invalid new file mode 100644 index 0000000000000..7fa5389beb031 --- /dev/null +++ b/test/libgit2/invalid @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAs1L+Z8s5GdtzLXGM3+4UVQ7jc5q/uNPzQgGUl+nC+o2VFuHm +omkAIxxrS3zkVT0A4AnkrVq/H2l2AOlxKudFan4o87AJQsTHkj9LvFBhm+bBdHau +0SGSft8cCWAXv5lifFChYaxT78Y3QnSO4Q7AVEXQVAmGFiu3CgBKq7c1srQt8V4n +dH8PuMYdIiYuNG8HNAnErGjApdNHmosY63jybkRmTffvhuS/Df1FKLYY60QYThKM +50P+8HHX1jvH+JI5bWLyDhG97E8Vmh9bpgvHhdZ52WBVaf5i6qmYB2FBHHfb8Yuh +/EB39RQjPLEI9K5HP5LkBXAWxozv75qmKF7AiQIDAQABAoIBAFF1H89yRyvxva4k +6INIGMBSlQuMfg6taNDQ+vjO3R0Hd3P/hc68t607WZnez7HQljcvB0uf7zWLqGjd +oeSFTckEKgIYMvy7epR6YCLYuJ4jAjmvN9YT1AIBwzCXD/Ke8FfcIJLHvxEqDywG +2mhtVPxzAiFKejhT/z9xxnmeLaxQ3eE77XrFJiJR0M+fc6B2zyN8eVR/jdpoVFOw +Jb6TkzxDY1OWVY72EMf+7JBzpnNVqe36T0aJapF1c4qeqC+bklYtgnJ1GfohzbKU +ij8SF1yH1y+LX0qq67DLfxmm1qNMgBNhLC8eYm9yfAWkRi4eX9c7U2X/61S3Sm9a +CMGb8QECgYEA2x9d5uCeVdg595NutArea7sHVuJViF8kWYBwYgkAFgdEtjGhoEXX +YMa+11HQ+yUX4WfrLhcQm/eiSdaqKEcE0g/tz6ytuFCZvPHPZe2p2QIIHjqKYezc +mtcc95qYm1O3U5iTHsiL73TurdESOl7O1eSK/TgQwoes6cuELqZ5GBkCgYEA0YD2 +lJ7uW1MBCQwTENbe4ZapvwtEXsRIVad0dg6kzgaYgBWDIuNS0XBnB6sbD3B0TL6G +vhpfO7wMV8VQ1H2h0aMLSgpevPxHrD0uQsXhZ0cM8hzhAKmbAscBdQXv6MnXzr37 +8FL3nHyYc9qvk7qNcMqa1x975s5SlzR5UrA9ufECgYAydOeXiXOMSu0WMFHWjYYo +AnovLJELhPUG0weN24q0h9nvpkAUeuCcfUdmp4Vav3DfS6GhDFibwYsSO6cU/T2D +7X0STC34ej7cfkYGr5Jj0Q7zfwFsiTFHSm92KJgpdD6Ltl9yQDXQ3vky9yieXkR8 +hlLm+ikJ0lojv+RhJZ5OyQKBgQDLlVuIXszXF9jItuAMHBEn/GVlTYiZ4nk8KuaE +FoTV5BjrVnxBOc/v0B9+lypLnYaWUQrUzwG+JWWFISwD4TWPZrYAtAUN9sWbPTSo +FGyOFMAiwidvomEMmN/0nNleSE4bDAk3pxgRDA6FfnvhvYXWljtTUrfvOI2Pe6Ft +1e+VsQKBgFF1wW0E7L7ItpClFifF0tDZdOjfBwiUutusvFSj6RVtIv9s0WiSoc/R +qOc4Jfle2F0cw3Fwp5Qv/qgKItOT0zo4mOJKOzyHfER5UgI7zcIK9dBNuYCRBwwE +lXZzcMoTuRH8GrMdoTUTMyJ5DRC5vqRW422pM4K+ICVIYrZpfpDh +-----END RSA PRIVATE KEY----- diff --git a/test/libgit2/invalid.pub b/test/libgit2/invalid.pub new file mode 100644 index 0000000000000..d7abfc26e25c8 --- /dev/null +++ b/test/libgit2/invalid.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCzUv5nyzkZ23MtcYzf7hRVDuNzmr+40/NCAZSX6cL6jZUW4eaiaQAjHGtLfORVPQDgCeStWr8faXYA6XEq50VqfijzsAlCxMeSP0u8UGGb5sF0dq7RIZJ+3xwJYBe/mWJ8UKFhrFPvxjdCdI7hDsBURdBUCYYWK7cKAEqrtzWytC3xXid0fw+4xh0iJi40bwc0CcSsaMCl00eaixjrePJuRGZN9++G5L8N/UUothjrRBhOEoznQ/7wcdfWO8f4kjltYvIOEb3sTxWaH1umC8eF1nnZYFVp/mLqqZgHYUEcd9vxi6H8QHf1FCM8sQj0rkc/kuQFcBbGjO/vmqYoXsCJ invalid-credentials diff --git a/test/libgit2/valid b/test/libgit2/valid new file mode 100644 index 0000000000000..bc6cf6a402ae8 --- /dev/null +++ b/test/libgit2/valid @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEA3oA311O95RTuncUrnHxLu7CUMN9Mh5ZolXct33RoEoAkar7E +oyW2C0AQ+yA7C3PjlC2SmgYbebUC+N/0bFOoibDwFCUmZbOlRTWITYbq7t0f6nk7 +cl4l8BvyMPbRN25ozPyn1SrGc/vHj11LnGXGNZWqCfz5EJ6LfLIlA5P/0814QrRk +ePg/J3RZ3HJj7QlvHvG9uAQQ//WXeFdmRQDKNhZbMc0bibxZGgMQeKL7hoGwGBHT +a5DSWsCWermUC5IYsrC5PAzGcN/KwTbQ0S9U7xVTOuKDSEMv8AzEmkpCtkulVses +x7P47wUKhOOm9OFikVEC2s0uoRvNfUDUSzjFLQIDAQABAoIBACgKhwIXLetV8wMt +goWs0Kw8QM7ywID+DmAnjHfUKQ57RRJ4tkZt+O7ZXrTyve13s5LtCJ7zTmp+qsRC ++WetPn1Y/DuD2/8dbzafRaI+D3VhEedOXeZdDxLA1Lr/D/ObyPxq04FHK2OgAe/I +6FyC7EKkZm9ZuTDGd2+/V23nanihAXJ8ILk02cKxNjpq4gxt0i0Zm3CjVEYlrywm +fBov7sbLWwu2ovISdRBziJAs8wsGPKTcbOCREtHe2BP7bfiAcf9UEatdH7C1kO8U +gdCluvH2RMwy00NunthrKEy7CmdOh/lfV7p6VYbH3/ikq+XkhntE8SEJzafLuIUl +mbglGsECgYEA+SflaLun2WqqsUlrVH3mN7lUbYpHhs72zOa7NcvRzBqEeYhhFyoQ +WvQzJlzfIZ+I/JqgHjsGeJx8cHpxI7zwd7n45nc9ycU9yc5UHsAGcyQwrTpVMIEn +gHL6Ybe2vN7CIazPGnmiwaCD25/Kp5eBXmc8Syckt12GMDIwMuozwbkCgYEA5Jzh +O8lZMGTmoz4iGIWr0g21ySmNX+toKq+zto7jhZSZcEpFGxARP4GdiN9CafGJRRz1 +r4ZHruWazLpxozsWRAgVnWJrgee7JZ4oWi0geAw+wUxQYny+/rx0AQl81lHwPhOm +f8WfTZifKhu9QaR5fa3DAfrgc8Gfay1TP7UtaRUCgYEAqFeEcRcZeZTQb6ijlBrc +iZn2qWxcl4EOz7K1mstznOvtxg+XSgdptYp5ZNorCJS6AbKXrNVEsglJKtYPy43F +C5/jxBOc888IyGlX/M7RjMpO+TwIgxVAk1EcSxnNph78G7Se2cyFYz4I2UNFsaZ0 +CkzGOCDideIC4F2Io14KSkECgYBhRzw0Q45XIGhfyD2b761YWYskCTFmQnZ1y4QO +R6kbG0tbU88qH+EnA9Fz/4R0Llo59YO558qy6nK/cQqP6cGku0fvS4TxpxikfjMv +hApP6u39NKrz7Z8cKDa4hj//tqgi0hvEPOR3kV0Q/vK+bu1fhEP5oLZHq3lZktTc +xAyJrQKBgClH3j759U82D2bUXVanDqs7S0Zef91u11kYDFrnX4kUWlG0DZCB7e5P +yBUWd/ZoXULBkoCfbwO8PGGxFYRmXzYQvVnSGiAP09dHFodvMm7hP8VueoRbAbEL +/UKMQOhYhEpcENylUjaaLUzxaYzwqeT/dcu+Edd7sCKk0J/1beA/ +-----END RSA PRIVATE KEY----- diff --git a/test/libgit2/valid-passphrase b/test/libgit2/valid-passphrase new file mode 100644 index 0000000000000..169fef6df16d0 --- /dev/null +++ b/test/libgit2/valid-passphrase @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CBC,EC9D334AA2ECD3E7A9DCBD7BDFB5CABC + +J9EWrlaxABoCAeow7k8oteiGorPKpZMVQBmIomx91kpfncVBC/WDbRa2HbmVkkYh +kgFbpDmzD6cMuu1sAbOROcCBFLqtKsXwHj4nynW8PTJRNSG9GazY9tmQ/OzAV9Ng +ZELXVncyexKEG7WDlXuArqd2KwbopNe6SetW4OYZy6t7QBNp6c4wwyRwuCYwGjMg +3rAugZvMPv7Ytr4DCluKp+/S5P81LKPpGDYdGSD3wMQtEzB/81DPsp+BP2r0rqPA +9Wa49c5aOcLdDaG8tVlogAQEwn4Mt/GI3U5b2Q14/YUy41AD4ZuYLl+3iv+18PsM +6Kqs0QmD6FM6hDg82+FYh5fbvJqoHjAFqieljWFdm0oLpuz7p3q3MMfAkhl5Xrvq +bCLQenFww8IxgyIMUGYRtq5kGKm+rXbKg/vQV/jxyLCdQZoZXO6F07gwUKX2YM1K +H1j9DbexbtJXoAtXP7nP0qo2WJjhGnDvcqxuBRrJFW7Z/T8r0pqetYSUFuIiS7Nt +ftT60QPziRB1G9nwR7TiWhOfl1VQlrRxXompfK+We3+njp96Yuqdw9mOZ3slEz40 +LlTlPqmC8Fp1rm+M5qtjotlYGJLUcFOpbwKzt0knl+gYPg7qCSVcjoQ0E6WrciyH +3t8+pRtguICjV2Jfq+MFnzfJujNSBIxYro/oQ+dl3b2s9eeks6SVloCmuaGj45hN +Y3wrfMe+4dv+wy9JuYzHualBpPk8GCxDNHqXkd7nTjDPY9uCW2xqjP8HBq+GNj0Q +XLSyZ95iPJwxcAigXa8g3+jMg/IUddIF7tNQbHLZR1h+4nP2HB7Fo0GQM9dOGNzU +r+LGBeIJTmFite0jSFDjRHDo/GunV7/A21ZSykt8aMAQYlEQg2eKAdfzDYK5JTXw +dFn5YURKGpmlyRWc91Dvg6uF28KAwcMBogRK/3EiEyZushndHqtE1Rqtq+Afi1Ld +GBgIk2dgD+TCqxtmTcPO+ZQN4Tm1rRM5j+b4VehCTQTxeqC+YMfiwZZvW8xQj5Ja +DMG/A+0M8PZtjr+QygGXGmtWxx0dn/ez0sLO6om11U7OmYXJGEp6KqNKnlZZiv3t +wY7wJ/IS5DhWhZ+ttsq3z+0XKCiP/06IhNmT6Aq0CUaYuXmbtx7hdnhGA92Jbn8X +pwF8GkDdPA/nqmRiwwJSI2jAMs5EGtYCbcn4QlpCZu9x+m3/YTCGqByQN3VLRtrd +u3UlYH1dT+EAsnG6fxXzj1MdSmT5RRadbEOW6Z3Ykfw47Ft6FKEC+WX0ZC5bBrpC +8a9f/knEbAd5NHEgEuhHHZ+8yv0cz/SHdrDS+cygKIEB237Zwx1TIJ0x9wVtns7g +jk7EV9PBFdmw2aD0WBoK16gQYVhGb8sDQ88ps6llxm8iLV4iQSIAeBDURvjx90aA +vIjqC2RzqXsbtueIo1zk41gElDpDYdI9hSMqhyJaShBOcAPPSso3V0VcAylRTjRt +B9NBbLVjajgWjqse6jcNacbhMnFvbqFEWeHLAI3jOog3aXTmkgIDtuSHGjD/r0WA +FpOQrzn5IDkMEamtqaemFxp14MKxRAPMJ8nOPyZzXM1Pz6dARH1d3EKeC1tFMh3j +-----END RSA PRIVATE KEY----- diff --git a/test/libgit2/valid-passphrase.pub b/test/libgit2/valid-passphrase.pub new file mode 100644 index 0000000000000..2ed2cd3eb54d9 --- /dev/null +++ b/test/libgit2/valid-passphrase.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDLsjzj6P2eGJEASR+MqajdDkVzCK5rTnc/BXDzgCA3Zff8uGgHQlXTX++OspluSnPKvaHFuYUWbCDEH2mwHeLWiwXk68T5+3/GqOX9/m2dxEy6TOmLQ4iOPVC5mrBrSFbHTc5J2PPh3q9hwp/p35BwWo5nCUMc+pqq7WEVdgNNziRuFyAtva2vCVDXEZ5+6FJDvysoMndoIQQlVJXHoPp8w+Eb8gOg5kxTYtpNjb7Vjx/Ux70nl26B5JYtpWUTxLHfnzPRcjGrINgtbsbVDC6BJTnSnBttxaZRcON4/pZDpcvLBhOhqBKjkRkxoMvTGeiA7M5cm/G9LWROeCc88I/D valid-credentials-with-passphrase diff --git a/test/libgit2/valid.pub b/test/libgit2/valid.pub new file mode 100644 index 0000000000000..1e53e6c51b7b0 --- /dev/null +++ b/test/libgit2/valid.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDegDfXU73lFO6dxSucfEu7sJQw30yHlmiVdy3fdGgSgCRqvsSjJbYLQBD7IDsLc+OULZKaBht5tQL43/RsU6iJsPAUJSZls6VFNYhNhuru3R/qeTtyXiXwG/Iw9tE3bmjM/KfVKsZz+8ePXUucZcY1laoJ/PkQnot8siUDk//TzXhCtGR4+D8ndFnccmPtCW8e8b24BBD/9Zd4V2ZFAMo2FlsxzRuJvFkaAxB4ovuGgbAYEdNrkNJawJZ6uZQLkhiysLk8DMZw38rBNtDRL1TvFVM64oNIQy/wDMSaSkK2S6VWx6zHs/jvBQqE46b04WKRUQLazS6hG819QNRLOMUt valid-credentials From 5af9bc0eb322a65dcf72220c8b5a610f8ec32ae7 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Mon, 3 Apr 2017 18:32:03 +0000 Subject: [PATCH 0338/1534] Split TBAA for array buffers --- src/codegen.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 210ca52284752..97ce1743d3207 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -262,7 +262,8 @@ static MDNode *tbaa_binding; // jl_binding_t::value static MDNode *tbaa_value; // jl_value_t, that is not jl_array_t static MDNode *tbaa_mutab; // mutable type static MDNode *tbaa_immut; // immutable type -static MDNode *tbaa_arraybuf; // Data in an array +static MDNode *tbaa_ptrarraybuf; // Data in an array of boxed values +static MDNode *tbaa_arraybuf; // Data in an array of POD static MDNode *tbaa_array; // jl_array_t static MDNode *tbaa_arrayptr; // The pointer inside a jl_array_t static MDNode *tbaa_arraysize; // A size in a jl_array_t @@ -2827,7 +2828,8 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, *ret = ghostValue(ety); } else { - *ret = typed_load(emit_arrayptr(ary, args[1], ctx), idx, ety, ctx, tbaa_arraybuf); + *ret = typed_load(emit_arrayptr(ary, args[1], ctx), idx, ety, ctx, + jl_array_store_unboxed(ety) ? tbaa_arraybuf : tbaa_ptrarraybuf); } JL_GC_POP(); return true; @@ -2850,14 +2852,14 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, if (jl_is_array_type(aty_dt) && indexes_ok) { jl_value_t *ety = jl_tparam0(aty_dt); if (!jl_has_free_typevars(ety) && jl_subtype(vty, ety)) { // TODO: jn/foreigncall branch has a better predicate - if (!jl_array_store_unboxed(ety)) + bool isboxed = !jl_array_store_unboxed(ety); + if (isboxed) ety = (jl_value_t*)jl_any_type; jl_value_t *ndp = jl_tparam1(aty_dt); if (jl_is_long(ndp) || nargs==3) { jl_cgval_t ary = emit_expr(args[1], ctx); ssize_t nd = jl_is_long(ndp) ? jl_unbox_long(ndp) : -1; Value *idx = emit_array_nd_index(ary, args[1], nd, &args[3], nargs-2, ctx); - bool isboxed = !jl_array_store_unboxed(ety); if (!isboxed && jl_datatype_size(ety) == 0) { // no-op, but emit expr for possible effects assert(jl_is_datatype(ety)); @@ -2906,7 +2908,7 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, data_owner->addIncoming(own_ptr, ownedBB); } typed_store(emit_arrayptr(ary,args[1],ctx), idx, v, - ety, ctx, tbaa_arraybuf, data_owner, 0, + ety, ctx, !isboxed ? tbaa_arraybuf : tbaa_ptrarraybuf, data_owner, 0, false); // don't need to root the box if we had to make one since it's being stored in the array immediatly } *ret = ary; @@ -6309,6 +6311,7 @@ static void init_julia_llvm_meta(void) tbaa_mutab = tbaa_make_child("jtbaa_mutab", tbaa_value_scalar).first; tbaa_immut = tbaa_make_child("jtbaa_immut", tbaa_value_scalar).first; tbaa_arraybuf = tbaa_make_child("jtbaa_arraybuf", tbaa_data_scalar).first; + tbaa_ptrarraybuf = tbaa_make_child("jtbaa_ptrarraybuf", tbaa_data_scalar).first; MDNode *tbaa_array_scalar; std::tie(tbaa_array, tbaa_array_scalar) = tbaa_make_child("jtbaa_array"); tbaa_arrayptr = tbaa_make_child("jtbaa_arrayptr", tbaa_array_scalar).first; From 3a4cc446dc1ff780f88296fb6d0fc733e5636876 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 24 Feb 2017 17:30:30 -0500 Subject: [PATCH 0339/1534] allow TTYTerminal streams to be any IO types --- base/Terminals.jl | 6 +++--- test/repl.jl | 7 +++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/base/Terminals.jl b/base/Terminals.jl index 11b75bf89aa3f..a4f2747b7152c 100644 --- a/base/Terminals.jl +++ b/base/Terminals.jl @@ -100,9 +100,9 @@ end mutable struct TTYTerminal <: UnixTerminal term_type::String - in_stream::Base.TTY - out_stream::Base.TTY - err_stream::Base.TTY + in_stream::IO + out_stream::IO + err_stream::IO end const CSI = "\x1b[" diff --git a/test/repl.jl b/test/repl.jl index d4adaf0fdd193..15733ad2feefd 100644 --- a/test/repl.jl +++ b/test/repl.jl @@ -632,3 +632,10 @@ let ends_with_semicolon = Base.REPL.ends_with_semicolon @test !ends_with_semicolon("begin\na; #=#=#\n=#b=#\nend") @test ends_with_semicolon("\na; #=#=#\n=#b=#\n# test\n#=\nfoobar\n=##bazbax\n") end + +# PR #20794, TTYTerminal with other kinds of streams +let term = Base.Terminals.TTYTerminal("dumb",IOBuffer("1+2\n"),IOBuffer(),IOBuffer()) + r = Base.REPL.BasicREPL(term) + REPL.run_repl(r) + @test String(take!(term.out_stream)) == "julia> 3\n\njulia> \n" +end From 338e22d88bafafcde13f38b87703917aefd62eaa Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 3 Apr 2017 15:40:17 +0200 Subject: [PATCH 0340/1534] ensure that AST of a constant return function is correct fix #21175 --- base/inference.jl | 6 +++--- test/inference.jl | 9 +++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 65cf9bd02f256..c16dfc890c020 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -2510,12 +2510,12 @@ function typeinf_code(linfo::MethodInstance, optimize::Bool, cached::Bool, # see if this code already exists in the cache # staged functions make this hard since they have two "inferred" conditions, # so need to check whether the code itself is also inferred - inf = linfo.inferred if min_world(linfo) <= params.world <= max_world(linfo) + inf = linfo.inferred if linfo.jlcall_api == 2 method = linfo.def tree = ccall(:jl_new_code_info_uninit, Ref{CodeInfo}, ()) - tree.code = Any[ Expr(:return, QuoteNode(inf)) ] + tree.code = Any[ Expr(:return, QuoteNode(linfo.inferred_const)) ] tree.slotnames = Any[ compiler_temp_sym for i = 1:method.nargs ] tree.slotflags = UInt8[ 0 for i = 1:method.nargs ] tree.slottypes = nothing @@ -2526,7 +2526,7 @@ function typeinf_code(linfo::MethodInstance, optimize::Bool, cached::Bool, i == 2 && ccall(:jl_typeinf_end, Void, ()) return svec(linfo, tree, linfo.rettype) elseif isa(inf, CodeInfo) - if (inf::CodeInfo).inferred + if inf.inferred i == 2 && ccall(:jl_typeinf_end, Void, ()) return svec(linfo, inf, linfo.rettype) end diff --git a/test/inference.jl b/test/inference.jl index 0bd563a24b75c..7cf7f368551f6 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -729,3 +729,12 @@ end # inference on invalid getfield call @eval _getfield_with_string_() = getfield($(1=>2), "") @test Base.return_types(_getfield_with_string_, ()) == Any[Union{}] + +# inference AST of a constant return value +f21175() = 902221 +@test code_typed(f21175, ())[1].second === Int +# call again, so that the AST is built on-demand +let e = code_typed(f21175, ())[1].first.code[1]::Expr + @test e.head === :return + @test e.args[1] == Core.QuoteNode(902221) +end From 9086161cfd04234ea4ff6ce2a8112b9a2aa9d19e Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Fri, 31 Mar 2017 13:12:45 -0700 Subject: [PATCH 0341/1534] Allow newline or semicolon in abstract and primitive defs --- src/julia-parser.scm | 12 ++++++++++-- test/parse.jl | 14 ++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 8ea23c1f1eda2..afdd40ad2dd46 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -1141,6 +1141,14 @@ (begin0 (list 'type (if mut? 'true 'false) sig (parse-block s)) (expect-end s word)))) +;; consume any number of line endings from a token stream +(define (take-lineendings s) + (let ((nt (peek-token s))) + (if (or (newline? nt) (eqv? nt #\;)) + (begin (take-token s) + (take-lineendings s)) + s))) + ;; parse expressions or blocks introduced by syntactic reserved words (define (parse-resword s word) (with-bindings @@ -1271,7 +1279,7 @@ (syntax-deprecation s (string "abstract " (deparse spec)) (string "abstract type " (deparse spec) " end"))) (begin0 (list 'abstract spec) - (if ty (expect-end s "abstract type")))))) + (if ty (expect-end (take-lineendings s) "abstract type")))))) ((struct) (begin (take-token s) (parse-struct-def s #f word))) @@ -1287,7 +1295,7 @@ (let* ((spec (with-space-sensitive (parse-subtype-spec s))) (nb (with-space-sensitive (parse-cond s)))) (begin0 (list 'bitstype nb spec) - (expect-end s "primitive type")))))) + (expect-end (take-lineendings s) "primitive type")))))) ;; deprecated type keywords ((type) ;; TODO fully deprecate post-0.6 diff --git a/test/parse.jl b/test/parse.jl index 8fc8d6a1f1d4f..f91964a324661 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -1065,3 +1065,17 @@ g21054(>:) = >:2 # issue #21168 @test expand(:(a.[1])) == Expr(:error, "invalid syntax a.[1]") @test expand(:(a.{1})) == Expr(:error, "invalid syntax a.{1}") + +# Issue #21225 +let abstr = parse("abstract type X end") + @test parse("abstract type X; end") == abstr + @test parse(string("abstract type X", ";"^5, " end")) == abstr + @test parse("abstract type X\nend") == abstr + @test parse(string("abstract type X", "\n"^5, "end")) == abstr +end +let prim = parse("primitive type X 8 end") + @test parse("primitive type X 8; end") == prim + @test parse(string("primitive type X 8", ";"^5, " end")) == prim + @test parse("primitive type X 8\nend") == prim + @test parse(string("primitive type X 8", "\n"^5, "end")) == prim +end From e796e39e29d0405f88f18312345f168b03a48054 Mon Sep 17 00:00:00 2001 From: m-j-w Date: Tue, 4 Apr 2017 07:45:13 +0200 Subject: [PATCH 0342/1534] Fix exports of undefined/missing/conditionally defined symbols (#21217) * Remove Base.Parallel export. * Remove 'big_str' export from mpfr.jl * Remove 'dense' from export in sparse.jl --- base/exports.jl | 4 ++-- base/mpfr.jl | 3 +-- base/sparse/sparse.jl | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/base/exports.jl b/base/exports.jl index 51bfbf6632ef1..f38b87fe2bff0 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -23,7 +23,7 @@ export Markdown, Threads, Iterators, - Parallel, + Distributed, # Types AbstractChannel, @@ -1344,7 +1344,7 @@ export nzrange, nnz, -# Parallel module re-exports +# Distributed module re-exports @spawn, @spawnat, @fetch, diff --git a/base/mpfr.jl b/base/mpfr.jl index 808de3a0ca3c7..9141c2ad704dd 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -4,8 +4,7 @@ module MPFR export BigFloat, - setprecision, - big_str + setprecision import Base: (*), +, -, /, <, <=, ==, >, >=, ^, ceil, cmp, convert, copysign, div, diff --git a/base/sparse/sparse.jl b/base/sparse/sparse.jl index 3ca298a66099d..2425d02dae46d 100644 --- a/base/sparse/sparse.jl +++ b/base/sparse/sparse.jl @@ -27,7 +27,7 @@ import Base: @get!, acos, acosd, acot, acotd, acsch, asech, asin, asind, asinh, triu, vec, permute!, map, map! export AbstractSparseArray, AbstractSparseMatrix, AbstractSparseVector, - SparseMatrixCSC, SparseVector, blkdiag, dense, droptol!, dropzeros!, dropzeros, + SparseMatrixCSC, SparseVector, blkdiag, droptol!, dropzeros!, dropzeros, issparse, nonzeros, nzrange, rowvals, sparse, sparsevec, spdiagm, speye, spones, sprand, sprandn, spzeros, nnz, permute From 18e864b8283c2686c254973d8f77a59287104167 Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Tue, 4 Apr 2017 14:08:24 +0200 Subject: [PATCH 0343/1534] deprecate unintended methods of zeros, ones (#21183) --- base/deprecated.jl | 12 ++++++++++++ test/arrayops.jl | 11 +++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index 7649120d70e2a..dc95156ebffb8 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1307,6 +1307,18 @@ end end end +# #19635 +for fname in (:ones, :zeros) + @eval @deprecate ($fname)(T::Type, arr) ($fname)(T, size(arr)) + @eval ($fname)(T::Type, i::Integer) = ($fname)(T, (i,)) + @eval function ($fname){T}(::Type{T}, arr::Array{T}) + msg = string("`", $fname, "{T}(::Type{T}, arr::Array{T})` is deprecated, use ", + "`", $fname , "(T, size(arr))` instead. ", + ) + error(msg) + end +end + # END 0.6 deprecations # BEGIN 1.0 deprecations diff --git a/test/arrayops.jl b/test/arrayops.jl index 4ad942d900bba..ca9bc0636ad2b 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -2054,12 +2054,11 @@ end zs = zeros(SparseMatrixCSC([1 2; 3 4]), Complex{Float64}, (2,3)) test_zeros(zs, SparseMatrixCSC{Complex{Float64}}, (2, 3)) - @testset "#19265" begin - @test_throws MethodError zeros(Float64, [1.]) - x = [1.] - test_zeros(zeros(x, Float64), Vector{Float64}, (1,)) - @test x == [1.] - end + # #19265" + @test_throws ErrorException zeros(Float64, [1.]) # TODO change to MethodError, when v0.6 deprecations are done + x = [1.] + test_zeros(zeros(x, Float64), Vector{Float64}, (1,)) + @test x == [1.] # exotic indexing oarr = zeros(randn(3), UInt16, 1:3, -1:0) From f1bbac7a1169a3612d322e462ac01e520ba2471e Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 4 Apr 2017 10:47:07 -0400 Subject: [PATCH 0344/1534] fix error handling for ccall without a concrete layout fix #21104 --- src/cgutils.cpp | 2 +- test/ccall.jl | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 60a8c7db5b8fb..3d6321f9682f2 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -440,7 +440,7 @@ static bool julia_struct_has_layout(jl_datatype_t *dt, jl_unionall_t *ua) if (dt->layout || dt->struct_decl || jl_is_primitivetype(dt) || jl_isbits(dt)) return true; if (ua) { - size_t i, ntypes = jl_datatype_nfields(dt); + size_t i, ntypes = jl_svec_len(dt->types); for (i = 0; i < ntypes; i++) { jl_value_t *ty = jl_svecref(dt->types, i); if (jl_has_typevar_from_unionall(ty, ua)) diff --git a/test/ccall.jl b/test/ccall.jl index 33b4ec9811948..6c56ce10e429b 100644 --- a/test/ccall.jl +++ b/test/ccall.jl @@ -1239,6 +1239,23 @@ end # issue #20835 @test_throws ErrorException eval(:(f20835(x) = ccall(:fn, Void, (Ptr{typeof(x)},), x))) +@noinline f21104at(::Type{T}) where {T} = ccall(:fn, Void, (Nullable{T},), 0) +@noinline f21104rt(::Type{T}) where {T} = ccall(:fn, Nullable{T}, ()) +@test code_llvm(f21104at, (Type{Float64},)) === nothing +@test code_llvm(f21104rt, (Type{Float64},)) === nothing +@test try + f21104at(Float64) + "unreachable" + catch ex + (ex::ErrorException).msg + end == "ccall: the type of argument 1 doesn't correspond to a C type" +@test try + f21104rt(Float64) + "unreachable" + catch ex + (ex::ErrorException).msg + end == "ccall: return type doesn't correspond to a C type" + # cfunction on non-function singleton struct CallableSingleton From ac02f1e0741d2515ab3fadaa3aa3095238a8e2ba Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Tue, 4 Apr 2017 11:05:34 -0500 Subject: [PATCH 0345/1534] Test that `convert(Tuple{...}, (...))` throws for mismatched numbers of elements --- test/core.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/core.jl b/test/core.jl index f3c42b0875cfb..80e74e6144dcd 100644 --- a/test/core.jl +++ b/test/core.jl @@ -181,6 +181,8 @@ nttest1{n}(x::NTuple{n,Int}) = n # #17198 @test_throws MethodError convert(Tuple{Int}, (1.0, 2.0, 3.0)) +# #21238 +@test_throws MethodError convert(Tuple{Int,Int,Int}, (1, 2)) # type declarations From a01b8f2ccd0948e5e549b35d583c6de1a0b62a27 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 4 Apr 2017 16:17:45 -0400 Subject: [PATCH 0346/1534] fix #20614, need error for `Vararg` on non-final argument --- src/method.c | 6 ++++++ test/parse.jl | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/src/method.c b/src/method.c index 1c6177d52bdc3..e48158b9727ee 100644 --- a/src/method.c +++ b/src/method.c @@ -668,6 +668,12 @@ JL_DLLEXPORT void jl_method_def(jl_svec_t *argdata, jl_symbol_name(m->file), m->line); } + if (jl_is_vararg_type(elt) && i < na-1) + jl_exceptionf(jl_argumenterror_type, + "Vararg on non-final argument in method definition for %s at %s:%d", + jl_symbol_name(name), + jl_symbol_name(m->file), + m->line); } int ishidden = !!strchr(jl_symbol_name(name), '#'); diff --git a/test/parse.jl b/test/parse.jl index f91964a324661..75beb92f6f003 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -695,6 +695,11 @@ let m_error, error_out, filename = Base.source_path() m_error = try @eval method_c6(A; B) = 3; catch e; e; end error_out = sprint(showerror, m_error) @test error_out == "syntax: keyword argument \"B\" needs a default value" + + # issue #20614 + m_error = try @eval foo{N}(types::NTuple{N}, values::Vararg{Any,N}, c) = nothing; catch e; e; end + error_out = sprint(showerror, m_error) + @test startswith(error_out, "ArgumentError: Vararg on non-final argument") end # issue #7272 From cab83c596603501581508de9fac4599583d67465 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Tue, 4 Apr 2017 20:16:21 -0500 Subject: [PATCH 0347/1534] Ensure that `collect(::AbstractArray)` always returns an `Array` (#21257) The docstring specifies that the return type is `Array`, but `similar` isn't guaranteed to return an `Array`. (Exceptions include AxisArrays, OffsetArrays, etc.) --- base/array.jl | 10 ++++++++++ test/offsetarray.jl | 2 ++ 2 files changed, 12 insertions(+) diff --git a/base/array.jl b/base/array.jl index 55e21377a3fec..a7e28bb6f9a93 100644 --- a/base/array.jl +++ b/base/array.jl @@ -383,6 +383,8 @@ julia> collect(1:2:13) """ collect(itr) = _collect(1:1 #= Array =#, itr, iteratoreltype(itr), iteratorsize(itr)) +collect(A::AbstractArray) = _collect_indices(indices(A), A) + collect_similar(cont, itr) = _collect(cont, itr, iteratoreltype(itr), iteratorsize(itr)) _collect(cont, itr, ::HasEltype, isz::Union{HasLength,HasShape}) = @@ -396,6 +398,14 @@ function _collect(cont, itr, ::HasEltype, isz::SizeUnknown) return a end +_collect_indices(::Tuple{}, A) = copy!(Array{eltype(A)}(), A) +_collect_indices(indsA::Tuple{Vararg{OneTo}}, A) = + copy!(Array{eltype(A)}(length.(indsA)), A) +function _collect_indices(indsA, A) + B = Array{eltype(A)}(length.(indsA)) + copy!(B, CartesianRange(indices(B)), A, CartesianRange(indsA)) +end + if isdefined(Core, :Inference) _default_eltype(itrt::ANY) = Core.Inference.return_type(first, Tuple{itrt}) else diff --git a/test/offsetarray.jl b/test/offsetarray.jl index 8fffbe70bb1f0..edb61d47263ef 100644 --- a/test/offsetarray.jl +++ b/test/offsetarray.jl @@ -281,6 +281,7 @@ v = OffsetArray(v0, (-3,)) @test endof(v) == 1 @test v ≈ v @test indices(v') === (Base.OneTo(1),-2:1) +@test parent(v) == collect(v) rv = reverse(v) @test indices(rv) == indices(v) @test rv[1] == v[-2] @@ -294,6 +295,7 @@ A = OffsetArray(rand(4,4), (-3,5)) @test A ≈ A @test indices(A') === (6:9, -2:1) @test parent(A') == parent(A)' +@test collect(A) == parent(A) @test maximum(A) == maximum(parent(A)) @test minimum(A) == minimum(parent(A)) @test extrema(A) == extrema(parent(A)) From d6c5c67e1ff65a6ee6f50551dc8d9275c7674938 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 4 Apr 2017 22:24:10 -0400 Subject: [PATCH 0348/1534] fix #21271, codegen of typeassert involving `Tuple{Type{T}}` --- src/cgutils.cpp | 74 ++++++++++++++++++++++------------------------ src/codegen.cpp | 27 +++++++---------- src/intrinsics.cpp | 4 +-- test/core.jl | 6 ++++ 4 files changed, 54 insertions(+), 57 deletions(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 60a8c7db5b8fb..091c7d8de1f2c 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -941,21 +941,24 @@ static void emit_type_error(const jl_cgval_t &x, Value *type, const std::string #endif } -static Value *emit_isa(const jl_cgval_t &x, jl_value_t *type, const std::string *msg, jl_codectx_t *ctx) +static std::pair emit_isa(const jl_cgval_t &x, jl_value_t *type, const std::string *msg, jl_codectx_t *ctx) { - bool maybe_isa = true; + Optional known_isa; if (x.constant) - maybe_isa = jl_isa(x.constant, type); + known_isa = jl_isa(x.constant, type); + else if (jl_subtype(x.typ, type)) + known_isa = true; else if (jl_type_intersection(x.typ, type) == (jl_value_t*)jl_bottom_type) - maybe_isa = false; - if (!maybe_isa && msg) { - emit_type_error(x, literal_pointer_val(type), *msg, ctx); - builder.CreateUnreachable(); - BasicBlock *failBB = BasicBlock::Create(jl_LLVMContext, "fail", ctx->f); - builder.SetInsertPoint(failBB); + known_isa = false; + if (known_isa) { + if (!*known_isa && msg) { + emit_type_error(x, literal_pointer_val(type), *msg, ctx); + builder.CreateUnreachable(); + BasicBlock *failBB = BasicBlock::Create(jl_LLVMContext, "fail", ctx->f); + builder.SetInsertPoint(failBB); + } + return std::make_pair(ConstantInt::get(T_int1, *known_isa), true); } - if (!maybe_isa || x.constant) - return ConstantInt::get(T_int1, maybe_isa); // intersection with Type needs to be handled specially if (jl_has_intersect_type_not_kind(type)) { @@ -966,15 +969,15 @@ static Value *emit_isa(const jl_cgval_t &x, jl_value_t *type, const std::string #else builder.CreateCall2(prepare_call(jltypeassert_func), vx, literal_pointer_val(type)); #endif - return ConstantInt::get(T_int1, 1); + return std::make_pair(ConstantInt::get(T_int1, 1), true); } - return builder.CreateICmpNE( + return std::make_pair(builder.CreateICmpNE( #if JL_LLVM_VERSION >= 30700 builder.CreateCall(prepare_call(jlisa_func), { vx, literal_pointer_val(type) }), #else builder.CreateCall2(prepare_call(jlisa_func), vx, literal_pointer_val(type)), #endif - ConstantInt::get(T_int32, 0)); + ConstantInt::get(T_int32, 0)), false); } // tests for isa leaftype can be handled with pointer comparisons if (jl_is_leaf_type(type)) { @@ -983,7 +986,7 @@ static Value *emit_isa(const jl_cgval_t &x, jl_value_t *type, const std::string if (tindex > 0) { // optimize more when we know that this is a split union-type where tindex = 0 is invalid Value *xtindex = builder.CreateAnd(x.TIndex, ConstantInt::get(T_int8, 0x7f)); - return builder.CreateICmpEQ(xtindex, ConstantInt::get(T_int8, tindex)); + return std::make_pair(builder.CreateICmpEQ(xtindex, ConstantInt::get(T_int8, tindex)), false); } else { // test for (x.TIndex == 0x80 && typeof(x.V) == type) @@ -999,31 +1002,29 @@ static Value *emit_isa(const jl_cgval_t &x, jl_value_t *type, const std::string PHINode *istype = builder.CreatePHI(T_int1, 2); istype->addIncoming(ConstantInt::get(T_int1, 0), currBB); istype->addIncoming(istype_boxed, isaBB); - return istype; + return std::make_pair(istype, false); } } - return builder.CreateICmpEQ(emit_typeof_boxed(x, ctx), literal_pointer_val(type)); + return std::make_pair(builder.CreateICmpEQ(emit_typeof_boxed(x, ctx), literal_pointer_val(type)), false); } // everything else can be handled via subtype tests Value *vxt = emit_typeof_boxed(x, ctx); - return builder.CreateICmpNE( + return std::make_pair(builder.CreateICmpNE( #if JL_LLVM_VERSION >= 30700 builder.CreateCall(prepare_call(jlsubtype_func), { vxt, literal_pointer_val(type) }), #else builder.CreateCall2(prepare_call(jlsubtype_func), vxt, literal_pointer_val(type)), #endif - ConstantInt::get(T_int32, 0)); + ConstantInt::get(T_int32, 0)), false); } static void emit_typecheck(const jl_cgval_t &x, jl_value_t *type, const std::string &msg, jl_codectx_t *ctx) { - // if (jl_subtype(x.typ, type)) { - // // This case should already be handled by the caller - // return; - // } - Value *istype = emit_isa(x, type, &msg, ctx); - if (!isa(istype)) { + Value *istype; + bool handled_msg; + std::tie(istype, handled_msg) = emit_isa(x, type, &msg, ctx); + if (!handled_msg) { BasicBlock *failBB = BasicBlock::Create(jl_LLVMContext, "fail", ctx->f); BasicBlock *passBB = BasicBlock::Create(jl_LLVMContext, "pass"); builder.CreateCondBr(istype, passBB, failBB); @@ -2176,12 +2177,11 @@ static jl_cgval_t emit_new_struct(jl_value_t *ty, size_t nargs, jl_value_t **arg strct = emit_static_alloca(lt); unsigned idx = 0; - for (size_t i=0; i < na; i++) { - jl_value_t *jtype = jl_svecref(sty->types,i); + for (size_t i = 0; i < na; i++) { + jl_value_t *jtype = jl_svecref(sty->types, i); Type *fty = julia_type_to_llvm(jtype); - jl_cgval_t fval_info = emit_expr(args[i+1], ctx); - if (!jl_subtype(fval_info.typ, jtype)) - emit_typecheck(fval_info, jtype, "new", ctx); + jl_cgval_t fval_info = emit_expr(args[i + 1], ctx); + emit_typecheck(fval_info, jtype, "new", ctx); if (!type_is_ghost(fty)) { Value *fval = NULL, *dest = NULL; if (!init_as_value) { @@ -2225,34 +2225,32 @@ static jl_cgval_t emit_new_struct(jl_value_t *ty, size_t nargs, jl_value_t **arg jl_cgval_t strctinfo = mark_julia_type(strct, true, ty, ctx); if (f1) { jl_cgval_t f1info = mark_julia_type(f1, true, jl_any_type, ctx); - if (!jl_subtype(expr_type(args[1],ctx), jl_field_type(sty,0))) - emit_typecheck(f1info, jl_field_type(sty,0), "new", ctx); + emit_typecheck(f1info, jl_field_type(sty, 0), "new", ctx); emit_setfield(sty, strctinfo, 0, f1info, ctx, false, false); } - for(size_t i=j; i < nf; i++) { + for (size_t i = j; i < nf; i++) { if (jl_field_isptr(sty, i)) { tbaa_decorate(strctinfo.tbaa, builder.CreateStore( V_null, builder.CreatePointerCast( builder.CreateGEP(emit_bitcast(strct, T_pint8), - ConstantInt::get(T_size, jl_field_offset(sty,i))), + ConstantInt::get(T_size, jl_field_offset(sty, i))), T_ppjlvalue))); } } bool need_wb = false; // TODO: verify that nargs <= nf (currently handled by front-end) - for(size_t i=j+1; i < nargs; i++) { + for (size_t i = j + 1; i < nargs; i++) { jl_cgval_t rhs = emit_expr(args[i], ctx); if (jl_field_isptr(sty, i - 1) && !rhs.isboxed) { need_wb = true; } if (rhs.isboxed) { - if (!jl_subtype(expr_type(args[i],ctx), jl_svecref(sty->types,i-1))) - emit_typecheck(rhs, jl_svecref(sty->types,i-1), "new", ctx); + emit_typecheck(rhs, jl_svecref(sty->types, i - 1), "new", ctx); } if (might_need_root(args[i])) // TODO: how to remove this? need_wb = true; - emit_setfield(sty, strctinfo, i-1, rhs, ctx, false, need_wb); + emit_setfield(sty, strctinfo, i - 1, rhs, ctx, false, need_wb); } return strctinfo; } diff --git a/src/codegen.cpp b/src/codegen.cpp index 210ca52284752..998ffbb4ac20b 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -74,6 +74,7 @@ // support #include +#include #include #include #include // for llvmcall @@ -2525,9 +2526,9 @@ static Value *emit_f_is(const jl_cgval_t &arg1, const jl_cgval_t &arg2, jl_codec if (arg1.isghost || arg2.isghost) { // comparing to a singleton object if (arg1.TIndex) - return emit_isa(arg1, rt2, NULL, ctx); // rt2 is a singleton type + return emit_isa(arg1, rt2, NULL, ctx).first; // rt2 is a singleton type if (arg2.TIndex) - return emit_isa(arg2, rt1, NULL, ctx); // rt1 is a singleton type + return emit_isa(arg2, rt1, NULL, ctx).first; // rt1 is a singleton type // mark_gc_use isn't needed since we won't load this pointer // and we know at least one of them is a unique Singleton // which is already enough to ensure pointer uniqueness for this test @@ -2543,7 +2544,7 @@ static Value *emit_f_is(const jl_cgval_t &arg1, const jl_cgval_t &arg2, jl_codec jl_value_t *typ = jl_isbits(rt1) ? rt1 : rt2; if (rt1 == rt2) return emit_bits_compare(arg1, arg2, ctx); - Value *same_type = (typ == rt2) ? emit_isa(arg1, typ, NULL, ctx) : emit_isa(arg2, typ, NULL, ctx); + Value *same_type = (typ == rt2) ? emit_isa(arg1, typ, NULL, ctx).first : emit_isa(arg2, typ, NULL, ctx).first; BasicBlock *currBB = builder.GetInsertBlock(); BasicBlock *isaBB = BasicBlock::Create(jl_LLVMContext, "is", ctx->f); BasicBlock *postBB = BasicBlock::Create(jl_LLVMContext, "post_is", ctx->f); @@ -2637,8 +2638,7 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, jl_value_t *tp0 = jl_tparam0(ty); *ret = emit_expr(args[1], ctx); emit_expr(args[2], ctx); - if (!jl_subtype(arg, tp0)) - emit_typecheck(*ret, tp0, "typeassert", ctx); + emit_typecheck(*ret, tp0, "typeassert", ctx); ty = expr_type(expr, ctx); rt2 = ty; *ret = update_julia_type(*ret, ty, ctx); JL_GC_POP(); @@ -2672,13 +2672,10 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, jl_value_t *tp0 = jl_tparam0(ty); jl_cgval_t rt_arg = emit_expr(args[1], ctx); emit_expr(args[2], ctx); - if (jl_subtype(arg, tp0)) { - *ret = mark_julia_type(ConstantInt::get(T_int8, 1), false, jl_bool_type, ctx); - } - else { - Value *isa = emit_isa(rt_arg, tp0, NULL, ctx); - *ret = mark_julia_type(builder.CreateZExt(isa, T_int8), false, jl_bool_type, ctx); - } + Value *isa_result = emit_isa(rt_arg, tp0, NULL, ctx).first; + if (isa_result->getType() == T_int1) + isa_result = builder.CreateZExt(isa_result, T_int8); + *ret = mark_julia_type(isa_result, false, jl_bool_type, ctx); JL_GC_POP(); return true; } @@ -4587,10 +4584,8 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t retval = mark_julia_type(ret, true, astrt, &ctx); } - if (!jl_subtype(astrt, declrt)) { - // inline a call to typeassert here - emit_typecheck(retval, declrt, "cfunction", &ctx); - } + // inline a call to typeassert here + emit_typecheck(retval, declrt, "cfunction", &ctx); // Prepare the return value Value *r; diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index 3856f4d10ce5b..7dd108e7bb4bd 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -661,9 +661,7 @@ static jl_cgval_t emit_pointerset(jl_cgval_t *argv, jl_codectx_t *ctx) return emit_runtime_pointerset(argv, ctx); if (!jl_is_datatype(ety)) ety = (jl_value_t*)jl_any_type; - jl_value_t *xty = x.typ; - if (!jl_subtype(xty, ety)) - emit_typecheck(x, ety, "pointerset: type mismatch in assign", ctx); + emit_typecheck(x, ety, "pointerset: type mismatch in assign", ctx); Value *idx = emit_unbox(T_size, i, (jl_value_t*)jl_long_type); Value *im1 = builder.CreateSub(idx, ConstantInt::get(T_size, 1)); diff --git a/test/core.jl b/test/core.jl index f3c42b0875cfb..b1c52fab95f9b 100644 --- a/test/core.jl +++ b/test/core.jl @@ -4792,3 +4792,9 @@ b21178(::F1,::F2) where {B1,B2,F1<:F21178{B1,<:Any},F2<:F21178{B2}} = F1,F2,B1,B a21172 = f21172(x) = 2x @test f21172(8) == 16 @test a21172 === f21172 + +# issue #21271 +f21271() = convert(Tuple{Type{Int}, Type{Float64}}, (Int, Float64))::Tuple{Type{Int}, Type{Float64}} +f21271(x) = x::Tuple{Type{Int}, Type{Float64}} +@test_throws TypeError f21271() +@test_throws TypeError f21271((Int, Float64)) From 9d641e4e9dec270655be750f023e758ab98e52e2 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 4 Apr 2017 18:12:10 -0400 Subject: [PATCH 0349/1534] help union-alloca variables emit better native code SROA likes this form better Also, since many of these loop variables are loop-dependent, it helps to run the loop structure analysis passes twice --- src/cgutils.cpp | 81 +++++++++++++++++++++++++++++++++-------------- src/codegen.cpp | 7 +++- src/jitlayers.cpp | 22 +++++++++++-- 3 files changed, 84 insertions(+), 26 deletions(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 2a05fc60f0ef3..17c7aad31c999 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -1360,9 +1360,30 @@ static jl_cgval_t emit_getfield_knownidx(const jl_cgval_t &strct, unsigned idx, Value *fldv = NULL; if (strct.ispointer()) { Value *addr; - Value *ptr = data_pointer(strct, ctx, T_pint8); - Value *llvm_idx = ConstantInt::get(T_size, jl_field_offset(jt, idx)); - addr = builder.CreateGEP(ptr, llvm_idx); + bool isboxed; + Type *lt = julia_type_to_llvm((jl_value_t*)jt, &isboxed); + if (isboxed) { + Value *ptr = data_pointer(strct, ctx, T_pint8); + Value *llvm_idx = ConstantInt::get(T_size, jl_field_offset(jt, idx)); + addr = builder.CreateGEP(ptr, llvm_idx); + } + else { + if (VectorType *vlt = dyn_cast(lt)) { + // doesn't have the struct wrapper, so this must have been a VecElement + // cast to the element type so that it can be addressed with GEP + lt = vlt->getElementType(); + Value *ptr = data_pointer(strct, ctx, lt->getPointerTo()); + Value *llvm_idx = ConstantInt::get(T_size, idx); + addr = builder.CreateGEP(LLVM37_param(lt) ptr, llvm_idx); + } + else if (lt->isSingleValueType()) { + addr = data_pointer(strct, ctx, lt->getPointerTo()); + } + else { + Value *ptr = data_pointer(strct, ctx, lt->getPointerTo()); + addr = builder.CreateStructGEP(LLVM37_param(lt) ptr, idx); + } + } if (jl_field_isptr(jt, idx)) { Value *fldv = tbaa_decorate(strct.tbaa, builder.CreateLoad(emit_bitcast(addr, T_ppjlvalue))); if (idx >= (unsigned)jt->ninitialized) @@ -1966,6 +1987,8 @@ static Value *boxed(const jl_cgval_t &vinfo, jl_codectx_t *ctx, bool gcrooted) // copy src to dest, if src is isbits. if skip is true, the value of dest is undefined static void emit_unionmove(Value *dest, const jl_cgval_t &src, Value *skip, bool isVolatile, MDNode *tbaa, jl_codectx_t *ctx) { + if (AllocaInst *ai = dyn_cast(dest)) + builder.CreateStore(UndefValue::get(ai->getAllocatedType()), ai); if (jl_is_leaf_type(src.typ) || src.constant) { jl_value_t *typ = src.constant ? jl_typeof(src.constant) : src.typ; Type *store_ty = julia_type_to_llvm(typ); @@ -1982,38 +2005,50 @@ static void emit_unionmove(Value *dest, const jl_cgval_t &src, Value *skip, bool src_ptr = builder.CreateSelect(skip, dest, src_ptr); unsigned nb = jl_datatype_size(typ); unsigned alignment = 0; - builder.CreateMemCpy(dest, src_ptr, nb, alignment, tbaa); + builder.CreateMemCpy(dest, src_ptr, nb, alignment, isVolatile, tbaa); } } } else if (src.TIndex) { Value *tindex = builder.CreateAnd(src.TIndex, ConstantInt::get(T_int8, 0x7f)); - Value *copy_bytes = ConstantInt::get(T_int32, -1); + if (skip) + tindex = builder.CreateSelect(skip, ConstantInt::get(T_int8, 0), tindex); + Value *src_ptr = data_pointer(src, ctx, T_pint8); + if (dest->getType() != T_pint8) + dest = emit_bitcast(dest, T_pint8); + BasicBlock *defaultBB = BasicBlock::Create(jl_LLVMContext, "union_move_skip", ctx->f); + SwitchInst *switchInst = builder.CreateSwitch(tindex, defaultBB); + BasicBlock *postBB = BasicBlock::Create(jl_LLVMContext, "post_union_move", ctx->f); unsigned counter = 0; bool allunboxed = for_each_uniontype_small( [&](unsigned idx, jl_datatype_t *jt) { - Value *cmp = builder.CreateICmpEQ(tindex, ConstantInt::get(T_int8, idx)); - copy_bytes = builder.CreateSelect(cmp, ConstantInt::get(T_int32, jl_datatype_size(jt)), copy_bytes); + unsigned nb = jl_datatype_size(jt); + unsigned alignment = 0; + BasicBlock *tempBB = BasicBlock::Create(jl_LLVMContext, "union_move", ctx->f); + builder.SetInsertPoint(tempBB); + switchInst->addCase(ConstantInt::get(T_int8, idx), tempBB); + if (nb > 0) + builder.CreateMemCpy(dest, src_ptr, nb, alignment, isVolatile, tbaa); + builder.CreateBr(postBB); }, src.typ, counter); - Value *src_ptr = data_pointer(src, ctx, T_pint8); - if (dest->getType() != T_pint8) - dest = emit_bitcast(dest, T_pint8); - if (skip) { - if (allunboxed) // copy dest -> dest to simulate an undef value / conditional copy - src_ptr = builder.CreateSelect(skip, dest, src_ptr); - else - copy_bytes = builder.CreateSelect(skip, ConstantInt::get(copy_bytes->getType(), 0), copy_bytes); + builder.SetInsertPoint(defaultBB); + if (!skip && allunboxed && (src.V == NULL || isa(src.V))) { + Function *trap_func = Intrinsic::getDeclaration( + ctx->f->getParent(), + Intrinsic::trap); + builder.CreateCall(trap_func); + builder.CreateUnreachable(); + } + else { + builder.CreateBr(postBB); + } + builder.SetInsertPoint(postBB); + if (src.gcroot && src.V != src.gcroot) { + // if this is a derived pointer, make sure the root usage itself is also visible to the delete-root pass + mark_gc_use(src); } -#ifndef JL_NDEBUG - // try to catch codegen errors early, before it uses this to memcpy over the entire stack - CreateConditionalAbort(builder, builder.CreateICmpEQ(copy_bytes, ConstantInt::get(T_int32, -1))); -#endif - builder.CreateMemCpy(dest, - src_ptr, - copy_bytes, - /*TODO: min-align*/1); } else { Value *datatype = emit_typeof_boxed(src, ctx); diff --git a/src/codegen.cpp b/src/codegen.cpp index 998ffbb4ac20b..e3b4826a1dc03 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -829,6 +829,7 @@ static void CreateTrap(IRBuilder<> &builder) builder.SetInsertPoint(newBB); } +#if 0 // this code is likely useful, but currently unused #ifndef JL_NDEBUG static void CreateConditionalAbort(IRBuilder<> &builder, Value *test) { @@ -845,6 +846,7 @@ static void CreateConditionalAbort(IRBuilder<> &builder, Value *test) builder.SetInsertPoint(postBB); } #endif +#endif static void emit_write_barrier(jl_codectx_t*, Value*, Value*); @@ -3629,7 +3631,8 @@ static Value *try_emit_union_alloca(jl_uniontype_t *ut, bool &allunbox, size_t & union_alloca_type(ut, allunbox, nbytes, align, min_align); if (nbytes > 0) { // at least some of the values can live on the stack - Type *AT = ArrayType::get(T_int8, nbytes); + // try to pick an Integer type size such that SROA will emit reasonable code + Type *AT = ArrayType::get(IntegerType::get(jl_LLVMContext, 8 * min_align), (nbytes + min_align - 1) / min_align); AllocaInst *lv = emit_static_alloca(AT, ctx); if (align > 1) lv->setAlignment(align); @@ -3853,6 +3856,8 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) } else { Value *dest = vi.value.V; + if (vi.pTIndex) + builder.CreateStore(UndefValue::get(cast(vi.value.V)->getAllocatedType()), vi.value.V); Type *store_ty = julia_type_to_llvm(rval_info.constant ? jl_typeof(rval_info.constant) : rval_info.typ); Type *dest_ty = store_ty->getPointerTo(); if (dest_ty != dest->getType()) diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index 5853fe8aba69b..27eca4c7e3c14 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -127,7 +127,14 @@ void addOptimizationPasses(PassManager *PM) PM->add(llvm::createMemorySanitizerPass(true)); #endif if (jl_options.opt_level == 0) { + PM->add(createCFGSimplificationPass()); // Clean up disgusting code + PM->add(createMemCpyOptPass()); // Remove memcpy / form memset PM->add(createLowerPTLSPass(imaging_mode)); +#if JL_LLVM_VERSION >= 40000 + PM->add(createAlwaysInlinerLegacyPass()); // Respect always_inline +#else + PM->add(createAlwaysInlinerPass()); // Respect always_inline +#endif return; } #if JL_LLVM_VERSION >= 30700 @@ -149,7 +156,10 @@ void addOptimizationPasses(PassManager *PM) } // list of passes from vmkit PM->add(createCFGSimplificationPass()); // Clean up disgusting code - PM->add(createPromoteMemoryToRegisterPass());// Kill useless allocas + PM->add(createPromoteMemoryToRegisterPass()); // Kill useless allocas + + // hopefully these functions (from llvmcall) don't try to interact with the Julia runtime + // or have anything that might corrupt the createLowerPTLSPass pass #if JL_LLVM_VERSION >= 40000 PM->add(createAlwaysInlinerLegacyPass()); // Respect always_inline #else @@ -229,6 +239,15 @@ void addOptimizationPasses(PassManager *PM) #endif PM->add(createJumpThreadingPass()); // Thread jumps PM->add(createDeadStoreEliminationPass()); // Delete dead stores + + // see if all of the constant folding has exposed more loops + // to simplification and deletion + // this helps significantly with cleaning up iteration + PM->add(createCFGSimplificationPass()); // Merge & remove BBs + PM->add(createLoopIdiomPass()); + PM->add(createLoopDeletionPass()); // Delete dead loops + PM->add(createJumpThreadingPass()); // Thread jumps + #if JL_LLVM_VERSION >= 30500 if (jl_options.opt_level >= 3) { PM->add(createSLPVectorizerPass()); // Vectorize straight-line code @@ -242,7 +261,6 @@ void addOptimizationPasses(PassManager *PM) PM->add(createLoopVectorizePass()); // Vectorize loops PM->add(createInstructionCombiningPass()); // Clean up after loop vectorizer #endif - //PM->add(createCFGSimplificationPass()); // Merge & remove BBs } #ifdef USE_ORCJIT From 58dd828276832508c9f6aa6e5d56274ae3d73655 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 5 Apr 2017 02:30:48 -0400 Subject: [PATCH 0350/1534] disable llvm output from PR #21276 test --- test/ccall.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/ccall.jl b/test/ccall.jl index 6c56ce10e429b..3e6ce1bbadbfd 100644 --- a/test/ccall.jl +++ b/test/ccall.jl @@ -1241,8 +1241,8 @@ end @test_throws ErrorException eval(:(f20835(x) = ccall(:fn, Void, (Ptr{typeof(x)},), x))) @noinline f21104at(::Type{T}) where {T} = ccall(:fn, Void, (Nullable{T},), 0) @noinline f21104rt(::Type{T}) where {T} = ccall(:fn, Nullable{T}, ()) -@test code_llvm(f21104at, (Type{Float64},)) === nothing -@test code_llvm(f21104rt, (Type{Float64},)) === nothing +@test code_llvm(DevNull, f21104at, (Type{Float64},)) === nothing +@test code_llvm(DevNull, f21104rt, (Type{Float64},)) === nothing @test try f21104at(Float64) "unreachable" From f81c6269e31cf3abaf1b5f851fd742f0549e6328 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 4 Apr 2017 11:19:33 -0400 Subject: [PATCH 0351/1534] codegen emit constant data as llvm constants this allows llvm to optimize constant data access fix #21121 --- src/ccall.cpp | 25 ++++++++++++++----------- src/cgutils.cpp | 25 ++++++++++++++----------- src/codegen.cpp | 27 +++++++++++++++++++++++++-- 3 files changed, 53 insertions(+), 24 deletions(-) diff --git a/src/ccall.cpp b/src/ccall.cpp index c80ad39ce9d50..934be68a0ec8c 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -1927,19 +1927,18 @@ jl_cgval_t function_sig_t::emit_a_ccall( // argument, allocate the box and store that as the first argument type bool sretboxed = false; if (sret) { - jl_cgval_t sret_val = emit_new_struct(rt, 1, NULL, ctx); // TODO: is it valid to be creating an incomplete type this way? - assert(sret_val.typ != NULL && "Type was not concrete"); - if (!sret_val.ispointer()) { - Value *mem = emit_static_alloca(lrt, ctx); - builder.CreateStore(sret_val.V, mem); - result = mem; + assert(!retboxed && jl_is_datatype(rt) && "sret return type invalid"); + if (jl_isbits(rt)) { + result = emit_static_alloca(lrt, ctx); } else { - // XXX: result needs a GC root here if result->getType() == T_pjlvalue - result = sret_val.V; + // XXX: result needs to be zero'd and given a GC root here + assert(jl_datatype_size(rt) > 0 && "sret shouldn't be a singleton instance"); + result = emit_allocobj(ctx, jl_datatype_size(rt), + literal_pointer_val((jl_value_t*)rt)); + sretboxed = true; } argvals[0] = emit_bitcast(result, fargt_sig.at(0)); - sretboxed = sret_val.isboxed; } Instruction *stacksave = NULL; @@ -2062,8 +2061,12 @@ jl_cgval_t function_sig_t::emit_a_ccall( } else if (sret) { jlretboxed = sretboxed; - if (!jlretboxed) - result = builder.CreateLoad(result); // something alloca'd above + if (!jlretboxed) { + // something alloca'd above is SSA + if (static_rt) + return mark_julia_slot(result, rt, NULL, tbaa_stack); + result = builder.CreateLoad(result); + } } else { Type *jlrt = julia_type_to_llvm(rt, &jlretboxed); // compute the real "julian" return type and compute whether it is boxed diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 2a05fc60f0ef3..a97c520127db9 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -74,20 +74,13 @@ static Value *stringConstPtr(IRBuilder<> &builder, const std::string &txt) static int strno = 0; std::stringstream ssno; ssno << "_j_str" << strno++; - GlobalVariable *gv = new GlobalVariable(*shadow_output, - ArrayType::get(T_int8, pooledtxt.size()), - true, - GlobalVariable::PrivateLinkage, + GlobalVariable *gv = get_pointer_to_constant( ConstantDataArray::get(jl_LLVMContext, ArrayRef( (const unsigned char*)pooledtxt.data(), pooledtxt.size())), - ssno.str()); -#if JL_LLVM_VERSION >= 30900 - gv->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); -#else - gv->setUnnamedAddr(true); -#endif + ssno.str(), + *shadow_output); pooledval->second = gv; jl_ExecutionEngine->addGlobalMapping(gv, (void*)(uintptr_t)pooledtxt.data()); } @@ -1272,9 +1265,19 @@ static jl_value_t *expr_type(jl_value_t *e, jl_codectx_t *ctx) // --- accessing the representations of built-in data types --- +static Constant *julia_const_to_llvm(jl_value_t *e); static Value *data_pointer(const jl_cgval_t &x, jl_codectx_t *ctx, Type *astype = T_ppjlvalue) { - Value *data = x.constant ? boxed(x, ctx) : x.V; + Value *data = x.V; + if (x.constant) { + Constant *val = julia_const_to_llvm(x.constant); + if (val) { + data = get_pointer_to_constant(val, "", *jl_Module); + } + else { + data = boxed(x, ctx); + } + } if (data->getType() != astype) data = emit_bitcast(data, astype); return data; diff --git a/src/codegen.cpp b/src/codegen.cpp index 998ffbb4ac20b..54353f2305ea9 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -657,6 +657,23 @@ template static void mark_gc_uses(T &&vec) // --- convenience functions for tagging llvm values with julia types --- +static GlobalVariable *get_pointer_to_constant(Constant *val, StringRef name, Module &M) +{ + GlobalVariable *gv = new GlobalVariable( + M, + val->getType(), + true, + GlobalVariable::PrivateLinkage, + val, + name); +#if JL_LLVM_VERSION >= 30900 + gv->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); +#else + gv->setUnnamedAddr(true); +#endif + return gv; +} + static AllocaInst *emit_static_alloca(Type *lty, int arraysize, jl_codectx_t *ctx) { return new AllocaInst(lty, ConstantInt::get(T_int32, arraysize), "", /*InsertBefore=*/ctx->ptlsStates); @@ -740,8 +757,14 @@ static inline jl_cgval_t mark_julia_type(Value *v, bool isboxed, jl_value_t *typ if (v && T->isAggregateType() && !isboxed) { // eagerly put this back onto the stack // llvm mem2reg pass will remove this if unneeded - Value *loc = emit_static_alloca(T); - builder.CreateStore(v, loc); + Value *loc; + if (Constant *cv = dyn_cast(v)) { + loc = get_pointer_to_constant(cv, "", *jl_Module); + } + else { + loc = emit_static_alloca(T); + builder.CreateStore(v, loc); + } return mark_julia_slot(loc, typ, NULL, tbaa_stack); } Value *froot = NULL; From 188bef21dc3b8e6f1b269ebd85fbd8a04dad1842 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 4 Apr 2017 18:33:09 -0400 Subject: [PATCH 0352/1534] add NoCapture and ReadOnly attributes to function calls --- src/codegen.cpp | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 54353f2305ea9..c6b2f318c83c1 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -5005,26 +5005,35 @@ static jl_returninfo_t get_specsig_function(Module *M, const std::string &name, } } } +#if JL_LLVM_VERSION >= 50000 + AttributeList attributes; // function declaration attributes +#else + AttributeSet attributes; // function declaration attributes +#endif + if (props.cc == jl_returninfo_t::SRet) { + attributes = attributes.addAttribute(jl_LLVMContext, 1, Attribute::StructRet); + attributes = attributes.addAttribute(jl_LLVMContext, 1, Attribute::NoAlias); + attributes = attributes.addAttribute(jl_LLVMContext, 1, Attribute::NoCapture); + } + if (props.cc == jl_returninfo_t::Union) { + attributes = attributes.addAttribute(jl_LLVMContext, 1, Attribute::NoAlias); + attributes = attributes.addAttribute(jl_LLVMContext, 1, Attribute::NoCapture); + } for (size_t i = 0; i < jl_nparams(sig); i++) { jl_value_t *jt = jl_tparam(sig, i); Type *ty = julia_type_to_llvm(jt); if (type_is_ghost(ty)) continue; - if (ty->isAggregateType()) // aggregate types are passed by pointer + if (ty->isAggregateType()) { // aggregate types are passed by pointer + attributes = attributes.addAttribute(jl_LLVMContext, fsig.size() + 1, Attribute::NoCapture); + attributes = attributes.addAttribute(jl_LLVMContext, fsig.size() + 1, Attribute::ReadOnly); ty = PointerType::get(ty, 0); + } fsig.push_back(ty); } FunctionType *ftype = FunctionType::get(rt, fsig, false); Function *f = Function::Create(ftype, GlobalVariable::ExternalLinkage, name, M); - if (props.cc == jl_returninfo_t::SRet) { - f->addAttribute(1, Attribute::StructRet); - f->addAttribute(1, Attribute::NoAlias); - f->addAttribute(1, Attribute::NoCapture); - } - if (props.cc == jl_returninfo_t::Union) { - f->addAttribute(1, Attribute::NoAlias); - f->addAttribute(1, Attribute::NoCapture); - } + f->setAttributes(attributes); props.decl = f; return props; } From 2c38fecbfa06b11653cfd61cea996222ef18dbee Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Wed, 5 Apr 2017 09:57:51 -0500 Subject: [PATCH 0353/1534] Move credential_loop out of Base --- base/libgit2/callbacks.jl | 53 ------------------------------------ test/TestHelpers.jl | 5 +++- test/libgit2-helpers.jl | 56 +++++++++++++++++++++++++++++++++++++++ test/libgit2.jl | 10 ++++--- 4 files changed, 67 insertions(+), 57 deletions(-) create mode 100644 test/libgit2-helpers.jl diff --git a/base/libgit2/callbacks.jl b/base/libgit2/callbacks.jl index c3e9d4c7b6e36..2cfa1cb1ef2e9 100644 --- a/base/libgit2/callbacks.jl +++ b/base/libgit2/callbacks.jl @@ -253,56 +253,3 @@ mirror_cb() = cfunction(mirror_callback, Cint, (Ptr{Ptr{Void}}, Ptr{Void}, Cstri credentials_cb() = cfunction(credentials_callback, Cint, (Ptr{Ptr{Void}}, Cstring, Cstring, Cuint, Ptr{Void})) "C function pointer for `fetchhead_foreach_callback`" fetchhead_foreach_cb() = cfunction(fetchhead_foreach_callback, Cint, (Cstring, Cstring, Ptr{GitHash}, Cuint, Ptr{Void})) - -""" -Emulates the LibGit2 credential loop to allows testing of the credential_callback function -without having to authenticate against a real server. -""" -function credential_loop( - valid_credential::AbstractCredentials, - url::AbstractString, - user::AbstractString, - allowed_types::UInt32) - cb = credentials_cb() - libgitcred_ptr_ptr = Ref{Ptr{Void}}(C_NULL) - cache = CachedCredentials() - payload_ptr = Ref(Nullable{AbstractCredentials}(cache)) - - # Number of times credentials were authenticated against. With the real LibGit2 - # credential loop this would be how many times we sent credentials to the remote. - num_authentications = 0 - - # Emulate how LibGit2 uses the credential callback by repeatedly calling the function - # until we find valid credentials or an exception is raised. - err = Cint(0) - while err == 0 - err = ccall(cb, Cint, (Ptr{Ptr{Void}}, Cstring, Cstring, Cuint, Ptr{Void}), - libgitcred_ptr_ptr, url, isempty(user) ? C_NULL : user, allowed_types, pointer_from_objref(payload_ptr)) - num_authentications += 1 - - # Check if the callback provided us with valid credentials - if length(cache.cred) == 1 && first(values(cache.cred)) == valid_credential - break - end - - if num_authentications > 50 - error("Credential callback seems to be caught in an infinite loop") - end - end - - return err, num_authentications -end - -function credential_loop( - valid_credential::UserPasswordCredentials, - url::AbstractString, - user::AbstractString="") - credential_loop(valid_credential, url, user, 0x000001) -end - -function credential_loop( - valid_credential::SSHCredentials, - url::AbstractString, - user::AbstractString="") - credential_loop(valid_credential, url, user, 0x000046) -end diff --git a/test/TestHelpers.jl b/test/TestHelpers.jl index 538e6a07a3d8a..422cd085410ff 100644 --- a/test/TestHelpers.jl +++ b/test/TestHelpers.jl @@ -56,8 +56,11 @@ end function challenge_prompt(code::AbstractString, challenges; timeout::Integer=10, debug::Bool=true) output_file = tempname() wrapped_code = """ + result = let + $code + end open("$output_file", "w") do fp - serialize(fp, begin $code end) + serialize(fp, result) end """ cmd = `$(Base.julia_cmd()) --startup-file=no -e $wrapped_code` diff --git a/test/libgit2-helpers.jl b/test/libgit2-helpers.jl new file mode 100644 index 0000000000000..9312487aa39a9 --- /dev/null +++ b/test/libgit2-helpers.jl @@ -0,0 +1,56 @@ +# This file is a part of Julia. License is MIT: http://julialang.org/license + +import Base.LibGit2: AbstractCredentials, UserPasswordCredentials, SSHCredentials + +""" +Emulates the LibGit2 credential loop to allows testing of the credential_callback function +without having to authenticate against a real server. +""" +function credential_loop( + valid_credential::AbstractCredentials, + url::AbstractString, + user::AbstractString, + allowed_types::UInt32) + cb = Base.LibGit2.credentials_cb() + libgitcred_ptr_ptr = Ref{Ptr{Void}}(C_NULL) + cache = Base.LibGit2.CachedCredentials() + payload_ptr = Ref(Nullable{AbstractCredentials}(cache)) + + # Number of times credentials were authenticated against. With the real LibGit2 + # credential loop this would be how many times we sent credentials to the remote. + num_authentications = 0 + + # Emulate how LibGit2 uses the credential callback by repeatedly calling the function + # until we find valid credentials or an exception is raised. + err = Cint(0) + while err == 0 + err = ccall(cb, Cint, (Ptr{Ptr{Void}}, Cstring, Cstring, Cuint, Ptr{Void}), + libgitcred_ptr_ptr, url, isempty(user) ? C_NULL : user, allowed_types, pointer_from_objref(payload_ptr)) + num_authentications += 1 + + # Check if the callback provided us with valid credentials + if length(cache.cred) == 1 && first(values(cache.cred)) == valid_credential + break + end + + if num_authentications > 50 + error("Credential callback seems to be caught in an infinite loop") + end + end + + return err, num_authentications +end + +function credential_loop( + valid_credential::UserPasswordCredentials, + url::AbstractString, + user::AbstractString="") + credential_loop(valid_credential, url, user, 0x000001) +end + +function credential_loop( + valid_credential::SSHCredentials, + url::AbstractString, + user::AbstractString="") + credential_loop(valid_credential, url, user, 0x000046) +end diff --git a/test/libgit2.jl b/test/libgit2.jl index a7e2a22810f40..bc93cbadabc71 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -4,6 +4,7 @@ isdefined(Main, :TestHelpers) || @eval Main include(joinpath(dirname(@__FILE__), import TestHelpers: challenge_prompt const LIBGIT2_MIN_VER = v"0.23.0" +const LIBGIT2_HELPER_PATH = joinpath(dirname(@__FILE__), "libgit2-helpers.jl") ######### # TESTS # @@ -1105,14 +1106,16 @@ mktempdir() do dir passphrase = "secret" ssh_cmd = """ + include("$LIBGIT2_HELPER_PATH") valid_cred = LibGit2.SSHCredentials("git", "", "$valid_key", "$valid_key.pub") - err, auth_attempts = LibGit2.credential_loop(valid_cred, "$url", "git") + err, auth_attempts = credential_loop(valid_cred, "$url", "git") (err < 0 ? LibGit2.GitError(err) : err, auth_attempts) """ ssh_p_cmd = """ + include("$LIBGIT2_HELPER_PATH") valid_cred = LibGit2.SSHCredentials("git", "$passphrase", "$valid_p_key", "$valid_p_key.pub") - err, auth_attempts = LibGit2.credential_loop(valid_cred, "$url", "git") + err, auth_attempts = credential_loop(valid_cred, "$url", "git") (err < 0 ? LibGit2.GitError(err) : err, auth_attempts) """ @@ -1221,8 +1224,9 @@ mktempdir() do dir valid_password = randstring(16) https_cmd = """ + include("$LIBGIT2_HELPER_PATH") valid_cred = LibGit2.UserPasswordCredentials("$valid_username", "$valid_password") - err, auth_attempts = LibGit2.credential_loop(valid_cred, "$url") + err, auth_attempts = credential_loop(valid_cred, "$url") (err < 0 ? LibGit2.GitError(err) : err, auth_attempts) """ From a5053ac804dc259475d7c9c444abc6a3f3b9812e Mon Sep 17 00:00:00 2001 From: kshyatt Date: Thu, 9 Mar 2017 08:58:22 -0800 Subject: [PATCH 0354/1534] [docathon] Add examples for diff_files --- base/libgit2/libgit2.jl | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/base/libgit2/libgit2.jl b/base/libgit2/libgit2.jl index 6f5f9bebbb34e..1843944e01137 100644 --- a/base/libgit2/libgit2.jl +++ b/base/libgit2/libgit2.jl @@ -154,6 +154,25 @@ The keyword argument is: Returns only the *names* of the files which have changed, *not* their contents. +# Example + +```julia +LibGit2.branch!(repo, "branch/a") +LibGit2.branch!(repo, "branch/b") +# add a file to repo +open(joinpath(LibGit2.path(repo),"file"),"w") do f + write(f, "hello repo\n") +end +LibGit2.add!(repo, "file") +LibGit2.commit(repo, "add file") +# returns ["file"] +filt = Set([LibGit2.Consts.DELTA_ADDED]) +files = LibGit2.diff_files(repo, "branch/a", "branch/b", filter=filt) +# returns [] because existing files weren't modified +filt = Set([LibGit2.Consts.DELTA_MODIFIED]) +files = LibGit2.diff_files(repo, "branch/a", "branch/b", filter=filt) +``` + Equivalent to `git diff --name-only --diff-filter= `. """ function diff_files(repo::GitRepo, branch1::AbstractString, branch2::AbstractString; From 9ed7d828ff8b8bf5c609012acae5279aab3a565a Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Wed, 5 Apr 2017 22:23:30 +0100 Subject: [PATCH 0355/1534] Add a test for aborting a rebase (#21222) * Add a test for aborting a rebase * Fix bad merge tests corrupting test_repo --- test/libgit2.jl | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/test/libgit2.jl b/test/libgit2.jl index 6a1050a23815a..e04e25d58792c 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -985,6 +985,7 @@ mktempdir() do dir LibGit2.add!(repo, "file6") LibGit2.commit(repo, "add file6") + pre_abort_head = LibGit2.head_oid(repo) # Rebase type head_ann = LibGit2.GitAnnotated(repo, "branch/a") upst_ann = LibGit2.GitAnnotated(repo, "master") @@ -996,13 +997,21 @@ mktempdir() do dir @test rbo_str == "RebaseOperation($(string(rbo.id)))\nOperation type: REBASE_OPERATION_PICK\n" rb_str = sprint(show, rb) @test rb_str == "GitRebase:\nNumber: 2\nCurrently performing operation: 1\n" + + # test rebase abort + LibGit2.abort(rb) + @test LibGit2.head_oid(repo) == pre_abort_head finally close(repo) end end @testset "merge" begin - repo = LibGit2.GitRepo(test_repo) + path = joinpath(dir, "Example.simple_merge") + repo = LibGit2.clone(cache_repo, path) + cfg = LibGit2.GitConfig(repo) + LibGit2.set!(cfg, "user.name", "AAAA") + LibGit2.set!(cfg, "user.email", "BBBB@BBBB.COM") try LibGit2.branch!(repo, "branch/merge_a") @@ -1012,8 +1021,8 @@ mktempdir() do dir end LibGit2.add!(repo, "merge_file1") LibGit2.commit(repo, "add merge_file1") - - a_head_ann = LibGit2.GitAnnotated(repo, "branch/a") + LibGit2.branch!(repo, "master") + a_head_ann = LibGit2.GitAnnotated(repo, "branch/merge_a") @test LibGit2.merge!(repo, [a_head_ann]) #merge returns true if successful finally close(repo) @@ -1040,6 +1049,7 @@ mktempdir() do dir close(repo) end end + @testset "checkout/headname" begin repo = LibGit2.GitRepo(cache_repo) try From 74334d4881974705cff1ebd8b99786534cb55b91 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sun, 26 Feb 2017 19:15:32 -0500 Subject: [PATCH 0356/1534] reorg: move code related to static compilation to precompile.c also fix compile=all for jb/subtype --- base/inference.jl | 9 +- src/Makefile | 2 +- src/ccall.cpp | 5 +- src/gf.c | 393 ++++--------------------------------------- src/init.c | 72 +------- src/jltypes.c | 43 ++++- src/julia_internal.h | 3 + src/precompile.c | 358 +++++++++++++++++++++++++++++++++++++++ 8 files changed, 442 insertions(+), 443 deletions(-) create mode 100644 src/precompile.c diff --git a/base/inference.jl b/base/inference.jl index c16dfc890c020..72482f5f316f1 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -1930,8 +1930,12 @@ function abstract_eval(e::ANY, vtypes::VarTable, sv::InferenceState) if isdefined(sv.linfo, :def) spsig = sv.linfo.def.sig if isa(spsig, UnionAll) - env = data_pointer_from_objref(sv.linfo.sparam_vals) + sizeof(Ptr{Void}) - rt = ccall(:jl_instantiate_type_in_env, Any, (Any, Any, Ptr{Any}), e.args[2], spsig, env) + if !isempty(sv.linfo.sparam_vals) + env = data_pointer_from_objref(sv.linfo.sparam_vals) + sizeof(Ptr{Void}) + rt = ccall(:jl_instantiate_type_in_env, Any, (Any, Any, Ptr{Any}), e.args[2], spsig, env) + else + rt = rewrap_unionall(e.args[2], spsig) + end end end abstract_eval(e.args[1], vtypes, sv) @@ -3290,6 +3294,7 @@ function substitute!(e::ANY, na::Int, argexprs::Vector{Any}, spsig::ANY, spvals: if head === :static_parameter return spvals[e.args[1]] elseif head === :foreigncall + @assert !isa(spsig,UnionAll) || !isempty(spvals) for i = 1:length(e.args) if i == 2 e.args[2] = ccall(:jl_instantiate_type_in_env, Any, (Any, Any, Ptr{Any}), e.args[2], spsig, spvals) diff --git a/src/Makefile b/src/Makefile index ae3db0cb4c649..9fde74da895a8 100644 --- a/src/Makefile +++ b/src/Makefile @@ -42,7 +42,7 @@ endif SRCS := \ jltypes gf typemap ast builtins module interpreter symbol \ dlload sys init task array dump toplevel jl_uv datatype \ - simplevector APInt-C runtime_intrinsics runtime_ccall \ + simplevector APInt-C runtime_intrinsics runtime_ccall precompile \ threadgroup threading stackwalk gc gc-debug gc-pages method \ jlapi signal-handling safepoint jloptions timing subtype rtutils diff --git a/src/ccall.cpp b/src/ccall.cpp index c80ad39ce9d50..0b603a9c8ee5f 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -1464,7 +1464,7 @@ static const std::string verify_ccall_sig(size_t nargs, jl_value_t *&rt, jl_valu } else { static_rt = retboxed || !jl_has_typevar_from_unionall(rt, unionall_env); - if (!static_rt && sparam_vals != NULL) { + if (!static_rt && sparam_vals != NULL && jl_svec_len(sparam_vals) > 0) { rt = jl_instantiate_type_in_env(rt, unionall_env, jl_svec_data(sparam_vals)); // `rt` is gc-rooted by the caller static_rt = true; @@ -1875,7 +1875,8 @@ jl_cgval_t function_sig_t::emit_a_ccall( // if we know the function sparams, try to fill those in now // so that the julia_to_native type checks are more likely to be doable (e.g. leaf types) at compile-time jl_value_t *jargty_in_env = jargty; - if (ctx->spvals_ptr == NULL && !toboxed && unionall_env && jl_has_typevar_from_unionall(jargty, unionall_env)) { + if (ctx->spvals_ptr == NULL && !toboxed && unionall_env && jl_has_typevar_from_unionall(jargty, unionall_env) && + jl_svec_len(ctx->linfo->sparam_vals) > 0) { jargty_in_env = jl_instantiate_type_in_env(jargty_in_env, unionall_env, jl_svec_data(ctx->linfo->sparam_vals)); if (jargty_in_env != jargty) jl_add_method_root(ctx, jargty_in_env); diff --git a/src/gf.c b/src/gf.c index 7518b47c6885d..f324d42bad191 100644 --- a/src/gf.c +++ b/src/gf.c @@ -3,10 +3,10 @@ /* Generic Functions . method table and lookup - . GF constructor, add_method + . GF constructor . dispatch . static parameter inference - . method specialization, invoking type inference + . method specialization and caching, invoking type inference */ #include #include @@ -282,8 +282,7 @@ jl_code_info_t *jl_type_infer(jl_method_instance_t **pli, size_t world, int forc return src; } - -static int jl_is_rettype_inferred(jl_method_instance_t *li) +int jl_is_rettype_inferred(jl_method_instance_t *li) { if (!li->inferred) return 0; @@ -292,11 +291,11 @@ static int jl_is_rettype_inferred(jl_method_instance_t *li) return 1; } - struct set_world { jl_method_instance_t *replaced; size_t world; }; + static int set_max_world2(jl_typemap_entry_t *entry, void *closure0) { struct set_world *closure = (struct set_world*)closure0; @@ -306,6 +305,7 @@ static int set_max_world2(jl_typemap_entry_t *entry, void *closure0) } return 1; } + static int set_min_world2(jl_typemap_entry_t *entry, void *closure0) { struct set_world *closure = (struct set_world*)closure0; @@ -315,6 +315,7 @@ static int set_min_world2(jl_typemap_entry_t *entry, void *closure0) } return 1; } + static void update_world_bound(jl_method_instance_t *replaced, jl_typemap_visitor_fptr fptr, size_t world) { struct set_world update; @@ -333,7 +334,6 @@ static void update_world_bound(jl_method_instance_t *replaced, jl_typemap_visito jl_typemap_visitor(gf->name->mt->cache, fptr, (void*)&update); } - JL_DLLEXPORT jl_method_instance_t* jl_set_method_inferred( jl_method_instance_t *li, jl_value_t *rettype, jl_value_t *inferred_const, jl_value_t *inferred, @@ -427,7 +427,6 @@ JL_DLLEXPORT jl_method_instance_t* jl_set_method_inferred( return li; } - static int get_spec_unspec_list(jl_typemap_entry_t *l, void *closure) { if (jl_is_method_instance(l->func.value) && !jl_is_rettype_inferred(l->func.linfo)) @@ -441,32 +440,32 @@ static int get_method_unspec_list(jl_typemap_entry_t *def, void *closure) return 1; } - -static void jl_reset_mt_caches(jl_module_t *m, jl_array_t *unspec) +void jl_foreach_mtable_in_module( + jl_module_t *m, + void (*visit)(jl_methtable_t *mt, void *env), + void *env) { - // removes all method caches size_t i; void **table = m->bindings.table; - for(i=1; i < m->bindings.size; i+=2) { + for (i = 1; i < m->bindings.size; i += 2) { if (table[i] != HT_NOTFOUND) { jl_binding_t *b = (jl_binding_t*)table[i]; if (b->owner == m && b->value && b->constp) { - if (jl_is_datatype(b->value)) { - jl_typename_t *tn = ((jl_datatype_t*)b->value)->name; + jl_value_t *v = jl_unwrap_unionall(b->value); + if (jl_is_datatype(v)) { + jl_typename_t *tn = ((jl_datatype_t*)v)->name; if (tn->module == m && tn->name == b->name) { jl_methtable_t *mt = tn->mt; if (mt != NULL && (jl_value_t*)mt != jl_nothing) { - if (mt->defs.unknown != jl_nothing) // make sure not to reset builtin functions - mt->cache.unknown = jl_nothing; - jl_typemap_visitor(mt->defs, get_method_unspec_list, (void*)unspec); + visit(mt, env); } } } - else if (jl_is_module(b->value)) { - jl_module_t *child = (jl_module_t*)b->value; + else if (jl_is_module(v)) { + jl_module_t *child = (jl_module_t*)v; if (child != m && child->parent == m && child->name == b->name) { // this is the original/primary binding for the submodule - jl_reset_mt_caches((jl_module_t*)b->value, unspec); + jl_foreach_mtable_in_module(child, visit, env); } } } @@ -474,6 +473,15 @@ static void jl_reset_mt_caches(jl_module_t *m, jl_array_t *unspec) } } +static void reset_mt_caches(jl_methtable_t *mt, void *env) +{ + // removes all method caches + if (mt->defs.unknown != jl_nothing) // make sure not to reset builtin functions + mt->cache.unknown = jl_nothing; + jl_typemap_visitor(mt->defs, get_method_unspec_list, env); +} + + jl_function_t *jl_typeinf_func = NULL; size_t jl_typeinf_world = 0; @@ -486,7 +494,7 @@ JL_DLLEXPORT void jl_set_typeinf_func(jl_value_t *f) // TODO: also reinfer if max_world != ~(size_t)0 jl_array_t *unspec = jl_alloc_vec_any(0); JL_GC_PUSH1(&unspec); - jl_reset_mt_caches(jl_main_module, unspec); + jl_foreach_mtable_in_module(jl_main_module, reset_mt_caches, (void*)unspec); size_t i, l; for (i = 0, l = jl_array_len(unspec); i < l; i++) { jl_method_instance_t *li = (jl_method_instance_t*)jl_array_ptr_ref(unspec, i); @@ -1170,8 +1178,7 @@ static int check_ambiguous_visitor(jl_typemap_entry_t *oldentry, struct typemap_ return 1; } -static jl_value_t *check_ambiguous_matches(union jl_typemap_t defs, - jl_typemap_entry_t *newentry) +static jl_value_t *check_ambiguous_matches(union jl_typemap_t defs, jl_typemap_entry_t *newentry) { jl_tupletype_t *type = newentry->sig; jl_tupletype_t *ttypes = (jl_tupletype_t*)jl_unwrap_unionall((jl_value_t*)type); @@ -1730,345 +1737,6 @@ jl_tupletype_t *jl_argtype_with_function(jl_function_t *f, jl_tupletype_t *types return (jl_tupletype_t*)tt; } -#if 0 // TODO restore this for jb/subtype -static int tupletype_any_bottom(jl_value_t *sig) -{ - sig = jl_unwrap_unionall(sig); - assert(jl_is_tuple_type(sig)); - jl_svec_t *types = ((jl_tupletype_t*)sig)->types; - size_t i, l = jl_svec_len(types); - for (i = 0; i < l; i++) { - if (jl_svecref(types, i) == jl_bottom_type) - return 1; - } - return 0; -} - -static int _compile_all_tvar_union(jl_tupletype_t *methsig, jl_svec_t *tvars) -{ - // f{<:Union{...}}(...) is a common pattern - // and expanding the Union may give a leaf function - jl_tvar_t **tvs; - int tvarslen; - if (jl_is_typevar(tvars)) { - tvs = (jl_tvar_t**)&tvars; - tvarslen = 1; - } - else { - tvs = (jl_tvar_t**)jl_svec_data(tvars); - tvarslen = jl_svec_len(tvars); - if (tvarslen == 0) { - if (jl_is_leaf_type((jl_value_t*)methsig)) { - // usually can create a specialized version of the function, - // if the signature is already a leaftype - if (jl_compile_hint(methsig)) { - return 1; - } - } - return 0; - } - } - - int complete = 1; - jl_value_t **env; - JL_GC_PUSHARGS(env, 2 * tvarslen); - int *idx = (int*)alloca(sizeof(int) * tvarslen); - int i; - for (i = 0; i < tvarslen; i++) { - idx[i] = 0; - env[2 * i] = (jl_value_t*)tvs[i]; - env[2 * i + 1] = jl_bottom_type; // initialize the list with Union{}, since T<:Union{} is always a valid option - } - - for (i = 0; i < tvarslen; /* incremented by inner loop */) { - jl_value_t *sig; - JL_TRY { - sig = (jl_value_t*) - jl_instantiate_type_with((jl_value_t*)methsig, env, tvarslen); - } - JL_CATCH { - goto getnext; // sigh, we found an invalid type signature. should we warn the user? - } - assert(jl_is_tuple_type(sig)); - if (sig == jl_bottom_type || tupletype_any_bottom(sig)) { - goto getnext; // signature wouldn't be callable / is invalid -- skip it - } - if (jl_is_leaf_type(sig)) { - if (jl_compile_hint((jl_tupletype_t*)sig)) { - if (!jl_has_typevars((jl_value_t*)sig)) goto getnext; // success - } - } - complete = 0; - -getnext: - for (i = 0; i < tvarslen; i++) { - jl_tvar_t *tv = tvs[i]; - if (jl_is_uniontype(tv->ub)) { - jl_uniontype_t *ub = (jl_uniontype_t*)tv->ub; - size_t l = jl_svec_len(ub->types); - size_t j = idx[i]; - if (j == l) { - env[2 * i + 1] = jl_bottom_type; - idx[i] = 0; - } - else { - jl_value_t *ty = jl_svecref(ub->types, j); - if (!jl_is_leaf_type(ty)) - ty = (jl_value_t*)jl_new_typevar(tv->name, tv->lb, ty); - env[2 * i + 1] = ty; - idx[i] = j + 1; - break; - } - } - else { - env[2 * i + 1] = (jl_value_t*)tv; - complete = 0; - } - } - } - JL_GC_POP(); - return complete; -} -#endif -#if 0 -static int _compile_all_union(jl_tupletype_t *sig, jl_svec_t *tvars) -{ - // f(::Union{...}, ...) is a common pattern - // and expanding the Union may give a leaf function - int complete = 1; - size_t count_unions = 0; - size_t i, l = jl_svec_len(sig->parameters); - jl_svec_t *p = NULL; - jl_tupletype_t *methsig = NULL; - - for (i = 0; i < l; i++) { - jl_value_t *ty = jl_svecref(sig->parameters, i); - if (jl_is_uniontype(ty)) { - jl_svec_t *utypes = ((jl_uniontype_t*)ty)->types; - size_t l = jl_svec_len(utypes); - if (l == 0) - return 1; // why does this method exist? - ++count_unions; - } - } - - //if (count_unions == 0) - // return _compile_all_tvar_union(sig, tvars); - - int *idx = (int*)alloca(sizeof(int) * count_unions); - for (i = 0; i < count_unions; i++) { - idx[i] = 0; - } - - JL_GC_PUSH2(&p, &methsig); - int idx_ctr = 0, incr = 0; - while (!incr) { - jl_svec_t *p = jl_alloc_svec_uninit(l); - for (i = 0, idx_ctr = 0, incr = 1; i < l; i++) { - jl_value_t *ty = jl_svecref(sig->parameters, i); - if (jl_is_uniontype(ty)) { - jl_svec_t *utypes = ((jl_uniontype_t*)ty)->types; - size_t l = jl_svec_len(utypes); - size_t j = idx[idx_ctr]; - jl_svecset(p, i, jl_svecref(utypes, j)); - ++j; - if (incr) { - if (j == l) { - idx[idx_ctr] = 0; - } - else { - idx[idx_ctr] = j; - incr = 0; - } - } - ++idx_ctr; - } - else { - jl_svecset(p, i, ty); - } - } - methsig = jl_apply_tuple_type(p); - //if (!_compile_all_tvar_union(methsig, tvars)) - // complete = 0; - } - - JL_GC_POP(); - return complete; -} -#endif - -static void _compile_all_deq(jl_array_t *found) -{ - int found_i, found_l = jl_array_len(found); - jl_printf(JL_STDERR, "found %d uncompiled methods for compile-all\n", (int)found_l); - jl_method_instance_t *linfo = NULL; - jl_code_info_t *src = NULL; - JL_GC_PUSH2(&linfo, &src); - for (found_i = 0; found_i < found_l; found_i++) { - if (found_i % (1 + found_l / 300) == 0 || found_i == found_l - 1) // show 300 progress steps, to show progress without overwhelming log files - jl_printf(JL_STDERR, " %d / %d\r", found_i + 1, found_l); - jl_typemap_entry_t *ml = (jl_typemap_entry_t*)jl_array_ptr_ref(found, found_i); - jl_method_t *m = ml->func.method; - jl_method_instance_t *linfo = m->unspecialized; - if (!linfo) { - linfo = jl_get_specialized(m, (jl_value_t*)ml->sig, jl_emptysvec); - m->unspecialized = linfo; - jl_gc_wb(m, linfo); - } - - //// infer this function now, if necessary - //if (linfo->jlcall_api == 2) - // continue; - //src = jl_type_infer(&linfo, jl_world_counter, 1); - //if (linfo->jlcall_api == 2) - // continue; - - // keep track of whether all possible signatures have been cached (and thus whether it can skip trying to compile the template function) - // this is necessary because many intrinsics try to call static_eval and thus are not compilable unspecialized - int complete = 0;//_compile_all_union(ml->sig, ml->tvars); - if (complete) { - if (linfo->fptr == NULL && linfo->functionObjectsDecls.functionObject == NULL) - // indicate that this method doesn't need to be compiled, because it was fully covered above - // TODO: do this some other way - linfo->fptr = (jl_fptr_t)(uintptr_t)-1; - } - else { - jl_compile_linfo(&linfo, src, jl_world_counter, &jl_default_cgparams); - assert(linfo->functionObjectsDecls.functionObject != NULL); - } - } - JL_GC_POP(); - jl_printf(JL_STDERR, "\n"); -} - -static int _compile_all_enq(jl_typemap_entry_t *ml, void *env) -{ - jl_array_t *found = (jl_array_t*)env; - // method definition -- compile template field - jl_method_t *m = ml->func.method; - if (!m->unspecialized || - (m->unspecialized->functionObjectsDecls.functionObject == NULL && - m->unspecialized->jlcall_api != 2 && - m->unspecialized->fptr == NULL)) { - // found a lambda that still needs to be compiled - jl_array_ptr_1d_push(found, (jl_value_t*)ml); - } - return 1; -} - -static void _compile_all_enq_module(jl_module_t *m, jl_array_t *found) -{ - // scan through all types reachable from 'v' and - // record all jl_method_instance_t objects and signatures in their method tables - size_t i, sz = m->bindings.size; - for(i=1; i < sz; i+=2) { - if (m->bindings.table[i] != HT_NOTFOUND) { - jl_binding_t *b = (jl_binding_t*)m->bindings.table[i]; - if (b->owner == m && b->value && b->constp) { - jl_value_t *v = b->value; - if (jl_is_datatype(v)) { - jl_typename_t *tn = ((jl_datatype_t*)v)->name; - if (tn->module == m && tn->name == b->name) { - jl_methtable_t *mt = tn->mt; - if (mt != NULL && (jl_value_t*)mt != jl_nothing) { - jl_typemap_visitor(mt->defs, _compile_all_enq, (void*)found); - } - } - } - else if (jl_is_module(v)) { - jl_module_t *child = (jl_module_t*)b->value; - if (child != m && child->parent == m && child->name == b->name) { - // this is the original/primary binding for the submodule - _compile_all_enq_module(child, found); - } - } - } - } - } -} - -static void jl_compile_all_defs(void) -{ - // this "found" array will contain - // TypeMapEntries for Methods and MethodInstances that need to be compiled - jl_array_t *m = jl_alloc_vec_any(0); - JL_GC_PUSH1(&m); - while (1) { - _compile_all_enq_module(jl_main_module, m); - size_t changes = jl_array_len(m); - if (!changes) - break; - _compile_all_deq(m); - jl_array_del_end(m, changes); - } - JL_GC_POP(); -} - -static int _precompile_enq_tfunc(jl_typemap_entry_t *l, void *closure) -{ - if (jl_is_method_instance(l->func.value) && - l->func.linfo->functionObjectsDecls.functionObject == NULL && - l->func.linfo->jlcall_api != 2) - jl_array_ptr_1d_push((jl_array_t*)closure, (jl_value_t*)l->sig); - return 1; -} - -static int _precompile_enq_spec(jl_typemap_entry_t *def, void *closure) -{ - jl_typemap_visitor(def->func.method->specializations, _precompile_enq_tfunc, closure); - return 1; -} - -static void _precompile_enq_module(jl_module_t *m, jl_array_t *unspec) -{ - // removes all method caches - size_t i; - void **table = m->bindings.table; - for (i = 1; i < m->bindings.size; i += 2) { - if (table[i] != HT_NOTFOUND) { - jl_binding_t *b = (jl_binding_t*)table[i]; - if (b->owner == m && b->value && b->constp) { - if (jl_is_datatype(b->value)) { - jl_typename_t *tn = ((jl_datatype_t*)b->value)->name; - if (tn->module == m && tn->name == b->name) { - jl_methtable_t *mt = tn->mt; - if (mt != NULL && (jl_value_t*)mt != jl_nothing) { - jl_typemap_visitor(mt->defs, _precompile_enq_spec, (void*)unspec); - } - } - } - else if (jl_is_module(b->value)) { - jl_module_t *child = (jl_module_t*)b->value; - if (child != m && child->parent == m && child->name == b->name) { - // this is the original/primary binding for the submodule - _precompile_enq_module((jl_module_t*)b->value, unspec); - } - } - } - } - } -} - -static void jl_compile_specializations(void) -{ - // this "found" array will contain function - // type signatures that were inferred but haven't been compiled - jl_array_t *m = jl_alloc_vec_any(0); - JL_GC_PUSH1(&m); - _precompile_enq_module(jl_main_module, m); - size_t i, l; - for (i = 0, l = jl_array_len(m); i < l; i++) { - jl_compile_hint((jl_tupletype_t*)jl_array_ptr_ref(m, i)); - } - JL_GC_POP(); -} - -void jl_precompile(int all) { - if (all) - jl_compile_all_defs(); - jl_compile_specializations(); -} - #ifdef JL_TRACE static int trace_en = 0; static int error_en = 1; @@ -2112,7 +1780,8 @@ jl_typemap_entry_t *call_cache[N_CALL_CACHE]; static uint8_t pick_which[N_CALL_CACHE]; #ifdef JL_GF_PROFILE size_t ncalls; -void call_cache_stats() { +void call_cache_stats() +{ int pick_which_stat[4] = {0, 0, 0, 0}; int i, count = 0; for (i = 0; i < N_CALL_CACHE; i++) { diff --git a/src/init.c b/src/init.c index 3cc3f04b22dcb..778be20efb38b 100644 --- a/src/init.c +++ b/src/init.c @@ -177,7 +177,7 @@ static void jl_uv_exitcleanup_walk(uv_handle_t *handle, void *arg) void jl_write_coverage_data(void); void jl_write_malloc_log(void); -static void julia_save(void); +void jl_write_compiler_output(void); static struct uv_shutdown_queue_item *next_shutdown_queue_item(struct uv_shutdown_queue_item *item) { @@ -193,7 +193,7 @@ void jl_uv_call_close_callback(jl_value_t *val); JL_DLLEXPORT void jl_atexit_hook(int exitcode) { jl_ptls_t ptls = jl_get_ptls_states(); - if (exitcode == 0) julia_save(); + if (exitcode == 0) jl_write_compiler_output(); jl_print_gc_stats(JL_STDERR); if (jl_options.code_coverage) jl_write_coverage_data(); @@ -710,74 +710,6 @@ void _julia_init(JL_IMAGE_SEARCH rel) jl_install_sigint_handler(); } -extern int asprintf(char **str, const char *fmt, ...); - -JL_DLLEXPORT int jl_generating_output(void) -{ - return jl_options.outputo || jl_options.outputbc || jl_options.outputji; -} - -void jl_precompile(int all); - -static void julia_save(void) -{ - if (!jl_generating_output()) - return; - - if (!jl_options.incremental) - jl_precompile(jl_options.compile_enabled == JL_OPTIONS_COMPILE_ALL); - - if (!jl_module_init_order) { - jl_printf(JL_STDERR, "WARNING: --output requested, but no modules defined during run\n"); - return; - } - - jl_array_t *worklist = jl_module_init_order; - JL_GC_PUSH1(&worklist); - jl_module_init_order = jl_alloc_vec_any(0); - int i, l = jl_array_len(worklist); - for (i = 0; i < l; i++) { - jl_value_t *m = jl_arrayref(worklist, i); - if (jl_get_global((jl_module_t*)m, jl_symbol("__init__"))) { - jl_array_ptr_1d_push(jl_module_init_order, m); - } - } - - if (jl_options.incremental) { - if (jl_options.outputji) - if (jl_save_incremental(jl_options.outputji, worklist)) - jl_exit(1); - if (jl_options.outputbc) - jl_printf(JL_STDERR, "WARNING: incremental output to a .bc file is not implemented\n"); - if (jl_options.outputo) - jl_printf(JL_STDERR, "WARNING: incremental output to a .o file is not implemented\n"); - } - else { - ios_t *s = NULL; - if (jl_options.outputo || jl_options.outputbc) - s = jl_create_system_image(); - - if (jl_options.outputji) { - if (s == NULL) { - jl_save_system_image(jl_options.outputji); - } - else { - ios_t f; - if (ios_file(&f, jl_options.outputji, 1, 1, 1, 1) == NULL) - jl_errorf("cannot open system image file \"%s\" for writing", jl_options.outputji); - ios_write(&f, (const char*)s->buf, (size_t)s->size); - ios_close(&f); - } - } - - if (jl_options.outputo || jl_options.outputbc) - jl_dump_native(jl_options.outputbc, - jl_options.outputo, - (const char*)s->buf, (size_t)s->size); - } - JL_GC_POP(); -} - static jl_value_t *core(const char *name) { return jl_get_global(jl_core_module, jl_symbol(name)); diff --git a/src/jltypes.c b/src/jltypes.c index 032d992b06298..089a3407e0d4b 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -307,6 +307,35 @@ static int count_union_components(jl_value_t **types, size_t n) return c; } +int jl_count_union_components(jl_value_t *v) +{ + if (!jl_is_uniontype(v)) return 1; + jl_uniontype_t *u = (jl_uniontype_t*)v; + return jl_count_union_components(u->a) + jl_count_union_components(u->b); +} + +// Return the `*pi`th element of a nested type union, according to a +// standard traversal order. Anything that is not itself a `Union` is +// considered an "element". `*pi` is destroyed in the process. +static jl_value_t *nth_union_component(jl_value_t *v, int *pi) +{ + if (!jl_is_uniontype(v)) { + if (*pi == 0) + return v; + (*pi)--; + return NULL; + } + jl_uniontype_t *u = (jl_uniontype_t*)v; + jl_value_t *a = nth_union_component(u->a, pi); + if (a) return a; + return nth_union_component(u->b, pi); +} + +jl_value_t *jl_nth_union_component(jl_value_t *v, int i) +{ + return nth_union_component(v, &i); +} + static void flatten_type_union(jl_value_t **types, size_t n, jl_value_t **out, size_t *idx) { size_t i; @@ -1363,12 +1392,14 @@ static jl_value_t *_jl_instantiate_type_in_env(jl_value_t *ty, jl_unionall_t *en JL_DLLEXPORT jl_value_t *jl_instantiate_type_in_env(jl_value_t *ty, jl_unionall_t *env, jl_value_t **vals) { - jl_value_t *typ; - JL_TRY { - typ = _jl_instantiate_type_in_env(ty, env, vals, NULL); - } - JL_CATCH { - typ = jl_bottom_type; + jl_value_t *typ = ty; + if (jl_is_unionall(env)) { + JL_TRY { + typ = _jl_instantiate_type_in_env(ty, env, vals, NULL); + } + JL_CATCH { + typ = jl_bottom_type; + } } return typ; } diff --git a/src/julia_internal.h b/src/julia_internal.h index b5d5139bcced4..8eb3842a8a9be 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -433,6 +433,8 @@ jl_value_t *jl_instantiate_type_with(jl_value_t *t, jl_value_t **env, size_t n); JL_DLLEXPORT jl_value_t *jl_instantiate_type_in_env(jl_value_t *ty, jl_unionall_t *env, jl_value_t **vals); jl_value_t *jl_substitute_var(jl_value_t *t, jl_tvar_t *var, jl_value_t *val); jl_svec_t *jl_outer_unionall_vars(jl_value_t *u); +int jl_count_union_components(jl_value_t *v); +jl_value_t *jl_nth_union_component(jl_value_t *v, int i); jl_datatype_t *jl_new_uninitialized_datatype(void); jl_datatype_t *jl_new_abstracttype(jl_value_t *name, jl_datatype_t *super, jl_svec_t *parameters); @@ -581,6 +583,7 @@ JL_DLLEXPORT jl_methtable_t *jl_new_method_table(jl_sym_t *name, jl_module_t *mo jl_method_instance_t *jl_get_specialization1(jl_tupletype_t *types, size_t world); JL_DLLEXPORT int jl_has_call_ambiguities(jl_tupletype_t *types, jl_method_t *m); jl_method_instance_t *jl_get_specialized(jl_method_t *m, jl_value_t *types, jl_svec_t *sp); +int jl_is_rettype_inferred(jl_method_instance_t *li); JL_DLLEXPORT jl_value_t *jl_methtable_lookup(jl_methtable_t *mt, jl_tupletype_t *type, size_t world); JL_DLLEXPORT jl_method_instance_t *jl_specializations_get_linfo(jl_method_t *m, jl_value_t *type, jl_svec_t *sparams, size_t world); JL_DLLEXPORT void jl_method_instance_add_backedge(jl_method_instance_t *callee, jl_method_instance_t *caller); diff --git a/src/precompile.c b/src/precompile.c new file mode 100644 index 0000000000000..8994941d15514 --- /dev/null +++ b/src/precompile.c @@ -0,0 +1,358 @@ +// This file is a part of Julia. License is MIT: http://julialang.org/license + +/* + precompile.c + Generating compiler output artifacts (object files, etc.) +*/ + +#include +#include + +#include "julia.h" +#include "julia_internal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +JL_DLLEXPORT int jl_generating_output(void) +{ + return jl_options.outputo || jl_options.outputbc || jl_options.outputji; +} + +void jl_precompile(int all); + +void jl_write_compiler_output(void) +{ + if (!jl_generating_output()) + return; + + if (!jl_options.incremental) + jl_precompile(jl_options.compile_enabled == JL_OPTIONS_COMPILE_ALL); + + if (!jl_module_init_order) { + jl_printf(JL_STDERR, "WARNING: --output requested, but no modules defined during run\n"); + return; + } + + jl_array_t *worklist = jl_module_init_order; + JL_GC_PUSH1(&worklist); + jl_module_init_order = jl_alloc_vec_any(0); + int i, l = jl_array_len(worklist); + for (i = 0; i < l; i++) { + jl_value_t *m = jl_arrayref(worklist, i); + if (jl_get_global((jl_module_t*)m, jl_symbol("__init__"))) { + jl_array_ptr_1d_push(jl_module_init_order, m); + } + } + + if (jl_options.incremental) { + if (jl_options.outputji) + if (jl_save_incremental(jl_options.outputji, worklist)) + jl_exit(1); + if (jl_options.outputbc) + jl_printf(JL_STDERR, "WARNING: incremental output to a .bc file is not implemented\n"); + if (jl_options.outputo) + jl_printf(JL_STDERR, "WARNING: incremental output to a .o file is not implemented\n"); + } + else { + ios_t *s = NULL; + if (jl_options.outputo || jl_options.outputbc) + s = jl_create_system_image(); + + if (jl_options.outputji) { + if (s == NULL) { + jl_save_system_image(jl_options.outputji); + } + else { + ios_t f; + if (ios_file(&f, jl_options.outputji, 1, 1, 1, 1) == NULL) + jl_errorf("cannot open system image file \"%s\" for writing", jl_options.outputji); + ios_write(&f, (const char*)s->buf, (size_t)s->size); + ios_close(&f); + } + } + + if (jl_options.outputo || jl_options.outputbc) + jl_dump_native(jl_options.outputbc, + jl_options.outputo, + (const char*)s->buf, (size_t)s->size); + } + JL_GC_POP(); +} + +static int tupletype_any_bottom(jl_value_t *sig) +{ + sig = jl_unwrap_unionall(sig); + assert(jl_is_tuple_type(sig)); + jl_svec_t *types = ((jl_tupletype_t*)sig)->types; + size_t i, l = jl_svec_len(types); + for (i = 0; i < l; i++) { + if (jl_svecref(types, i) == jl_bottom_type) + return 1; + } + return 0; +} + +// f{<:Union{...}}(...) is a common pattern +// and expanding the Union may give a leaf function +static void _compile_all_tvar_union(jl_value_t *methsig) +{ + if (!jl_is_unionall(methsig) && jl_is_leaf_type(methsig)) { + // usually can create a specialized version of the function, + // if the signature is already a leaftype + if (jl_compile_hint((jl_tupletype_t*)methsig)) + return; + } + + int tvarslen = jl_subtype_env_size(methsig); + jl_value_t *sigbody = methsig; + jl_value_t **env; + JL_GC_PUSHARGS(env, 2 * tvarslen); + int *idx = (int*)alloca(sizeof(int) * tvarslen); + int i; + for (i = 0; i < tvarslen; i++) { + assert(jl_is_unionall(sigbody)); + idx[i] = 0; + env[2 * i] = (jl_value_t*)((jl_unionall_t*)sigbody)->var; + env[2 * i + 1] = jl_bottom_type; // initialize the list with Union{}, since T<:Union{} is always a valid option + sigbody = ((jl_unionall_t*)sigbody)->body; + } + + for (i = 0; i < tvarslen; /* incremented by inner loop */) { + jl_value_t *sig; + JL_TRY { + // TODO: wrap in UnionAll for each tvar in env[2*i + 1] ? + // currently doesn't matter much, since jl_compile_hint doesn't work on abstract types + sig = (jl_value_t*)jl_instantiate_type_with(sigbody, env, tvarslen); + } + JL_CATCH { + goto getnext; // sigh, we found an invalid type signature. should we warn the user? + } + assert(jl_is_tuple_type(sig)); + if (sig == jl_bottom_type || tupletype_any_bottom(sig)) + goto getnext; // signature wouldn't be callable / is invalid -- skip it + if (jl_is_leaf_type(sig)) { + if (jl_compile_hint((jl_tupletype_t*)sig)) + goto getnext; // success + } + + getnext: + for (i = 0; i < tvarslen; i++) { + jl_tvar_t *tv = (jl_tvar_t*)env[2 * i]; + if (jl_is_uniontype(tv->ub)) { + size_t l = jl_count_union_components(tv->ub); + size_t j = idx[i]; + if (j == l) { + env[2 * i + 1] = jl_bottom_type; + idx[i] = 0; + } + else { + jl_value_t *ty = jl_nth_union_component(tv->ub, j); + if (!jl_is_leaf_type(ty)) + ty = (jl_value_t*)jl_new_typevar(tv->name, tv->lb, ty); + env[2 * i + 1] = ty; + idx[i] = j + 1; + break; + } + } + else { + env[2 * i + 1] = (jl_value_t*)tv; + } + } + } + JL_GC_POP(); +} + +// f(::Union{...}, ...) is a common pattern +// and expanding the Union may give a leaf function +static void _compile_all_union(jl_value_t *sig) +{ + jl_tupletype_t *sigbody = (jl_tupletype_t*)jl_unwrap_unionall(sig); + size_t count_unions = 0; + size_t i, l = jl_svec_len(sigbody->parameters); + jl_svec_t *p = NULL; + jl_value_t *methsig = NULL; + + for (i = 0; i < l; i++) { + jl_value_t *ty = jl_svecref(sigbody->parameters, i); + if (jl_is_uniontype(ty)) + ++count_unions; + else if (ty == jl_bottom_type) + return; // why does this method exist? + } + + if (count_unions == 0) { + _compile_all_tvar_union(sig); + return; + } + + int *idx = (int*)alloca(sizeof(int) * count_unions); + for (i = 0; i < count_unions; i++) { + idx[i] = 0; + } + + JL_GC_PUSH2(&p, &methsig); + int idx_ctr = 0, incr = 0; + while (!incr) { + jl_svec_t *p = jl_alloc_svec_uninit(l); + for (i = 0, idx_ctr = 0, incr = 1; i < l; i++) { + jl_value_t *ty = jl_svecref(sigbody->parameters, i); + if (jl_is_uniontype(ty)) { + size_t l = jl_count_union_components(ty); + size_t j = idx[idx_ctr]; + jl_svecset(p, i, jl_nth_union_component(ty, j)); + ++j; + if (incr) { + if (j == l) { + idx[idx_ctr] = 0; + } + else { + idx[idx_ctr] = j; + incr = 0; + } + } + ++idx_ctr; + } + else { + jl_svecset(p, i, ty); + } + } + methsig = (jl_value_t*)jl_apply_tuple_type(p); + methsig = jl_rewrap_unionall(methsig, sig); + _compile_all_tvar_union(methsig); + } + + JL_GC_POP(); +} + +static void _compile_all_deq(jl_array_t *found) +{ + int found_i, found_l = jl_array_len(found); + jl_printf(JL_STDERR, "found %d uncompiled methods for compile-all\n", (int)found_l); + jl_method_instance_t *linfo = NULL; + jl_value_t *src = NULL; + JL_GC_PUSH2(&linfo, &src); + for (found_i = 0; found_i < found_l; found_i++) { + if (found_i % (1 + found_l / 300) == 0 || found_i == found_l - 1) // show 300 progress steps, to show progress without overwhelming log files + jl_printf(JL_STDERR, " %d / %d\r", found_i + 1, found_l); + jl_typemap_entry_t *ml = (jl_typemap_entry_t*)jl_array_ptr_ref(found, found_i); + jl_method_t *m = ml->func.method; + if (m->isstaged) // TODO: generic implementations of generated functions + continue; + linfo = m->unspecialized; + if (!linfo) { + linfo = jl_get_specialized(m, (jl_value_t*)m->sig, jl_emptysvec); + m->unspecialized = linfo; + jl_gc_wb(m, linfo); + } + + if (linfo->jlcall_api == 2) + continue; + src = m->source; + // TODO: the `unspecialized` field is not yet world-aware, so we can't store + // an inference result there. + //src = jl_type_infer(&linfo, jl_world_counter, 1); + //m->unspecialized = linfo; + //jl_gc_wb(m, linfo); + //if (linfo->jlcall_api == 2) + // continue; + + // first try to create leaf signatures from the signature declaration and compile those + _compile_all_union((jl_value_t*)ml->sig); + // then also compile the generic fallback + jl_compile_linfo(&linfo, (jl_code_info_t*)src, jl_world_counter, &jl_default_cgparams); + assert(linfo->functionObjectsDecls.functionObject != NULL); + } + JL_GC_POP(); + jl_printf(JL_STDERR, "\n"); +} + +static int compile_all_enq__(jl_typemap_entry_t *ml, void *env) +{ + jl_array_t *found = (jl_array_t*)env; + // method definition -- compile template field + jl_method_t *m = ml->func.method; + if (!m->isstaged && + (!m->unspecialized || + (m->unspecialized->functionObjectsDecls.functionObject == NULL && + m->unspecialized->jlcall_api != 2 && + m->unspecialized->fptr == NULL))) { + // found a lambda that still needs to be compiled + jl_array_ptr_1d_push(found, (jl_value_t*)ml); + } + return 1; +} + + +static void compile_all_enq_(jl_methtable_t *mt, void *env) +{ + jl_typemap_visitor(mt->defs, compile_all_enq__, env); +} + +void jl_foreach_mtable_in_module( + jl_module_t *m, + void (*visit)(jl_methtable_t *mt, void *env), + void *env); + +static void jl_compile_all_defs(void) +{ + // this "found" array will contain + // TypeMapEntries for Methods and MethodInstances that need to be compiled + jl_array_t *m = jl_alloc_vec_any(0); + JL_GC_PUSH1(&m); + while (1) { + jl_foreach_mtable_in_module(jl_main_module, compile_all_enq_, m); + size_t changes = jl_array_len(m); + if (!changes) + break; + _compile_all_deq(m); + jl_array_del_end(m, changes); + } + JL_GC_POP(); +} + +static int precompile_enq_specialization_(jl_typemap_entry_t *l, void *closure) +{ + if (jl_is_method_instance(l->func.value) && + l->func.linfo->functionObjectsDecls.functionObject == NULL && + l->func.linfo->jlcall_api != 2) + jl_array_ptr_1d_push((jl_array_t*)closure, (jl_value_t*)l->sig); + return 1; +} + +static int precompile_enq_all_specializations__(jl_typemap_entry_t *def, void *closure) +{ + jl_typemap_visitor(def->func.method->specializations, precompile_enq_specialization_, closure); + return 1; +} + +static void precompile_enq_all_specializations_(jl_methtable_t *mt, void *env) +{ + jl_typemap_visitor(mt->defs, precompile_enq_all_specializations__, env); +} + +static void jl_compile_specializations(void) +{ + // this "found" array will contain function + // type signatures that were inferred but haven't been compiled + jl_array_t *m = jl_alloc_vec_any(0); + JL_GC_PUSH1(&m); + jl_foreach_mtable_in_module(jl_main_module, precompile_enq_all_specializations_, m); + size_t i, l; + for (i = 0, l = jl_array_len(m); i < l; i++) { + jl_compile_hint((jl_tupletype_t*)jl_array_ptr_ref(m, i)); + } + JL_GC_POP(); +} + +void jl_precompile(int all) +{ + if (all) + jl_compile_all_defs(); + jl_compile_specializations(); +} + +#ifdef __cplusplus +} +#endif From beea404c3b512367462ec18f7aa3e939b9ca3422 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 5 Apr 2017 17:34:11 -0400 Subject: [PATCH 0357/1534] improve backedge debugging to list causes --- src/gf.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/gf.c b/src/gf.c index f324d42bad191..de023ba2163ea 100644 --- a/src/gf.c +++ b/src/gf.c @@ -1250,11 +1250,10 @@ static void invalidate_method_instance(jl_method_instance_t *replaced, size_t ma assert(replaced->min_world <= max_world && "attempting to set invalid world constraints"); if (JL_DEBUG_METHOD_INVALIDATION) { int d0 = depth; - char space = ' ', nl = '\n'; while (d0-- > 0) - jl_uv_puts(JL_STDOUT, &space, 1); + jl_uv_puts(JL_STDOUT, " ", 1); jl_static_show(JL_STDOUT, (jl_value_t*)replaced); - jl_uv_puts(JL_STDOUT, &nl, 1); + jl_uv_puts(JL_STDOUT, "\n", 1); } replaced->max_world = max_world; update_world_bound(replaced, set_max_world2, max_world); @@ -1274,6 +1273,7 @@ static void invalidate_method_instance(jl_method_instance_t *replaced, size_t ma struct invalidate_conflicting_env { struct typemap_intersection_env match; size_t max_world; + int invalidated; }; static int invalidate_backedges(jl_typemap_entry_t *oldentry, struct typemap_intersection_env *closure0) { @@ -1302,6 +1302,7 @@ static int invalidate_backedges(jl_typemap_entry_t *oldentry, struct typemap_int invalidate_method_instance(replaced[i], closure->max_world, 0); } } + closure->invalidated = 1; def.replaced->backedges = NULL; JL_UNLOCK_NOGC(&def.replaced->def->writelock); } @@ -1368,6 +1369,7 @@ JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method jl_value_t *type = method->sig; jl_value_t *oldvalue = NULL; struct invalidate_conflicting_env env; + env.invalidated = 0; env.max_world = method->min_world - 1; JL_GC_PUSH1(&oldvalue); JL_LOCK(&mt->writelock); @@ -1389,6 +1391,7 @@ JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method if (jl_type_intersection(backedgetyp, (jl_value_t*)type) != (jl_value_t*)jl_bottom_type) { jl_method_instance_t *backedge = (jl_method_instance_t*)backedges[i]; invalidate_method_instance(backedge, env.max_world, 0); + env.invalidated = 1; } else { backedges[ins++] = backedges[i - 1]; @@ -1428,6 +1431,13 @@ JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method } } } + if (env.invalidated && JL_DEBUG_METHOD_INVALIDATION) { + jl_uv_puts(JL_STDOUT, ">> ", 3); + jl_static_show(JL_STDOUT, (jl_value_t*)method); + jl_uv_puts(JL_STDOUT, " ", 1); + jl_static_show(JL_STDOUT, (jl_value_t*)type); + jl_uv_puts(JL_STDOUT, "\n", 1); + } update_max_args(mt, type); JL_UNLOCK(&mt->writelock); JL_GC_POP(); From 5720299a3d67b12e78bba59198b2535de34ff0cd Mon Sep 17 00:00:00 2001 From: kshyatt Date: Sat, 1 Apr 2017 12:30:03 -0700 Subject: [PATCH 0358/1534] Add a silly test for RevWalk count --- test/libgit2.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/libgit2.jl b/test/libgit2.jl index e04e25d58792c..ca82b0a1f87f6 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -831,6 +831,9 @@ mktempdir() do dir for i in eachindex(oids) @test cache_oids[i] == test_oids[i] end + LibGit2.with(LibGit2.GitRevWalker(repo)) do walker + @test count((oid,repo)->(oid == commit_oid1), walker, oid=commit_oid1, by=LibGit2.Consts.SORT_TIME) == 1 + end finally close(repo) close(cache) From 9f52fe0778ab4b714e4acd08a7ac312ea72d292f Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 6 Apr 2017 12:47:29 -0400 Subject: [PATCH 0359/1534] enable some type intersection tests that now work --- test/subtype.jl | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/test/subtype.jl b/test/subtype.jl index 93962697141c3..6e0859f3eb46d 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -827,14 +827,13 @@ function test_intersection() Tuple{Array{Ref{T}, 1}, Array{Pair{M, T}, 1}, SS} where T where M where SS, Union{}) - # TODO: these test cases currently hang - @test_skip typeintersect(Tuple{Array{Ref{T}, 1}, Array{Pair{M, V}, 1}, Int} where V where T where M, - Tuple{Array{Ref{T}, 1}, Array{Pair{M, T}, 1}, Any} where T where M) == - Tuple{Array{Ref{T}, 1}, Array{Pair{M, T}, 1}, Int} - - @test_skip typeintersect(Tuple{Int, Ref{Pair{K,V}}} where V where K, - Tuple{Any, Ref{Pair{T,T}} where T }) == - Tuple{Int, Ref{Pair{T,T}} where T } + @testintersect(Tuple{Array{Ref{T}, 1}, Array{Pair{M, V}, 1}, Int} where V where T where M, + Tuple{Array{Ref{T}, 1}, Array{Pair{M, T}, 1}, Any} where T where M, + Tuple{Array{Ref{T}, 1}, Array{Pair{M, T}, 1}, Int} where T where M) + + @testintersect(Tuple{Int, Ref{Pair{K,V}}} where V where K, + Tuple{Any, Ref{Pair{T,T}} where T }, + Tuple{Int, Ref{Pair{T,T}} where T }) @test_broken isequal_type(_type_intersect(Tuple{T,T} where T, Union{Tuple{S,Array{Int64,1}},Tuple{S,Array{S,1}}} where S), From 9f0a952358750a0245c63f8068eaddfb361f3e56 Mon Sep 17 00:00:00 2001 From: Pablo Zubieta Date: Tue, 21 Feb 2017 12:03:33 -0600 Subject: [PATCH 0360/1534] Couple of tuple speed-ups --- base/range.jl | 5 +++++ base/tuple.jl | 57 ++++++++++++++++++++++++++++++++------------------- 2 files changed, 41 insertions(+), 21 deletions(-) diff --git a/base/range.jl b/base/range.jl index 420a57e60a55a..6d2bed9b6c743 100644 --- a/base/range.jl +++ b/base/range.jl @@ -151,6 +151,11 @@ unitrange_last{T}(start::T, stop::T) = ifelse(stop >= start, convert(T,start+floor(stop-start)), convert(T,start-oneunit(stop-start))) +if isdefined(Main, :Base) + getindex(t::Tuple, r::AbstractUnitRange{<:Real}) = + (o = first(r) - 1; ntuple(n -> t[o + n], length(r))) +end + """ Base.OneTo(n) diff --git a/base/tuple.jl b/base/tuple.jl index 3b45f812fc0b6..4195f2e85a48e 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -20,7 +20,7 @@ endof(t::Tuple) = length(t) size(t::Tuple, d) = d==1 ? length(t) : throw(ArgumentError("invalid tuple dimension $d")) getindex(t::Tuple, i::Int) = getfield(t, i) getindex(t::Tuple, i::Real) = getfield(t, convert(Int, i)) -getindex(t::Tuple, r::AbstractArray{<:Any,1}) = tuple([t[ri] for ri in r]...) +getindex(t::Tuple, r::AbstractArray{<:Any,1}) = ([t[ri] for ri in r]...) getindex(t::Tuple, b::AbstractArray{Bool,1}) = length(b) == length(t) ? getindex(t,find(b)) : throw(BoundsError(t, b)) # returns new tuple; N.B.: becomes no-op if i is out-of-bounds @@ -104,17 +104,23 @@ julia> ntuple(i -> 2*i, 4) (2, 4, 6, 8) ``` """ -ntuple(f::Function, n::Integer) = - n <= 0 ? () : - n == 1 ? (f(1),) : - n == 2 ? (f(1),f(2),) : - n == 3 ? (f(1),f(2),f(3),) : - n == 4 ? (f(1),f(2),f(3),f(4),) : - n == 5 ? (f(1),f(2),f(3),f(4),f(5),) : - n < 16 ? (ntuple(f,n-5)..., f(n-4), f(n-3), f(n-2), f(n-1), f(n)) : - _ntuple(f, n) - -_ntuple(f::Function, n::Integer) = (@_noinline_meta; ((f(i) for i = 1:n)...)) +function ntuple{F}(f::F, n::Integer) + t = n <= 0 ? () : + n == 1 ? (f(1),) : + n == 2 ? (f(1), f(2)) : + n == 3 ? (f(1), f(2), f(3)) : + n == 4 ? (f(1), f(2), f(3), f(4)) : + n == 5 ? (f(1), f(2), f(3), f(4), f(5)) : + n == 6 ? (f(1), f(2), f(3), f(4), f(5), f(6)) : + n == 7 ? (f(1), f(2), f(3), f(4), f(5), f(6), f(7)) : + n == 8 ? (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8)) : + n == 9 ? (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9)) : + n == 10 ? (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10)) : + _ntuple(f, n) + return t +end + +_ntuple(f, n) = (@_noinline_meta; ([f(i) for i = 1:n]...)) # inferrable ntuple function ntuple{F,N}(f::F, ::Type{Val{N}}) @@ -142,11 +148,11 @@ All16{T,N} = Tuple{T,T,T,T,T,T,T,T, T,T,T,T,T,T,T,T,Vararg{T,N}} function map(f, t::Any16) n = length(t) - A = Array{Any}(n) + A = Array{Any,1}(n) for i=1:n A[i] = f(t[i]) end - (A...,) + (A...) end # 2 argument function map(f, t::Tuple{}, s::Tuple{}) = () @@ -158,19 +164,28 @@ function map(f, t::Tuple, s::Tuple) end function map(f, t::Any16, s::Any16) n = length(t) - A = Array{Any}(n) + A = Array{Any,1}(n) for i = 1:n A[i] = f(t[i], s[i]) end - (A...,) + (A...) end # n argument function -heads() = () -heads(t::Tuple, ts::Tuple...) = (t[1], heads(ts...)...) -tails() = () -tails(t::Tuple, ts::Tuple...) = (tail(t), tails(ts...)...) +heads(ts::Tuple...) = map(t -> t[1], ts) +tails(ts::Tuple...) = map(tail, ts) map(f, ::Tuple{}, ts::Tuple...) = () -map(f, t1::Tuple, t2::Tuple, ts::Tuple...) = (f(heads(t1, t2, ts...)...), map(f, tails(t1, t2, ts...)...)...) +function map(f, t1::Tuple, t2::Tuple, ts::Tuple...) + @_inline_meta + (f(heads(t1, t2, ts...)...), map(f, tails(t1, t2, ts...)...)...) +end +function map(f, t1::Any16, t2::Any16, ts::Any16...) + n = length(t1) + A = Array{Any,1}(n) + for i = 1:n + A[i] = f(t1[i], t2[i], map(t -> t[i], ts)...) + end + (A...) +end # type-stable padding From 1d1ff14c19e9bc6e1ada947bc6cde83581551e55 Mon Sep 17 00:00:00 2001 From: Pablo Zubieta Date: Sat, 18 Mar 2017 09:42:00 -0600 Subject: [PATCH 0361/1534] Homogenize behaviour of map over tuples when one is empty --- base/tuple.jl | 2 +- test/tuple.jl | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/base/tuple.jl b/base/tuple.jl index 4195f2e85a48e..420a28672096a 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -173,7 +173,7 @@ end # n argument function heads(ts::Tuple...) = map(t -> t[1], ts) tails(ts::Tuple...) = map(tail, ts) -map(f, ::Tuple{}, ts::Tuple...) = () +map(f, ::Tuple{}...) = () function map(f, t1::Tuple, t2::Tuple, ts::Tuple...) @_inline_meta (f(heads(t1, t2, ts...)...), map(f, tails(t1, t2, ts...)...)...) diff --git a/test/tuple.jl b/test/tuple.jl index 70f08a30f667a..7756797e9af4d 100644 --- a/test/tuple.jl +++ b/test/tuple.jl @@ -96,14 +96,17 @@ begin @test map(foo, (1,2), (1,2)) === (2,4) @test map(foo, (1,2,3,4), (1,2,3,4)) === (2,4,6,8) @test map(foo, longtuple, longtuple) === ntuple(i->2i,20) + @test_throws BoundsError map(foo, (), (1,)) + @test_throws BoundsError map(foo, (1,), ()) # n arguments @test map(foo, (), (), ()) === () - @test map(foo, (), (1,2,3), (1,2,3)) === () @test map(foo, (1,), (1,), (1,)) === (3,) @test map(foo, (1,2), (1,2), (1,2)) === (3,6) @test map(foo, (1,2,3,4), (1,2,3,4), (1,2,3,4)) === (3,6,9,12) @test map(foo, longtuple, longtuple, longtuple) === ntuple(i->3i,20) + @test_throws BoundsError map(foo, (), (1,), (1,)) + @test_throws BoundsError map(foo, (1,), (1,), ()) end ## comparison ## From 5bcfd2c64dff222007e159bdedbf0b44c7d1453e Mon Sep 17 00:00:00 2001 From: rfourquet Date: Fri, 7 Apr 2017 01:14:11 +0700 Subject: [PATCH 0362/1534] make MersenneTwister() randomly seeded (#16984) * make MersenneTwister() randomly seeded * deprecate the zero-arg MersenneTwister() constructor --- NEWS.md | 3 +++ base/deprecated.jl | 3 +++ base/random.jl | 6 +++--- test/random.jl | 11 +++++------ test/sparse/sparsevector.jl | 2 +- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/NEWS.md b/NEWS.md index da5ccd9ff7169..9f9811b9188f9 100644 --- a/NEWS.md +++ b/NEWS.md @@ -395,6 +395,9 @@ Deprecated or removed * `convert` methods from `Diagonal` and `Bidiagonal` to subtypes of `AbstractTriangular` have been deprecated ([#17723]). + * The zero-argument constructor `MersenneTwister()` has been + deprecated in favor of the explicit `MersenneTwister(0)` ([#16984]). + [#265]: https://github.com/JuliaLang/julia/issues/265 [#4615]: https://github.com/JuliaLang/julia/issues/4615 diff --git a/base/deprecated.jl b/base/deprecated.jl index dc95156ebffb8..81bf76e5402ec 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1307,6 +1307,9 @@ end end end +# PR #16984 +@deprecate MersenneTwister() MersenneTwister(0) + # #19635 for fname in (:ones, :zeros) @eval @deprecate ($fname)(T::Type, arr) ($fname)(T, size(arr)) diff --git a/base/random.jl b/base/random.jl index 074cd1cbc7bc3..38aab289b578c 100644 --- a/base/random.jl +++ b/base/random.jl @@ -89,12 +89,12 @@ MersenneTwister(seed::Vector{UInt32}, state::DSFMT_state) = MersenneTwister(seed, state, zeros(Float64, MTCacheLength), MTCacheLength) """ - MersenneTwister(seed=0) + MersenneTwister(seed) Create a `MersenneTwister` RNG object. Different RNG objects can have their own seeds, which may be useful for generating different streams of random numbers. """ -MersenneTwister(seed=0) = srand(MersenneTwister(Vector{UInt32}(), DSFMT_state()), seed) +MersenneTwister(seed) = srand(MersenneTwister(Vector{UInt32}(), DSFMT_state()), seed) function copy!(dst::MersenneTwister, src::MersenneTwister) copy!(resize!(dst.seed, length(src.seed)), src.seed) @@ -256,7 +256,7 @@ end ## Global RNG -const GLOBAL_RNG = MersenneTwister() +const GLOBAL_RNG = MersenneTwister(0) globalRNG() = GLOBAL_RNG # rand: a non-specified RNG defaults to GLOBAL_RNG diff --git a/test/random.jl b/test/random.jl index 90a126a05d996..6ccccd49860ba 100644 --- a/test/random.jl +++ b/test/random.jl @@ -15,7 +15,6 @@ srand(0); rand(); x = rand(384) @test length(randn(4, 5)) == 20 @test length(bitrand(4, 5)) == 20 -@test rand(MersenneTwister()) == 0.8236475079774124 @test rand(MersenneTwister(0)) == 0.8236475079774124 @test rand(MersenneTwister(42)) == 0.5331830160438613 # Try a seed larger than 2^32 @@ -38,7 +37,7 @@ A = zeros(UInt128, 2, 2) @test_throws BoundsError rand!(MersenneTwister(0), A, 5) # rand from AbstractArray -let mt = MersenneTwister() +let mt = MersenneTwister(0) srand(mt) @test rand(mt, 0:3:1000) in 0:3:1000 @test issubset(rand!(mt, Array{Int}(100), 0:3:1000), 0:3:1000) @@ -227,7 +226,7 @@ u4 = uuid4() @test u4 == UUID(string(u4)) == UUID(GenericString(string(u4))) @test u1 == UUID(UInt128(u1)) @test u4 == UUID(UInt128(u4)) -@test uuid4(MersenneTwister()) == uuid4(MersenneTwister()) +@test uuid4(MersenneTwister(0)) == uuid4(MersenneTwister(0)) @test_throws ArgumentError UUID("550e8400e29b-41d4-a716-446655440000") @test_throws ArgumentError UUID("550e8400e29b-41d4-a716-44665544000098") @test_throws ArgumentError UUID("z50e8400-e29b-41d4-a716-446655440000") @@ -278,7 +277,7 @@ let mt = MersenneTwister(0) end # Issue #9037 -let mt = MersenneTwister() +let mt = MersenneTwister(0) a = Array{Float64}(0) resize!(a, 1000) # could be 8-byte aligned b = Array{Float64}(1000) # should be 16-byte aligned @@ -306,7 +305,7 @@ let a = [rand(RandomDevice(), UInt128) for i=1:10] end # test all rand APIs -for rng in ([], [MersenneTwister()], [RandomDevice()]) +for rng in ([], [MersenneTwister(0)], [RandomDevice()]) types = [Base.BitInteger_types..., Bool, Float16, Float32, Float64, Char] ftypes = [Float16, Float32, Float64] b2 = big(2) @@ -378,7 +377,7 @@ function hist(X,n) end # test uniform distribution of floats -for rng in [srand(MersenneTwister()), RandomDevice()] +for rng in [srand(MersenneTwister(0)), RandomDevice()] for T in [Float16,Float32,Float64] # array version counts = hist(rand(rng, T, 2000), 4) diff --git a/test/sparse/sparsevector.jl b/test/sparse/sparsevector.jl index 1a7ac162b2b09..a2c429dad196f 100644 --- a/test/sparse/sparsevector.jl +++ b/test/sparse/sparsevector.jl @@ -159,7 +159,7 @@ let xr = sprand(Bool, 1000, 0.9) @test all(nonzeros(xr)) end -let r1 = MersenneTwister(), r2 = MersenneTwister() +let r1 = MersenneTwister(0), r2 = MersenneTwister(0) @test sprand(r1, 100, .9) == sprand(r2, 100, .9) @test sprandn(r1, 100, .9) == sprandn(r2, 100, .9) @test sprand(r1, Bool, 100, .9, ) == sprand(r2, Bool, 100, .9) From c3ced45346d19bd53a92555c50f3632005fb09ab Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 6 Apr 2017 14:32:55 -0400 Subject: [PATCH 0363/1534] fix #21243 and #21250, sigill due to incorrect empty type intersection --- src/julia.h | 4 +++ src/subtype.c | 79 ++++++++++++++++++++++++++++++++++--------------- test/subtype.jl | 5 ++++ 3 files changed, 64 insertions(+), 24 deletions(-) diff --git a/src/julia.h b/src/julia.h index 9f6ae3f7a3483..f5efda7e378c7 100644 --- a/src/julia.h +++ b/src/julia.h @@ -615,6 +615,10 @@ typedef struct _jl_gcframe_t { void *__gc_stkf[] = {(void*)11, jl_pgcstack, arg1, arg2, arg3, arg4, arg5}; \ jl_pgcstack = (jl_gcframe_t*)__gc_stkf; +#define JL_GC_PUSH6(arg1, arg2, arg3, arg4, arg5, arg6) \ + void *__gc_stkf[] = {(void*)13, jl_pgcstack, arg1, arg2, arg3, arg4, arg5, arg6}; \ + jl_pgcstack = (jl_gcframe_t*)__gc_stkf; + #define JL_GC_PUSHARGS(rts_var,n) \ rts_var = ((jl_value_t**)alloca(((n)+2)*sizeof(jl_value_t*)))+2; \ ((void**)rts_var)[-2] = (void*)(((size_t)(n))<<1); \ diff --git a/src/subtype.c b/src/subtype.c index 0bbd5278c5d52..eeb5d4376f64d 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -74,6 +74,9 @@ typedef struct _varbinding { // when this variable's integer value is compared to that of another, // it equals `other + offset`. used by vararg length parameters. int offset; + // array of typevars that our bounds depend on, whose UnionAlls need to be + // moved outside ours. + jl_array_t *innervars; struct _varbinding *prev; } jl_varbinding_t; @@ -132,14 +135,15 @@ static void save_env(jl_stenv_t *e, jl_value_t **root, jl_savedenv_t *se) len++; v = v->prev; } - *root = (jl_value_t*)jl_alloc_svec(len*2); + *root = (jl_value_t*)jl_alloc_svec(len*3); se->buf = (int8_t*)(len ? malloc(len*2) : NULL); - int i=0; v = e->vars; + int i=0, j=0; v = e->vars; while (v != NULL) { - jl_svecset(*root, i, v->lb); se->buf[i] = v->occurs_inv; - i++; - jl_svecset(*root, i, v->ub); se->buf[i] = v->occurs_cov; - i++; + jl_svecset(*root, i++, v->lb); + jl_svecset(*root, i++, v->ub); + jl_svecset(*root, i++, (jl_value_t*)v->innervars); + se->buf[j++] = v->occurs_inv; + se->buf[j++] = v->occurs_cov; v = v->prev; } se->rdepth = e->Runions.depth; @@ -148,14 +152,16 @@ static void save_env(jl_stenv_t *e, jl_value_t **root, jl_savedenv_t *se) static void restore_env(jl_stenv_t *e, jl_value_t *root, jl_savedenv_t *se) { jl_varbinding_t *v = e->vars; - int i = 0; + int i = 0, j = 0; while (v != NULL) { if (root) v->lb = jl_svecref(root, i); - v->occurs_inv = se->buf[i]; i++; if (root) v->ub = jl_svecref(root, i); - v->occurs_cov = se->buf[i]; i++; + if (root) v->innervars = (jl_array_t*)jl_svecref(root, i); + i++; + v->occurs_inv = se->buf[j++]; + v->occurs_cov = se->buf[j++]; v = v->prev; } e->Runions.depth = se->rdepth; @@ -457,7 +463,7 @@ static int subtype_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_t *e, int8 } btemp = btemp->prev; } - jl_varbinding_t vb = { u->var, u->var->lb, u->var->ub, R, NULL, 0, 0, 0, 0, e->invdepth, 0, e->vars }; + jl_varbinding_t vb = { u->var, u->var->lb, u->var->ub, R, NULL, 0, 0, 0, 0, e->invdepth, 0, NULL, e->vars }; JL_GC_PUSH3(&u, &vb.lb, &vb.ub); e->vars = &vb; int ans; @@ -1275,8 +1281,9 @@ static int var_occurs_inside(jl_value_t *v, jl_tvar_t *var, int inside, int want // Caller might not have rooted `res` static jl_value_t *finish_unionall(jl_value_t *res, jl_varbinding_t *vb, jl_stenv_t *e) { - jl_value_t *varval = NULL, *root = NULL; - JL_GC_PUSH2(&res, &root); + jl_value_t *varval = NULL; + jl_tvar_t *newvar = vb->var; + JL_GC_PUSH2(&res, &newvar); // try to reduce var to a single value if (obviously_egal(vb->lb, vb->ub)) { // given x<:T<:x, substitute x for T @@ -1287,8 +1294,12 @@ static jl_value_t *finish_unionall(jl_value_t *res, jl_varbinding_t *vb, jl_sten varval = vb->ub; } + if (!varval && (vb->lb != vb->var->lb || vb->ub != vb->var->ub)) + newvar = jl_new_typevar(vb->var->name, vb->lb, vb->ub); + // remove/replace/rewrap free occurrences of this var in the environment jl_varbinding_t *btemp = e->vars; + int wrap = 1; while (btemp != NULL) { if (jl_has_typevar(btemp->lb, vb->var)) { if (vb->lb == (jl_value_t*)btemp->var) { @@ -1299,6 +1310,21 @@ static jl_value_t *finish_unionall(jl_value_t *res, jl_varbinding_t *vb, jl_sten btemp->lb = jl_substitute_var(btemp->lb, vb->var, varval); else if (btemp->lb == (jl_value_t*)vb->var) btemp->lb = vb->lb; + else if (btemp->depth0 == vb->depth0 && !jl_has_typevar(vb->lb, btemp->var) && + !jl_has_typevar(vb->ub, btemp->var) && jl_has_typevar(btemp->ub, vb->var)) { + // if our variable is T, and some outer variable has constraint S = Ref{T}, + // move the `where T` outside `where S` instead of putting it here. issue #21243. + if (btemp->innervars == NULL) + btemp->innervars = jl_alloc_array_1d(jl_array_any_type, 0); + if (newvar != vb->var) { + btemp->lb = jl_substitute_var(btemp->lb, vb->var, (jl_value_t*)newvar); + btemp->ub = jl_substitute_var(btemp->ub, vb->var, (jl_value_t*)newvar); + } + jl_array_ptr_1d_push(btemp->innervars, (jl_value_t*)newvar); + wrap = 0; + btemp = btemp->prev; + continue; + } else btemp->lb = jl_new_struct(jl_unionall_type, vb->var, btemp->lb); assert((jl_value_t*)btemp->var != btemp->lb); @@ -1321,26 +1347,31 @@ static jl_value_t *finish_unionall(jl_value_t *res, jl_varbinding_t *vb, jl_sten // if `v` still occurs, re-wrap body in `UnionAll v` or eliminate the UnionAll if (jl_has_typevar(res, vb->var)) { - res = jl_new_struct(jl_unionall_type, vb->var, res); if (varval) { JL_TRY { // you can construct `T{x} where x` even if T's parameter is actually // limited. in that case we might get an invalid instantiation here. - res = jl_instantiate_unionall((jl_unionall_t*)res, varval); + res = jl_substitute_var(res, vb->var, varval); } JL_CATCH { res = jl_bottom_type; } } else { - if (vb->lb != vb->var->lb || vb->ub != vb->var->ub) { - varval = root = (jl_value_t*)jl_new_typevar(vb->var->name, vb->lb, vb->ub); - res = jl_instantiate_unionall((jl_unionall_t*)res, root); - res = jl_new_struct(jl_unionall_type, (jl_tvar_t*)root, res); - } - else { - varval = (jl_value_t*)vb->var; - } + if (newvar != vb->var) + res = jl_substitute_var(res, vb->var, (jl_value_t*)newvar); + varval = (jl_value_t*)newvar; + if (wrap) + res = jl_new_struct(jl_unionall_type, (jl_tvar_t*)newvar, res); + } + } + + if (res != jl_bottom_type && vb->innervars != NULL) { + int i; + for(i=0; i < jl_array_len(vb->innervars); i++) { + jl_tvar_t *var = (jl_tvar_t*)jl_arrayref(vb->innervars, i); + if (jl_has_typevar(res, var)) + res = jl_new_struct(jl_unionall_type, (jl_tvar_t*)var, res); } } @@ -1418,8 +1449,8 @@ static jl_value_t *intersect_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_ { jl_value_t *res=NULL, *res2=NULL, *save=NULL, *save2=NULL; jl_savedenv_t se, se2; - jl_varbinding_t vb = { u->var, u->var->lb, u->var->ub, R, NULL, 0, 0, 0, 0, e->invdepth, 0, e->vars }; - JL_GC_PUSH5(&res, &save2, &vb.lb, &vb.ub, &save); + jl_varbinding_t vb = { u->var, u->var->lb, u->var->ub, R, NULL, 0, 0, 0, 0, e->invdepth, 0, NULL, e->vars }; + JL_GC_PUSH6(&res, &save2, &vb.lb, &vb.ub, &save, &vb.innervars); save_env(e, &save, &se); res = intersect_unionall_(t, u, e, R, param, &vb); if (res != jl_bottom_type) { diff --git a/test/subtype.jl b/test/subtype.jl index 6e0859f3eb46d..20415b9235117 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -898,6 +898,11 @@ function test_intersection() Tuple{Type{T}, T} where T, Tuple{Type{SIQ20671{T,mS,kgS,sS,AS,KS,molS,cdS,radS,srS}}, SIQ20671{T,mS,kgS,sS,AS,KS,molS,cdS,radS,srS}} where {T,mS,kgS,sS,AS,KS,molS,cdS,radS,srS}) + + # issue #21243 + @testintersect(Tuple{Ref{Ref{T}} where T, Ref}, + Tuple{Ref{T}, Ref{T}} where T, + Tuple{Ref{Ref{T}}, Ref{Ref{T}}} where T) end function test_intersection_properties() From cbd90ac94d138bb46c6ecbf443e7889720e14170 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Mon, 3 Apr 2017 13:49:47 +0000 Subject: [PATCH 0364/1534] Make codegen emit dereferenceability attributes Consider for example the function ``` type foo a::Vector{Float64} end function bar(x::foo, n) for i = 1:1000 for j = 1:n x.a[i] = i end end end ``` Now, there's three loads in the inner loop: - x.a (the field reference) - a (the load of the array ptr) - a[i] (the load of the array value) However, two of those loads have loop invariant addresses, so they can be hoisted all the way out of the loop nest. However, without this commit LLVM isn't actually allowed to do so. Since n could be <= 0, there are valid executions in which the loads don't happen. Naively, this means that hoisting the loads could introduce segfaults that weren't there before (because the pointers could be invalid when n <= 0). Now, in this partiuclar case, LLVM is smart enough to do at least some form of loop versioning and (one for n > 0 with hoisted loads, and one regular case), but it doesn't always know how to do that. In cache sensitive codes, the extra loads can easily kill performance. With this commit, we tell LLVM that julia objects aren't generally invalid pointers, so it's safe to speculatively dereference them. This allows LLVM to perform the LICM without having to fear introducing extra segfaults. --- src/cgutils.cpp | 78 +++++++++++++++++++++++++++++++++++++++++++++---- src/codegen.cpp | 9 ++++-- 2 files changed, 80 insertions(+), 7 deletions(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 58c9efba8844f..bdc1de56ae06c 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -912,6 +912,56 @@ static void raise_exception_if(Value *cond, Value *exc, jl_codectx_t *ctx) exc, ctx); } +static size_t dereferenceable_size(jl_value_t *jt) { + size_t size = 0; + if (jl_is_array_type(jt)) { + // Array has at least this much data + size = sizeof(jl_array_t); + } else { + size = jl_datatype_size(jt); + } + return size; +} + +static inline void maybe_mark_argument_dereferenceable(Argument *A, jl_value_t *jt) { + if (!jl_is_leaf_type(jt)) { + return; + } + size_t size = dereferenceable_size(jt); + if (!size) { + return; + } + llvm::AttrBuilder Attrs; + Attrs.addDereferenceableAttr(size); +#if JL_LLVM_VERSION >= 50000 + A->addAttr(llvm::AttributeList::get(jl_LLVMContext, + A->getArgNo() + 1, Attrs)); +#else + A->addAttr(llvm::AttributeSet::get(jl_LLVMContext, + A->getArgNo() + 1, Attrs)); +#endif +} + +static inline Instruction *maybe_mark_load_dereferenceable(Instruction *LI, bool can_be_null, size_t size) { + if (!size) { + return LI; + } + llvm::SmallVector OPs; + OPs.push_back(ConstantAsMetadata::get(ConstantInt::get(T_int64, size))); + LI->setMetadata(can_be_null ? "dereferenceable_or_null" : + "dereferenceable", + MDNode::get(jl_LLVMContext, OPs)); + return LI; +} + +static inline Instruction *maybe_mark_load_dereferenceable(Instruction *LI, bool can_be_null, jl_value_t *jt) { + if (!jl_is_leaf_type(jt)) { + return LI; + } + size_t size = dereferenceable_size(jt); + return maybe_mark_load_dereferenceable(LI, can_be_null, size); +} + static void null_pointer_check(Value *v, jl_codectx_t *ctx) { raise_exception_unless(builder.CreateICmpNE(v,Constant::getNullValue(v->getType())), @@ -1142,6 +1192,8 @@ static jl_cgval_t typed_load(Value *ptr, Value *idx_0based, jl_value_t *jltype, //else { Instruction *load = builder.CreateAlignedLoad(data, isboxed ? alignment : julia_alignment(data, jltype, alignment), false); + if (isboxed) + load = maybe_mark_load_dereferenceable(load, true, jltype); if (tbaa) { elt = tbaa_decorate(tbaa, load); } @@ -1290,9 +1342,20 @@ static bool emit_getfield_unknownidx(jl_cgval_t *ret, const jl_cgval_t &strct, if (strct.ispointer()) { // boxed or stack if (is_datatype_all_pointers(stt)) { idx = emit_bounds_check(strct, (jl_value_t*)stt, idx, ConstantInt::get(T_size, nfields), ctx); - Value *fld = tbaa_decorate(strct.tbaa, builder.CreateLoad( - builder.CreateGEP(data_pointer(strct, ctx), idx))); - if ((unsigned)stt->ninitialized != nfields) + bool maybe_null = (unsigned)stt->ninitialized != nfields; + size_t minimum_field_size = (size_t)-1; + for (size_t i = 0; i < nfields; ++i) { + minimum_field_size = std::min(minimum_field_size, + dereferenceable_size(jl_field_type(stt, i))); + if (minimum_field_size == 0) + break; + } + Value *fld = tbaa_decorate(strct.tbaa, + maybe_mark_load_dereferenceable( + builder.CreateLoad( + builder.CreateGEP(data_pointer(strct, ctx), idx)), + maybe_null, minimum_field_size)); + if (maybe_null) null_pointer_check(fld, ctx); *ret = mark_julia_type(fld, true, jl_any_type, ctx, strct.gcroot || !strct.isimmutable); return true; @@ -1388,8 +1451,13 @@ static jl_cgval_t emit_getfield_knownidx(const jl_cgval_t &strct, unsigned idx, } } if (jl_field_isptr(jt, idx)) { - Value *fldv = tbaa_decorate(strct.tbaa, builder.CreateLoad(emit_bitcast(addr, T_ppjlvalue))); - if (idx >= (unsigned)jt->ninitialized) + bool maybe_null = idx >= (unsigned)jt->ninitialized; + Instruction *Load = maybe_mark_load_dereferenceable( + builder.CreateLoad(emit_bitcast(addr, T_ppjlvalue)), + maybe_null, jl_field_type(jt, idx) + ); + Value *fldv = tbaa_decorate(strct.tbaa, Load); + if (maybe_null) null_pointer_check(fldv, ctx); return mark_julia_type(fldv, true, jfty, ctx, strct.gcroot || !strct.isimmutable); } diff --git a/src/codegen.cpp b/src/codegen.cpp index b39e996044e09..a0f0a6e168fc1 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -5627,11 +5627,16 @@ static std::unique_ptr emit_function( theArg = ghostValue(argType); } else if (llvmArgType->isAggregateType()) { - theArg = mark_julia_slot(&*AI++, argType, NULL, tbaa_const); // this argument is by-pointer + Argument *Arg = &*AI++; + maybe_mark_argument_dereferenceable(Arg, argType); + theArg = mark_julia_slot(Arg, argType, NULL, tbaa_const); // this argument is by-pointer theArg.isimmutable = true; } else { - theArg = mark_julia_type(&*AI++, isboxed, argType, &ctx, /*needsgcroot*/false); + Argument *Arg = &*AI++; + if (isboxed) + maybe_mark_argument_dereferenceable(Arg, argType); + theArg = mark_julia_type(Arg, isboxed, argType, &ctx, /*needsgcroot*/false); } } else { From 04454ac714813e3e36dfed2cdf61a55605a47a90 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Thu, 6 Apr 2017 20:43:41 +0100 Subject: [PATCH 0365/1534] incorrect variable name in deprecation --- base/deprecated.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index 81bf76e5402ec..9609e9fbe0989 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1139,7 +1139,7 @@ end @deprecate object(repo::GitRepo, te::GitTreeEntry) GitObject(repo, te) false @deprecate commit(ann::GitAnnotated) GitHash(ann) false @deprecate lookup(repo::GitRepo, oid::GitHash) GitBlob(repo, oid) false - function Base.cat{T<:GitObject}(repo::GitRepo, ::Type{T}, object::Union{AbstractString,AbstractGitHash}) + function Base.cat{T<:GitObject}(repo::GitRepo, ::Type{T}, spec::Union{AbstractString,AbstractGitHash}) Base.depwarn("cat(repo::GitRepo, T, spec) is deprecated, use content(T(repo, spec))", :cat) try return content(GitBlob(repo, spec)) @@ -1148,7 +1148,7 @@ end rethrow(e) end end - Base.cat(repo::GitRepo, object::Union{AbstractString,AbstractGitHash}) = cat(repo, GitBlob, object) + Base.cat(repo::GitRepo, spec::Union{AbstractString,AbstractGitHash}) = cat(repo, GitBlob, spec) end # when this deprecation is deleted, remove all calls to it, and all From aff0eb84aed741a0d02a5fa25cb416ce62dc0cd3 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 6 Apr 2017 16:18:22 -0400 Subject: [PATCH 0366/1534] try to add location info to `_` deprecation warning --- src/julia-syntax.scm | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index ad6d7a4bd8c93..ce9c7dd6d1361 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -730,6 +730,11 @@ `(,(car sig) ,item ,@(cdr sig)) `(,item ,@sig))) +(define (linenode-string lno) + (cond ((length= lno 2) (string " around line " (cadr lno))) + ((length= lno 3) (string " around " (caddr lno) ":" (cadr lno))) + (else ""))) + (define (ctor-signature name params bounds method-params sig) (if (null? params) (if (null? method-params) @@ -774,10 +779,7 @@ body)) (lno (if (null? lnos) '() (car lnos)))) (syntax-deprecation #f - (string "inner constructor " name "(...)" - (cond ((length= lno 2) (string " around line " (cadr lno))) - ((length= lno 3) (string " around " (caddr lno) ":" (cadr lno))) - (else ""))) + (string "inner constructor " name "(...)" (linenode-string lno)) (deparse `(where (call (curly ,name ,@params) ...) ,@params))))) `(,keyword ,sig ,(ctor-body body params))))))) @@ -3228,6 +3230,7 @@ f(x) = yt(x) (let ((code '()) (filename 'none) (first-line #t) + (current-loc #f) (rett #f) (arg-map #f) ;; map arguments to new names if they are assigned (label-counter 0) ;; counter for generating label addresses @@ -3320,7 +3323,8 @@ f(x) = yt(x) (and (pair? e) (or (eq? (car e) 'outerref) (eq? (car e) 'globalref)) (eq? (cadr e) '_)))) - (syntax-deprecation #f "_ as an rvalue" "")) + (syntax-deprecation #f (string "_ as an rvalue" (linenode-string current-loc)) + "")) (cond (tail (emit-return e1)) (value e1) ((or (eq? e1 'true) (eq? e1 'false)) #f) @@ -3561,6 +3565,7 @@ f(x) = yt(x) ((import importall using export line meta inbounds boundscheck simdloop) (let ((have-ret? (and (pair? code) (pair? (car code)) (eq? (caar code) 'return)))) (cond ((eq? (car e) 'line) + (set! current-loc e) (if first-line (begin (set! first-line #f) (emit e)) From f2c035208a4915a6077f32d7cd1fd16ef71c49bc Mon Sep 17 00:00:00 2001 From: Rory-Finnegan Date: Thu, 6 Apr 2017 16:19:32 -0500 Subject: [PATCH 0367/1534] Finding and removing `StackFrame`s from `StackTrace`s based on source `Module`. * `StackTraces.remove_frames!(::StackTrace, ::Module)` for removing `StackFrame`s from a given `Module`. * `StackTraces.from(::StackFrame, ::Module) -> Bool` tests if the `StackFrame` is from the `Module`. --- base/stacktraces.jl | 27 +++++++++++++++++++++++++++ test/stacktraces.jl | 12 ++++++++++++ 2 files changed, 39 insertions(+) diff --git a/base/stacktraces.jl b/base/stacktraces.jl index a7d9af7037999..2734f7c8c5392 100644 --- a/base/stacktraces.jl +++ b/base/stacktraces.jl @@ -190,6 +190,16 @@ function remove_frames!(stack::StackTrace, names::Vector{Symbol}) return stack end +""" + remove_frames!(stack::StackTrace, m::Module) + +Returns the `StackTrace` with all `StackFrame`s from the provided `Module` removed. +""" +function remove_frames!(stack::StackTrace, m::Module) + filter!(f -> !from(f, m), stack) + return stack +end + function show_spec_linfo(io::IO, frame::StackFrame) if isnull(frame.linfo) if frame.func === empty_sym @@ -226,4 +236,21 @@ function show(io::IO, frame::StackFrame; full_path::Bool=false) end end +""" + from(frame::StackFrame, filter_mod::Module) -> Bool + +Returns whether the `frame` is from the provided `Module` +""" +function from(frame::StackFrame, m::Module) + finfo = frame.linfo + result = false + + if !isnull(finfo) + frame_m = get(finfo).def.module + result = module_name(frame_m) === module_name(m) + end + + return result +end + end diff --git a/test/stacktraces.jl b/test/stacktraces.jl index 5bb12afab67be..079e0b73d388e 100644 --- a/test/stacktraces.jl +++ b/test/stacktraces.jl @@ -130,3 +130,15 @@ let st = stacktrace(empty!(backtrace())) @test isempty(st) @test isa(st, StackTrace) end + +module StackTracesTestMod + unfiltered_stacktrace() = stacktrace() + filtered_stacktrace() = StackTraces.remove_frames!(stacktrace(), StackTracesTestMod) +end + +# Test that `removes_frames!` can correctly remove frames from withing the module +trace = StackTracesTestMod.unfiltered_stacktrace() +@test contains(string(trace), "unfiltered_stacktrace") + +trace = StackTracesTestMod.filtered_stacktrace() +@test !contains(string(trace), "filtered_stacktrace") From 79e8714064968cdd5faf928dd499f23abc58f34c Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 6 Apr 2017 17:42:55 -0400 Subject: [PATCH 0368/1534] update precompile.jl --- base/precompile.jl | 2370 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 1887 insertions(+), 483 deletions(-) diff --git a/base/precompile.jl b/base/precompile.jl index 6fe485436dd9e..96118ece4c7f2 100644 --- a/base/precompile.jl +++ b/base/precompile.jl @@ -1,486 +1,1890 @@ # This file is a part of Julia. License is MIT: http://julialang.org/license -# prime method cache with some things we know we'll need right after startup -precompile(!=, (Bool, Bool)) -precompile(!=, (SubString{String}, String)) -precompile(*, (String, String, String)) -precompile(-, (Int,)) -precompile(==, (String, String)) -precompile(==, (String, Char)) -precompile(==, (String, Int)) -precompile(==, (Array{Char, 1}, Array{Char, 1})) -precompile(==, (Array{Char,1}, Array{Char,1})) -precompile(==, (Base.LineEdit.HistoryPrompt{Base.REPL.REPLHistoryProvider}, Base.LineEdit.Prompt)) -precompile(==, (Base.LineEdit.Prompt, Base.LineEdit.Prompt)) -precompile(==, (Base.Multimedia.TextDisplay, Base.REPL.REPLDisplay{Base.REPL.LineEditREPL})) -precompile(==, (Base.REPL.REPLDisplay{Base.REPL.LineEditREPL}, Base.Multimedia.TextDisplay)) -precompile(==, (Int32, Int32)) -precompile(==, (Int32, Int64)) -precompile(==, (Int64, Int32)) -precompile(==, (Int64, Int64)) -precompile(==, (Bool,Bool)) -precompile(==, (Char, String)) -precompile(==, (IOStream,Void)) -precompile(==, (Type{String}, Type{Any})) -precompile(==, (Type{Base.LineEdit.Prompt}, Type{Base.LineEdit.Prompt})) -precompile(==, (Type{Function}, Int)) -precompile(==, (Type{Function}, Type{String})) -precompile(Base._atreplinit, (Base.REPL.LineEditREPL,)) -precompile(Base.BitArray, (Int,)) -precompile(Base.Dict, ()) -precompile(Base.Dict{Any,Any}, (Int,)) -precompile(Base.IOStream, (String, Array{UInt8,1})) -precompile(Base.KeyError, (Int,)) -precompile(Base.LineEdit.Prompt, (String, String, String, Function, Function, Base.REPL.LineEditREPL, Base.REPL.REPLCompletionProvider, Function, Function, Base.LineEdit.EmptyHistoryProvider, Bool)) -precompile(Base.LineEdit.Prompt, (String, String, String, Function, Function, Base.REPL.LineEditREPL, Base.REPL.ShellCompletionProvider, Function, Function, Base.LineEdit.EmptyHistoryProvider, Bool)) -precompile(Base.LineEdit.Prompt, (String, String, Function, Function, Base.REPL.LineEditREPL, Base.REPL.REPLCompletionProvider, Function, Function, Base.LineEdit.EmptyHistoryProvider, Bool, String)) -precompile(Base.LineEdit.Prompt, (String, String, Function, Function, Base.REPL.LineEditREPL, Base.REPL.ShellCompletionProvider, Function, Function, Base.LineEdit.EmptyHistoryProvider, Bool, String)) -precompile(Base.LineEdit.PromptState, (Base.Terminals.TTYTerminal, Base.LineEdit.Prompt, IOBuffer, Base.LineEdit.InputAreaState, Int)) -precompile(Base.LineEdit.activate, (Base.LineEdit.Prompt, Base.LineEdit.MIState, Base.Terminals.TTYTerminal)) -precompile(Base.LineEdit.activate, (Base.LineEdit.Prompt, Base.LineEdit.PromptState, Base.Terminals.TTYTerminal)) -precompile(Base.LineEdit.activate, (Base.LineEdit.Prompt, Base.LineEdit.PromptState, Base.Terminals.TerminalBuffer)) -precompile(Base.LineEdit.add_history, (Base.LineEdit.PromptState,)) -precompile(Base.LineEdit.buffer, (Base.LineEdit.MIState,)) -precompile(Base.LineEdit.buffer, (Base.LineEdit.PromptState,)) -precompile(Base.LineEdit.char_move_left, (IOBuffer,)) -precompile(Base.LineEdit.clear_input_area, (Base.Terminals.TTYTerminal, Base.LineEdit.InputAreaState)) -precompile(Base.LineEdit.commit_line, (Base.LineEdit.MIState,)) -precompile(Base.LineEdit.deactivate, (Base.LineEdit.Prompt,Base.LineEdit.PromptState, Base.Terminals.TerminalBuffer)) -precompile(Base.LineEdit.edit_backspace, (Base.LineEdit.MIState,)) -precompile(Base.LineEdit.edit_backspace, (Base.LineEdit.PromptState,)) -precompile(Base.LineEdit.edit_backspace, (IOBuffer,)) -precompile(Base.LineEdit.edit_clear, (Base.LineEdit.MIState,)) -precompile(Base.LineEdit.edit_delete, (Base.LineEdit.MIState,)) -precompile(Base.LineEdit.edit_delete, (IOBuffer,)) -precompile(Base.LineEdit.edit_insert, (Base.LineEdit.MIState, Char)) -precompile(Base.LineEdit.edit_insert, (Base.LineEdit.PromptState, Char)) -precompile(Base.LineEdit.edit_insert, (IOBuffer, String)) -precompile(Base.LineEdit.edit_move_down, (Base.LineEdit.MIState,)) -precompile(Base.LineEdit.edit_move_left, (Base.LineEdit.MIState,)) -precompile(Base.LineEdit.edit_move_left, (Base.LineEdit.PromptState,)) -precompile(Base.LineEdit.edit_move_left, (IOBuffer,)) -precompile(Base.LineEdit.edit_move_right, (Base.LineEdit.MIState,)) -precompile(Base.LineEdit.edit_move_right, (Base.LineEdit.PromptState,)) -precompile(Base.LineEdit.edit_move_right, (IOBuffer,)) -precompile(Base.LineEdit.edit_move_up, (Base.LineEdit.MIState,)) -precompile(Base.LineEdit.edit_move_up, (IOBuffer,)) -precompile(Base.LineEdit.postprocess!, (Void, Int)) -precompile(Base.LineEdit.history_prev, (Base.LineEdit.MIState, Base.REPL.REPLHistoryProvider)) -precompile(Base.LineEdit.history_prev, (Base.LineEdit.MIState, Base.REPL.REPLHistoryProvider, Int)) -precompile(Base.LineEdit.init_state, (Base.Terminals.TTYTerminal, Base.LineEdit.HistoryPrompt{Base.REPL.REPLHistoryProvider})) -precompile(Base.LineEdit.init_state, (Base.Terminals.TTYTerminal, Base.LineEdit.Prompt)) -precompile(Base.LineEdit.input_string, (Base.LineEdit.PromptState,)) -precompile(Base.LineEdit.keymap, (Base.LineEdit.PromptState, Base.LineEdit.Prompt)) -precompile(Base.LineEdit.keymap_data, (Base.LineEdit.PromptState, Base.LineEdit.Prompt)) -precompile(Base.LineEdit.keymap_fcn, (Function, String)) -precompile(Base.LineEdit.match_input, (Dict{Char,Any},Base.LineEdit.MIState)) -precompile(Base.LineEdit.match_input, (Dict{Char, Any}, Base.LineEdit.MIState, Base.Terminals.TTYTerminal)) -precompile(Base.LineEdit.match_input, (Function, Base.LineEdit.MIState, Base.Terminals.TTYTerminal, Array{Char,1})) -precompile(Base.LineEdit.mode, (Base.LineEdit.MIState,)) -precompile(Base.LineEdit.move_line_end, (Base.LineEdit.MIState,)) -precompile(Base.LineEdit.on_enter, (Base.LineEdit.MIState,)) -precompile(Base.LineEdit.on_enter, (Base.LineEdit.PromptState,)) -precompile(Base.LineEdit.prompt!, (Base.Terminals.TTYTerminal, Base.LineEdit.ModalInterface, Base.LineEdit.MIState)) -precompile(Base.LineEdit.refresh_line, (Base.LineEdit.MIState,)) -precompile(Base.LineEdit.refresh_multi_line, (Base.LineEdit.MIState,)) -precompile(Base.LineEdit.refresh_multi_line, (Base.LineEdit.PromptState,)) -precompile(Base.LineEdit.refresh_multi_line, (Base.Terminals.TTYTerminal, Base.LineEdit.PromptState)) -precompile(Base.LineEdit.refresh_multi_line, (Base.Terminals.TerminalBuffer, Base.LineEdit.SearchState)) -precompile(Base.LineEdit.refresh_multi_line, (Base.Terminals.TerminalBuffer, Base.Terminals.TTYTerminal, Base.LineEdit.PromptState)) -precompile(Base.LineEdit.replace_line, (Base.LineEdit.PromptState, String)) -precompile(Base.LineEdit.replace_line, (Base.LineEdit.PromptState, Base.IOBuffer)) -precompile(Base.LineEdit.reset_key_repeats, (Function, Base.LineEdit.MIState,)) -precompile(Base.LineEdit.reset_state, (Base.LineEdit.MIState,)) -precompile(Base.LineEdit.reset_state, (Base.LineEdit.PromptState,)) -precompile(Base.LineEdit.reset_state, (Base.LineEdit.SearchState,)) -precompile(Base.LineEdit.run_interface, (Base.Terminals.TTYTerminal, Base.LineEdit.ModalInterface)) -precompile(Base.LineEdit.setup_search_keymap, (Base.REPL.REPLHistoryProvider,)) -precompile(Base.LineEdit.splice_buffer!, (IOBuffer, UnitRange{Int}, String)) -precompile(Base.LineEdit.state, (Base.LineEdit.MIState, Base.LineEdit.Prompt)) -precompile(Base.LineEdit.terminal, (Base.LineEdit.MIState,)) -precompile(Base.LineEdit.terminal, (Base.LineEdit.PromptState,)) -precompile(Base.LineEdit.transition, (Base.LineEdit.MIState, Base.LineEdit.Prompt)) -precompile(Base.LineEdit.transition, (Base.LineEdit.MIState, Symbol)) -precompile(Base.LineEdit.update_key_repeats, (Base.LineEdit.MIState, Array{Char, 1})) -precompile(Base.LineEdit.update_key_repeats, (Base.LineEdit.MIState, Array{Char,1})) -precompile(Base.LineEdit.write_prompt, (Base.Terminals.TTYTerminal, Base.LineEdit.Prompt)) -precompile(Base.LineEdit.write_prompt, (Base.Terminals.TerminalBuffer, Base.LineEdit.PromptState)) -precompile(Base.Multimedia.TextDisplay, (Base.TTY,)) -precompile(Base.Multimedia.display, (Int,)) -precompile(Base.Distributed.ProcessGroup, (Int, Array{Any,1}, Array{Any,1})) -precompile(Base.REPL.:(==), (Base.REPL.REPLDisplay{Base.REPL.LineEditREPL}, Base.REPL.REPLDisplay{Base.REPL.LineEditREPL})) -precompile(Base.REPL.LineEditREPL, (Base.Terminals.TTYTerminal, Bool, String, String, String, String, String, Bool, Bool, Bool, Bool)) -precompile(Base.REPL.LineEditREPL, (Base.Terminals.TTYTerminal,)) -precompile(Base.REPL.REPLBackendRef, (Channel{Any}, Channel{Any})) -precompile(Base.REPL.REPLDisplay, (Base.REPL.BasicREPL,)) -precompile(Base.REPL.REPLDisplay, (Base.REPL.LineEditREPL,)) -precompile(Base.REPL.add_history, (Base.REPL.REPLHistoryProvider, Base.LineEdit.PromptState)) -precompile(Base.REPL.backend, (Base.REPL.LineEditREPL,)) -precompile(Base.REPL.display, (Base.REPL.REPLDisplay{Base.REPL.LineEditREPL}, Base.Multimedia.MIME{Symbol("text/plain")}, Int)) -precompile(Base.REPL.display, (Base.REPL.REPLDisplay{Base.REPL.LineEditREPL}, Int)) -precompile(Base.REPL.ends_with_semicolon, (String,)) -precompile(Base.REPL.find_hist_file, ()) -precompile(Base.REPL.hist_from_file, (Base.REPL.REPLHistoryProvider, IOStream, String)) -precompile(Base.REPL.history_next, (Base.LineEdit.MIState, Base.REPL.REPLHistoryProvider, Int)) -precompile(Base.REPL.history_next_prefix, (Base.LineEdit.MIState, Base.REPL.REPLHistoryProvider,)) -precompile(Base.REPL.history_prev_prefix, (Base.LineEdit.MIState, Base.REPL.REPLHistoryProvider,)) -precompile(Base.REPL.mode_idx, (Base.REPL.REPLHistoryProvider, Base.LineEdit.Prompt)) -precompile(Base.REPL.reset, (Base.REPL.LineEditREPL,)) -precompile(Base.REPL.reset_state, (Base.REPL.REPLHistoryProvider,)) -precompile(Base.REPL.respond, (Function, Base.REPL.LineEditREPL, Base.LineEdit.Prompt)) -precompile(Base.REPL.return_callback, (Base.LineEdit.PromptState,)) -precompile(Base.REPL.run_repl, (Base.REPL.LineEditREPL,)) -precompile(Base.REPL.send_to_backend, (Expr, Base.REPL.REPLBackendRef)) -precompile(Base.REPL.send_to_backend, (Expr, Channel{Any}, Channel{Any})) -precompile(Base.REPL.send_to_backend, (Symbol, Base.REPL.REPLBackendRef)) -precompile(Base.REPL.start_repl_backend, (Channel{Any}, Channel{Any})) -precompile(Base.REPLCompletions.complete_methods, (String,)) -precompile(Base.REPLCompletions.complete_symbol, (String, Function)) -precompile(Base.REPLCompletions.completions, (String, Int)) -precompile(Base.Random.srand, ()) -precompile(Base.Random.srand, (String, Int)) -precompile(Base.Random.srand, (UInt,)) -precompile(Base.Distributed.RemoteChannel, (Int, Int, Int)) -precompile(Base.Distributed.RemoteValue, ()) -precompile(Base.Set, ()) -precompile(Base.SystemError, (String,)) -precompile(Base.TCPSocket, (Ptr{Void},)) -precompile(Base.TTY, (Ptr{Void},)) -precompile(Base.Terminals.TTYTerminal, (String, Base.TTY, Base.TTY, Base.TTY)) -precompile(Base.Terminals.beep, (Base.Terminals.TTYTerminal,)) -precompile(Base.Terminals.raw!, (Base.Terminals.TTYTerminal, Bool)) -precompile(Base.Terminals.write, (Base.Terminals.TTYTerminal, Array{UInt8, 1})) -precompile(Libc.TmStruct, (Float64,)) -precompile(Base.VersionNumber, (Int, Int, Int, Tuple{}, Tuple{String})) -precompile(Base._atexit, ()) -precompile(Base._deleteat!, (Array{UInt8, 1}, Int, Int)) -precompile(Base._growat!, (Array{UInt8, 1}, Int, Int)) -precompile(Base._setindex!, (Base.Dict{Symbol, Any}, Base.LineEdit.Prompt, Symbol, Int)) -precompile(Base._setindex!, (Dict{Any, Any}, Base.LineEdit.PromptState, Base.LineEdit.Prompt, Int)) -precompile(Base._setindex!, (Dict{Any, Any}, Bool, WeakRef, Int)) -precompile(Base._setindex!, (Dict{UInt8, Any}, Base.LineEdit.Prompt, UInt8, Int)) -precompile(Base._start, ()) -precompile(Base.abs, (Char,)) -precompile(Base.abspath, (String, String)) -precompile(Base.abspath, (String,)) -precompile(Base.alignment, (Base.IOContext, Float64,)) -precompile(Base.any, (Function, Array{Any,1})) -precompile(Base.arg_gen, (String,)) -precompile(Base.associate_julia_struct, (Ptr{Void}, Base.TTY)) -precompile(Base.async_run_thunk, (Function,)) -precompile(Base.atexit, (Function,)) -precompile(Base.banner, (Base.Terminals.TTYTerminal,)) -precompile(Base.startswith, (String, String)) -precompile(Base.String, (String,)) -precompile(Base.chop, (String,)) -precompile(Base.close, (Base.TTY,)) -precompile(Base.close, (IOStream,)) -precompile(Base.cmp, (Int32, Int32)) -precompile(Base.convert, (Type{Any}, Base.LineEdit.ModalInterface)) -precompile(Base.convert, (Type{Any}, Base.LineEdit.Prompt)) -precompile(Base.convert, (Type{Any}, Base.ObjectIdDict)) -precompile(Base.convert, (Type{Any}, Base.REPL.LatexCompletions)) -precompile(Base.convert, (Type{Any}, Base.REPL.REPLHistoryProvider)) -precompile(Base.convert, (Type{Any}, Function)) -precompile(Base.convert, (Type{Any}, IOStream)) -precompile(Base.convert, (Type{Any}, Int)) -precompile(Base.convert, (Type{Any}, Void)) -precompile(Base.convert, (Type{Base.IPAddr}, Base.IPv4)) -precompile(Base.convert, (Type{Base.LineEdit.InputAreaState}, Base.LineEdit.InputAreaState)) -precompile(Base.convert, (Type{Char}, Char)) -precompile(Base.convert, (Type{Function}, Function)) -precompile(Base.convert, (Type{IOBuffer}, IOBuffer)) -precompile(Base.convert, (Type{Module}, Module)) -precompile(Base.convert, (Type{AbstractString}, String)) -precompile(Base.copy!, (Array{Dict{Any, Any}, 1}, Int, Array{Dict{Any, Any}, 1}, Int, Int)) -precompile(Base.copy, (Bool,)) -precompile(Base.deleteat!, (Array{UInt8, 1}, Base.UnitRange{Int})) -precompile(Base.done, (Array{Base.LineEdit.TextInterface, 1}, Int)) -precompile(Base.done, (Dict{Any,Any}, Int)) -precompile(Base.done, (Dict{Symbol,Any}, Int)) -precompile(Base.done, (IntSet, Int)) -precompile(Base.done, (UnitRange{Int},Int)) -precompile(Base.endof, (Array{Any,1},)) -precompile(Base.enq_work, (Task,)) -precompile(Base.eval_user_input, (Expr, Bool)) -precompile(Base.fdio, (Int32,)) -precompile(Base.fill!, (BitArray{1}, Bool)) -precompile(Base.first, (UnitRange{Int},)) -precompile(Base.flush, (IOStream,)) -precompile(Base.Distributed.flush_gc_msgs, ()) -precompile(Base.Distributed.flush_gc_msgs, (Base.Distributed.Worker,)) -precompile(Base.get, (Base.EnvHash, String, String)) -precompile(Base.get, (Dict{Any, Any}, Tuple{Int, Int}, Bool)) -precompile(Base.get, (Dict{Any,Any}, Symbol, String)) -precompile(Base.get_chunks_id, (Int,)) -precompile(Base.getindex, (Array{Base.LineEdit.TextInterface, 1}, Int)) -precompile(Base.getindex, (BitArray{1}, Int,)) -precompile(Base.getindex, (Dict{Any, Any}, Base.LineEdit.Prompt)) -precompile(Base.getindex, (Dict{Any,Any}, Int32)) -precompile(Base.getindex, (Dict{Symbol,Any},Symbol)) -precompile(Base.getindex, (Type{AbstractString},)) -precompile(Base.getindex, (Type{String}, String, String)) -precompile(Base.getindex, (Type{Dict{Any, Any}}, Dict{Any, Any}, Dict{Any, Any}, Dict{Any, Any}, Dict{Any, Any}, Dict{Any, Any})) -precompile(Base.getpid, ()) -precompile(Base.hash, (Int,)) -precompile(Base.hash, (Base.Distributed.RemoteChannel, UInt)) -precompile(Base.hash, (Base.Distributed.RemoteChannel,)) -precompile(Base.haskey, (Base.EnvHash, String)) -precompile(Base.haskey, (Dict{Symbol,Any}, Symbol)) -precompile(Base.haskey, (ObjectIdDict, Symbol)) -precompile(Base.hex, (Char, Int)) -precompile(Base.ht_keyindex, (Dict{Any, Any}, Base.LineEdit.Prompt)) -precompile(Base.ht_keyindex, (Dict{Any,Any}, Int32)) -precompile(Base.ht_keyindex, (Dict{UInt8, Any}, UInt8)) -precompile(Base.ht_keyindex2, (Dict{Any, Any}, Base.LineEdit.Prompt)) -precompile(Base.ht_keyindex2, (Dict{UInt8, Any}, UInt8)) -precompile(Base.in, (Char, String)) -precompile(Base.in, (Int, Base.UnitRange{Int})) -precompile(Base.in, (UInt8, Base.KeyIterator{Dict{UInt8, Any}})) -precompile(Base.include_from_node1, (String,)) -precompile(Base.init_stdio, (Ptr{Void},)) -precompile(Base.input_color, ()) -precompile(Base.insert!, (Array{Any,1}, Int, Base.GlobalRef)) -precompile(Base.Int, (Int,)) -precompile(Base.Int, (UInt,)) -precompile(Base.isabspath, (String,)) -precompile(Base.isempty, (String,)) -precompile(Base.isempty, (Array{Any,1},)) -precompile(Base.isempty, (Base.LineEdit.MIState,)) -precompile(Base.isempty, (Base.LineEdit.PromptState,)) -precompile(Base.isempty, (SubString{String},)) -precompile(Base.isequal, (Tuple{Int,Int},Tuple{Int,Int})) -precompile(Base.isequal, (Base.LineEdit.Prompt, Base.LineEdit.Prompt)) -precompile(Base.isequal, (Bool, Bool)) -precompile(Base.isequal, (Char, String)) -precompile(Base.isequal, (Int,Int)) -precompile(Base.isequal, (Base.Distributed.RemoteChannel, Base.Distributed.RemoteChannel)) -precompile(Base.isequal, (Base.Distributed.RemoteChannel, WeakRef)) -precompile(Base.isequal, (Symbol, Symbol)) -precompile(Base.isequal, (VersionNumber, VersionNumber)) -precompile(Base.isequal, (Void, Void)) -precompile(Base.isfile, (String,)) -precompile(Base.ismatch, (Regex, String)) -precompile(Base.isslotempty, (Dict{Any,Any}, Int)) -precompile(Base.istaskdone, (Task,)) -precompile(Base.joinpath, (String, String)) -precompile(Base.joinpath, (String, String, String)) -precompile(Base.keys, (Dict{UInt8, Any},)) -precompile(Base.last, (UnitRange{Int},)) -precompile(Base.length, (String,)) -precompile(Base.length, (Array{UInt8,1},)) -precompile(Base.length, (UnitRange{Int},)) -precompile(Base.match, (Regex, String)) -precompile(Base.match, (Regex, String, Int)) -precompile(Base.min, (Int32, Int32)) -precompile(Base.next, (Array{Base.LineEdit.TextInterface, 1}, Int)) -precompile(Base.next, (Dict{Any,Any}, Int)) -precompile(Base.next, (Dict{Symbol,Any},Int)) -precompile(Base.next, (IntSet, Int)) -precompile(Base.next, (UnitRange{Int},Int)) -precompile(Base.nextind, (String, Int)) -precompile(Base.normpath, (String, String)) -precompile(Base.normpath, (String,)) -precompile(Base.notify, (Condition, Any)) -precompile(Base.open, (String, String)) -precompile(Base.parse_input_line, (String,)) -precompile(Base.parse, (Type{Int}, String, Int)) -precompile(Base.peek, (Base.IOBuffer,)) -precompile(Base.pop!, (Array{Any,1},)) -precompile(Base.position, (IOBuffer,)) -precompile(Base.prepend!, (Array{Dict{Any, Any}, 1}, Array{Dict{Any, Any}, 1})) -precompile(Base.print, (String,)) -precompile(Base.print, (Base.TTY, String)) -precompile(Base.print, (Base.TTY,Char)) -precompile(Base.print, (Base.Terminals.TTYTerminal, String)) -precompile(Base.print, (Base.Terminals.TTYTerminal, String, Char)) -precompile(Base.print, (Base.Terminals.TTYTerminal, String, Char,)) -precompile(Base.print, (Float64,)) -precompile(Base.print, (IOBuffer, String)) -precompile(Base.print, (IOBuffer, VersionNumber)) -precompile(Base.print, (IOStream, Int32)) -precompile(Base.print, (IOStream,String)) -precompile(Base.join, (IOBuffer, Tuple{String}, Char)) -precompile(Base.join, (IOBuffer, Tuple{Int}, Char)) -precompile(Base.join, (IOBuffer, Array{String,1}, Char)) -precompile(Base.join, (IOBuffer, Array{AbstractString,1}, String)) -precompile(Base.join, (IOBuffer, Array{SubString{String}, 1}, String)) -precompile(Base.println, (Base.TTY,)) -precompile(Base.println, (Base.Terminals.TTYTerminal,)) -precompile(Base.promote_type, (Type{Base.LineEdit.Prompt}, Type{Base.LineEdit.HistoryPrompt{Base.REPL.REPLHistoryProvider}})) -precompile(Base.promote_type, (Type{Base.LineEdit.Prompt}, Type{Base.LineEdit.Prompt})) -precompile(Base.promote_type, (Type{Base.LineEdit.Prompt}, Type{Base.LineEdit.TextInterface})) -precompile(Base.promote_type, (Type{Int}, Bool)) -precompile(Base.push!, (Array{AbstractString, 1}, String)) -precompile(Base.push!, (Array{AbstractString,1}, String)) -precompile(Base.push!, (Array{Base.Multimedia.Display, 1}, Base.Multimedia.TextDisplay)) -precompile(Base.push!, (Array{Char, 1}, Char)) -precompile(Base.push!, (Array{Union{String, String}, 1}, String)) -precompile(Base.pushdisplay, (Base.Multimedia.TextDisplay,)) -precompile(Base.pwd, ()) -precompile(Base.read, (Base.Terminals.TTYTerminal, Type{Char})) -precompile(Base.read, (IOBuffer, Type{Char})) -precompile(Base.read, (IOBuffer, Type{UInt8})) -precompile(Base.read, (IOStream, Array{UInt32,1})) -precompile(Base.readline, (String,)) -precompile(Base.readline, (IOBuffer,)) -precompile(Base.readline, (IOStream,)) -precompile(Base.readuntil, (IOBuffer, Char)) -precompile(Base.readuntil, (IOBuffer, UInt8)) -precompile(Base.rehash!, (Dict{Any,Any}, Int)) -precompile(Base.rehash!, (Dict{UInt8, Any}, Int)) -precompile(Base.reinit_stdio, ()) -precompile(Base.repeat, (String, Int)) -precompile(Base.repl_cmd, (Cmd, Base.Terminals.TTYTerminal)) -precompile(Base.require, (Symbol,)) -precompile(Base.Distributed.remoteref_id, (Base.Distributed.RemoteChannel,)) -precompile(Base.rsearch, (String, Char)) -precompile(Base.rstrip, (String,)) -precompile(Base.run, (Cmd,)) -precompile(Base.search, (String, Regex, Int)) -precompile(Base.search, (IOBuffer, UInt8)) -precompile(Base.seek, (IOBuffer, Int)) -precompile(Base.seekend, (IOStream,)) -precompile(Base.setindex!, (Array{AbstractString, 1}, String, Int)) -precompile(Base.setindex!, (Array{Any, 1}, Array{UInt8, 1}, Int)) -precompile(Base.setindex!, (Array{Any, 1}, Base.NewvarNode, Int)) -precompile(Base.setindex!, (Array{Any, 1}, GlobalRef, Int)) -precompile(Base.setindex!, (Array{Any,1}, WeakRef, Int)) -precompile(Base.setindex!, (Array{Base.LineEdit.TextInterface, 1}, Base.LineEdit.HistoryPrompt{Base.REPL.REPLHistoryProvider}, UnitRange{Int})) -precompile(Base.setindex!, (Array{Base.LineEdit.TextInterface, 1}, Base.LineEdit.Prompt, UnitRange{Int})) -precompile(Base.setindex!, (Array{Char, 1}, Char, Int)) -precompile(Base.setindex!, (Array{Symbol, 1}, Symbol, Int)) -precompile(Base.setindex!, (Array{UInt8,1}, UInt8, Int)) -precompile(Base.setindex!, (Base.Dict{Symbol, Any}, Base.LineEdit.Prompt, Symbol)) -precompile(Base.setindex!, (BitArray{1}, Bool, Int,)) -precompile(Base.setindex!, (Dict{Any, Any}, Base.LineEdit.PromptState, Base.LineEdit.Prompt)) -precompile(Base.setindex!, (Dict{Any,Any}, Base.LineEdit.SearchState, Base.LineEdit.HistoryPrompt{Base.REPL.REPLHistoryProvider})) -precompile(Base.setindex!, (Dict{Any,Any}, Bool, Cmd)) -precompile(Base.setindex!, (Dict{UInt8, Any}, Base.LineEdit.Prompt, UInt8)) -precompile(Base.setindex!, (Base.EnvHash, String, String)) -precompile(Base.setindex!, (Vector{Any}, UInt8, Int)) -precompile(Base.setindex!, (Vector{Any}, Vector{Any}, Int)) -precompile(Base.show, (Base.Terminals.TTYTerminal, Int)) -precompile(Base.show, (Float64,)) -precompile(Base.show, (IOStream, Int32)) -precompile(Base.showcompact, (Base.Terminals.TTYTerminal, Int)) -precompile(Base.similar, (Array{Base.LineEdit.Prompt, 1}, Type{Base.LineEdit.TextInterface}, Tuple{Int})) -precompile(Base.size, (Base.Terminals.TTYTerminal,)) -precompile(Base.sizehint!, (Base.Dict{Symbol, Any}, Int)) -precompile(Base.sizeof, (String,)) -precompile(Base.source_path, (Void,)) -precompile(Base.splice!, (Array{UInt8, 1}, Base.UnitRange{Int}, Array{UInt8, 1})) -precompile(Base.split, (String, String)) -precompile(Base.split, (String, Regex)) -precompile(Base.split, (String,)) -precompile(Base.srand, (Array{UInt32,1},)) -precompile(Base.start, (Array{Base.LineEdit.TextInterface, 1},)) -precompile(Base.start, (Dict{Any,Any},)) -precompile(Base.start, (Dict{Symbol,Any},)) -precompile(Base.start, (UnitRange{Int},)) -precompile(Base.start_reading, (Base.TTY,)) -precompile(Base.stop_reading, (Base.TTY,)) -precompile(Libc.strftime, (String, Libc.TmStruct)) -precompile(Base.string, (Int,)) -precompile(Base.strip, (String,)) -precompile(Base.strwidth, (String,)) -precompile(Base.Symbol, (SubString{String},)) -precompile(Base.sync_begin, ()) -precompile(Base.sync_end, ()) -precompile(Base.systemerror, (Symbol, Bool)) -precompile(Base.Distributed.take!, (Base.Distributed.RemoteValue,)) -precompile(Base.Distributed.take!, (Base.Distributed.RemoteChannel,)) -precompile(Base.Distributed.take_ref, (Tuple{Int,Int},)) -precompile(Base.take!, (IOBuffer,)) -precompile(Base.task_local_storage, ()) -precompile(Base.Distributed.terminate_all_workers, ()) -precompile(Base.try_include, (String,)) -precompile(Base.UInt, (UInt,)) -precompile(Base.unsafe_copy!, (Array{Dict{Any, Any}, 1}, Int, Array{Dict{Any, Any}, 1}, Int, Int)) -precompile(Base.unsafe_copy!, (Ptr{Dict{Any, Any}}, Ptr{Dict{Any, Any}}, Int)) -precompile(Base.unshift!, (Array{Any,1}, Task)) -precompile(Base.uv_error, (String, Bool)) -precompile(Base.uvfinalize, (Base.TTY,)) -precompile(Base.vcat, (Base.LineEdit.Prompt,)) -precompile(Base.wait, ()) -precompile(Base.Distributed.wait, (Base.Distributed.RemoteChannel,)) -precompile(Base.write, (Base.Terminals.TTYTerminal, String)) -precompile(Base.write, (Base.Terminals.TerminalBuffer, String)) -precompile(Base.write, (IOBuffer, Vector{UInt8})) -precompile(Base.show, (Base.Terminals.TTYTerminal, Base.Multimedia.MIME{Symbol("text/plain")}, Int)) +# Steps to regenerate this file: +# 1. Remove all `precompile` calls +# 2. Rebuild system image +# 3. Enable TRACE_COMPILE in options.h and rebuild +# 4. Run `./julia 2> precompiles.txt` and do various things. +# 5. Run `grep -v '#[0-9]' precompiles.txt >> base/precompile.jl` (filters out closures, which +# might have different generated names in different environments) -# The following are intended to help speed Pkg.update() -precompile(Base.Pkg.Entry.update, (String,)) -precompile(Base.Pkg.Query.prune_dependencies, (Dict{String, Base.Pkg.Types.VersionSet}, Dict{String, Dict{VersionNumber, Base.Pkg.Types.Available}})) -precompile(Base.Pkg.Read.installed_version, (String, Dict{VersionNumber, Base.Pkg.Types.Available})) -precompile(Base.Pkg.Resolve.resolve, (Dict{String, Base.Pkg.Types.VersionSet}, Dict{String, Dict{VersionNumber, Base.Pkg.Types.Available}})) -precompile(Base.Pkg.update, ()) -precompile(Base.Sort.sort!, (Array{Any, 1}, Base.Sort.MergeSortAlg, Base.Order.ForwardOrdering)) -precompile(Base.Sort.sort!, (Array{Any, 1}, Int, Int, Base.Sort.InsertionSortAlg, Base.Order.ForwardOrdering)) -precompile(Base.Sort.sort!, (Array{Any,1},)) -precompile(Base.Sort.sort!, (Array{VersionNumber, 1}, Int, Int, Base.Sort.InsertionSortAlg, Base.Order.ForwardOrdering)) -precompile(Base.info, (String,)) -precompile(Base.isempty, (Array{Void, 1},)) -precompile(Base.setindex!, (Dict{String, VersionNumber}, VersionNumber, String)) -precompile(Base.spawn, (Cmd, Tuple{Base.TTY, Base.TTY, Base.TTY}, Bool, Bool)) -precompile(Base.spawn, (Cmd,)) - -# For repl startup -precompile(Base.yieldto, (Task, Int)) -precompile(Base.open, (String, Bool, Bool, Bool, Bool, Bool)) -precompile(Base.setindex!, (Base.Dict{Any, Any}, Char, Char)) -precompile(Base.setindex!, (Base.Dict{Any, Any}, Char, String)) -precompile(Base.in, (String, Array{Any, 1})) -precompile(Base.getindex, (Base.Dict{Any, Any}, String)) -precompile(Base.LineEdit.setup_prefix_keymap, (Base.REPL.REPLHistoryProvider, Base.LineEdit.Prompt)) -precompile(Base.convert, (Type{Any}, Base.Dict{Char, Any})) -precompile(Base.REPL.mode_keymap, (Base.LineEdit.Prompt,)) -precompile(Base.promote_type, (Type{Base.LineEdit.Prompt}, Type{Base.LineEdit.HistoryPrompt{Base.REPL.REPLHistoryProvider}}, Type)) -precompile(Base.promote_type, (Type{Base.LineEdit.HistoryPrompt{Base.REPL.REPLHistoryProvider}}, Type{Base.LineEdit.PrefixHistoryPrompt{Base.REPL.REPLHistoryProvider}})) -precompile(Base.similar, (Array{Base.LineEdit.Prompt, 1}, Type{Base.LineEdit.TextInterface}, Tuple{Int64})) -precompile(Base.setindex!, (Array{Base.LineEdit.TextInterface, 1}, Base.LineEdit.PrefixHistoryPrompt{Base.REPL.REPLHistoryProvider}, Base.UnitRange{Int64})) -precompile(Base.LineEdit.init_state, (Base.Terminals.TTYTerminal, Base.LineEdit.PrefixHistoryPrompt{Base.REPL.REPLHistoryProvider})) -precompile(Base.setindex!, (Base.Dict{Any, Any}, Base.LineEdit.PrefixSearchState, Base.LineEdit.PrefixHistoryPrompt{Base.REPL.REPLHistoryProvider})) -precompile(Base.get, (Base.Dict{Any, Any}, Tuple{Int64, Int64}, Bool)) -precompile(Base.LineEdit.refresh_multi_line, (Array{Any, 1}, Base.Terminals.TerminalBuffer, Base.Terminals.TTYTerminal, Base.IOBuffer, Base.LineEdit.InputAreaState, Base.LineEdit.PromptState)) -precompile(Base.schedule, (Array{Any, 1}, Task, Void)) -precompile(Base.LineEdit.match_input, (Function, Base.LineEdit.MIState, Base.Terminals.TTYTerminal, Array{Char, 1}, Base.Dict{Char, Any})) -precompile(==, (Base.Distributed.RemoteChannel, WeakRef)) -precompile(==, (Base.Distributed.RemoteChannel, Base.Distributed.RemoteChannel)) -precompile(Base.Distributed.send_del_client, (Base.Distributed.RemoteChannel,)) -precompile(!=, (Base.SubString{String}, String)) -precompile(Base.join, (Base.IOBuffer, Array{Base.SubString{String}, 1}, String)) -precompile(Base.joinpath, (String, String, String, String)) -precompile(Base.string, (String, String, Char)) -precompile(Base.string, (String, String, Int)) -precompile(Base.vect, (Base.LineEdit.Prompt, String)) - -# Speed up type inference in the post-Base world redefinition of convert -isdefined(Core, :Inference) && Base.code_typed(Base.code_typed) - -# Speeding up addprocs for LocalManager -precompile(Base.Distributed.start_worker, ()) -precompile(Base.Distributed.start_worker, (Base.TTY,)) -precompile(Base.Distributed.process_messages, (Base.TCPSocket, Base.TCPSocket)) -precompile(Base.Distributed.process_messages, (Base.TCPSocket, Base.TCPSocket, Void)) -precompile(Base.Distributed.process_tcp_streams, (Base.TCPSocket, Base.TCPSocket, Void)) -precompile(Base.Distributed.message_handler_loop, (Base.TCPSocket, Base.TCPSocket, Void)) -precompile(Base.Distributed.connect_to_peer, (Base.Distributed.LocalManager, Int64, Base.Distributed.WorkerConfig)) -precompile(Base.Distributed.connect, (Base.Distributed.LocalManager, Int64, Base.Distributed.WorkerConfig)) -precompile(Base.Distributed.connect_w2w, (Int64, Base.Distributed.WorkerConfig)) -precompile(Base.Distributed.connect_to_worker, (String, Int64)) -precompile(Base.Distributed.addprocs, (Base.Distributed.LocalManager, )) -precompile(Base.Distributed.addprocs, (Int, )) -precompile(Base.Distributed.setup_launched_worker, (Base.Distributed.LocalManager, Dict, Base.Distributed.WorkerConfig, Array{Int,1})) -precompile(Base.Distributed.create_worker, (Base.Distributed.LocalManager, Dict, Base.Distributed.WorkerConfig)) -precompile(Base.Distributed.launch, (Base.Distributed.LocalManager, Dict, Array{Base.Distributed.WorkerConfig, 1}, Base.Condition)) -precompile(Base.Distributed.set_valid_processes, (Array{Int, 1}, )) - -# Speed up repl help -sprint(Markdown.term, @doc mean) -sprint(Docs.repl_search, "mean") -sprint(Docs.repl_corrections, "meen") - -# Speed up repl completions -Base.REPLCompletions.completions("IOBuffer().",11) -Base.REPLCompletions.completions("max([1],",8) +precompile(Tuple{typeof(Base.pointer), Array{UInt8, 1}, UInt64}) +precompile(Tuple{typeof(Base.convert), Type{Ptr{Int32}}, Ptr{UInt8}}) +precompile(Tuple{typeof(Base.SparseArrays.CHOLMOD.set_print_level), Array{UInt8, 1}, Int64}) +precompile(Tuple{Type{Base.Multimedia.TextDisplay}, Base.TTY}) +precompile(Tuple{typeof(Base._start)}) +precompile(Tuple{typeof(Base.copy!), Array{String, 1}, Int64, Array{Any, 1}, Int64, Int64}) +precompile(Tuple{typeof(Base.empty!), Base.Dict{Int64, Union{Base.Distributed.Worker, Base.Distributed.LocalProcess}}}) +precompile(Tuple{typeof(Core.Inference.isbits), Base.Distributed.DefaultClusterManager}) +precompile(Tuple{typeof(Base.Distributed.init_worker), String, Base.Distributed.DefaultClusterManager}) +precompile(Tuple{typeof(Base.finalizer), Base.TCPServer, typeof(Base.uvfinalize)}) +precompile(Tuple{Type{Base.TCPServer}, Ptr{Void}, Int64}) +precompile(Tuple{typeof(Base.show), Base.IOContext{Base.AbstractIOBuffer{Array{UInt8, 1}}}, Int32}) +precompile(Tuple{typeof(Base.print), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.Libc.RawFD}) +precompile(Tuple{typeof(Base.uv_status_string), Base.TCPServer}) +precompile(Tuple{typeof(Base._fd), Base.TCPServer}) +precompile(Tuple{typeof(Base.print), Base.AbstractIOBuffer{Array{UInt8, 1}}, Type{Base.TCPServer}, String, Base.Libc.RawFD, String, String, String}) +precompile(Tuple{typeof(Base.print), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.TCPServer}) +precompile(Tuple{typeof(Base.isopen), Base.TCPServer}) +precompile(Tuple{typeof(Base.check_open), Base.TCPServer}) +precompile(Tuple{typeof(Base.unpreserve_handle), Base.TCPServer}) +precompile(Tuple{typeof(Base.stream_wait), Base.TCPServer, Base.Condition}) +precompile(Tuple{Type{Base.TCPServer}}) +precompile(Tuple{typeof(Base.close), Base.TCPServer}) +precompile(Tuple{getfield(Base, Symbol("#kw##listen")), Array{Any, 1}, typeof(Base.listen), Base.TCPServer}) +precompile(Tuple{getfield(Base, Symbol("#kw##listen")), Array{Any, 1}, typeof(Base.listen), Base.InetAddr{Base.IPv4}}) +precompile(Tuple{typeof(Base.ndigits0z), UInt16}) +precompile(Tuple{typeof(Base.dec), UInt16, Int64, Bool}) +precompile(Tuple{typeof(Base.Libc.strerror), Int32}) +precompile(Tuple{typeof(Base.copy!), Array{Any, 1}, Base.KeyIterator{Base.Dict{Any, Any}}}) +precompile(Tuple{typeof(Base.promoteK), Type{Any}}) +precompile(Tuple{typeof(Core.Inference.length), Tuple{Core.Inference.Const, DataType, Core.Inference.Const, Core.Inference.Const}}) +precompile(Tuple{typeof(Core.Inference.getindex), Tuple{Core.Inference.Const, DataType, Core.Inference.Const, Core.Inference.Const}, Int64}) +precompile(Tuple{typeof(Base.sync_add), Task}) +precompile(Tuple{typeof(Core.Inference.getindex), Tuple{Int64, Tuple{Int64, Tuple{}}}, Int64}) +precompile(Tuple{typeof(Base.Distributed.local_remotecall_thunk), typeof(Base.Distributed.set_valid_processes), Tuple{Array{Int64, 1}}, Array{Any, 1}}) +precompile(Tuple{typeof(Base.Distributed.remote_do), typeof(Base.Distributed.set_valid_processes), Base.Distributed.Worker, Array{Int64, 1}}) +precompile(Tuple{typeof(Base.Distributed.remote_do), typeof(Base.Distributed.set_valid_processes), Base.Distributed.LocalProcess, Array{Int64, 1}}) +precompile(Tuple{getfield(Base.Distributed, Symbol("#kw##remote_do")), Array{Any, 1}, typeof(Base.Distributed.remote_do), typeof(Base.Distributed.set_valid_processes), Base.Distributed.Worker, Array{Int64, 1}}) +precompile(Tuple{getfield(Base.Distributed, Symbol("#kw##remote_do")), Array{Any, 1}, typeof(Base.Distributed.remote_do), typeof(Base.Distributed.set_valid_processes), Base.Distributed.LocalProcess, Array{Int64, 1}}) +precompile(Tuple{typeof(Base.Sort.Float.isnan), Base.Order.ForwardOrdering, Float32}) +precompile(Tuple{typeof(Base.Sort.Float.isnan), Base.Order.ForwardOrdering, Float64}) +precompile(Tuple{typeof(Base.Sort.Float.isnan), Base.Order.ReverseOrdering{Base.Order.ForwardOrdering}, Float32}) +precompile(Tuple{typeof(Base.Sort.Float.isnan), Base.Order.ReverseOrdering{Base.Order.ForwardOrdering}, Float64}) +precompile(Tuple{typeof(Base.Sort.Float.issignleft), Base.Order.ForwardOrdering, Float32}) +precompile(Tuple{typeof(Base.Sort.Float.issignleft), Base.Order.ReverseOrdering{Base.Order.ForwardOrdering}, Float32}) +precompile(Tuple{typeof(Base.Sort.Float.issignleft), Base.Order.ForwardOrdering, Float64}) +precompile(Tuple{typeof(Base.Sort.Float.issignleft), Base.Order.ReverseOrdering{Base.Order.ForwardOrdering}, Float64}) +precompile(Tuple{typeof(Core.Inference.isbits), Base.Sort.Float.Left}) +precompile(Tuple{typeof(Base.Sort.Float.left), Base.Order.ForwardOrdering}) +precompile(Tuple{typeof(Base.Sort.Float.left), Base.Order.ReverseOrdering{Base.Order.ForwardOrdering}}) +precompile(Tuple{typeof(Core.Inference.isbits), Base.Sort.Float.Right}) +precompile(Tuple{typeof(Base.Sort.Float.right), Base.Order.ForwardOrdering}) +precompile(Tuple{typeof(Base.Sort.Float.right), Base.Order.ReverseOrdering{Base.Order.ForwardOrdering}}) +precompile(Tuple{typeof(Base.stat), Int64}) +precompile(Tuple{typeof(Base.readbytes_all!), Base.IOStream, Array{UInt8, 1}, Int64}) +precompile(Tuple{typeof(Base.read), Base.IOStream}) +precompile(Tuple{typeof(Base.open), typeof(Base.readstring), String}) +precompile(Tuple{typeof(Base.rstrip), Base.SubString{String}, Array{Char, 1}}) +precompile(Tuple{typeof(Base.lstrip), Base.SubString{String}, Array{Char, 1}}) +precompile(Tuple{getfield(Base, Symbol("#kw##split")), Array{Any, 1}, typeof(Base.split), String, Char}) +precompile(Tuple{getfield(Base, Symbol("#kw##split")), Array{Any, 1}, typeof(Base.split), Base.SubString{String}, Char}) +precompile(Tuple{typeof(Base.map!), typeof(Base.strip), Array{Base.SubString{String}, 1}, Array{Base.SubString{String}, 1}}) +precompile(Tuple{typeof(Base.UTF8proc.isnumber), Base.SubString{String}}) +precompile(Tuple{Type{Core.Inference.Generator{I, F} where F where I}, Type{Core.Inference.Const}, Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}}) +precompile(Tuple{Type{Core.Inference.Generator{Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}, Type{Core.Inference.Const}}}, Type{Core.Inference.Const}, Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}}) +precompile(Tuple{typeof(Core.Inference.convert), Type{Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}}, Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}}) +precompile(Tuple{typeof(Core.Inference.collect), Type{Any}, Core.Inference.Generator{Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.iteratorsize), Core.Inference.Generator{Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.iteratorsize), Type{Core.Inference.Generator{Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}, Type{Core.Inference.Const}}}}) +precompile(Tuple{typeof(Core.Inference.iteratorsize), Type{Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}}}) +precompile(Tuple{typeof(Core.Inference._collect), Type{Any}, Core.Inference.Generator{Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}, Type{Core.Inference.Const}}, Core.Inference.HasLength}) +precompile(Tuple{typeof(Core.Inference.length), Core.Inference.Generator{Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.length), Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}}) +precompile(Tuple{typeof(Core.Inference.copy!), Array{Any, 1}, Core.Inference.Generator{Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.start), Core.Inference.Generator{Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.start), Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}}) +precompile(Tuple{typeof(Core.Inference.done), Core.Inference.Generator{Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}, Type{Core.Inference.Const}}, Int64}) +precompile(Tuple{typeof(Core.Inference.done), Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}, Int64}) +precompile(Tuple{typeof(Core.Inference.next), Core.Inference.Generator{Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}, Type{Core.Inference.Const}}, Int64}) +precompile(Tuple{typeof(Core.Inference.next), Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}, Int64}) +precompile(Tuple{typeof(Core.Inference.getindex), Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}, Int64}) +precompile(Tuple{typeof(Core.Inference.start), Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}, Int64}}) +precompile(Tuple{typeof(Core.Inference.indexed_next), Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}, Int64}, Int64, Int64}) +precompile(Tuple{typeof(Core.Inference.getindex), Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}, Int64}, Int64}) +precompile(Tuple{typeof(Core.Inference.isbits), Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}) +precompile(Tuple{typeof(Core.Inference.isbits), Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}}) +precompile(Tuple{Type{Core.Inference.Generator{I, F} where F where I}, Type{QuoteNode}, Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}}) +precompile(Tuple{Type{Core.Inference.Generator{Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}, Type{QuoteNode}}}, Type{QuoteNode}, Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}}) +precompile(Tuple{typeof(Core.Inference.iteratorsize), Type{Core.Inference.Generator{Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}, Type{QuoteNode}}}}) +precompile(Tuple{typeof(Core.Inference._collect), Type{Any}, Core.Inference.Generator{Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}, Type{QuoteNode}}, Core.Inference.HasLength}) +precompile(Tuple{typeof(Core.Inference.length), Core.Inference.Generator{Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}, Type{QuoteNode}}}) +precompile(Tuple{typeof(Core.Inference.copy!), Array{Any, 1}, Core.Inference.Generator{Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}, Type{QuoteNode}}}) +precompile(Tuple{typeof(Core.Inference.start), Core.Inference.Generator{Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}, Type{QuoteNode}}}) +precompile(Tuple{typeof(Core.Inference.done), Core.Inference.Generator{Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}, Type{QuoteNode}}, Int64}) +precompile(Tuple{typeof(Core.Inference.next), Core.Inference.Generator{Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}, Type{QuoteNode}}, Int64}) +precompile(Tuple{typeof(Core.Inference.isbits), Base.DevNullStream}) +precompile(Tuple{typeof(Base.finalizer), Base.Process, typeof(Base.uvfinalize)}) +precompile(Tuple{typeof(Core.Inference.isbits), Tuple{Base.DevNullStream, Bool}}) +precompile(Tuple{Type{Ref{Base.Cstring}}, Array{String, 1}}) +precompile(Tuple{typeof(Core.Inference.eltype), Type{Array{String, 1}}}) +precompile(Tuple{typeof(Base.string), Void, String, DataType}) +precompile(Tuple{typeof(Base.print), Base.IOContext{Base.AbstractIOBuffer{Array{UInt8, 1}}}, String, Char}) +precompile(Tuple{typeof(Base.throw_boundserror), Base.UnitRange{Int64}, Tuple{Base.UnitRange{Int64}}}) +precompile(Tuple{typeof(Core.Inference.convert), Type{DataType}, Type{Bool}}) +precompile(Tuple{typeof(Core.Inference.convert), Type{DataType}, Type{Base.OneTo{Int64}}}) +precompile(Tuple{typeof(Core.Inference.length), Tuple{DataType, DataType, typeof(Type), Core.Inference.Const, Core.Inference.Const}}) +precompile(Tuple{typeof(Core.Inference.getindex), Tuple{DataType, DataType, typeof(Type), Core.Inference.Const, Core.Inference.Const}, Int64}) +precompile(Tuple{Type{Core.Inference.Generator{I, F} where F where I}, Type{Core.Inference.Const}, Tuple{Tuple{}, Tuple{}, Int64}}) +precompile(Tuple{Type{Core.Inference.Generator{Tuple{Tuple{}, Tuple{}, Int64}, Type{Core.Inference.Const}}}, Type{Core.Inference.Const}, Tuple{Tuple{}, Tuple{}, Int64}}) +precompile(Tuple{typeof(Core.Inference.convert), Type{Tuple{Tuple{}, Tuple{}, Int64}}, Tuple{Tuple{}, Tuple{}, Int64}}) +precompile(Tuple{typeof(Core.Inference.collect), Type{Any}, Core.Inference.Generator{Tuple{Tuple{}, Tuple{}, Int64}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.iteratorsize), Core.Inference.Generator{Tuple{Tuple{}, Tuple{}, Int64}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.iteratorsize), Type{Core.Inference.Generator{Tuple{Tuple{}, Tuple{}, Int64}, Type{Core.Inference.Const}}}}) +precompile(Tuple{typeof(Core.Inference.iteratorsize), Type{Tuple{Tuple{}, Tuple{}, Int64}}}) +precompile(Tuple{typeof(Core.Inference._collect), Type{Any}, Core.Inference.Generator{Tuple{Tuple{}, Tuple{}, Int64}, Type{Core.Inference.Const}}, Core.Inference.HasLength}) +precompile(Tuple{typeof(Core.Inference.length), Core.Inference.Generator{Tuple{Tuple{}, Tuple{}, Int64}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.length), Tuple{Tuple{}, Tuple{}, Int64}}) +precompile(Tuple{typeof(Core.Inference.copy!), Array{Any, 1}, Core.Inference.Generator{Tuple{Tuple{}, Tuple{}, Int64}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.start), Core.Inference.Generator{Tuple{Tuple{}, Tuple{}, Int64}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.start), Tuple{Tuple{}, Tuple{}, Int64}}) +precompile(Tuple{typeof(Core.Inference.done), Core.Inference.Generator{Tuple{Tuple{}, Tuple{}, Int64}, Type{Core.Inference.Const}}, Int64}) +precompile(Tuple{typeof(Core.Inference.done), Tuple{Tuple{}, Tuple{}, Int64}, Int64}) +precompile(Tuple{typeof(Core.Inference.next), Core.Inference.Generator{Tuple{Tuple{}, Tuple{}, Int64}, Type{Core.Inference.Const}}, Int64}) +precompile(Tuple{typeof(Core.Inference.next), Tuple{Tuple{}, Tuple{}, Int64}, Int64}) +precompile(Tuple{typeof(Core.Inference.getindex), Tuple{Tuple{}, Tuple{}, Int64}, Int64}) +precompile(Tuple{typeof(Core.Inference.isbits), Tuple{Tuple{}, Tuple{}, Int64}}) +precompile(Tuple{Type{Core.Inference.Generator{I, F} where F where I}, Type{QuoteNode}, Tuple{Tuple{}, Tuple{}, Int64}}) +precompile(Tuple{Type{Core.Inference.Generator{Tuple{Tuple{}, Tuple{}, Int64}, Type{QuoteNode}}}, Type{QuoteNode}, Tuple{Tuple{}, Tuple{}, Int64}}) +precompile(Tuple{typeof(Core.Inference.iteratorsize), Type{Core.Inference.Generator{Tuple{Tuple{}, Tuple{}, Int64}, Type{QuoteNode}}}}) +precompile(Tuple{typeof(Core.Inference._collect), Type{Any}, Core.Inference.Generator{Tuple{Tuple{}, Tuple{}, Int64}, Type{QuoteNode}}, Core.Inference.HasLength}) +precompile(Tuple{typeof(Core.Inference.length), Core.Inference.Generator{Tuple{Tuple{}, Tuple{}, Int64}, Type{QuoteNode}}}) +precompile(Tuple{typeof(Core.Inference.copy!), Array{Any, 1}, Core.Inference.Generator{Tuple{Tuple{}, Tuple{}, Int64}, Type{QuoteNode}}}) +precompile(Tuple{typeof(Core.Inference.start), Core.Inference.Generator{Tuple{Tuple{}, Tuple{}, Int64}, Type{QuoteNode}}}) +precompile(Tuple{typeof(Core.Inference.done), Core.Inference.Generator{Tuple{Tuple{}, Tuple{}, Int64}, Type{QuoteNode}}, Int64}) +precompile(Tuple{typeof(Core.Inference.next), Core.Inference.Generator{Tuple{Tuple{}, Tuple{}, Int64}, Type{QuoteNode}}, Int64}) +precompile(Tuple{Type{Core.Inference.Generator{I, F} where F where I}, Type{Core.Inference.Const}, Tuple{Tuple{}, Tuple{}}}) +precompile(Tuple{Type{Core.Inference.Generator{Tuple{Tuple{}, Tuple{}}, Type{Core.Inference.Const}}}, Type{Core.Inference.Const}, Tuple{Tuple{}, Tuple{}}}) +precompile(Tuple{typeof(Core.Inference.convert), Type{Tuple{Tuple{}, Tuple{}}}, Tuple{Tuple{}, Tuple{}}}) +precompile(Tuple{typeof(Core.Inference.collect), Type{Any}, Core.Inference.Generator{Tuple{Tuple{}, Tuple{}}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.iteratorsize), Core.Inference.Generator{Tuple{Tuple{}, Tuple{}}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.iteratorsize), Type{Core.Inference.Generator{Tuple{Tuple{}, Tuple{}}, Type{Core.Inference.Const}}}}) +precompile(Tuple{typeof(Core.Inference.iteratorsize), Type{Tuple{Tuple{}, Tuple{}}}}) +precompile(Tuple{typeof(Core.Inference._collect), Type{Any}, Core.Inference.Generator{Tuple{Tuple{}, Tuple{}}, Type{Core.Inference.Const}}, Core.Inference.HasLength}) +precompile(Tuple{typeof(Core.Inference.length), Core.Inference.Generator{Tuple{Tuple{}, Tuple{}}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.length), Tuple{Tuple{}, Tuple{}}}) +precompile(Tuple{typeof(Core.Inference.copy!), Array{Any, 1}, Core.Inference.Generator{Tuple{Tuple{}, Tuple{}}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.start), Core.Inference.Generator{Tuple{Tuple{}, Tuple{}}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.start), Tuple{Tuple{}, Tuple{}}}) +precompile(Tuple{typeof(Core.Inference.done), Core.Inference.Generator{Tuple{Tuple{}, Tuple{}}, Type{Core.Inference.Const}}, Int64}) +precompile(Tuple{typeof(Core.Inference.done), Tuple{Tuple{}, Tuple{}}, Int64}) +precompile(Tuple{typeof(Core.Inference.next), Core.Inference.Generator{Tuple{Tuple{}, Tuple{}}, Type{Core.Inference.Const}}, Int64}) +precompile(Tuple{typeof(Core.Inference.next), Tuple{Tuple{}, Tuple{}}, Int64}) +precompile(Tuple{typeof(Core.Inference.getindex), Tuple{Tuple{}, Tuple{}}, Int64}) +precompile(Tuple{Type{Core.Inference.Generator{I, F} where F where I}, Type{QuoteNode}, Tuple{Tuple{}, Tuple{}}}) +precompile(Tuple{Type{Core.Inference.Generator{Tuple{Tuple{}, Tuple{}}, Type{QuoteNode}}}, Type{QuoteNode}, Tuple{Tuple{}, Tuple{}}}) +precompile(Tuple{typeof(Core.Inference.iteratorsize), Type{Core.Inference.Generator{Tuple{Tuple{}, Tuple{}}, Type{QuoteNode}}}}) +precompile(Tuple{typeof(Core.Inference._collect), Type{Any}, Core.Inference.Generator{Tuple{Tuple{}, Tuple{}}, Type{QuoteNode}}, Core.Inference.HasLength}) +precompile(Tuple{typeof(Core.Inference.length), Core.Inference.Generator{Tuple{Tuple{}, Tuple{}}, Type{QuoteNode}}}) +precompile(Tuple{typeof(Core.Inference.copy!), Array{Any, 1}, Core.Inference.Generator{Tuple{Tuple{}, Tuple{}}, Type{QuoteNode}}}) +precompile(Tuple{typeof(Core.Inference.start), Core.Inference.Generator{Tuple{Tuple{}, Tuple{}}, Type{QuoteNode}}}) +precompile(Tuple{typeof(Core.Inference.done), Core.Inference.Generator{Tuple{Tuple{}, Tuple{}}, Type{QuoteNode}}, Int64}) +precompile(Tuple{typeof(Core.Inference.next), Core.Inference.Generator{Tuple{Tuple{}, Tuple{}}, Type{QuoteNode}}, Int64}) +precompile(Tuple{typeof(Core.Inference.length), Tuple{DataType, DataType, DataType, Core.Inference.Const, Core.Inference.Const}}) +precompile(Tuple{typeof(Core.Inference.getindex), Tuple{DataType, DataType, DataType, Core.Inference.Const, Core.Inference.Const}, Int64}) +precompile(Tuple{typeof(Core.Inference.length), Tuple{DataType, DataType, typeof(Type), typeof(Type), Core.Inference.Const}}) +precompile(Tuple{typeof(Core.Inference.getindex), Tuple{DataType, DataType, typeof(Type), typeof(Type), Core.Inference.Const}, Int64}) +precompile(Tuple{typeof(Core.Inference.length), Tuple{DataType, DataType, DataType, DataType, Core.Inference.Const}}) +precompile(Tuple{typeof(Core.Inference.getindex), Tuple{DataType, DataType, DataType, DataType, Core.Inference.Const}, Int64}) +precompile(Tuple{typeof(Base.unpreserve_handle), Base.Process}) +precompile(Tuple{typeof(Base.stream_wait), Base.Process, Base.Condition}) +precompile(Tuple{typeof(Base.kill), Base.Process, Int64}) +precompile(Tuple{typeof(Base.banner), Base.Terminals.TTYTerminal}) +precompile(Tuple{typeof(Core.Inference.isbits), Base.Dict{Any, Any}}) +precompile(Tuple{typeof(Base.answer_color)}) +precompile(Tuple{typeof(Base.input_color)}) +precompile(Tuple{typeof(Base.show_circular), Base.IOContext{Base.AbstractIOBuffer{Array{UInt8, 1}}}, Tuple{}}) +precompile(Tuple{typeof(Base.show_delim_array), Base.IOContext{Base.AbstractIOBuffer{Array{UInt8, 1}}}, Tuple{}, Char, Char, Char, Bool, Int64, Int64}) +precompile(Tuple{typeof(Base.throw_boundserror), Array{Base.StackTraces.StackFrame, 1}, Tuple{Base.UnitRange{Int64}}}) +precompile(Tuple{typeof(Base.splice!), Array{Base.StackTraces.StackFrame, 1}, Base.UnitRange{Int64}, Array{Any, 1}}) +precompile(Tuple{typeof(Base.REPL.ip_matches_func), Ptr{Void}, Symbol}) +precompile(Tuple{typeof(Base.throw_boundserror), Array{Ptr{Void}, 1}, Tuple{Base.UnitRange{Int64}}}) +precompile(Tuple{typeof(Base.unsafe_copy!), Array{Ptr{Void}, 1}, Int64, Array{Ptr{Void}, 1}, Int64, Int64}) +precompile(Tuple{Type{Base.Channel{Any}}, Int64}) +precompile(Tuple{typeof(Base.rsearch), String, UInt8, Int64}) +precompile(Tuple{typeof(Base.rsearch), String, Char, Int64}) +precompile(Tuple{typeof(Base.rsearch), Array{UInt8, 1}, UInt8, Int64}) +precompile(Tuple{typeof(Base._rsearchindex), Array{UInt8, 1}, Array{UInt8, 1}, Int64}) +precompile(Tuple{typeof(Base._rsearch), Array{UInt8, 1}, Array{UInt8, 1}, Int64}) +precompile(Tuple{typeof(Base.rsearch), Array{Int8, 1}, UInt8, Int64}) +precompile(Tuple{typeof(Base._rsearchindex), Array{Int8, 1}, Array{UInt8, 1}, Int64}) +precompile(Tuple{typeof(Base._rsearch), Array{Int8, 1}, Array{UInt8, 1}, Int64}) +precompile(Tuple{typeof(Base.rsearch), Array{UInt8, 1}, Char, Int64}) +precompile(Tuple{typeof(Base.rsearch), Array{Int8, 1}, Char, Int64}) +precompile(Tuple{typeof(Base.splice!), Array{Base.Multimedia.Display, 1}, Int64, Array{Any, 1}}) +precompile(Tuple{typeof(Core.Inference.isbits), Base.LineEdit.EmptyCompletionProvider}) +precompile(Tuple{typeof(Core.Inference.isbits), Base.LineEdit.EmptyHistoryProvider}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Symbol, Any}, Base.LineEdit.Prompt, Symbol, Int64}) +precompile(Tuple{typeof(Base.sizehint!), Base.Dict{Symbol, Any}, Int64}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Symbol, Any}, Base.LineEdit.Prompt, Symbol}) +precompile(Tuple{typeof(Base.copy!), Base.IndexLinear, Array{Symbol, 1}, Base.IndexLinear, Array{UInt8, 1}}) +precompile(Tuple{getfield(Base, Symbol("#kw##readline")), Array{Any, 1}, typeof(Base.readline), Base.IOStream}) +precompile(Tuple{Type{Core.Inference.Generator{I, F} where F where I}, Type{Core.Inference.Const}, Tuple{Void}}) +precompile(Tuple{Type{Core.Inference.Generator{Tuple{Void}, Type{Core.Inference.Const}}}, Type{Core.Inference.Const}, Tuple{Void}}) +precompile(Tuple{typeof(Core.Inference.convert), Type{Tuple{Void}}, Tuple{Void}}) +precompile(Tuple{typeof(Core.Inference.collect), Type{Any}, Core.Inference.Generator{Tuple{Void}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.iteratorsize), Core.Inference.Generator{Tuple{Void}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.iteratorsize), Type{Core.Inference.Generator{Tuple{Void}, Type{Core.Inference.Const}}}}) +precompile(Tuple{typeof(Core.Inference.iteratorsize), Type{Tuple{Void}}}) +precompile(Tuple{typeof(Core.Inference._collect), Type{Any}, Core.Inference.Generator{Tuple{Void}, Type{Core.Inference.Const}}, Core.Inference.HasLength}) +precompile(Tuple{typeof(Core.Inference.length), Core.Inference.Generator{Tuple{Void}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.length), Tuple{Void}}) +precompile(Tuple{typeof(Core.Inference.copy!), Array{Any, 1}, Core.Inference.Generator{Tuple{Void}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.start), Core.Inference.Generator{Tuple{Void}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.start), Tuple{Void}}) +precompile(Tuple{typeof(Core.Inference.done), Core.Inference.Generator{Tuple{Void}, Type{Core.Inference.Const}}, Int64}) +precompile(Tuple{typeof(Core.Inference.done), Tuple{Void}, Int64}) +precompile(Tuple{typeof(Core.Inference.next), Core.Inference.Generator{Tuple{Void}, Type{Core.Inference.Const}}, Int64}) +precompile(Tuple{typeof(Core.Inference.next), Tuple{Void}, Int64}) +precompile(Tuple{typeof(Core.Inference.getindex), Tuple{Void}, Int64}) +precompile(Tuple{typeof(Base.join), Base.AbstractIOBuffer{Array{UInt8, 1}}, Array{String, 1}, Char}) +precompile(Tuple{Type{Core.Inference.Generator{I, F} where F where I}, Type{Core.Inference.Const}, Tuple{String, typeof(Base.info)}}) +precompile(Tuple{Type{Core.Inference.Generator{Tuple{String, typeof(Base.info)}, Type{Core.Inference.Const}}}, Type{Core.Inference.Const}, Tuple{String, typeof(Base.info)}}) +precompile(Tuple{typeof(Core.Inference.convert), Type{Tuple{String, typeof(Base.info)}}, Tuple{String, typeof(Base.info)}}) +precompile(Tuple{typeof(Core.Inference.collect), Type{Any}, Core.Inference.Generator{Tuple{String, typeof(Base.info)}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.iteratorsize), Core.Inference.Generator{Tuple{String, typeof(Base.info)}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.iteratorsize), Type{Core.Inference.Generator{Tuple{String, typeof(Base.info)}, Type{Core.Inference.Const}}}}) +precompile(Tuple{typeof(Core.Inference.iteratorsize), Type{Tuple{String, typeof(Base.info)}}}) +precompile(Tuple{typeof(Core.Inference._collect), Type{Any}, Core.Inference.Generator{Tuple{String, typeof(Base.info)}, Type{Core.Inference.Const}}, Core.Inference.HasLength}) +precompile(Tuple{typeof(Core.Inference.length), Core.Inference.Generator{Tuple{String, typeof(Base.info)}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.length), Tuple{String, typeof(Base.info)}}) +precompile(Tuple{typeof(Core.Inference.copy!), Array{Any, 1}, Core.Inference.Generator{Tuple{String, typeof(Base.info)}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.start), Core.Inference.Generator{Tuple{String, typeof(Base.info)}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.start), Tuple{String, typeof(Base.info)}}) +precompile(Tuple{typeof(Core.Inference.done), Core.Inference.Generator{Tuple{String, typeof(Base.info)}, Type{Core.Inference.Const}}, Int64}) +precompile(Tuple{typeof(Core.Inference.done), Tuple{String, typeof(Base.info)}, Int64}) +precompile(Tuple{typeof(Core.Inference.next), Core.Inference.Generator{Tuple{String, typeof(Base.info)}, Type{Core.Inference.Const}}, Int64}) +precompile(Tuple{typeof(Core.Inference.next), Tuple{String, typeof(Base.info)}, Int64}) +precompile(Tuple{typeof(Core.Inference.getindex), Tuple{String, typeof(Base.info)}, Int64}) +precompile(Tuple{typeof(Core.Inference.start), Tuple{String, Int64}}) +precompile(Tuple{typeof(Core.Inference.start), Tuple{typeof(Base.info), Int64}}) +precompile(Tuple{typeof(Core.Inference.indexed_next), Tuple{typeof(Base.info), Int64}, Int64, Int64}) +precompile(Tuple{typeof(Core.Inference.getindex), Tuple{typeof(Base.info), Int64}, Int64}) +precompile(Tuple{typeof(Base.print), Base.IOContext{Base.AbstractIOBuffer{Array{UInt8, 1}}}, Base.SubString{String}, Char}) +precompile(Tuple{typeof(Base.sizehint!), Base.Dict{Any, Any}, Int64}) +precompile(Tuple{typeof(Base.LineEdit.getEntry), Base.Dict{Char, Any}, Char}) +precompile(Tuple{typeof(Base.LineEdit.getEntry), Base.Dict{Char, Any}, String}) +precompile(Tuple{typeof(Base.unsafe_copy!), Array{Base.Dict{Any, Any}, 1}, Int64, Array{Base.Dict{Any, Any}, 1}, Int64, Int64}) +precompile(Tuple{typeof(Base.copy!), Array{Base.Dict{Any, Any}, 1}, Int64, Array{Base.Dict{Any, Any}, 1}, Int64, Int64}) +precompile(Tuple{typeof(Base.promote_type), Type{Base.LineEdit.HistoryPrompt{Base.REPL.REPLHistoryProvider}}, Type{Base.LineEdit.PrefixHistoryPrompt{Base.REPL.REPLHistoryProvider}}}) +precompile(Tuple{typeof(Base.promote_rule), Type{Base.LineEdit.HistoryPrompt{Base.REPL.REPLHistoryProvider}}, Type{Base.LineEdit.PrefixHistoryPrompt{Base.REPL.REPLHistoryProvider}}}) +precompile(Tuple{typeof(Base.promote_rule), Type{Base.LineEdit.PrefixHistoryPrompt{Base.REPL.REPLHistoryProvider}}, Type{Base.LineEdit.HistoryPrompt{Base.REPL.REPLHistoryProvider}}}) +precompile(Tuple{typeof(Base.promote_result), Type{Base.LineEdit.HistoryPrompt{Base.REPL.REPLHistoryProvider}}, Type{Base.LineEdit.PrefixHistoryPrompt{Base.REPL.REPLHistoryProvider}}, Type{Union{}}, Type{Union{}}}) +precompile(Tuple{typeof(Base.promote_type), Type{Base.LineEdit.Prompt}, Type{Base.LineEdit.TextInterface}}) +precompile(Tuple{typeof(Base.promote_rule), Type{Base.LineEdit.Prompt}, Type{Base.LineEdit.TextInterface}}) +precompile(Tuple{typeof(Base.promote_rule), Type{Base.LineEdit.TextInterface}, Type{Base.LineEdit.Prompt}}) +precompile(Tuple{typeof(Base.promote_result), Type{Base.LineEdit.Prompt}, Type{Base.LineEdit.TextInterface}, Type{Union{}}, Type{Union{}}}) +precompile(Tuple{typeof(Base.setindex!), Array{Base.LineEdit.TextInterface, 1}, Base.LineEdit.Prompt, Int64}) +precompile(Tuple{typeof(Base.setindex!), Array{Base.LineEdit.TextInterface, 1}, Base.LineEdit.HistoryPrompt{Base.REPL.REPLHistoryProvider}, Int64}) +precompile(Tuple{typeof(Base.setindex!), Array{Base.LineEdit.TextInterface, 1}, Base.LineEdit.PrefixHistoryPrompt{Base.REPL.REPLHistoryProvider}, Int64}) +precompile(Tuple{typeof(Base.copy!), Array{Base.LineEdit.TextInterface, 1}, Tuple{Base.LineEdit.Prompt, Base.LineEdit.Prompt, Base.LineEdit.Prompt, Base.LineEdit.HistoryPrompt{Base.REPL.REPLHistoryProvider}, Base.LineEdit.PrefixHistoryPrompt{Base.REPL.REPLHistoryProvider}}}) +precompile(Tuple{typeof(Base.print), Base.AbstractIOBuffer{Array{UInt8, 1}}, String, Int64, String, Bool}) +precompile(Tuple{typeof(Base.uv_status_string), Base.UDPSocket}) +precompile(Tuple{typeof(Base.Terminals.cmove_up), Base.Terminals.TerminalBuffer, Int64}) +precompile(Tuple{typeof(Base.Terminals.cmove_down), Base.Terminals.TerminalBuffer, Int64}) +precompile(Tuple{typeof(Base.readuntil), Base.AbstractIOBuffer{Array{UInt8, 1}}, UInt8}) +precompile(Tuple{typeof(Base.Terminals.cmove_right), Base.Terminals.TerminalBuffer, Int64}) +precompile(Tuple{typeof(Base.LineEdit._clear_input_area), Base.Terminals.TerminalBuffer, Base.LineEdit.InputAreaState}) +precompile(Tuple{typeof(Base.seek), Base.AbstractIOBuffer{Array{UInt8, 1}}, Int64}) +precompile(Tuple{getfield(Base, Symbol("#kw##readline")), Array{Any, 1}, typeof(Base.readline), Base.AbstractIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(Base.endswith), String, String}) +precompile(Tuple{getfield(Base, Symbol("#kw##readline")), Array{Any, 1}, typeof(Base.readline), Base.Terminals.TerminalBuffer}) +precompile(Tuple{typeof(Base.LineEdit.write_prompt), Base.Terminals.TerminalBuffer, Base.LineEdit.Prompt}) +precompile(Tuple{getfield(Base.LineEdit, Symbol("#kw##refresh_multi_line")), Array{Any, 1}, typeof(Base.LineEdit.refresh_multi_line), Base.Terminals.TerminalBuffer, Base.Terminals.TerminalBuffer, Base.Terminals.TerminalBuffer, Base.LineEdit.InputAreaState, String}) +precompile(Tuple{typeof(Base.:(==)), Array{Char, 1}, Array{Char, 1}}) +precompile(Tuple{typeof(Base.LineEdit.update_key_repeats), Base.LineEdit.MIState, Array{Char, 1}}) +precompile(Tuple{typeof(Base.LineEdit.reset_state), Base.LineEdit.MIState}) +precompile(Tuple{Type{Base.Dict{Any, Any}}, Array{Any, 1}}) +precompile(Tuple{typeof(Base.Distributed.default_addprocs_params)}) +precompile(Tuple{typeof(Base.Distributed.topology), Symbol}) +precompile(Tuple{typeof(Base.shift!), Array{Base.Distributed.WorkerConfig, 1}}) +precompile(Tuple{typeof(Base.sync_end)}) +precompile(Tuple{typeof(Base.wait), Task}) +precompile(Tuple{typeof(Base.Distributed.workers)}) +precompile(Tuple{typeof(Base.sort!), Array{Int64, 1}}) +precompile(Tuple{typeof(Base.lock), Base.ReentrantLock}) +precompile(Tuple{getfield(Base.Distributed, Symbol("#kw##addprocs_locked")), Array{Any, 1}, typeof(Base.Distributed.addprocs_locked), Base.Distributed.SSHManager}) +precompile(Tuple{typeof(Base.unlock), Base.ReentrantLock}) +precompile(Tuple{typeof(Base.Distributed.check_addprocs_args), Array{Any, 1}}) +precompile(Tuple{Type{Base.Distributed.SSHManager}, Array{Any, 1}}) +precompile(Tuple{getfield(Base.Distributed, Symbol("#kw##addprocs")), Array{Any, 1}, typeof(Base.Distributed.addprocs), Base.Distributed.SSHManager}) +precompile(Tuple{typeof(Base.cmd_gen), Tuple{Tuple{}}}) +precompile(Tuple{typeof(Base.extrema), Array{Int64, 1}}) +precompile(Tuple{typeof(Base.Sort.sort_int_range!), Array{Int64, 1}, Int64, Int64}) +precompile(Tuple{typeof(Core.Inference.isbits), Base.Sort.QuickSortAlg}) +precompile(Tuple{getfield(Base.Distributed, Symbol("#kw##addprocs_locked")), Array{Any, 1}, typeof(Base.Distributed.addprocs_locked), Base.Distributed.LocalManager}) +precompile(Tuple{typeof(Base.ht_keyindex2), Base.Dict{Any, Any}, Symbol}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Any, Any}, Symbol, Symbol, Int64}) +precompile(Tuple{Type{Base.Dict{Any, Any}}, Base.Pair{Symbol, Symbol}, Base.Pair{Symbol, String}, Base.Pair{Symbol, String}, Base.Pair{Symbol, Base.Cmd}, Base.Pair{Symbol, Bool}}) +precompile(Tuple{getfield(Base.Distributed, Symbol("#kw##addprocs")), Array{Any, 1}, typeof(Base.Distributed.addprocs), Base.Distributed.LocalManager}) +precompile(Tuple{typeof(Base.listenany), Base.IPv4, UInt16}) +precompile(Tuple{typeof(Base.Distributed.check_master_connect)}) +precompile(Tuple{typeof(Base.load_machine_file), String}) +precompile(Tuple{typeof(Base.load_juliarc)}) +precompile(Tuple{typeof(Base.shift!), Array{String, 1}}) +precompile(Tuple{typeof(Base.print), Base.IOContext{Base.AbstractIOBuffer{Array{UInt8, 1}}}, String, String, Char}) +precompile(Tuple{typeof(Base.read), Base.AbstractIOBuffer{Array{UInt8, 1}}, Type{Char}}) +precompile(Tuple{typeof(Base.write), Base.Terminals.TerminalBuffer, Array{UInt8, 1}}) +precompile(Tuple{typeof(Base.LineEdit.keymap), Array{Base.Dict{Any, Any}, 1}}) +precompile(Tuple{typeof(Base.LineEdit.add_specialisations), Base.Dict{Char, Any}, Base.Dict{Char, Any}, Int64}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Char, Any}, Base.Dict{Char, Any}, Char}) +precompile(Tuple{typeof(Base.ht_keyindex2), Base.Dict{Char, Any}, Char}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Char, Any}, Base.Dict{Char, Any}, Char, Int64}) +precompile(Tuple{typeof(Base.setdiff), Base.KeyIterator{Base.Dict{Any, Any}}, Base.KeyIterator{Base.Dict{Any, Any}}}) +precompile(Tuple{typeof(Base.LineEdit.keymap_merge), Base.Dict{Char, Any}, Base.Dict{Any, Any}}) +precompile(Tuple{typeof(Base.LineEdit.postprocess!), Base.Dict{Char, Any}}) +precompile(Tuple{typeof(Base.LineEdit.keymap_unify), Array{Base.Dict{Any, Any}, 1}}) +precompile(Tuple{typeof(Base.LineEdit.validate_keymap), Base.Dict{Char, Any}}) +precompile(Tuple{Type{Expr}, Symbol, GlobalRef, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue, SSAValue}) +precompile(Tuple{typeof(Core.Inference.isbits), Tuple{String, typeof(Base.info)}}) +precompile(Tuple{typeof(Base.:(==)), Void, String}) +precompile(Tuple{Type{Symbol}, Void}) +precompile(Tuple{Type{Symbol}, Base.SubString{String}}) +precompile(Tuple{typeof(Core.Inference.isbits), Base.REPL.REPLCompletionProvider}) +precompile(Tuple{getfield(Core, Symbol("#kw#Type")), Array{Any, 1}, Type{Base.LineEdit.Prompt}, String}) +precompile(Tuple{typeof(Core.Inference.isbits), Base.REPL.ShellCompletionProvider}) +precompile(Tuple{Type{Base.Dict{Symbol, Any}}, Base.Pair{Symbol, Base.LineEdit.Prompt}, Base.Pair{Symbol, Base.LineEdit.Prompt}, Base.Pair{Symbol, Base.LineEdit.Prompt}}) +precompile(Tuple{Type{Base.REPL.REPLHistoryProvider}, Base.Dict{Symbol, Any}}) +precompile(Tuple{typeof(Base.REPL.find_hist_file)}) +precompile(Tuple{typeof(Base.REPL.history_reset_state), Base.REPL.REPLHistoryProvider}) +precompile(Tuple{typeof(Base.LineEdit.setup_search_keymap), Base.REPL.REPLHistoryProvider}) +precompile(Tuple{typeof(Core.Inference.isbits), Base.REPL.LatexCompletions}) +precompile(Tuple{typeof(Base.LineEdit.setup_prefix_keymap), Base.REPL.REPLHistoryProvider, Base.LineEdit.Prompt}) +precompile(Tuple{typeof(Base.getindex), Type{Base.Dict{Any, Any}}, Base.Dict{Any, Any}, Base.Dict{Any, Any}, Base.Dict{Any, Any}, Base.Dict{Any, Any}, Base.Dict{Any, Any}, Base.Dict{Any, Any}}) +precompile(Tuple{typeof(Base.prepend!), Array{Base.Dict{Any, Any}, 1}, Array{Base.Dict{Any, Any}, 1}}) +precompile(Tuple{typeof(Base.REPL.mode_keymap), Base.LineEdit.Prompt}) +precompile(Tuple{typeof(Core.Inference.isbits), Array{Base.Multimedia.Display, 1}}) +precompile(Tuple{typeof(Base.Multimedia.popdisplay), Base.REPL.REPLDisplay{Base.REPL.LineEditREPL}}) +precompile(Tuple{Type{String}, Base.BitArray{1}}) +precompile(Tuple{typeof(Base.REPL.ends_with_semicolon), String}) +precompile(Tuple{typeof(Core.Inference.isbits), Tuple{Void, Int64}}) +precompile(Tuple{typeof(Base.Multimedia.popdisplay), Base.REPL.REPLDisplay{Base.REPL.BasicREPL}}) +precompile(Tuple{typeof(Base.Multimedia.popdisplay), Base.REPL.REPLDisplay{Base.REPL.StreamREPL}}) +precompile(Tuple{typeof(Base.REPL.start_repl_backend), Base.Channel{Any}, Base.Channel{Any}}) +precompile(Tuple{typeof(Base._collect), Array{Ptr{Void}, 1}, Base.Generator{Array{Ptr{Void}, 1}, typeof(Base.StackTraces.lookup)}, Base.EltypeUnknown, Base.HasShape}) +precompile(Tuple{typeof(Base.shift!), Array{Base.StackTraces.StackFrame, 1}}) +precompile(Tuple{typeof(Base.StackTraces.stacktrace), Array{Ptr{Void}, 1}, Bool}) +precompile(Tuple{typeof(Base.success), Base.Process}) +precompile(Tuple{typeof(Base.mapreduce_impl), typeof(Base.success), typeof(Base.:(&)), Array{Base.Process, 1}, Int64, Int64, Int64}) +precompile(Tuple{typeof(Base.string), Base.Cmd}) +precompile(Tuple{typeof(Base.test_success), Base.Process}) +precompile(Tuple{typeof(Base._mapreduce), typeof(Base.success), typeof(Base.:(&)), Base.IndexLinear, Array{Base.Process, 1}}) +precompile(Tuple{typeof(Core.Inference.isbits), Tuple{String, String, String}}) +precompile(Tuple{getfield(Base, Symbol("#kw##shell_escape")), Array{Any, 1}, typeof(Base.shell_escape), Base.Cmd}) +precompile(Tuple{typeof(Base.show), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.Cmd}) +precompile(Tuple{typeof(Base.print), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.Cmd}) +precompile(Tuple{typeof(Core.Inference.isbits), Ptr{Void}}) +precompile(Tuple{typeof(Base.cconvert), Type{Ptr{Base.Cstring}}, Ptr{Void}}) +precompile(Tuple{typeof(Base.cconvert), Type{Ptr{Base.Cstring}}, Void}) +precompile(Tuple{typeof(Base.cconvert), Type{Base.Cstring}, Ptr{Void}}) +precompile(Tuple{typeof(Base.unsafe_convert), Type{Ptr{Base.Cstring}}, Ptr{Void}}) +precompile(Tuple{typeof(Base.unsafe_convert), Type{Ptr{Base.Cstring}}, Base.RefArray{Base.Cstring, Array{Base.Cstring, 1}, Any}}) +precompile(Tuple{Type{Base.Process}, Base.Cmd, Ptr{Void}, Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}) +precompile(Tuple{getfield(Base, Symbol("#kw##spawn")), Array{Any, 1}, typeof(Base.spawn), Base.Cmd, Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}) +precompile(Tuple{typeof(Core.Inference.isbits), Tuple{Tuple{String}, Tuple{String}, Tuple{String}}}) +precompile(Tuple{typeof(Base.cmd_gen), Tuple{Tuple{String}, Tuple{String}, Tuple{String}}}) +precompile(Tuple{typeof(Base.append!), Array{String, 1}, Array{Any, 1}}) +precompile(Tuple{typeof(Base.process_options), Base.JLOptions}) +precompile(Tuple{typeof(Base.Terminals.hascolor), Base.Terminals.TTYTerminal}) +precompile(Tuple{Type{Base.REPL.LineEditREPL}, Base.Terminals.TTYTerminal, Bool}) +precompile(Tuple{typeof(Base.close), Base.IOStream}) +precompile(Tuple{typeof(Base._atexit)}) +precompile(Tuple{typeof(Base.Distributed.terminate_all_workers)}) +precompile(Tuple{getfield(Base, Symbol("#kw##notify")), Array{Any, 1}, typeof(Base.notify), Base.Condition, Void}) +precompile(Tuple{typeof(Base.Distributed.local_remotecall_thunk), typeof(Base.exit), Tuple{}, Array{Any, 1}}) +precompile(Tuple{typeof(Base.Distributed.remote_do), typeof(Base.exit), Base.Distributed.Worker}) +precompile(Tuple{typeof(Base.Distributed.remote_do), typeof(Base.exit), Base.Distributed.LocalProcess}) +precompile(Tuple{getfield(Base.Distributed, Symbol("#kw##remote_do")), Array{Any, 1}, typeof(Base.Distributed.remote_do), typeof(Base.exit), Base.Distributed.Worker}) +precompile(Tuple{getfield(Base.Distributed, Symbol("#kw##remote_do")), Array{Any, 1}, typeof(Base.Distributed.remote_do), typeof(Base.exit), Base.Distributed.LocalProcess}) +precompile(Tuple{typeof(Base.Distributed.set_worker_state), Base.Distributed.Worker, Base.Distributed.WorkerState}) +precompile(Tuple{typeof(Base.Distributed.set_worker_state), Base.Distributed.LocalProcess, Base.Distributed.WorkerState}) +precompile(Tuple{getfield(Base.Distributed, Symbol("#kw##rmprocs")), Array{Any, 1}, typeof(Base.Distributed.rmprocs), Array{Int64, 1}}) +precompile(Tuple{typeof(Base.Distributed.interrupt), Array{Int64, 1}}) +precompile(Tuple{typeof(Base.uvfinalize), Base.TTY}) +precompile(Tuple{typeof(Base.uv_status_string), Base.TTY}) +precompile(Tuple{typeof(Base._fd), Base.TTY}) +precompile(Tuple{typeof(Base.print), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.TTY}) +precompile(Tuple{typeof(Base.unpreserve_handle), Base.TTY}) +precompile(Tuple{typeof(Base.isopen), Base.TTY}) +precompile(Tuple{typeof(Base.stream_wait), Base.TTY, Base.Condition}) +precompile(Tuple{typeof(Base.close), Base.TTY}) +precompile(Tuple{typeof(Base.unsafe_store!), Ptr{Int32}, Int64}) +precompile(Tuple{Type{Base.Terminals.TTYTerminal}, String, Base.TTY, Base.TTY, Base.IOStream}) +precompile(Tuple{typeof(Base.unsafe_write), Base.TTY, Ptr{UInt8}, UInt64}) +precompile(Tuple{typeof(Base.unpreserve_handle), Task}) +precompile(Tuple{typeof(Base.check_open), Base.TTY}) +precompile(Tuple{typeof(Base.stream_wait), Task}) +precompile(Tuple{typeof(Base.uv_write), Base.TTY, Ptr{UInt8}, UInt64}) +precompile(Tuple{typeof(Base.flush), Base.TTY}) +precompile(Tuple{typeof(Base.Distributed.flush_gc_msgs)}) +precompile(Tuple{typeof(Base.__atreplinit), Base.REPL.LineEditREPL}) +precompile(Tuple{typeof(Base.:(==)), Base.Multimedia.TextDisplay, Base.REPL.REPLDisplay{Base.REPL.LineEditREPL}}) +precompile(Tuple{typeof(Base.:(==)), Base.REPL.REPLDisplay{Base.REPL.LineEditREPL}, Base.REPL.REPLDisplay{Base.REPL.LineEditREPL}}) +precompile(Tuple{typeof(Base.REPL.hist_from_file), Base.REPL.REPLHistoryProvider, Base.IOStream, String}) +precompile(Tuple{typeof(Base.REPL.hist_getline), Base.IOStream}) +precompile(Tuple{typeof(Base.push!), Array{String, 1}, Base.SubString{String}}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Any, Any}, Char, Char}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Any, Any}, Char, Char, Int64}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Any, Any}, Base.LineEdit.KeyAlias, Int64}) +precompile(Tuple{typeof(Base.ht_keyindex2), Base.Dict{Any, Any}, Int64}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Any, Any}, Base.LineEdit.KeyAlias, Int64, Int64}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Any, Any}, String, String}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Any, Any}, String, String, Int64}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Any, Any}, Void, String}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Any, Any}, Void, String, Int64}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Any, Any}, Base.LineEdit.KeyAlias, String}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Any, Any}, Base.LineEdit.KeyAlias, String, Int64}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Any, Any}, Char, String}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Any, Any}, Char, String, Int64}) +precompile(Tuple{getfield(Base.LineEdit, Symbol("#kw##add_nested_key!")), Array{Any, 1}, typeof(Base.LineEdit.add_nested_key!), Base.Dict{Char, Any}, String, Void}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Char, Any}, Void, Char, Int64}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Char, Any}, Void, Char}) +precompile(Tuple{getfield(Base.LineEdit, Symbol("#kw##add_nested_key!")), Array{Any, 1}, typeof(Base.LineEdit.add_nested_key!), Base.Dict{Char, Any}, String, Base.LineEdit.KeyAlias}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Char, Any}, Base.LineEdit.KeyAlias, Char, Int64}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Char, Any}, Base.LineEdit.KeyAlias, Char}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Any, Void}, Void, String}) +precompile(Tuple{typeof(Base.ht_keyindex2), Base.Dict{Any, Void}, String}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Any, Void}, Void, String, Int64}) +precompile(Tuple{typeof(Base.LineEdit.fixup_keymaps!), Base.Dict{Char, Any}, Int64, Char, Void}) +precompile(Tuple{typeof(Base.LineEdit.run_interface), Base.Terminals.TTYTerminal, Base.LineEdit.ModalInterface}) +precompile(Tuple{getfield(Base.LineEdit, Symbol("#kw##refresh_multi_line")), Array{Any, 1}, typeof(Base.LineEdit.refresh_multi_line), Base.Terminals.TerminalBuffer, Base.Terminals.TTYTerminal, Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.LineEdit.InputAreaState, Base.LineEdit.PromptState}) +precompile(Tuple{getfield(Base.LineEdit, Symbol("#kw##refresh_multi_line")), Array{Any, 1}, typeof(Base.LineEdit.refresh_multi_line), Base.Terminals.TerminalBuffer, Base.Terminals.TTYTerminal, Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.LineEdit.InputAreaState, Base.LineEdit.PrefixSearchState}) +precompile(Tuple{typeof(Base.write), Base.Terminals.TTYTerminal, Array{UInt8, 1}}) +precompile(Tuple{typeof(Base.LineEdit.init_state), Base.Terminals.TTYTerminal, Base.LineEdit.ModalInterface}) +precompile(Tuple{typeof(Base.LineEdit.prompt!), Base.Terminals.TTYTerminal, Base.LineEdit.ModalInterface, Base.LineEdit.MIState}) +precompile(Tuple{typeof(Base.getindex), Array{Base.LineEdit.TextInterface, 1}, Int64}) +precompile(Tuple{typeof(Base.start), Array{Base.LineEdit.TextInterface, 1}}) +precompile(Tuple{typeof(Base.done), Array{Base.LineEdit.TextInterface, 1}, Int64}) +precompile(Tuple{typeof(Base.next), Array{Base.LineEdit.TextInterface, 1}, Int64}) +precompile(Tuple{typeof(Base.LineEdit.init_state), Base.Terminals.TTYTerminal, Base.LineEdit.Prompt}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Any, Any}, Base.LineEdit.PromptState, Base.LineEdit.Prompt}) +precompile(Tuple{typeof(Base.ht_keyindex2), Base.Dict{Any, Any}, Base.LineEdit.Prompt}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Any, Any}, Base.LineEdit.PromptState, Base.LineEdit.Prompt, Int64}) +precompile(Tuple{typeof(Base.LineEdit.init_state), Base.Terminals.TTYTerminal, Base.LineEdit.HistoryPrompt{Base.REPL.REPLHistoryProvider}}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Any, Any}, Base.LineEdit.SearchState, Base.LineEdit.HistoryPrompt{Base.REPL.REPLHistoryProvider}}) +precompile(Tuple{typeof(Base.ht_keyindex2), Base.Dict{Any, Any}, Base.LineEdit.HistoryPrompt{Base.REPL.REPLHistoryProvider}}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Any, Any}, Base.LineEdit.SearchState, Base.LineEdit.HistoryPrompt{Base.REPL.REPLHistoryProvider}, Int64}) +precompile(Tuple{typeof(Base.LineEdit.init_state), Base.Terminals.TTYTerminal, Base.LineEdit.PrefixHistoryPrompt{Base.REPL.REPLHistoryProvider}}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Any, Any}, Base.LineEdit.PrefixSearchState, Base.LineEdit.PrefixHistoryPrompt{Base.REPL.REPLHistoryProvider}}) +precompile(Tuple{typeof(Base.ht_keyindex2), Base.Dict{Any, Any}, Base.LineEdit.PrefixHistoryPrompt{Base.REPL.REPLHistoryProvider}}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Any, Any}, Base.LineEdit.PrefixSearchState, Base.LineEdit.PrefixHistoryPrompt{Base.REPL.REPLHistoryProvider}, Int64}) +precompile(Tuple{typeof(Core.Inference.isbits), Tuple{Tuple{}, Void}}) +precompile(Tuple{typeof(Base.take!), Base.Channel{Any}}) +precompile(Tuple{typeof(Base.n_avail), Base.Channel{Any}}) +precompile(Tuple{typeof(Base.check_channel_state), Base.Channel{Any}}) +precompile(Tuple{typeof(Base.wait_impl), Base.Channel{Any}}) +precompile(Tuple{typeof(Base.wait_unbuffered), Base.Channel{Any}}) +precompile(Tuple{typeof(Base.wait), Base.Channel{Any}}) +precompile(Tuple{typeof(Base.take_unbuffered), Base.Channel{Any}}) +precompile(Tuple{typeof(Base.LineEdit.activate), Base.LineEdit.Prompt, Base.LineEdit.MIState, Base.Terminals.TTYTerminal, Base.Terminals.TTYTerminal}) +precompile(Tuple{typeof(Base.:(==)), Base.LineEdit.Prompt, Base.LineEdit.Prompt}) +precompile(Tuple{typeof(Base.getindex), Base.Dict{Any, Any}, Base.LineEdit.Prompt}) +precompile(Tuple{typeof(Base.ht_keyindex), Base.Dict{Any, Any}, Base.LineEdit.Prompt}) +precompile(Tuple{typeof(Base.LineEdit.activate), Base.LineEdit.Prompt, Base.LineEdit.PromptState, Base.Terminals.TTYTerminal, Base.Terminals.TTYTerminal}) +precompile(Tuple{typeof(Base.LineEdit.refresh_multi_line), Base.Terminals.TerminalBuffer, Base.Terminals.TerminalBuffer, Base.Terminals.TTYTerminal, Base.LineEdit.PromptState}) +precompile(Tuple{getfield(Base.LineEdit, Symbol("#kw##refresh_multi_line")), Array{Any, 1}, typeof(Base.LineEdit.refresh_multi_line), Base.Terminals.TerminalBuffer, Base.Terminals.TerminalBuffer, Base.Terminals.TTYTerminal, Base.LineEdit.PromptState}) +precompile(Tuple{getfield(Base.LineEdit, Symbol("#kw##refresh_multi_line")), Array{Any, 1}, typeof(Base.LineEdit.refresh_multi_line), Base.Terminals.TerminalBuffer, Base.Terminals.TTYTerminal, Base.LineEdit.PromptState}) +precompile(Tuple{typeof(Base.LineEdit.refresh_multi_line), Base.Terminals.TerminalBuffer, Base.Terminals.TTYTerminal, Base.LineEdit.PromptState}) +precompile(Tuple{typeof(Base.displaysize), Base.TTY}) +precompile(Tuple{typeof(Base.divrem), Int64, Int64}) +precompile(Tuple{typeof(Base.LineEdit.match_input), Base.Dict{Char, Any}, Base.LineEdit.MIState}) +precompile(Tuple{typeof(Base.LineEdit.match_input), Base.Dict{Char, Any}, Base.LineEdit.MIState, Base.AbstractIOBuffer{Array{UInt8, 1}}, Array{Char, 1}, Base.Dict{Char, Any}}) +precompile(Tuple{typeof(Base.LineEdit.terminal), Base.LineEdit.PromptState}) +precompile(Tuple{typeof(Base.LineEdit.match_input), Base.Dict{Char, Any}, Base.LineEdit.MIState, Base.Terminals.TTYTerminal, Array{Char, 1}, Base.Dict{Char, Any}}) +precompile(Tuple{typeof(Base.read), Base.Terminals.TTYTerminal, Type{Char}}) +precompile(Tuple{typeof(Base.eof), Base.TTY}) +precompile(Tuple{typeof(Base.isreadable), Base.TTY}) +precompile(Tuple{typeof(Base.start_reading), Base.TTY}) +precompile(Tuple{typeof(Base.wait_readnb), Base.TTY, Int64}) +precompile(Tuple{typeof(Base.alloc_buf_hook), Base.TTY, UInt64}) +precompile(Tuple{typeof(Base.read), Base.TTY, Type{UInt8}}) +precompile(Tuple{typeof(Base.throw_boundserror), Array{UInt8, 1}, Tuple{Base.UnitRange{Int64}}}) +precompile(Tuple{typeof(Base.deleteat!), Array{UInt8, 1}, Base.UnitRange{Int64}}) +precompile(Tuple{typeof(Base.splice!), Array{UInt8, 1}, Base.UnitRange{Int64}, Array{UInt8, 1}}) +precompile(Tuple{typeof(Base.LineEdit.splice_buffer!), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.UnitRange{Int64}, String}) +precompile(Tuple{typeof(Base.LineEdit.refresh_multi_line), Base.Terminals.TerminalBuffer, Base.LineEdit.PromptState}) +precompile(Tuple{typeof(Base.LineEdit.edit_insert), Base.AbstractIOBuffer{Array{UInt8, 1}}, String}) +precompile(Tuple{typeof(Base.LineEdit.edit_insert), Base.LineEdit.PromptState, String}) +precompile(Tuple{typeof(Base.Terminals.width), Base.Terminals.TTYTerminal}) +precompile(Tuple{Type{Base.Libc.TmStruct}, Float64}) +precompile(Tuple{typeof(Base.Libc.strftime), String, Base.Libc.TmStruct}) +precompile(Tuple{typeof(Base.replace), String, Base.Regex, String, Int64}) +precompile(Tuple{typeof(Base.REPL.mode_idx), Base.REPL.REPLHistoryProvider, Base.LineEdit.Prompt}) +precompile(Tuple{typeof(Base.LineEdit.commit_line), Base.LineEdit.MIState}) +precompile(Tuple{typeof(Base.LineEdit.on_enter), Base.LineEdit.PromptState}) +precompile(Tuple{typeof(Base.REPL.return_callback), Base.LineEdit.PromptState}) +precompile(Tuple{typeof(Base.LineEdit.refresh_multi_line), Base.LineEdit.PromptState}) +precompile(Tuple{typeof(Base.LineEdit.refresh_multi_line), Base.Terminals.TTYTerminal, Base.LineEdit.PromptState}) +precompile(Tuple{typeof(Base.println), Base.Terminals.TTYTerminal}) +precompile(Tuple{typeof(Base.write), Base.Terminals.TTYTerminal, Char}) +precompile(Tuple{typeof(Base.write), Base.TTY, UInt8}) +precompile(Tuple{typeof(Base.unsafe_write), Base.TTY, Base.RefValue{UInt8}, Int64}) +precompile(Tuple{typeof(Base.LineEdit.add_history), Base.LineEdit.PromptState}) +precompile(Tuple{typeof(Base.LineEdit.add_history), Base.REPL.REPLHistoryProvider, Base.LineEdit.PromptState}) +precompile(Tuple{typeof(Base.start), Base.Pair{Symbol, Any}}) +precompile(Tuple{typeof(Base.print), Base.IOStream, String}) +precompile(Tuple{typeof(Base.unsafe_write), Base.IOStream, Ptr{UInt8}, UInt64}) +precompile(Tuple{typeof(Base.flush), Base.IOStream}) +precompile(Tuple{typeof(Base.LineEdit.mode), Base.LineEdit.PromptState}) +precompile(Tuple{typeof(Base.REPL.reset), Base.REPL.LineEditREPL}) +precompile(Tuple{getfield(Base, Symbol("#kw##parse_input_line")), Array{Any, 1}, typeof(Base.parse_input_line), String}) +precompile(Tuple{typeof(Base.put!), Base.Channel{Any}, Tuple{Expr, Int64}}) +precompile(Tuple{typeof(Base.put_buffered), Base.Channel{Any}, Tuple{Expr, Int64}}) +precompile(Tuple{typeof(Base.put_unbuffered), Base.Channel{Any}, Tuple{Expr, Int64}}) +precompile(Tuple{typeof(Base.REPL.eval_user_input), Expr, Base.REPL.REPLBackend}) +precompile(Tuple{typeof(Base.put!), Base.Channel{Any}, Tuple{Int64, Void}}) +precompile(Tuple{typeof(Base.put_buffered), Base.Channel{Any}, Tuple{Int64, Void}}) +precompile(Tuple{typeof(Base.put_unbuffered), Base.Channel{Any}, Tuple{Int64, Void}}) +precompile(Tuple{typeof(Base.start), Tuple{Int64, Void}}) +precompile(Tuple{typeof(Base.REPL.print_response), Base.REPL.LineEditREPL, Int64, Void, Bool, Bool}) +precompile(Tuple{typeof(Base.REPL.print_response), Base.Terminals.TTYTerminal, Int64, Void, Bool, Bool, Void}) +precompile(Tuple{typeof(Base.print), Base.Terminals.TTYTerminal, DataType}) +precompile(Tuple{typeof(Base.print), Base.Terminals.TTYTerminal, Char}) +precompile(Tuple{typeof(Base.print), Base.Terminals.TTYTerminal, String, DataType, String, Char}) +precompile(Tuple{typeof(Base.print), Base.Terminals.TTYTerminal, String, Char}) +precompile(Tuple{Type{Base.IOContext{Base.Terminals.TTYTerminal}}, Base.Terminals.TTYTerminal, Base.ImmutableDict{Symbol, Any}}) +precompile(Tuple{getfield(Base, Symbol("#kw##with_output_color")), Array{Any, 1}, typeof(Base.with_output_color), typeof(Base.print), Symbol, Base.IOContext{Base.Terminals.TTYTerminal}, String}) +precompile(Tuple{getfield(Base, Symbol("#kw##with_output_color")), Array{Any, 1}, typeof(Base.with_output_color), typeof(Base.print), Int64, Base.IOContext{Base.Terminals.TTYTerminal}, String}) +precompile(Tuple{typeof(Base.write), Base.IOContext{Base.Terminals.TTYTerminal}, Symbol}) +precompile(Tuple{typeof(Base.show), Base.IOContext{Base.Terminals.TTYTerminal}, Module}) +precompile(Tuple{typeof(Base.print), Base.IOContext{Base.Terminals.TTYTerminal}, String}) +precompile(Tuple{typeof(Base.print), Base.IOContext{Base.Terminals.TTYTerminal}, Module}) +precompile(Tuple{typeof(Base.show), Base.IOContext{Base.Terminals.TTYTerminal}, Int32}) +precompile(Tuple{typeof(Base.print), Base.IOContext{Base.Terminals.TTYTerminal}, Symbol}) +precompile(Tuple{typeof(Base.print), Base.IOContext{Base.Terminals.TTYTerminal}, Int32}) +precompile(Tuple{typeof(Base.show), Base.IOContext{Base.Terminals.TTYTerminal}, Int64}) +precompile(Tuple{typeof(Base.print), Base.IOContext{Base.Terminals.TTYTerminal}, Int64}) +precompile(Tuple{typeof(Base.print), Base.IOContext{Base.Terminals.TTYTerminal}, String, Int64, String}) +precompile(Tuple{typeof(Base.write), Base.IOContext{Base.Terminals.TTYTerminal}, Char}) +precompile(Tuple{typeof(Base.show_circular), Base.IOContext{Base.Terminals.TTYTerminal}, Array{Any, 1}}) +precompile(Tuple{typeof(Base.show_delim_array), Base.IOContext{Base.Terminals.TTYTerminal}, Array{Any, 1}, Char, Char, Char, Bool, Int64, Int64}) +precompile(Tuple{typeof(Base.join), Base.IOContext{Base.Terminals.TTYTerminal}, Array{Any, 1}, String, String}) +precompile(Tuple{typeof(Base.join), Base.IOContext{Base.Terminals.TTYTerminal}, Tuple{}, String, String}) +precompile(Tuple{typeof(Base.show_method_params), Base.IOContext{Base.Terminals.TTYTerminal}, Array{Any, 1}}) +precompile(Tuple{typeof(Base.print), Base.IOContext{Base.Terminals.TTYTerminal}, String, Module}) +precompile(Tuple{typeof(Base.print), Base.IOContext{Base.Terminals.TTYTerminal}, String, Symbol, String, Int32}) +precompile(Tuple{typeof(Base.show_lambda_types), Base.IOContext{Base.Terminals.TTYTerminal}, Core.MethodInstance}) +precompile(Tuple{typeof(Base.print_with_color), Symbol, Base.IOContext{Base.Terminals.TTYTerminal}, String}) +precompile(Tuple{typeof(Base.print_with_color), Int64, Base.IOContext{Base.Terminals.TTYTerminal}, String}) +precompile(Tuple{typeof(Base.show), Base.IOContext{Base.Terminals.TTYTerminal}, Core.MethodInstance}) +precompile(Tuple{typeof(Base.StackTraces.show_spec_linfo), Base.IOContext{Base.Terminals.TTYTerminal}, Base.StackTraces.StackFrame}) +precompile(Tuple{getfield(Base, Symbol("#kw##show")), Array{Any, 1}, typeof(Base.show), Base.IOContext{Base.Terminals.TTYTerminal}, Base.StackTraces.StackFrame}) +precompile(Tuple{getfield(Base, Symbol("#kw##show_trace_entry")), Array{Any, 1}, typeof(Base.show_trace_entry), Base.IOContext{Base.Terminals.TTYTerminal}, Base.StackTraces.StackFrame, Int64}) +precompile(Tuple{typeof(Base.show_backtrace), Base.Terminals.TTYTerminal, Array{Ptr{Void}, 1}}) +precompile(Tuple{typeof(Base.Multimedia.display), Int64}) +precompile(Tuple{typeof(Core.Inference.isbits), Base.MIME{Symbol("text/plain")}}) +precompile(Tuple{typeof(Core.Inference.isbits), Tuple{typeof(Base.Multimedia.display), typeof(Base.show)}}) +precompile(Tuple{typeof(Base.Multimedia.display), Base.REPL.REPLDisplay{Base.REPL.LineEditREPL}, Int64}) +precompile(Tuple{Type{Base.MIME{Symbol("text/plain")}}}) +precompile(Tuple{typeof(Base.Multimedia.display), Base.REPL.REPLDisplay{Base.REPL.LineEditREPL}, Base.MIME{Symbol("text/plain")}, Int64}) +precompile(Tuple{typeof(Base.start), Base.Pair{Any, Any}}) +precompile(Tuple{typeof(Base.LineEdit.reset_state), Base.LineEdit.PromptState}) +precompile(Tuple{typeof(Base.LineEdit.reset_state), Base.LineEdit.SearchState}) +precompile(Tuple{typeof(Base.LineEdit.reset_state), Base.REPL.REPLHistoryProvider}) +precompile(Tuple{typeof(Base.LineEdit.reset_state), Base.LineEdit.PrefixSearchState}) +precompile(Tuple{typeof(Base.haskey), Base.Dict{Any, Any}, Base.LineEdit.Prompt}) +precompile(Tuple{typeof(Base.LineEdit.deactivate), Base.LineEdit.Prompt, Base.LineEdit.PromptState, Base.Terminals.TerminalBuffer, Base.Terminals.TTYTerminal}) +precompile(Tuple{typeof(Base.LineEdit.activate), Base.LineEdit.Prompt, Base.LineEdit.PromptState, Base.Terminals.TerminalBuffer, Base.Terminals.TTYTerminal}) +precompile(Tuple{typeof(Base.LineEdit.commit_changes), Base.Terminals.TTYTerminal, Base.Terminals.TerminalBuffer}) +precompile(Tuple{typeof(Base.LineEdit.complete_line), Base.LineEdit.PromptState, Int64}) +precompile(Tuple{typeof(Base.LineEdit.input_string_newlines_aftercursor), Base.LineEdit.PromptState}) +precompile(Tuple{typeof(Base.LineEdit.complete_line), Base.REPL.REPLCompletionProvider, Base.LineEdit.PromptState}) +precompile(Tuple{getfield(Base, Symbol("#kw##parse")), Array{Any, 1}, typeof(Base.parse), String}) +precompile(Tuple{typeof(Base.isvalid), Base.RevString{String}, Int64}) +precompile(Tuple{typeof(Base.nextind), Base.RevString{String}, Int64}) +precompile(Tuple{typeof(Base.search), Base.RevString{String}, Array{Char, 1}, Int64}) +precompile(Tuple{typeof(Base.rsearch), String, Array{Char, 1}, Int64}) +precompile(Tuple{getfield(Base.REPLCompletions, Symbol("#kw##find_start_brace")), Array{Any, 1}, typeof(Base.REPLCompletions.find_start_brace), String}) +precompile(Tuple{typeof(Core.Inference.isbits), Tuple{Void, Void, Void}}) +precompile(Tuple{typeof(Base.isidentifier), Base.SubString{String}}) +precompile(Tuple{typeof(Core.Inference.isbits), Tuple{Bool, Void, Void}}) +precompile(Tuple{typeof(Base.Filesystem.readdir), String}) +precompile(Tuple{typeof(Base.cmp), String, Base.SubString{String}}) +precompile(Tuple{typeof(Base.skip_deleted), Base.Dict{String, Void}, Int64}) +precompile(Tuple{typeof(Base.PCRE.exec), Ptr{Void}, String, UInt32, UInt32, Ptr{Void}}) +precompile(Tuple{typeof(Base.PCRE.exec), Ptr{Void}, String, UInt64, UInt32, Ptr{Void}}) +precompile(Tuple{typeof(Base.nextind), String, UInt64}) +precompile(Tuple{typeof(Base.matchall), Base.Regex, String, Bool}) +precompile(Tuple{typeof(Base.skip_deleted), Base.Dict{String, String}, Int64}) +precompile(Tuple{typeof(Base.reverse), String}) +precompile(Tuple{typeof(Core.Inference.isbits), Tuple{Void, Bool}}) +precompile(Tuple{typeof(Base._convert), Type{Array{Method, 1}}, Base.BitArray{1}}) +precompile(Tuple{typeof(Base.unsafe_copy!), Array{Method, 1}, Int64, Array{Method, 1}, Int64, Int64}) +precompile(Tuple{typeof(Base.copy!), Array{Method, 1}, Int64, Array{Method, 1}, Int64, Int64}) +precompile(Tuple{typeof(Core.Inference.length), Tuple{Core.Inference.PartialTypeVar}}) +precompile(Tuple{typeof(Core.Inference.getindex), Tuple{Core.Inference.PartialTypeVar}, Int64}) +precompile(Tuple{typeof(Base.show_delim_array), Base.AbstractIOBuffer{Array{UInt8, 1}}, Array{Any, 1}, Char, Char, Char, Bool, Int64, Int64}) +precompile(Tuple{typeof(Base.join), Base.AbstractIOBuffer{Array{UInt8, 1}}, Array{Any, 1}, String, String}) +precompile(Tuple{typeof(Base.join), Base.AbstractIOBuffer{Array{UInt8, 1}}, Tuple{}, String, String}) +precompile(Tuple{typeof(Base.show_method_params), Base.AbstractIOBuffer{Array{UInt8, 1}}, Array{Any, 1}}) +precompile(Tuple{typeof(Base.print), Base.AbstractIOBuffer{Array{UInt8, 1}}, String, Module}) +precompile(Tuple{typeof(Base.print), Base.AbstractIOBuffer{Array{UInt8, 1}}, String, Symbol, String, Int32}) +precompile(Tuple{typeof(Base.reverseind), String, Int64}) +precompile(Tuple{typeof(Base.Pkg.Dir.path)}) +precompile(Tuple{typeof(Base.promote_type), Type{String}, Type{Union{}}}) +precompile(Tuple{typeof(Base.promote_type), Type{Any}, Type{String}}) +precompile(Tuple{typeof(Base.promote_rule), Type{Any}, Type{String}}) +precompile(Tuple{typeof(Base.promote_rule), Type{String}, Type{Any}}) +precompile(Tuple{typeof(Base.promote_result), Type{Any}, Type{String}, Type{Union{}}, Type{Union{}}}) +precompile(Tuple{typeof(Base.promote_type), Type{String}, Type{Any}}) +precompile(Tuple{typeof(Base.promote_result), Type{String}, Type{Any}, Type{Union{}}, Type{Union{}}}) +precompile(Tuple{typeof(Base.cat_indices), String, Int64}) +precompile(Tuple{typeof(Base.cat_size), String, Int64}) +precompile(Tuple{typeof(Base.setindex!), Array{Any, 1}, String, Base.UnitRange{Int64}}) +precompile(Tuple{typeof(Base._cat), Array{Any, 1}, Tuple{Int64}, Tuple{Bool}, String, Array{Any, 1}, String}) +precompile(Tuple{typeof(Base.cat_t), Type{Base.Val{1}}, Type{Any}, String, Array{Any, 1}, String}) +precompile(Tuple{typeof(Base.Sort.searchsortedfirst), Array{String, 1}, String, Int64, Int64, Base.Order.ForwardOrdering}) +precompile(Tuple{typeof(Base.Sort.searchsortedlast), Array{String, 1}, String, Int64, Int64, Base.Order.ForwardOrdering}) +precompile(Tuple{typeof(Base.Sort.searchsorted), Array{String, 1}, String, Int64, Int64, Base.Order.ForwardOrdering}) +precompile(Tuple{typeof(Base.Sort.searchsorted), Array{String, 1}, String, Base.Order.ForwardOrdering}) +precompile(Tuple{typeof(Base.throw_boundserror), Array{String, 1}, Tuple{Base.UnitRange{Int64}}}) +precompile(Tuple{typeof(Core.Inference.precise_container_type), String, Core.Inference.Const, Array{Any, 1}, Core.Inference.InferenceState}) +precompile(Tuple{typeof(Base._rsearchindex), String, String, Int64}) +precompile(Tuple{typeof(Base.deleteat!), Array{Symbol, 1}, Base.UnitRange{Int64}}) +precompile(Tuple{typeof(Base.copy!), Array{String, 1}, Base.Generator{Array{Symbol, 1}, typeof(Base.string)}}) +precompile(Tuple{typeof(Base.deleteat!), Array{String, 1}, Base.UnitRange{Int64}}) +precompile(Tuple{typeof(Base.ht_keyindex), Base.Dict{String, Void}, String}) +precompile(Tuple{typeof(Base.push!), Base.Set{String}, String}) +precompile(Tuple{typeof(Base.isstructtype), DataType}) +precompile(Tuple{typeof(Base.start), Array{Int64, 1}}) +precompile(Tuple{typeof(Base.to_tuple_type), Type{Tuple}}) +precompile(Tuple{typeof(Base.append!), Array{Any, 1}, Array{Any, 1}}) +precompile(Tuple{typeof(Core.Inference.isbits), Tuple{DataType, Bool}}) +precompile(Tuple{typeof(Base.is_default_method), Method}) +precompile(Tuple{getfield(Base, Symbol("#kw##show")), Array{Any, 1}, typeof(Base.show), Base.AbstractIOBuffer{Array{UInt8, 1}}, Method}) +precompile(Tuple{typeof(Base.sort!), Array{String, 1}}) +precompile(Tuple{typeof(Base.rehash!), Base.Dict{String, Void}, Int64}) +precompile(Tuple{typeof(Base.ht_keyindex2), Base.Dict{String, Void}, String}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{String, Void}, Void, String, Int64}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{String, Void}, Void, String}) +precompile(Tuple{typeof(Base.Filesystem.realpath), Base.SubString{String}}) +precompile(Tuple{typeof(Base.Filesystem.readdir), Base.SubString{String}}) +precompile(Tuple{typeof(Base.REPLCompletions.dict_identifier_key), String, Symbol}) +precompile(Tuple{typeof(Base.Filesystem.expanduser), String}) +precompile(Tuple{typeof(Base.REPLCompletions.bslash_completions), String, Int64}) +precompile(Tuple{typeof(Base.REPLCompletions.should_method_complete), String}) +precompile(Tuple{typeof(Base.REPLCompletions.afterusing), String, Int64}) +precompile(Tuple{typeof(Base.REPLCompletions.complete_keyword), String}) +precompile(Tuple{typeof(Base.in), Char, Array{Any, 1}}) +precompile(Tuple{typeof(Base.string), Char, Char}) +precompile(Tuple{typeof(Base.unique), Array{String, 1}}) +precompile(Tuple{typeof(Base.REPL.beforecursor), Base.AbstractIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(Base.REPLCompletions.completions), String, Int64}) +precompile(Tuple{typeof(Base.incomplete_tag), Symbol}) +precompile(Tuple{typeof(Base.rsearchindex), String, String, Int64}) +precompile(Tuple{typeof(Base._rsearch), String, String, Int64}) +precompile(Tuple{typeof(Base.unshift!), Array{Base.SubString{String}, 1}, Base.SubString{String}}) +precompile(Tuple{typeof(Base.startswith), String, Base.SubString{String}}) +precompile(Tuple{typeof(Base.rsearch), String, Array{Char, 1}}) +precompile(Tuple{getfield(Base, Symbol("#kw##rsplit")), Array{Any, 1}, typeof(Base.rsplit), String, String}) +precompile(Tuple{typeof(Base.sort!), Array{String, 1}, Base.Sort.MergeSortAlg, Base.Order.ForwardOrdering}) +precompile(Tuple{typeof(Base.sort!), Array{String, 1}, Int64, Int64, Base.Sort.InsertionSortAlg, Base.Order.ForwardOrdering}) +precompile(Tuple{typeof(Base.sort!), Array{String, 1}, Int64, Int64, Base.Sort.MergeSortAlg, Base.Order.ForwardOrdering, Array{String, 1}}) +precompile(Tuple{typeof(Base.start), Tuple{Array{String, 1}, String, Bool}}) +precompile(Tuple{typeof(Base.indexed_next), Tuple{Array{String, 1}, String, Bool}, Int64, Int64}) +precompile(Tuple{typeof(Base.LineEdit.common_prefix), Array{String, 1}}) +precompile(Tuple{typeof(Base.LineEdit.show_completions), Base.LineEdit.PromptState, Array{String, 1}}) +precompile(Tuple{typeof(Base.collect_to!), Array{Int64, 1}, Base.Generator{Array{String, 1}, typeof(Base.length)}, Int64, Int64}) +precompile(Tuple{typeof(Base._collect), Array{String, 1}, Base.Generator{Array{String, 1}, typeof(Base.length)}, Base.EltypeUnknown, Base.HasShape}) +precompile(Tuple{typeof(Base.mapreduce_impl), typeof(Base.identity), typeof(Base.scalarmax), Array{Int64, 1}, Int64, Int64}) +precompile(Tuple{typeof(Base._mapreduce), typeof(Base.identity), typeof(Base.scalarmax), Base.IndexLinear, Array{Int64, 1}}) +precompile(Tuple{typeof(Base.Terminals.cmove_down), Base.Terminals.TTYTerminal, Int64}) +precompile(Tuple{typeof(Base.Terminals.cmove_col), Base.Terminals.TTYTerminal, Int64}) +precompile(Tuple{typeof(Base.Terminals.cmove_right), Base.Terminals.TTYTerminal, Int64}) +precompile(Tuple{typeof(Base.write), Base.TTY, Char}) +precompile(Tuple{typeof(Base.LineEdit.match_input), Base.LineEdit.KeyAlias, Base.LineEdit.MIState, Base.Terminals.TTYTerminal, Array{Char, 1}, Base.Dict{Char, Any}}) +precompile(Tuple{typeof(Base.peek), Base.AbstractIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(Base.LineEdit.char_move_left), Base.AbstractIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(Base.LineEdit.edit_backspace), Base.AbstractIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(Base.LineEdit.edit_backspace), Base.LineEdit.PromptState}) +precompile(Tuple{typeof(Base.Terminals.beep), Base.Terminals.TTYTerminal}) +precompile(Tuple{typeof(Base.LineEdit.edit_move_down), Base.AbstractIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(Core.Inference.length), Tuple{Core.Inference.Const, Core.Inference.Const, Core.Inference.Const, DataType}}) +precompile(Tuple{typeof(Core.Inference.getindex), Tuple{Core.Inference.Const, Core.Inference.Const, Core.Inference.Const, DataType}, Int64}) +precompile(Tuple{typeof(Base.LineEdit.replace_line), Base.LineEdit.PrefixSearchState, String}) +precompile(Tuple{typeof(Base.LineEdit.refresh_multi_line), Base.Terminals.TerminalBuffer, Base.LineEdit.PrefixSearchState}) +precompile(Tuple{typeof(Base.copy), Base.AbstractIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(Base.REPL.history_move), Base.LineEdit.PrefixSearchState, Base.REPL.REPLHistoryProvider, Int64, Int64}) +precompile(Tuple{typeof(Base.LineEdit.edit_move_down), Base.LineEdit.MIState}) +precompile(Tuple{typeof(Base.LineEdit.enter_prefix_search), Base.LineEdit.MIState, Base.LineEdit.PrefixHistoryPrompt{Base.REPL.REPLHistoryProvider}, Bool}) +precompile(Tuple{typeof(Base.haskey), Base.Dict{Any, Any}, Base.LineEdit.PrefixHistoryPrompt{Base.REPL.REPLHistoryProvider}}) +precompile(Tuple{typeof(Base.ht_keyindex), Base.Dict{Any, Any}, Base.LineEdit.PrefixHistoryPrompt{Base.REPL.REPLHistoryProvider}}) +precompile(Tuple{typeof(Base.getindex), Base.Dict{Any, Any}, Base.LineEdit.PrefixHistoryPrompt{Base.REPL.REPLHistoryProvider}}) +precompile(Tuple{typeof(Base.LineEdit.copybuf!), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.AbstractIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(Base.LineEdit.activate), Base.LineEdit.PrefixHistoryPrompt{Base.REPL.REPLHistoryProvider}, Base.LineEdit.PrefixSearchState, Base.Terminals.TerminalBuffer, Base.Terminals.TTYTerminal}) +precompile(Tuple{typeof(Base.LineEdit.refresh_multi_line), Base.Terminals.TerminalBuffer, Base.Terminals.TTYTerminal, Base.LineEdit.PrefixSearchState}) +precompile(Tuple{typeof(Base.LineEdit.history_next_prefix), Base.LineEdit.PrefixSearchState, Base.REPL.REPLHistoryProvider, String}) +precompile(Tuple{typeof(Base.REPL.history_move_prefix), Base.LineEdit.PrefixSearchState, Base.REPL.REPLHistoryProvider, String, Bool, Int64}) +precompile(Tuple{typeof(Base.LineEdit.keymap), Base.LineEdit.PrefixSearchState, Base.LineEdit.PrefixHistoryPrompt{Base.REPL.REPLHistoryProvider}}) +precompile(Tuple{typeof(Base.LineEdit.terminal), Base.LineEdit.PrefixSearchState}) +precompile(Tuple{typeof(Base.LineEdit.keymap_data), Base.LineEdit.PrefixSearchState, Base.LineEdit.PrefixHistoryPrompt{Base.REPL.REPLHistoryProvider}}) +precompile(Tuple{typeof(Base.LineEdit.history_prev_prefix), Base.LineEdit.PrefixSearchState, Base.REPL.REPLHistoryProvider, String}) +precompile(Tuple{typeof(Base.getindex), Base.Dict{Symbol, Any}, Symbol}) +precompile(Tuple{typeof(Base.LineEdit.transition), Base.LineEdit.MIState, Base.LineEdit.Prompt}) +precompile(Tuple{typeof(Base.LineEdit.deactivate), Base.LineEdit.PrefixHistoryPrompt{Base.REPL.REPLHistoryProvider}, Base.LineEdit.PrefixSearchState, Base.Terminals.TerminalBuffer, Base.Terminals.TTYTerminal}) +precompile(Tuple{typeof(Base.LineEdit.refresh_multi_line), Base.Terminals.TTYTerminal, Base.LineEdit.PrefixSearchState}) +precompile(Tuple{typeof(Base.LineEdit.refresh_multi_line), Base.Terminals.TerminalBuffer, Base.Terminals.TerminalBuffer, Base.Terminals.TTYTerminal, Base.LineEdit.PrefixSearchState}) +precompile(Tuple{getfield(Base.LineEdit, Symbol("#kw##refresh_multi_line")), Array{Any, 1}, typeof(Base.LineEdit.refresh_multi_line), Base.Terminals.TerminalBuffer, Base.Terminals.TerminalBuffer, Base.Terminals.TTYTerminal, Base.LineEdit.PrefixSearchState}) +precompile(Tuple{getfield(Base.LineEdit, Symbol("#kw##refresh_multi_line")), Array{Any, 1}, typeof(Base.LineEdit.refresh_multi_line), Base.Terminals.TerminalBuffer, Base.Terminals.TTYTerminal, Base.LineEdit.PrefixSearchState}) +precompile(Tuple{typeof(Base.LineEdit.replace_line), Base.LineEdit.PrefixSearchState, Base.AbstractIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(Base.LineEdit.accept_result), Base.LineEdit.MIState, Base.LineEdit.PrefixHistoryPrompt{Base.REPL.REPLHistoryProvider}}) +precompile(Tuple{typeof(Core.Inference.length), Tuple{Core.Inference.Const, Core.Inference.Const, DataType}}) +precompile(Tuple{typeof(Core.Inference.getindex), Tuple{Core.Inference.Const, Core.Inference.Const, DataType}, Int64}) +precompile(Tuple{typeof(Base.LineEdit.replace_line), Base.LineEdit.PromptState, Base.AbstractIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(Base.LineEdit.match_input), Base.Dict{Char, Any}, Base.LineEdit.MIState, Base.AbstractIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(Base.LineEdit.edit_move_left), Base.AbstractIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(Base.LineEdit.edit_move_left), Base.LineEdit.PromptState}) +precompile(Tuple{typeof(Base.LineEdit.edit_move_right), Base.AbstractIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(Base.LineEdit.edit_move_right), Base.LineEdit.PromptState}) +precompile(Tuple{typeof(Base.LineEdit.move_line_start), Base.LineEdit.MIState}) +precompile(Tuple{typeof(Base.LineEdit.move_line_end), Base.AbstractIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(Base.LineEdit.move_line_end), Base.LineEdit.MIState}) +precompile(Tuple{typeof(Base.LineEdit.edit_move_up), Base.AbstractIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(Base.LineEdit.edit_move_up), Base.LineEdit.MIState}) +precompile(Tuple{typeof(Base.:(==)), Symbol, Base.LineEdit.Prompt}) +precompile(Tuple{typeof(Base.isempty), Base.LineEdit.PromptState}) +precompile(Tuple{typeof(Base.LineEdit.default_enter_cb), Base.LineEdit.PromptState}) +precompile(Tuple{typeof(Base.Docs.helpmode), String}) +precompile(Tuple{typeof(Base.ht_keyindex), Base.Dict{Symbol, Base.Docs.DocStr}, Symbol}) +precompile(Tuple{typeof(Base.Docs.helpmode), Base.TTY, String}) +precompile(Tuple{getfield(Base.Docs, Symbol("#@repl")), Base.TTY, Symbol}) +precompile(Tuple{typeof(Base.Docs.repl), Base.TTY, Symbol}) +precompile(Tuple{typeof(Base.Docs._repl), Symbol}) +precompile(Tuple{getfield(Core, Symbol("#@doc")), Symbol}) +precompile(Tuple{typeof(Base.Docs.docm), Symbol}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Any, Any}, Base.Markdown.Config, Symbol, Int64}) +precompile(Tuple{Type{Base.Markdown.MD}}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Any, Any}, Base.Markdown.Config, Symbol}) +precompile(Tuple{typeof(Base.Markdown.skipblank), Base.AbstractIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(Base.vcat), Array{Function, 1}, Array{Function, 1}}) +precompile(Tuple{typeof(Base.Docs.formatdoc), Base.Docs.DocStr}) +precompile(Tuple{typeof(Base.Docs.parsedoc), Base.Docs.DocStr}) +precompile(Tuple{typeof(Base.Docs.repl_latex), Base.TTY, String}) +precompile(Tuple{typeof(Base.ht_keyindex), Base.Dict{String, String}, String}) +precompile(Tuple{typeof(Base.ht_keyindex), Base.Dict{Symbol, Tuple{String, String}}, Symbol}) +precompile(Tuple{typeof(Base.print), Base.TTY, Char, Char}) +precompile(Tuple{typeof(Base.rehash!), Base.Dict{String, String}, Int64}) +precompile(Tuple{typeof(Base.ht_keyindex2), Base.Dict{String, String}, String}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{String, String}, String, String, Int64}) +precompile(Tuple{typeof(Core.Inference.isbits), Base.Dict{String, String}}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{String, String}, String, String}) +precompile(Tuple{typeof(Base.Docs.symbol_latex), String}) +precompile(Tuple{typeof(Base.Docs.repl_search), Base.TTY, String}) +precompile(Tuple{typeof(Base.print), Base.TTY, String}) +precompile(Tuple{typeof(Base.print), Base.TTY, Char}) +precompile(Tuple{typeof(Base.print), Base.TTY, String, Char}) +precompile(Tuple{typeof(Base.mapreduce_impl), typeof(Base.identity), typeof(Base.:(+)), Array{Int64, 1}, Int64, Int64, Int64}) +precompile(Tuple{typeof(Base._mapreduce), typeof(Base.identity), typeof(Base.:(+)), Base.IndexLinear, Array{Int64, 1}}) +precompile(Tuple{typeof(Base.shift!), Array{Char, 1}}) +precompile(Tuple{typeof(Base.Docs.avgdistance), Array{Int64, 1}}) +precompile(Tuple{typeof(Core.Inference.isbits), Tuple{Array{String, 1}}}) +precompile(Tuple{typeof(Base.Docs.accessible), Module}) +precompile(Tuple{Type{Base.Generator{I, F} where F where I}, typeof(Base.names), Array{Any, 1}}) +precompile(Tuple{typeof(Base.iteratoreltype), Type{Base.Generator{Array{Any, 1}, typeof(Base.names)}}}) +precompile(Tuple{typeof(Base.iteratorsize), Type{Base.Generator{Array{Any, 1}, typeof(Base.names)}}}) +precompile(Tuple{typeof(Base._collect), Array{Any, 1}, Base.Generator{Array{Any, 1}, typeof(Base.names)}, Base.EltypeUnknown, Base.HasShape}) +precompile(Tuple{typeof(Base.collect_to!), Array{Array{Symbol, 1}, 1}, Base.Generator{Array{Any, 1}, typeof(Base.names)}, Int64, Int64}) +precompile(Tuple{typeof(Base.names), Module}) +precompile(Tuple{typeof(Base.vcat), Array{Symbol, 1}, Array{Symbol, 1}, Array{Symbol, 1}, Array{String, 1}}) +precompile(Tuple{typeof(Base.throw_boundserror), Array{Symbol, 2}, Tuple{Base.UnitRange{Int64}}}) +precompile(Tuple{typeof(Base.unsafe_copy!), Array{Symbol, 2}, Int64, Array{Symbol, 1}, Int64, Int64}) +precompile(Tuple{typeof(Base.promote_eltype), Array{Symbol, 1}, Array{Symbol, 1}, Array{Symbol, 1}, Array{String, 1}}) +precompile(Tuple{typeof(Base.promote_eltype), Array{Symbol, 1}, Array{String, 1}}) +precompile(Tuple{typeof(Base.promote_eltype), Array{String, 1}}) +precompile(Tuple{typeof(Base.promote_type), Type{Symbol}, Type{String}}) +precompile(Tuple{typeof(Base.promote_rule), Type{Symbol}, Type{String}}) +precompile(Tuple{typeof(Base.promote_rule), Type{String}, Type{Symbol}}) +precompile(Tuple{typeof(Base.promote_result), Type{Symbol}, Type{String}, Type{Union{}}, Type{Union{}}}) +precompile(Tuple{typeof(Base.typed_vcat), Type{Any}, Array{Symbol, 1}, Array{Symbol, 1}, Array{Symbol, 1}, Array{String, 1}}) +precompile(Tuple{typeof(Base.setindex!), Array{Any, 1}, Array{Symbol, 1}, Base.UnitRange{Int64}}) +precompile(Tuple{typeof(Base.setindex!), Array{Any, 1}, Array{String, 1}, Base.UnitRange{Int64}}) +precompile(Tuple{typeof(Base.throw_setindex_mismatch), Array{String, 1}, Tuple{Int64}}) +precompile(Tuple{typeof(Base.setindex_shape_check), Array{String, 1}, Int64}) +precompile(Tuple{typeof(Base.unique), Array{Any, 1}}) +precompile(Tuple{typeof(Base.getindex), Type{Symbol}, Symbol}) +precompile(Tuple{Type{Base.Set{Symbol}}, Tuple{Symbol}}) +precompile(Tuple{typeof(Base.union!), Base.Set{Symbol}, Tuple{Symbol}}) +precompile(Tuple{typeof(Base.unique_from), Array{Any, 1}, Array{Symbol, 1}, Base.Set{Symbol}, Int64}) +precompile(Tuple{typeof(Base.convert), Type{Base.Set{Any}}, Base.Set{Symbol}}) +precompile(Tuple{typeof(Base.ht_keyindex2), Base.Dict{Any, Void}, Symbol}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Any, Void}, Void, Symbol, Int64}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Any, Void}, Void, Symbol}) +precompile(Tuple{typeof(Base.union!), Base.Set{Any}, Base.Set{Symbol}}) +precompile(Tuple{typeof(Base.convert), Type{Array{Any, 1}}, Array{Symbol, 1}}) +precompile(Tuple{typeof(Base.copy!), Base.IndexLinear, Array{Any, 1}, Base.IndexLinear, Array{Symbol, 1}}) +precompile(Tuple{typeof(Base.:(==)), String, Symbol}) +precompile(Tuple{typeof(Base.unique_from), Array{Any, 1}, Array{Any, 1}, Base.Set{Any}, Int64}) +precompile(Tuple{Type{Base.Generator{I, F} where F where I}, typeof(Base.string), Array{Any, 1}}) +precompile(Tuple{typeof(Base.iteratoreltype), Type{Base.Generator{Array{Any, 1}, typeof(Base.string)}}}) +precompile(Tuple{typeof(Base.iteratorsize), Type{Base.Generator{Array{Any, 1}, typeof(Base.string)}}}) +precompile(Tuple{typeof(Base._collect), Array{Any, 1}, Base.Generator{Array{Any, 1}, typeof(Base.string)}, Base.EltypeUnknown, Base.HasShape}) +precompile(Tuple{typeof(Base.similar), Array{Any, 1}, Type{String}, Tuple{Base.OneTo{Int64}}}) +precompile(Tuple{typeof(Base.collect_to!), Array{String, 1}, Base.Generator{Array{Any, 1}, typeof(Base.string)}, Int64, Int64}) +precompile(Tuple{typeof(Base.UTF8proc.isalpha), Char}) +precompile(Tuple{getfield(Base.Docs, Symbol("#kw##matchinds")), Array{Any, 1}, typeof(Base.Docs.matchinds), String, String}) +precompile(Tuple{typeof(Base.Docs.bestmatch), String, String}) +precompile(Tuple{typeof(Base.length), Tuple{DataType, DataType}}) +precompile(Tuple{Type{BoundsError}, Array{Int64, 2}, Tuple{Base.UnitRange{Int64}, Int64}}) +precompile(Tuple{typeof(Base.throw_boundserror), Array{Int64, 2}, Tuple{Base.UnitRange{Int64}, Int64}}) +precompile(Tuple{getfield(Base.Cartesian, Symbol("#@nexprs")), Int64, Expr}) +precompile(Tuple{typeof(Base.Cartesian._nexprs), Int64, Expr}) +precompile(Tuple{typeof(Core.Inference.findnext), Array{Function, 1}, typeof(===), Int64}) +precompile(Tuple{typeof(Core.Inference.builtin_tfunction), typeof(===), Array{Any, 1}, Core.Inference.InferenceState, Core.Inference.InferenceParams}) +precompile(Tuple{typeof(Core.Inference.typeinf_frame), Core.MethodInstance, Void, Bool, Bool, Core.Inference.InferenceParams}) +precompile(Tuple{typeof(Core.Inference.typeinf_loop), Core.Inference.InferenceState}) +precompile(Tuple{typeof(Core.Inference.typeinf_frame), Core.Inference.InferenceState}) +precompile(Tuple{typeof(Base.Cartesian.inlineanonymous), Expr, Int64}) +precompile(Tuple{typeof(Base.Cartesian.lreplace), Expr, Symbol, Int64}) +precompile(Tuple{typeof(Base.copy), Expr}) +precompile(Tuple{typeof(Base.copy_exprargs), Array{Any, 1}}) +precompile(Tuple{typeof(Base.collect), Type{Any}, Base.Generator{Array{Any, 1}, typeof(Base.copy_exprs)}}) +precompile(Tuple{typeof(Base._collect), Type{Any}, Base.Generator{Array{Any, 1}, typeof(Base.copy_exprs)}, Base.HasShape}) +precompile(Tuple{typeof(Base.copy!), Array{Any, 1}, Base.Generator{Array{Any, 1}, typeof(Base.copy_exprs)}}) +precompile(Tuple{typeof(Base.next), Base.Generator{Array{Any, 1}, typeof(Base.copy_exprs)}, Int64}) +precompile(Tuple{typeof(Base.copy_exprs), Expr}) +precompile(Tuple{typeof(Base.Cartesian.lreplace!), Expr, Base.Cartesian.LReplace{String}}) +precompile(Tuple{typeof(Base.Cartesian.lreplace!), Symbol, Base.Cartesian.LReplace{String}}) +precompile(Tuple{typeof(Base.Cartesian.lreplace!), String, Base.Cartesian.LReplace{String}}) +precompile(Tuple{typeof(Base.Cartesian.exprresolve), Expr}) +precompile(Tuple{Type{BoundsError}, Array{Expr, 1}, Base.UnitRange{Int64}}) +precompile(Tuple{getfield(Base.Cartesian, Symbol("#@ncall")), Int64, Symbol, Symbol}) +precompile(Tuple{typeof(Base.Cartesian._ncall), Int64, Symbol, Symbol}) +precompile(Tuple{typeof(Base.getindex), Tuple{Symbol}, Base.UnitRange{Int64}}) +precompile(Tuple{getfield(Base.Cartesian, Symbol("#@ncall")), Int64, Symbol, Symbol, Expr}) +precompile(Tuple{typeof(Base.Cartesian._ncall), Int64, Symbol, Symbol, Expr}) +precompile(Tuple{typeof(Base.endof), Tuple{Symbol, Expr}}) +precompile(Tuple{typeof(Base.getindex), Tuple{Symbol, Expr}, Base.UnitRange{Int64}}) +precompile(Tuple{getfield(Base.Cartesian, Symbol("#@nloops")), Int64, Symbol, Expr, Expr}) +precompile(Tuple{typeof(Base.Cartesian._nloops), Int64, Symbol, Expr, Expr}) +precompile(Tuple{typeof(Base.endof), Tuple{Expr}}) +precompile(Tuple{typeof(Base.endof), Tuple{Symbol, Symbol, Symbol}}) +precompile(Tuple{typeof(Base.getindex), Tuple{Symbol, Symbol, Symbol}, Base.UnitRange{Int64}}) +precompile(Tuple{Type{Expr}, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol}) +precompile(Tuple{typeof(Base.join), Base.AbstractIOBuffer{Array{UInt8, 1}}, Tuple{String, String}, Char}) +precompile(Tuple{typeof(Base.dims2string), Tuple{Int64, Int64}}) +precompile(Tuple{typeof(Base.throw_setindex_mismatch), Base.UnitRange{Int64}, Tuple{Int64, Int64}}) +precompile(Tuple{typeof(Base.setindex_shape_check), Base.UnitRange{Int64}, Int64, Int64}) +precompile(Tuple{typeof(Base._unsafe_setindex!), Base.IndexLinear, Array{Int64, 2}, Base.UnitRange{Int64}, Base.UnitRange{Int64}, Int64}) +precompile(Tuple{Type{BoundsError}, Array{Int64, 2}, Tuple{Int64, Base.UnitRange{Int64}}}) +precompile(Tuple{typeof(Base.throw_boundserror), Array{Int64, 2}, Tuple{Int64, Base.UnitRange{Int64}}}) +precompile(Tuple{typeof(Base._unsafe_setindex!), Base.IndexLinear, Array{Int64, 2}, Base.UnitRange{Int64}, Int64, Base.UnitRange{Int64}}) +precompile(Tuple{typeof(Base.Docs.levenshtein), String, String}) +precompile(Tuple{typeof(Base.Docs.fuzzyscore), String, String}) +precompile(Tuple{typeof(Core.Inference.copy_exprargs), Array{Any, 1}}) +precompile(Tuple{typeof(Core.Inference.copy), Expr}) +precompile(Tuple{typeof(Core.Inference.copy!), Array{Any, 1}, Core.Inference.Generator{Array{Any, 1}, typeof(Core.Inference.copy_exprs)}}) +precompile(Tuple{typeof(Core.Inference._widen_all_consts!), Expr, Array{Bool, 1}}) +precompile(Tuple{typeof(Core.Inference._delete!), Core.Inference.IntSet, Int64}) +precompile(Tuple{typeof(Core.Inference.promote_type), Type{Float16}, Type{Int64}}) +precompile(Tuple{typeof(Core.Inference.mk_tuplecall), Array{Any, 1}, Core.Inference.InferenceState}) +precompile(Tuple{typeof(Core.Inference.get_source), Core.MethodInstance}) +precompile(Tuple{typeof(Core.Inference.inlining_pass), Expr, Core.Inference.InferenceState, Array{Any, 1}, Int64}) +precompile(Tuple{typeof(Core.Inference.annotate_slot_load!), Expr, Array{Any, 1}, Core.Inference.InferenceState, Array{Bool, 1}}) +precompile(Tuple{typeof(Core.Inference.record_slot_assign!), Core.Inference.InferenceState}) +precompile(Tuple{typeof(Core.Inference.type_annotate!), Core.Inference.InferenceState}) +precompile(Tuple{typeof(Core.Inference.inlining_pass!), Core.Inference.InferenceState}) +precompile(Tuple{typeof(Core.Inference.alloc_elim_pass!), Core.Inference.InferenceState}) +precompile(Tuple{typeof(Core.Inference.getfield_elim_pass!), Core.Inference.InferenceState}) +precompile(Tuple{typeof(Core.Inference.popmeta!), Array{Any, 1}, Symbol}) +precompile(Tuple{typeof(Core.Inference.widen_all_consts!), CodeInfo}) +precompile(Tuple{typeof(Core.Inference.stupdate!), Array{Any, 1}, Array{Any, 1}}) +precompile(Tuple{typeof(Core.Inference.push!), Core.Inference.IntSet, Int64}) +precompile(Tuple{typeof(Core.Inference.abstract_eval_call), Expr, Array{Any, 1}, Core.Inference.InferenceState}) +precompile(Tuple{typeof(Core.Inference.return_type_tfunc), Array{Any, 1}, Array{Any, 1}, Core.Inference.InferenceState}) +precompile(Tuple{typeof(Core.Inference.abstract_call), typeof(===), Tuple{}, Array{Any, 1}, Array{Any, 1}, Core.Inference.InferenceState}) +precompile(Tuple{typeof(Core.Inference.abstract_call), typeof(===), Array{Any, 1}, Array{Any, 1}, Array{Any, 1}, Core.Inference.InferenceState}) +precompile(Tuple{typeof(Core.Inference.type_too_complex), TypeVar, Int64}) +precompile(Tuple{typeof(Core.Inference.typeinf_frame), Core.MethodInstance, Core.Inference.InferenceState, Bool, Bool, Core.Inference.InferenceParams}) +precompile(Tuple{typeof(Core.Inference.abstract_eval), Expr, Array{Any, 1}, Core.Inference.InferenceState}) +precompile(Tuple{typeof(Core.Inference._setint!), Core.Inference.IntSet, Int64, Bool}) +precompile(Tuple{typeof(Core.Inference.stupdate1!), Array{Any, 1}, Core.Inference.StateUpdate}) +precompile(Tuple{typeof(Core.Inference.optimize), Core.Inference.InferenceState}) +precompile(Tuple{typeof(Core.Inference.deleteat!), Core.Inference.BitArray{1}, Core.Inference.UnitRange{Int64}}) +precompile(Tuple{typeof(Core.Inference.resize!), Core.Inference.BitArray{1}, Int64}) +precompile(Tuple{typeof(Core.Inference.copy_chunks!), Array{UInt64, 1}, Int64, Array{UInt64, 1}, Int64, Int64}) +precompile(Tuple{typeof(Core.Inference.copy_chunks_rtol!), Array{UInt64, 1}, Int64, Int64, Int64}) +precompile(Tuple{typeof(Core.Inference.find_ssavalue_uses), Array{Any, 1}}) +precompile(Tuple{typeof(Base.sortperm), Array{Tuple{Float64, Int64}, 1}}) +precompile(Tuple{Type{Base.Order.Perm{O, V} where V<:(AbstractArray{T, 1} where T) where O<:Base.Order.Ordering}, Base.Order.ForwardOrdering, Array{Tuple{Float64, Int64}, 1}}) +precompile(Tuple{typeof(Base.sort!), Array{Int64, 1}, Base.Sort.QuickSortAlg, Base.Order.Perm{Base.Order.ForwardOrdering, Array{Tuple{Float64, Int64}, 1}}}) +precompile(Tuple{typeof(Base.isequal), Float64, Float64}) +precompile(Tuple{typeof(Base.isequal), Int64, Float64}) +precompile(Tuple{typeof(Base.isequal), Float64, Int64}) +precompile(Tuple{typeof(Base.isless), Int64, Float64}) +precompile(Tuple{typeof(Base.isless), Float64, Int64}) +precompile(Tuple{typeof(Base.isless), Tuple{Float64, Int64}, Tuple{Float64, Int64}}) +precompile(Tuple{typeof(Base.sort!), Array{Int64, 1}, Int64, Int64, Base.Sort.InsertionSortAlg, Base.Order.Perm{Base.Order.ForwardOrdering, Array{Tuple{Float64, Int64}, 1}}}) +precompile(Tuple{typeof(Base.Sort.partition!), Array{Int64, 1}, Int64, Int64, Base.Order.Perm{Base.Order.ForwardOrdering, Array{Tuple{Float64, Int64}, 1}}}) +precompile(Tuple{typeof(Base.sort!), Array{Int64, 1}, Int64, Int64, Base.Sort.QuickSortAlg, Base.Order.Perm{Base.Order.ForwardOrdering, Array{Tuple{Float64, Int64}, 1}}}) +precompile(Tuple{typeof(Base.getindex), Array{String, 1}, Array{Int64, 1}}) +precompile(Tuple{typeof(Base.throw_boundserror), Array{String, 1}, Tuple{Array{Int64, 1}}}) +precompile(Tuple{typeof(Base.throw_checksize_error), Array{String, 1}, Tuple{Base.OneTo{Int64}}}) +precompile(Tuple{typeof(Base._unsafe_getindex), Base.IndexLinear, Array{String, 1}, Array{Int64, 1}}) +precompile(Tuple{typeof(Base.reverse), Array{String, 1}}) +precompile(Tuple{typeof(Base.reverse), Array{String, 1}, Int64, Int64}) +precompile(Tuple{getfield(Base.Docs, Symbol("#kw##printmatches")), Array{Any, 1}, typeof(Base.Docs.printmatches), Base.TTY, String, Array{String, 1}}) +precompile(Tuple{typeof(Base.Docs.printmatch), Base.TTY, String, String}) +precompile(Tuple{typeof(Base.Markdown.with_output_format), typeof(Base.print), Array{Symbol, 1}, Base.TTY, Char}) +precompile(Tuple{typeof(Base.Docs.doc), Base.Docs.Binding}) +precompile(Tuple{typeof(Base.print), Base.AbstractIOBuffer{Array{UInt8, 1}}, String, Base.Docs.Binding, String, String, String, Char}) +precompile(Tuple{typeof(Base.show_method_table), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.MethodList, Int64, Bool}) +precompile(Tuple{typeof(Base.print), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.MethodList}) +precompile(Tuple{typeof(Base.print), Base.AbstractIOBuffer{Array{UInt8, 1}}, String, Base.MethodList, String, Char}) +precompile(Tuple{typeof(Base.print), Base.AbstractIOBuffer{Array{UInt8, 1}}, String, String, DataType, String, DataType, Char}) +precompile(Tuple{typeof(Base.print), Base.AbstractIOBuffer{Array{UInt8, 1}}, DataType, Char}) +precompile(Tuple{typeof(Base.print), Base.AbstractIOBuffer{Array{UInt8, 1}}, typeof(Type), Char}) +precompile(Tuple{typeof(Base.print), Base.AbstractIOBuffer{Array{UInt8, 1}}, String, Module, String, Char}) +precompile(Tuple{typeof(Base.Pkg.dir), String, String}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Any, Any}, Array{Base.Docs.DocStr, 1}, Symbol, Int64}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Any, Any}, Base.Docs.Binding, Symbol, Int64}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Any, Any}, Type{Union{}}, Symbol, Int64}) +precompile(Tuple{typeof(Base._collect), Array{Base.Docs.DocStr, 1}, Base.Generator{Array{Base.Docs.DocStr, 1}, typeof(Base.Docs.parsedoc)}, Base.EltypeUnknown, Base.HasShape}) +precompile(Tuple{typeof(Base.ht_keyindex2), Base.Dict{Union{DataType, typeof(Type)}, Void}, typeof(Type)}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Union{DataType, typeof(Type)}, Void}, Void, typeof(Type), Int64}) +precompile(Tuple{typeof(Base.ht_keyindex2), Base.Dict{Union{DataType, typeof(Type)}, Void}, DataType}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Union{DataType, typeof(Type)}, Void}, Void, DataType, Int64}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Union{DataType, typeof(Type)}, Void}, Void, DataType}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Union{DataType, typeof(Type)}, Void}, Void, typeof(Type)}) +precompile(Tuple{typeof(Base.rehash!), Base.Dict{Union{DataType, typeof(Type)}, Void}, Int64}) +precompile(Tuple{typeof(Base._subtypes), Module, DataType, Base.Set{Union{DataType, typeof(Type)}}, Base.Set{Module}}) +precompile(Tuple{typeof(Base._subtypes), Module, DataType}) +precompile(Tuple{typeof(Base.isempty), Array{Int64, 1}}) +precompile(Tuple{typeof(Base.Iterators.zip), Array{Int64, 1}, SimpleVector}) +precompile(Tuple{typeof(Base.Iterators.zip), Array{Symbol, 1}, SimpleVector}) +precompile(Tuple{typeof(Base.start), Base.Iterators.Zip2{Array{Int64, 1}, SimpleVector}}) +precompile(Tuple{typeof(Base.start), Base.Iterators.Zip2{Array{Symbol, 1}, SimpleVector}}) +precompile(Tuple{typeof(Base.done), Base.Iterators.Zip2{Array{Int64, 1}, SimpleVector}, Tuple{Int64, Int64}}) +precompile(Tuple{typeof(Base.done), Base.Iterators.Zip2{Array{Symbol, 1}, SimpleVector}, Tuple{Int64, Int64}}) +precompile(Tuple{typeof(Base.next), Base.Iterators.Zip2{Array{Int64, 1}, SimpleVector}, Tuple{Int64, Int64}}) +precompile(Tuple{typeof(Base.next), Base.Iterators.Zip2{Array{Symbol, 1}, SimpleVector}, Tuple{Int64, Int64}}) +precompile(Tuple{typeof(Base.println), Base.AbstractIOBuffer{Array{UInt8, 1}}, DataType}) +precompile(Tuple{typeof(Base.println), Base.AbstractIOBuffer{Array{UInt8, 1}}, typeof(Type)}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Any, Any}, Array{Base.Docs.DocStr, 1}, Symbol}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Any, Any}, Base.Docs.Binding, Symbol}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Any, Any}, Type{Union{}}, Symbol}) +precompile(Tuple{typeof(Base.Docs.aliasof), Base.Docs.Binding}) +precompile(Tuple{typeof(Base.Docs.summarize), Base.Docs.Binding, Type{Union{}}}) +precompile(Tuple{typeof(Base.Docs.doc), Base.Docs.Binding, Type{Union{}}}) +precompile(Tuple{typeof(Base.haskey), Base.ObjectIdDict, Base.Docs.Binding}) +precompile(Tuple{typeof(Base.getindex), Base.ObjectIdDict, Base.Docs.Binding}) +precompile(Tuple{typeof(Base.push!), Array{Base.Docs.MultiDoc, 1}, Base.Docs.MultiDoc}) +precompile(Tuple{typeof(Base.start), Array{Type{T} where T, 1}}) +precompile(Tuple{typeof(Base.done), Array{Type{T} where T, 1}, Int64}) +precompile(Tuple{typeof(Base.next), Array{Type{T} where T, 1}, Int64}) +precompile(Tuple{typeof(Base.getindex), Base.ObjectIdDict, Type{Tuple{Any}}}) +precompile(Tuple{typeof(Base.push!), Array{Base.Docs.DocStr, 1}, Base.Docs.DocStr}) +precompile(Tuple{typeof(Base.Docs.formatdoc), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.Docs.DocStr, String}) +precompile(Tuple{typeof(Base.Markdown.hashheader), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.Markdown.MD}) +precompile(Tuple{typeof(Base.Markdown.parseinline), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.Markdown.MD, Array{Function, 1}}) +precompile(Tuple{typeof(Base.Markdown.config), Base.Markdown.MD}) +precompile(Tuple{typeof(Base.Markdown.parseinline), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.Markdown.MD, Base.Markdown.Config}) +precompile(Tuple{typeof(Base.Markdown.list), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.Markdown.MD}) +precompile(Tuple{typeof(Base.searchindex), String, String}) +precompile(Tuple{typeof(Base._searchindex), Base.SubString{String}, String, Int64}) +precompile(Tuple{getfield(Base.Markdown, Symbol("#kw##skipwhitespace")), Array{Any, 1}, typeof(Base.Markdown.skipwhitespace), Base.AbstractIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(Base.ht_keyindex), Base.Dict{Symbol, Base.Markdown.Config}, Symbol}) +precompile(Tuple{getfield(Base.Markdown, Symbol("#kw##parse")), Array{Any, 1}, typeof(Base.Markdown.parse), Base.AbstractIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{getfield(Base.Markdown, Symbol("#kw##startswith")), Array{Any, 1}, typeof(Base.Markdown.startswith), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.Regex}) +precompile(Tuple{typeof(Core.Inference.isbits), Tuple{Int64, Base.Regex}}) +precompile(Tuple{typeof(Base.contains), String, String}) +precompile(Tuple{typeof(Base.contains), Base.SubString{String}, String}) +precompile(Tuple{typeof(Base.Markdown.pushitem!), Base.Markdown.List, Base.AbstractIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(Base.Markdown.fencedcode), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.Markdown.MD}) +precompile(Tuple{getfield(Base.Markdown, Symbol("#kw##startswith")), Array{Any, 1}, typeof(Base.Markdown.startswith), Base.AbstractIOBuffer{Array{UInt8, 1}}, String}) +precompile(Tuple{typeof(Base.skip), Base.AbstractIOBuffer{Array{UInt8, 1}}, Int64}) +precompile(Tuple{typeof(Base.lstrip), String, Char}) +precompile(Tuple{typeof(Base.Markdown.blockquote), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.Markdown.MD}) +precompile(Tuple{getfield(Base.Markdown, Symbol("#kw##parse")), Array{Any, 1}, typeof(Base.Markdown.parse), String}) +precompile(Tuple{typeof(Base.Markdown.admonition), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.Markdown.MD}) +precompile(Tuple{typeof(Base.UTF8proc.isupper), Char}) +precompile(Tuple{getfield(Base.Markdown, Symbol("#kw##linecontains")), Array{Any, 1}, typeof(Base.Markdown.linecontains), Base.AbstractIOBuffer{Array{UInt8, 1}}, String}) +precompile(Tuple{typeof(Base.ucfirst), Base.SubString{String}}) +precompile(Tuple{typeof(Base.Markdown.blocktex), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.Markdown.MD}) +precompile(Tuple{typeof(Core.Inference.length), Tuple{DataType, Core.Inference.Const, DataType}}) +precompile(Tuple{typeof(Core.Inference.getindex), Tuple{DataType, Core.Inference.Const, DataType}, Int64}) +precompile(Tuple{getfield(Base.Markdown, Symbol("#kw##parse_inline_wrapper")), Array{Any, 1}, typeof(Base.Markdown.parse_inline_wrapper), Base.AbstractIOBuffer{Array{UInt8, 1}}, String}) +precompile(Tuple{typeof(Base.Markdown.startswith), Base.AbstractIOBuffer{Array{UInt8, 1}}, String}) +precompile(Tuple{typeof(Base.Markdown.blockinterp), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.Markdown.MD}) +precompile(Tuple{getfield(Base, Symbol("#kw##parse")), Array{Any, 1}, typeof(Base.parse), Base.AbstractIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(Base.Markdown.interpinner), Base.AbstractIOBuffer{Array{UInt8, 1}}, Bool}) +precompile(Tuple{typeof(Base.Markdown.indentcode), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.Markdown.MD}) +precompile(Tuple{typeof(Base.Markdown.footnote), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.Markdown.MD}) +precompile(Tuple{Type{Base.Markdown.Footnote}, Void, Array{Any, 1}}) +precompile(Tuple{Type{Base.Markdown.Footnote}, Base.SubString{String}, Array{Any, 1}}) +precompile(Tuple{typeof(Base.Markdown.github_table), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.Markdown.MD}) +precompile(Tuple{typeof(Base.replace), String, String, String, Int64}) +precompile(Tuple{typeof(Base.pop!), Array{Base.SubString{String}, 1}}) +precompile(Tuple{typeof(Base.union!), Base.Set{Char}, String}) +precompile(Tuple{typeof(Base.ht_keyindex), Base.Dict{Char, Void}, Char}) +precompile(Tuple{typeof(Base.issubset), Base.SubString{String}, Base.Set{Char}}) +precompile(Tuple{typeof(Core.Inference.length), Tuple{Core.Inference.Const, Core.Inference.Const, Core.Inference.Const, Core.Inference.Const, Core.Inference.Const}}) +precompile(Tuple{typeof(Core.Inference.getindex), Tuple{Core.Inference.Const, Core.Inference.Const, Core.Inference.Const, Core.Inference.Const, Core.Inference.Const}, Int64}) +precompile(Tuple{typeof(Base.throw_boundserror), Base.SubArray{UInt8, 1, Array{UInt8, 1}, Tuple{Base.UnitRange{Int64}}, true}, Tuple{Int64}}) +precompile(Tuple{typeof(Base.peek), Base.AbstractIOBuffer{Base.SubArray{UInt8, 1, Array{UInt8, 1}, Tuple{Base.UnitRange{Int64}}, true}}}) +precompile(Tuple{typeof(Base.Markdown.parseinline), Base.AbstractIOBuffer{Base.SubArray{UInt8, 1, Array{UInt8, 1}, Tuple{Base.UnitRange{Int64}}, true}}, Base.Markdown.MD, Array{Function, 1}}) +precompile(Tuple{typeof(Base.read), Base.AbstractIOBuffer{Base.SubArray{UInt8, 1, Array{UInt8, 1}, Tuple{Base.UnitRange{Int64}}, true}}, Type{Char}}) +precompile(Tuple{typeof(Base.Markdown.parseinline), Base.AbstractIOBuffer{Base.SubArray{UInt8, 1, Array{UInt8, 1}, Tuple{Base.UnitRange{Int64}}, true}}, Base.Markdown.MD, Base.Markdown.Config}) +precompile(Tuple{typeof(Base.copy!), Base.IndexLinear, Array{Array{Any, 1}, 1}, Base.IndexLinear, Array{Any, 1}}) +precompile(Tuple{typeof(Base.Markdown.parsealign), Void}) +precompile(Tuple{typeof(Base.Markdown.parsealign), Array{Base.SubString{String}, 1}}) +precompile(Tuple{typeof(Base.Markdown.rowlength!), Void, Int64}) +precompile(Tuple{typeof(Base.Markdown.rowlength!), Array{Base.SubString{String}, 1}, Int64}) +precompile(Tuple{Type{Base.Markdown.Table}, Array{Any, 1}, Void}) +precompile(Tuple{Type{Base.Markdown.Table}, Array{Any, 1}, Array{Symbol, 1}}) +precompile(Tuple{typeof(Base.Markdown.horizontalrule), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.Markdown.MD}) +precompile(Tuple{typeof(Core.Inference.isbits), Base.Markdown.HorizontalRule}) +precompile(Tuple{typeof(Base.Markdown.setextheader), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.Markdown.MD}) +precompile(Tuple{typeof(Base.Markdown.paragraph), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.Markdown.MD}) +precompile(Tuple{getfield(Base.Markdown, Symbol("#kw##parse")), Array{Any, 1}, typeof(Base.Markdown.parse), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.Markdown.MD, Base.Markdown.Config}) +precompile(Tuple{getfield(Base.Markdown, Symbol("#kw##parse")), Array{Any, 1}, typeof(Base.Markdown.parse), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.Markdown.MD}) +precompile(Tuple{typeof(Base.Markdown.inline_code), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.Markdown.MD}) +precompile(Tuple{typeof(Base.Markdown.readuntil), Base.AbstractIOBuffer{Array{UInt8, 1}}, String}) +precompile(Tuple{typeof(Base.Markdown.readuntil), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.SubString{String}}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Any, Any}, Module, Symbol}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Any, Any}, Module, Symbol, Int64}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Any, Any}, String, Symbol}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Any, Any}, String, Symbol, Int64}) +precompile(Tuple{typeof(Base.similar), Array{Base.Docs.DocStr, 1}, Type{Base.Markdown.MD}, Tuple{Base.OneTo{Int64}}}) +precompile(Tuple{typeof(Base.setindex!), Array{Base.Markdown.MD, 1}, Base.Markdown.MD, Int64}) +precompile(Tuple{typeof(Base.collect_to!), Array{Base.Markdown.MD, 1}, Base.Generator{Array{Base.Docs.DocStr, 1}, typeof(Base.Docs.parsedoc)}, Int64, Int64}) +precompile(Tuple{typeof(Base.unsafe_copy!), Array{Base.Markdown.MD, 1}, Int64, Array{Base.Markdown.MD, 1}, Int64, Int64}) +precompile(Tuple{typeof(Base.Docs.catdoc), Base.Markdown.MD}) +precompile(Tuple{typeof(Base.copy!), Base.IndexLinear, Array{Any, 1}, Base.IndexLinear, Array{Base.Markdown.MD, 1}}) +precompile(Tuple{Type{Base.Markdown.MD}, Array{Base.Markdown.MD, 1}}) +precompile(Tuple{Type{Base.Markdown.MD}, Base.Markdown.MD}) +precompile(Tuple{typeof(Base.vcat), Base.Markdown.MD}) +precompile(Tuple{typeof(Base.put!), Base.Channel{Any}, Tuple{Base.Markdown.MD, Void}}) +precompile(Tuple{typeof(Base.put_buffered), Base.Channel{Any}, Tuple{Base.Markdown.MD, Void}}) +precompile(Tuple{typeof(Base.put_unbuffered), Base.Channel{Any}, Tuple{Base.Markdown.MD, Void}}) +precompile(Tuple{typeof(Base.start), Tuple{Base.Markdown.MD, Void}}) +precompile(Tuple{typeof(Base.indexed_next), Tuple{Base.Markdown.MD, Void}, Int64, Int64}) +precompile(Tuple{typeof(Base.Multimedia.display), Base.Markdown.MD}) +precompile(Tuple{typeof(Base.Multimedia.display), Base.REPL.REPLDisplay{Base.REPL.LineEditREPL}, Base.Markdown.MD}) +precompile(Tuple{typeof(Base.displaysize), Base.Terminals.TTYTerminal}) +precompile(Tuple{typeof(Base.Markdown.term), Base.Terminals.TTYTerminal, Array{Any, 1}, Int64}) +precompile(Tuple{typeof(Base.Markdown.term), Base.Terminals.TTYTerminal, Base.Markdown.MD, Int64}) +precompile(Tuple{typeof(Base.Markdown.term), Base.Terminals.TTYTerminal, Base.Markdown.Code, Int64}) +precompile(Tuple{typeof(Base.write), Base.Terminals.TTYTerminal, Base.SubString{String}}) +precompile(Tuple{typeof(Base.print), Base.Terminals.TTYTerminal, Base.SubString{String}}) +precompile(Tuple{typeof(Base.print), Base.Terminals.TTYTerminal, Base.SubString{String}, Char}) +precompile(Tuple{typeof(Base.Markdown.term), Base.Terminals.TTYTerminal, Base.Markdown.Paragraph, Int64}) +precompile(Tuple{typeof(Core.Inference.eltype), Type{Array{T, 2} where T}}) +precompile(Tuple{getfield(Base.Markdown, Symbol("#kw##wrapped_lines")), Array{Any, 1}, typeof(Base.Markdown.wrapped_lines), String}) +precompile(Tuple{typeof(Base.start), Tuple{Symbol, String}}) +precompile(Tuple{typeof(Base.Markdown.terminline), Base.AbstractIOBuffer{Array{UInt8, 1}}, Array{Any, 1}}) +precompile(Tuple{typeof(Base.Markdown.terminline), Base.AbstractIOBuffer{Array{UInt8, 1}}, String}) +precompile(Tuple{typeof(Base.Markdown.terminline), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.Markdown.Code}) +precompile(Tuple{typeof(Base._search), Base.SubString{String}, String, Int64}) +precompile(Tuple{typeof(Base._split), Base.SubString{String}, String, Int64, Bool, Array{Base.SubString{String}, 1}}) +precompile(Tuple{getfield(Base.Markdown, Symbol("#kw##wrapped_lines")), Array{Any, 1}, typeof(Base.Markdown.wrapped_lines), Base.SubString{String}}) +precompile(Tuple{typeof(Base.endof), Array{AbstractString, 1}}) +precompile(Tuple{typeof(Base.getindex), Array{AbstractString, 1}, Base.UnitRange{Int64}}) +precompile(Tuple{typeof(Base.throw_boundserror), Array{AbstractString, 1}, Tuple{Base.UnitRange{Int64}}}) +precompile(Tuple{typeof(Base.unsafe_copy!), Array{AbstractString, 1}, Int64, Array{AbstractString, 1}, Int64, Int64}) +precompile(Tuple{typeof(Base.start), Array{AbstractString, 1}}) +precompile(Tuple{typeof(Base.done), Array{AbstractString, 1}, Int64}) +precompile(Tuple{typeof(Base.replace), String, Base.Regex, String}) +precompile(Tuple{typeof(Base.Distributed.addprocs), Int64}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Any, Any}, Base.Cmd, Symbol}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Any, Any}, Base.Cmd, Symbol, Int64}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Any, Any}, Bool, Symbol}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Any, Any}, Bool, Symbol, Int64}) +precompile(Tuple{typeof(Base.merge!), Base.Dict{Any, Any}, Base.Dict{Any, Any}, Base.Dict{Any, Any}}) +precompile(Tuple{Type{Symbol}, Symbol}) +precompile(Tuple{typeof(Core.Inference.mk_getfield), TypedSlot, Int64, Type{String}}) +precompile(Tuple{getfield(Core, Symbol("#kw#Type")), Array{Any, 1}, Type{Base.Cmd}, Base.Cmd}) +precompile(Tuple{typeof(Base.uv_status_string), Base.PipeEndpoint}) +precompile(Tuple{typeof(Base._fd), Base.PipeEndpoint}) +precompile(Tuple{typeof(Base.print), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.PipeEndpoint}) +precompile(Tuple{typeof(Base.unpreserve_handle), Base.PipeEndpoint}) +precompile(Tuple{typeof(Base.isopen), Base.PipeEndpoint}) +precompile(Tuple{typeof(Base.stream_wait), Base.PipeEndpoint, Base.Condition}) +precompile(Tuple{typeof(Base.close), Base.PipeEndpoint}) +precompile(Tuple{getfield(Base, Symbol("#kw##setenv")), Array{Any, 1}, typeof(Base.setenv), Base.Cmd}) +precompile(Tuple{Type{Base.Distributed.WorkerConfig}}) +precompile(Tuple{typeof(Base.Distributed.launch), Base.Distributed.LocalManager, Base.Dict{Any, Any}, Array{Base.Distributed.WorkerConfig, 1}, Base.Condition}) +precompile(Tuple{typeof(Base.julia_cmd), String}) +precompile(Tuple{typeof(Base.cmd_gen), Tuple{Tuple{String}, Tuple{String, String}, Tuple{String, String}, Tuple{String, String}, Tuple{String, String}}}) +precompile(Tuple{typeof(Base.arg_gen), String, String}) +precompile(Tuple{typeof(Base.cmd_gen), Tuple{Tuple{Base.Cmd}, Tuple{Base.Cmd}, Tuple{String}, Tuple{Base.Cmd}, Tuple{String}, Tuple{String}}}) +precompile(Tuple{typeof(Base.arg_gen), Base.Cmd}) +precompile(Tuple{typeof(Base.promote_type), Type{Bool}, Type{UInt8}}) +precompile(Tuple{typeof(Base.promote_rule), Type{UInt8}, Type{Bool}}) +precompile(Tuple{typeof(Base.promote_result), Type{Bool}, Type{UInt8}, Type{UInt8}, Type{Union{}}}) +precompile(Tuple{typeof(Base.promote_type), Type{UInt8}, Type{Union{}}}) +precompile(Tuple{typeof(Base.detach), Base.Cmd}) +precompile(Tuple{typeof(Base.open), Base.CmdRedirect, String, Base.DevNullStream}) +precompile(Tuple{typeof(Base.spawn), Base.CmdRedirect, Tuple{Base.DevNullStream, Base.Pipe, Base.IOStream}}) +precompile(Tuple{getfield(Base, Symbol("#kw##spawn")), Array{Any, 1}, typeof(Base.spawn), Base.Cmd, Tuple{Base.DevNullStream, Base.Pipe, Base.IOStream}}) +precompile(Tuple{getfield(Base, Symbol("#kw##init_pipe!")), Array{Any, 1}, typeof(Base.init_pipe!), Base.PipeEndpoint}) +precompile(Tuple{typeof(Base._link_pipe), Ptr{Void}, Ptr{Void}}) +precompile(Tuple{typeof(Base.link_pipe), Base.PipeEndpoint, Bool, Base.PipeEndpoint, Bool}) +precompile(Tuple{typeof(Base.close), Base.Filesystem.File}) +precompile(Tuple{typeof(Base.setup_stdio), Base.Pipe, Bool}) +precompile(Tuple{typeof(Base.setup_stdio), Base.IOStream, Bool}) +precompile(Tuple{Type{Base.Process}, Base.Cmd, Ptr{Void}, Base.DevNullStream, Base.Pipe, Base.IOStream}) +precompile(Tuple{typeof(Base._jl_spawn), String, Array{String, 1}, Ptr{Void}, Base.Process, Base.DevNullStream, Base.PipeEndpoint, Base.Filesystem.File}) +precompile(Tuple{Type{Base.Timer}, Int64, Float64}) +precompile(Tuple{typeof(Base.sleep), Int64}) +precompile(Tuple{typeof(Base._uv_hook_close), Base.PipeEndpoint}) +precompile(Tuple{typeof(Base.eltype), Type{Base.Nullable{IO}}}) +precompile(Tuple{Type{Base.Nullable{IO}}}) +precompile(Tuple{typeof(Base.eltype), Type{Base.Nullable{AbstractString}}}) +precompile(Tuple{Type{Base.Nullable{AbstractString}}}) +precompile(Tuple{typeof(Base.eltype), Type{Base.Nullable{Integer}}}) +precompile(Tuple{Type{Base.Nullable{Integer}}}) +precompile(Tuple{typeof(Base.eltype), Type{Base.Nullable{Union{Int64, Symbol}}}}) +precompile(Tuple{Type{Base.Nullable{Union{Int64, Symbol}}}}) +precompile(Tuple{typeof(Base.eltype), Type{Base.Nullable{Base.Cmd}}}) +precompile(Tuple{Type{Base.Nullable{Base.Cmd}}}) +precompile(Tuple{typeof(Base.eltype), Type{Base.Nullable{Any}}}) +precompile(Tuple{Type{Base.Nullable{Any}}}) +precompile(Tuple{typeof(Base.eltype), Type{Base.Nullable{Bool}}}) +precompile(Tuple{Type{Base.Nullable{Bool}}}) +precompile(Tuple{typeof(Base.eltype), Type{Base.Nullable{Base.Process}}}) +precompile(Tuple{Type{Base.Nullable{Base.Process}}}) +precompile(Tuple{typeof(Base.eltype), Type{Base.Nullable{Base.Dict{K, V} where V where K}}}) +precompile(Tuple{Type{Base.Nullable{Base.Dict{K, V} where V where K}}}) +precompile(Tuple{typeof(Base.eltype), Type{Base.Nullable{Array{T, N} where N where T}}}) +precompile(Tuple{Type{Base.Nullable{Array{T, N} where N where T}}}) +precompile(Tuple{typeof(Base.convert), Type{Base.Nullable{Base.Process}}, Base.Process}) +precompile(Tuple{typeof(Base.convert), Type{Base.Nullable{Bool}}, Bool}) +precompile(Tuple{typeof(Base.task_done_hook), Task}) +precompile(Tuple{typeof(Base.getindex), Tuple{Array{Any, 1}, Tuple{}}, Int64}) +precompile(Tuple{Type{Base.TCPSocket}}) +precompile(Tuple{typeof(Base.getsockname), Base.TCPSocket}) +precompile(Tuple{typeof(Base.unsafe_store!), Ptr{Int32}, Int64}) +precompile(Tuple{Type{Base.Multimedia.TextDisplay}, Base.PipeEndpoint}) +precompile(Tuple{typeof(Base.Distributed.start_worker), Base.PipeEndpoint, String}) +precompile(Tuple{typeof(Core.Inference.isbits), OutOfMemoryError}) +precompile(Tuple{typeof(Core.Inference.isbits), Tuple{Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64, Int64}}) +precompile(Tuple{typeof(Base.getaddrinfo), String}) +precompile(Tuple{typeof(Base.uv_status_string), Base.PipeEndpoint}) +precompile(Tuple{typeof(Base._fd), Base.PipeEndpoint}) +precompile(Tuple{typeof(Base.print), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.PipeEndpoint}) +precompile(Tuple{typeof(Base.print), Base.AbstractIOBuffer{Array{UInt8, 1}}, UInt16}) +precompile(Tuple{typeof(Base.isopen), Base.PipeEndpoint}) +precompile(Tuple{typeof(Base.unpreserve_handle), Task}) +precompile(Tuple{typeof(Base.check_open), Base.PipeEndpoint}) +precompile(Tuple{typeof(Base.stream_wait), Task}) +precompile(Tuple{typeof(Base.uv_write), Base.PipeEndpoint, Ptr{UInt8}, UInt64}) +precompile(Tuple{typeof(Base.flush), Base.PipeEndpoint}) +precompile(Tuple{typeof(Base.unsafe_write), Base.PipeEndpoint, Ptr{UInt8}, UInt64}) +precompile(Tuple{typeof(Base.unsafe_write), Base.PipeEndpoint, Base.RefValue{UInt8}, Int64}) +precompile(Tuple{typeof(Base.uv_status_string), Base.TCPSocket}) +precompile(Tuple{typeof(Base._fd), Base.TCPSocket}) +precompile(Tuple{typeof(Base.print), Base.PipeEndpoint, String}) +precompile(Tuple{typeof(Base.print), Base.PipeEndpoint, Char}) +precompile(Tuple{typeof(Base.print), Base.PipeEndpoint, String, Char}) +precompile(Tuple{typeof(Base.print), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.TCPSocket}) +precompile(Tuple{typeof(Base.write), Base.PipeEndpoint, Char}) +precompile(Tuple{typeof(Base.isopen), Base.TCPSocket}) +precompile(Tuple{typeof(Base.unpreserve_handle), Base.TCPSocket}) +precompile(Tuple{typeof(Base.check_open), Base.TCPSocket}) +precompile(Tuple{typeof(Base.stream_wait), Base.TCPSocket, Base.Condition}) +precompile(Tuple{typeof(Base.wait_connected), Base.TCPSocket}) +precompile(Tuple{typeof(Base.print), Base.AbstractIOBuffer{Array{UInt8, 1}}, String, Base.IPv4, String}) +precompile(Tuple{typeof(Base.print), Base.AbstractIOBuffer{Array{UInt8, 1}}, String, Base.IPv6, String}) +precompile(Tuple{typeof(Base.Distributed.socket_reuse_port)}) +precompile(Tuple{typeof(Base.promote_type), Type{Int64}, Type{Int16}}) +precompile(Tuple{typeof(Base.promote_rule), Type{Int16}, Type{Int64}}) +precompile(Tuple{typeof(Base.promote_result), Type{Int64}, Type{Int16}, Type{Int64}, Type{Union{}}}) +precompile(Tuple{typeof(Base.Distributed.flush_gc_msgs)}) +precompile(Tuple{typeof(Base.show), Base.AbstractIOBuffer{Array{UInt8, 1}}, Int16}) +precompile(Tuple{typeof(Base.print), Base.AbstractIOBuffer{Array{UInt8, 1}}, Int16}) +precompile(Tuple{typeof(Base.uv_status_string), Base.PipeServer}) +precompile(Tuple{typeof(Base._fd), Base.PipeServer}) +precompile(Tuple{typeof(Base.convert), Type{Int16}, Int16}) +precompile(Tuple{typeof(Base.string), String, Int16, String, String, String, String}) +precompile(Tuple{typeof(Base.print), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.PipeServer}) +precompile(Tuple{typeof(Base.unpreserve_handle), Base.PipeServer}) +precompile(Tuple{typeof(Base.isopen), Base.PipeServer}) +precompile(Tuple{typeof(Base.accept_nonblock), Base.PipeServer, Base.PipeEndpoint}) +precompile(Tuple{typeof(Base.stream_wait), Base.PipeServer, Base.Condition}) +precompile(Tuple{getfield(Base, Symbol("#kw##init_pipe!")), Array{Any, 1}, typeof(Base.init_pipe!), Base.PipeEndpoint}) +precompile(Tuple{typeof(Base.accept), Base.PipeServer, Base.PipeEndpoint}) +precompile(Tuple{typeof(Base.accept_nonblock), Base.TCPServer, Base.TCPSocket}) +precompile(Tuple{Type{Base.TCPSocket}}) +precompile(Tuple{typeof(Base.accept), Base.TCPServer, Base.TCPSocket}) +precompile(Tuple{typeof(Base.accept), Base.TCPServer}) +precompile(Tuple{typeof(Base.tryparse_internal), Type{Int16}, Base.SubString{String}, Int64, Int64, Int64, Bool}) +precompile(Tuple{typeof(Base.parse), Type{Int16}, Base.SubString{String}}) +precompile(Tuple{typeof(Base.write), Base.PipeEndpoint, String}) +precompile(Tuple{typeof(Base.Distributed.disable_nagle), Base.TCPServer}) +precompile(Tuple{typeof(Base.Distributed.next_tunnel_port)}) +precompile(Tuple{typeof(Core.Inference.isbits), Tuple{Tuple{String}, Tuple{String}, Tuple{String}, Tuple{String}, Tuple{String}, Tuple{String}}}) +precompile(Tuple{typeof(Base.cmd_gen), Tuple{Tuple{String}, Tuple{String}, Tuple{String}, Tuple{String}, Tuple{String}, Tuple{String}}}) +precompile(Tuple{typeof(Base._delete!), Base.Dict{Int64, Union{Base.Distributed.Worker, Base.Distributed.LocalProcess}}, Int64}) +precompile(Tuple{typeof(Base.ndigits0z), UInt8}) +precompile(Tuple{typeof(Base.dec), UInt8, Int64, Bool}) +precompile(Tuple{typeof(Core.Inference.length), Tuple{Core.Inference.Const, typeof(Type), Core.Inference.Const}}) +precompile(Tuple{typeof(Core.Inference.getindex), Tuple{Core.Inference.Const, typeof(Type), Core.Inference.Const}, Int64}) +precompile(Tuple{typeof(Base.Distributed.send_msg_), Base.Distributed.Worker, Base.Distributed.MsgHeader, Base.Distributed.JoinPGRPMsg, Bool}) +precompile(Tuple{typeof(Base.Distributed.send_msg_now), Base.Distributed.Worker, Base.Distributed.MsgHeader, Base.Distributed.JoinPGRPMsg}) +precompile(Tuple{typeof(Base.rehash!), Base.Dict{Int64, Void}, Int64}) +precompile(Tuple{typeof(Base.ht_keyindex2), Base.Dict{Int64, Void}, Int64}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Int64, Void}, Void, Int64, Int64}) +precompile(Tuple{typeof(Base.rehash!), Base.Dict{AbstractString, Base.Semaphore}, Int64}) +precompile(Tuple{typeof(Base.resize!), Array{Base.Semaphore, 1}, Int64}) +precompile(Tuple{typeof(Base.Distributed.connect_w2w), Int64, Base.Distributed.WorkerConfig}) +precompile(Tuple{typeof(Base.acquire), Base.Semaphore}) +precompile(Tuple{typeof(Base.release), Base.Semaphore}) +precompile(Tuple{typeof(Base.Distributed.create_worker), Base.Distributed.LocalManager, Base.Distributed.WorkerConfig}) +precompile(Tuple{typeof(Base.Distributed.setup_launched_worker), Base.Distributed.LocalManager, Base.Distributed.WorkerConfig, Array{Int64, 1}}) +precompile(Tuple{typeof(Base.connect), Base.Distributed.LocalManager, Int64, Base.Distributed.WorkerConfig}) +precompile(Tuple{typeof(Base.Distributed.read_worker_host_port), Base.Pipe}) +precompile(Tuple{typeof(Base.isreadable), Base.PipeEndpoint}) +precompile(Tuple{typeof(Base.search), Base.AbstractIOBuffer{Array{UInt8, 1}}, UInt8}) +precompile(Tuple{typeof(Base.start_reading), Base.PipeEndpoint}) +precompile(Tuple{typeof(Base.wait_readbyte), Base.PipeEndpoint, UInt8}) +precompile(Tuple{typeof(Base.readuntil), Base.PipeEndpoint, UInt8}) +precompile(Tuple{typeof(Base.alloc_buf_hook), Base.PipeEndpoint, UInt64}) +precompile(Tuple{typeof(Base._uv_hook_close), Base.Timer}) +precompile(Tuple{typeof(Base.notify), Base.Condition, Base.EOFError, Bool, Bool}) +precompile(Tuple{typeof(Base.unpreserve_handle), Base.Timer}) +precompile(Tuple{typeof(Base.disassociate_julia_struct), Base.Timer}) +precompile(Tuple{typeof(Base.Distributed.parse_connection_info), String}) +precompile(Tuple{typeof(Base._uv_hook_close), Base.Timer}) +precompile(Tuple{typeof(Base.notify), Base.Condition, Base.EOFError, Bool, Bool}) +precompile(Tuple{typeof(Base.unpreserve_handle), Base.Timer}) +precompile(Tuple{typeof(Base.disassociate_julia_struct), Base.Timer}) +precompile(Tuple{typeof(Base.convert), Type{Base.Nullable{AbstractString}}, Base.SubString{String}}) +precompile(Tuple{typeof(Base.Distributed.connect_to_worker), Base.SubString{String}, Int16}) +precompile(Tuple{typeof(Base.connect!), Base.TCPSocket, Base.SubString{String}, UInt16}) +precompile(Tuple{typeof(Base.notify), Base.Condition, Base.IPv4, Bool, Bool}) +precompile(Tuple{typeof(Base.schedule), Task, Base.IPv4}) +precompile(Tuple{typeof(Base.connect!), Base.TCPSocket, Base.IPv4, UInt16}) +precompile(Tuple{typeof(Base.Distributed.process_messages), Base.TCPSocket, Base.TCPSocket, Bool}) +precompile(Tuple{typeof(Base.uv_status_string), Base.TCPSocket}) +precompile(Tuple{typeof(Base._fd), Base.TCPSocket}) +precompile(Tuple{typeof(Base.print), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.TCPSocket}) +precompile(Tuple{typeof(Base.isopen), Base.TCPSocket}) +precompile(Tuple{typeof(Base.convert), Type{Base.Nullable{AbstractString}}, String}) +precompile(Tuple{typeof(Base.unpreserve_handle), Base.TCPSocket}) +precompile(Tuple{typeof(Base.check_open), Base.TCPSocket}) +precompile(Tuple{typeof(Base.stream_wait), Base.TCPSocket, Base.Condition}) +precompile(Tuple{getfield(Core, Symbol("#kw#Type")), Array{Any, 1}, Type{Base.Distributed.Worker}, Int64, Base.TCPSocket, Base.TCPSocket, Base.Distributed.LocalManager}) +precompile(Tuple{typeof(Base.read_sub), Base.AbstractIOBuffer{Array{UInt8, 1}}, Array{UInt8, 1}, Int64, Int64}) +precompile(Tuple{typeof(Base.isreadable), Base.TCPSocket}) +precompile(Tuple{typeof(Base.start_reading), Base.TCPSocket}) +precompile(Tuple{typeof(Base.write_sub), Base.AbstractIOBuffer{Array{UInt8, 1}}, Array{UInt8, 1}, Int64, Int64}) +precompile(Tuple{typeof(Base.readbytes!), Base.AbstractIOBuffer{Array{UInt8, 1}}, Array{UInt8, 1}, Int64}) +precompile(Tuple{typeof(Base.wait_readnb), Base.TCPSocket, Int64}) +precompile(Tuple{typeof(Base.write), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.AbstractIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(Base.readbytes!), Base.TCPSocket, Array{UInt8, 1}, Int64}) +precompile(Tuple{typeof(Base.read), Base.TCPSocket, Int64}) +precompile(Tuple{typeof(Base.Distributed.worker_id_from_socket), Base.TCPSocket}) +precompile(Tuple{Type{Base.Distributed.ClusterSerializer{Base.TCPSocket}}, Base.TCPSocket}) +precompile(Tuple{typeof(Base.unsafe_read), Base.TCPSocket, Ptr{UInt8}, UInt64}) +precompile(Tuple{typeof(Base.read!), Base.TCPSocket, Array{Int64, 1}}) +precompile(Tuple{typeof(Base.read), Base.TCPSocket, Type{UInt8}}) +precompile(Tuple{typeof(Base.Distributed.send_msg_), Base.Distributed.Worker, Base.Distributed.MsgHeader, Base.Distributed.ResultMsg, Bool}) +precompile(Tuple{typeof(Base.Distributed.send_msg_now), Base.Distributed.Worker, Base.Distributed.MsgHeader, Base.Distributed.ResultMsg}) +precompile(Tuple{Type{Core.Inference.Generator{I, F} where F where I}, Type{Core.Inference.Const}, Tuple{Int64, typeof(Base.Distributed.rmprocs)}}) +precompile(Tuple{Type{Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{Core.Inference.Const}}}, Type{Core.Inference.Const}, Tuple{Int64, typeof(Base.Distributed.rmprocs)}}) +precompile(Tuple{typeof(Core.Inference.convert), Type{Tuple{Int64, typeof(Base.Distributed.rmprocs)}}, Tuple{Int64, typeof(Base.Distributed.rmprocs)}}) +precompile(Tuple{typeof(Core.Inference.collect), Type{Any}, Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.iteratorsize), Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.iteratorsize), Type{Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{Core.Inference.Const}}}}) +precompile(Tuple{typeof(Core.Inference.iteratorsize), Type{Tuple{Int64, typeof(Base.Distributed.rmprocs)}}}) +precompile(Tuple{typeof(Core.Inference._collect), Type{Any}, Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{Core.Inference.Const}}, Core.Inference.HasLength}) +precompile(Tuple{typeof(Core.Inference.length), Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.length), Tuple{Int64, typeof(Base.Distributed.rmprocs)}}) +precompile(Tuple{typeof(Core.Inference.copy!), Array{Any, 1}, Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.start), Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.start), Tuple{Int64, typeof(Base.Distributed.rmprocs)}}) +precompile(Tuple{typeof(Core.Inference.done), Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{Core.Inference.Const}}, Int64}) +precompile(Tuple{typeof(Core.Inference.done), Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Int64}) +precompile(Tuple{typeof(Core.Inference.next), Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{Core.Inference.Const}}, Int64}) +precompile(Tuple{typeof(Core.Inference.next), Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Int64}) +precompile(Tuple{typeof(Core.Inference.getindex), Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Int64}) +precompile(Tuple{typeof(Core.Inference.start), Tuple{typeof(Base.Distributed.rmprocs), Int64}}) +precompile(Tuple{typeof(Core.Inference.indexed_next), Tuple{typeof(Base.Distributed.rmprocs), Int64}, Int64, Int64}) +precompile(Tuple{typeof(Core.Inference.getindex), Tuple{typeof(Base.Distributed.rmprocs), Int64}, Int64}) +precompile(Tuple{typeof(Base.Distributed.register_worker_streams), Base.Distributed.Worker}) +precompile(Tuple{typeof(Base.Distributed.register_worker_streams), Base.Distributed.LocalProcess}) +precompile(Tuple{typeof(Base.convert), Type{IO}, Base.TCPSocket}) +precompile(Tuple{Type{Base.Distributed.ClusterSerializer{Base.TCPSocket}}, Base.TCPSocket}) +precompile(Tuple{typeof(Base.Distributed.worker_id_from_socket), Base.TCPSocket}) +precompile(Tuple{typeof(Base.convert), Type{Base.Distributed.ClusterSerializer{I} where I<:IO}, Base.Distributed.ClusterSerializer{Base.TCPSocket}}) +precompile(Tuple{typeof(Base.convert), Type{Base.Distributed.ClusterManager}, Base.Distributed.LocalManager}) +precompile(Tuple{typeof(Base.convert), Type{Base.Distributed.WorkerConfig}, Base.Distributed.WorkerConfig}) +precompile(Tuple{typeof(Base.convert), Type{Base.Nullable{Base.VersionNumber}}, Base.Nullable{Base.VersionNumber}}) +precompile(Tuple{typeof(Base.join), Base.AbstractIOBuffer{Array{UInt8, 1}}, Tuple{Int64}, Char}) +precompile(Tuple{typeof(Base.get), Base.Dict{Any, Any}, Base.Distributed.RRID, Bool}) +precompile(Tuple{typeof(Base.ht_keyindex), Base.Dict{Any, Any}, Base.Distributed.RRID}) +precompile(Tuple{typeof(Core.Inference.isbits), Tuple{Int64, typeof(Base.Distributed.rmprocs)}}) +precompile(Tuple{Type{Core.Inference.Generator{I, F} where F where I}, Type{QuoteNode}, Tuple{Int64, typeof(Base.Distributed.rmprocs)}}) +precompile(Tuple{Type{Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{QuoteNode}}}, Type{QuoteNode}, Tuple{Int64, typeof(Base.Distributed.rmprocs)}}) +precompile(Tuple{typeof(Core.Inference.iteratorsize), Type{Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{QuoteNode}}}}) +precompile(Tuple{typeof(Core.Inference._collect), Type{Any}, Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{QuoteNode}}, Core.Inference.HasLength}) +precompile(Tuple{typeof(Core.Inference.length), Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{QuoteNode}}}) +precompile(Tuple{typeof(Core.Inference.copy!), Array{Any, 1}, Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{QuoteNode}}}) +precompile(Tuple{typeof(Core.Inference.start), Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{QuoteNode}}}) +precompile(Tuple{typeof(Core.Inference.done), Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{QuoteNode}}, Int64}) +precompile(Tuple{typeof(Core.Inference.next), Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{QuoteNode}}, Int64}) +precompile(Tuple{typeof(Base.Distributed.local_remotecall_thunk), typeof(Base.Distributed.rmprocs), Tuple{Int64}, Array{Any, 1}}) +precompile(Tuple{typeof(Base.Distributed.remote_do), typeof(Base.Distributed.rmprocs), Base.Distributed.Worker, Int64}) +precompile(Tuple{typeof(Base.Distributed.remote_do), typeof(Base.Distributed.rmprocs), Base.Distributed.LocalProcess, Int64}) +precompile(Tuple{getfield(Base.Distributed, Symbol("#kw##remote_do")), Array{Any, 1}, typeof(Base.Distributed.remote_do), typeof(Base.Distributed.rmprocs), Base.Distributed.Worker, Int64}) +precompile(Tuple{getfield(Base.Distributed, Symbol("#kw##remote_do")), Array{Any, 1}, typeof(Base.Distributed.remote_do), typeof(Base.Distributed.rmprocs), Base.Distributed.LocalProcess, Int64}) +precompile(Tuple{Type{Base.Distributed.ResultMsg}, Base.Distributed.RemoteException}) +precompile(Tuple{Type{Base.Distributed.ResultMsg}, Symbol}) +precompile(Tuple{typeof(Base.Distributed.send_msg_now), Base.TCPSocket, Base.Distributed.MsgHeader, Base.Distributed.ResultMsg}) +precompile(Tuple{typeof(Base.close), Base.TCPSocket}) +precompile(Tuple{typeof(Base._delete!), Base.Dict{Int64, Union{Base.Distributed.Worker, Base.Distributed.LocalProcess}}, Int64}) +precompile(Tuple{typeof(Base.Distributed.def_rv_channel)}) +precompile(Tuple{typeof(Base.convert), Type{Base.AbstractChannel}, Base.Channel{Any}}) +precompile(Tuple{typeof(Base.ndigits0z), UInt8}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Any, Any}, Base.Distributed.RemoteValue, Base.Distributed.RRID}) +precompile(Tuple{typeof(Base.dec), UInt8, Int64, Bool}) +precompile(Tuple{typeof(Core.Inference.mk_getfield), TypedSlot, Int64, Type{Integer}}) +precompile(Tuple{typeof(Base.ht_keyindex2), Base.Dict{Any, Any}, Base.Distributed.RRID}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Any, Any}, Base.Distributed.RemoteValue, Base.Distributed.RRID, Int64}) +precompile(Tuple{typeof(Core.Inference.length), Tuple{Core.Inference.Const, DataType, Core.Inference.Const}}) +precompile(Tuple{typeof(Core.Inference.getindex), Tuple{Core.Inference.Const, DataType, Core.Inference.Const}, Int64}) +precompile(Tuple{typeof(Base.notify), Base.Condition, Base.Distributed.ProcessExitedException, Bool, Bool}) +precompile(Tuple{typeof(Base.rehash!), Base.Dict{Int64, Void}, Int64}) +precompile(Tuple{typeof(Base.Distributed.process_messages), Base.TCPSocket, Base.TCPSocket, Bool}) +precompile(Tuple{typeof(Base.ht_keyindex2), Base.Dict{Int64, Void}, Int64}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Int64, Void}, Void, Int64, Int64}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Int64, Void}, Void, Int64}) +precompile(Tuple{typeof(Base.pop!), Base.Dict{Int64, Union{Base.Distributed.Worker, Base.Distributed.LocalProcess}}, Int64, Void}) +precompile(Tuple{typeof(Base.Distributed.send_connection_hdr), Base.Distributed.Worker, Bool}) +precompile(Tuple{typeof(Base.Distributed.deregister_worker), Base.Distributed.ProcessGroup, Int64}) +precompile(Tuple{typeof(Base.Distributed.process_hdr), Base.TCPSocket, Bool}) +precompile(Tuple{typeof(Base.Distributed.deserialize_msg), Base.Distributed.ClusterSerializer{Base.TCPSocket}}) +precompile(Tuple{typeof(Base.Distributed.null_id), Base.Distributed.RRID}) +precompile(Tuple{typeof(Base.Distributed.deliver_result), Base.TCPSocket, Symbol, Base.Distributed.RRID, Base.Distributed.RemoteException}) +precompile(Tuple{typeof(Base.Distributed.disable_nagle), Base.TCPSocket}) +precompile(Tuple{typeof(Base.wait_connected), Base.TCPSocket}) +precompile(Tuple{typeof(Base.Distributed.message_handler_loop), Base.TCPSocket, Base.TCPSocket, Bool}) +precompile(Tuple{typeof(Base.Distributed.process_tcp_streams), Base.TCPSocket, Base.TCPSocket, Bool}) +precompile(Tuple{typeof(Base.write), Base.TCPSocket, String}) +precompile(Tuple{typeof(Base.uv_write), Base.TCPSocket, Ptr{UInt8}, UInt64}) +precompile(Tuple{typeof(Base.flush), Base.TCPSocket}) +precompile(Tuple{typeof(Base.unsafe_write), Base.TCPSocket, Ptr{UInt8}, UInt64}) +precompile(Tuple{Type{Base.Distributed.JoinPGRPMsg}, Int64, Array{Union{Tuple{Any, Int64}, Tuple{Tuple{}, Any, Bool}}, 1}, Symbol, Bool}) +precompile(Tuple{typeof(Base.write), Base.TCPSocket, Int64, Int64, Int64, Int64}) +precompile(Tuple{typeof(Base.unsafe_write), Base.TCPSocket, Base.RefValue{Int64}, Int64}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Base.Distributed.JoinPGRPMsg}) +precompile(Tuple{typeof(Base.unsafe_write), Base.TCPSocket, Base.RefValue{UInt8}, Int64}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Int64}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Array{Union{Tuple{Any, Int64}, Tuple{Tuple{}, Any, Bool}}, 1}}) +precompile(Tuple{typeof(Core.Inference.length), Tuple{Core.Inference.Const, DataType, Core.Inference.Const}}) +precompile(Tuple{typeof(Core.Inference.getindex), Tuple{Core.Inference.Const, DataType, Core.Inference.Const}, Int64}) +precompile(Tuple{typeof(Base.unsafe_write), Base.TCPSocket, Base.RefValue{Int32}, Int64}) +precompile(Tuple{typeof(Base.Serializer.write_as_tag), Base.TCPSocket, Int32}) +precompile(Tuple{typeof(Base.copy!), Array{Any, 1}, Base.MethodList}) +precompile(Tuple{typeof(Base.Serializer.should_send_whole_type), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Type{Any}}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Distributed.ClusterSerializer{Base.TCPSocket}, SimpleVector}) +precompile(Tuple{typeof(Base.Serializer.serialize_type_data), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Type{Any}, Bool}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Type{Any}}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Tuple{Int64}}) +precompile(Tuple{typeof(Base.ht_keyindex), Base.Dict{UInt64, UInt64}, UInt64}) +precompile(Tuple{typeof(Base.unique), Array{Symbol, 1}}) +precompile(Tuple{typeof(Base.Serializer.serialize_cycle), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Type{Union{Tuple{Any, Int64}, Tuple{Tuple{}, Any, Bool}}}}) +precompile(Tuple{typeof(Base.Serializer.serialize_type), Base.Distributed.ClusterSerializer{Base.TCPSocket}, DataType}) +precompile(Tuple{typeof(Base.rehash!), Base.Dict{UInt64, UInt64}, Int64}) +precompile(Tuple{typeof(Base.resize!), Array{UInt64, 1}, Int64}) +precompile(Tuple{typeof(Base.ht_keyindex2), Base.Dict{UInt64, UInt64}, UInt64}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Bool}) +precompile(Tuple{typeof(Base.Distributed.serialize_global_from_main), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Symbol}) +precompile(Tuple{typeof(Base.Serializer.serialize_mod_names), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Module}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Symbol}) +precompile(Tuple{typeof(Core.Inference.isbits), Symbol}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Module}) +precompile(Tuple{typeof(Base.isassigned), Array{Symbol, 1}, Int64}) +precompile(Tuple{typeof(Base.rehash!), Base.Dict{UInt64, Void}, Int64}) +precompile(Tuple{typeof(Base.ht_keyindex2), Base.Dict{UInt64, Void}, UInt64}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{UInt64, Void}, Void, UInt64, Int64}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Array{Any, 1}}) +precompile(Tuple{typeof(Base.ht_keyindex), Base.Dict{WeakRef, Any}, TypeName}) +precompile(Tuple{typeof(Base.Serializer.serialize_cycle), Base.Distributed.ClusterSerializer{Base.TCPSocket}, TypeName}) +precompile(Tuple{typeof(Base.Serializer.object_number), TypeName}) +precompile(Tuple{typeof(Base.Serializer.serialize_typename), Base.Distributed.ClusterSerializer{Base.TCPSocket}, TypeName}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Array{Symbol, 1}}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Distributed.ClusterSerializer{Base.TCPSocket}, TypeName}) +precompile(Tuple{typeof(Base.Serializer.serialize_cycle_header), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Type{Union{Tuple{Any, Int64}, Tuple{Tuple{}, Any, Bool}}}}) +precompile(Tuple{typeof(Base.Serializer.serialize_any), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Type{Union{Tuple{Any, Int64}, Tuple{Tuple{}, Any, Bool}}}}) +precompile(Tuple{typeof(Base.isassigned), Array{Union{Tuple{Any, Int64}, Tuple{Tuple{}, Any, Bool}}, 1}, Int64}) +precompile(Tuple{typeof(Base.uvfinalize), Base.TCPSocket}) +precompile(Tuple{typeof(Base.close), Base.TCPSocket}) +precompile(Tuple{typeof(Base.write), Base.TCPSocket, Array{UInt8, 1}}) +precompile(Tuple{typeof(Base.wait_readnb), Base.PipeEndpoint, Int64}) +precompile(Tuple{typeof(Base.eof), Base.PipeEndpoint}) +precompile(Tuple{typeof(Base.Distributed.deserialize_msg), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Type{Base.Distributed.JoinPGRPMsg}}) +precompile(Tuple{typeof(Base.unsafe_read), Base.TCPSocket, Base.RefValue{Int32}, Int64}) +precompile(Tuple{typeof(Base.unsafe_read), Base.TCPSocket, Base.RefValue{Int64}, Int64}) +precompile(Tuple{typeof(Base.read!), Base.TCPSocket, Array{UInt8, 1}}) +precompile(Tuple{typeof(Base.read_sub), Base.AbstractIOBuffer{Array{UInt8, 1}}, Array{UInt8, 1}, Int64, Int64}) +precompile(Tuple{typeof(Base.isreadable), Base.TCPSocket}) +precompile(Tuple{typeof(Base.start_reading), Base.TCPSocket}) +precompile(Tuple{typeof(Base.write_sub), Base.AbstractIOBuffer{Array{UInt8, 1}}, Array{UInt8, 1}, Int64, Int64}) +precompile(Tuple{typeof(Base.readbytes!), Base.AbstractIOBuffer{Array{UInt8, 1}}, Array{UInt8, 1}, Int64}) +precompile(Tuple{typeof(Base.wait_readnb), Base.TCPSocket, Int64}) +precompile(Tuple{typeof(Base.write), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.AbstractIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(Base.readbytes!), Base.TCPSocket, Array{UInt8, 1}, Int64}) +precompile(Tuple{typeof(Base.read), Base.TCPSocket, Int64}) +precompile(Tuple{typeof(Base.promote_type), Type{Int64}, Type{UInt8}}) +precompile(Tuple{typeof(Base.promote_rule), Type{Int64}, Type{UInt8}}) +precompile(Tuple{typeof(Base.promote_result), Type{Int64}, Type{UInt8}, Type{Union{}}, Type{Int64}}) +precompile(Tuple{typeof(Base.read!), Base.TCPSocket, Array{UInt64, 1}}) +precompile(Tuple{typeof(Base.unsafe_read), Base.TCPSocket, Ptr{UInt8}, UInt64}) +precompile(Tuple{typeof(Base.read!), Base.TCPSocket, Array{Int64, 1}}) +precompile(Tuple{typeof(Base.read), Base.TCPSocket, Type{UInt8}}) +precompile(Tuple{typeof(Base.Distributed.send_msg_), Base.Distributed.Worker, Base.Distributed.MsgHeader, Base.Distributed.ResultMsg, Bool}) +precompile(Tuple{typeof(Base.Distributed.send_msg_now), Base.Distributed.Worker, Base.Distributed.MsgHeader, Base.Distributed.ResultMsg}) +precompile(Tuple{Type{Core.Inference.Generator{I, F} where F where I}, Type{Core.Inference.Const}, Tuple{Int64, typeof(Base.Distributed.rmprocs)}}) +precompile(Tuple{Type{Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{Core.Inference.Const}}}, Type{Core.Inference.Const}, Tuple{Int64, typeof(Base.Distributed.rmprocs)}}) +precompile(Tuple{typeof(Core.Inference.convert), Type{Tuple{Int64, typeof(Base.Distributed.rmprocs)}}, Tuple{Int64, typeof(Base.Distributed.rmprocs)}}) +precompile(Tuple{typeof(Core.Inference.collect), Type{Any}, Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.iteratorsize), Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.iteratorsize), Type{Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{Core.Inference.Const}}}}) +precompile(Tuple{typeof(Core.Inference.iteratorsize), Type{Tuple{Int64, typeof(Base.Distributed.rmprocs)}}}) +precompile(Tuple{typeof(Core.Inference._collect), Type{Any}, Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{Core.Inference.Const}}, Core.Inference.HasLength}) +precompile(Tuple{typeof(Core.Inference.length), Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.length), Tuple{Int64, typeof(Base.Distributed.rmprocs)}}) +precompile(Tuple{typeof(Core.Inference.copy!), Array{Any, 1}, Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.start), Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.start), Tuple{Int64, typeof(Base.Distributed.rmprocs)}}) +precompile(Tuple{typeof(Core.Inference.done), Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{Core.Inference.Const}}, Int64}) +precompile(Tuple{typeof(Core.Inference.done), Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Int64}) +precompile(Tuple{typeof(Core.Inference.next), Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{Core.Inference.Const}}, Int64}) +precompile(Tuple{typeof(Core.Inference.next), Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Int64}) +precompile(Tuple{typeof(Core.Inference.getindex), Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Int64}) +precompile(Tuple{typeof(Core.Inference.start), Tuple{typeof(Base.Distributed.rmprocs), Int64}}) +precompile(Tuple{typeof(Core.Inference.indexed_next), Tuple{typeof(Base.Distributed.rmprocs), Int64}, Int64, Int64}) +precompile(Tuple{typeof(Core.Inference.getindex), Tuple{typeof(Base.Distributed.rmprocs), Int64}, Int64}) +precompile(Tuple{typeof(Base.Serializer.deserialize), Base.Distributed.ClusterSerializer{Base.TCPSocket}}) +precompile(Tuple{typeof(Base.Serializer.deserialize_cycle), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Expr}) +precompile(Tuple{typeof(Base.Serializer.handle_deserialize), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Int32}) +precompile(Tuple{typeof(Base._array_for), Type{Union{}}, Base.UnitRange{Int64}, Base.HasShape}) +precompile(Tuple{typeof(Base.Serializer.deserialize_array), Base.Distributed.ClusterSerializer{Base.TCPSocket}}) +precompile(Tuple{typeof(Base.Serializer.deserialize_datatype), Base.Distributed.ClusterSerializer{Base.TCPSocket}}) +precompile(Tuple{typeof(Base.Serializer.deserialize_expr), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Int64}) +precompile(Tuple{typeof(Base.join), Base.AbstractIOBuffer{Array{UInt8, 1}}, Tuple{Int64}, Char}) +precompile(Tuple{typeof(Core.Inference.isbits), Tuple{Int64, typeof(Base.Distributed.rmprocs)}}) +precompile(Tuple{Type{Core.Inference.Generator{I, F} where F where I}, Type{QuoteNode}, Tuple{Int64, typeof(Base.Distributed.rmprocs)}}) +precompile(Tuple{Type{Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{QuoteNode}}}, Type{QuoteNode}, Tuple{Int64, typeof(Base.Distributed.rmprocs)}}) +precompile(Tuple{typeof(Core.Inference.iteratorsize), Type{Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{QuoteNode}}}}) +precompile(Tuple{typeof(Core.Inference._collect), Type{Any}, Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{QuoteNode}}, Core.Inference.HasLength}) +precompile(Tuple{typeof(Core.Inference.length), Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{QuoteNode}}}) +precompile(Tuple{typeof(Core.Inference.copy!), Array{Any, 1}, Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{QuoteNode}}}) +precompile(Tuple{typeof(Core.Inference.start), Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{QuoteNode}}}) +precompile(Tuple{typeof(Core.Inference.done), Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{QuoteNode}}, Int64}) +precompile(Tuple{typeof(Core.Inference.next), Core.Inference.Generator{Tuple{Int64, typeof(Base.Distributed.rmprocs)}, Type{QuoteNode}}, Int64}) +precompile(Tuple{typeof(Base.Distributed.local_remotecall_thunk), typeof(Base.Distributed.rmprocs), Tuple{Int64}, Array{Any, 1}}) +precompile(Tuple{typeof(Base.Distributed.remote_do), typeof(Base.Distributed.rmprocs), Base.Distributed.Worker, Int64}) +precompile(Tuple{typeof(Base.Distributed.remote_do), typeof(Base.Distributed.rmprocs), Base.Distributed.LocalProcess, Int64}) +precompile(Tuple{getfield(Base.Distributed, Symbol("#kw##remote_do")), Array{Any, 1}, typeof(Base.Distributed.remote_do), typeof(Base.Distributed.rmprocs), Base.Distributed.Worker, Int64}) +precompile(Tuple{getfield(Base.Distributed, Symbol("#kw##remote_do")), Array{Any, 1}, typeof(Base.Distributed.remote_do), typeof(Base.Distributed.rmprocs), Base.Distributed.LocalProcess, Int64}) +precompile(Tuple{Type{Base.Distributed.ResultMsg}, Base.Distributed.RemoteException}) +precompile(Tuple{Type{Base.Distributed.ResultMsg}, Symbol}) +precompile(Tuple{typeof(Base.Distributed.send_msg_now), Base.TCPSocket, Base.Distributed.MsgHeader, Base.Distributed.ResultMsg}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Int64, Void}, Void, Int64}) +precompile(Tuple{typeof(Base.notify), Base.Condition, Base.Distributed.ProcessExitedException, Bool, Bool}) +precompile(Tuple{typeof(Base.pop!), Base.Dict{Int64, Union{Base.Distributed.Worker, Base.Distributed.LocalProcess}}, Int64, Void}) +precompile(Tuple{typeof(Base.Distributed.deregister_worker), Base.Distributed.ProcessGroup, Int64}) +precompile(Tuple{typeof(Base.Distributed.process_hdr), Base.TCPSocket, Bool}) +precompile(Tuple{typeof(Base.Distributed.deserialize_msg), Base.Distributed.ClusterSerializer{Base.TCPSocket}}) +precompile(Tuple{typeof(Base.Distributed.null_id), Base.Distributed.RRID}) +precompile(Tuple{typeof(Base.Distributed.deliver_result), Base.TCPSocket, Symbol, Base.Distributed.RRID, Base.Distributed.RemoteException}) +precompile(Tuple{typeof(Base.Distributed.disable_nagle), Base.TCPSocket}) +precompile(Tuple{typeof(Base.Distributed.message_handler_loop), Base.TCPSocket, Base.TCPSocket, Bool}) +precompile(Tuple{typeof(Base.Distributed.process_tcp_streams), Base.TCPSocket, Base.TCPSocket, Bool}) +precompile(Tuple{typeof(Base.Serializer.deserialize), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Type{Union}}) +precompile(Tuple{typeof(Base.Serializer.deserialize), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Type{Module}}) +precompile(Tuple{typeof(Base.Serializer.deserialize), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Type{SimpleVector}}) +precompile(Tuple{Type{Array{Union{Tuple{Any, Int64}, Tuple{Tuple{}, Any, Bool}}, 1}}, Tuple{Int64}}) +precompile(Tuple{typeof(Base.eachindex), Array{Union{Tuple{Any, Int64}, Tuple{Tuple{}, Any, Bool}}, 1}}) +precompile(Tuple{Type{Base.Distributed.JoinPGRPMsg}, Int64, Array{Union{Tuple{Any, Int64}, Tuple{Tuple{}, Any, Bool}}, 1}, Symbol, Bool}) +precompile(Tuple{typeof(Base.Distributed.handle_msg), Base.Distributed.JoinPGRPMsg, Base.Distributed.MsgHeader, Base.TCPSocket, Base.TCPSocket, Base.VersionNumber}) +precompile(Tuple{Type{Base.Distributed.WorkerConfig}}) +precompile(Tuple{typeof(Base.LinAlg.BLAS.set_num_threads), Int64}) +precompile(Tuple{typeof(Base.Distributed.send_msg_), Base.Distributed.Worker, Base.Distributed.MsgHeader, Base.Distributed.JoinCompleteMsg, Bool}) +precompile(Tuple{typeof(Base.Distributed.send_msg_now), Base.Distributed.Worker, Base.Distributed.MsgHeader, Base.Distributed.JoinCompleteMsg}) +precompile(Tuple{getfield(Core, Symbol("#kw#Type")), Array{Any, 1}, Type{Base.Distributed.Worker}, Int64, Base.TCPSocket, Base.TCPSocket, Base.Distributed.DefaultClusterManager}) +precompile(Tuple{typeof(Base.eltype), Type{Base.Nullable{IO}}}) +precompile(Tuple{Type{Base.Nullable{IO}}}) +precompile(Tuple{typeof(Base.eltype), Type{Base.Nullable{AbstractString}}}) +precompile(Tuple{Type{Base.Nullable{AbstractString}}}) +precompile(Tuple{typeof(Base.eltype), Type{Base.Nullable{Integer}}}) +precompile(Tuple{Type{Base.Nullable{Integer}}}) +precompile(Tuple{typeof(Base.eltype), Type{Base.Nullable{Union{Int64, Symbol}}}}) +precompile(Tuple{Type{Base.Nullable{Union{Int64, Symbol}}}}) +precompile(Tuple{typeof(Base.eltype), Type{Base.Nullable{Base.Cmd}}}) +precompile(Tuple{Type{Base.Nullable{Base.Cmd}}}) +precompile(Tuple{typeof(Base.eltype), Type{Base.Nullable{Any}}}) +precompile(Tuple{Type{Base.Nullable{Any}}}) +precompile(Tuple{typeof(Base.eltype), Type{Base.Nullable{Bool}}}) +precompile(Tuple{Type{Base.Nullable{Bool}}}) +precompile(Tuple{typeof(Base.eltype), Type{Base.Nullable{Base.Process}}}) +precompile(Tuple{Type{Base.Nullable{Base.Process}}}) +precompile(Tuple{typeof(Base.eltype), Type{Base.Nullable{Base.Dict{K, V} where V where K}}}) +precompile(Tuple{Type{Base.Nullable{Base.Dict{K, V} where V where K}}}) +precompile(Tuple{typeof(Base.eltype), Type{Base.Nullable{Array{T, N} where N where T}}}) +precompile(Tuple{Type{Base.Nullable{Array{T, N} where N where T}}}) +precompile(Tuple{typeof(Base.Distributed.register_worker_streams), Base.Distributed.Worker}) +precompile(Tuple{typeof(Base.Distributed.register_worker_streams), Base.Distributed.LocalProcess}) +precompile(Tuple{typeof(Base.convert), Type{IO}, Base.TCPSocket}) +precompile(Tuple{typeof(Base.convert), Type{Base.Distributed.ClusterSerializer{I} where I<:IO}, Base.Distributed.ClusterSerializer{Base.TCPSocket}}) +precompile(Tuple{typeof(Base.convert), Type{Base.Distributed.ClusterManager}, Base.Distributed.DefaultClusterManager}) +precompile(Tuple{typeof(Base.convert), Type{Base.Distributed.WorkerConfig}, Base.Distributed.WorkerConfig}) +precompile(Tuple{typeof(Base.convert), Type{Base.Nullable{Base.VersionNumber}}, Base.VersionNumber}) +precompile(Tuple{typeof(Base.Distributed.send_connection_hdr), Base.Distributed.Worker, Bool}) +precompile(Tuple{typeof(Base.unsafe_write), Base.TCPSocket, Ptr{UInt8}, UInt64}) +precompile(Tuple{typeof(Base.Distributed.manage), Base.Distributed.LocalManager, Int64, Base.Distributed.WorkerConfig, Symbol}) +precompile(Tuple{typeof(Base.uv_write), Base.TCPSocket, Ptr{UInt8}, UInt64}) +precompile(Tuple{typeof(Base.flush), Base.TCPSocket}) +precompile(Tuple{typeof(Base.write), Base.TCPSocket, Int64, Int64, Int64, Int64}) +precompile(Tuple{typeof(Base.unsafe_write), Base.TCPSocket, Base.RefValue{Int64}, Int64}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Base.Distributed.JoinCompleteMsg}) +precompile(Tuple{typeof(Base.unsafe_write), Base.TCPSocket, Base.RefValue{UInt8}, Int64}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Int64}) +precompile(Tuple{typeof(Base.write), Base.TCPSocket, Array{UInt8, 1}}) +precompile(Tuple{typeof(Base.Distributed.deserialize_msg), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Type{Base.Distributed.JoinCompleteMsg}}) +precompile(Tuple{typeof(Base.unsafe_read), Base.TCPSocket, Base.RefValue{Int32}, Int64}) +precompile(Tuple{typeof(Base.unsafe_read), Base.TCPSocket, Base.RefValue{Int64}, Int64}) +precompile(Tuple{typeof(Base.read!), Base.TCPSocket, Array{UInt8, 1}}) +precompile(Tuple{typeof(Base.promote_type), Type{Int64}, Type{UInt8}}) +precompile(Tuple{typeof(Base.promote_rule), Type{Int64}, Type{UInt8}}) +precompile(Tuple{typeof(Base.promote_result), Type{Int64}, Type{UInt8}, Type{Union{}}, Type{Int64}}) +precompile(Tuple{typeof(Base.read!), Base.TCPSocket, Array{UInt64, 1}}) +precompile(Tuple{typeof(Base.Serializer.deserialize), Base.Distributed.ClusterSerializer{Base.TCPSocket}}) +precompile(Tuple{typeof(Base.Serializer.deserialize_cycle), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Expr}) +precompile(Tuple{typeof(Base.Serializer.handle_deserialize), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Int32}) +precompile(Tuple{typeof(Base._array_for), Type{Union{}}, Base.UnitRange{Int64}, Base.HasShape}) +precompile(Tuple{typeof(Base.Serializer.deserialize_array), Base.Distributed.ClusterSerializer{Base.TCPSocket}}) +precompile(Tuple{typeof(Base.Serializer.deserialize_datatype), Base.Distributed.ClusterSerializer{Base.TCPSocket}}) +precompile(Tuple{typeof(Base.Serializer.deserialize_expr), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Int64}) +precompile(Tuple{typeof(Base.Serializer.deserialize), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Type{Int64}}) +precompile(Tuple{typeof(Base.read), Base.TCPSocket, Type{Int64}}) +precompile(Tuple{Type{Base.Distributed.JoinCompleteMsg}, Int64, Int64}) +precompile(Tuple{typeof(Base.Distributed.handle_msg), Base.Distributed.JoinCompleteMsg, Base.Distributed.MsgHeader, Base.TCPSocket, Base.TCPSocket, Base.VersionNumber}) +precompile(Tuple{typeof(Base.hash), Base.Distributed.RemoteChannel{Base.Channel{Any}}, UInt64}) +precompile(Tuple{typeof(Base.ht_keyindex), Base.Dict{WeakRef, Void}, Base.Distributed.RemoteChannel{Base.Channel{Any}}}) +precompile(Tuple{typeof(Base.Distributed.remotecall_fetch), typeof(Base.Distributed.put_ref), Base.Distributed.Worker, Base.Distributed.RRID, Base.Distributed.WorkerPool}) +precompile(Tuple{typeof(Base.Distributed.remotecall_fetch), typeof(Base.Distributed.put_ref), Base.Distributed.LocalProcess, Base.Distributed.RRID, Base.Distributed.WorkerPool}) +precompile(Tuple{getfield(Base.Distributed, Symbol("#kw##remotecall_fetch")), Array{Any, 1}, typeof(Base.Distributed.remotecall_fetch), typeof(Base.Distributed.put_ref), Base.Distributed.Worker, Base.Distributed.RRID, Base.Distributed.WorkerPool}) +precompile(Tuple{getfield(Base.Distributed, Symbol("#kw##remotecall_fetch")), Array{Any, 1}, typeof(Base.Distributed.remotecall_fetch), typeof(Base.Distributed.put_ref), Base.Distributed.LocalProcess, Base.Distributed.RRID, Base.Distributed.WorkerPool}) +precompile(Tuple{typeof(Base.rehash!), Base.Dict{WeakRef, Void}, Int64}) +precompile(Tuple{typeof(Base.ht_keyindex2), Base.Dict{WeakRef, Void}, WeakRef}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{WeakRef, Void}, Void, WeakRef, Int64}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{WeakRef, Void}, Void, WeakRef}) +precompile(Tuple{typeof(Base.finalizer), Base.Distributed.RemoteChannel{Base.Channel{Any}}, typeof(Base.Distributed.finalize_ref)}) +precompile(Tuple{typeof(Base.Distributed.test_existing_ref), Base.Distributed.RemoteChannel{Base.Channel{Any}}}) +precompile(Tuple{Type{Base.Distributed.RemoteChannel{T} where T<:Base.AbstractChannel}, Int64}) +precompile(Tuple{Type{Base.Channel{Int64}}, Int64}) +precompile(Tuple{Type{Base.Distributed.WorkerPool}}) +precompile(Tuple{typeof(Base.Distributed.default_worker_pool)}) +precompile(Tuple{typeof(Base.get), Base.Nullable{Base.Dict{K, V} where V where K}, Base.Dict{Any, Any}}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Any, Any}, Int64, Symbol}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Any, Any}, Int64, Symbol, Int64}) +precompile(Tuple{typeof(Base.convert), Type{Base.Nullable{Base.Dict{K, V} where V where K}}, Base.Dict{Any, Any}}) +precompile(Tuple{typeof(Base.convert), Type{Base.Nullable{Integer}}, Int64}) +precompile(Tuple{typeof(Base.convert), Type{Base.Nullable{Base.VersionNumber}}, Base.VersionNumber}) +precompile(Tuple{typeof(Base.put!), Base.Channel{Any}, Int64}) +precompile(Tuple{typeof(Base.put_buffered), Base.Channel{Any}, Int64}) +precompile(Tuple{typeof(Base.put_unbuffered), Base.Channel{Any}, Int64}) +precompile(Tuple{typeof(Base.Distributed.call_on_owner), typeof(Base.Distributed.put_ref), Base.Distributed.RemoteChannel{Base.Channel{Any}}, Base.Distributed.WorkerPool}) +precompile(Tuple{typeof(Base.Distributed.put_ref), Base.Distributed.RRID, Base.Distributed.WorkerPool}) +precompile(Tuple{typeof(Base.put!), Base.Distributed.RemoteValue, Base.Distributed.WorkerPool}) +precompile(Tuple{typeof(Base.put!), Base.Channel{Any}, Base.Distributed.WorkerPool}) +precompile(Tuple{typeof(Base.put_buffered), Base.Channel{Any}, Base.Distributed.WorkerPool}) +precompile(Tuple{typeof(Base.put_unbuffered), Base.Channel{Any}, Base.Distributed.WorkerPool}) +precompile(Tuple{typeof(Base.push!), Base.Distributed.WorkerPool, Int64}) +precompile(Tuple{typeof(Base.check_channel_state), Base.Channel{Int64}}) +precompile(Tuple{typeof(Base.put_buffered), Base.Channel{Int64}, Int64}) +precompile(Tuple{typeof(Base.put_unbuffered), Base.Channel{Int64}, Int64}) +precompile(Tuple{typeof(Base.put!), Base.Channel{Int64}, Int64}) +precompile(Tuple{typeof(Base._delete!), Base.Dict{Any, Any}, Int64}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Base.Distributed.RemoteDoMsg}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Distributed.ClusterSerializer{Base.TCPSocket}, typeof(Base.Distributed.set_valid_processes)}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Tuple{Array{Int64, 1}}}) +precompile(Tuple{typeof(Base.write), Base.TCPSocket, Array{Int64, 1}}) +precompile(Tuple{typeof(Base.Serializer.serialize_array_data), Base.TCPSocket, Array{Int64, 1}}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Array{Int64, 1}}) +precompile(Tuple{typeof(Base.sort!), Array{Int64, 1}, Int64, Int64, Base.Sort.InsertionSortAlg, Base.Order.ForwardOrdering}) +precompile(Tuple{typeof(Base.Sort.partition!), Array{Int64, 1}, Int64, Int64, Base.Order.ForwardOrdering}) +precompile(Tuple{typeof(Base.sort!), Array{Int64, 1}, Int64, Int64, Base.Sort.QuickSortAlg, Base.Order.ForwardOrdering}) +precompile(Tuple{typeof(Base.Serializer.deserialize), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Type{typeof(Base.Distributed.set_valid_processes)}}) +precompile(Tuple{typeof(Base.Distributed.handle_msg), Base.Distributed.RemoteDoMsg, Base.Distributed.MsgHeader, Base.TCPSocket, Base.TCPSocket, Base.VersionNumber}) +precompile(Tuple{typeof(Base.put!), Base.Channel{Any}, Tuple{Array{Int64, 1}, Void}}) +precompile(Tuple{typeof(Base.put_buffered), Base.Channel{Any}, Tuple{Array{Int64, 1}, Void}}) +precompile(Tuple{typeof(Base.put_unbuffered), Base.Channel{Any}, Tuple{Array{Int64, 1}, Void}}) +precompile(Tuple{typeof(Base.Distributed.set_valid_processes), Array{Int64, 1}}) +precompile(Tuple{typeof(Base.promote_type), Type{Int64}, Type{Int64}}) +precompile(Tuple{typeof(Base.sizehint!), Base.Dict{Int64, Void}, Int64}) +precompile(Tuple{typeof(Base.union!), Base.Set{Int64}, Array{Int64, 1}}) +precompile(Tuple{typeof(Base.start), Tuple{Array{Int64, 1}, Void}}) +precompile(Tuple{typeof(Base.indexed_next), Tuple{Array{Int64, 1}, Void}, Int64, Int64}) +precompile(Tuple{typeof(Base.setdiff), Array{Int64, 1}, Array{Int64, 1}}) +precompile(Tuple{typeof(Base.Multimedia.display), Array{Int64, 1}}) +precompile(Tuple{typeof(Base.isassigned), Array{Int64, 1}, Int64}) +precompile(Tuple{typeof(Base.array_eltype_show_how), Array{Int64, 1}}) +precompile(Tuple{typeof(Base._summary), Array{Int64, 1}, Tuple{Base.OneTo{Int64}}}) +precompile(Tuple{typeof(Base.isassigned), Array{Int64, 1}, Int64, Int64}) +precompile(Tuple{typeof(Base.isassigned), Array{Int64, 1}}) +precompile(Tuple{typeof(Base.Multimedia.display), Base.REPL.REPLDisplay{Base.REPL.LineEditREPL}, Array{Int64, 1}}) +precompile(Tuple{typeof(Base.Multimedia.display), Base.REPL.REPLDisplay{Base.REPL.LineEditREPL}, Base.MIME{Symbol("text/plain")}, Array{Int64, 1}}) +precompile(Tuple{typeof(Base.show_delim_array), Base.IOContext{Base.Terminals.TTYTerminal}, Array{Int64, 1}, String, String, String, Bool, Int64, Int64}) +precompile(Tuple{typeof(Base.print), Base.IOContext{Base.Terminals.TTYTerminal}, Char}) +precompile(Tuple{typeof(Base.print), Base.IOContext{Base.Terminals.TTYTerminal}, String, Char}) +precompile(Tuple{typeof(Base.print), Base.IOContext{Base.Terminals.TTYTerminal}, String, String}) +precompile(Tuple{typeof(Base.print), Base.IOContext{Base.Terminals.TTYTerminal}, String, String, Char}) +precompile(Tuple{typeof(Base.show_vector), Base.IOContext{Base.Terminals.TTYTerminal}, Array{Int64, 1}, String, String}) +precompile(Tuple{typeof(Base.print_matrix_repr), Base.IOContext{Base.Terminals.TTYTerminal}, Array{Int64, 1}}) +precompile(Tuple{typeof(Base.show_nd), Base.IOContext{Base.Terminals.TTYTerminal}, Array{Int64, 1}, typeof(Base.print_matrix_repr), Bool}) +precompile(Tuple{typeof(Base.repremptyarray), Base.IOContext{Base.Terminals.TTYTerminal}, Array{Int64, 1}}) +precompile(Tuple{typeof(Base.print_matrix), Base.IOContext{Base.Terminals.TTYTerminal}, Array{Int64, 1}, String, String, String}) +precompile(Tuple{typeof(Base.getindex), Base.ImmutableDict{Symbol, Any}, Symbol}) +precompile(Tuple{typeof(Base.vcat), Base.OneTo{Int64}}) +precompile(Tuple{typeof(Base.collect_to!), Array{Int64, 1}, Base.Generator{Array{Tuple{Int64, Int64}, 1}, typeof(Base.sum)}, Int64, Int64}) +precompile(Tuple{typeof(Base._collect), Array{Tuple{Int64, Int64}, 1}, Base.Generator{Array{Tuple{Int64, Int64}, 1}, typeof(Base.sum)}, Base.EltypeUnknown, Base.HasShape}) +precompile(Tuple{typeof(Base.pop!), Array{Tuple{Int64, Int64}, 1}}) +precompile(Tuple{typeof(Base.reverse), Array{Tuple{Int64, Int64}, 1}, Int64, Int64}) +precompile(Tuple{typeof(Base.print_matrix_vdots), Base.IOContext{Base.Terminals.TTYTerminal}, String, Array{Tuple{Int64, Int64}, 1}, String, Int64, Int64}) +precompile(Tuple{typeof(Base.print_matrix), Base.IOContext{Base.Terminals.TTYTerminal}, Array{Int64, 1}, String, String, String, String, String, String, Int64, Int64}) +precompile(Tuple{typeof(Base.alignment), Base.IOContext{Base.Terminals.TTYTerminal}, Array{Int64, 1}, Array{Int64, 1}, Array{Int64, 1}, Int64, Int64, Int64}) +precompile(Tuple{getfield(Base, Symbol("#kw##sprint")), Array{Any, 1}, typeof(Base.sprint), Int64, typeof(Base.show), Int64}) +precompile(Tuple{typeof(Base.sub2ind), Tuple{Int64}, Int64, Int64}) +precompile(Tuple{typeof(Base._sub2ind), Tuple{Int64}, Int64, Int64, Int64, Int64}) +precompile(Tuple{typeof(Base._sub2ind), Tuple{}, Int64, Int64, Int64}) +precompile(Tuple{typeof(Base.first), Array{Int64, 1}}) +precompile(Tuple{typeof(Base.print_matrix_row), Base.IOContext{Base.Terminals.TTYTerminal}, Array{Int64, 1}, Array{Tuple{Int64, Int64}, 1}, Int64, Array{Int64, 1}, String}) +precompile(Tuple{typeof(Base.print), Base.AbstractIOBuffer{Array{UInt8, 1}}, Base.OneTo{Int64}}) +precompile(Tuple{typeof(Base.last), Array{Int64, 1}}) +precompile(Tuple{typeof(Base.LineEdit.edit_delete), Base.AbstractIOBuffer{Array{UInt8, 1}}}) +precompile(Tuple{typeof(Base.print), String}) +precompile(Tuple{typeof(Base.vcat), Array{Int64, 1}}) +precompile(Tuple{typeof(Base.Distributed._rmprocs), Array{Int64, 1}, Float64}) +precompile(Tuple{typeof(Core.Inference.eltype), Type{Array{Int64, 1}}}) +precompile(Tuple{typeof(Base.vcat), Int64}) +precompile(Tuple{typeof(Base.kill), Base.Distributed.LocalManager, Int64, Base.Distributed.WorkerConfig}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Distributed.ClusterSerializer{Base.TCPSocket}, typeof(Base.exit)}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Tuple{}}) +precompile(Tuple{typeof(Base.Serializer.deserialize), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Type{typeof(Base.exit)}}) +precompile(Tuple{typeof(Base.uvfinalize), Base.PipeEndpoint}) +precompile(Tuple{typeof(Base.unpreserve_handle), Base.PipeEndpoint}) +precompile(Tuple{typeof(Base.stream_wait), Base.PipeEndpoint, Base.Condition}) +precompile(Tuple{typeof(Base.close), Base.PipeEndpoint}) +precompile(Tuple{typeof(Base.uvfinalize), Base.TCPServer}) +precompile(Tuple{typeof(Base.uvfinalize), Base.TCPSocket}) +precompile(Tuple{typeof(Base._uv_hook_close), Base.TCPSocket}) +precompile(Tuple{typeof(Base.in), Int64, Base.IntSet}) +precompile(Tuple{typeof(Base._uv_hook_close), Base.Process}) +precompile(Tuple{typeof(Base.Distributed.finalize_ref), Base.Distributed.RemoteChannel{Base.Channel{Any}}}) +precompile(Tuple{typeof(Base._delete!), Base.Dict{WeakRef, Void}, Int64}) +precompile(Tuple{typeof(Base.Distributed.send_del_client), Base.Distributed.RemoteChannel{Base.Channel{Any}}}) +precompile(Tuple{typeof(Base.:(==)), Base.Distributed.RemoteChannel{Base.Channel{Any}}, Base.Distributed.RemoteChannel{Base.Channel{Any}}}) +precompile(Tuple{typeof(Base.delete!), Base.IntSet, Int64}) +precompile(Tuple{typeof(Base.isempty), Base.IntSet}) +precompile(Tuple{typeof(Base.any), Base.BitArray{1}}) +precompile(Tuple{typeof(Base.uvfinalize), Base.PipeEndpoint}) +precompile(Tuple{typeof(Base.uvfinalize), Base.Process}) +precompile(Tuple{getfield(Base.Distributed, Symbol("#kw##remotecall_fetch")), Array{Any, 1}, typeof(Base.Distributed.remotecall_fetch), typeof(Base.Distributed.fetch_future), Base.Distributed.Worker, Base.Distributed.RRID, Int64}) +precompile(Tuple{getfield(Base.Distributed, Symbol("#kw##remotecall_fetch")), Array{Any, 1}, typeof(Base.Distributed.remotecall_fetch), typeof(Base.find_in_path), Base.Distributed.LocalProcess, String, Void}) +precompile(Tuple{getfield(Base.Distributed, Symbol("#kw##remotecall_fetch")), Array{Any, 1}, typeof(Base.Distributed.remotecall_fetch), typeof(Base.find_in_path), Base.Distributed.Worker, String, Void}) +precompile(Tuple{getfield(Base.Distributed, Symbol("#kw##remotecall_fetch")), Array{Any, 1}, typeof(Base.Distributed.remotecall_fetch), typeof(Base.open), Base.Distributed.LocalProcess, typeof(Base.read), String}) +precompile(Tuple{getfield(Base.Distributed, Symbol("#kw##remotecall_fetch")), Array{Any, 1}, typeof(Base.Distributed.remotecall_fetch), typeof(Base.open), Base.Distributed.Worker, typeof(Base.read), String}) +precompile(Tuple{getfield(Base.Distributed, Symbol("#kw##remote_do")), Array{Any, 1}, typeof(Base.Distributed.remote_do), typeof(Base.exit), Base.Distributed.Worker}) +precompile(Tuple{getfield(Base.Distributed, Symbol("#kw##rmprocs")), Array{Any, 1}, typeof(Base.Distributed.rmprocs), Array{Int64, 1}}) +precompile(Tuple{getfield(Base.Filesystem, Symbol("#kw##rm")), Array{Any, 1}, typeof(Base.Filesystem.rm), String}) +precompile(Tuple{getfield(Base, Symbol("#kw##info")), Array{Any, 1}, typeof(Base.info), Base.IOStream, String}) +precompile(Tuple{getfield(Base, Symbol("#kw##print_with_color")), Array{Any, 1}, typeof(Base.print_with_color), Symbol, Base.IOStream, String}) +precompile(Tuple{getfield(Base, Symbol("#kw##readbytes!")), Array{Any, 1}, typeof(Base.readbytes!), Base.IOStream, Array{UInt8, 1}, Int32}) +precompile(Tuple{getfield(Base, Symbol("#kw##spawn")), Array{Any, 1}, typeof(Base.spawn), Base.Cmd, Tuple{Base.Pipe, Base.TTY, Base.IOStream}}) +precompile(Tuple{getfield(Base, Symbol("#kw##systemerror")), Array{Any, 1}, typeof(Base.systemerror), Symbol, Bool}) +precompile(Tuple{getfield(Base, Symbol("#kw##with_output_color")), Array{Any, 1}, typeof(Base.with_output_color), typeof(Base.println), Symbol, Base.IOStream, Base.SubString{String}}) +precompile(Tuple{getfield(Base, Symbol("#kw##with_output_color")), Array{Any, 1}, typeof(Base.with_output_color), typeof(Base.print), Symbol, Base.IOStream, String}) +precompile(Tuple{Type{Base.Distributed.Future}, Int64}) +precompile(Tuple{Type{Base.Process}, Base.Cmd, Ptr{Void}, Base.Pipe, Base.TTY, Base.IOStream}) +precompile(Tuple{Type{Base.Set{Tuple{String, Float64}}}, Tuple{Tuple{String, Float64}}}) +precompile(Tuple{Type{Base.VersionNumber}, Int64, Int64, Int64, Tuple{String, Int64}, Tuple{}}) +precompile(Tuple{Type{Base.VersionNumber}, Int64, Int64, Int64, Tuple{String}, Tuple{Int64}}) +precompile(Tuple{Type{Core.Inference.Generator{I, F} where F where I}, Type{Core.Inference.Const}, Tuple{Symbol, Expr}}) +precompile(Tuple{Type{Core.Inference.Generator{Tuple{Symbol, Expr}, Type{Core.Inference.Const}}}, Type{Core.Inference.Const}, Tuple{Symbol, Expr}}) +precompile(Tuple{typeof(Base.cmd_gen), Tuple{Tuple{Base.Cmd}, Tuple{String}, Tuple{String}, Tuple{String}, Tuple{String}, Tuple{String}, Tuple{String}, Tuple{String, String}, Tuple{String}, Tuple{String}}}) +precompile(Tuple{typeof(Base._collect), Array{Any, 1}, Base.Generator{Array{Any, 1}, typeof(Base.FastMath.make_fastmath)}, Base.EltypeUnknown, Base.HasShape}) +precompile(Tuple{typeof(Base._collect), Array{Base.Process, 1}, Base.Generator{Array{Base.Process, 1}, typeof(Base.kill)}, Base.EltypeUnknown, Base.HasShape}) +precompile(Tuple{typeof(Base.collect_to!), Array{Any, 1}, Base.Generator{Array{Any, 1}, typeof(Base.FastMath.make_fastmath)}, Int64, Int64}) +precompile(Tuple{typeof(Base.collect_to!), Array{Expr, 1}, Base.Generator{Array{Any, 1}, typeof(Base.FastMath.make_fastmath)}, Int64, Int64}) +precompile(Tuple{typeof(Base.collect_to!), Array{Int32, 1}, Base.Generator{Array{Base.Process, 1}, typeof(Base.kill)}, Int64, Int64}) +precompile(Tuple{typeof(Base.collect_to!), Array{Symbol, 1}, Base.Generator{Array{Any, 1}, typeof(Base.FastMath.make_fastmath)}, Int64, Int64}) +precompile(Tuple{typeof(Base.compilecache), String}) +precompile(Tuple{typeof(Base.copy!), Array{Tuple{String, Float64}, 1}, Int64, Array{Tuple{String, Float64}, 1}, Int64, Int64}) +precompile(Tuple{typeof(Base.create_expr_cache), String, String, Array{Any, 1}}) +precompile(Tuple{typeof(Base._delete!), Base.Dict{Symbol, Base.Condition}, Int64}) +precompile(Tuple{typeof(Base.Distributed.call_on_owner), typeof(Base.Distributed.fetch_future), Base.Distributed.Future, Int64}) +precompile(Tuple{typeof(Base.Distributed.fetch_future), Base.Distributed.RRID, Int64}) +precompile(Tuple{typeof(Base.Distributed.flush_gc_msgs), Base.Distributed.Worker}) +precompile(Tuple{typeof(Base.Distributed.remotecall_fetch), typeof(Base.Distributed.fetch_future), Base.Distributed.Worker, Base.Distributed.RRID, Int64}) +precompile(Tuple{typeof(Base.Distributed.remotecall_fetch), typeof(Base.find_in_path), Base.Distributed.LocalProcess, String, Void}) +precompile(Tuple{typeof(Base.Distributed.remotecall_fetch), typeof(Base.find_in_path), Base.Distributed.Worker, String, Void}) +precompile(Tuple{typeof(Base.Distributed.remotecall_fetch), typeof(Base.open), Base.Distributed.LocalProcess, typeof(Base.read), String}) +precompile(Tuple{typeof(Base.Distributed.remotecall_fetch), typeof(Base.open), Base.Distributed.Worker, typeof(Base.read), String}) +precompile(Tuple{typeof(Base.Distributed.remote_do), typeof(Base.exit), Base.Distributed.Worker}) +precompile(Tuple{typeof(Base.Distributed.send_del_client), Base.Distributed.Future}) +precompile(Tuple{typeof(Base.Distributed.send_msg), Base.Distributed.Worker, Base.Distributed.MsgHeader, Base.Distributed.CallMsg{:call}}) +precompile(Tuple{typeof(Base.Distributed.send_msg_), Base.Distributed.Worker, Base.Distributed.MsgHeader, Base.Distributed.CallMsg{:call}, Bool}) +precompile(Tuple{typeof(Base.Distributed.send_msg), Base.Distributed.Worker, Base.Distributed.MsgHeader, Base.Distributed.CallMsg{:call_fetch}}) +precompile(Tuple{typeof(Base.Distributed.send_msg_), Base.Distributed.Worker, Base.Distributed.MsgHeader, Base.Distributed.CallMsg{:call_fetch}, Bool}) +precompile(Tuple{typeof(Base.Distributed.send_msg), Base.Distributed.Worker, Base.Distributed.MsgHeader, Base.Distributed.RemoteDoMsg}) +precompile(Tuple{typeof(Base.Distributed.send_msg_), Base.Distributed.Worker, Base.Distributed.MsgHeader, Base.Distributed.RemoteDoMsg, Bool}) +precompile(Tuple{typeof(Base.Distributed.terminate_all_workers)}) +precompile(Tuple{typeof(Base.Distributed.test_existing_ref), Base.Distributed.Future}) +precompile(Tuple{typeof(Base.Docs.docm), String, Expr}) +precompile(Tuple{typeof(Base.Docs.docm), String, Expr, Bool}) +precompile(Tuple{typeof(Base.Docs.keyworddoc), String, Base.BaseDocs.Keyword}) +precompile(Tuple{typeof(Base.Docs.objectdoc), String, Expr, Expr, Expr}) +precompile(Tuple{typeof(Base.FastMath.make_fastmath), Expr}) +precompile(Tuple{typeof(Base.Filesystem.lstat), String}) +precompile(Tuple{typeof(Base.Filesystem.mkdir), String, UInt16}) +precompile(Tuple{typeof(Base.Filesystem.mkpath), String, UInt16}) +precompile(Tuple{typeof(Base.Filesystem.samefile), String, String}) +precompile(Tuple{typeof(Base.Filesystem.unlink), String}) +precompile(Tuple{typeof(Base.finalizer), Base.Distributed.Future, typeof(Base.Distributed.finalize_ref)}) +precompile(Tuple{typeof(Base.find_all_in_cache_path), Symbol}) +precompile(Tuple{typeof(Base.find_in_node_path), String, Void, Int64}) +precompile(Tuple{typeof(Base.find_in_path), String, Void}) +precompile(Tuple{typeof(Base.getindex), Base.ObjectIdDict, Symbol}) +precompile(Tuple{typeof(Base.getindex), Type{Tuple{String, Float64}}, Tuple{String, Float64}}) +precompile(Tuple{typeof(Base.Grisu._show), Base.IOContext{Base.AbstractIOBuffer{Array{UInt8, 1}}}, Float64, Int64, Int64, Bool, Bool}) +precompile(Tuple{typeof(Base.hash), Base.Distributed.Future, UInt64}) +precompile(Tuple{typeof(Base.hash), Tuple{String, Float64}, UInt64}) +precompile(Tuple{typeof(Base.ht_keyindex2), Base.Dict{Symbol, Base.Condition}, Symbol}) +precompile(Tuple{typeof(Base.ht_keyindex2), Base.Dict{Symbol, UInt64}, Symbol}) +precompile(Tuple{typeof(Base.ht_keyindex2), Base.Dict{Tuple{String, Float64}, Void}, Tuple{String, Float64}}) +precompile(Tuple{typeof(Base.ht_keyindex), Base.Dict{Symbol, Base.Condition}, Symbol}) +precompile(Tuple{typeof(Base.ht_keyindex), Base.Dict{Symbol, UInt64}, Symbol}) +precompile(Tuple{typeof(Base.ht_keyindex), Base.Dict{Tuple{String, Float64}, Void}, Tuple{String, Float64}}) +precompile(Tuple{typeof(Base.ht_keyindex), Base.Dict{WeakRef, Void}, Base.Distributed.Future}) +precompile(Tuple{typeof(Base.ident_cmp), Tuple{String, String, Int64}, Tuple{String, Int64}}) +precompile(Tuple{typeof(Base.include_from_node1), String}) +precompile(Tuple{typeof(Base._include_from_serialized), String}) +precompile(Tuple{typeof(Base.indexed_next), Tuple{Symbol, UInt64}, Int64, Int64}) +precompile(Tuple{typeof(Base.indexed_next), Tuple{Void, Void}, Int64, Int64}) +precompile(Tuple{typeof(Base.isassigned), Array{String, 1}, Int64}) +precompile(Tuple{typeof(Base.isempty), Tuple{String, Int64}}) +precompile(Tuple{typeof(Base.isequal), Float64, String}) +precompile(Tuple{typeof(Base.isequal), String, Float64}) +precompile(Tuple{typeof(Base.isequal), Tuple{String, Float64}, Tuple{String, Float64}}) +precompile(Tuple{typeof(Base._jl_spawn), String, Array{String, 1}, Ptr{Void}, Base.Process, Base.PipeEndpoint, Base.TTY, Base.Filesystem.File}) +precompile(Tuple{typeof(Base.julia_cmd)}) +precompile(Tuple{typeof(Base.load_hook), String, String, String}) +precompile(Tuple{typeof(Base.load_hook), String, String, Void}) +precompile(Tuple{typeof(Base.next), Base.Generator{Array{Any, 1}, typeof(Base.FastMath.make_fastmath)}, Int64}) +precompile(Tuple{typeof(Base.open), Base.CmdRedirect, String, Base.TTY}) +precompile(Tuple{typeof(Base.open), String, String}) +precompile(Tuple{typeof(Base.open), typeof(Base.read), String}) +precompile(Tuple{typeof(Base.parse_cache_header), Base.IOStream}) +precompile(Tuple{typeof(Base.pop!), Base.Dict{Symbol, Base.Condition}, Symbol}) +precompile(Tuple{typeof(Base.precompilableerror), Base.LoadError, Bool}) +precompile(Tuple{typeof(Base.precompilableerror), Base.PrecompilableError, Bool}) +precompile(Tuple{typeof(Base.__precompile__)}) +precompile(Tuple{typeof(Base.__precompile__), Bool}) +precompile(Tuple{typeof(Base.println_with_color), Symbol, Base.IOStream, Base.SubString{String}}) +precompile(Tuple{typeof(Base.push!), Array{Tuple{String, Float64}, 1}, Tuple{String, Float64}}) +precompile(Tuple{typeof(Base.put!), Base.Channel{Any}, Tuple{Void, Void}}) +precompile(Tuple{typeof(Base.put_buffered), Base.Channel{Any}, Tuple{Void, Void}}) +precompile(Tuple{typeof(Base.put_unbuffered), Base.Channel{Any}, Tuple{Void, Void}}) +precompile(Tuple{typeof(Base.read), Base.IOStream, Type{Int32}}) +precompile(Tuple{typeof(Base.read), Base.IOStream, Type{Int64}}) +precompile(Tuple{typeof(Base.read), Base.IOStream, Type{UInt64}}) +precompile(Tuple{typeof(Base.read!), Base.PipeEndpoint, Array{UInt64, 1}}) +precompile(Tuple{typeof(Base.read!), Base.PipeEndpoint, Array{UInt8, 1}}) +precompile(Tuple{typeof(Base.read), Base.PipeEndpoint, Type{Int64}}) +precompile(Tuple{typeof(Base.read), Base.PipeEndpoint, Type{UInt64}}) +precompile(Tuple{typeof(Base.read), Base.PipeEndpoint, Type{UInt8}}) +precompile(Tuple{typeof(Base.readbytes_all!), Base.IOStream, Array{UInt8, 1}, Int32}) +precompile(Tuple{typeof(Base.readbytes_some!), Base.IOStream, Array{UInt8, 1}, Int32}) +precompile(Tuple{typeof(Base._redirect), Base.IOStream, Base.Dict{Tuple{Union{Module, Void}, Union{Symbol, Void}}, IO}, Base.StackTraces.StackFrame}) +precompile(Tuple{typeof(Base._redirect), Base.IOStream, Base.Dict{Tuple{Union{Module, Void}, Union{Symbol, Void}}, IO}, Symbol}) +precompile(Tuple{typeof(Base.rehash!), Base.Dict{Symbol, Base.Condition}, Int64}) +precompile(Tuple{typeof(Base.rehash!), Base.Dict{Symbol, UInt64}, Int64}) +precompile(Tuple{typeof(Base.rehash!), Base.Dict{Tuple{String, Float64}, Void}, Int64}) +precompile(Tuple{typeof(Base.remove_linenums!), Module}) +precompile(Tuple{typeof(Base._require_from_serialized), Int64, Symbol, String, Bool}) +precompile(Tuple{typeof(Base._require_search_from_serialized), Int64, Symbol, String, Bool}) +precompile(Tuple{typeof(Base.require), Symbol}) +precompile(Tuple{typeof(Base.resize!), Array{Base.Condition, 1}, Int64}) +precompile(Tuple{typeof(Base.resize!), Array{Tuple{String, Float64}, 1}, Int64}) +precompile(Tuple{typeof(Base.resize!), Array{UInt8, 1}, Int32}) +precompile(Tuple{typeof(Base.Serializer.deserialize_array), Base.Serializer.SerializationState{Base.PipeEndpoint}}) +precompile(Tuple{typeof(Base.Serializer.deserialize), Base.PipeEndpoint}) +precompile(Tuple{typeof(Base.Serializer.deserialize), Base.Serializer.SerializationState{Base.PipeEndpoint}}) +precompile(Tuple{typeof(Base.Serializer.deserialize), Base.Serializer.SerializationState{Base.PipeEndpoint}, Type{Int64}}) +precompile(Tuple{typeof(Base.Serializer.deserialize), Base.Serializer.SerializationState{Base.PipeEndpoint}, Type{QuoteNode}}) +precompile(Tuple{typeof(Base.Serializer.deserialize), Base.Serializer.SerializationState{Base.PipeEndpoint}, Type{String}}) +precompile(Tuple{typeof(Base.Serializer.deserialize), Base.Serializer.SerializationState{Base.PipeEndpoint}, Type{UInt64}}) +precompile(Tuple{typeof(Base.Serializer.deserialize_cycle), Base.Serializer.SerializationState{Base.PipeEndpoint}, Expr}) +precompile(Tuple{typeof(Base.Serializer.deserialize_datatype), Base.Serializer.SerializationState{Base.PipeEndpoint}}) +precompile(Tuple{typeof(Base.Serializer.deserialize_expr), Base.Serializer.SerializationState{Base.PipeEndpoint}, Int64}) +precompile(Tuple{typeof(Base.Serializer.handle_deserialize), Base.Serializer.SerializationState{Base.PipeEndpoint}, Int32}) +precompile(Tuple{typeof(Base.Serializer.serialize_any), Base.Serializer.SerializationState{Base.Pipe}, QuoteNode}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Serializer.SerializationState{Base.Pipe}, Array{Any, 1}}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Serializer.SerializationState{Base.Pipe}, Array{String, 1}}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Serializer.SerializationState{Base.Pipe}, Bool}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Serializer.SerializationState{Base.Pipe}, Expr}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Serializer.SerializationState{Base.Pipe}, Int64}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Serializer.SerializationState{Base.Pipe}, Module}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Serializer.SerializationState{Base.Pipe}, QuoteNode}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Serializer.SerializationState{Base.Pipe}, SimpleVector}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Serializer.SerializationState{Base.Pipe}, String}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Serializer.SerializationState{Base.Pipe}, Symbol}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Serializer.SerializationState{Base.Pipe}, Tuple{Int64}}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Serializer.SerializationState{Base.Pipe}, Tuple{Symbol, UInt64}}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Serializer.SerializationState{Base.Pipe}, Type{Any}}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Serializer.SerializationState{Base.Pipe}, TypeName}) +precompile(Tuple{typeof(Base.Serializer.serialize), Base.Serializer.SerializationState{Base.Pipe}, UInt64}) +precompile(Tuple{typeof(Base.Serializer.serialize_cycle), Base.Serializer.SerializationState{Base.Pipe}, Expr}) +precompile(Tuple{typeof(Base.Serializer.serialize_cycle), Base.Serializer.SerializationState{Base.Pipe}, TypeName}) +precompile(Tuple{typeof(Base.Serializer.serialize_cycle), Base.Serializer.SerializationState{Base.Pipe}, UInt64}) +precompile(Tuple{typeof(Base.Serializer.serialize_cycle_header), Base.Serializer.SerializationState{Base.Pipe}, QuoteNode}) +precompile(Tuple{typeof(Base.Serializer.serialize_mod_names), Base.Serializer.SerializationState{Base.Pipe}, Module}) +precompile(Tuple{typeof(Base.Serializer.serialize_type), Base.Serializer.SerializationState{Base.Pipe}, DataType}) +precompile(Tuple{typeof(Base.Serializer.serialize_type_data), Base.Serializer.SerializationState{Base.Pipe}, Type{Any}, Bool}) +precompile(Tuple{typeof(Base.Serializer.serialize_typename), Base.Serializer.SerializationState{Base.Pipe}, TypeName}) +precompile(Tuple{typeof(Base.Serializer.should_send_whole_type), Base.Serializer.SerializationState{Base.Pipe}, Type{Any}}) +precompile(Tuple{typeof(Base.Serializer.write_as_tag), Base.Pipe, Int32}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Symbol, Base.Condition}, Base.Condition, Symbol}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Symbol, Base.Condition}, Base.Condition, Symbol, Int64}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Symbol, UInt64}, UInt64, Symbol}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Symbol, UInt64}, UInt64, Symbol, Int64}) +precompile(Tuple{typeof(Base.setindex!), Base.Dict{Tuple{String, Float64}, Void}, Void, Tuple{String, Float64}}) +precompile(Tuple{typeof(Base._setindex!), Base.Dict{Tuple{String, Float64}, Void}, Void, Tuple{String, Float64}, Int64}) +precompile(Tuple{typeof(Base.show), Base.IOContext{Base.AbstractIOBuffer{Array{UInt8, 1}}}, Float64}) +precompile(Tuple{typeof(Base.show_delim_array), Base.AbstractIOBuffer{Array{UInt8, 1}}, Tuple{String, Float64}, Char, Char, Char, Bool, Int64, Int64}) +precompile(Tuple{typeof(Base.show_unquoted), Base.AbstractIOBuffer{Array{UInt8, 1}}, Expr}) +precompile(Tuple{typeof(Base.skip_deleted), Base.Dict{Tuple{String, Float64}, Void}, Int64}) +precompile(Tuple{typeof(Base.spawn), Base.CmdRedirect, Tuple{Base.Pipe, Base.TTY, Base.IOStream}}) +precompile(Tuple{typeof(Base.stale_cachefile), String, String}) +precompile(Tuple{typeof(Base.start), Tuple{Symbol, UInt64}}) +precompile(Tuple{typeof(Base.start), Tuple{Void, Void}}) +precompile(Tuple{typeof(Base.:(>)), String, String}) +precompile(Tuple{typeof(Base._str), String}) +precompile(Tuple{typeof(Base._str), Void}) +precompile(Tuple{typeof(Base.sync_add), Base.Distributed.Future}) +precompile(Tuple{typeof(Base.trunc), Float64, Int64, Int64}) +precompile(Tuple{typeof(Base.union!), Base.Set{Tuple{String, Float64}}, Tuple{Tuple{String, Float64}}}) +precompile(Tuple{typeof(Base.unique_from), Array{Any, 1}, Array{Tuple{String, Float64}, 1}, Base.Set{Tuple{String, Float64}}, Int64}) +precompile(Tuple{typeof(Base.unsafe_copy!), Array{Tuple{String, Float64}, 1}, Int64, Array{Tuple{String, Float64}, 1}, Int64, Int64}) +precompile(Tuple{typeof(Base.unsafe_read), Base.IOStream, Base.RefValue{Float64}, Int64}) +precompile(Tuple{typeof(Base.unsafe_read), Base.PipeEndpoint, Base.RefValue{Int32}, Int64}) +precompile(Tuple{typeof(Base.unsafe_read), Base.PipeEndpoint, Base.RefValue{Int64}, Int64}) +precompile(Tuple{typeof(Base.unsafe_read), Base.PipeEndpoint, Base.RefValue{UInt64}, Int64}) +precompile(Tuple{typeof(Base.unsafe_read), Base.PipeEndpoint, Ptr{UInt8}, UInt64}) +precompile(Tuple{typeof(Base.unsafe_write), Base.Pipe, Base.RefValue{Int32}, Int64}) +precompile(Tuple{typeof(Base.unsafe_write), Base.Pipe, Base.RefValue{Int64}, Int64}) +precompile(Tuple{typeof(Base.unsafe_write), Base.Pipe, Base.RefValue{UInt64}, Int64}) +precompile(Tuple{typeof(Base.write), Base.Pipe, UInt64}) +precompile(Tuple{typeof(Core.Inference.collect), Type{Any}, Core.Inference.Generator{Tuple{Symbol, Expr}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference._collect), Type{Any}, Core.Inference.Generator{Tuple{Symbol, Expr}, Type{Core.Inference.Const}}, Core.Inference.HasLength}) +precompile(Tuple{typeof(Core.Inference.convert), Type{Tuple{Symbol, Expr}}, Tuple{Symbol, Expr}}) +precompile(Tuple{typeof(Core.Inference.copy!), Array{Any, 1}, Core.Inference.Generator{Tuple{Symbol, Expr}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.done), Core.Inference.Generator{Tuple{Symbol, Expr}, Type{Core.Inference.Const}}, Int64}) +precompile(Tuple{typeof(Core.Inference.done), Tuple{Symbol, Expr}, Int64}) +precompile(Tuple{typeof(Core.Inference.getindex), Tuple{Symbol, Expr}, Int64}) +precompile(Tuple{typeof(Core.Inference.isbits), Array{Module, 1}}) +precompile(Tuple{typeof(Core.Inference.iteratorsize), Core.Inference.Generator{Tuple{Symbol, Expr}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.iteratorsize), Type{Core.Inference.Generator{Tuple{Symbol, Expr}, Type{Core.Inference.Const}}}}) +precompile(Tuple{typeof(Core.Inference.iteratorsize), Type{Tuple{Symbol, Expr}}}) +precompile(Tuple{typeof(Core.Inference.length), Core.Inference.Generator{Tuple{Symbol, Expr}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.length), Tuple{Symbol, Expr}}) +precompile(Tuple{typeof(Core.Inference.next), Core.Inference.Generator{Tuple{Symbol, Expr}, Type{Core.Inference.Const}}, Int64}) +precompile(Tuple{typeof(Core.Inference.next), Tuple{Symbol, Expr}, Int64}) +precompile(Tuple{typeof(Core.Inference.start), Core.Inference.Generator{Tuple{Symbol, Expr}, Type{Core.Inference.Const}}}) +precompile(Tuple{typeof(Core.Inference.start), Tuple{Expr, Int64}}) +precompile(Tuple{typeof(Core.Inference.start), Tuple{Symbol, Expr}}) +precompile(Tuple{Type{Union{}}, Base.Distributed.RRID}) From b5dfcc7fb095f9ae843777af02771c7723dfb775 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Thu, 6 Apr 2017 16:43:28 -0500 Subject: [PATCH 0369/1534] Refactor == for SSHCredentials --- base/libgit2/types.jl | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/base/libgit2/types.jl b/base/libgit2/types.jl index 73e0532676c94..be76f294c8a0e 100644 --- a/base/libgit2/types.jl +++ b/base/libgit2/types.jl @@ -702,12 +702,7 @@ function securezero!(cred::SSHCredentials) end function Base.:(==)(a::SSHCredentials, b::SSHCredentials) - return ( - a.user == b.user && - a.pass == b.pass && - a.prvkey == b.prvkey && - a.pubkey == b.pubkey - ) + a.user == b.user && a.pass == b.pass && a.prvkey == b.prvkey && a.pubkey == b.pubkey end "Credentials that support caching" From 7421e11476142c1221176e30065326dd6dd19f91 Mon Sep 17 00:00:00 2001 From: m-j-w Date: Fri, 7 Apr 2017 01:02:26 +0200 Subject: [PATCH 0370/1534] Reformat of README.windows.md (#21285) with some minor edits --- README.windows.md | 549 +++++++++++++++++++++++++++------------------- 1 file changed, 320 insertions(+), 229 deletions(-) diff --git a/README.windows.md b/README.windows.md index 91655d5e18da9..36aab711e0984 100644 --- a/README.windows.md +++ b/README.windows.md @@ -1,198 +1,249 @@ -# General Information for Windows +# Julia on Windows This file describes how to install, or build, and use Julia on Windows. -For more general information about Julia, please see the [main README](https://github.com/JuliaLang/julia/blob/master/README.md) or the [documentation](http://docs.julialang.org/). -# Unicode font support +For more general information about Julia, please see the +[main README](https://github.com/JuliaLang/julia/blob/master/README.md) +or the [documentation](http://docs.julialang.org/). -The built-in Windows fonts have rather poor coverage of the Unicode character space. -The free [`DejaVu Sans Mono`](http://dejavu-fonts.org/) font can be used as a replacement font in the Windows console. -Since Windows 2000, simply downloading the font and installing it is insufficient, since Windows keeps a list of approved fonts in the registry. -Instructions for adding fonts to the terminal are available at: -[http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q247815](http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q247815) +## General Information for Windows -Additionally, rather than sticking with the default command prompt, you may want to use a different terminal emulator program, such as [`Conemu`](https://code.google.com/p/conemu-maximus5/) or [`Mintty`](https://code.google.com/p/mintty/) -(note that running Julia on Mintty needs a copy of `stty.exe` in your `%PATH%` to work properly). -Alternatively, you may prefer the features of a more full-function IDE, such as [`Juno`](http://junolab.org), [`LightTable`](https://github.com/one-more-minute/Jupiter-LT), [`Sublime-IJulia`](https://github.com/quinnj/Sublime-IJulia), or [`IJulia`](https://github.com/JuliaLang/IJulia.jl). +### Unicode font support +The built-in Windows fonts have rather poor coverage of the Unicode character +space. The free [`DejaVu Sans Mono`](http://dejavu-fonts.org/) font can be used +as a replacement font in the Windows console. Since Windows 2000, simply +downloading the font and installing it is insufficient, since Windows keeps a +list of approved fonts in the registry. -# Binary distribution +Instructions for adding fonts to the terminal are available at +[this answer on superuser.com](https://superuser.com/a/5079) -Julia runs on Windows 7 and later. -Both the 32-bit and 64-bit versions are supported. -The 32-bit (i686) binary will run on either a 32-bit and 64-bit operating system. -The 64-bit (x86_64) binary will only run on 64-bit Windows and will otherwise refuse to launch. - -1. [Download](http://julialang.org/downloads) the latest version of Julia. Extract the binary to a reasonable destination folder, e.g. `C:\julia`. - -2. Double-click the `julia` shortcut to launch Julia. - -3. Julia's home directory is the location pointed to by the Windows environment variable `HOME`: this directory is for instance where the startup file `.juliarc.jl` resides. `HOMEDRIVE`\\`HOMEPATH` is used as a fallback if `HOME` is not defined. - - -# Line endings - -Julia uses binary-mode files exclusively. Unlike many other Windows programs, if you write '\n' to a file, you get a '\n' in the file, not some other bit pattern. This matches the behavior exhibited by other operating systems. If you have installed msysGit, it is suggested, but not required, that you configure your system msysGit to use the same convention: - - git config --global core.eol lf - git config --global core.autocrlf input - -or edit `%USERPROFILE%\.gitconfig` and add/edit the lines: - - [core] eol = lf - autocrlf = input - - -# Source distribution - -## Supported build platforms -- Windows 10: supported (32 and 64 bits) -- Windows 8: supported (32 and 64 bits) -- Windows 7: supported (32 and 64 bits) -- Windows Vista: not officially supported (but probably works anyways) -- Windows XP: not supported (but may work anyways, if you can get around the lack of junction points) +Additionally, rather than sticking with the default command prompt, you may want +to use a different terminal emulator program, such as +[Conemu](https://code.google.com/p/conemu-maximus5/) or [Mintty]( +https://code.google.com/p/mintty/) (note that running Julia on Mintty needs a +copy of `stty.exe` in your `%PATH%` to work properly). Alternatively, you may +prefer the features of a more full-function IDE, such as [Juno](http://junolab.org), +[Sublime-IJulia](https://github.com/quinnj/Sublime-IJulia), or +[IJulia](https://github.com/JuliaLang/IJulia.jl). -## Compiling with MinGW/MSYS2 -### MSYS2 provides a robust MSYS experience. +### Line endings -1. Install [Python 2.x](http://www.python.org/downloads/). Do **not** install Python 3. - -2. Install [CMake](http://www.cmake.org/download/). - -3. Install and configure [MSYS2](https://msys2.github.io), a minimal POSIX-like environment for Windows. - - 1. Download and run the latest installer for the [32-bit](http://sourceforge.net/projects/msys2/files/Base/i686/) or [64-bit](http://sourceforge.net/projects/msys2/files/Base/x86_64/) distribution. The installer will have a name like `msys2-i686-yyyymmdd.exe` or `msys2-x86_64-yyyymmdd.exe`. - - 2. Double-click `msys2_shell.bat` in the installed msys directory. Initialize the MSYS2 base system using the `pacman` package manager included in MSYS2: - - ``` - update-core - pacman --needed -Sy bash pacman pacman-mirrors msys2-runtime # if update-core is not available - pacman -Syu #Update package database and full system upgrade +Julia uses binary-mode files exclusively. Unlike many other Windows programs, +if you write `\n` to a file, you get a `\n` in the file, not some other bit +pattern. This matches the behavior exhibited by other operating systems. If +you have installed msysGit, it is suggested, but not required, that you +configure your system msysGit to use the same convention: +```sh +git config --global core.eol lf +git config --global core.autocrlf input ``` - - 3. Exit and restart MSYS2, then install packages required to build julia: - - ``` - pacman -S diffutils git m4 make patch tar p7zip msys/openssh ca-certificates +or edit `%USERPROFILE%\.gitconfig` and add/edit the lines: ``` - - 4. Configure your MSYS2 shell so Python is visible on the path: - - ``` - echo "export PATH=/usr/local/bin:/usr/bin:/opt/bin:/C/Python27" >> ~/.bashrc +[core] + eol = lf + autocrlf = input ``` - *N.B.* The `export` clobbers whatever `$PATH` is already defined. This is suggested to avoid path-masking. If you use MSYS2 for purposes other than building Julia, you may prefer to append rather than clobber. - - *N.B.* All of the path separators are unix-style. In MSYS2, `/C/` means the root of your `C:\` drive. Replace `/C/Python27` with the location where you installed Python. - +## Binary distribution - 5. Configuration of MSYS2 is complete. Now `exit` the MSYS2 shell. +Julia runs on Windows 7 and later. +Both the 32-bit and 64-bit versions are supported. +The 32-bit (i686) binary will run on either a 32-bit and 64-bit operating system. +The 64-bit (x86_64) binary will only run on 64-bit Windows and will otherwise refuse to launch. -4. Build Julia and its dependencies from source. - 1. Open a new MSYS2 shell and clone the Julia sources - ``` - git clone https://github.com/JuliaLang/julia.git - cd julia -``` + 1. [Download](http://julialang.org/downloads) the latest version of Julia. + Extract the binary to a reasonable destination folder, e.g. `C:\julia`. - 2. Run the following script to download the correct versions of the MinGW-w64 compilers - ``` - contrib/windows/get_toolchain.sh 32 # for 32 bit Julia - # or - contrib/windows/get_toolchain.sh 64 # for 64 bit Julia -``` - Then follow the printed instructions by running either - ``` - export PATH=$PWD/usr/i686-w64-mingw32/sys-root/mingw/bin:$PATH # for 32 bit Julia - # or - export PATH=$PWD/usr/x86_64-w64-mingw32/sys-root/mingw/bin:$PATH # for 64 bit Julia -``` - to add the downloaded MinGW-w64 compilers to your path (temporarily, only needed during the shell session when you build Julia). + 2. Double-click the `julia` shortcut to launch Julia. - 3. Specify the location where you installed CMake + 3. Julia's home directory is the location pointed to by the Windows environment + variable `%HOME%`: this directory is for instance where the startup file + `.juliarc.jl` resides. `%HOMEDRIVE%\%HOMEPATH%` is used as a fallback if + `%HOME%` is not defined. - ``` - echo 'override CMAKE=/C/path/to/CMake/bin/cmake.exe' > Make.user -``` +## Source distribution - 4. Start the build - ``` - make -j 4 # Adjust the number of cores (4) to match your build environment. -``` +### Supported build platforms -5. Setup Package Development Environment - 1. The `Pkg` module in Base provides many convenient tools for [developing and publishing packages](http://docs.julialang.org/en/latest/manual/packages/). - One of the packages added through pacman above was `openssh`, which will allow secure access to GitHub APIs. - Follow GitHub's [guide](https://help.github.com/articles/generating-ssh-keys) to setting up SSH keys to ensure your local machine can communicate with GitHub effectively. + - Windows 10: supported (32 and 64 bits) + - Windows 8: supported (32 and 64 bits) + - Windows 7: supported (32 and 64 bits) - 2. In case of the issues with building packages (i.e. ICU fails to build with the following error message ```error compiling xp_parse: error compiling xp_make_parser: could not load module libexpat-1: %```) run ```make win-extras``` and then copy everything from the ```dist-extras``` folder into ```usr/bin```. -## Cygwin-to-MinGW cross compiling +### Compiling with MinGW/MSYS2 -Julia can be also compiled from source in [Cygwin](http://www.cygwin.com), using versions of the MinGW-w64 compilers available through Cygwin's package manager. +*MSYS2 provides a robust MSYS experience.* -1. Download and run Cygwin setup for [32 bit](http://cygwin.com/setup-x86.exe) or [64 bit](http://cygwin.com/setup-x86_64.exe). Note that you can compile either 32 or 64 bit Julia from either 32 or 64 bit Cygwin. 64 bit Cygwin has a slightly smaller but often more up-to-date selection of packages. + 1. Install [Python 2.x](http://www.python.org/downloads/). + Do **not** install Python 3. -2. Select installation location and download mirror. + 2. Install [CMake](http://www.cmake.org/download/). -3. At the "Select Packages" step, select the following: - 1. `git` (under `Devel` category) - 2. `make` (under `Devel` category) - 3. `curl` (under `Net` category) - 4. `patch` (under `Devel` category) - 5. `python` (under `Interpreters` or `Python` category) - 6. `gcc-g++` (under `Devel` category) - 7. `m4` (under `Interpreters` category) - 8. `cmake` (under `Devel` category) - 9. `p7zip` (under `Archive` category) - 10. `mingw64-i686-gcc-g++` and `mingw64-i686-gcc-fortran` (for 32 bit Julia, under `Devel` category) - 11. `mingw64-x86_64-gcc-g++` and `mingw64-x86_64-gcc-fortran` (for 64 bit Julia, under `Devel` category) + 3. Install and configure [MSYS2](https://msys2.github.io), a minimal POSIX-like + environment for Windows. -4. At the "Resolving Dependencies" step, be sure to leave "Select required packages (RECOMMENDED)" enabled. + 1. Download and run the latest installer for the [32-bit]( + http://sourceforge.net/projects/msys2/files/Base/i686/) or [64-bit]( + http://sourceforge.net/projects/msys2/files/Base/x86_64/) distribution. + The installer will have a name like `msys2-i686-yyyymmdd.exe` or + `msys2-x86_64-yyyymmdd.exe`. -5. Allow Cygwin installation to finish, then start a "Cygwin Terminal" (or "Cygwin64 Terminal") from the installed shortcut. + 2. Double-click `msys2_shell.bat` in the installed msys directory. + Initialize the MSYS2 base system using the `pacman` package manager + included in MSYS2: + ```sh + update-core + # or, if update-core is not available + pacman --needed -Sy bash pacman pacman-mirrors msys2-runtime + # update package database and full system upgrade + pacman -Syyuu + ``` -6. Build Julia and its dependencies from source. - 1. Get the Julia sources - ``` - git clone --recursive https://github.com/JuliaLang/julia.git - cd julia -``` - *Tips:* - - If you get an `error: cannot fork() for fetch-pack: Resource temporarily unavailable` from git, add `alias git="env PATH=/usr/bin git"` to `~/.bashrc` and restart Cygwin. + 3. Exit and restart MSYS2, then install packages required to build julia: + ```sh + pacman -S diffutils git m4 make patch tar p7zip msys/openssh ca-certificates + ``` - 2. Set the `XC_HOST` variable in `Make.user` to indicate MinGW-w64 cross compilation + 4. Configure your MSYS2 shell so Python is visible on the path: + ```sh + echo "export PATH=/usr/local/bin:/usr/bin:/opt/bin:/C/Python27" >> ~/.bashrc + ``` - For 32 bit Julia - ``` - echo 'XC_HOST = i686-w64-mingw32' > Make.user -``` - For 64 bit Julia - ``` - echo 'XC_HOST = x86_64-w64-mingw32' > Make.user -``` + Note, the `export` clobbers whatever `$PATH` is already defined. This is + suggested to avoid path-masking. If you use MSYS2 for purposes other than + building Julia, you may prefer to append rather than clobber. - 3. Start the build - ``` - make -j 4 # Adjust the number of cores (4) to match your build environment. -``` + Note, all of the path separators are unix-style. In MSYS2, `/C/` means + the root of your `C:\` drive. Replace `/C/Python27` with the location + where you installed Python. -7. Run Julia using the Julia executables directly - ``` + 5. Configuration of MSYS2 is complete. Now `exit` the MSYS2 shell. + + 4. Build Julia and its dependencies from source. + + 1. Open a new MSYS2 shell and clone the Julia sources + ```sh + git clone https://github.com/JuliaLang/julia.git + cd julia + ``` + + 2. Run the following script to download the correct versions of the MinGW-w64 compilers + ```sh + contrib/windows/get_toolchain.sh 32 # for 32 bit Julia + # or + contrib/windows/get_toolchain.sh 64 # for 64 bit Julia + ``` + + Then follow the printed instructions by running either + ```sh + export PATH=$PWD/usr/i686-w64-mingw32/sys-root/mingw/bin:$PATH # for 32 bit Julia + # or + export PATH=$PWD/usr/x86_64-w64-mingw32/sys-root/mingw/bin:$PATH # for 64 bit Julia + ``` + to add the downloaded MinGW-w64 compilers to your path (temporarily, only + needed during the shell session when you build Julia). + + 3. Specify the location where you installed CMake + ```sh + echo 'override CMAKE=/C/path/to/CMake/bin/cmake.exe' > Make.user + ``` + + 4. Start the build + ```sh + make -j 4 # Adjust the number of cores (4) to match your build environment. + ``` + + 5. Setup Package Development Environment + + 1. The `Pkg` module in Base provides many convenient tools for [developing + and publishing packages](http://docs.julialang.org/en/latest/manual/packages/). + One of the packages added through pacman above was `openssh`, which will + allow secure access to GitHub APIs. Follow GitHub's [guide]( + https://help.github.com/articles/generating-ssh-keys) to setting up SSH + keys to ensure your local machine can communicate with GitHub effectively. + + 2. In case of the issues with building packages (i.e. ICU fails to build + with the following error message `error compiling xp_parse: error + compiling xp_make_parser: could not load module libexpat-1: %`) run + `make win-extras` and then copy everything from the `dist-extras` folder + into `usr/bin`. + + +### Cygwin-to-MinGW cross-compiling + +Julia can be also compiled from source in [Cygwin](http://www.cygwin.com), using +versions of the MinGW-w64 compilers available through Cygwin's package manager. + + 1. Download and run Cygwin setup for [32 bit](http://cygwin.com/setup-x86.exe) + or [64 bit](http://cygwin.com/setup-x86_64.exe). Note, that you can compile + either 32 or 64 bit Julia from either 32 or 64 bit Cygwin. 64 bit Cygwin + has a slightly smaller but often more up-to-date selection of packages. + + 2. Select installation location and download mirror. + + 3. At the '*Select Packages'* step, select the following: + + 1. From the *Devel* category: `cmake`, `gcc-g++`, `git`, `make`, `patch` + 2. From the *Net* category: `curl` + 3. From *Interpreters* (or *Python*) category: `m4`, `python` + 4. From the *Archive* category: `p7zip` + 5. For 32 bit Julia, and also from the *Devel* category: + `mingw64-i686-gcc-g++` and `mingw64-i686-gcc-fortran` + 6. For 64 bit Julia, and also from the *Devel* category: + `mingw64-x86_64-gcc-g++` and `mingw64-x86_64-gcc-fortran` + + 4. At the *'Resolving Dependencies'* step, be sure to leave *'Select required + packages (RECOMMENDED)'* enabled. + + 5. Allow Cygwin installation to finish, then start from the installed shortcut + a *'Cygwin Terminal'*, or *'Cygwin64 Terminal'*, respectively. + + 6. Build Julia and its dependencies from source: + + 1. Get the Julia sources + ```sh + git clone --recursive https://github.com/JuliaLang/julia.git + cd julia + ``` + Tip: If you get an `error: cannot fork() for fetch-pack: Resource + temporarily unavailable` from git, add `alias git="env PATH=/usr/bin git"` + to `~/.bashrc` and restart Cygwin. + + 2. Set the `XC_HOST` variable in `Make.user` to indicate MinGW-w64 cross + compilation + ```sh + echo 'XC_HOST = i686-w64-mingw32' > Make.user # for 32 bit Julia + # or + echo 'XC_HOST = x86_64-w64-mingw32' > Make.user #for 64 bit Julia + ``` + + 3. Start the build + ```sh + make -j 4 # Adjust the number of cores (4) to match your build environment. + ``` + + 7. Run Julia using the Julia executables directly + ```sh usr/bin/julia.exe usr/bin/julia-debug.exe -``` + ``` -## Cross-compiling from Unix + +### Cross-compiling from Unix If you prefer to cross-compile, the following steps should get you started. -For maximum compatibility with packages that use [WinRPM.jl](https://github.com/JuliaLang/WinRPM.jl) for binary dependencies on Windows, it is recommended that you use OpenSUSE 13.2 for cross-compiling a Windows build of Julia. If you use a different Linux distribution or OS X, install [Vagrant](http://www.vagrantup.com/downloads) and use the following `Vagrantfile`: +For maximum compatibility with packages that use [WinRPM.jl]( +https://github.com/JuliaLang/WinRPM.jl) for binary dependencies on Windows, it +is recommended that you use OpenSUSE 13.2 for cross-compiling a Windows build +of Julia. If you use a different Linux distribution or OS X, install +[Vagrant](http://www.vagrantup.com/downloads) and use the following `Vagrantfile`: + ``` # Vagrantfile for MinGW-w64 cross-compilation of Julia @@ -227,77 +278,100 @@ Vagrant.configure("2") do |config| end ``` -### Cross-building Julia without Vagrant - -If you don't care that the build is potentially incompatible with the WinRPM ecosystem (or happen to be on opensuse), use the following steps to cross-compile julia: -First, you will need to ensure your system has the required dependencies. We need wine (>=1.7.5), -a system compiler, and some downloaders. - -On Ubuntu (on other linux systems, the dependency names are likely to be similar): - - apt-add-repository ppa:ubuntu-wine/ppa - apt-get update - apt-get install wine1.7 subversion cvs gcc wget p7zip-full - -On Mac: Install XCode, XCode command line tools, X11 (now [XQuartz](http://xquartz.macosforge.org/)), -and [MacPorts](http://www.macports.org/install.php) or [Homebrew](http://mxcl.github.io/homebrew/). -Then run ```port install wine wget``` or ```brew install wine wget```, as appropriate. - -On Both: - -Unfortunately, the version of gcc installed by Ubuntu targets pthreads. -On Mac, the situation is similar: the version in MacPorts is very old and Homebrew does not have it. -So first we need to get a cross-compile version of gcc. -Most binary packages appear to not include gfortran, so we will need to compile it from source. -This is typically quite a bit of work, so we will use [this script](http://sourceforge.net/projects/mingw-w64-dgn/) o make it easy. - -1. `svn checkout svn://svn.code.sf.net/p/mingw-w64-dgn/code/trunk mingw-w64-dgn` -2. `cd mingw-w64-dgn` -3. edit `rebuild_cross.sh` and make the following two changes: - a. uncomment `export MAKE_OPT="-j 2"`, if appropriate for your machine - b. add `fortran` to the end of `--enable-languages=c,c++,objc,obj-c++` -5. `bash update_source.sh` -4. `bash rebuild_cross.sh` -5. `mv cross ~/cross-w64` -6. `export PATH=$HOME/cross-w64/bin:$PATH` # NOTE: it is important that you remember to always do this before using make in the following steps! You can put this line in your .profile to make it easy. +### Cross-building Julia without Vagrant -Then we can essentially just repeat these steps for the 32-bit compiler, reusing some of the work: +If you don't care that the build is potentially incompatible with the WinRPM +ecosystem (or happen to be on opensuse), use the following steps to cross- +compile julia: -7. `cd ..` -8. `cp -a mingw-w64-dgn mingw-w32-dgn` -9. `cd mingw-w32-dgn` -10. `rm -r cross build` -11. `bash rebuild_cross.sh 32r` -12. `mv cross ~/cross-w32` -13. `export PATH=$HOME/cross-w32/bin:$PATH` # NOTE: it is important that you remember to always do this before using make in the following steps! You can put this line in your .profile to make it easy. +First, you will need to ensure your system has the required dependencies. We +need wine (>=1.7.5), a system compiler, and some downloaders. -Note: for systems that support rpm-based package managers, the necessary dependencies can be downloaded from the OpenSUSE build service (see the Vagrant script above). +**On Ubuntu** (on other linux systems, the dependency names are likely to be similar): +```sh +apt-add-repository ppa:ubuntu-wine/ppa +apt-get update +apt-get install wine1.7 subversion cvs gcc wget p7zip-full +``` -@vtjnash occassionally upload his builds, so you can also download those to save build time: -- [x86_64-w64-mingw64 gcc-5.2.0 MacOS-10.10 (105 MB)](https://onedrive.live.com/redir?resid=BCAF288A35FC4406!1601&authkey=!ANpFOoCqFGYTcHM&ithint=file%2cgz) -- [i686-w64-mingw64 gcc-5.2.0 MacOS-10.10 (89 MB)](https://onedrive.live.com/redir?resid=BCAF288A35FC4406!1607&authkey=!AFrL8G5G70iYhUU&ithint=file%2cgz) -- [*-w64-mingw64 gcc-4.9.2 Ubuntu-15.04 (168 MB)](https://onedrive.live.com/redir?resid=BCAF288A35FC4406!1602&authkey=!ABhstrqDG-4zdLo&ithint=file%2cgz) +**On Mac**: Install XCode, XCode command line tools, X11 (now [XQuartz]( +http://xquartz.macosforge.org/)), and [MacPorts](http://www.macports.org/install.php) +or [Homebrew](http://mxcl.github.io/homebrew/). Then run `port install wine wget`, +or `brew install wine wget`, as appropriate. + +**On Both:** +Unfortunately, the version of gcc installed by Ubuntu targets pthreads. On Mac, +the situation is similar: the version in MacPorts is very old and Homebrew does +not have it. So first we need to get a cross-compile version of gcc. Most +binary packages appear to not include gfortran, so we will need to compile it +from source. This is typically quite a bit of work, so we will use [this script]( +http://sourceforge.net/projects/mingw-w64-dgn/) to make it easy. + + 1. `svn checkout svn://svn.code.sf.net/p/mingw-w64-dgn/code/trunk mingw-w64-dgn` + 2. `cd mingw-w64-dgn` + 3. edit `rebuild_cross.sh` and make the following two changes: + 1. uncomment `export MAKE_OPT="-j 2"`, if appropriate for your machine + 2. add `fortran` to the end of `--enable-languages=c,c++,objc,obj-c++` + 4. `bash update_source.sh` + 5. `bash rebuild_cross.sh` + 6. `mv cross ~/cross-w64` + 7. `export PATH=$HOME/cross-w64/bin:$PATH` + + Note, that it is important that you remember to always `export PATH=...` + before using `make` in the following steps! You can put this line in your + `~/.profile` to make it easy. + +Then we can essentially just repeat these steps for the 32-bit compiler, reusing +some of the work: + + 8. `cd ..` + 9. `cp -a mingw-w64-dgn mingw-w32-dgn` + 10. `cd mingw-w32-dgn` + 11. `rm -r cross build` + 12. `bash rebuild_cross.sh 32r` + 13. `mv cross ~/cross-w32` + 14. `export PATH=$HOME/cross-w32/bin:$PATH` + + Note, that it is important that you remember to always `export PATH=...` + before using `make` in the following steps! You can put this line in your + `~/.profile` to make it easy. + +Note: for systems that support rpm-based package managers, the necessary +dependencies can be downloaded from the OpenSUSE build service (see the Vagrant +script above). + +@vtjnash occassionally upload his builds, so you can also download those to +save build time: + + - [x86_64-w64-mingw64 gcc-5.2.0 MacOS-10.10 (105 MB)](https://onedrive.live.com/redir?resid=BCAF288A35FC4406!1601&authkey=!ANpFOoCqFGYTcHM&ithint=file%2cgz) + - [i686-w64-mingw64 gcc-5.2.0 MacOS-10.10 (89 MB)](https://onedrive.live.com/redir?resid=BCAF288A35FC4406!1607&authkey=!AFrL8G5G70iYhUU&ithint=file%2cgz) + - [*-w64-mingw64 gcc-4.9.2 Ubuntu-15.04 (168 MB)](https://onedrive.live.com/redir?resid=BCAF288A35FC4406!1602&authkey=!ABhstrqDG-4zdLo&ithint=file%2cgz) Then run the build: -1. `git clone https://github.com/JuliaLang/julia.git julia-win32` -2. `echo override XC_HOST = i686-w64-mingw32 >> Make.user` -3. `make` -4. `make win-extras` (Necessary before running `make binary-dist`) -5. `make binary-dist` -6. move the julia-*.exe installer to the target machine + 1. `git clone https://github.com/JuliaLang/julia.git julia-win32` + 2. `echo override XC_HOST = i686-w64-mingw32 >> Make.user` + 3. `make` + 4. `make win-extras` (Necessary before running `make binary-dist`) + 5. `make binary-dist` + 6. move the `julia-*.exe` installer to the target machine + +If you are building for 64-bit windows, the steps are essentially the same. +Just replace `i686` in `XC_HOST` with `x86_64`. (note: on Mac, wine only runs +in 32-bit mode). -If you are building for 64-bit windows, the steps are essentially the same. Just replace i686 in XC_HOST with x86_64. (note: on Mac, wine only runs in 32-bit mode). ## Debugging a cross-compiled build under wine -The most effective way to debug a cross-compiled version of julia on the cross-compilation -host is to install a windows version of gdb and run it under wine as usual. The pre-built packages -available [as part of the MSYS2 project](https://sourceforge.net/projects/msys2/files/REPOS/MINGW/) -are known to work. Apart from the GDB package you may also need the python and termcap packages. -Finally, GDB's prompt may not work when launch from the command line. This can be worked around -by prepending `wineconsole` to the regular GDB invocation. +The most effective way to debug a cross-compiled version of julia on the cross- +compilation host is to install a windows version of gdb and run it under wine as +usual. The pre-built packages available [as part of the MSYS2 project]( +https://sourceforge.net/projects/msys2/files/REPOS/MINGW/) are known to work. +Apart from the GDB package you may also need the python and termcap packages. +Finally, GDB's prompt may not work when launch from the command line. This can +be worked around by prepending `wineconsole` to the regular GDB invocation. + ## Using a Windows VM @@ -305,7 +379,9 @@ by prepending `wineconsole` to the regular GDB invocation. guest VM via the `Vagrantfile` in [contrib/windows](contrib/windows/Vagrantfile), just run `vagrant up` from that folder. To build with Cygwin instead of MSYS2, replace `config.vm.provision :shell, privileged: false, :inline => $script_msys2` -(near the end of the file) with `config.vm.provision :shell, privileged: false, :inline => $script_cygwin`. +(near the end of the file) with `config.vm.provision :shell, privileged: false, +:inline => $script_cygwin`. + ## After compiling @@ -315,33 +391,48 @@ If you need these components, the easiest way to get them is to build the instal yourself using ```make win-extras``` followed by ```make binary-dist```, and then running the resulting installer. + ## Windows Build Debugging + ### GDB hangs with cygwin mintty -- Run gdb under the windows console (cmd) instead. gdb [may not function properly](https://www.cygwin.com/ml/cygwin/2009-02/msg00531.html) under mintty with non-cygwin applications. You can use `cmd /c start` to start the windows console from mintty if necessary. +- Run gdb under the windows console (cmd) instead. gdb [may not function properly]( + https://www.cygwin.com/ml/cygwin/2009-02/msg00531.html) under mintty with non- + cygwin applications. You can use `cmd /c start` to start the windows console + from mintty if necessary. ### GDB not attaching to the right process -- Use the PID from the windows task manager or `WINPID` from the `ps` command instead of the PID from unix style command line tools (e.g. `pgrep`). You may need to add the PID column if it is not shown by default in the windows task manager. + - Use the PID from the windows task manager or `WINPID` from the `ps` command + instead of the PID from unix style command line tools (e.g. `pgrep`). You + may need to add the PID column if it is not shown by default in the windows + task manager. ### GDB not showing the right backtrace -- When attaching to the julia process, GDB may not be attaching to the right thread. Use `info threads` command to show all the threads and `thread ` to switch threads. -- Be sure to use a 32 bit version of GDB to debug a 32 bit build of Julia, or a 64 bit version of GDB to debug a 64 bit build of Julia. + - When attaching to the julia process, GDB may not be attaching to the right + thread. Use `info threads` command to show all the threads and + `thread ` to switch threads. + - Be sure to use a 32 bit version of GDB to debug a 32 bit build of Julia, or + a 64 bit version of GDB to debug a 64 bit build of Julia. ### Build process is slow/eats memory/hangs my computer -- Disable the Windows [Superfetch](https://en.wikipedia.org/wiki/Windows_Vista_I/O_technologies#SuperFetch) and - [Program Compatibility Assistant](http://blogs.msdn.com/b/cjacks/archive/2011/11/22/managing-the-windows-7-program-compatibility-assistant-pca.aspx) services, as they are known to have - [spurious interactions]((https://cygwin.com/ml/cygwin/2011-12/msg00058.html)) with MinGW/Cygwin. - - As mentioned in the link above: excessive memory use by `svchost` specifically may be investigated in the Task - Manager by clicking on the high-memory `svchost.exe` process and selecting `Go to Services`. Disable child services - one-by-one until a culprit is found. - -- Beware of [BLODA](https://cygwin.com/faq/faq.html#faq.using.bloda) - - The [vmmap](http://technet.microsoft.com/en-us/sysinternals/dd535533.aspx) tool is indispensable for identifying - such software conflicts. Use vmmap to inspect the list of loaded DLLs for bash, mintty, or another persistent - process used to drive the build. Essentially *any* DLL outside of the Windows System directory is potential BLODA. + - Disable the Windows [Superfetch](https://en.wikipedia.org/wiki/Windows_Vista_I/O_technologies#SuperFetch) + and [Program Compatibility Assistant]( + http://blogs.msdn.com/b/cjacks/archive/2011/11/22/managing-the-windows-7-program-compatibility-assistant-pca.aspx) + services, as they are known to have [spurious interactions]( + https://cygwin.com/ml/cygwin/2011-12/msg00058.html) with MinGW/Cygwin. + + As mentioned in the link above: excessive memory use by `svchost` specifically + may be investigated in the Task Manager by clicking on the high-memory + `svchost.exe` process and selecting `Go to Services`. Disable child services + one-by-one until a culprit is found. + + - Beware of [BLODA](https://cygwin.com/faq/faq.html#faq.using.bloda). + The [vmmap](http://technet.microsoft.com/en-us/sysinternals/dd535533.aspx) + tool is indispensable for identifying such software conflicts. Use vmmap to + inspect the list of loaded DLLs for bash, mintty, or another persistent + process used to drive the build. Essentially *any* DLL outside of the Windows + System directory is potential BLODA. From afeecd0c23991f16de44f56b8632730e8497fab8 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Thu, 6 Apr 2017 19:33:28 -0400 Subject: [PATCH 0371/1534] Make TBAA for non leaftypes more precise --- src/codegen.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index a0f0a6e168fc1..d40a42dd4a008 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -434,6 +434,17 @@ static bool isbits_spec(jl_value_t *jt, bool allow_singleton = true) (allow_singleton || (jl_datatype_size(jt) > 0) || (jl_datatype_nfields(jt) > 0)); } +static MDNode *best_tbaa(jl_value_t *jt) { + jt = jl_unwrap_unionall(jt); + if (!jl_is_datatype(jt)) + return tbaa_value; + if (jl_is_abstracttype(jt)) + return tbaa_value; + // If we're here, we know all subtypes are (im)mutable, even if we + // don't know what the exact type is + return jl_is_mutable(jt) ? tbaa_mutab : tbaa_immut; +} + // metadata tracking for a llvm Value* during codegen struct jl_cgval_t { Value *V; // may be of type T* or T, or set to NULL if ghost (or if the value has not been initialized yet, for a variable definition) @@ -464,9 +475,7 @@ struct jl_cgval_t { isboxed(isboxed), isghost(false), isimmutable(isboxed && jl_is_immutable_datatype(typ)), - tbaa(isboxed ? (jl_is_leaf_type(typ) ? - (jl_is_mutable(typ) ? tbaa_mutab : tbaa_immut) : - tbaa_value) : nullptr) + tbaa(isboxed ? best_tbaa(typ) : nullptr) { assert(!(isboxed && TIndex != NULL)); assert(TIndex == NULL || TIndex->getType() == T_int8); From c562caa6f962ce7e49ef2bc361dad1c5e5ee4ffb Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 6 Apr 2017 20:50:15 -0400 Subject: [PATCH 0372/1534] support more kinds of constants in `_apply` inlining --- base/inference.jl | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 72482f5f316f1..e45bd9c098ed5 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -4491,11 +4491,14 @@ function inlining_pass(e::Expr, sv::InferenceState, stmts, ins) newargs = Vector{Any}(na-2) for i = 3:na aarg = e.args[i] - t = widenconst(exprtype(aarg, sv.src, sv.mod)) + argt = exprtype(aarg, sv.src, sv.mod) + t = widenconst(argt) if isa(aarg,Expr) && (is_known_call(aarg, tuple, sv.src, sv.mod) || is_known_call(aarg, svec, sv.src, sv.mod)) # apply(f,tuple(x,y,...)) => f(x,y,...) newargs[i-2] = aarg.args[2:end] - elseif isa(aarg, Tuple) || (isa(aarg, QuoteNode) && isa(aarg.value, Tuple)) + elseif isa(argt,Const) && (isa(argt.val, Tuple) || isa(argt.val, SimpleVector)) + newargs[i-2] = Any[ QuoteNode(x) for x in argt.val ] + elseif isa(aarg, Tuple) || (isa(aarg, QuoteNode) && (isa(aarg.value, Tuple) || isa(aarg.value, SimpleVector))) if isa(aarg, QuoteNode) aarg = aarg.value end From 086361ad4a586809aa88f03001f86c68ad80809b Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 6 Apr 2017 20:50:45 -0400 Subject: [PATCH 0373/1534] allow inferring `T.parameters` when T is a known leaf type --- base/inference.jl | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index e45bd9c098ed5..e79a4e804182b 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -745,19 +745,21 @@ function getfield_tfunc(s00::ANY, name) s00 = s00.ub end s = unwrap_unionall(s00) - if isType(s) - p1 = s.parameters[1] - if !isleaftype(p1) - return Any - end - s = DataType # typeof(p1) - elseif isa(s, Union) + if isa(s, Union) return tmerge(rewrap(getfield_tfunc(s.a, name),s00), rewrap(getfield_tfunc(s.b, name),s00)) elseif isa(s, Conditional) return Bottom # Bool has no fields - elseif isa(s, Const) - sv = s.val + elseif isa(s, Const) || isType(s) + if !isa(s, Const) + p1 = s.parameters[1] + if !isleaftype(p1) + return Any + end + sv = p1 + else + sv = s.val + end if isa(name, Const) nv = name.val if isa(sv, UnionAll) From caf8af5b4bfc7b19da411ce8f1bca511131dccf5 Mon Sep 17 00:00:00 2001 From: Mus M Date: Thu, 6 Apr 2017 21:18:11 -0400 Subject: [PATCH 0374/1534] Move unlink export to file where function is defined (#21254) --- base/file.jl | 1 + base/filesystem.jl | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/base/file.jl b/base/file.jl index 30eb9696de249..7a4ccff63e7a5 100644 --- a/base/file.jl +++ b/base/file.jl @@ -24,6 +24,7 @@ export tempdir, tempname, touch, + unlink, walkdir # get and set current directory diff --git a/base/filesystem.jl b/base/filesystem.jl index f66bbfd5a0df5..1f6bc997156ff 100644 --- a/base/filesystem.jl +++ b/base/filesystem.jl @@ -21,7 +21,6 @@ export File, StatStruct, # open, futime, - unlink, write, JL_O_WRONLY, JL_O_RDONLY, From 6a9c3c25de5e3fcdd7a74e028887e4b281a72ffe Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 7 Apr 2017 13:14:53 -0400 Subject: [PATCH 0375/1534] fix #21313, precompile.jl with USE_GPL_LIBS=0 --- base/precompile.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/base/precompile.jl b/base/precompile.jl index 96118ece4c7f2..b9d6f78bd41f9 100644 --- a/base/precompile.jl +++ b/base/precompile.jl @@ -10,7 +10,9 @@ precompile(Tuple{typeof(Base.pointer), Array{UInt8, 1}, UInt64}) precompile(Tuple{typeof(Base.convert), Type{Ptr{Int32}}, Ptr{UInt8}}) +if USE_GPL_LIBS precompile(Tuple{typeof(Base.SparseArrays.CHOLMOD.set_print_level), Array{UInt8, 1}, Int64}) +end precompile(Tuple{Type{Base.Multimedia.TextDisplay}, Base.TTY}) precompile(Tuple{typeof(Base._start)}) precompile(Tuple{typeof(Base.copy!), Array{String, 1}, Int64, Array{Any, 1}, Int64, Int64}) From bfad81797f32962f1b16b007a5d2906203bd6f9b Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Fri, 7 Apr 2017 12:35:31 -0500 Subject: [PATCH 0376/1534] Support `unsafe_trunc(<:Integer, x::Float16)` Fixes #18771 --- base/float.jl | 4 ++++ test/float16.jl | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/base/float.jl b/base/float.jl index 612e9360c08a7..c66a655a2380a 100644 --- a/base/float.jl +++ b/base/float.jl @@ -275,12 +275,14 @@ float{T<:Number}(::Type{T}) = typeof(float(zero(T))) for Ti in (Int8, Int16, Int32, Int64) @eval begin + unsafe_trunc(::Type{$Ti}, x::Float16) = unsafe_trunc($Ti, Float32(x)) unsafe_trunc(::Type{$Ti}, x::Float32) = fptosi($Ti, x) unsafe_trunc(::Type{$Ti}, x::Float64) = fptosi($Ti, x) end end for Ti in (UInt8, UInt16, UInt32, UInt64) @eval begin + unsafe_trunc(::Type{$Ti}, x::Float16) = unsafe_trunc($Ti, Float32(x)) unsafe_trunc(::Type{$Ti}, x::Float32) = fptoui($Ti, x) unsafe_trunc(::Type{$Ti}, x::Float64) = fptoui($Ti, x) end @@ -314,6 +316,8 @@ function unsafe_trunc(::Type{Int128}, x::Float32) copysign(unsafe_trunc(UInt128,x) % Int128, x) end +unsafe_trunc(::Type{UInt128}, x::Float16) = unsafe_trunc(UInt128, Float32(x)) +unsafe_trunc(::Type{Int128}, x::Float16) = unsafe_trunc(Int128, Float32(x)) # matches convert methods # also determines floor, ceil, round diff --git a/test/float16.jl b/test/float16.jl index 10e741336c53c..b07d7b38cab0d 100644 --- a/test/float16.jl +++ b/test/float16.jl @@ -49,6 +49,11 @@ g = Float16(1.) @test floor(Float16(1)) === Float16(1) @test ceil(Float16(0.1)) == ceil(0.1) @test ceil(Float16(0.9)) == ceil(0.9) +@test unsafe_trunc(UInt8, Float16(3)) === 0x03 +@test unsafe_trunc(Int16, Float16(3)) === Int16(3) +@test unsafe_trunc(UInt128, Float16(3)) === UInt128(3) +@test unsafe_trunc(Int128, Float16(3)) === Int128(3) +@test unsafe_trunc(Int16, NaN16) === Int16(0) #18771 @test fma(Float16(0.1),Float16(0.9),Float16(0.5)) ≈ fma(0.1,0.9,0.5) @test muladd(Float16(0.1),Float16(0.9),Float16(0.5)) ≈ muladd(0.1,0.9,0.5) @test convert(Int128,Float16(-1.0)) == Int128(-1) From f3a157031da1b0ecd88a718ea1d616603bc84c08 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 7 Apr 2017 13:40:25 -0400 Subject: [PATCH 0377/1534] fix #21314, `close` on a SubArray-based IOBuffer affected `base64decode` on SubString --- base/iobuffer.jl | 4 +--- test/base64.jl | 3 +++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/base/iobuffer.jl b/base/iobuffer.jl index 0b2536ad57cda..d8b584c56a0f9 100644 --- a/base/iobuffer.jl +++ b/base/iobuffer.jl @@ -4,7 +4,7 @@ # Stateful string mutable struct AbstractIOBuffer{T<:AbstractVector{UInt8}} <: IO - data::T # T should support: getindex, setindex!, length, copy!, resize!, and T() + data::T # T should support: getindex, setindex!, length, copy!, and resize! readable::Bool writable::Bool seekable::Bool # if not seekable, implementation is free to destroy (compact) past read data @@ -251,8 +251,6 @@ eof(io::AbstractIOBuffer) = (io.ptr-1 == io.size) io.mark = -1 if io.writable resize!(io.data, 0) - else - io.data = T() end nothing end diff --git a/test/base64.jl b/test/base64.jl index 1055cc1c302f9..952e4e056ecd5 100644 --- a/test/base64.jl +++ b/test/base64.jl @@ -41,3 +41,6 @@ ipipe = Base64DecodePipe(IOBuffer(string(encodedMaxLine76[1:end-2],"=="))) # Test incorrect format ipipe = Base64DecodePipe(IOBuffer(encodedMaxLine76[1:end-3])) @test_throws ArgumentError readstring(ipipe) + +# issue #21314 +@test base64decode(chomp("test")) == base64decode("test") From a27ce01e5ef1ae2aefcfa2ce362210b40c07512d Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 7 Apr 2017 16:08:48 -0400 Subject: [PATCH 0378/1534] fix #21311, inlining `_apply` reordering evaluations --- base/inference.jl | 19 +++++++++++++++++-- test/inline.jl | 18 ++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index e79a4e804182b..039496b3f89ca 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -4491,6 +4491,8 @@ function inlining_pass(e::Expr, sv::InferenceState, stmts, ins) if f === _apply na = length(e.args) newargs = Vector{Any}(na-2) + newstmts = Any[] + effect_free_upto = 0 for i = 3:na aarg = e.args[i] argt = exprtype(aarg, sv.src, sv.mod) @@ -4507,14 +4509,25 @@ function inlining_pass(e::Expr, sv::InferenceState, stmts, ins) newargs[i-2] = Any[ QuoteNode(x) for x in aarg ] elseif isa(t, DataType) && t.name === Tuple.name && !isvatuple(t) && length(t.parameters) <= sv.params.MAX_TUPLE_SPLAT + for k = (effect_free_upto+1):(i-3) + as = newargs[k] + for kk = 1:length(as) + ak = as[kk] + if !effect_free(ak, sv.src, sv.mod, true) + tmpv = newvar!(sv, widenconst(exprtype(ak, sv.src, sv.mod))) + push!(newstmts, Expr(:(=), tmpv, ak)) + as[kk] = tmpv + end + end + end + effect_free_upto = i-3 if effect_free(aarg, sv.src, sv.mod, true) # apply(f,t::(x,y)) => f(t[1],t[2]) tmpv = aarg else # apply(f,t::(x,y)) => tmp=t; f(tmp[1],tmp[2]) tmpv = newvar!(sv, t) - insert!(stmts, ins, Expr(:(=), tmpv, aarg)) - ins += 1 + push!(newstmts, Expr(:(=), tmpv, aarg)) end tp = t.parameters newargs[i-2] = Any[ mk_getfield(tmpv,j,tp[j]) for j=1:length(tp) ] @@ -4523,6 +4536,8 @@ function inlining_pass(e::Expr, sv::InferenceState, stmts, ins) return e end end + splice!(stmts, ins:ins-1, newstmts) + ins += length(newstmts) e.args = [Any[e.args[2]]; newargs...] # now try to inline the simplified call diff --git a/test/inline.jl b/test/inline.jl index a213f26e50ab0..3f21750fd2f63 100644 --- a/test/inline.jl +++ b/test/inline.jl @@ -93,3 +93,21 @@ end let (src, _) = code_typed(g21074, ())[1] @test src.code[1] == Expr(:return, 1) end + +# issue #21311 +counter21311 = Ref(0) +@noinline function update21311!(x) + counter21311[] += 1 + x[] = counter21311[] + return x +end +@noinline map21311(t::Tuple{Any}) = (update21311!(t[1]),) +@inline map21311(t::Tuple) = (update21311!(t[1]), map21311(Base.tail(t))...) +function read21311() + xs = Ref(1), Ref(1) + map21311(xs) + return xs[1] +end +let a = read21311() + @test a[] == 1 +end From d9771af87ca722f87e2298b418fe705239b320b0 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Fri, 7 Apr 2017 19:08:20 -0700 Subject: [PATCH 0379/1534] Add a doctest for isposdef! (#21320) --- base/linalg/dense.jl | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/base/linalg/dense.jl b/base/linalg/dense.jl index aba54fe857f34..e2516fee049da 100644 --- a/base/linalg/dense.jl +++ b/base/linalg/dense.jl @@ -36,6 +36,20 @@ isposdef!(A::StridedMatrix{<:BlasFloat}, UL::Symbol) = LAPACK.potrf!(char_uplo(U isposdef!(A) -> Bool Test whether a matrix is positive definite, overwriting `A` in the process. + +# Example + +```jldoctest +julia> A = [1. 2.; 2. 50.]; + +julia> isposdef!(A) +true + +julia> A +2×2 Array{Float64,2}: + 1.0 2.0 + 2.0 6.78233 +``` """ isposdef!(A::StridedMatrix) = ishermitian(A) && isposdef!(A, :U) From ae6cdd1daa7b2d5daf14fbd6c1010d152ebad10e Mon Sep 17 00:00:00 2001 From: Pablo Zubieta Date: Fri, 7 Apr 2017 15:19:53 -0500 Subject: [PATCH 0380/1534] Fix #21291, type-stabilize broadcast over tuples and scalars --- base/broadcast.jl | 25 +++++++++++-------------- test/broadcast.jl | 6 ++++++ 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/base/broadcast.jl b/base/broadcast.jl index 7dc7800da7688..1d429ba4ffa99 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -311,20 +311,17 @@ end end end @inline broadcast_c(f, ::Type{Any}, a...) = f(a...) -broadcast_c(f, ::Type{Tuple}, As...) = - ntuple(k -> f(_tuplebroadcast_getargs(As, k)...), _tuplebroadcast_reslength(As)) -broadcast_c{T}(f, ::Type{Tuple}, ::Type{T}, As...) = - ntuple(k -> f(T, _tuplebroadcast_getargs(As, k)...), _tuplebroadcast_reslength(As)) -@inline _tuplebroadcast_getargs(::Tuple{}, k) = () -@inline _tuplebroadcast_getargs(As, k) = - (_broadcast_getindex(first(As), k), _tuplebroadcast_getargs(tail(As), k)...) -@noinline _tuplebroadcast_reslength(As) = - _tuplebroadcast_maxlength(_tuplebroadcast_length(first(As)), tail(As)) -@inline _tuplebroadcast_maxlength(l, As) = - _tuplebroadcast_maxlength(max(l, _tuplebroadcast_length(first(As))), tail(As)) -@inline _tuplebroadcast_maxlength(l, ::Tuple{}) = l -@inline _tuplebroadcast_length(t::Tuple) = length(t) -@inline _tuplebroadcast_length(s) = 1 +@inline broadcast_c(f, ::Type{Tuple}, A, Bs...) = + tuplebroadcast(f, first_tuple(A, Bs...), A, Bs...) +@inline tuplebroadcast{N}(f, ::NTuple{N,Any}, As...) = + ntuple(k -> f(tuplebroadcast_getargs(As, k)...), Val{N}) +@inline tuplebroadcast{N,T}(f, ::NTuple{N,Any}, ::Type{T}, As...) = + ntuple(k -> f(T, tuplebroadcast_getargs(As, k)...), Val{N}) +first_tuple(A::Tuple, Bs...) = A +@inline first_tuple(A, Bs...) = first_tuple(Bs...) +tuplebroadcast_getargs(::Tuple{}, k) = () +@inline tuplebroadcast_getargs(As, k) = + (_broadcast_getindex(first(As), k), tuplebroadcast_getargs(tail(As), k)...) """ broadcast(f, As...) diff --git a/test/broadcast.jl b/test/broadcast.jl index 324fa60d8666b..1648eb52eabfa 100644 --- a/test/broadcast.jl +++ b/test/broadcast.jl @@ -494,3 +494,9 @@ end A[1:3,1:3] .= [ones(2,2)] @test all(A[1:3,1:3] .== [ones(2,2)]) end + +# Issue #21291 +let t = (0, 1, 2) + o = 1 + @test @inferred(broadcast(+, t, o)) == (1, 2, 3) +end From 965c938eb933f9850f55dcebf12198952ba34b62 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Sat, 8 Apr 2017 14:57:58 -0700 Subject: [PATCH 0381/1534] Add test for revcount, update docstring (#20865) * Add test for revcount, update docstring * Add better docstring --- base/libgit2/libgit2.jl | 25 ++++++++++++++++++------- test/libgit2.jl | 2 ++ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/base/libgit2/libgit2.jl b/base/libgit2/libgit2.jl index a4be3b6c5d8f8..0721ab7b8e4c2 100644 --- a/base/libgit2/libgit2.jl +++ b/base/libgit2/libgit2.jl @@ -514,16 +514,26 @@ Equivalent to `git reset [--soft | --mixed | --hard] `. reset!(repo::GitRepo, id::GitHash, mode::Cint = Consts.RESET_MIXED) = reset!(repo, GitObject(repo, id), mode) -""" git rev-list --count """ -function revcount(repo::GitRepo, fst::AbstractString, snd::AbstractString) - fst_id = revparseid(repo, fst) - snd_id = revparseid(repo, snd) - base_id = merge_base(repo, string(fst_id), string(snd_id)) +""" + LibGit2.revcount(repo::GitRepo, commit1::AbstractString, commit2::AbstractString) + +List the number of revisions between `commit1` and `commit2` (committish OIDs in string form). +Since `commit1` and `commit2` may be on different branches, `revcount` performs a "left-right" +revision list (and count), returning a tuple of `Int`s - the number of left and right +commits, respectively. A left (or right) commit refers to which side of a symmetric +difference in a tree the commit is reachable from. + +Equivalent to `git rev-list --left-right --count `. +""" +function revcount(repo::GitRepo, commit1::AbstractString, commit2::AbstractString) + commit1_id = revparseid(repo, commit1) + commit2_id = revparseid(repo, commit2) + base_id = merge_base(repo, string(commit1_id), string(commit2_id)) fc = with(GitRevWalker(repo)) do walker - count((i,r)->i!=base_id, walker, oid=fst_id, by=Consts.SORT_TOPOLOGICAL) + count((i,r)->i!=base_id, walker, oid=commit1_id, by=Consts.SORT_TOPOLOGICAL) end sc = with(GitRevWalker(repo)) do walker - count((i,r)->i!=base_id, walker, oid=snd_id, by=Consts.SORT_TOPOLOGICAL) + count((i,r)->i!=base_id, walker, oid=commit2_id, by=Consts.SORT_TOPOLOGICAL) end return (fc-1, sc-1) end @@ -827,3 +837,4 @@ end end # module + diff --git a/test/libgit2.jl b/test/libgit2.jl index ca82b0a1f87f6..2bb76b14b8332 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -392,6 +392,8 @@ mktempdir() do dir @test contains(showstr[4], "SHA:") @test showstr[5] == "Message:" @test showstr[6] == commit_msg1 + + @test LibGit2.revcount(repo, string(commit_oid1), string(commit_oid3)) == (-1,0) finally close(cmt) end From df2438ccbc9bd68dc933ca37c8bc2d0b4677ae70 Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Sun, 9 Apr 2017 21:34:40 -0700 Subject: [PATCH 0382/1534] Restrict lfact to the domain of factorial (#21321) --- base/special/gamma.jl | 6 ++++-- test/math.jl | 5 ++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/base/special/gamma.jl b/base/special/gamma.jl index 61952ce1edf22..7363de8a78454 100644 --- a/base/special/gamma.jl +++ b/base/special/gamma.jl @@ -27,9 +27,11 @@ lgamma_r(x::Number) = lgamma(x), 1 # lgamma does not take abs for non-real x """ lfact(x) -Compute the logarithmic factorial of `x` +Compute the logarithmic factorial of a nonnegative integer `x`. +Equivalent to [`lgamma`](@ref) of `x + 1`, but `lgamma` extends this function +to non-integer `x`. """ -lfact(x::Real) = (x<=1 ? zero(float(x)) : lgamma(x+oneunit(x))) +lfact(x::Integer) = x < 0 ? throw(DomainError()) : lgamma(x + oneunit(x)) """ lgamma(x) diff --git a/test/math.jl b/test/math.jl index 2dab2c3f07278..744ce7d7a4be4 100644 --- a/test/math.jl +++ b/test/math.jl @@ -424,8 +424,11 @@ relerrc(z, x) = max(relerr(real(z),real(x)), relerr(imag(z),imag(x))) for x in (3.2, 2+1im, 3//2, 3.2+0.1im) @test factorial(x) == gamma(1+x) end - @test lfact(1) == 0 + @test lfact(0) == lfact(1) == 0 @test lfact(2) == lgamma(3) + # Ensure that the domain of lfact matches that of factorial (issue #21318) + @test_throws DomainError lfact(-3) + @test_throws MethodError lfact(1.0) end # lgamma test cases (from Wolfram Alpha) From ea8d04be615aac4f27e991536eeb688f2927f21e Mon Sep 17 00:00:00 2001 From: Martin Holters Date: Mon, 10 Apr 2017 09:12:57 +0200 Subject: [PATCH 0383/1534] Some more `typeintersect` tests --- test/subtype.jl | 63 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/test/subtype.jl b/test/subtype.jl index 20415b9235117..1d9747b5c26bd 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -999,6 +999,69 @@ ftwoparams(::TwoParams{<:Real,<:Real}) = 3 @testintersect(Tuple{Val{Val{0}}, Val{N}} where N, Tuple{Val{Val{N}}, Val{N}} where N, Tuple{Val{Val{0}},Val{0}}) @testintersect(Tuple{Val{Val{N}}, Val{0}} where N, Tuple{Val{Val{N}}, Val{N}} where N, Tuple{Val{Val{0}},Val{0}}) +# a bunch of cases found by fuzzing +let a = Tuple{Float64,T7} where T7, + b = Tuple{S5,Tuple{S5}} where S5 + @test_broken typeintersect(a, b) <: b +end +let a = Tuple{T1,T1} where T1, + b = Tuple{Val{S2},S6} where S2 where S6 + @test_broken typeintersect(a, b) == typeintersect(b, a) +end +let a = Val{Tuple{T1,T1}} where T1, + b = Val{Tuple{Val{S2},S6}} where S2 where S6 + @testintersect(a, b, Val{Tuple{Val{T},Val{T}}} where T) +end +let a = Tuple{Float64,T3,T4} where T4 where T3, + b = Tuple{S2,Tuple{S3},S3} where S2 where S3 + @test_broken typeintersect(a, b) == typeintersect(b, a) +end +let a = Tuple{T1,Tuple{T1}} where T1, + b = Tuple{Float64,S3} where S3 + @test_broken typeintersect(a, b) <: a +end +let a = Tuple{5,T4,T5} where T4 where T5, + b = Tuple{S2,S3,Tuple{S3}} where S2 where S3 + @test_broken typeintersect(a, b) == typeintersect(b, a) +end +let a = Tuple{T2,Tuple{T4,T2}} where T4 where T2, + b = Tuple{Float64,Tuple{Tuple{S3},S3}} where S3 + @test_broken typeintersect(a, b) <: b +end +let a = Tuple{Tuple{T2,4},T6} where T2 where T6, + b = Tuple{Tuple{S2,S3},Tuple{S2}} where S2 where S3 + @test_broken typeintersect(a, b) == typeintersect(b, a) +end +let a = Tuple{T3,Int64,Tuple{T3}} where T3, + b = Tuple{S3,S3,S4} where S4 where S3 + @test_broken typeintersect(a, b) <: a +end +let a = Tuple{T1,Val{T2},T2} where T2 where T1, + b = Tuple{Float64,S1,S2} where S2 where S1 + @test_broken typeintersect(a, b) == typeintersect(b, a) +end +let a = Tuple{T1,Val{T2},T2} where T2 where T1, + b = Tuple{Float64,S1,S2} where S2 where S1 + @test_broken typeintersect(a, b) <: a +end +let a = Tuple{Float64,T1} where T1, + b = Tuple{S1,Tuple{S1}} where S1 + @test_broken typeintersect(a, b) <: b +end +let a = Tuple{Val{T1},T2,T2} where T2 where T1, + b = Tuple{Val{Tuple{S2}},S3,Float64} where S2 where S3 + @testintersect(a, b, Tuple{Val{Tuple{S2}},Float64,Float64} where S2) +end +let a = Tuple{T1,T2,T2} where T1 where T2, + b = Tuple{Val{S2},S2,Float64} where S2, + x = Tuple{Val{Float64},Float64,Float64} + @test_broken x <: typeintersect(a, b) +end +let a = Val{Tuple{T1,Val{T2},Val{Int64},Tuple{Tuple{T3,5,Float64},T4,T2,T5}}} where T1 where T5 where T4 where T3 where T2, + b = Val{Tuple{Tuple{S1,5,Float64},Val{S2},S3,Tuple{Tuple{Val{Float64},5,Float64},2,Float64,S4}}} where S2 where S3 where S1 where S4 + @test_skip typeintersect(b, a) +end + # issue #20992 abstract type A20992{T,D,d} end abstract type B20992{SV,T,D,d} <: A20992{T,D,d} end From ec49c9eb1b3c6726fbf5c71950250c513b621c8a Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Mon, 10 Apr 2017 13:06:58 -0500 Subject: [PATCH 0384/1534] Re-introduce SSH agent error checking When re-using credentials like we do with `Pkg.update` we need to allow `creds.usesshagent == "U"` to allow separate authentications to the same host to both use the SSH agent. This allows the SSH agent to be used multiple times when we have multiple private packages. Re-introducing this code did mean we needed to introduce a way of disabling the use of the SSH agent for testing purposes. --- base/libgit2/callbacks.jl | 12 +++++++++++- test/libgit2-helpers.jl | 20 +++++++++++++++----- test/libgit2.jl | 8 ++++---- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/base/libgit2/callbacks.jl b/base/libgit2/callbacks.jl index 2cfa1cb1ef2e9..13dd8e73a97ec 100644 --- a/base/libgit2/callbacks.jl +++ b/base/libgit2/callbacks.jl @@ -28,8 +28,18 @@ function authenticate_ssh(creds::SSHCredentials, libgit2credptr::Ptr{Ptr{Void}}, username_ptr, schema, host) isusedcreds = checkused!(creds) + # Note: The same SSHCredentials can be used authenticate separate requests using the + # same credential cache. e.g. using Pkg.update when there are two private packages. + errcls, errmsg = Error.last_error() + if errcls != Error.None + # Check if we used ssh-agent + if creds.usesshagent == "U" + creds.usesshagent = "E" # reported ssh-agent error, disables ssh agent use for the future + end + end + # first try ssh-agent if credentials support its usage - if creds.usesshagent == "Y" + if creds.usesshagent == "Y" || creds.usesshagent == "U" err = ccall((:git_cred_ssh_key_from_agent, :libgit2), Cint, (Ptr{Ptr{Void}}, Cstring), libgit2credptr, username_ptr) creds.usesshagent = "U" # used ssh-agent only one time diff --git a/test/libgit2-helpers.jl b/test/libgit2-helpers.jl index 9312487aa39a9..a5756250257c1 100644 --- a/test/libgit2-helpers.jl +++ b/test/libgit2-helpers.jl @@ -1,6 +1,6 @@ # This file is a part of Julia. License is MIT: http://julialang.org/license -import Base.LibGit2: AbstractCredentials, UserPasswordCredentials, SSHCredentials +import Base.LibGit2: AbstractCredentials, UserPasswordCredentials, SSHCredentials, CachedCredentials """ Emulates the LibGit2 credential loop to allows testing of the credential_callback function @@ -10,10 +10,10 @@ function credential_loop( valid_credential::AbstractCredentials, url::AbstractString, user::AbstractString, - allowed_types::UInt32) + allowed_types::UInt32, + cache::CachedCredentials=CachedCredentials()) cb = Base.LibGit2.credentials_cb() libgitcred_ptr_ptr = Ref{Ptr{Void}}(C_NULL) - cache = Base.LibGit2.CachedCredentials() payload_ptr = Ref(Nullable{AbstractCredentials}(cache)) # Number of times credentials were authenticated against. With the real LibGit2 @@ -51,6 +51,16 @@ end function credential_loop( valid_credential::SSHCredentials, url::AbstractString, - user::AbstractString="") - credential_loop(valid_credential, url, user, 0x000046) + user::AbstractString=""; + use_ssh_agent::Bool=false) + cache = CachedCredentials() + + if !use_ssh_agent + m = match(LibGit2.URL_REGEX, url) + default_cred = LibGit2.reset!(SSHCredentials(true), -1) + default_cred.usesshagent = "N" + LibGit2.get_creds!(cache, "ssh://$(m[:host])", default_cred) + end + + credential_loop(valid_credential, url, user, 0x000046, cache) end diff --git a/test/libgit2.jl b/test/libgit2.jl index bc93cbadabc71..0c54238d5ae2b 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -1127,7 +1127,7 @@ mktempdir() do dir withenv("SSH_KEY_PATH" => valid_key) do err, auth_attempts = challenge_prompt(ssh_cmd, []) @test err == 0 - @test auth_attempts == 2 + @test auth_attempts == 1 end # Default credentials are valid but requires a passphrase @@ -1137,7 +1137,7 @@ mktempdir() do dir ] err, auth_attempts = challenge_prompt(ssh_p_cmd, challenges) @test err == 0 - @test auth_attempts == 2 + @test auth_attempts == 1 # User mistypes passphrase. # Note: In reality LibGit2 will raise an error upon using the invalid SSH @@ -1150,13 +1150,13 @@ mktempdir() do dir ] err, auth_attempts = challenge_prompt(ssh_p_cmd, challenges) @test err == 0 - @test auth_attempts == 6 + @test auth_attempts == 5 end withenv("SSH_KEY_PATH" => valid_p_key, "SSH_KEY_PASS" => passphrase) do err, auth_attempts = challenge_prompt(ssh_p_cmd, []) @test err == 0 - @test auth_attempts == 2 + @test auth_attempts == 1 end # TODO: Tests are currently broken. Credential callback prompts for: From cbc32a50817206d0be83b1630d2f9dbee13808da Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 10 Apr 2017 15:07:27 -0400 Subject: [PATCH 0385/1534] add tests for issues #10207, #10178, #12939 --- test/core.jl | 16 ++++++++++++++++ test/inference.jl | 7 +++++++ test/staged.jl | 12 ++++++++++++ 3 files changed, 35 insertions(+) diff --git a/test/core.jl b/test/core.jl index 2016d2d5973ee..8fd63755a1f13 100644 --- a/test/core.jl +++ b/test/core.jl @@ -81,6 +81,22 @@ _bound_vararg_specificity_1{T}(::Type{Array{T,1}}, d::Int) = 1 @test _bound_vararg_specificity_1(Array{Int,1}, 1) == 1 @test _bound_vararg_specificity_1(Array{Int,2}, 1, 1) == 0 +# issue #12939 +module Issue12939 +abstract type Abs; end +struct Foo <: Abs; end +struct Bar; val::Int64; end +struct Baz; val::Int64; end +f{T}(::Type{T}, x::T) = T(3) +f{T <: Abs}(::Type{Bar}, x::T) = Bar(2) +f(::Type{Bar}, x) = Bar(1) +f(::Type{Baz}, x) = Baz(1) +f{T <: Abs}(::Type{Baz}, x::T) = Baz(2) +end + +@test Issue12939.f(Issue12939.Baz,Issue12939.Foo()) === Issue12939.Baz(2) +@test Issue12939.f(Issue12939.Bar,Issue12939.Foo()) === Issue12939.Bar(2) + # issue #11840 TT11840{T} = Tuple{T,T} f11840(::Type) = "Type" diff --git a/test/inference.jl b/test/inference.jl index 7cf7f368551f6..b0673e8e1ba25 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -738,3 +738,10 @@ let e = code_typed(f21175, ())[1].first.code[1]::Expr @test e.head === :return @test e.args[1] == Core.QuoteNode(902221) end + +# issue #10207 +type T10207{A, B} + a::A + b::B +end +@test code_typed(T10207, (Int,Any))[1].second == T10207{Int,T} where T diff --git a/test/staged.jl b/test/staged.jl index c9066742eff76..28bb661fe361e 100644 --- a/test/staged.jl +++ b/test/staged.jl @@ -213,3 +213,15 @@ end # issue #19897 @test code_lowered(staged_t1, (Int,Int)) isa Array # check no error thrown + +# issue #10178 +@generated function f10178(x::X) where X + :(x) +end +g10178(x) = f10178(x) +@test g10178(5) == 5 +@generated function f10178(x::X) where X + :(2x) +end +g10178(x) = f10178(x) +@test g10178(5) == 10 From 33aa319142b3bca8bc47032ea76df9e4618d232f Mon Sep 17 00:00:00 2001 From: Mus M Date: Mon, 10 Apr 2017 15:32:36 -0400 Subject: [PATCH 0386/1534] Fix build_sysimg.jl on Windows when linking failure occurs (#21235) In case linking fails, fall back to `syimg_file.old`. For windows we first attempt to link to a temporary sysimg_file; if this fails we simply, it fall backs to the current sysimg_file in use safely. This is done since Windows has difficulties overwriting a file in use. --- contrib/build_sysimg.jl | 43 ++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/contrib/build_sysimg.jl b/contrib/build_sysimg.jl index e26195286f84a..50ba236dbb885 100644 --- a/contrib/build_sysimg.jl +++ b/contrib/build_sysimg.jl @@ -33,8 +33,8 @@ function build_sysimg(sysimg_path=nothing, cpu_target="native", userimg_path=not sysimg = Libdl.dlopen_e("sys") if sysimg != C_NULL if !force && Base.samefile(Libdl.dlpath(sysimg), "$(sysimg_path).$(Libdl.dlext)") - info("System image already loaded at $(Libdl.dlpath(sysimg)), set force=true to override") - return + info("System image already loaded at $(Libdl.dlpath(sysimg)), set force=true to override.") + return nothing end end @@ -54,14 +54,14 @@ function build_sysimg(sysimg_path=nothing, cpu_target="native", userimg_path=not touch("$sysimg_path.ji") catch err_msg = "Unable to modify $sysimg_path.ji, ensure parent directory exists " - err_msg *= "and is writable. Absolute paths work best.)" - error( err_msg ) + err_msg *= "and is writable; absolute paths work best.)" + error(err_msg) end # Copy in userimg.jl if it exists if userimg_path !== nothing if !isfile(userimg_path) - error("$userimg_path is not found, ensure it is an absolute path!") + error("$userimg_path is not found, ensure it is an absolute path.") end if isfile("userimg.jl") error("$base_dir/userimg.jl already exists, delete manually to continue.") @@ -72,28 +72,28 @@ function build_sysimg(sysimg_path=nothing, cpu_target="native", userimg_path=not # Start by building inference.{ji,o} inference_path = joinpath(dirname(sysimg_path), "inference") info("Building inference.o") - println("$julia -C $cpu_target --output-ji $inference_path.ji --output-o $inference_path.o coreimg.jl") + info("$julia -C $cpu_target --output-ji $inference_path.ji --output-o $inference_path.o coreimg.jl") run(`$julia -C $cpu_target --output-ji $inference_path.ji --output-o $inference_path.o coreimg.jl`) # Bootstrap off of that to create sys.{ji,o} info("Building sys.o") - println("$julia -C $cpu_target --output-ji $sysimg_path.ji --output-o $sysimg_path.o -J $inference_path.ji --startup-file=no sysimg.jl") + info("$julia -C $cpu_target --output-ji $sysimg_path.ji --output-o $sysimg_path.o -J $inference_path.ji --startup-file=no sysimg.jl") run(`$julia -C $cpu_target --output-ji $sysimg_path.ji --output-o $sysimg_path.o -J $inference_path.ji --startup-file=no sysimg.jl`) if cc !== nothing link_sysimg(sysimg_path, cc, debug) else - info("System image successfully built at $sysimg_path.ji") + info("System image successfully built at $sysimg_path.ji.") end if !Base.samefile("$(default_sysimg_path(debug)).ji", "$sysimg_path.ji") if Base.isfile("$sysimg_path.$(Libdl.dlext)") - info("To run Julia with this image loaded, run: julia -J $sysimg_path.$(Libdl.dlext)") + info("To run Julia with this image loaded, run: `julia -J $sysimg_path.$(Libdl.dlext)`.") else - info("To run Julia with this image loaded, run: julia -J $sysimg_path.ji") + info("To run Julia with this image loaded, run: `julia -J $sysimg_path.ji`.") end else - info("Julia will automatically load this system image at next startup") + info("Julia will automatically load this system image at next startup.") end finally # Cleanup userimg.jl @@ -106,9 +106,9 @@ end # Search for a compiler to link sys.o into sys.dl_ext. Honor LD environment variable. function find_system_compiler() - if haskey( ENV, "CC" ) + if haskey(ENV, "CC") if !success(`$(ENV["CC"]) -v`) - warn("Using compiler override $(ENV["CC"]), but unable to run `$(ENV["CC"]) -v`") + warn("Using compiler override $(ENV["CC"]), but unable to run `$(ENV["CC"]) -v`.") end return ENV["CC"] end @@ -117,15 +117,15 @@ function find_system_compiler() if is_windows() try eval(Main, :(using WinRPM)) - winrpmgcc = joinpath(WinRPM.installdir,"usr","$(Sys.ARCH)-w64-mingw32", - "sys-root","mingw","bin","gcc.exe") + winrpmgcc = joinpath(WinRPM.installdir, "usr", "$(Sys.ARCH)-w64-mingw32", + "sys-root", "mingw", "bin", "gcc.exe") if success(`$winrpmgcc --version`) return winrpmgcc else throw() end catch - warn("Install GCC via `Pkg.add(\"WinRPM\"); WinRPM.install(\"gcc\")` to generate sys.dll for faster startup times") + warn("Install GCC via `Pkg.add(\"WinRPM\"); WinRPM.install(\"gcc\")` to generate sys.dll for faster startup times.") end end @@ -137,7 +137,7 @@ function find_system_compiler() end end - warn( "No supported compiler found; startup times will be longer" ) + warn("No supported compiler found; startup times will be longer.") end # Link sys.o into sys.$(dlext) @@ -157,10 +157,13 @@ function link_sysimg(sysimg_path=nothing, cc=find_system_compiler(), debug=false sysimg_file = "$sysimg_path.$(Libdl.dlext)" info("Linking sys.$(Libdl.dlext)") - # Windows has difficulties overwriting a file in use so we first rename it + info("$cc $FLAGS -o $sysimg_file $sysimg_path.o") + # Windows has difficulties overwriting a file in use so we first link to a temp file if is_windows() && isfile(sysimg_file) - mv(sysimg_file, "$sysimg_file.old"; remove_destination=true) - run(`$cc $FLAGS -o $sysimg_file $sysimg_path.o`) + if success(pipeline(`$cc $FLAGS -o $sysimg_path.tmp $sysimg_path.o`; stdout=STDOUT, stderr=STDERR)) + mv(sysimg_file, "$sysimg_file.old"; remove_destination=true) + mv("$sysimg_path.tmp", sysimg_file; remove_destination=true) + end else run(`$cc $FLAGS -o $sysimg_file $sysimg_path.o`) end From 05ad3927f39aaa1918921e0cd2b565d8ca5bb5b3 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Mon, 10 Apr 2017 15:21:47 -0500 Subject: [PATCH 0387/1534] [ci skip] Review change --- base/libgit2/callbacks.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/libgit2/callbacks.jl b/base/libgit2/callbacks.jl index 13dd8e73a97ec..da74f2e88071f 100644 --- a/base/libgit2/callbacks.jl +++ b/base/libgit2/callbacks.jl @@ -28,7 +28,7 @@ function authenticate_ssh(creds::SSHCredentials, libgit2credptr::Ptr{Ptr{Void}}, username_ptr, schema, host) isusedcreds = checkused!(creds) - # Note: The same SSHCredentials can be used authenticate separate requests using the + # Note: The same SSHCredentials can be used to authenticate separate requests using the # same credential cache. e.g. using Pkg.update when there are two private packages. errcls, errmsg = Error.last_error() if errcls != Error.None From 81c8815f28a460f6acc7fabf07cfde09e488469e Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 10 Apr 2017 12:57:45 -0400 Subject: [PATCH 0388/1534] improve codegen of typecheck on first field of new structs prompted by #21323 This removes the special case for the first field. --- src/cgutils.cpp | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index bdc1de56ae06c..98af1bc751d46 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -2315,26 +2315,10 @@ static jl_cgval_t emit_new_struct(jl_value_t *ty, size_t nargs, jl_value_t **arg else return mark_julia_slot(strct, ty, NULL, tbaa_stack); } - Value *f1 = NULL; - size_t j = 0; - if (nf > 0 && jl_field_isptr(sty, 0) && nargs>1) { - // emit first field before allocating struct to save - // a couple store instructions. avoids initializing - // the first field to NULL, and sometimes the GC root - // for the new struct. - jl_cgval_t fval_info = emit_expr(args[1],ctx); - f1 = boxed(fval_info, ctx); - j++; - } Value *strct = emit_allocobj(ctx, jl_datatype_size(sty), literal_pointer_val((jl_value_t*)ty)); jl_cgval_t strctinfo = mark_julia_type(strct, true, ty, ctx); - if (f1) { - jl_cgval_t f1info = mark_julia_type(f1, true, jl_any_type, ctx); - emit_typecheck(f1info, jl_field_type(sty, 0), "new", ctx); - emit_setfield(sty, strctinfo, 0, f1info, ctx, false, false); - } - for (size_t i = j; i < nf; i++) { + for (size_t i = 0; i < nf; i++) { if (jl_field_isptr(sty, i)) { tbaa_decorate(strctinfo.tbaa, builder.CreateStore( V_null, @@ -2346,7 +2330,7 @@ static jl_cgval_t emit_new_struct(jl_value_t *ty, size_t nargs, jl_value_t **arg } bool need_wb = false; // TODO: verify that nargs <= nf (currently handled by front-end) - for (size_t i = j + 1; i < nargs; i++) { + for (size_t i = 1; i < nargs; i++) { jl_cgval_t rhs = emit_expr(args[i], ctx); if (jl_field_isptr(sty, i - 1) && !rhs.isboxed) { need_wb = true; From bb1e493bd87989bb513d9d425d72ad6e3983e2c2 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 11 Apr 2017 15:00:06 -0400 Subject: [PATCH 0389/1534] speed up ambiguous method checking and intersection; helps #21173 --- src/gf.c | 28 +++++++++----- src/julia_internal.h | 4 +- src/subtype.c | 91 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 111 insertions(+), 12 deletions(-) diff --git a/src/gf.c b/src/gf.c index de023ba2163ea..c6df93465cf1a 100644 --- a/src/gf.c +++ b/src/gf.c @@ -1090,12 +1090,6 @@ void print_func_loc(JL_STREAM *s, jl_method_t *m) however, (AbstractArray, AbstractMatrix, Foo) and (AbstractMatrix, AbstractArray, Bar) are fine since Foo and Bar are disjoint, so there would be no confusion over which one to call. - - There is also this kind of ambiguity: foo{T,S}(T, S) vs. foo(Any,Any) - In this case jl_types_equal() is true, but one is jl_type_morespecific - or jl_type_match_morespecific than the other. - To check this, jl_types_equal_generic needs to be more sophisticated - so (T,T) is not equivalent to (Any,Any). (TODO) */ struct ambiguous_matches_env { struct typemap_intersection_env match; @@ -1124,8 +1118,23 @@ static int check_ambiguous_visitor(jl_typemap_entry_t *oldentry, struct typemap_ // or !jl_type_morespecific(sig, type) [after] // based on their sort order in the typemap // now we are checking that the reverse is true - if (!jl_type_morespecific((jl_value_t*)(closure->after ? type : sig), - (jl_value_t*)(closure->after ? sig : type))) { + int msp; + if (closure->match.issubty) { + assert(closure->after); + msp = 1; + } + else if (closure->after) { + assert(!jl_subtype((jl_value_t*)sig, (jl_value_t*)type)); + msp = jl_type_morespecific_no_subtype((jl_value_t*)type, (jl_value_t*)sig); + } + else { + if (jl_subtype((jl_value_t*)sig, (jl_value_t*)type)) + msp = 1; + else + msp = jl_type_morespecific_no_subtype((jl_value_t*)sig, (jl_value_t*)type); + } + + if (!msp) { // see if the intersection is covered by another existing method // that will resolve the ambiguity (by being more specific than either) // (if type-morespecific made a mistake, this also might end up finding @@ -1196,7 +1205,7 @@ static jl_value_t *check_ambiguous_matches(union jl_typemap_t defs, jl_typemap_e env.match.type = (jl_value_t*)type; env.match.va = va; env.match.ti = NULL; - env.match.env = NULL; + env.match.env = jl_emptysvec; env.defs = defs; env.newentry = newentry; env.shadowed = NULL; @@ -1418,6 +1427,7 @@ JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method env.match.va = va; env.match.type = (jl_value_t*)type; env.match.fptr = invalidate_backedges; + env.match.env = NULL; if (jl_is_method(oldvalue)) { jl_typemap_intersection_visitor(((jl_method_t*)oldvalue)->specializations, 0, &env.match); diff --git a/src/julia_internal.h b/src/julia_internal.h index 8eb3842a8a9be..e40cd82eea32c 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -421,14 +421,14 @@ int jl_tuple_isa(jl_value_t **child, size_t cl, jl_datatype_t *pdt); int jl_has_intersect_type_not_kind(jl_value_t *t); int jl_subtype_invariant(jl_value_t *a, jl_value_t *b, int ta); -jl_value_t *jl_type_match(jl_value_t *a, jl_value_t *b); -jl_value_t *jl_type_match_morespecific(jl_value_t *a, jl_value_t *b); jl_datatype_t *jl_inst_concrete_tupletype_v(jl_value_t **p, size_t np); jl_datatype_t *jl_inst_concrete_tupletype(jl_svec_t *p); JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method, jl_tupletype_t *simpletype); void jl_mk_builtin_func(jl_datatype_t *dt, const char *name, jl_fptr_t fptr); jl_value_t *jl_type_intersection_env_s(jl_value_t *a, jl_value_t *b, jl_svec_t **penv, int *issubty); jl_value_t *jl_type_intersection_env(jl_value_t *a, jl_value_t *b, jl_svec_t **penv); +// specificity comparison assuming !(a <: b) and !(b <: a) +JL_DLLEXPORT int jl_type_morespecific_no_subtype(jl_value_t *a, jl_value_t *b); jl_value_t *jl_instantiate_type_with(jl_value_t *t, jl_value_t **env, size_t n); JL_DLLEXPORT jl_value_t *jl_instantiate_type_in_env(jl_value_t *ty, jl_unionall_t *env, jl_value_t **vals); jl_value_t *jl_substitute_var(jl_value_t *t, jl_tvar_t *var, jl_value_t *val); diff --git a/src/subtype.c b/src/subtype.c index eeb5d4376f64d..8a1984c7a285f 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -238,6 +238,84 @@ static int obviously_unequal(jl_value_t *a, jl_value_t *b) return 0; } +static int obviously_disjoint(jl_value_t *a, jl_value_t *b) +{ + if (a == b || a == (jl_value_t*)jl_any_type || b == (jl_value_t*)jl_any_type) + return 0; + if (jl_is_leaf_type(a) && !((jl_datatype_t*)a)->abstract && + jl_is_leaf_type(b) && !((jl_datatype_t*)b)->abstract && + // TODO: remove these 2 lines if and when Tuple{Union{}} === Union{} + (((jl_datatype_t*)a)->name != jl_tuple_typename || + ((jl_datatype_t*)b)->name != jl_tuple_typename)) + return 1; + if (jl_is_unionall(a)) a = jl_unwrap_unionall(a); + if (jl_is_unionall(b)) b = jl_unwrap_unionall(b); + if (jl_is_datatype(a) && jl_is_datatype(b)) { + jl_datatype_t *ad = (jl_datatype_t*)a, *bd = (jl_datatype_t*)b; + if (ad->name != bd->name) { + jl_datatype_t *temp = ad; + while (temp != jl_any_type && temp->name != bd->name) + temp = temp->super; + if (temp == jl_any_type) { + temp = bd; + while (temp != jl_any_type && temp->name != ad->name) + temp = temp->super; + if (temp == jl_any_type) + return 1; + bd = temp; + } + else { + ad = temp; + } + } + int istuple = (ad->name == jl_tuple_typename); + size_t np; + if (istuple) { + size_t na = jl_nparams(ad), nb = jl_nparams(bd); + if (jl_is_va_tuple(ad)) { + na -= 1; + if (jl_is_va_tuple(bd)) + nb -= 1; + } + else if (jl_is_va_tuple(bd)) { + nb -= 1; + } + else if (na != nb) { + return 1; + } + np = na < nb ? na : nb; + } + else { + np = jl_nparams(ad); + } + size_t i; + for(i=0; i < np; i++) { + jl_value_t *ai = jl_tparam(ad,i); + jl_value_t *bi = jl_tparam(bd,i); + if (jl_is_typevar(ai) || jl_is_typevar(bi)) + continue; + if (jl_is_type(ai)) { + if (jl_is_type(bi)) { + if (istuple && (ai == jl_bottom_type || bi == jl_bottom_type)) + ; // TODO: this can return 1 if and when Tuple{Union{}} === Union{} + else if (obviously_disjoint(ai, bi)) + return 1; + } + else { + return 1; + } + } + else if (!jl_egal(ai, bi)) { + return 1; + } + } + } + else if (a == jl_bottom_type || b == jl_bottom_type) { + return 1; + } + return 0; +} + static int in_union(jl_value_t *u, jl_value_t *x) { if (u == x) return 1; @@ -1967,6 +2045,8 @@ static jl_value_t *intersect_all(jl_value_t *x, jl_value_t *y, jl_stenv_t *e) JL_DLLEXPORT jl_value_t *jl_intersect_types(jl_value_t *x, jl_value_t *y) { jl_stenv_t e; + if (obviously_disjoint(x, y)) + return jl_bottom_type; init_stenv(&e, NULL, 0); e.intersection = 1; return intersect_all(x, y, &e); @@ -1992,12 +2072,16 @@ jl_svec_t *jl_outer_unionall_vars(jl_value_t *u) // sets *issubty to 1 iff `a` is a subtype of `b` jl_value_t *jl_type_intersection_env_s(jl_value_t *a, jl_value_t *b, jl_svec_t **penv, int *issubty) { + if (issubty) *issubty = 0; + if (obviously_disjoint(a, b)) { + if (issubty && a == jl_bottom_type) *issubty = 1; + return jl_bottom_type; + } int szb = jl_subtype_env_size(b); int sz = 0, i = 0; jl_value_t **env, **ans; JL_GC_PUSHARGS(env, szb+1); ans = &env[szb]; *ans = jl_bottom_type; - if (issubty) *issubty = 0; if (jl_subtype_env(a, b, env, szb)) { *ans = a; sz = szb; if (issubty) *issubty = 1; @@ -2491,6 +2575,11 @@ JL_DLLEXPORT int jl_type_morespecific(jl_value_t *a, jl_value_t *b) return type_morespecific_(a, b, 0, NULL); } +JL_DLLEXPORT int jl_type_morespecific_no_subtype(jl_value_t *a, jl_value_t *b) +{ + return type_morespecific_(a, b, 0, NULL); +} + #ifdef __cplusplus } #endif From 7b16106fa4cc3400f32279106d48f7c39cc3e819 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 6 Apr 2017 12:57:39 -0400 Subject: [PATCH 0390/1534] fix llvm 3.3 build --- src/cgutils.cpp | 12 ++++-------- src/codegen.cpp | 2 ++ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index bdc1de56ae06c..b030270e7b2c3 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -931,14 +931,8 @@ static inline void maybe_mark_argument_dereferenceable(Argument *A, jl_value_t * if (!size) { return; } - llvm::AttrBuilder Attrs; - Attrs.addDereferenceableAttr(size); -#if JL_LLVM_VERSION >= 50000 - A->addAttr(llvm::AttributeList::get(jl_LLVMContext, - A->getArgNo() + 1, Attrs)); -#else - A->addAttr(llvm::AttributeSet::get(jl_LLVMContext, - A->getArgNo() + 1, Attrs)); +#if JL_LLVM_VERSION >= 30700 + A->getParent()->addDereferenceableAttr(A->getArgNo() + 1, size); #endif } @@ -946,11 +940,13 @@ static inline Instruction *maybe_mark_load_dereferenceable(Instruction *LI, bool if (!size) { return LI; } +#if JL_LLVM_VERSION >= 30700 llvm::SmallVector OPs; OPs.push_back(ConstantAsMetadata::get(ConstantInt::get(T_int64, size))); LI->setMetadata(can_be_null ? "dereferenceable_or_null" : "dereferenceable", MDNode::get(jl_LLVMContext, OPs)); +#endif return LI; } diff --git a/src/codegen.cpp b/src/codegen.cpp index a0f0a6e168fc1..7a6b7e3983867 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -5033,7 +5033,9 @@ static jl_returninfo_t get_specsig_function(Module *M, const std::string &name, continue; if (ty->isAggregateType()) { // aggregate types are passed by pointer attributes = attributes.addAttribute(jl_LLVMContext, fsig.size() + 1, Attribute::NoCapture); +#if JL_LLVM_VERSION >= 30500 attributes = attributes.addAttribute(jl_LLVMContext, fsig.size() + 1, Attribute::ReadOnly); +#endif ty = PointerType::get(ty, 0); } fsig.push_back(ty); From a52919962d527029ebed75b713ef9fa40815ed6e Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 6 Apr 2017 13:38:49 -0400 Subject: [PATCH 0391/1534] delete false pretense of support of max_world on a Method --- base/inference.jl | 2 +- base/methodshow.jl | 2 +- base/reflection.jl | 2 +- base/replutil.jl | 3 --- src/dump.c | 7 ------- src/gf.c | 11 +++++------ src/jltypes.c | 8 +++----- src/julia.h | 1 - src/method.c | 3 +-- 9 files changed, 12 insertions(+), 27 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 039496b3f89ca..9840772355935 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -2391,7 +2391,7 @@ function finalize_backedges(frame::InferenceState) end function code_for_method(method::Method, atypes::ANY, sparams::SimpleVector, world::UInt, preexisting::Bool=false) - if world < min_world(method) || world > max_world(method) + if world < min_world(method) return nothing end if method.isstaged && !isleaftype(atypes) diff --git a/base/methodshow.jl b/base/methodshow.jl index 8ae16639561a6..6429133a0ebe9 100644 --- a/base/methodshow.jl +++ b/base/methodshow.jl @@ -68,7 +68,7 @@ end function kwarg_decl(m::Method, kwtype::DataType) sig = rewrap_unionall(Tuple{kwtype, Core.AnyVector, unwrap_unionall(m.sig).parameters...}, m.sig) - kwli = ccall(:jl_methtable_lookup, Any, (Any, Any, UInt), kwtype.name.mt, sig, max_world(m)) + kwli = ccall(:jl_methtable_lookup, Any, (Any, Any, UInt), kwtype.name.mt, sig, typemax(UInt)) if kwli !== nothing kwli = kwli::Method src = uncompressed_ast(kwli, kwli.source) diff --git a/base/reflection.jl b/base/reflection.jl index 44fad1bd4601c..3d4b35c7bc3f4 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -1002,6 +1002,6 @@ has_bottom_parameter(t::TypeVar) = has_bottom_parameter(t.ub) has_bottom_parameter(::Any) = false min_world(m::Method) = reinterpret(UInt, m.min_world) -max_world(m::Method) = reinterpret(UInt, m.max_world) +max_world(m::Method) = typemax(UInt) min_world(m::Core.MethodInstance) = reinterpret(UInt, m.min_world) max_world(m::Core.MethodInstance) = reinterpret(UInt, m.max_world) diff --git a/base/replutil.jl b/base/replutil.jl index 3827db8bd278a..33e4f461d081d 100644 --- a/base/replutil.jl +++ b/base/replutil.jl @@ -576,9 +576,6 @@ function show_method_candidates(io::IO, ex::MethodError, kwargs::Vector=Any[]) if ex.world < min_world(method) print(buf, " (method too new to be called from this world context.)") end - if ex.world > max_world(method) - print(buf, " (method deleted before this world age.)") - end # TODO: indicate if it's in the wrong world push!(lines, (buf, right_matches)) end diff --git a/src/dump.c b/src/dump.c index 3df2965305ed6..1684477413617 100644 --- a/src/dump.c +++ b/src/dump.c @@ -924,10 +924,6 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li write_int32(s->s, m->line); if (s->mode != MODE_MODULE) { write_int32(s->s, m->min_world); - write_int32(s->s, m->max_world); - } - else { - assert(m->max_world == ~(size_t)0 && "method replacement cannot be handled by incremental serializer"); } if (external_mt) jl_serialize_value(s, jl_nothing); @@ -1667,11 +1663,9 @@ static jl_value_t *jl_deserialize_value_method(jl_serializer_state *s, jl_value_ m->line = read_int32(s->s); if (s->mode != MODE_MODULE) { m->min_world = read_int32(s->s); - m->max_world = read_int32(s->s); } else { m->min_world = jl_world_counter; - m->max_world = ~(size_t)0; } m->ambig = jl_deserialize_value(s, (jl_value_t**)&m->ambig); jl_gc_wb(m, m->ambig); @@ -2204,7 +2198,6 @@ static jl_value_t *read_verify_mod_list(ios_t *s) "Requiring \"%s\" did not define a corresponding module.", name); } if (!jl_is_module(m)) { - ios_close(s); return jl_get_exceptionf(jl_errorexception_type, "Invalid module path (%s does not name a module).", name); } diff --git a/src/gf.c b/src/gf.c index de023ba2163ea..7ed522fe6e74e 100644 --- a/src/gf.c +++ b/src/gf.c @@ -142,7 +142,7 @@ static int8_t jl_cachearg_offset(jl_methtable_t *mt) // get or create the MethodInstance for a specialization JL_DLLEXPORT jl_method_instance_t *jl_specializations_get_linfo(jl_method_t *m, jl_value_t *type, jl_svec_t *sparams, size_t world) { - assert(world >= m->min_world && world <= m->max_world && "typemap lookup is corrupted"); + assert(world >= m->min_world && "typemap lookup is corrupted"); JL_LOCK(&m->writelock); jl_typemap_entry_t *sf = jl_typemap_assoc_by_type(m->specializations, (jl_tupletype_t*)type, NULL, 1, /*subtype*/0, /*offs*/0, world); @@ -163,8 +163,7 @@ JL_DLLEXPORT jl_method_instance_t *jl_specializations_get_linfo(jl_method_t *m, li->min_world = world; } if (world == jl_world_counter) { - assert(m->max_world == ~(size_t)0 && "method validity shouldn't be scheduled to terminate at a fixed future age"); - li->max_world = m->max_world; + li->max_world = ~(size_t)0; } else { li->max_world = world; @@ -350,7 +349,7 @@ JL_DLLEXPORT jl_method_instance_t* jl_set_method_inferred( } else { JL_LOCK(&li->def->writelock); - assert(min_world >= li->def->min_world && max_world <= li->def->max_world); + assert(min_world >= li->def->min_world); int isinferred = jl_is_rettype_inferred(li); if (!isinferred && li->min_world >= min_world && li->max_world <= max_world) { // expand the current (uninferred) entry to cover the full inferred range @@ -917,7 +916,7 @@ static jl_method_instance_t *cache_method(jl_methtable_t *mt, union jl_typemap_t } size_t min_valid = definition->min_world; - size_t max_valid = definition->max_world; + size_t max_valid = ~(size_t)0; int cache_with_orig = 0; jl_svec_t* guardsigs = jl_emptysvec; jl_tupletype_t *origtype = type; // backup the prior value of `type` @@ -1375,7 +1374,7 @@ JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method JL_LOCK(&mt->writelock); jl_typemap_entry_t *newentry = jl_typemap_insert(&mt->defs, (jl_value_t*)mt, (jl_tupletype_t*)type, simpletype, jl_emptysvec, (jl_value_t*)method, 0, &method_defs, - method->min_world, method->max_world, &oldvalue); + method->min_world, ~(size_t)0, &oldvalue); if (oldvalue) { method->ambig = ((jl_method_t*)oldvalue)->ambig; method_overwrite(newentry, (jl_method_t*)oldvalue); diff --git a/src/jltypes.c b/src/jltypes.c index 089a3407e0d4b..c5526a59abe17 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -1882,14 +1882,13 @@ void jl_init_types(void) jl_method_type = jl_new_datatype(jl_symbol("Method"), jl_any_type, jl_emptysvec, - jl_svec(20, + jl_svec(19, jl_symbol("name"), jl_symbol("module"), jl_symbol("file"), jl_symbol("line"), jl_symbol("sig"), jl_symbol("min_world"), - jl_symbol("max_world"), jl_symbol("ambig"), jl_symbol("specializations"), jl_symbol("sparam_syms"), @@ -1903,14 +1902,13 @@ void jl_init_types(void) jl_symbol("isva"), jl_symbol("isstaged"), jl_symbol("pure")), - jl_svec(20, + jl_svec(19, jl_sym_type, jl_module_type, jl_sym_type, jl_int32_type, jl_type_type, jl_long_type, - jl_long_type, jl_any_type, // Union{Array, Void} jl_any_type, // TypeMap jl_simplevector_type, @@ -1924,7 +1922,7 @@ void jl_init_types(void) jl_bool_type, jl_bool_type, jl_bool_type), - 0, 1, 10); + 0, 1, 9); jl_method_instance_type = jl_new_datatype(jl_symbol("MethodInstance"), diff --git a/src/julia.h b/src/julia.h index f5efda7e378c7..db2fda638b455 100644 --- a/src/julia.h +++ b/src/julia.h @@ -231,7 +231,6 @@ typedef struct _jl_method_t { // method's type signature. redundant with TypeMapEntry->specTypes jl_value_t *sig; size_t min_world; - size_t max_world; // list of potentially-ambiguous methods (nothing = none, Vector{Any} of Methods otherwise) jl_value_t *ambig; diff --git a/src/method.c b/src/method.c index e48158b9727ee..65caef3a10986 100644 --- a/src/method.c +++ b/src/method.c @@ -362,7 +362,7 @@ jl_method_instance_t *jl_get_specialized(jl_method_t *m, jl_value_t *types, jl_s new_linfo->specTypes = types; new_linfo->sparam_vals = sp; new_linfo->min_world = m->min_world; - new_linfo->max_world = m->max_world; + new_linfo->max_world = ~(size_t)0; return new_linfo; } @@ -435,7 +435,6 @@ JL_DLLEXPORT jl_method_t *jl_new_method_uninit(void) m->nargs = 0; m->traced = 0; m->min_world = 1; - m->max_world = ~(size_t)0; JL_MUTEX_INIT(&m->writelock); return m; } From 5e709e46458f8a1cc566d75718b385a63ac9d917 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 6 Apr 2017 16:20:21 -0400 Subject: [PATCH 0392/1534] improve correctness of incremental precompile deserialized edges previously we just assumed that the user didn't load any other code now this actually keeps track of which method would have been visible in the precompilation process --- src/dump.c | 104 +++++++++++++++++++++++++++++++++++++++++---------- src/gf.c | 9 ++++- src/julia.h | 1 + src/module.c | 4 +- 4 files changed, 97 insertions(+), 21 deletions(-) diff --git a/src/dump.c b/src/dump.c index 1684477413617..007e75860f3ac 100644 --- a/src/dump.c +++ b/src/dump.c @@ -1833,6 +1833,7 @@ static jl_value_t *jl_deserialize_value_module(jl_serializer_state *s) } m->istopmod = read_uint8(s->s); m->uuid = read_uint64(s->s); + m->primary_world = jl_world_counter; m->counter = read_int32(s->s); return (jl_value_t*)m; } @@ -2128,6 +2129,7 @@ static void jl_insert_methods(linkedlist_t *list) } } +void jl_method_instance_delete(jl_method_instance_t *mi); static void jl_insert_backedges(linkedlist_t *list) { while (list) { @@ -2138,7 +2140,11 @@ static void jl_insert_backedges(linkedlist_t *list) assert(jl_is_method_instance(caller)); jl_value_t *callee = list->def[i].callee; if (jl_is_method_instance(callee)) { - jl_method_instance_add_backedge((jl_method_instance_t*)callee, caller); + jl_method_instance_t *callee_mi = (jl_method_instance_t*)callee; + if (callee_mi->max_world == ~(size_t)0) + jl_method_instance_add_backedge(callee_mi, caller); + else + jl_method_instance_delete(caller); } else { jl_datatype_t *gf = jl_first_argument_datatype(callee); @@ -2161,7 +2167,12 @@ static void free_linkedlist(linkedlist_t *list) } } -static jl_value_t *read_verify_mod_list(ios_t *s) +static int size_isgreater(const void *a, const void *b) +{ + return *(size_t*)b - *(size_t*)a; +} + +static jl_value_t *read_verify_mod_list(ios_t *s, arraylist_t *dependent_worlds) { if (!jl_main_module->uuid) { return jl_get_exceptionf(jl_errorexception_type, @@ -2205,6 +2216,8 @@ static jl_value_t *read_verify_mod_list(ios_t *s) return jl_get_exceptionf(jl_errorexception_type, "Module %s uuid did not match cache file.", name); } + if (m->primary_world > jl_main_module->primary_world) + arraylist_push(dependent_worlds, (void*)m->primary_world); } } @@ -2381,6 +2394,7 @@ static void jl_save_system_image_to_stream(ios_t *f) NULL, NULL, jl_get_ptls_states() }; + write_int32(f, jl_world_counter); // orphan old Base module if present jl_base_module = (jl_module_t*)jl_get_global(jl_main_module, jl_symbol("Base")); @@ -2427,7 +2441,6 @@ static void jl_save_system_image_to_stream(ios_t *f) write_int32(f, jl_get_t_uid_ctr()); write_int32(f, jl_get_gs_ctr()); - write_int32(f, jl_world_counter); jl_finalize_serializer(&s); // done with f and s htable_reset(&backref_table, 0); @@ -2498,6 +2511,7 @@ static void jl_restore_system_image_from_stream(ios_t *f) NULL, NULL, jl_get_ptls_states() }; + jl_world_counter = read_int32(f); jl_main_module = (jl_module_t*)jl_deserialize_value(&s, NULL); jl_top_module = (jl_module_t*)jl_deserialize_value(&s, NULL); @@ -2516,7 +2530,7 @@ static void jl_restore_system_image_from_stream(ios_t *f) jl_module_type->name->mt = (jl_methtable_t*)jl_deserialize_value(&s, NULL); intptr_t i; - for(i=0; i < builtin_typenames.len; i++) { + for (i = 0; i < builtin_typenames.len; i++) { jl_typename_t *tn = (jl_typename_t*)builtin_typenames.items[i]; tn->cache = (jl_svec_t*)jl_deserialize_value(&s, NULL); jl_gc_wb(tn, tn->cache); tn->linearcache = (jl_svec_t*)jl_deserialize_value(&s, NULL); jl_gc_wb(tn, tn->linearcache); @@ -2538,7 +2552,6 @@ static void jl_restore_system_image_from_stream(ios_t *f) int uid_ctr = read_int32(f); int gs_ctr = read_int32(f); - jl_world_counter = read_int32(f); jl_module_init_order = jl_finalize_deserializer(&s, NULL); // done with s and f jl_set_t_uid_ctr(uid_ctr); @@ -2992,26 +3005,72 @@ static void jl_update_backref_list(jl_value_t *old, jl_value_t *_new, size_t sta } } -jl_method_t *jl_recache_method(jl_method_t *m, size_t start) +static size_t lowerbound_dependent_world_set(size_t world, arraylist_t *dependent_worlds) +{ + size_t i, l = dependent_worlds->len; + for (i = 0; i < l; i++) { + size_t depworld = (size_t)dependent_worlds->items[i]; + if (depworld <= world) + return depworld; + } + return jl_main_module->primary_world; +} + +// repeated look up older methods until we come to one that existed +// at the time this module was serialized +static jl_method_t *jl_lookup_method_worldset(jl_methtable_t *mt, jl_datatype_t *sig, arraylist_t *dependent_worlds) +{ + size_t world = jl_world_counter; + jl_method_t *_new; + while (1) { + _new = (jl_method_t*)jl_methtable_lookup(mt, sig, world); + assert(_new && jl_is_method(_new)); + if (_new->min_world == jl_world_counter) + return _new; + if (_new->min_world <= jl_main_module->primary_world) + return _new; + world = lowerbound_dependent_world_set(_new->min_world, dependent_worlds); + if (world == _new->min_world) + return _new; + } +} + +// repeated look up older methods until we come to one that was valid +// at the time this module was serialized +static jl_method_instance_t *jl_lookup_methodinstance_worldset(jl_method_t *m, jl_datatype_t *argtypes, jl_svec_t *env, arraylist_t *dependent_worlds) +{ + size_t world = jl_world_counter; + jl_method_instance_t *_new; + while (1) { + _new = jl_specializations_get_linfo(m, (jl_value_t*)argtypes, env, world); + if (_new->min_world == jl_world_counter) + return _new; + if (_new->min_world <= jl_main_module->primary_world) + return _new; + world = lowerbound_dependent_world_set(_new->min_world, dependent_worlds); + if (world == _new->min_world) + return _new; + } +} + +static jl_method_t *jl_recache_method(jl_method_t *m, size_t start, arraylist_t *dependent_worlds) { jl_datatype_t *sig = (jl_datatype_t*)m->sig; jl_datatype_t *ftype = jl_first_argument_datatype((jl_value_t*)sig); jl_methtable_t *mt = ftype->name->mt; jl_set_typeof(m, (void*)(intptr_t)0x30); // invalidate the old value to help catch errors - jl_method_t *_new = (jl_method_t*)jl_methtable_lookup(mt, sig, /*TODO*/jl_world_counter); - assert(_new && jl_is_method(_new)); + jl_method_t *_new = jl_lookup_method_worldset(mt, sig, dependent_worlds); jl_update_backref_list((jl_value_t*)m, (jl_value_t*)_new, start); return _new; } -jl_method_instance_t *jl_recache_method_instance(jl_method_instance_t *li, size_t start) +static jl_method_instance_t *jl_recache_method_instance(jl_method_instance_t *li, size_t start, arraylist_t *dependent_worlds) { jl_datatype_t *sig = (jl_datatype_t*)li->def; assert(jl_is_datatype(sig) || jl_is_unionall(sig)); jl_datatype_t *ftype = jl_first_argument_datatype((jl_value_t*)sig); jl_methtable_t *mt = ftype->name->mt; - jl_method_t *m = (jl_method_t*)jl_methtable_lookup(mt, sig, /*TODO*/jl_world_counter); - assert(m && jl_is_method(m)); + jl_method_t *m = jl_lookup_method_worldset(mt, sig, dependent_worlds); jl_datatype_t *argtypes = (jl_datatype_t*)li->specTypes; jl_set_typeof(li, (void*)(intptr_t)0x40); // invalidate the old value to help catch errors @@ -3020,12 +3079,12 @@ jl_method_instance_t *jl_recache_method_instance(jl_method_instance_t *li, size_ //assert(ti != jl_bottom_type); (void)ti; if (ti == jl_bottom_type) env = jl_emptysvec; // the intersection may fail now if the type system had made an incorrect subtype env in the past - jl_method_instance_t *_new = jl_specializations_get_linfo(m, (jl_value_t*)argtypes, env, /*TODO*/jl_world_counter); + jl_method_instance_t *_new = jl_lookup_methodinstance_worldset(m, argtypes, env, dependent_worlds); jl_update_backref_list((jl_value_t*)li, (jl_value_t*)_new, start); return _new; } -static void jl_recache_other(void) +static void jl_recache_other(arraylist_t *dependent_worlds) { size_t i = 0; while (i < flagref_list.len) { @@ -3035,11 +3094,11 @@ static void jl_recache_other(void) i += 2; if (jl_is_method(o)) { // lookup the real Method based on the placeholder sig - _new = (jl_value_t*)jl_recache_method((jl_method_t*)o, i); + _new = (jl_value_t*)jl_recache_method((jl_method_t*)o, i, dependent_worlds); } else if (jl_is_method_instance(o)) { // lookup the real MethodInstance based on the placeholder specTypes - _new = (jl_value_t*)jl_recache_method_instance((jl_method_instance_t*)o, i); + _new = (jl_value_t*)jl_recache_method_instance((jl_method_instance_t*)o, i, dependent_worlds); } else { abort(); @@ -3075,9 +3134,14 @@ static jl_value_t *_jl_restore_incremental(ios_t *f) ios_skip(f, deplen); } + // list of world counters of incremental dependencies + arraylist_t dependent_worlds; + arraylist_new(&dependent_worlds, 0); + // verify that the system state is valid - jl_value_t *verify_error = read_verify_mod_list(f); + jl_value_t *verify_error = read_verify_mod_list(f, &dependent_worlds); if (verify_error) { + arraylist_free(&dependent_worlds); ios_close(f); return verify_error; } @@ -3086,6 +3150,7 @@ static jl_value_t *_jl_restore_incremental(ios_t *f) arraylist_new(&backref_list, 4000); arraylist_push(&backref_list, jl_main_module); arraylist_new(&flagref_list, 0); + qsort(dependent_worlds.items, dependent_worlds.len, sizeof(size_t), size_isgreater); int en = jl_gc_enable(0); ++jl_world_counter; // reserve a world age for the deserialization @@ -3112,17 +3177,18 @@ static jl_value_t *_jl_restore_incremental(ios_t *f) jl_recache_types(); // make all of the types identities correct init_order = jl_finalize_deserializer(&s, tracee_list); // done with f and s (needs to be after recache types) jl_insert_methods(&external_methods); // hook up methods of external generic functions (needs to be after recache types) - jl_recache_other(); // make all of the other objects identities correct (needs to be after insert methods) + jl_recache_other(&dependent_worlds); // make all of the other objects identities correct (needs to be after insert methods) jl_insert_backedges(&external_methods); // restore external backedges (needs to be after recache other) free_linkedlist(external_methods.next); serializer_worklist = NULL; - JL_GC_PUSH2(&init_order, &restored); - jl_gc_enable(en); arraylist_free(&flagref_list); arraylist_free(&backref_list); + arraylist_free(&dependent_worlds); ios_close(f); + JL_GC_PUSH2(&init_order, &restored); + jl_gc_enable(en); if (tracee_list) { jl_methtable_t *mt; while ((mt = (jl_methtable_t*)arraylist_pop(tracee_list)) != NULL) diff --git a/src/gf.c b/src/gf.c index 7ed522fe6e74e..31adb4e020b6a 100644 --- a/src/gf.c +++ b/src/gf.c @@ -1246,7 +1246,7 @@ static void invalidate_method_instance(jl_method_instance_t *replaced, size_t ma jl_array_t *backedges = replaced->backedges; if (replaced->max_world > max_world) { // recurse to all backedges to update their valid range also - assert(replaced->min_world <= max_world && "attempting to set invalid world constraints"); + assert(replaced->min_world - 1 <= max_world && "attempting to set invalid world constraints"); if (JL_DEBUG_METHOD_INVALIDATION) { int d0 = depth; while (d0-- > 0) @@ -1361,6 +1361,13 @@ JL_DLLEXPORT void jl_method_table_add_backedge(jl_methtable_t *mt, jl_value_t *t JL_UNLOCK(&mt->writelock); } +void jl_method_instance_delete(jl_method_instance_t *mi) +{ + invalidate_method_instance(mi, mi->min_world - 1, 0); + if (JL_DEBUG_METHOD_INVALIDATION) + jl_uv_puts(JL_STDOUT, "<<<\n", 4); +} + JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method, jl_tupletype_t *simpletype) { assert(jl_is_method(method)); diff --git a/src/julia.h b/src/julia.h index db2fda638b455..f9c520c0d4c59 100644 --- a/src/julia.h +++ b/src/julia.h @@ -405,6 +405,7 @@ typedef struct _jl_module_t { arraylist_t usings; // modules with all bindings potentially imported uint8_t istopmod; uint64_t uuid; + size_t primary_world; uint32_t counter; } jl_module_t; diff --git a/src/module.c b/src/module.c index 4225ce5eaa0f9..ec64c58dcc866 100644 --- a/src/module.c +++ b/src/module.c @@ -29,7 +29,9 @@ JL_DLLEXPORT jl_module_t *jl_new_module(jl_sym_t *name) m->istopmod = 0; static unsigned int mcounter; // simple counter backup, in case hrtime is not incrementing m->uuid = jl_hrtime() + (++mcounter); - if (!m->uuid) m->uuid++; // uuid 0 is invalid + if (!m->uuid) + m->uuid++; // uuid 0 is invalid + m->primary_world = 0; m->counter = 0; htable_new(&m->bindings, 0); arraylist_new(&m->usings, 0); From 8d16ddda75cfe26fdf8e1a9fea589d8170fe9585 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 6 Apr 2017 19:06:18 -0400 Subject: [PATCH 0393/1534] add many missing backedges getting lost during incremental deserialization we need to restore not only backedges directly to the new methods, but also to any methods whos backedges have not been inferred but which might propagate invalidation changes to the new code fix #21141 --- src/dump.c | 153 +++++++++++++++++++++++++++++++++++++----------- test/compile.jl | 47 ++++++++++++++- 2 files changed, 164 insertions(+), 36 deletions(-) diff --git a/src/dump.c b/src/dump.c index 007e75860f3ac..d482cd3cf5cdc 100644 --- a/src/dump.c +++ b/src/dump.c @@ -62,6 +62,10 @@ static arraylist_t reinit_list; // (only used by the incremental serializer in MODE_MODULE) static jl_array_t *serializer_worklist; +// inverse of backedges tree +// (only used by the incremental serializer in MODE_MODULE) +htable_t edges_map; + // list of modules being deserialized with __init__ methods // (not used in MODE_AST) jl_array_t *jl_module_init_order; @@ -1152,30 +1156,42 @@ static void jl_serialize_missing_backedges_to_mod(jl_serializer_state *s, jl_met size_t i, l = jl_array_len(backedges); for (i = 1; i < l; i += 2) { jl_method_instance_t *caller = (jl_method_instance_t*)jl_array_ptr_ref(backedges, i); - if (caller->max_world == ~(size_t)0 && module_in_worklist(caller->def->module)) { - jl_serialize_value(s, caller); - jl_serialize_value(s, jl_array_ptr_ref(backedges, i - 1)); + if (caller->max_world == ~(size_t)0) { + jl_value_t *missing_callee = jl_array_ptr_ref(backedges, i - 1); + jl_array_t **edges = (jl_array_t**)ptrhash_bp(&edges_map, (void*)caller); + if (*edges == HT_NOTFOUND) + *edges = jl_alloc_vec_any(0); + jl_array_ptr_1d_push(*edges, missing_callee); } } } } -static int jl_serialize_backedges_to_mod(jl_typemap_entry_t *ml, void *closure) +// the intent of this function is to invert the backedges tree +static void serialize_backedges(jl_method_instance_t *callee) { - jl_serializer_state *s = (jl_serializer_state*)closure; - jl_method_instance_t *callee = ml->func.linfo; jl_array_t *backedges = callee->backedges; if (backedges) { assert(callee->max_world == ~(size_t)0); size_t i, l = jl_array_len(backedges); for (i = 0; i < l; i++) { jl_method_instance_t *caller = (jl_method_instance_t*)jl_array_ptr_ref(backedges, i); - if (caller->max_world == ~(size_t)0 && module_in_worklist(caller->def->module)) { - jl_serialize_value(s, caller); - jl_serialize_value(s, callee); + if (caller->max_world == ~(size_t)0) { + jl_array_t **edges = (jl_array_t**)ptrhash_bp(&edges_map, caller); + if (*edges == HT_NOTFOUND) + *edges = jl_alloc_vec_any(0); + jl_array_ptr_1d_push(*edges, (jl_value_t*)callee); } } } +} + + +static int jl_serialize_backedges_to_mod(jl_typemap_entry_t *ml, void *closure) +{ + (void)(jl_serializer_state*)closure; + jl_method_instance_t *callee = ml->func.linfo; + serialize_backedges(callee); return 1; } @@ -1233,6 +1249,36 @@ static void jl_serialize_lambdas_from_mod(jl_serializer_state *s, jl_module_t *m } } +static void jl_serialize_backedges(jl_serializer_state *s) +{ + arraylist_t worklist; + arraylist_new(&worklist, 0); + size_t i; + void **table = edges_map.table; + for (i = 0; i < edges_map.size; i += 2) { + jl_method_instance_t *caller = (jl_method_instance_t*)table[i]; + jl_array_t *callee = (jl_array_t*)table[i + 1]; + if (callee != HT_NOTFOUND && module_in_worklist(caller->def->module)) { + arraylist_push(&worklist, (void*)caller); + } + } + while (worklist.len) { + jl_method_instance_t *caller = (jl_method_instance_t*)arraylist_pop(&worklist); + jl_array_t **pcallee = (jl_array_t**)ptrhash_bp(&edges_map, (void*)caller), + *callee = *pcallee; + if (callee != HT_NOTFOUND) { + jl_serialize_value(s, caller); + jl_serialize_value(s, callee); + *pcallee = HT_NOTFOUND; + for (i = 0; i < jl_array_len(callee); i++) { + jl_value_t *c = jl_array_ptr_ref(callee, i); + if (jl_is_method_instance(c)) + arraylist_push(&worklist, (void*)c); + } + } + } +} + // serialize information about all of the modules accessible directly from Main static void write_mod_list(ios_t *s) { @@ -2084,7 +2130,7 @@ typedef struct _linkedlist_t { }; struct { jl_method_instance_t *caller; - jl_value_t *callee; + jl_array_t *callee; }; } def[100]; size_t count; @@ -2118,12 +2164,11 @@ static void jl_insert_methods(linkedlist_t *list) while (list) { size_t i; for (i = 0; i < list->count; i++) { - if (jl_is_method(list->def[i].meth)) { - jl_method_t *meth = list->def[i].meth; - jl_datatype_t *gf = jl_first_argument_datatype((jl_value_t*)meth->sig); - assert(jl_is_datatype(gf) && gf->name->mt); - jl_method_table_insert(gf->name->mt, meth, list->def[i].simpletype); - } + assert(jl_is_method(list->def[i].meth)); + jl_method_t *meth = list->def[i].meth; + jl_datatype_t *gf = jl_first_argument_datatype((jl_value_t*)meth->sig); + assert(jl_is_datatype(gf) && gf->name->mt); + jl_method_table_insert(gf->name->mt, meth, list->def[i].simpletype); } list = list->next; } @@ -2133,23 +2178,56 @@ void jl_method_instance_delete(jl_method_instance_t *mi); static void jl_insert_backedges(linkedlist_t *list) { while (list) { - size_t i; + size_t i, j; for (i = 0; i < list->count; i++) { - if (!jl_is_method(list->def[i].meth)) { - jl_method_instance_t *caller = list->def[i].caller; - assert(jl_is_method_instance(caller)); - jl_value_t *callee = list->def[i].callee; - if (jl_is_method_instance(callee)) { - jl_method_instance_t *callee_mi = (jl_method_instance_t*)callee; - if (callee_mi->max_world == ~(size_t)0) - jl_method_instance_add_backedge(callee_mi, caller); - else - jl_method_instance_delete(caller); - } - else { - jl_datatype_t *gf = jl_first_argument_datatype(callee); - assert(jl_is_datatype(gf) && gf->name->mt); - jl_method_table_add_backedge(gf->name->mt, callee, (jl_value_t*)caller); + jl_method_instance_t *caller = list->def[i].caller; + assert(jl_is_method_instance(caller)); + jl_array_t *callees = list->def[i].callee; + assert(jl_is_array(callees)); + if (!caller->inferred || module_in_worklist(caller->def->module)) { + for (j = 0; j < jl_array_len(callees); j++) { + jl_value_t *callee = jl_array_ptr_ref(callees, j); + if (jl_is_method_instance(callee)) { + jl_method_instance_t *callee_mi = (jl_method_instance_t*)callee; + if (!module_in_worklist(callee_mi->def->module)) { + // verify that this MethodInstance is still the correct lookup for this callee sig + jl_value_t *sig = callee_mi->specTypes; + jl_method_t *m = NULL; + if (jl_is_datatype(sig)) { + jl_datatype_t *ftype = jl_first_argument_datatype(sig); + jl_methtable_t *mt = ftype->name->mt; + jl_typemap_entry_t *entry = jl_typemap_assoc_by_type( + mt->defs, (jl_datatype_t*)sig, + NULL, /*inexact*/0, /*subtype*/1, 0, jl_world_counter); + if (entry != NULL) + m = entry->func.method; + } + if (m != callee_mi->def) { + // probably no good, just invalidate everything now + jl_method_instance_delete(caller); + break; + } + } + if (callee_mi->max_world == ~(size_t)0) { + // if this callee is still valid, just add a backedge + jl_method_instance_add_backedge(callee_mi, caller); + } + else if (caller->min_world == jl_world_counter) { + // if this caller was just added, delete everything associated with it + jl_method_instance_delete(caller); + break; + } + else { + // the caller must have been something pre-existing + // assume that it'll take care of deleting the deserialized code + // whenever we process it here + } + } + else { + jl_datatype_t *gf = jl_first_argument_datatype(callee); + assert(jl_is_datatype(gf) && gf->name->mt); + jl_method_table_add_backedge(gf->name->mt, callee, (jl_value_t*)caller); + } } } } @@ -2800,6 +2878,7 @@ JL_DLLEXPORT int jl_save_incremental(const char *fname, jl_array_t *worklist) // best to keep it early (before any actual initialization) arraylist_new(&reinit_list, 0); + htable_new(&edges_map, 0); htable_new(&backref_table, 5000); ptrhash_put(&backref_table, jl_main_module, (char*)HT_NOTFOUND + 1); backref_table_numel = 1; @@ -2814,10 +2893,13 @@ JL_DLLEXPORT int jl_save_incremental(const char *fname, jl_array_t *worklist) jl_serialize_value(&s, worklist); jl_serialize_lambdas_from_mod(&s, jl_main_module); jl_serialize_value(&s, NULL); // signal end of lambdas + jl_serialize_backedges(&s); + jl_serialize_value(&s, NULL); // signal end of backedges jl_finalize_serializer(&s); // done with f serializer_worklist = NULL; jl_gc_enable(en); + htable_reset(&edges_map, 0); htable_reset(&backref_table, 0); arraylist_free(&reinit_list); ios_close(&f); @@ -3016,7 +3098,7 @@ static size_t lowerbound_dependent_world_set(size_t world, arraylist_t *dependen return jl_main_module->primary_world; } -// repeated look up older methods until we come to one that existed +// repeatedly look up older methods until we come to one that existed // at the time this module was serialized static jl_method_t *jl_lookup_method_worldset(jl_methtable_t *mt, jl_datatype_t *sig, arraylist_t *dependent_worlds) { @@ -3167,6 +3249,8 @@ static jl_value_t *_jl_restore_incremental(ios_t *f) // get list of external generic functions linkedlist_t external_methods; jl_deserialize_methods_from_mod(&s, &external_methods); + linkedlist_t external_backedges; + jl_deserialize_methods_from_mod(&s, &external_backedges); arraylist_t *tracee_list = NULL; if (jl_newmeth_tracer) @@ -3178,8 +3262,9 @@ static jl_value_t *_jl_restore_incremental(ios_t *f) init_order = jl_finalize_deserializer(&s, tracee_list); // done with f and s (needs to be after recache types) jl_insert_methods(&external_methods); // hook up methods of external generic functions (needs to be after recache types) jl_recache_other(&dependent_worlds); // make all of the other objects identities correct (needs to be after insert methods) - jl_insert_backedges(&external_methods); // restore external backedges (needs to be after recache other) + jl_insert_backedges(&external_backedges); // restore external backedges (needs to be after recache other) free_linkedlist(external_methods.next); + free_linkedlist(external_backedges.next); serializer_worklist = NULL; arraylist_free(&flagref_list); diff --git a/test/compile.jl b/test/compile.jl index 91b0f1e4192f8..0e058899537f5 100644 --- a/test/compile.jl +++ b/test/compile.jl @@ -3,6 +3,7 @@ using Base.Test Foo_module = :Foo4b3a94a1a081a8cb +Foo2_module = :F2oo4b3a94a1a081a8cb FooBase_module = :FooBase4b3a94a1a081a8cb @eval module ConflictingBindings export $Foo_module, $FooBase_module @@ -21,6 +22,7 @@ insert!(LOAD_PATH, 1, dir) insert!(Base.LOAD_CACHE_PATH, 1, dir) try Foo_file = joinpath(dir, "$Foo_module.jl") + Foo2_file = joinpath(dir, "$Foo2_module.jl") FooBase_file = joinpath(dir, "$FooBase_module.jl") write(FooBase_file, @@ -30,12 +32,23 @@ try module $FooBase_module end """) + write(Foo2_file, + """ + __precompile__(true) + + module $Foo2_module + export override + override(x::Integer) = 2 + override(x::AbstractFloat) = Float64(override(1)) + end + """) write(Foo_file, """ __precompile__(true) module $Foo_module using $FooBase_module + import $Foo2_module: $Foo2_module, override # test that docs get reconnected @doc "foo function" foo(x) = x + 1 @@ -109,6 +122,9 @@ try ccall(:jl_specializations_get_linfo, Ref{Core.MethodInstance}, (Any, Any, Any, UInt), some_method, Tuple{typeof(Base.include), String}, Core.svec(), typemax(UInt)) end + + g() = override(1.0) + Base.Test.@test g() === 2.0 # compile this end """) @test_throws ErrorException Core.kwfunc(Base.nothing) # make sure `nothing` didn't have a kwfunc (which would invalidate the attempted test) @@ -116,9 +132,29 @@ try # Issue #12623 @test __precompile__(true) === nothing + # Issue #21307 + Base.require(Foo2_module) + @eval let Foo2_module = $(QuoteNode(Foo2_module)), # use @eval to see the results of loading the compile + Foo = getfield(Main, Foo2_module) + Foo.override(::Int) = 'a' + Foo.override(::Float32) = 'b' + end + Base.require(Foo_module) - cachefile = joinpath(dir, "$Foo_module.ji") + @eval let Foo_module = $(QuoteNode(Foo_module)), # use @eval to see the results of loading the compile + Foo = getfield(Main, Foo_module) + @test Foo.foo(17) == 18 + @test Foo.Bar.bar(17) == 19 + + # Issue #21307 + @test Foo.g() === 97.0 + @test Foo.override(1.0e0) == Float64('a') + @test Foo.override(1.0f0) == 'b' + @test Foo.override(UInt(1)) == 2 + end + + cachefile = joinpath(dir, "$Foo_module.ji") # use _require_from_serialized to ensure that the test fails if # the module doesn't reload from the image: @test_warn "WARNING: replacing module Foo4b3a94a1a081a8cb.\nWARNING: Method definition " begin @@ -129,6 +165,7 @@ try @test_throws MethodError Foo.foo(17) # world shouldn't be visible yet end @eval let Foo_module = $(QuoteNode(Foo_module)), # use @eval to see the results of loading the compile + Foo2_module = $(QuoteNode(Foo2_module)), FooBase_module = $(QuoteNode(FooBase_module)), Foo = getfield(Main, Foo_module), dir = $(QuoteNode(dir)), @@ -137,6 +174,12 @@ try @test Foo.foo(17) == 18 @test Foo.Bar.bar(17) == 19 + # Issue #21307 + @test Foo.g() === 97.0 + @test Foo.override(1.0e0) == Float64('a') + @test Foo.override(1.0f0) == 'b' + @test Foo.override(UInt(1)) == 2 + # issue #12284: @test stringmime("text/plain", Base.Docs.doc(Foo.foo)) == "foo function\n" @test stringmime("text/plain", Base.Docs.doc(Foo.Bar.bar)) == "bar function\n" @@ -147,7 +190,7 @@ try modules, deps1 = Base.cache_dependencies(cachefile) @test sort(modules) == Any[(s, Base.module_uuid(getfield(Foo, s))) for s in - [:Base, :Core, FooBase_module, :Main]] + [:Base, :Core, Foo2_module, FooBase_module, :Main]] @test deps == deps1 @test current_task()(0x01, 0x4000, 0x30031234) == 2 From 64dbcbc2279d247145a89adb1b2c1c79c281ee39 Mon Sep 17 00:00:00 2001 From: Fengyang Wang Date: Tue, 11 Apr 2017 16:13:48 -0400 Subject: [PATCH 0394/1534] Fix #21325, use special version of eltype (#21328) * Fix #21325, use special version of eltype --- base/broadcast.jl | 36 +++++++++++++++++++++++++++++------- base/nullable.jl | 6 ------ test/broadcast.jl | 15 +++++++++++++++ 3 files changed, 44 insertions(+), 13 deletions(-) diff --git a/base/broadcast.jl b/base/broadcast.jl index 1d429ba4ffa99..53927084de7f9 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -5,7 +5,7 @@ module Broadcast using Base.Cartesian using Base: linearindices, tail, OneTo, to_shape, _msk_end, unsafe_bitgetindex, bitcache_chunks, bitcache_size, dumpbitcache, - nullable_returntype, null_safe_eltype_op, hasvalue, isoperator + nullable_returntype, null_safe_op, hasvalue, isoperator import Base: broadcast, broadcast! export broadcast_getindex, broadcast_setindex!, dotview, @__dot__ @@ -51,6 +51,7 @@ broadcast_indices(::Type{Tuple}, A) = (OneTo(length(A)),) broadcast_indices(::Type{Array}, A::Ref) = () broadcast_indices(::Type{Array}, A) = indices(A) @inline broadcast_indices(A, B...) = broadcast_shape((), broadcast_indices(A), map(broadcast_indices, B)...) + # shape (i.e., tuple-of-indices) inputs broadcast_shape(shape::Tuple) = shape @inline broadcast_shape(shape::Tuple, shape1::Tuple, shapes::Tuple...) = broadcast_shape(_bcs((), shape, shape1), shapes...) @@ -279,10 +280,30 @@ end return C end -eltypestuple(a) = (Base.@_pure_meta; Tuple{eltype(a)}) -eltypestuple(T::Type) = (Base.@_pure_meta; Tuple{Type{T}}) -eltypestuple(a, b...) = (Base.@_pure_meta; Tuple{eltypestuple(a).types..., eltypestuple(b...).types...}) -_broadcast_eltype(f, A, Bs...) = Base._return_type(f, eltypestuple(A, Bs...)) +maptoTuple(f) = Tuple{} +maptoTuple(f, a, b...) = Tuple{f(a), maptoTuple(f, b...).types...} + +# An element type satisfying for all A: +# broadcast_getindex( +# containertype(A), +# A, broadcast_indices(A) +# )::_broadcast_getindex_eltype(A) +_broadcast_getindex_eltype(A) = _broadcast_getindex_eltype(containertype(A), A) +_broadcast_getindex_eltype(::ScalarType, T::Type) = Type{T} +_broadcast_getindex_eltype(::ScalarType, A) = typeof(A) +_broadcast_getindex_eltype(::Any, A) = eltype(A) # Tuple, Array, etc. + +# An element type satisfying for all A: +# unsafe_get(A)::unsafe_get_eltype(A) +_unsafe_get_eltype(x::Nullable) = eltype(x) +_unsafe_get_eltype(T::Type) = Type{T} +_unsafe_get_eltype(x) = typeof(x) + +# Inferred eltype of result of broadcast(f, xs...) +_broadcast_eltype(f, A, As...) = + Base._return_type(f, maptoTuple(_broadcast_getindex_eltype, A, As...)) +_nullable_eltype(f, A, As...) = + Base._return_type(f, maptoTuple(_unsafe_get_eltype, A, As...)) # broadcast methods that dispatch on the type of the final container @inline function broadcast_c(f, ::Type{Array}, A, Bs...) @@ -299,8 +320,9 @@ _broadcast_eltype(f, A, Bs...) = Base._return_type(f, eltypestuple(A, Bs...)) end @inline function broadcast_c(f, ::Type{Nullable}, a...) nonnull = all(hasvalue, a) - S = _broadcast_eltype(f, a...) - if isleaftype(S) && null_safe_eltype_op(f, a...) + S = _nullable_eltype(f, a...) + if isleaftype(S) && null_safe_op(f, maptoTuple(_unsafe_get_eltype, + a...).types...) Nullable{S}(f(map(unsafe_get, a)...), nonnull) else if nonnull diff --git a/base/nullable.jl b/base/nullable.jl index c27804abd895f..2d81ebdbfe569 100644 --- a/base/nullable.jl +++ b/base/nullable.jl @@ -188,12 +188,6 @@ const EqualOrLess = Union{typeof(isequal), typeof(isless)} null_safe_op{T}(::typeof(identity), ::Type{T}) = isbits(T) -eltypes() = Tuple{} -eltypes(x, xs...) = Tuple{eltype(x), eltypes(xs...).parameters...} - -@pure null_safe_eltype_op(op, xs...) = - null_safe_op(op, eltypes(xs...).parameters...) - null_safe_op(f::EqualOrLess, ::NullSafeTypes, ::NullSafeTypes) = true null_safe_op{S,T}(f::EqualOrLess, ::Type{Rational{S}}, ::Type{T}) = null_safe_op(f, T, S) diff --git a/test/broadcast.jl b/test/broadcast.jl index 1648eb52eabfa..a9a25093a4c2b 100644 --- a/test/broadcast.jl +++ b/test/broadcast.jl @@ -495,6 +495,21 @@ end @test all(A[1:3,1:3] .== [ones(2,2)]) end +# Test that broadcast does not confuse eltypes. See also +# https://github.com/JuliaLang/julia/issues/21325 +@testset "eltype confusion (#21325)" begin + foo(x::Char, y::Int) = 0 + foo(x::String, y::Int) = "hello" + @test broadcast(foo, "x", [1, 2, 3]) == ["hello", "hello", "hello"] + + @test isequal( + [Set([1]), Set([2])] .∪ Set([3]), + [Set([1, 3]), Set([2, 3])]) + + @test isequal(@inferred(broadcast(foo, "world", Nullable(1))), + Nullable("hello")) +end + # Issue #21291 let t = (0, 1, 2) o = 1 From b7836db4527e07a07d2415a8780294e9067a1f97 Mon Sep 17 00:00:00 2001 From: traktofon Date: Wed, 12 Apr 2017 04:16:56 +0800 Subject: [PATCH 0395/1534] Add bswap method for complex numbers. (#21346) It byte-swaps the real and imaginary parts individually, following what Fortran compilers do. The tests read the binary test data from an ad-hoc IOBuffer, because reinterpret doesn't work for complex numbers. --- base/complex.jl | 3 +++ test/numbers.jl | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/base/complex.jl b/base/complex.jl index 4a1ae9ed210e1..7e5ed0874c609 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -167,6 +167,9 @@ function write(s::IO, z::Complex) write(s,real(z),imag(z)) end +## byte order swaps: real and imaginary part are swapped individually +bswap(z::Complex) = Complex(bswap(real(z)), bswap(imag(z))) + ## equality and hashing of complex numbers ## ==(z::Complex, w::Complex) = (real(z) == real(w)) & (imag(z) == imag(w)) diff --git a/test/numbers.jl b/test/numbers.jl index f926085912ba3..738d22dfb6f6e 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -2491,6 +2491,13 @@ end @test reinterpret(Float32,bswap(0x0000c03f)) === 1.5f0 @test bswap(reinterpret(Float64,0x000000000000f03f)) === 1.0 @test bswap(reinterpret(Float32,0x0000c03f)) === 1.5f0 +zbuf = IOBuffer([0xbf, 0xc0, 0x00, 0x00, 0x40, 0x20, 0x00, 0x00, + 0x40, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) +z1 = read(zbuf, Complex64) +z2 = read(zbuf, Complex128) +@test bswap(z1) === -1.5f0 + 2.5f0im +@test bswap(z2) === 3.5 - 4.5im #isreal(x::Real) = true for x in [1.23, 7, e, 4//5] #[FP, Int, Irrational, Rat] From c1c3c993291cb10d1efab4b0657f487fb0cb055e Mon Sep 17 00:00:00 2001 From: Fengyang Wang Date: Tue, 11 Apr 2017 17:13:44 -0400 Subject: [PATCH 0396/1534] Refer to `mkpath` from `mkdir` docs (#21343) --- base/file.jl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/base/file.jl b/base/file.jl index 7a4ccff63e7a5..24e26ff462dd7 100644 --- a/base/file.jl +++ b/base/file.jl @@ -85,7 +85,10 @@ cd(f::Function) = cd(f, homedir()) mkdir(path::AbstractString, mode::Unsigned=0o777) Make a new directory with name `path` and permissions `mode`. `mode` defaults to `0o777`, -modified by the current file creation mask. +modified by the current file creation mask. This function never creates more than one +directory. If the directory already exists, or some intermediate directories do not exist, +this function throws an error. See [`mkpath`](@ref) for a function which creates all +required intermediate directories. """ function mkdir(path::AbstractString, mode::Unsigned=0o777) @static if is_windows() From 5a565ffc06342461f5afba2a5e741ac1ad01f0d0 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 11 Apr 2017 17:43:37 -0400 Subject: [PATCH 0397/1534] fix #21352, update dev docs on type specificity [ci skip] --- doc/src/devdocs/types.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/src/devdocs/types.md b/doc/src/devdocs/types.md index dd95329d08e17..f59dcfb703ca2 100644 --- a/doc/src/devdocs/types.md +++ b/doc/src/devdocs/types.md @@ -486,10 +486,10 @@ mysubtype(Tuple{Array{Int,2}, Int8}, Tuple{Array{T}, T} where T) ## Subtyping and method sorting The `type_morespecific` functions are used for imposing a partial order on functions in method -tables (from most-to-least specific). Note that `jl_type_morespecific(a,b)` really means "is `a` -at least as specific as `b`?" and not "is `a` strictly more specific than `b`?" +tables (from most-to-least specific). Specificity is strict; if `a` is more specific than `b`, +then `a` does not equal `b` and `b` is not more specific than `a`. -If `a` is a subtype of `b`, then it is automatically considered more specific. +If `a` is a strict subtype of `b`, then it is automatically considered more specific. From there, `type_morespecific` employs some less formal rules. For example, `subtype` is sensitive to the number of arguments, but `type_morespecific` may not be. In particular, `Tuple{Int,AbstractFloat}` is more specific than `Tuple{Integer}`, even though it is From 3def60766261de5a1aa10297116f34fc84642083 Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Mon, 10 Apr 2017 22:38:45 -0700 Subject: [PATCH 0398/1534] Add LibGit2 binding docs to devdocs [ci skip] --- doc/make.jl | 1 + doc/src/devdocs/libgit2.md | 119 +++++++++++++++++++++++++++++++++++++ doc/src/index.md | 1 + 3 files changed, 121 insertions(+) create mode 100644 doc/src/devdocs/libgit2.md diff --git a/doc/make.jl b/doc/make.jl index 0ca31f155f940..4ef4222db9e8f 100644 --- a/doc/make.jl +++ b/doc/make.jl @@ -103,6 +103,7 @@ const PAGES = [ "devdocs/boundscheck.md", "devdocs/locks.md", "devdocs/offset-arrays.md", + "devdocs/libgit2.md", ], "Developing/debugging Julia's C code" => [ "devdocs/backtraces.md", diff --git a/doc/src/devdocs/libgit2.md b/doc/src/devdocs/libgit2.md new file mode 100644 index 0000000000000..94e3d720a24d8 --- /dev/null +++ b/doc/src/devdocs/libgit2.md @@ -0,0 +1,119 @@ +# Base.LibGit2 + +The LibGit2 module provides bindings to [libgit2](https://libgit2.github.com/), a portable C library that +implements core functionality for the [Git](https://git-scm.com/) version control system. +These bindings are currently used to power Julia's package manager. +It is expected that this module will eventually be moved into a separate package. + +### Functionality + +Some of this documentation assumes some prior knowledge of the libgit2 API. +For more information on some of the objects and methods referenced here, consult the upstream +[libgit2 API reference](https://libgit2.github.com/libgit2/#v0.25.1). + +```@docs +Base.LibGit2.AbstractCredentials +Base.LibGit2.Buffer +Base.LibGit2.CachedCredentials +Base.LibGit2.CheckoutOptions +Base.LibGit2.CloneOptions +Base.LibGit2.DiffDelta +Base.LibGit2.DiffFile +Base.LibGit2.DiffOptionsStruct +Base.LibGit2.FetchHead +Base.LibGit2.FetchOptions +Base.LibGit2.GitBlob +Base.LibGit2.GitCommit +Base.LibGit2.GitHash +Base.LibGit2.GitObject +Base.LibGit2.GitRemote +Base.LibGit2.GitRemoteAnon +Base.LibGit2.GitRepo +Base.LibGit2.GitRepoExt +Base.LibGit2.GitShortHash +Base.LibGit2.GitSignature +Base.LibGit2.GitStatus +Base.LibGit2.GitTag +Base.LibGit2.GitTree +Base.LibGit2.IndexEntry +Base.LibGit2.IndexTime +Base.LibGit2.MergeOptions +Base.LibGit2.ProxyOptions +Base.LibGit2.PushOptions +Base.LibGit2.RebaseOperation +Base.LibGit2.RebaseOptions +Base.LibGit2.RemoteCallbacks +Base.LibGit2.SSHCredentials +Base.LibGit2.SignatureStruct +Base.LibGit2.StatusEntry +Base.LibGit2.StatusOptions +Base.LibGit2.StrArrayStruct +Base.LibGit2.TimeStruct +Base.LibGit2.UserPasswordCredentials +Base.LibGit2.add_fetch! +Base.LibGit2.add_push! +Base.LibGit2.addblob! +Base.LibGit2.authors +Base.LibGit2.branch +Base.LibGit2.branch! +Base.LibGit2.checkout! +Base.LibGit2.checkused! +Base.LibGit2.clone +Base.LibGit2.commit +Base.LibGit2.create_branch +Base.LibGit2.credentials_callback +Base.LibGit2.credentials_cb +Base.LibGit2.default_signature +Base.LibGit2.delete_branch +Base.LibGit2.diff_files +Base.LibGit2.fetch +Base.LibGit2.fetch_refspecs +Base.LibGit2.fetchhead_foreach_cb +Base.LibGit2.ffmerge! +Base.LibGit2.fullname +Base.LibGit2.get_creds! +Base.LibGit2.gitdir +Base.LibGit2.head +Base.LibGit2.head! +Base.LibGit2.head_oid +Base.LibGit2.headname +Base.LibGit2.init +Base.LibGit2.is_ancestor_of +Base.LibGit2.isbinary +Base.LibGit2.iscommit +Base.LibGit2.isdiff +Base.LibGit2.isdirty +Base.LibGit2.isorphan +Base.LibGit2.lookup_branch +Base.LibGit2.mirror_callback +Base.LibGit2.mirror_cb +Base.LibGit2.name +Base.LibGit2.need_update +Base.LibGit2.objtype +Base.LibGit2.path +Base.LibGit2.peel +Base.LibGit2.posixpath +Base.LibGit2.push +Base.LibGit2.push_refspecs +Base.LibGit2.read_tree! +Base.LibGit2.rebase! +Base.LibGit2.ref_list +Base.LibGit2.reftype +Base.LibGit2.remotes +Base.LibGit2.reset! +Base.LibGit2.restore +Base.LibGit2.revcount +Base.LibGit2.set_remote_url +Base.LibGit2.shortname +Base.LibGit2.snapshot +Base.LibGit2.status +Base.LibGit2.tag_create +Base.LibGit2.tag_delete +Base.LibGit2.tag_list +Base.LibGit2.target +Base.LibGit2.treewalk +Base.LibGit2.upstream +Base.LibGit2.url +Base.LibGit2.with +Base.LibGit2.workdir +``` diff --git a/doc/src/index.md b/doc/src/index.md index ff862c7d1955e..bdfb34252e42d 100644 --- a/doc/src/index.md +++ b/doc/src/index.md @@ -87,6 +87,7 @@ * [Bounds checking](@ref) * [Proper maintenance and care of multi-threading locks](@ref) * [Arrays with custom indices](@ref) + * [Base.LibGit2](@ref) * Developing/debugging Julia's C code * [Reporting and analyzing crashes (segfaults)](@ref) * [gdb debugging tips](@ref) From fec32878a7f91159625f9130cb0249896f362e8d Mon Sep 17 00:00:00 2001 From: tan Date: Tue, 11 Apr 2017 13:29:30 +0530 Subject: [PATCH 0399/1534] make nprocs report only fully connected workers This changes nprocs (and therefore nworkers) report only workers in `W_CONNECTED` state. This is to avoid issue with `@everywhere` or other similar methods that broadcast messages to all workers. To simulate: - introduce an artificial delay at https://github.com/JuliaLang/julia/blob/2c4f6d74577a1b7606ed5e74e96158810f4f7af4/base/distributed/cluster.jl#L443 with `sleep(10)` - start a master with: ``` using ClusterManagers ElasticManager(;addr=IPv4("0.0.0.0"), port=9009, cookie="cookie", topology=:master_slave) while nworkers() < 4 sleep(1) end @everywhere println(myid()) ``` - start 4 workers with: ``` using ClusterManagers ClusterManagers.elastic_worker("cookie", "127.0.0.1", 9009; stdout_to_master=false) ``` Without this change, this will often result in: ``` ERROR: LoadError: peer 3 is not connected to 1. Topology : master_slave check_worker_state(::Base.Distributed.Worker) at ./distributed/cluster.jl:115 send_msg_(::Base.Distributed.Worker, ::Base.Distributed.MsgHeader, ::Base.Distributed.CallMsg{:call_fetch}, ::Bool) at ./distributed/messages.jl:180 remotecall_fetch(::Function, ::Base.Distributed.Worker, ::Expr, ::Vararg{Expr,N} where N) at ./distributed/remotecall.jl:346 remotecall_fetch(::Function, ::Int64, ::Expr, ::Vararg{Expr,N} where N) at ./distributed/remotecall.jl:367 (::##1#3)() at ./distributed/macros.jl:84 ``` --- base/distributed/cluster.jl | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/base/distributed/cluster.jl b/base/distributed/cluster.jl index 9b91ecc8bb74b..a92ef77c4c71c 100644 --- a/base/distributed/cluster.jl +++ b/base/distributed/cluster.jl @@ -651,7 +651,15 @@ myid() = LPROC.id Get the number of available processes. """ -nprocs() = length(PGRP.workers) +function nprocs() + n = length(PGRP.workers) + for jw in PGRP.workers + if !isa(jw, LocalProcess) && (jw.state != W_CONNECTED) + n = n - 1 + end + end + n +end """ nworkers() From 884e5f42f6b85c1ad578ec4f0e117fa390eb30a9 Mon Sep 17 00:00:00 2001 From: tan Date: Wed, 12 Apr 2017 10:22:07 +0530 Subject: [PATCH 0400/1534] make procs & workers return fully connected wrkrs --- base/distributed/cluster.jl | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/base/distributed/cluster.jl b/base/distributed/cluster.jl index a92ef77c4c71c..2d1d4fe1a38e4 100644 --- a/base/distributed/cluster.jl +++ b/base/distributed/cluster.jl @@ -677,7 +677,7 @@ end Returns a list of all process identifiers. """ -procs() = Int[x.id for x in PGRP.workers] +procs() = Int[x.id for x in PGRP.workers if isa(x, LocalProcess) || (x.state == W_CONNECTED)] """ procs(pid::Integer) @@ -687,11 +687,12 @@ Specifically all workers bound to the same ip-address as `pid` are returned. """ function procs(pid::Integer) if myid() == 1 + all_workers = [x for x in PGRP.workers if isa(x, LocalProcess) || (x.state == W_CONNECTED)] if (pid == 1) || (isa(map_pid_wrkr[pid].manager, LocalManager)) - Int[x.id for x in filter(w -> (w.id==1) || (isa(w.manager, LocalManager)), PGRP.workers)] + Int[x.id for x in filter(w -> (w.id==1) || (isa(w.manager, LocalManager)), all_workers)] else ipatpid = get_bind_addr(pid) - Int[x.id for x in filter(w -> get_bind_addr(w) == ipatpid, PGRP.workers)] + Int[x.id for x in filter(w -> get_bind_addr(w) == ipatpid, all_workers)] end else remotecall_fetch(procs, 1, pid) @@ -705,7 +706,7 @@ Returns a list of all worker process identifiers. """ function workers() allp = procs() - if nprocs() == 1 + if length(allp) == 1 allp else filter(x -> x != 1, allp) From 4e698cb55248b8191c4d68f9c18b656fecf48da4 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 12 Apr 2017 11:16:06 -0400 Subject: [PATCH 0401/1534] fix test for code-coverage configuration with --code-coverage, jlcall_api is disabled, altering the AST that gets stored for this function --- test/inference.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/inference.jl b/test/inference.jl index b0673e8e1ba25..6ed1e7068f270 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -736,7 +736,7 @@ f21175() = 902221 # call again, so that the AST is built on-demand let e = code_typed(f21175, ())[1].first.code[1]::Expr @test e.head === :return - @test e.args[1] == Core.QuoteNode(902221) + @test e.args[1] ∈ (902221, Core.QuoteNode(902221)) end # issue #10207 From 9f200a5f3d62ab7de6f02d2d835944d82fab2591 Mon Sep 17 00:00:00 2001 From: Lyndon White Date: Thu, 13 Apr 2017 00:41:54 +0800 Subject: [PATCH 0402/1534] Tweak description of restrictions on generated functions (#21357) --- doc/src/manual/metaprogramming.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/src/manual/metaprogramming.md b/doc/src/manual/metaprogramming.md index 633cbfc5b1ad0..7f9fc660e592d 100644 --- a/doc/src/manual/metaprogramming.md +++ b/doc/src/manual/metaprogramming.md @@ -876,8 +876,10 @@ When defining generated functions, there are four main differences to ordinary f function. 3. Instead of calculating something or performing some action, you return a *quoted expression* which, when evaluated, does what you want. -4. Generated functions must not have any side-effects or examine any non-constant global state (including, - for example, IO, locks, or non-local dictionaries). In other words, they must be completely pure. +4. Generated functions must not *mutate* or *observe* any non-constant global state (including, + for example, IO, locks, non-local dictionaries, or using `method_exists`). + This means they can only read global constants, and cannot have any side effects. + In other words, they must be completely pure. Due to an implementation limitation, this also means that they currently cannot define a closure or untyped generator. From 75a6a9057d75c9938afa2f407bee0a80cf5f6a4c Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 12 Apr 2017 12:58:58 -0400 Subject: [PATCH 0403/1534] add a fast path function for checking for empty intersections add `obviously_disjoint` fast path to type_morespecific further helps #21173 --- src/gf.c | 6 ++---- src/julia.h | 1 + src/subtype.c | 45 +++++++++++++++++++++++++++++++++++---------- src/typemap.c | 2 +- 4 files changed, 39 insertions(+), 15 deletions(-) diff --git a/src/gf.c b/src/gf.c index c6df93465cf1a..c61853f0e3218 100644 --- a/src/gf.c +++ b/src/gf.c @@ -1397,7 +1397,7 @@ JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method size_t ins = 0; for (i = 1; i < na; i += 2) { jl_value_t *backedgetyp = backedges[i - 1]; - if (jl_type_intersection(backedgetyp, (jl_value_t*)type) != (jl_value_t*)jl_bottom_type) { + if (!jl_has_empty_intersection(backedgetyp, (jl_value_t*)type)) { jl_method_instance_t *backedge = (jl_method_instance_t*)backedges[i]; invalidate_method_instance(backedge, env.max_world, 0); env.invalidated = 1; @@ -1731,10 +1731,8 @@ JL_DLLEXPORT int jl_has_call_ambiguities(jl_tupletype_t *types, jl_method_t *m) if (m->ambig == jl_nothing) return 0; for (size_t i = 0; i < jl_array_len(m->ambig); i++) { jl_method_t *mambig = (jl_method_t*)jl_array_ptr_ref(m->ambig, i); - if (jl_type_intersection((jl_value_t*)mambig->sig, - (jl_value_t*)types) != (jl_value_t*)jl_bottom_type) { + if (!jl_has_empty_intersection((jl_value_t*)mambig->sig, (jl_value_t*)types)) return 1; - } } return 0; } diff --git a/src/julia.h b/src/julia.h index f5efda7e378c7..b3188fa2b5905 100644 --- a/src/julia.h +++ b/src/julia.h @@ -982,6 +982,7 @@ JL_DLLEXPORT int jl_isa(jl_value_t *a, jl_value_t *t); JL_DLLEXPORT int jl_types_equal(jl_value_t *a, jl_value_t *b); JL_DLLEXPORT jl_value_t *jl_type_union(jl_value_t **ts, size_t n); JL_DLLEXPORT jl_value_t *jl_type_intersection(jl_value_t *a, jl_value_t *b); +JL_DLLEXPORT int jl_has_empty_intersection(jl_value_t *x, jl_value_t *y); JL_DLLEXPORT jl_value_t *jl_type_unionall(jl_tvar_t *v, jl_value_t *body); JL_DLLEXPORT const char *jl_typename_str(jl_value_t *v); JL_DLLEXPORT const char *jl_typeof_str(jl_value_t *v); diff --git a/src/subtype.c b/src/subtype.c index 8a1984c7a285f..113cb1675085e 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -91,6 +91,7 @@ typedef struct { int invdepth; // current number of invariant constructors we're nested in int ignore_free; // treat free vars as black boxes; used during intersection int intersection; // true iff subtype is being called from intersection + int emptiness_only; // true iff intersection only needs to test for emptiness } jl_stenv_t; // state manipulation utilities @@ -238,7 +239,7 @@ static int obviously_unequal(jl_value_t *a, jl_value_t *b) return 0; } -static int obviously_disjoint(jl_value_t *a, jl_value_t *b) +static int obviously_disjoint(jl_value_t *a, jl_value_t *b, int specificity) { if (a == b || a == (jl_value_t*)jl_any_type || b == (jl_value_t*)jl_any_type) return 0; @@ -280,7 +281,8 @@ static int obviously_disjoint(jl_value_t *a, jl_value_t *b) else if (jl_is_va_tuple(bd)) { nb -= 1; } - else if (na != nb) { + else if (!specificity && na != nb) { + // note: some disjoint types (e.g. tuples of different lengths) can be more specific return 1; } np = na < nb ? na : nb; @@ -298,13 +300,18 @@ static int obviously_disjoint(jl_value_t *a, jl_value_t *b) if (jl_is_type(bi)) { if (istuple && (ai == jl_bottom_type || bi == jl_bottom_type)) ; // TODO: this can return 1 if and when Tuple{Union{}} === Union{} - else if (obviously_disjoint(ai, bi)) + else if (obviously_disjoint(ai, bi, specificity)) return 1; } - else { + else if (!specificity) { + // Tuple{1} is more specific than Tuple{Any} return 1; } } + else if (jl_is_type(bi)) { + if (!specificity) + return 1; + } else if (!jl_egal(ai, bi)) { return 1; } @@ -534,8 +541,9 @@ static int subtype_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_t *e, int8 // if the var for this unionall (based on identity) already appears somewhere // in the environment, rename to get a fresh var. while (btemp != NULL) { - if (btemp->var == u->var || jl_has_typevar(btemp->lb, u->var) || - jl_has_typevar(btemp->ub, u->var)) { + if (btemp->var == u->var || + (btemp->lb != jl_bottom_type && jl_has_typevar(btemp->lb, u->var)) || + (btemp->ub != (jl_value_t*)jl_any_type && jl_has_typevar(btemp->ub, u->var))) { u = rename_unionall(u); break; } @@ -619,7 +627,7 @@ static int subtype_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_t *e, int8 btemp = e->vars; while (btemp != NULL) { jl_value_t *vi = btemp->ub; - if (vi != (jl_value_t*)vb.var && jl_has_typevar(vi, vb.var)) { + if (vi != (jl_value_t*)vb.var && vi != (jl_value_t*)jl_any_type && jl_has_typevar(vi, vb.var)) { btemp->ub = jl_new_struct(jl_unionall_type, vb.var, vi); btemp->lb = jl_bottom_type; } @@ -1003,6 +1011,7 @@ static void init_stenv(jl_stenv_t *e, jl_value_t **env, int envsz) e->invdepth = 0; e->ignore_free = 0; e->intersection = 0; + e->emptiness_only = 0; e->Lunions.depth = 0; e->Runions.depth = 0; e->Lunions.more = 0; e->Runions.more = 0; } @@ -2012,6 +2021,8 @@ static jl_value_t *intersect_all(jl_value_t *x, jl_value_t *y, jl_stenv_t *e) int lastset = 0, niter = 0; jl_value_t *ii = intersect(x, y, e, 0); while (e->Runions.more) { + if (e->emptiness_only && ii != jl_bottom_type) + return ii; e->Runions.depth = 0; int set = e->Runions.more - 1; e->Runions.more = 0; @@ -2042,16 +2053,28 @@ static jl_value_t *intersect_all(jl_value_t *x, jl_value_t *y, jl_stenv_t *e) // type intersection entry points -JL_DLLEXPORT jl_value_t *jl_intersect_types(jl_value_t *x, jl_value_t *y) +static jl_value_t *intersect_types(jl_value_t *x, jl_value_t *y, int emptiness_only) { jl_stenv_t e; - if (obviously_disjoint(x, y)) + if (obviously_disjoint(x, y, 0)) return jl_bottom_type; init_stenv(&e, NULL, 0); e.intersection = 1; + e.emptiness_only = emptiness_only; return intersect_all(x, y, &e); } +JL_DLLEXPORT jl_value_t *jl_intersect_types(jl_value_t *x, jl_value_t *y) +{ + return intersect_types(x, y, 0); +} + +// TODO: this can probably be done more efficiently +JL_DLLEXPORT int jl_has_empty_intersection(jl_value_t *x, jl_value_t *y) +{ + return intersect_types(x, y, 1) == jl_bottom_type; +} + // return a SimpleVector of all vars from UnionAlls wrapping a given type jl_svec_t *jl_outer_unionall_vars(jl_value_t *u) { @@ -2073,7 +2096,7 @@ jl_svec_t *jl_outer_unionall_vars(jl_value_t *u) jl_value_t *jl_type_intersection_env_s(jl_value_t *a, jl_value_t *b, jl_svec_t **penv, int *issubty) { if (issubty) *issubty = 0; - if (obviously_disjoint(a, b)) { + if (obviously_disjoint(a, b, 0)) { if (issubty && a == jl_bottom_type) *issubty = 1; return jl_bottom_type; } @@ -2570,6 +2593,8 @@ static int type_morespecific_(jl_value_t *a, jl_value_t *b, int invariant, jl_ty JL_DLLEXPORT int jl_type_morespecific(jl_value_t *a, jl_value_t *b) { + if (obviously_disjoint(a, b, 1)) + return 0; if (jl_subtype(b, a)) return 0; if (jl_subtype(a, b)) return 1; return type_morespecific_(a, b, 0, NULL); diff --git a/src/typemap.c b/src/typemap.c index 0119678b92584..b70accd357b87 100644 --- a/src/typemap.c +++ b/src/typemap.c @@ -515,7 +515,7 @@ int jl_typemap_intersection_visitor(union jl_typemap_t map, int offs, else { // else an array scan is required to check subtypes // first, fast-path: optimized pre-intersection test to see if `ty` could intersect with any Type - if (typetype || jl_type_intersection((jl_value_t*)jl_type_type, ty) != jl_bottom_type) + if (typetype || !jl_has_empty_intersection((jl_value_t*)jl_type_type, ty)) if (!jl_typemap_intersection_array_visitor(&cache->targ, ty, 1, offs, closure)) return 0; } } From 7c168974303cfc11714836012eb53cea25b220fb Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 12 Apr 2017 11:16:06 -0400 Subject: [PATCH 0404/1534] fix test for code-coverage configuration with --code-coverage, jlcall_api is disabled, altering the AST that gets stored for this function --- test/inline.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/inline.jl b/test/inline.jl index 3f21750fd2f63..1de15c909d3e1 100644 --- a/test/inline.jl +++ b/test/inline.jl @@ -87,11 +87,11 @@ end @inline Base.getindex(v::s21074, i::Integer) = v.x[i] @eval f21074() = $(s21074((1,2))).x[1] let (src, _) = code_typed(f21074, ())[1] - @test src.code[1] == Expr(:return, 1) + @test src.code[end] == Expr(:return, 1) end @eval g21074() = $(s21074((1,2)))[1] let (src, _) = code_typed(g21074, ())[1] - @test src.code[1] == Expr(:return, 1) + @test src.code[end] == Expr(:return, 1) end # issue #21311 From 31337ae89ce75ec1c8a8e4d979ca34c75a9f85e0 Mon Sep 17 00:00:00 2001 From: Nathan Daly Date: Mon, 10 Apr 2017 00:05:08 -0500 Subject: [PATCH 0405/1534] Added more details to Operator Precedence section From Issue #14933. - Made Operator Precedence a higher heading, since it's not really a subsection of `##Numeric Comparisons`, and it references all the operators described in earlier sections on the page. - Added a link to the source file that lists *all* operator precedences. - Added code examples for `Base.operator_precedence` to show how to programmatically find an operator's precedence. --- doc/src/manual/mathematical-operations.md | 31 ++++++++++++++++------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/doc/src/manual/mathematical-operations.md b/doc/src/manual/mathematical-operations.md index faebc4227408c..38d291270dc74 100644 --- a/doc/src/manual/mathematical-operations.md +++ b/doc/src/manual/mathematical-operations.md @@ -331,7 +331,18 @@ comparison is undefined. It is strongly recommended not to use expressions with as printing) in chained comparisons. If side effects are required, the short-circuit `&&` operator should be used explicitly (see [Short-Circuit Evaluation](@ref)). -### Operator Precedence +### Elementary Functions + +Julia provides a comprehensive collection of mathematical functions and operators. These mathematical +operations are defined over as broad a class of numerical values as permit sensible definitions, +including integers, floating-point numbers, rationals, and complexes, wherever such definitions +make sense. + +Moreover, these functions (like any Julia function) can be applied in "vectorized" fashion to +arrays and other collections with the [dot syntax](@ref man-vectorized) `f.(A)`, +e.g. `sin.(A)` will compute the elementwise sine of each element of an array `A`. + +## Operator Precedence Julia applies the following order of operations, from highest precedence to lowest: @@ -348,16 +359,18 @@ Julia applies the following order of operations, from highest precedence to lowe | Control flow | `&&` followed by `\|\|` followed by `?` | | Assignments | `= += -= *= /= //= \= ^= ÷= %= \|= &= ⊻= <<= >>= >>>=` | -### Elementary Functions +For a complete list of *every* Julia operator's precedence, see the top of this file: +[julia/src/julia-parser.scm](https://github.com/JuliaLang/julia/blob/master/src/julia-parser.scm) -Julia provides a comprehensive collection of mathematical functions and operators. These mathematical -operations are defined over as broad a class of numerical values as permit sensible definitions, -including integers, floating-point numbers, rationals, and complexes, wherever such definitions -make sense. +You can also find the numerical precedence for any given operator via the built-in function `Base.operator_precedence`, where higher numbers take precedence: -Moreover, these functions (like any Julia function) can be applied in "vectorized" fashion to -arrays and other collections with the [dot syntax](@ref man-vectorized) `f.(A)`, -e.g. `sin.(A)` will compute the elementwise sine of each element of an array `A`. +```jldoctest +julia> Base.operator_precedence(:+), Base.operator_precedence(:*), Base.operator_precedence(:.) +(9,11,15) + +julia> Base.operator_precedence(:+=), Base.operator_precedence(:(=)) # (Note the necessary parens on `:(=)`) +(1,1) +``` ## Numerical Conversions From 7eb0dc6129f9471df56f3af48826e1d27796927c Mon Sep 17 00:00:00 2001 From: Nathan Daly Date: Mon, 10 Apr 2017 15:44:33 -0500 Subject: [PATCH 0406/1534] Added docstring to `Base.operator_precedence` As part of #14933, added docstring and jldoctest examples to Base.operator_precedence(s::Symbol). --- base/show.jl | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/base/show.jl b/base/show.jl index 40ac09f544530..e526c0a653ded 100644 --- a/base/show.jl +++ b/base/show.jl @@ -469,6 +469,24 @@ end isidentifier(s::Symbol) = isidentifier(string(s)) isoperator(s::Symbol) = ccall(:jl_is_operator, Cint, (Cstring,), s) != 0 + +""" + operator_precedence(s::Symbol) + +Return an integer representing the precedence of operator `s`, relative to +other operators. Higher-numbered operators take precedence over lower-numbered +operators. Return `0` if `s` is not a valid operator. + +# Examples + +```jldoctest +julia> Base.operator_precedence(:+), Base.operator_precedence(:*), Base.operator_precedence(:.) +(9,11,15) + +julia> Base.operator_precedence(:+=), Base.operator_precedence(:(=)) # (Note the necessary parens on `:(=)`) +(1,1) +``` +""" operator_precedence(s::Symbol) = Int(ccall(:jl_operator_precedence, Cint, (Cstring,), s)) operator_precedence(x::Any) = 0 # fallback for generic expression nodes const prec_power = operator_precedence(:(^)) From 653fb16c320c009b831567000b535aa806feba92 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 6 Apr 2017 18:16:59 -0400 Subject: [PATCH 0407/1534] fix `jl_load_dynamic_library` with NULL argument This was supposed to return a handle for libjulia, but on unix systems was returning a handle for the main executable. --- src/dlload.c | 5 ++++- src/init.c | 14 ++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/dlload.c b/src/dlload.c index 860aeda708f6f..a73813ba33684 100644 --- a/src/dlload.c +++ b/src/dlload.c @@ -139,7 +139,10 @@ static void *jl_load_dynamic_library_(const char *modname, unsigned flags, int t jl_error("could not load base module"); } #else - handle = dlopen(NULL, RTLD_NOW); + Dl_info info; + if (!dladdr(&jl_load_dynamic_library, &info) || !info.dli_fname) + jl_error("could not load base module"); + handle = dlopen(info.dli_fname, RTLD_NOW); #endif goto done; } diff --git a/src/init.c b/src/init.c index 778be20efb38b..0d35d7a8e4624 100644 --- a/src/init.c +++ b/src/init.c @@ -299,8 +299,8 @@ void jl_get_builtins(void); JL_DLLEXPORT void *jl_dl_handle; void *jl_RTLD_DEFAULT_handle; -#ifdef _OS_WINDOWS_ JL_DLLEXPORT void *jl_exe_handle; +#ifdef _OS_WINDOWS_ void *jl_ntdll_handle; void *jl_kernel32_handle; void *jl_crtdll_handle; @@ -541,11 +541,6 @@ void _julia_init(JL_IMAGE_SEARCH rel) jl_arr_xtralloc_limit = total_mem / 100; // Extra allocation limited to 1% of total RAM jl_find_stack_bottom(); jl_dl_handle = jl_load_dynamic_library(NULL, JL_RTLD_DEFAULT); -#ifdef RTLD_DEFAULT - jl_RTLD_DEFAULT_handle = RTLD_DEFAULT; -#else - jl_RTLD_DEFAULT_handle = jl_dl_handle; -#endif #ifdef _OS_WINDOWS_ jl_ntdll_handle = jl_dlopen("ntdll.dll", 0); // bypass julia's pathchecking for system dlls jl_kernel32_handle = jl_dlopen("kernel32.dll", 0); @@ -564,6 +559,13 @@ void _julia_init(JL_IMAGE_SEARCH rel) HMODULE jl_dbghelp = (HMODULE) jl_dlopen("dbghelp.dll", 0); if (jl_dbghelp) hSymRefreshModuleList = (BOOL (WINAPI*)(HANDLE)) jl_dlsym(jl_dbghelp, "SymRefreshModuleList"); +#else + jl_exe_handle = jl_dlopen(NULL, JL_RTLD_NOW); +#ifdef RTLD_DEFAULT + jl_RTLD_DEFAULT_handle = RTLD_DEFAULT; +#else + jl_RTLD_DEFAULT_handle = jl_exe_handle; +#endif #endif #if defined(JL_USE_INTEL_JITEVENTS) From aaec5e228e37038ecfa60057a2e4ad81ca9f668e Mon Sep 17 00:00:00 2001 From: Isaiah Norton Date: Fri, 7 Apr 2017 12:26:06 -0400 Subject: [PATCH 0408/1534] fix off-by-one error in `jl_pathname_for_handle` on OS X --- src/sys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sys.c b/src/sys.c index e391c469de3fb..0e984cef70d3a 100644 --- a/src/sys.c +++ b/src/sys.c @@ -668,7 +668,7 @@ JL_DLLEXPORT const char *jl_pathname_for_handle(void *handle) #ifdef __APPLE__ // Iterate through all images currently in memory - for (int32_t i = _dyld_image_count(); i >= 0 ; i--) { + for (int32_t i = _dyld_image_count() - 1; i >= 0 ; i--) { // dlopen() each image, check handle const char *image_name = _dyld_get_image_name(i); void *probe_lib = jl_load_dynamic_library(image_name, JL_RTLD_DEFAULT); From 25fd57e42565842d18a8375191de9279d996ff28 Mon Sep 17 00:00:00 2001 From: Tracy Wadleigh Date: Sun, 12 Feb 2017 23:14:28 -0500 Subject: [PATCH 0409/1534] Add test/embedding.jl --- test/embedding.jl | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 test/embedding.jl diff --git a/test/embedding.jl b/test/embedding.jl new file mode 100644 index 0000000000000..2e78c45db10ca --- /dev/null +++ b/test/embedding.jl @@ -0,0 +1,8 @@ +# test that the embedding example runs without error +let + embedding_bin = joinpath(JULIA_HOME,"..","libexec","embedding") + lines = readlines(pipeline(`$(embedding_bin)`, + stderr=DevNull)) + @test length(lines) == 5 + @test parse(Float64, lines[1]) ≈ sqrt(2) +end From 5d7c4c2781f4a02fad00d57f068a2c5aca1b93eb Mon Sep 17 00:00:00 2001 From: Isaiah Norton Date: Thu, 23 Mar 2017 12:17:56 -0400 Subject: [PATCH 0410/1534] julia-config needs -std=gnu99 --- contrib/julia-config.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/julia-config.jl b/contrib/julia-config.jl index ad7b038ca47c9..7a175bdf80078 100755 --- a/contrib/julia-config.jl +++ b/contrib/julia-config.jl @@ -70,9 +70,9 @@ function cflags() arg2 = replace(includeDir(),"\\","\\\\") threading_def = threadingOn() ? "-DJULIA_ENABLE_THREADING=1 " : "" if is_unix() - return """$(threading_def)-fPIC -DJULIA_INIT_DIR=\\"$arg1\\" -I$arg2""" + return """-std=gnu99 $(threading_def)-fPIC -DJULIA_INIT_DIR=\\"$arg1\\" -I$arg2""" else - return """$(threading_def)-DJULIA_INIT_DIR=\\"$arg1\\" -I$arg2""" + return """-std=gnu99 $(threading_def)-DJULIA_INIT_DIR=\\"$arg1\\" -I$arg2""" end end From c8026a91acd988fbbb08158092a89e111c243965 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 12 Apr 2017 22:38:38 -0400 Subject: [PATCH 0411/1534] fix #20220 (#21367) If there was an intervening stack frame with unknown location, we mistakenly returned it from `firstcaller` by comparing with `===` instead of `==`. --- base/deprecated.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index 9609e9fbe0989..8b78df5a87bf7 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -85,7 +85,7 @@ function firstcaller(bt::Array{Ptr{Void},1}, funcsyms) for frame in bt lkups = StackTraces.lookup(frame) for lkup in lkups - if lkup === StackTraces.UNKNOWN + if lkup == StackTraces.UNKNOWN continue end found && @goto found @@ -1061,7 +1061,7 @@ function partial_linear_indexing_warning_lookup(nidxs_remaining) for frame in bt lkups = StackTraces.lookup(frame) for caller in lkups - if caller === StackTraces.UNKNOWN + if caller == StackTraces.UNKNOWN continue end found && @goto found From 8dd31233b4f6ad6e56e743e6f0b3f40cec81fa27 Mon Sep 17 00:00:00 2001 From: Isaiah Norton Date: Wed, 8 Feb 2017 23:14:13 -0500 Subject: [PATCH 0412/1534] Fix embedding example and simplify Makefile - get rid of makefile cruft - use julia-config for flags, as documented in manual - build into `libexec` also move to subdir for clarity. --- Makefile | 14 ++++++-- examples/Makefile | 48 +++++++++------------------- examples/embedding/Makefile | 39 ++++++++++++++++++++++ examples/{ => embedding}/embedding.c | 5 +-- src/jlapi.c | 2 ++ src/jloptions.c | 4 +-- src/julia.h | 1 + 7 files changed, 73 insertions(+), 40 deletions(-) create mode 100644 examples/embedding/Makefile rename examples/{ => embedding}/embedding.c (95%) diff --git a/Makefile b/Makefile index 7ae826525d65f..4de0a1070ab38 100644 --- a/Makefile +++ b/Makefile @@ -62,14 +62,21 @@ $(BUILDROOT)/doc/_build/html/en/index.html: $(shell find $(BUILDROOT)/base $(BUI CLEAN_TARGETS += clean-docdir clean-docdir: @-rm -fr $(abspath $(build_docdir)) -$(build_prefix)/.examples: $(wildcard $(JULIAHOME)/examples/*.jl) $(shell find $(JULIAHOME)/examples/clustermanager) + +$(build_prefix)/.examples: $(wildcard $(JULIAHOME)/examples/*.jl) \ + $(shell find $(JULIAHOME)/examples/clustermanager) @echo Copying in usr/share/doc/julia/examples @-rm -fr $(build_docdir)/examples @mkdir -p $(build_docdir)/examples + @mkdir -p $(build_docdir)/examples/embedding @cp -R $(JULIAHOME)/examples/*.jl $(build_docdir)/examples/ @cp -R $(JULIAHOME)/examples/clustermanager $(build_docdir)/examples/ + @cp -R $(JULIAHOME)/examples/embedding $(build_docdir)/examples/embedding @echo 1 > $@ +examples: julia-sysimg-$(JULIA_BUILD_MODE) + @$(MAKE) $(QUIET_MAKE) -C $(BUILDROOT)/examples $(JULIA_BUILD_MODE) + julia-symlink: julia-ui-$(JULIA_BUILD_MODE) ifneq ($(OS),WINNT) ifndef JULIA_VAGRANT_BUILD @@ -107,7 +114,7 @@ julia-sysimg-release : julia-inference julia-ui-release julia-sysimg-debug : julia-inference julia-ui-debug @$(MAKE) $(QUIET_MAKE) -C $(BUILDROOT) $(build_private_libdir)/sys-debug$(CPUID_TAG).$(SHLIB_EXT) JULIA_BUILD_MODE=debug -julia-debug julia-release : julia-% : julia-ui-% julia-sysimg-% julia-symlink julia-libccalltest +julia-debug julia-release : julia-% : julia-ui-% julia-sysimg-% julia-symlink julia-libccalltest examples debug release : % : julia-% @@ -522,6 +529,7 @@ clean: | $(CLEAN_TARGETS) @-$(MAKE) -C $(BUILDROOT)/src clean @-$(MAKE) -C $(BUILDROOT)/ui clean @-$(MAKE) -C $(BUILDROOT)/test clean + @-$(MAKE) -C $(BUILDROOT)/examples clean -rm -f $(BUILDROOT)/julia -rm -f $(BUILDROOT)/*.tar.gz -rm -f $(build_depsbindir)/stringreplace \ @@ -548,7 +556,7 @@ distcleanall: cleanall test testall testall1 test clean distcleanall cleanall clean-* \ run-julia run-julia-debug run-julia-release run \ install binary-dist light-source-dist.tmp light-source-dist \ - dist full-source-dist source-dist + dist full-source-dist source-dist examples test: check-whitespace $(JULIA_BUILD_MODE) @$(MAKE) $(QUIET_MAKE) -C $(BUILDROOT)/test default JULIA_BUILD_MODE=$(JULIA_BUILD_MODE) diff --git a/examples/Makefile b/examples/Makefile index 8f9ba2b87bc73..56e328bdd9c28 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -1,41 +1,23 @@ -JULIAHOME := $(abspath ..) +SRCDIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) +BUILDDIR := . +JULIAHOME := $(abspath $(SRCDIR)/..) include $(JULIAHOME)/Make.inc -FLAGS = -Wall -Wno-strict-aliasing -fno-omit-frame-pointer \ - -I$(JULIAHOME)/src -I$(JULIAHOME)/src/support -I$(build_includedir) $(CFLAGS) +embedding_binary := $(abspath $(build_libexecdir)/embedding$(JULIA_LIBSUFFIX)$(EXE)) -DEBUGFLAGS += $(FLAGS) -SHIPFLAGS += $(FLAGS) -JLDFLAGS += $(LDFLAGS) $(NO_WHOLE_ARCHIVE) $(call exec,$(LLVM_CONFIG) --ldflags) $(OSLIBS) $(RPATH) +release: embedding +debug: embedding-debug -ifeq ($(USE_SYSTEM_LIBM),0) -ifneq ($(UNTRUSTED_SYSTEM_LIBM),0) -JLDFLAGS += $(WHOLE_ARCHIVE) $(build_libdir)/libopenlibm.a $(NO_WHOLE_ARCHIVE) -endif -endif +embedding: $(embedding_binary) +embedding-debug: $(embedding_binary) -embedding-release: embedding +$(embedding_binary): $(wildcard embedding/*) + @$(MAKE) $(QUIET_MAKE) -C $(BUILDROOT)/examples/embedding $(JULIA_BUILD_MODE) \ + JULIA="$(JULIA_EXECUTABLE)" BIN="$(build_libexecdir)" \ + SPAWN="$(spawn)" CC="$(CC)" -release debug: - $(MAKE) embedding-$@ +clean: + -rm -f $(embedding_binary) $(embedding_binary)-debug -%.o: %.c - @$(call PRINT_CC, $(CC) $(CPPFLAGS) $(CFLAGS) $(SHIPFLAGS) -c $< -o $@) -%.do: %.c - @$(call PRINT_CC, $(CC) $(CPPFLAGS) $(CFLAGS) $(DEBUGFLAGS) -c $< -o $@) - -embedding: $(build_bindir)/embedding$(EXE) -embedding-debug: $(build_bindir)/embedding-debug$(EXE) - -$(build_bindir)/embedding$(EXE): embedding.o - @$(call PRINT_LINK, $(CXX) $(LINK_FLAGS) $(SHIPFLAGS) $^ -o $@ -L$(build_private_libdir) -L$(build_shlibdir) -ljulia $(JLDFLAGS)) -$(build_bindir)/embedding-debug$(EXE): embedding.do - @$(call PRINT_LINK, $(CXX) $(LINK_FLAGS) $(DEBUGFLAGS) $^ -o $@ -L$(build_private_libdir) -L$(build_shlibdir) -ljulia-debug $(JLDFLAGS)) - - -clean: | $(CLEAN_TARGETS) - rm -f *.o *.do - rm -f $(build_bindir)/embedding-debug $(build_bindir)/embedding - -.PHONY: clean release debug +.PHONY: all embedding clean diff --git a/examples/embedding/Makefile b/examples/embedding/Makefile new file mode 100644 index 0000000000000..4ad51f5ce46d8 --- /dev/null +++ b/examples/embedding/Makefile @@ -0,0 +1,39 @@ +# This Makefile template requires the following variables to be set +# in the environment or on the command-line: +# JULIA: path to julia[.exe] executable +# BIN: binary build directory + +ifndef JULIA + $(error "Please pass JULIA=[path of target julia binary], or set as environment variable!") +endif +ifndef BIN + $(error "Please pass BIN=[path of build directory], or set as environment variable!") +endif + +#============================================================================= +# get the executable suffix, if any +EXE := $(suffix $(abspath $(JULIA))) + +# get compiler and linker flags. (see: `contrib/julia-config.jl`) +CFLAGS += -lm $(shell $(SPAWN) $(JULIA) -e \ + 'include(joinpath(JULIA_HOME,Base.DATAROOTDIR,"julia","julia-config.jl"))' \ + -- --cflags --ldflags --ldlibs) + +DEBUGFLAGS += -g + +#============================================================================= + +release: $(BIN)/embedding$(EXE) +debug: $(BIN)/embedding-debug$(EXE) + +$(BIN)/embedding$(EXE): embedding.c + $(CC) $^ -o $@ $(CFLAGS) + +$(BIN)/embedding-debug$(EXE): embedding.c + $(CC) $^ -o $@ $(CFLAGS) $(DEBUGFLAGS) + +clean: + @rm -f $(BIN)/embedding-debug$(EXE) $(BIN)/embedding$(EXE) + +.PHONY: release debug clean + diff --git a/examples/embedding.c b/examples/embedding/embedding.c similarity index 95% rename from examples/embedding.c rename to examples/embedding/embedding.c index 34a7e42290841..1e66b91c1c289 100644 --- a/examples/embedding.c +++ b/examples/embedding/embedding.c @@ -14,7 +14,7 @@ double my_c_sqrt(double x) int main() { - jl_init(NULL); + jl_init(); { // Simple running Julia code @@ -49,7 +49,7 @@ int main() { // 1D arrays - jl_value_t* array_type = jl_apply_array_type( jl_float64_type, 1 ); + jl_value_t* array_type = jl_apply_array_type( (jl_value_t*)jl_float64_type, 1 ); jl_array_t* x = jl_alloc_array_1d(array_type , 10); JL_GC_PUSH1(&x); @@ -97,6 +97,7 @@ int main() jl_show(jl_stderr_obj(), jl_exception_occurred()); jl_printf(jl_stderr_stream(), "\n"); } + } int ret = 0; diff --git a/src/jlapi.c b/src/jlapi.c index c971927528b09..34bb7f2ca6b44 100644 --- a/src/jlapi.c +++ b/src/jlapi.c @@ -43,6 +43,8 @@ JL_DLLEXPORT void jl_init_with_image(const char *julia_home_dir, jl_options.julia_home = julia_home_dir; if (image_relative_path != NULL) jl_options.image_file = image_relative_path; + else + jl_options.image_file = jl_get_default_sysimg_path(); julia_init(JL_IMAGE_JULIA_HOME); jl_exception_clear(); } diff --git a/src/jloptions.c b/src/jloptions.c index f87964aa5865f..fca0657b59c49 100644 --- a/src/jloptions.c +++ b/src/jloptions.c @@ -20,7 +20,7 @@ char *shlib_ext = ".so"; #endif static char system_image_path[256] = "\0" JL_SYSTEM_IMAGE_PATH; -static const char *get_default_sysimg_path(void) +JL_DLLEXPORT const char *jl_get_default_sysimg_path(void) { #ifdef CPUID_SPECIFIC_BINARIES char *path = &system_image_path[1]; @@ -203,7 +203,7 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp) // If CPUID specific binaries are enabled, this varies between runs, so initialize // it here, rather than as part of the static initialization above. - jl_options.image_file = get_default_sysimg_path(); + jl_options.image_file = jl_get_default_sysimg_path(); int codecov = JL_LOG_NONE; int malloclog= JL_LOG_NONE; diff --git a/src/julia.h b/src/julia.h index fa58e2db3b0bd..ebfc5b61286f7 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1319,6 +1319,7 @@ JL_DLLEXPORT void julia_init(JL_IMAGE_SEARCH rel); JL_DLLEXPORT void jl_init(const char *julia_home_dir); JL_DLLEXPORT void jl_init_with_image(const char *julia_home_dir, const char *image_relative_path); +JL_DLLEXPORT const char* jl_get_default_sysimg_path(); JL_DLLEXPORT int jl_is_initialized(void); JL_DLLEXPORT void jl_atexit_hook(int status); JL_DLLEXPORT void JL_NORETURN jl_exit(int status); From 0c123c12e044634b91404f36e252c79bd96642f3 Mon Sep 17 00:00:00 2001 From: Isaiah Norton Date: Fri, 24 Mar 2017 00:18:19 -0400 Subject: [PATCH 0413/1534] Teach jl_init to find itself update manual for change to `jl_init` --- doc/src/manual/embedding.md | 17 +++++++---------- src/jlapi.c | 16 +++++++++++++--- src/julia.h | 5 +++-- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/doc/src/manual/embedding.md b/doc/src/manual/embedding.md index 21a8f42ae04ea..7aa1d755ed9d8 100644 --- a/doc/src/manual/embedding.md +++ b/doc/src/manual/embedding.md @@ -17,7 +17,7 @@ We start with a simple C program that initializes Julia and calls some Julia cod int main(int argc, char *argv[]) { /* required: setup the Julia context */ - jl_init(NULL); + jl_init(); /* run Julia commands */ jl_eval_string("print(sqrt(2.0))"); @@ -48,9 +48,9 @@ The file `ui/repl.c` program is another simple example of how to set `jl_options linking against `libjulia`. The first thing that has to be done before calling any other Julia C function is to initialize -Julia. This is done by calling `jl_init`, which takes as argument a C string (`const char*`) to -the location where Julia is installed. When the argument is `NULL`, Julia tries to determine the -install location automatically. +Julia. This is done by calling `jl_init`, which tries to automatically determine Julia's install +location. If you need to specify a custom location, or specify which system image to load, +use `jl_init_with_image` instead. The second statement in the test program evaluates a Julia statement using a call to `jl_eval_string`. @@ -63,8 +63,8 @@ example program calls this before returning from `main`. ``` >>> julia=CDLL('./libjulia.dylib',RTLD_GLOBAL) - >>> julia.jl_init.argtypes = [c_char_p] - >>> julia.jl_init('.') + >>> julia.jl_init.argtypes = [] + >>> julia.jl_init() 250593296 ``` @@ -83,15 +83,12 @@ shared data directory. #### Example -Below is essentially the same as above with one small change; the argument to `jl_init` is now -**JULIA_INIT_DIR** which is defined by *julia-config.jl*.: - ``` #include int main(int argc, char *argv[]) { - jl_init(JULIA_INIT_DIR); + jl_init(); (void)jl_eval_string("println(sqrt(2.0))"); jl_atexit_hook(0); return 0; diff --git a/src/jlapi.c b/src/jlapi.c index 34bb7f2ca6b44..94dcf9f6d2f0c 100644 --- a/src/jlapi.c +++ b/src/jlapi.c @@ -49,9 +49,19 @@ JL_DLLEXPORT void jl_init_with_image(const char *julia_home_dir, jl_exception_clear(); } -JL_DLLEXPORT void jl_init(const char *julia_home_dir) -{ - jl_init_with_image(julia_home_dir, NULL); +JL_DLLEXPORT void jl_init(void) +{ + char *libjldir = NULL; + + void *hdl = (void*)jl_load_dynamic_library_e(NULL, JL_RTLD_DEFAULT); + if (hdl) + libjldir = dirname((char*)jl_pathname_for_handle(hdl)); + if (libjldir) + jl_init_with_image(libjldir, jl_get_default_sysimg_path()); + else { + printf("jl_init unable to find libjulia!\n"); + abort(); + } } JL_DLLEXPORT jl_value_t *jl_eval_string(const char *str) diff --git a/src/julia.h b/src/julia.h index ebfc5b61286f7..208b3ce7eb186 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1316,13 +1316,14 @@ typedef enum { //JL_IMAGE_LIBJULIA = 2, } JL_IMAGE_SEARCH; JL_DLLEXPORT void julia_init(JL_IMAGE_SEARCH rel); -JL_DLLEXPORT void jl_init(const char *julia_home_dir); +JL_DLLEXPORT void jl_init(void); JL_DLLEXPORT void jl_init_with_image(const char *julia_home_dir, const char *image_relative_path); -JL_DLLEXPORT const char* jl_get_default_sysimg_path(); +JL_DLLEXPORT const char *jl_get_default_sysimg_path(void); JL_DLLEXPORT int jl_is_initialized(void); JL_DLLEXPORT void jl_atexit_hook(int status); JL_DLLEXPORT void JL_NORETURN jl_exit(int status); +JL_DLLEXPORT const char *jl_pathname_for_handle(void *handle); JL_DLLEXPORT int jl_deserialize_verify_header(ios_t *s); JL_DLLEXPORT void jl_preload_sysimg_so(const char *fname); From 1f05ba937c8f34cefb7464d66506fdd3fa7860e7 Mon Sep 17 00:00:00 2001 From: Isaiah Norton Date: Sun, 12 Feb 2017 17:37:07 -0500 Subject: [PATCH 0414/1534] remove redundant jl_show entry point --- examples/embedding/embedding.c | 2 +- src/jlapi.c | 1 - src/julia.h | 1 - src/rtutils.c | 21 +-------------------- src/toplevel.c | 2 -- ui/repl.c | 4 ++-- 6 files changed, 4 insertions(+), 27 deletions(-) diff --git a/examples/embedding/embedding.c b/examples/embedding/embedding.c index 1e66b91c1c289..3fc8c80d673ec 100644 --- a/examples/embedding/embedding.c +++ b/examples/embedding/embedding.c @@ -94,7 +94,7 @@ int main() jl_eval_string("this_function_does_not_exist()"); if (jl_exception_occurred()) { - jl_show(jl_stderr_obj(), jl_exception_occurred()); + jl_call2(jl_get_function(jl_base_module, "show"), jl_stderr_obj(), jl_exception_occurred()); jl_printf(jl_stderr_stream(), "\n"); } diff --git a/src/jlapi.c b/src/jlapi.c index 94dcf9f6d2f0c..7bdbc82e43a70 100644 --- a/src/jlapi.c +++ b/src/jlapi.c @@ -80,7 +80,6 @@ JL_DLLEXPORT jl_value_t *jl_eval_string(const char *str) jl_exception_clear(); } JL_CATCH { - //jl_show(jl_stderr_obj(), jl_exception_in_transit); r = NULL; } return r; diff --git a/src/julia.h b/src/julia.h index 208b3ce7eb186..9e3b6a2de60c7 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1667,7 +1667,6 @@ JL_DLLEXPORT JL_STREAM *jl_stdin_stream(void); JL_DLLEXPORT JL_STREAM *jl_stderr_stream(void); // showing and std streams -JL_DLLEXPORT void jl_show(jl_value_t *stream, jl_value_t *v); JL_DLLEXPORT void jl_flush_cstdio(void); JL_DLLEXPORT jl_value_t *jl_stdout_obj(void); JL_DLLEXPORT jl_value_t *jl_stderr_obj(void); diff --git a/src/rtutils.c b/src/rtutils.c index 7c84842e7eb14..66cb6bb3b7f39 100644 --- a/src/rtutils.c +++ b/src/rtutils.c @@ -439,24 +439,6 @@ JL_DLLEXPORT jl_value_t *jl_stderr_obj(void) return stderr_obj; } -static jl_function_t *jl_show_gf=NULL; - -JL_DLLEXPORT void jl_show(jl_value_t *stream, jl_value_t *v) -{ - if (jl_base_module) { - if (jl_show_gf == NULL) { - jl_show_gf = (jl_function_t*)jl_get_global(jl_base_module, jl_symbol("show")); - } - if (jl_show_gf==NULL || stream==NULL) { - jl_printf(JL_STDERR, " could not show value of type %s", - jl_symbol_name(((jl_datatype_t*)jl_typeof(v))->name->name)); - return; - } - jl_value_t *args[3] = {jl_show_gf,stream,v}; - jl_apply(args, 3); - } -} - // toys for debugging --------------------------------------------------------- static size_t jl_show_svec(JL_STREAM *out, jl_svec_t *t, const char *head, const char *opn, const char *cls) @@ -868,8 +850,7 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt static size_t jl_static_show_x(JL_STREAM *out, jl_value_t *v, struct recur_list *depth) { - // mimic jl_show, but never calling a julia method and - // never allocate through julia gc + // show values without calling a julia method or allocating through the GC if (v == NULL) { return jl_printf(out, "#"); } diff --git a/src/toplevel.c b/src/toplevel.c index 8d70905d9e494..37cf7f97e440f 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -461,8 +461,6 @@ static jl_method_instance_t *jl_new_thunk(jl_code_info_t *src, jl_module_t *modu jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast, int expanded) { jl_ptls_t ptls = jl_get_ptls_states(); - //jl_show(ex); - //jl_printf(JL_STDOUT, "\n"); if (!jl_is_expr(e)) { if (jl_is_linenode(e)) { jl_lineno = jl_linenode_line(e); diff --git a/ui/repl.c b/ui/repl.c index 4c998ce262695..5f8f066cccb46 100644 --- a/ui/repl.c +++ b/ui/repl.c @@ -52,7 +52,7 @@ static int exec_program(char *program) jl_value_t *errs = jl_stderr_obj(); jl_value_t *e = ptls->exception_in_transit; // Manually save and restore the backtrace so that we print the original - // one instead of the one caused by `jl_show`. + // one instead of the one caused by `show`. // We can't use safe_restore since that will cause any error // (including the ones that would have been caught) to abort. uintptr_t *volatile bt_data = NULL; @@ -61,7 +61,7 @@ static int exec_program(char *program) if (errs) { bt_data = (uintptr_t*)malloc(bt_size * sizeof(void*)); memcpy(bt_data, ptls->bt_data, bt_size * sizeof(void*)); - jl_show(errs, e); + jl_call2(jl_get_function(jl_base_module, "show"), errs, e); jl_printf(JL_STDERR, "\n"); free(bt_data); } From 87601aa5416147f410aca254ff18aa0da6248a70 Mon Sep 17 00:00:00 2001 From: Isaiah Norton Date: Sat, 25 Feb 2017 12:56:21 -0500 Subject: [PATCH 0415/1534] Run embedding test on appveyor and travis always use libexec for embedding executable --- .travis.yml | 3 ++- Make.inc | 1 + Makefile | 9 +++------ appveyor.yml | 2 +- base/Makefile | 1 + contrib/julia-config.jl | 12 ++++++++++-- contrib/windows/msys_build.sh | 1 + examples/Makefile | 7 +++++-- test/embedding.jl | 8 ++++++-- 9 files changed, 30 insertions(+), 14 deletions(-) diff --git a/.travis.yml b/.travis.yml index e8445b240c913..8c75dc224245f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -121,6 +121,7 @@ script: install -pm755 usr/lib/lib${name}*.dylib* /tmp/julia/lib/julia/; done; fi + - make $BUILDOPTS NO_GIT=1 prefix=/tmp/julia -C examples - cd .. && mv julia julia2 - /tmp/julia/bin/julia --precompiled=no -e 'true' && /tmp/julia/bin/julia-debug --precompiled=no -e 'true' @@ -128,7 +129,7 @@ script: - export JULIA_CPU_CORES=2 && export JULIA_TEST_MAXRSS_MB=600 && cd /tmp/julia/share/julia/test && /tmp/julia/bin/julia --check-bounds=yes runtests.jl $TESTSTORUN && - /tmp/julia/bin/julia --check-bounds=yes runtests.jl libgit2-online download pkg + /tmp/julia/bin/julia --check-bounds=yes runtests.jl libgit2-online download pkg embedding - cd `dirname $TRAVIS_BUILD_DIR` && mv julia2 julia && rm -f julia/deps/scratch/libgit2-*/CMakeFiles/CMakeOutput.log # uncomment the following if failures are suspected to be due to the out-of-memory killer diff --git a/Make.inc b/Make.inc index ffc1bde03162c..3bceb7bf8adb8 100644 --- a/Make.inc +++ b/Make.inc @@ -219,6 +219,7 @@ libdir_rel := $(shell $(JULIAHOME)/contrib/relative_path.sh $(bindir) $(libdir)) build_private_libdir_rel := $(shell $(JULIAHOME)/contrib/relative_path.sh $(build_bindir) $(build_private_libdir)) private_libdir_rel := $(shell $(JULIAHOME)/contrib/relative_path.sh $(bindir) $(private_libdir)) datarootdir_rel := $(shell $(JULIAHOME)/contrib/relative_path.sh $(bindir) $(datarootdir)) +libexecdir_rel := $(shell $(JULIAHOME)/contrib/relative_path.sh $(bindir) $(libexecdir)) docdir_rel := $(shell $(JULIAHOME)/contrib/relative_path.sh $(bindir) $(docdir)) sysconfdir_rel := $(shell $(JULIAHOME)/contrib/relative_path.sh $(bindir) $(sysconfdir)) includedir_rel := $(shell $(JULIAHOME)/contrib/relative_path.sh $(bindir) $(includedir)) diff --git a/Makefile b/Makefile index 4de0a1070ab38..846b252996923 100644 --- a/Makefile +++ b/Makefile @@ -68,15 +68,12 @@ $(build_prefix)/.examples: $(wildcard $(JULIAHOME)/examples/*.jl) \ @echo Copying in usr/share/doc/julia/examples @-rm -fr $(build_docdir)/examples @mkdir -p $(build_docdir)/examples - @mkdir -p $(build_docdir)/examples/embedding @cp -R $(JULIAHOME)/examples/*.jl $(build_docdir)/examples/ + @cp -R $(JULIAHOME)/examples/Makefile $(build_docdir)/examples/ @cp -R $(JULIAHOME)/examples/clustermanager $(build_docdir)/examples/ - @cp -R $(JULIAHOME)/examples/embedding $(build_docdir)/examples/embedding + @cp -R $(JULIAHOME)/examples/embedding $(build_docdir)/examples @echo 1 > $@ -examples: julia-sysimg-$(JULIA_BUILD_MODE) - @$(MAKE) $(QUIET_MAKE) -C $(BUILDROOT)/examples $(JULIA_BUILD_MODE) - julia-symlink: julia-ui-$(JULIA_BUILD_MODE) ifneq ($(OS),WINNT) ifndef JULIA_VAGRANT_BUILD @@ -114,7 +111,7 @@ julia-sysimg-release : julia-inference julia-ui-release julia-sysimg-debug : julia-inference julia-ui-debug @$(MAKE) $(QUIET_MAKE) -C $(BUILDROOT) $(build_private_libdir)/sys-debug$(CPUID_TAG).$(SHLIB_EXT) JULIA_BUILD_MODE=debug -julia-debug julia-release : julia-% : julia-ui-% julia-sysimg-% julia-symlink julia-libccalltest examples +julia-debug julia-release : julia-% : julia-ui-% julia-sysimg-% julia-symlink julia-libccalltest debug release : % : julia-% diff --git a/appveyor.yml b/appveyor.yml index b7bdb2e3e50fc..e8cec32f6c96b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -56,4 +56,4 @@ test_script: - usr\bin\julia -e "versioninfo()" - usr\bin\julia --precompiled=no -e "true" - cd test && ..\usr\bin\julia --check-bounds=yes runtests.jl all && - ..\usr\bin\julia --check-bounds=yes runtests.jl libgit2-online download pkg + ..\usr\bin\julia --check-bounds=yes runtests.jl libgit2-online download pkg embedding diff --git a/base/Makefile b/base/Makefile index 9edca7ec8f417..f3711fafefcb5 100644 --- a/base/Makefile +++ b/base/Makefile @@ -62,6 +62,7 @@ endif @echo "const DATAROOTDIR = \"$(datarootdir_rel)\"" >> $@ @echo "const DOCDIR = \"$(docdir_rel)\"" >> $@ @echo "const LIBDIR = \"$(libdir_rel)\"" >> $@ + @echo "const LIBEXECDIR = \"$(libexecdir_rel)\"" >> $@ @echo "const INCLUDEDIR = \"$(includedir_rel)\"" >> $@ @# This to ensure that we always rebuild this file, but only when it is modified do we touch build_h.jl, diff --git a/contrib/julia-config.jl b/contrib/julia-config.jl index 7a175bdf80078..2e18d760dc2f0 100755 --- a/contrib/julia-config.jl +++ b/contrib/julia-config.jl @@ -23,6 +23,8 @@ function libDir() end end +private_libDir() = joinpath(libDir(), "julia") + function includeDir() joinpath(match(r"(.*)(bin)",JULIA_HOME).captures[1],"include","julia") end @@ -49,7 +51,13 @@ function initDir() end function ldflags() - replace("""-L$(libDir())""","\\","\\\\") + fl = replace("""-L$(libDir())""","\\","\\\\") + if is_windows() + fl = fl * " -Wl,--stack,8388608" + elseif is_linux() + fl = fl * " -Wl,--export-dynamic" + end + return fl end function ldlibs() @@ -59,7 +67,7 @@ function ldlibs() "julia" end if is_unix() - return replace("""-Wl,-rpath,$(libDir()) -l$libname""","\\","\\\\") + return replace("""-Wl,-rpath,$(libDir()) -Wl,-rpath,$(private_libDir()) -l$libname""","\\","\\\\") else return "-l$libname -lopenlibm" end diff --git a/contrib/windows/msys_build.sh b/contrib/windows/msys_build.sh index 715a1c858ad43..f9c3c08aedba6 100755 --- a/contrib/windows/msys_build.sh +++ b/contrib/windows/msys_build.sh @@ -206,3 +206,4 @@ cat Make.user make -j3 VERBOSE=1 make build-stats #make debug +make VERBOSE=1 -C examples diff --git a/examples/Makefile b/examples/Makefile index 56e328bdd9c28..f1950b7d2f6a4 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -1,9 +1,12 @@ SRCDIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) BUILDDIR := . JULIAHOME := $(abspath $(SRCDIR)/..) +prefix := $(JULIAHOME)/usr include $(JULIAHOME)/Make.inc -embedding_binary := $(abspath $(build_libexecdir)/embedding$(JULIA_LIBSUFFIX)$(EXE)) +outdir := $(libexecdir) + +embedding_binary := $(abspath $(outdir)/embedding$(JULIA_LIBSUFFIX)$(EXE)) release: embedding debug: embedding-debug @@ -13,7 +16,7 @@ embedding-debug: $(embedding_binary) $(embedding_binary): $(wildcard embedding/*) @$(MAKE) $(QUIET_MAKE) -C $(BUILDROOT)/examples/embedding $(JULIA_BUILD_MODE) \ - JULIA="$(JULIA_EXECUTABLE)" BIN="$(build_libexecdir)" \ + JULIA="$(bindir)/julia$(JULIA_LIBSUFFIX)$(EXE)" BIN="$(outdir)" \ SPAWN="$(spawn)" CC="$(CC)" clean: diff --git a/test/embedding.jl b/test/embedding.jl index 2e78c45db10ca..628aa3e3781bd 100644 --- a/test/embedding.jl +++ b/test/embedding.jl @@ -1,8 +1,12 @@ # test that the embedding example runs without error let - embedding_bin = joinpath(JULIA_HOME,"..","libexec","embedding") + if is_windows() + embedding_bin = joinpath(JULIA_HOME,Base.LIBEXECDIR,"embedding.exe") + else + embedding_bin = joinpath(JULIA_HOME,Base.LIBEXECDIR,"embedding") + end lines = readlines(pipeline(`$(embedding_bin)`, stderr=DevNull)) - @test length(lines) == 5 + @test length(lines) == 6 @test parse(Float64, lines[1]) ≈ sqrt(2) end From b4d01d9ca54fce61b000be3337d1f3036922e86e Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 10 Apr 2017 17:14:41 -0400 Subject: [PATCH 0416/1534] improve location of private_libdir in julia-config.jl --- base/Makefile | 1 + contrib/julia-config.jl | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/base/Makefile b/base/Makefile index f3711fafefcb5..11515409e19e6 100644 --- a/base/Makefile +++ b/base/Makefile @@ -62,6 +62,7 @@ endif @echo "const DATAROOTDIR = \"$(datarootdir_rel)\"" >> $@ @echo "const DOCDIR = \"$(docdir_rel)\"" >> $@ @echo "const LIBDIR = \"$(libdir_rel)\"" >> $@ + @echo "const PRIVATE_LIBDIR = \"$(private_libdir_rel)\"" >> $@ @echo "const LIBEXECDIR = \"$(libexecdir_rel)\"" >> $@ @echo "const INCLUDEDIR = \"$(includedir_rel)\"" >> $@ diff --git a/contrib/julia-config.jl b/contrib/julia-config.jl index 2e18d760dc2f0..a61727213c187 100755 --- a/contrib/julia-config.jl +++ b/contrib/julia-config.jl @@ -23,7 +23,7 @@ function libDir() end end -private_libDir() = joinpath(libDir(), "julia") +private_libDir() = joinpath(JULIA_HOME, Base.PRIVATE_LIBDIR) function includeDir() joinpath(match(r"(.*)(bin)",JULIA_HOME).captures[1],"include","julia") From c691234704559b4126ac7f83bad008b32a2b9153 Mon Sep 17 00:00:00 2001 From: Martin Holters Date: Wed, 12 Apr 2017 09:26:38 +0200 Subject: [PATCH 0417/1534] Add tests for #20103 --- test/subtype.jl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/subtype.jl b/test/subtype.jl index 1d9747b5c26bd..b8bb66126aa37 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -1070,3 +1070,9 @@ end @testintersect(Tuple{A20992{R, D, d} where d where D, Int} where R, Tuple{C20992{S, n, T, D, d} where d where D where T where n where S, Any}, Tuple{C20992, Int}) + +# issue #20103, OP and comments +struct TT20103{X,Y} end +f20103{X,Y}(::Type{TT20103{X,Y}},x::X,y::Y) = 1 +f20103{X}(::Type{TT20103{X,X}},x::X) = 100 +@test_broken typeintersect(Type{NTuple{N,E}} where E where N, Type{NTuple{N,E} where N} where E) == Union{} # use @testintersect once fixed From d4010e58472f910727c42110a316eebeb83026ed Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Thu, 13 Apr 2017 10:35:40 +0200 Subject: [PATCH 0418/1534] add support for vscode editor (#21106) * add support for vscode editor * adress review --- base/interactiveutil.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/base/interactiveutil.jl b/base/interactiveutil.jl index d4c3a2bbe23f0..1d12a95249976 100644 --- a/base/interactiveutil.jl +++ b/base/interactiveutil.jl @@ -49,6 +49,8 @@ function edit(path::AbstractString, line::Integer=0) cmd = line != 0 ? `$command $path -l $line` : `$command $path` elseif startswith(name, "subl") || startswith(name, "atom") cmd = line != 0 ? `$command $path:$line` : `$command $path` + elseif name == "code" || (is_windows() && uppercase(name) == "CODE.EXE") + cmd = line != 0 ? `$command -g $path:$line` : `$command -g $path` elseif startswith(name, "notepad++") cmd = line != 0 ? `$command $path -n$line` : `$command $path` elseif is_apple() && name == "open" From 1e92102d3e30a8159a18cbefd081429aa8147611 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Thu, 13 Apr 2017 10:16:44 -0700 Subject: [PATCH 0419/1534] Add a test for merging a renamed file (#21364) --- test/libgit2.jl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/libgit2.jl b/test/libgit2.jl index 5265b84bde506..3a5def70e5ab8 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -724,6 +724,18 @@ mktempdir() do dir # merge them now that we allow non-ff @test LibGit2.merge!(repo, [upst_ann], false) @test LibGit2.is_ancestor_of(string(oldhead), string(LibGit2.head_oid(repo)), repo) + + # go back to merge_a and rename a file + LibGit2.branch!(repo, "branch/merge_b") + mv(joinpath(LibGit2.path(repo),"file1"),joinpath(LibGit2.path(repo),"mvfile1")) + LibGit2.add!(repo, "mvfile1") + LibGit2.commit(repo, "move file1") + LibGit2.branch!(repo, "master") + upst_ann = LibGit2.GitAnnotated(repo, "branch/merge_b") + rename_flag = 0 + rename_flag = LibGit2.toggle(rename_flag, 0) # turns on the find renames opt + mos = LibGit2.MergeOptions(flags=rename_flag) + @test LibGit2.merge!(repo, [upst_ann], merge_opts=mos) finally close(repo) end From 94417e46a16e26a51cc1171889659a192c15e6d6 Mon Sep 17 00:00:00 2001 From: Mus M Date: Thu, 13 Apr 2017 15:08:09 -0400 Subject: [PATCH 0420/1534] Use struct instead of immutable in misc places (#21372) --- base/deprecated.jl | 2 +- base/linalg/conjarray.jl | 2 +- doc/src/devdocs/functions.md | 2 +- doc/src/devdocs/subarrays.md | 2 +- doc/src/stdlib/simd-types.md | 2 +- test/inference.jl | 2 +- test/subtype.jl | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index 8b78df5a87bf7..1c8905f167136 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1174,7 +1174,7 @@ end ## the replacement StepRangeLen also has 4 real-valued fields, which ## makes deprecation tricky. See #20506. -immutable Use_StepRangeLen_Instead{T<:AbstractFloat} <: Range{T} +struct Use_StepRangeLen_Instead{T<:AbstractFloat} <: Range{T} start::T step::T len::T diff --git a/base/linalg/conjarray.jl b/base/linalg/conjarray.jl index 9cad2c8da5be4..065795042e44a 100644 --- a/base/linalg/conjarray.jl +++ b/base/linalg/conjarray.jl @@ -21,7 +21,7 @@ julia> ConjArray([1+im 0; 0 1-im]) 0+0im 1+1im ``` """ -immutable ConjArray{T, N, A <: AbstractArray} <: AbstractArray{T, N} +struct ConjArray{T, N, A <: AbstractArray} <: AbstractArray{T, N} parent::A end diff --git a/doc/src/devdocs/functions.md b/doc/src/devdocs/functions.md index 8c98d0d418028..77c3cefbe3802 100644 --- a/doc/src/devdocs/functions.md +++ b/doc/src/devdocs/functions.md @@ -80,7 +80,7 @@ end is lowered to (roughly): ```julia -immutable ##1{T} +struct ##1{T} x::T end diff --git a/doc/src/devdocs/subarrays.md b/doc/src/devdocs/subarrays.md index 8055e72865b38..4c6fdb5964ed0 100644 --- a/doc/src/devdocs/subarrays.md +++ b/doc/src/devdocs/subarrays.md @@ -55,7 +55,7 @@ any runtime overhead. The strategy adopted is first and foremost expressed in the definition of the type: ``` -immutable SubArray{T,N,P,I,L} <: AbstractArray{T,N} +struct SubArray{T,N,P,I,L} <: AbstractArray{T,N} parent::P indexes::I offset1::Int # for linear indexing and pointer, only valid when L==true diff --git a/doc/src/stdlib/simd-types.md b/doc/src/stdlib/simd-types.md index 7da49c924b32e..dbd362053c64c 100644 --- a/doc/src/stdlib/simd-types.md +++ b/doc/src/stdlib/simd-types.md @@ -4,7 +4,7 @@ Type `VecElement{T}` is intended for building libraries of SIMD operations. Prac requires using `llvmcall`. The type is defined as: ```julia -immutable VecElement{T} +struct VecElement{T} value::T end ``` diff --git a/test/inference.jl b/test/inference.jl index 6ed1e7068f270..062437d0a01f2 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -611,7 +611,7 @@ function i20343() f20343([1,2,3]..., 4) end @test Base.return_types(i20343, ()) == [Int8] -immutable Foo20518 <: AbstractVector{Int}; end # issue #20518; inference assumed AbstractArrays +struct Foo20518 <: AbstractVector{Int}; end # issue #20518; inference assumed AbstractArrays Base.getindex(::Foo20518, ::Int) = "oops" # not to lie about their element type Base.indices(::Foo20518) = (Base.OneTo(4),) foo20518(xs::Any...) = -1 diff --git a/test/subtype.jl b/test/subtype.jl index 1d9747b5c26bd..5abcb3a2d6166 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -622,7 +622,7 @@ abstract type AbstractTriangular{T,S<:AbstractMatrix} <: AbstractMatrix{T} end struct UpperTriangular{T,S<:AbstractMatrix} <: AbstractTriangular{T,S} end struct UnitUpperTriangular{T,S<:AbstractMatrix} <: AbstractTriangular{T,S} end -immutable SIQ20671{T<:Number,m,kg,s,A,K,mol,cd,rad,sr} <: Number +struct SIQ20671{T<:Number,m,kg,s,A,K,mol,cd,rad,sr} <: Number val::T end From cfe6666ae72b697b2f855850608996c57c143122 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 22 Mar 2017 16:59:15 -0400 Subject: [PATCH 0421/1534] i686.README: reference more correct lib32gfortran-6-dev package --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bc2a5936898df..e2e9f95a8f737 100644 --- a/README.md +++ b/README.md @@ -185,7 +185,7 @@ Julia does not install anything outside the directory it was cloned into. Julia Julia can be built for a non-generic architecture by configuring the `ARCH` Makefile variable. See the appropriate section of `Make.inc` for additional customization options, such as `MARCH` and `JULIA_CPU_TARGET`. -For example, to build for Pentium 4, set `MARCH=pentium4` and install the necessary system libraries for linking. On Ubuntu, these may include lib32gfortran3 (also manually call `ln -s /usr/lib32/libgfortran3.so.0 /usr/lib32/libgfortran3.so`) and lib32gcc1, lib32stdc++6, among others. +For example, to build for Pentium 4, set `MARCH=pentium4` and install the necessary system libraries for linking. On Ubuntu, these may include lib32gfortran-6-dev, lib32gcc1, and lib32stdc++6, among others. You can also set `MARCH=native` for a maximum-performance build customized for the current machine CPU. From b2c43cc644b130be1b66d06400bcd8ba052ae627 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 13 Apr 2017 17:07:04 -0400 Subject: [PATCH 0422/1534] fix #21370, regression in dynamic dispatch of complex constructors --- src/dump.c | 3 ++- src/gf.c | 3 ++- src/typemap.c | 19 ++++++++++++++----- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/dump.c b/src/dump.c index d482cd3cf5cdc..698c96ca69037 100644 --- a/src/dump.c +++ b/src/dump.c @@ -2379,7 +2379,8 @@ static void jl_reinit_item(jl_value_t *v, int how, arraylist_t *tracee_list) case 3: { // rehash MethodTable jl_methtable_t *mt = (jl_methtable_t*)v; jl_typemap_rehash(mt->defs, 0); - jl_typemap_rehash(mt->cache, (mt == jl_type_typename->mt) ? 0 : 1); + // TODO: consider reverting this when we can split on Type{...} better + jl_typemap_rehash(mt->cache, 1); //(mt == jl_type_typename->mt) ? 0 : 1); if (tracee_list) arraylist_push(tracee_list, mt); break; diff --git a/src/gf.c b/src/gf.c index 675d1bd07e1a1..a018ae0feebc3 100644 --- a/src/gf.c +++ b/src/gf.c @@ -134,7 +134,8 @@ const struct jl_typemap_info tfunc_cache = { static int8_t jl_cachearg_offset(jl_methtable_t *mt) { - return (mt == jl_type_type_mt) ? 0 : 1; + // TODO: consider reverting this when we can split on Type{...} better + return 1; //(mt == jl_type_type_mt) ? 0 : 1; } /// ----- Insertion logic for special entries ----- /// diff --git a/src/typemap.c b/src/typemap.c index b70accd357b87..3c48c310b8f6b 100644 --- a/src/typemap.c +++ b/src/typemap.c @@ -65,8 +65,7 @@ static int sig_match_by_type_simple(jl_value_t **types, size_t n, jl_tupletype_t } else if (!jl_is_kind(a) || !jl_is_typevar(tp0) || ((jl_tvar_t*)tp0)->ub != (jl_value_t*)jl_any_type) { // manually unroll jl_subtype(a, decl) - // where `a` can be a subtype like TypeConstructor - // and decl is Type{T} + // where `a` can be a subtype and decl is Type{T} return 0; } } @@ -142,8 +141,18 @@ static inline int sig_match_simple(jl_value_t **args, size_t n, jl_value_t **sig return 0; } else { - if (a!=tp0 && !(jl_typeof(a) == jl_typeof(tp0) && jl_types_equal(a,tp0))) - return 0; + if (a != tp0) { + if (jl_typeof(a) != jl_typeof(tp0)) + return 0; + jl_datatype_t *da = (jl_datatype_t*)a; + jl_datatype_t *dt = (jl_datatype_t*)tp0; + while (jl_is_unionall(da)) da = (jl_datatype_t*)((jl_unionall_t*)da)->body; + while (jl_is_unionall(dt)) dt = (jl_datatype_t*)((jl_unionall_t*)dt)->body; + if (jl_is_datatype(da) && jl_is_datatype(dt) && da->name != dt->name) + return 0; + if (!jl_types_equal(a, tp0)) + return 0; + } } } else { @@ -326,7 +335,7 @@ static union jl_typemap_t *mtcache_hash_bp(struct jl_ordereddict_t *pa, jl_value if (jl_is_datatype(ty)) { uintptr_t uid = ((jl_datatype_t*)ty)->uid; if (!uid || jl_is_kind(ty) || jl_has_free_typevars(ty)) - // be careful not to put non-leaf types or DataType/TypeConstructor in the cache here, + // be careful not to put non-leaf types or DataType/UnionAll in the cache here, // since they should have a lower priority and need to go into the sorted list return NULL; if (pa->values == (void*)jl_nothing) { From 261c716b9425e070b30a3e2dbee0af86b0a02f43 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 5 Apr 2017 14:28:49 -0400 Subject: [PATCH 0423/1534] add stdio dup call for fd on windows this ensures that another library calling _setmode or _dup2 does not affect our library output fix #21264 --- src/init.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/init.c b/src/init.c index 778be20efb38b..d87b5825348dc 100644 --- a/src/init.c +++ b/src/init.c @@ -317,9 +317,15 @@ static void *init_stdio_handle(uv_file fd,int readable) #ifndef _OS_WINDOWS_ // Duplicate the file descriptor so we can later dup it over if we want to redirect // STDIO without having to worry about closing the associated libuv object. + // This also helps limit the impact other libraries can cause on our file handle. // On windows however, libuv objects remember streams by their HANDLE, so this is // unnecessary. fd = dup(fd); +#else + if (type == UV_FILE) { + fd = _dup(fd); + _setmode(fd, _O_BINARY); + } #endif //jl_printf(JL_STDOUT, "%d: %d -- %d\n", fd, type, 0); switch(type) { @@ -334,9 +340,14 @@ static void *init_stdio_handle(uv_file fd,int readable) case UV_UNKNOWN_HANDLE: // dup the descriptor with a new one pointing at the bit bucket ... #if defined(_OS_WINDOWS_) - _dup2(_open("NUL", O_RDWR | O_BINARY, _S_IREAD | _S_IWRITE), fd); + fd = _open("NUL", O_RDWR | O_BINARY, _S_IREAD | _S_IWRITE); #else - dup2(open("/dev/null", O_RDWR, S_IRUSR | S_IWUSR /* 0600 */ | S_IRGRP | S_IROTH /* 0644 */), fd); + { + int nullfd; + nullfd = open("/dev/null", O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH /* 0666 */); + dup2(nullfd, fd); + close(nullfd); + } #endif // ...and continue on as in the UV_FILE case case UV_FILE: From 5846b3d73c44f6b113fef3287ade2f69e5ab7acb Mon Sep 17 00:00:00 2001 From: Jim Garrison Date: Fri, 14 Apr 2017 10:10:09 -0400 Subject: [PATCH 0424/1534] Fix BLAS.gbmv doc (#21381) [av skip] --- base/linalg/blas.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/linalg/blas.jl b/base/linalg/blas.jl index 8b52ffffa3595..75c07ff7d7d12 100644 --- a/base/linalg/blas.jl +++ b/base/linalg/blas.jl @@ -555,11 +555,11 @@ sub-diagonals and `ku` super-diagonals. `alpha` and `beta` are scalars. Returns function gbmv! end """ - gbmv(trans, m, kl, ku, alpha, A, x, beta, y) + gbmv(trans, m, kl, ku, alpha, A, x) Returns `alpha*A*x` or `alpha*A'*x` according to [`trans`](@ref stdlib-blas-trans). The matrix `A` is a general band matrix of dimension `m` by `size(A,2)` with `kl` sub-diagonals and `ku` -super-diagonals. `alpha` and `beta` are scalars. +super-diagonals, and `alpha` is a scalar. """ function gbmv end From c0d01c90756569661f717152055ec1c5fc555ada Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Fri, 14 Apr 2017 07:36:29 -0400 Subject: [PATCH 0425/1534] Fix building of embedding example for out of tree build dont set prefix in examples/Makefile install libexecdir on windows too run make install on appveyor use installed julia exe to run tests on appveyor --- Make.inc | 2 +- Makefile | 7 +++---- appveyor.yml | 4 ++-- contrib/windows/msys_build.sh | 4 ++-- examples/Makefile | 1 - examples/embedding/Makefile | 7 +++++-- 6 files changed, 13 insertions(+), 12 deletions(-) diff --git a/Make.inc b/Make.inc index 3bceb7bf8adb8..568582c425d06 100644 --- a/Make.inc +++ b/Make.inc @@ -177,7 +177,7 @@ endif USE_GPL_LIBS ?= 1 # Directories where said libraries get installed to -prefix ?= $(abspath julia-$(JULIA_COMMIT)) +prefix ?= $(BUILDROOT)/julia-$(JULIA_COMMIT) bindir := $(prefix)/bin libdir := $(prefix)/lib libexecdir := $(prefix)/libexec diff --git a/Makefile b/Makefile index 846b252996923..337643c272bb7 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ all: debug release # sort is used to remove potential duplicates DIRS := $(sort $(build_bindir) $(build_depsbindir) $(build_libdir) $(build_private_libdir) $(build_libexecdir) $(build_includedir) $(build_includedir)/julia $(build_sysconfdir)/julia $(build_datarootdir)/julia $(build_man1dir)) ifneq ($(BUILDROOT),$(JULIAHOME)) -BUILDDIRS := $(BUILDROOT) $(addprefix $(BUILDROOT)/,base src ui doc deps test test/perf) +BUILDDIRS := $(BUILDROOT) $(addprefix $(BUILDROOT)/,base src ui doc deps test test/perf examples examples/embedding) BUILDDIRMAKE := $(addsuffix /Makefile,$(BUILDDIRS)) DIRS := $(DIRS) $(BUILDDIRS) $(BUILDDIRMAKE): | $(BUILDDIRS) @@ -339,16 +339,15 @@ install: $(build_depsbindir)/stringreplace $(BUILDROOT)/doc/_build/html/en/index done $(INSTALL_M) $(build_bindir)/julia* $(DESTDIR)$(bindir)/ + -cp -a $(build_libexecdir) $(DESTDIR)$(prefix) ifeq ($(OS),WINNT) -$(INSTALL_M) $(build_bindir)/*.dll $(DESTDIR)$(bindir)/ -$(INSTALL_M) $(build_libdir)/libjulia.dll.a $(DESTDIR)$(libdir)/ -$(INSTALL_M) $(build_libdir)/libjulia-debug.dll.a $(DESTDIR)$(libdir)/ -$(INSTALL_M) $(build_bindir)/libopenlibm.dll.a $(DESTDIR)$(libdir)/ else - -cp -a $(build_libexecdir) $(DESTDIR)$(prefix) - - # Copy over .dSYM directories directly ifeq ($(OS),Darwin) + # Copy over .dSYM directories directly -cp -a $(build_libdir)/*.dSYM $(DESTDIR)$(libdir) -cp -a $(build_private_libdir)/*.dSYM $(DESTDIR)$(private_libdir) endif diff --git a/appveyor.yml b/appveyor.yml index e8cec32f6c96b..e2f7543300df3 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -55,5 +55,5 @@ build_script: test_script: - usr\bin\julia -e "versioninfo()" - usr\bin\julia --precompiled=no -e "true" - - cd test && ..\usr\bin\julia --check-bounds=yes runtests.jl all && - ..\usr\bin\julia --check-bounds=yes runtests.jl libgit2-online download pkg embedding + - cd julia-* && .\bin\julia.exe --check-bounds=yes share\julia\test\runtests.jl all && + .\bin\julia.exe --check-bounds=yes share\julia\test\runtests.jl libgit2-online download pkg embedding diff --git a/contrib/windows/msys_build.sh b/contrib/windows/msys_build.sh index f9c3c08aedba6..500171f72c4d7 100755 --- a/contrib/windows/msys_build.sh +++ b/contrib/windows/msys_build.sh @@ -203,7 +203,7 @@ fi echo 'FORCE_ASSERTIONS = 1' >> Make.user cat Make.user -make -j3 VERBOSE=1 +make -j3 VERBOSE=1 install +cp usr/bin/busybox.exe julia-*/bin make build-stats -#make debug make VERBOSE=1 -C examples diff --git a/examples/Makefile b/examples/Makefile index f1950b7d2f6a4..bc065d751530b 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -1,7 +1,6 @@ SRCDIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) BUILDDIR := . JULIAHOME := $(abspath $(SRCDIR)/..) -prefix := $(JULIAHOME)/usr include $(JULIAHOME)/Make.inc outdir := $(libexecdir) diff --git a/examples/embedding/Makefile b/examples/embedding/Makefile index 4ad51f5ce46d8..c5710924abbb8 100644 --- a/examples/embedding/Makefile +++ b/examples/embedding/Makefile @@ -11,6 +11,9 @@ ifndef BIN endif #============================================================================= +# this source directory where embedding.c is located +SRCDIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) + # get the executable suffix, if any EXE := $(suffix $(abspath $(JULIA))) @@ -26,10 +29,10 @@ DEBUGFLAGS += -g release: $(BIN)/embedding$(EXE) debug: $(BIN)/embedding-debug$(EXE) -$(BIN)/embedding$(EXE): embedding.c +$(BIN)/embedding$(EXE): $(SRCDIR)/embedding.c $(CC) $^ -o $@ $(CFLAGS) -$(BIN)/embedding-debug$(EXE): embedding.c +$(BIN)/embedding-debug$(EXE): $(SRCDIR)/embedding.c $(CC) $^ -o $@ $(CFLAGS) $(DEBUGFLAGS) clean: From 52607b07f60d1d5dbea2ae7f64f77c4f877072c6 Mon Sep 17 00:00:00 2001 From: Nathan Daly Date: Fri, 14 Apr 2017 09:39:33 -0500 Subject: [PATCH 0426/1534] Docs wording cleanup to mathematical-operations.md. (#21363) Minor wording fixes (left over from #21338) to doc/src/manual/mathematical-operations.md. --- doc/src/manual/mathematical-operations.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/src/manual/mathematical-operations.md b/doc/src/manual/mathematical-operations.md index 38d291270dc74..718d95b5ad2aa 100644 --- a/doc/src/manual/mathematical-operations.md +++ b/doc/src/manual/mathematical-operations.md @@ -335,12 +335,12 @@ should be used explicitly (see [Short-Circuit Evaluation](@ref)). Julia provides a comprehensive collection of mathematical functions and operators. These mathematical operations are defined over as broad a class of numerical values as permit sensible definitions, -including integers, floating-point numbers, rationals, and complexes, wherever such definitions -make sense. +including integers, floating-point numbers, rationals, and complex numbers, +wherever such definitions make sense. Moreover, these functions (like any Julia function) can be applied in "vectorized" fashion to arrays and other collections with the [dot syntax](@ref man-vectorized) `f.(A)`, -e.g. `sin.(A)` will compute the elementwise sine of each element of an array `A`. +e.g. `sin.(A)` will compute the sine of each element of an array `A`. ## Operator Precedence From 0bbccf1ecd5f6c2596e3fe91f463efd4446cefb6 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 14 Apr 2017 11:31:27 -0400 Subject: [PATCH 0427/1534] speed up BitArray `reshape` This mitigates a slight performance regression due to the change in constructor dispatch. --- base/bitarray.jl | 2 +- base/multidimensional.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/base/bitarray.jl b/base/bitarray.jl index 53b81513146b5..51598bcf04516 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -476,7 +476,7 @@ function reshape{N}(B::BitArray, dims::NTuple{N,Int}) prod(dims) == length(B) || throw(DimensionMismatch("new dimensions $(dims) must be consistent with array size $(length(B))")) dims == size(B) && return B - Br = BitArray{N}(ntuple(i->0,N)...) + Br = BitArray{N}(ntuple(i->0,Val{N})...) Br.chunks = B.chunks Br.len = prod(dims) N != 1 && (Br.dims = dims) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 0e50fdd342c9e..f4850926aa878 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -1198,7 +1198,7 @@ end @generated function findn{N}(B::BitArray{N}) quote nnzB = countnz(B) - I = ntuple(x->Array{Int}(nnzB), $N) + I = ntuple(x->Array{Int}(nnzB), Val{$N}) if nnzB > 0 count = 1 @nloops $N i B begin From 7bb938e9fc56f8252af253650f731fb263986bdd Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Fri, 14 Apr 2017 11:04:42 -0500 Subject: [PATCH 0428/1534] Remove need for temp_rel_pkg_dir --- test/pkg.jl | 34 +++++++++------------------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/test/pkg.jl b/test/pkg.jl index ee9fc64103b33..bbe361d345934 100644 --- a/test/pkg.jl +++ b/test/pkg.jl @@ -18,10 +18,11 @@ function capture_stdout(f::Function) end -function temp_pkg_dir(fn::Function, remove_tmp_dir::Bool=true) +function temp_pkg_dir(fn::Function, tmp_dir=joinpath(tempdir(), randstring()), + remove_tmp_dir::Bool=true) + # Used in tests below to set up and tear down a sandboxed package directory - const tmpdir = joinpath(tempdir(),randstring()) - withenv("JULIA_PKGDIR" => tmpdir) do + withenv("JULIA_PKGDIR" => tmp_dir) do @test !isdir(Pkg.dir()) try Pkg.init() @@ -29,7 +30,7 @@ function temp_pkg_dir(fn::Function, remove_tmp_dir::Bool=true) Pkg.resolve() fn() finally - remove_tmp_dir && rm(tmpdir, recursive=true) + remove_tmp_dir && rm(tmp_dir, recursive=true) end end end @@ -569,28 +570,11 @@ let io = IOBuffer() @test !contains(String(take!(io)), "backtrace()") end - -function temp_rel_pkg_dir(fn::Function, remove_tmp_dir::Bool=true) - # Used in tests below to set up and tear down a sandboxed package directory +@testset "Relative path operations" begin cd(tempdir()) do - const tmpdir = randstring() - withenv("JULIA_PKGDIR" => tmpdir) do - @test !isdir(Pkg.dir()) - try - Pkg.init() - @test isdir(Pkg.dir()) - Pkg.resolve() - fn() - finally - remove_tmp_dir && rm(tmpdir, recursive=true) - end + temp_pkg_dir(randstring()) do + Pkg.add("Example") + @test [keys(Pkg.installed())...] == ["Example"] end end end - -@testset "Relative path operations" begin - temp_rel_pkg_dir() do - Pkg.add("Example") - @test [keys(Pkg.installed())...] == ["Example"] - end -end From 94f1f8530402ab830bc31ffcdbc4192fd905fb35 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Sat, 14 Jan 2017 12:03:51 -0600 Subject: [PATCH 0429/1534] Exit calls in build scripts no longer abort build --- base/pkg/entry.jl | 26 ++++++++++++++++---------- test/pkg.jl | 42 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 54 insertions(+), 14 deletions(-) diff --git a/base/pkg/entry.jl b/base/pkg/entry.jl index 13f9abcb6d867..63ff84ae05475 100644 --- a/base/pkg/entry.jl +++ b/base/pkg/entry.jl @@ -609,19 +609,25 @@ function build!(pkgs::Vector, errs::Dict, seen::Set=Set()) empty!(Base.DL_LOAD_PATH) append!(Base.DL_LOAD_PATH, $(repr(Base.DL_LOAD_PATH))) open("$(escape_string(errfile))", "a") do f - for path in eachline(STDIN) - pkg = basename(dirname(dirname(path))) - try - info("Building \$pkg") - cd(dirname(path)) do - evalfile(path) + pkg = "" + atexit(() -> !isempty(pkg) && run_build()) + function run_build() + for path in eachline(STDIN) + pkg = basename(dirname(dirname(path))) + try + info("Building \$pkg") + cd(dirname(path)) do + evalfile(path) + end + catch err + Base.Pkg.Entry.warnbanner(err, label="[ ERROR: \$pkg ]") + serialize(f, pkg) + serialize(f, err) end - catch err - Base.Pkg.Entry.warnbanner(err, label="[ ERROR: \$pkg ]") - serialize(f, pkg) - serialize(f, err) end end + run_build() + pkg = "" end """ io, pobj = open(pipeline(detach(`$(Base.julia_cmd()) -O0 diff --git a/test/pkg.jl b/test/pkg.jl index bbe361d345934..afbf89adef932 100644 --- a/test/pkg.jl +++ b/test/pkg.jl @@ -19,15 +19,19 @@ end function temp_pkg_dir(fn::Function, tmp_dir=joinpath(tempdir(), randstring()), - remove_tmp_dir::Bool=true) + remove_tmp_dir::Bool=true; initialize::Bool=true) # Used in tests below to set up and tear down a sandboxed package directory withenv("JULIA_PKGDIR" => tmp_dir) do @test !isdir(Pkg.dir()) try - Pkg.init() - @test isdir(Pkg.dir()) - Pkg.resolve() + if initialize + Pkg.init() + @test isdir(Pkg.dir()) + Pkg.resolve() + else + mkpath(Pkg.dir()) + end fn() finally remove_tmp_dir && rm(tmp_dir, recursive=true) @@ -578,3 +582,33 @@ end end end end + +temp_pkg_dir(initialize=false) do + function write_build(pkg, content) + build_filename = Pkg.dir(pkg, "deps", "build.jl") + mkpath(dirname(build_filename)) + write(build_filename, content) + end + + write_build("Normal", "") + write_build("Error", "error(\"An error has occurred while building a package\")") + write_build("Exit", "exit()") + + cd(Pkg.dir()) do + errors = Dict() + + empty!(errors) + @test_warn ("INFO: Building Error", + "INFO: Building Normal") Pkg.Entry.build!(["Error", "Normal"], errors) + + empty!(errors) + @test_warn ("INFO: Building Exit", + "INFO: Building Normal") Pkg.Entry.build!(["Exit", "Normal"], errors) + + empty!(errors) + @test_warn ("INFO: Building Exit", + "INFO: Building Normal", + "INFO: Building Exit", + "INFO: Building Normal") Pkg.Entry.build!(["Exit", "Normal", "Exit", "Normal"], errors) + end +end From 7a3c2fe383b257a2b3ceeeff9215941269f6126d Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Tue, 24 Jan 2017 11:09:40 -0600 Subject: [PATCH 0430/1534] Isolate each build.jl in a seperate Julia process --- base/pkg/entry.jl | 87 ++++++++++++++++++++--------------------------- 1 file changed, 37 insertions(+), 50 deletions(-) diff --git a/base/pkg/entry.jl b/base/pkg/entry.jl index 63ff84ae05475..d5fea32de717c 100644 --- a/base/pkg/entry.jl +++ b/base/pkg/entry.jl @@ -579,26 +579,9 @@ function warnbanner(msg...; label="[ WARNING ]", prefix="") warn(prefix="", "="^cols) end -function build!(pkgs::Vector, buildstream::IO, seen::Set) - for pkg in pkgs - pkg == "julia" && continue - pkg in seen ? continue : push!(seen,pkg) - Read.isinstalled(pkg) || throw(PkgError("$pkg is not an installed package")) - build!(Read.requires_list(pkg),buildstream,seen) - path = abspath(pkg,"deps","build.jl") - isfile(path) || continue - println(buildstream, path) # send to build process for evalfile - flush(buildstream) - end -end - -function build!(pkgs::Vector, errs::Dict, seen::Set=Set()) - # To isolate the build from the running Julia process, we - # execute the build.jl files in a separate process that - # is sitting there waiting for paths to evaluate. Errors - # are serialized to errfile for later retrieval into errs[pkg] - errfile = tempname() - close(open(errfile, "w")) # create empty file +function build(pkg::AbstractString, build_file::AbstractString, errfile::AbstractString) + # To isolate the build from the running Julia process, we execute each build.jl file in + # a separate process. Errors are serialized to errfile for later reporting. # TODO: serialize the same way the load cache does, not with strings LOAD_PATH = filter(x -> x isa AbstractString, Base.LOAD_PATH) code = """ @@ -609,37 +592,45 @@ function build!(pkgs::Vector, errs::Dict, seen::Set=Set()) empty!(Base.DL_LOAD_PATH) append!(Base.DL_LOAD_PATH, $(repr(Base.DL_LOAD_PATH))) open("$(escape_string(errfile))", "a") do f - pkg = "" - atexit(() -> !isempty(pkg) && run_build()) - function run_build() - for path in eachline(STDIN) - pkg = basename(dirname(dirname(path))) - try - info("Building \$pkg") - cd(dirname(path)) do - evalfile(path) - end - catch err - Base.Pkg.Entry.warnbanner(err, label="[ ERROR: \$pkg ]") - serialize(f, pkg) - serialize(f, err) - end + pkg, build_file = "$pkg", "$(escape_string(build_file))" + try + info("Building \$pkg") + cd(dirname(build_file)) do + evalfile(build_file) end + catch err + Base.Pkg.Entry.warnbanner(err, label="[ ERROR: \$pkg ]") + serialize(f, pkg) + serialize(f, err) end - run_build() - pkg = "" end """ - io, pobj = open(pipeline(detach(`$(Base.julia_cmd()) -O0 - --compilecache=$(Bool(Base.JLOptions().use_compilecache) ? "yes" : "no") - --history-file=no - --color=$(Base.have_color ? "yes" : "no") - --eval $code`), stderr=STDERR), "w", STDOUT) + cmd = `$(Base.julia_cmd()) -O0 + --compilecache=$(Bool(Base.JLOptions().use_compilecache) ? "yes" : "no") + --history-file=no + --color=$(Base.have_color ? "yes" : "no") + --eval $code` + + success(pipeline(cmd, stderr=STDERR)) +end + +function build!(pkgs::Vector, seen::Set, errfile::AbstractString) + for pkg in pkgs + pkg == "julia" && continue + pkg in seen ? continue : push!(seen,pkg) + Read.isinstalled(pkg) || throw(PkgError("$pkg is not an installed package")) + build!(Read.requires_list(pkg), seen, errfile) + path = abspath(pkg,"deps","build.jl") + isfile(path) || continue + build(pkg, path, errfile) || error("Build process failed.") + end +end + +function build!(pkgs::Vector, errs::Dict, seen::Set=Set()) + errfile = tempname() + touch(errfile) # create empty file try - build!(pkgs, io, seen) - close(io) - wait(pobj) - success(pobj) || error("Build process failed.") + build!(pkgs, seen, errfile) open(errfile, "r") do f while !eof(f) pkg = deserialize(f) @@ -647,10 +638,6 @@ function build!(pkgs::Vector, errs::Dict, seen::Set=Set()) errs[pkg] = err end end - catch err - close(io) - isa(err, PkgError) ? wait(pobj) : kill(pobj) - rethrow(err) finally isfile(errfile) && Base.rm(errfile) end From c3063d4eb6f0849ebf15c326d57c3fb8a39c95d3 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Fri, 14 Apr 2017 11:21:43 -0500 Subject: [PATCH 0431/1534] Switch to triple-backticks --- base/pkg/entry.jl | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/base/pkg/entry.jl b/base/pkg/entry.jl index d5fea32de717c..b794d25012f3b 100644 --- a/base/pkg/entry.jl +++ b/base/pkg/entry.jl @@ -605,11 +605,13 @@ function build(pkg::AbstractString, build_file::AbstractString, errfile::Abstrac end end """ - cmd = `$(Base.julia_cmd()) -O0 - --compilecache=$(Bool(Base.JLOptions().use_compilecache) ? "yes" : "no") - --history-file=no - --color=$(Base.have_color ? "yes" : "no") - --eval $code` + cmd = ``` + $(Base.julia_cmd()) -O0 + --compilecache=$(Bool(Base.JLOptions().use_compilecache) ? "yes" : "no") + --history-file=no + --color=$(Base.have_color ? "yes" : "no") + --eval $code + ``` success(pipeline(cmd, stderr=STDERR)) end From 4e7ec790b587f4fe26ce7620c83d3e3197b3c871 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 12 Apr 2017 17:41:57 -0400 Subject: [PATCH 0432/1534] make jl_init more friendly to embedded targets this throws the error messages directly when the problem occurs, rather than waiting until late to throw a generic "System image file not found" message --- base/options.jl | 12 ++--- base/replutil.jl | 15 ++++++ base/util.jl | 8 ++- src/dump.c | 64 +++++++++++------------- src/init.c | 117 +++++++++++++++++++++++++------------------- src/jitlayers.cpp | 10 ++++ src/julia.h | 1 + test/cmdlineargs.jl | 41 +++++++++++++++- test/misc.jl | 16 ++++-- 9 files changed, 185 insertions(+), 99 deletions(-) diff --git a/base/options.jl b/base/options.jl index ac8d7643680d5..af18585939ce6 100644 --- a/base/options.jl +++ b/base/options.jl @@ -40,15 +40,15 @@ end JLOptions() = unsafe_load(cglobal(:jl_options, JLOptions)) function show(io::IO, opt::JLOptions) - println(io, "JLOptions(") + print(io, "JLOptions(") fields = fieldnames(opt) nfields = length(fields) - for (i,f) in enumerate(fieldnames(opt)) - v = getfield(opt,f) + for (i, f) in enumerate(fields) + v = getfield(opt, i) if isa(v, Ptr{UInt8}) - v = v != C_NULL ? unsafe_string(v) : "" + v = (v != C_NULL) ? unsafe_string(v) : "" end - println(io, " ", f, " = ", repr(v), i < nfields ? "," : "") + print(io, f, " = ", repr(v), i < nfields ? ", " : "") end - print(io,")") + print(io, ")") end diff --git a/base/replutil.jl b/base/replutil.jl index 33e4f461d081d..e40e194a3762c 100644 --- a/base/replutil.jl +++ b/base/replutil.jl @@ -151,6 +151,21 @@ function show(io::IO, ::MIME"text/plain", s::String) end end +function show(io::IO, ::MIME"text/plain", opt::JLOptions) + println(io, "JLOptions(") + fields = fieldnames(opt) + nfields = length(fields) + for (i, f) in enumerate(fields) + v = getfield(opt, i) + if isa(v, Ptr{UInt8}) + v = (v != C_NULL) ? unsafe_string(v) : "" + end + println(io, " ", f, " = ", repr(v), i < nfields ? "," : "") + end + print(io, ")") +end + + # showing exception objects as descriptive error messages showerror(io::IO, ex) = show(io, ex) diff --git a/base/util.jl b/base/util.jl index 9a50ddf25db31..8e3e7010b3db8 100644 --- a/base/util.jl +++ b/base/util.jl @@ -619,7 +619,13 @@ function julia_cmd(julia=joinpath(JULIA_HOME, julia_exename())) `$julia -C$cpu_target -J$image_file --compile=$compile --depwarn=$depwarn` end -julia_exename() = ccall(:jl_is_debugbuild,Cint,())==0 ? "julia" : "julia-debug" +function julia_exename() + if ccall(:jl_is_debugbuild, Cint, ()) == 0 + return @static is_windows() ? "julia.exe" : "julia" + else + return @static is_windows() ? "julia-debug.exe" : "julia-debug" + end +end """ securezero!(o) diff --git a/src/dump.c b/src/dump.c index d482cd3cf5cdc..c404521b0822a 100644 --- a/src/dump.c +++ b/src/dump.c @@ -222,15 +222,11 @@ JL_DLLEXPORT int jl_running_on_valgrind(void) return RUNNING_ON_VALGRIND; } -static int jl_load_sysimg_so(void) +static void jl_load_sysimg_so(void) { #ifndef _OS_WINDOWS_ Dl_info dlinfo; #endif - // attempt to load the pre-compiled sysimage from jl_sysimg_handle - if (jl_sysimg_handle == 0) - return -1; - int imaging_mode = jl_generating_output() && !jl_options.incremental; // in --build mode only use sysimg data, not precompiled native code if (!imaging_mode && jl_options.use_precompiled==JL_OPTIONS_USE_PRECOMPILED_YES) { @@ -276,13 +272,9 @@ static int jl_load_sysimg_so(void) } #endif } - const char *sysimg_data = (const char*)jl_dlsym_e(jl_sysimg_handle, "jl_system_image_data"); - if (sysimg_data) { - size_t len = *(size_t*)jl_dlsym(jl_sysimg_handle, "jl_system_image_size"); - jl_restore_system_image_data(sysimg_data, len); - return 0; - } - return -1; + const char *sysimg_data = (const char*)jl_dlsym(jl_sysimg_handle, "jl_system_image_data"); + size_t len = *(size_t*)jl_dlsym(jl_sysimg_handle, "jl_system_image_size"); + jl_restore_system_image_data(sysimg_data, len); } static jl_value_t *jl_deserialize_gv(jl_serializer_state *s, jl_value_t *v) @@ -2552,30 +2544,31 @@ extern void jl_get_builtins(void); extern void jl_get_builtin_hooks(void); extern void jl_get_system_hooks(void); -// Takes in a path of the form "usr/lib/julia/sys.{ji,so}", as passed to jl_restore_system_image() +// Takes in a path of the form "usr/lib/julia/sys.so" (jl_restore_system_image should be passed the same string) JL_DLLEXPORT void jl_preload_sysimg_so(const char *fname) { - // If passed NULL, don't even bother - if (!fname) - return; + if (jl_sysimg_handle) + return; // embedded target already called jl_set_sysimg_so - // First, get "sys" from "sys.ji" - char *fname_shlib = (char*)alloca(strlen(fname)+1); - strcpy(fname_shlib, fname); - char *fname_shlib_dot = strrchr(fname_shlib, '.'); - if (fname_shlib_dot != NULL) { - if (!strcmp(fname_shlib_dot, ".ji")) - return; // .ji extension => load .ji file only - *fname_shlib_dot = 0; - } + char *dot = (char*) strrchr(fname, '.'); + int is_ji = (dot && !strcmp(dot, ".ji")); // Get handle to sys.so - jl_sysimg_handle = jl_load_dynamic_library_e(fname_shlib, JL_RTLD_LOCAL | JL_RTLD_NOW); + if (!is_ji) // .ji extension => load .ji file only + jl_set_sysimg_so(jl_load_dynamic_library(fname, JL_RTLD_LOCAL | JL_RTLD_NOW)); +} +// Allow passing in a module handle directly, rather than a path +JL_DLLEXPORT void jl_set_sysimg_so(void *handle) +{ // set cpu target if unspecified by user and available from sysimg // otherwise default to native. - if (jl_sysimg_handle && jl_options.cpu_target == NULL) - jl_options.cpu_target = (const char *)jl_dlsym(jl_sysimg_handle, "jl_sysimg_cpu_target"); + void* *jl_RTLD_DEFAULT_handle_pointer = (void**)jl_dlsym_e(handle, "jl_RTLD_DEFAULT_handle_pointer"); + if (!jl_RTLD_DEFAULT_handle_pointer || (void*)&jl_RTLD_DEFAULT_handle != *jl_RTLD_DEFAULT_handle_pointer) + jl_error("System image file failed consistency check: maybe opened the wrong version?"); + if (jl_options.cpu_target == NULL) + jl_options.cpu_target = (const char *)jl_dlsym(handle, "jl_sysimg_cpu_target"); + jl_sysimg_handle = handle; } static void jl_restore_system_image_from_stream(ios_t *f) @@ -2653,16 +2646,15 @@ static void jl_restore_system_image_from_stream(ios_t *f) JL_DLLEXPORT void jl_restore_system_image(const char *fname) { - char *dot = (char*) strrchr(fname, '.'); +#ifndef NDEBUG + char *dot = fname ? (char*)strrchr(fname, '.') : NULL; int is_ji = (dot && !strcmp(dot, ".ji")); + assert((is_ji || jl_sysimg_handle) && "System image file not preloaded"); +#endif - if (!is_ji) { - int err = jl_load_sysimg_so(); - if (err != 0) { - if (jl_sysimg_handle == 0) - jl_errorf("System image file \"%s\" not found.", fname); - jl_errorf("Library \"%s\" does not contain a valid system image.", fname); - } + if (jl_sysimg_handle) { + // load the pre-compiled sysimage from jl_sysimg_handle + jl_load_sysimg_so(); } else { ios_t f; diff --git a/src/init.c b/src/init.c index 778be20efb38b..765db589cedd5 100644 --- a/src/init.c +++ b/src/init.c @@ -190,10 +190,52 @@ void jl_init_timing(void); void jl_destroy_timing(void); void jl_uv_call_close_callback(jl_value_t *val); +static void jl_close_item_atexit(uv_handle_t *handle) +{ + if (handle->type != UV_FILE && uv_is_closing(handle)) + return; + switch(handle->type) { + case UV_PROCESS: + // cause Julia to forget about the Process object + if (handle->data) + jl_uv_call_close_callback((jl_value_t*)handle->data); + // and make libuv think it is already dead + ((uv_process_t*)handle)->pid = 0; + // fall-through + case UV_TTY: + case UV_UDP: + case UV_TCP: + case UV_NAMED_PIPE: + case UV_POLL: + case UV_TIMER: + case UV_ASYNC: + case UV_FS_EVENT: + case UV_FS_POLL: + case UV_IDLE: + case UV_PREPARE: + case UV_CHECK: + case UV_SIGNAL: + case UV_FILE: + // These will be shutdown as appropriate by jl_close_uv + jl_close_uv(handle); + break; + case UV_HANDLE: + case UV_STREAM: + case UV_UNKNOWN_HANDLE: + case UV_HANDLE_TYPE_MAX: + case UV_RAW_FD: + case UV_RAW_HANDLE: + default: + assert(0); + } +} + JL_DLLEXPORT void jl_atexit_hook(int exitcode) { jl_ptls_t ptls = jl_get_ptls_states(); - if (exitcode == 0) jl_write_compiler_output(); + + if (exitcode == 0) + jl_write_compiler_output(); jl_print_gc_stats(JL_STDERR); if (jl_options.code_coverage) jl_write_coverage_data(); @@ -203,10 +245,10 @@ JL_DLLEXPORT void jl_atexit_hook(int exitcode) jl_value_t *f = jl_get_global(jl_base_module, jl_symbol("_atexit")); if (f != NULL) { JL_TRY { - size_t last_age = jl_get_ptls_states()->world_age; - jl_get_ptls_states()->world_age = jl_get_world_counter(); + size_t last_age = ptls->world_age; + ptls->world_age = jl_get_world_counter(); jl_apply(&f, 1); - jl_get_ptls_states()->world_age = last_age; + ptls->world_age = last_age; } JL_CATCH { jl_printf(JL_STDERR, "\natexit hook threw an error: "); @@ -231,62 +273,33 @@ JL_DLLEXPORT void jl_atexit_hook(int exitcode) struct uv_shutdown_queue queue = {NULL, NULL}; uv_walk(loop, jl_uv_exitcleanup_walk, &queue); struct uv_shutdown_queue_item *item = queue.first; - while (item) { - JL_TRY { - while (item) { - uv_handle_t *handle = item->h; - if (handle->type != UV_FILE && uv_is_closing(handle)) { + if (ptls->current_task != NULL) { + while (item) { + JL_TRY { + while (item) { + jl_close_item_atexit(item->h); item = next_shutdown_queue_item(item); - continue; - } - switch(handle->type) { - case UV_PROCESS: - // cause Julia to forget about the Process object - if (handle->data) - jl_uv_call_close_callback((jl_value_t*)handle->data); - // and make libuv think it is already dead - ((uv_process_t*)handle)->pid = 0; - // fall-through - case UV_TTY: - case UV_UDP: - case UV_TCP: - case UV_NAMED_PIPE: - case UV_POLL: - case UV_TIMER: - case UV_ASYNC: - case UV_FS_EVENT: - case UV_FS_POLL: - case UV_IDLE: - case UV_PREPARE: - case UV_CHECK: - case UV_SIGNAL: - case UV_FILE: - // These will be shutdown as appropriate by jl_close_uv - jl_close_uv(handle); - break; - case UV_HANDLE: - case UV_STREAM: - case UV_UNKNOWN_HANDLE: - case UV_HANDLE_TYPE_MAX: - case UV_RAW_FD: - case UV_RAW_HANDLE: - default: - assert(0); } + } + JL_CATCH { + //error handling -- continue cleanup, as much as possible + uv_unref(item->h); + jl_printf(JL_STDERR, "error during exit cleanup: close: "); + jl_static_show(JL_STDERR, ptls->exception_in_transit); item = next_shutdown_queue_item(item); } } - JL_CATCH { - //error handling -- continue cleanup, as much as possible - uv_unref(item->h); - jl_printf(JL_STDERR, "error during exit cleanup: close: "); - jl_static_show(JL_STDERR, ptls->exception_in_transit); + } + else { + while (item) { + jl_close_item_atexit(item->h); item = next_shutdown_queue_item(item); } } + // force libuv to spin until everything has finished closing loop->stop_flag = 0; - while (uv_run(loop,UV_RUN_DEFAULT)) {} + while (uv_run(loop, UV_RUN_DEFAULT)) { } jl_destroy_timing(); #ifdef ENABLE_TIMINGS @@ -527,9 +540,11 @@ void _julia_init(JL_IMAGE_SEARCH rel) // best to call this first, since it also initializes libuv jl_init_signal_async(); restore_signals(); + jl_resolve_sysimg_location(rel); // loads sysimg if available, and conditionally sets jl_options.cpu_target - jl_preload_sysimg_so(jl_options.image_file); + if (jl_options.image_file) + jl_preload_sysimg_so(jl_options.image_file); if (jl_options.cpu_target == NULL) jl_options.cpu_target = "native"; diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index 27eca4c7e3c14..ddb71b565c807 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -1121,6 +1121,16 @@ static void jl_gen_llvm_globaldata(llvm::Module *mod, ValueToValueMapTy &VMap, feature_string, "jl_sysimg_cpu_target")); + // reflect the address of the jl_RTLD_DEFAULT_handle variable + // back to the caller, so that we can check for consistency issues + GlobalValue *jlRTLD_DEFAULT_var = mod->getNamedValue("jl_RTLD_DEFAULT_handle"); + addComdat(new GlobalVariable(*mod, + jlRTLD_DEFAULT_var->getType(), + true, + GlobalVariable::ExternalLinkage, + jlRTLD_DEFAULT_var, + "jl_RTLD_DEFAULT_handle_pointer")); + #ifdef HAVE_CPUID // For native also store the cpuid if (strcmp(jl_options.cpu_target,"native") == 0) { diff --git a/src/julia.h b/src/julia.h index f9c520c0d4c59..1727d14f09040 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1324,6 +1324,7 @@ JL_DLLEXPORT void JL_NORETURN jl_exit(int status); JL_DLLEXPORT int jl_deserialize_verify_header(ios_t *s); JL_DLLEXPORT void jl_preload_sysimg_so(const char *fname); +JL_DLLEXPORT void jl_set_sysimg_so(void *handle); JL_DLLEXPORT ios_t *jl_create_system_image(void); JL_DLLEXPORT void jl_save_system_image(const char *fname); JL_DLLEXPORT void jl_restore_system_image(const char *fname); diff --git a/test/cmdlineargs.jl b/test/cmdlineargs.jl index 170b3b8c63a8b..47dda4097da81 100644 --- a/test/cmdlineargs.jl +++ b/test/cmdlineargs.jl @@ -62,8 +62,8 @@ let exename = `$(Base.julia_cmd()) --precompiled=yes --startup-file=no` @test !success(`$exename --load`) # --cpu-target - # NOTE: this test only holds true when there is a sys.{dll,dylib,so} shared library present. - if Libdl.dlopen_e(splitext(unsafe_string(Base.JLOptions().image_file))[1]) != C_NULL + # NOTE: this test only holds true if image_file is a shared library. + if Libdl.dlopen_e(unsafe_string(Base.JLOptions().image_file)) != C_NULL @test !success(`$exename -C invalidtarget --precompiled=yes`) @test !success(`$exename --cpu-target=invalidtarget --precompiled=yes`) else @@ -331,6 +331,43 @@ let exename = `$(Base.julia_cmd()) --precompiled=yes --startup-file=no` end end + +# Find the path of libjulia (or libjulia-debug, as the case may be) +# to use as a dummy shlib to open +libjulia = abspath(Libdl.dlpath((ccall(:jl_is_debugbuild, Cint, ()) != 0) ? "libjulia-debug" : "libjulia")) + +# test error handling code paths of running --sysimage +let exename = joinpath(JULIA_HOME, Base.julia_exename()), + sysname = unsafe_string(Base.JLOptions().image_file) + for nonexist_image in ( + joinpath(@__DIR__, "nonexistent"), + "$sysname.nonexistent", + ) + let stderr = Pipe(), + p = spawn(pipeline(`$exename --sysimage=$nonexist_image`, stderr=stderr)) + close(stderr.in) + let s = readstring(stderr) + @test contains(s, "ERROR: could not load library \"$nonexist_image\"\n") + @test !contains(s, "Segmentation fault") + @test !contains(s, "EXCEPTION_ACCESS_VIOLATION") + end + @test !success(p) + @test !Base.process_signaled(p) + @test p.exitcode == 1 + end + end + let stderr = Pipe(), + p = spawn(pipeline(`$exename --sysimage=$libjulia`, stderr=stderr)) + close(stderr.in) + let s = readstring(stderr) + @test s == "ERROR: System image file failed consistency check: maybe opened the wrong version?\n" + end + @test !success(p) + @test !Base.process_signaled(p) + @test p.exitcode == 1 + end +end + let exename = `$(Base.julia_cmd()) --precompiled=yes` # --startup-file let JL_OPTIONS_STARTUPFILE_ON = 1, diff --git a/test/misc.jl b/test/misc.jl index 27db61156ea91..a1e2b99096f77 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -514,9 +514,19 @@ if is_windows() end end -optstring = sprint(show, Base.JLOptions()) -@test startswith(optstring, "JLOptions(") -@test endswith(optstring, ")") +let optstring = stringmime(MIME("text/plain"), Base.JLOptions()) + @test startswith(optstring, "JLOptions(\n") + @test !contains(optstring, "Ptr") + @test endswith(optstring, "\n)") + @test contains(optstring, " = \"") +end +let optstring = repr(Base.JLOptions()) + @test startswith(optstring, "JLOptions(") + @test endswith(optstring, ")") + @test !contains(optstring, "\n") + @test !contains(optstring, "Ptr") + @test contains(optstring, " = \"") +end # Base.securezero! functions (#17579) import Base: securezero!, unsafe_securezero! From 669990bb8336cd66a7762dcf33297c1d7263ed9a Mon Sep 17 00:00:00 2001 From: strickek Date: Fri, 14 Apr 2017 22:38:04 +0200 Subject: [PATCH 0433/1534] Update types.jl Added Time in doc string of TimeType --- base/dates/types.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/dates/types.jl b/base/dates/types.jl index b1ef80aeb4ee4..3a2d67415339f 100644 --- a/base/dates/types.jl +++ b/base/dates/types.jl @@ -90,7 +90,7 @@ struct UTC <: TimeZone end TimeType `TimeType` types wrap `Instant` machine instances to provide human representations of the -machine instant. Both `DateTime` and `Date` are subtypes of `TimeType`. +machine instant. `Time`, `DateTime` and `Date` are subtypes of `TimeType`. """ abstract type TimeType <: AbstractTime end From 908b5b72f7f6642bfef31e67de6145cf8910f9ca Mon Sep 17 00:00:00 2001 From: Mus M Date: Fri, 14 Apr 2017 17:56:13 -0400 Subject: [PATCH 0434/1534] Use dirname in the location of the sys image path --- contrib/build_sysimg.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/build_sysimg.jl b/contrib/build_sysimg.jl index 50ba236dbb885..3fa8efafdb7f6 100644 --- a/contrib/build_sysimg.jl +++ b/contrib/build_sysimg.jl @@ -8,7 +8,7 @@ function default_sysimg_path(debug=false) if is_unix() splitext(Libdl.dlpath(debug ? "sys-debug" : "sys"))[1] else - joinpath(JULIA_HOME, "..", "lib", "julia", debug ? "sys-debug" : "sys") + joinpath(dirname(JULIA_HOME), "lib", "julia", debug ? "sys-debug" : "sys") end end From c30f950e86ef70029fb5f121f6796dce2f7d0ca7 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Sat, 15 Apr 2017 11:05:19 -0400 Subject: [PATCH 0435/1534] improve show-ambiguous to suggest a method intersection that could resolve the ambiguity (#21361) --- base/precompile.jl | 2 +- base/replutil.jl | 6 ++++++ base/show.jl | 24 +++++++++++------------- base/stacktraces.jl | 2 +- test/ambiguous.jl | 2 ++ 5 files changed, 21 insertions(+), 15 deletions(-) diff --git a/base/precompile.jl b/base/precompile.jl index b9d6f78bd41f9..01f9470161758 100644 --- a/base/precompile.jl +++ b/base/precompile.jl @@ -555,7 +555,7 @@ precompile(Tuple{typeof(Base.join), Base.IOContext{Base.Terminals.TTYTerminal}, precompile(Tuple{typeof(Base.show_method_params), Base.IOContext{Base.Terminals.TTYTerminal}, Array{Any, 1}}) precompile(Tuple{typeof(Base.print), Base.IOContext{Base.Terminals.TTYTerminal}, String, Module}) precompile(Tuple{typeof(Base.print), Base.IOContext{Base.Terminals.TTYTerminal}, String, Symbol, String, Int32}) -precompile(Tuple{typeof(Base.show_lambda_types), Base.IOContext{Base.Terminals.TTYTerminal}, Core.MethodInstance}) +precompile(Tuple{typeof(Base.show_tuple_as_call), Base.IOContext{Base.Terminals.TTYTerminal}, Symbol, Type}) precompile(Tuple{typeof(Base.print_with_color), Symbol, Base.IOContext{Base.Terminals.TTYTerminal}, String}) precompile(Tuple{typeof(Base.print_with_color), Int64, Base.IOContext{Base.Terminals.TTYTerminal}, String}) precompile(Tuple{typeof(Base.show), Base.IOContext{Base.Terminals.TTYTerminal}, Core.MethodInstance}) diff --git a/base/replutil.jl b/base/replutil.jl index 33e4f461d081d..8dbb703c219d6 100644 --- a/base/replutil.jl +++ b/base/replutil.jl @@ -414,8 +414,14 @@ function showerror_ambiguous(io::IO, meth, f, args) i < length(p) && print(io, ", ") end print(io, ") is ambiguous. Candidates:") + sigfix = Any for m in meth print(io, "\n ", m) + sigfix = typeintersect(m.sig, sigfix) + end + if isa(unwrap_unionall(sigfix), DataType) && sigfix <: Tuple + print(io, "\nPossible fix, define\n ") + Base.show_tuple_as_call(io, :function, sigfix) end nothing end diff --git a/base/show.jl b/base/show.jl index e526c0a653ded..fc81db8fb4018 100644 --- a/base/show.jl +++ b/base/show.jl @@ -313,7 +313,7 @@ function show(io::IO, l::Core.MethodInstance) show(io, l.def) else print(io, "MethodInstance for ") - show_lambda_types(io, l) + show_tuple_as_call(io, l.def.name, l.specTypes) end else print(io, "Toplevel MethodInstance thunk") @@ -1043,18 +1043,17 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int) nothing end -function show_lambda_types(io::IO, li::Core.MethodInstance) +function show_tuple_as_call(io::IO, name::Symbol, sig::Type) # print a method signature tuple for a lambda definition - local sig - returned_from_do = false - Base.with_output_color(have_color && get(io, :backtrace, false) ? stackframe_function_color() : :nothing, io) do io - if li.specTypes === Tuple - print(io, li.def.name, "(...)") - returned_from_do = true - return - end - sig = unwrap_unionall(li.specTypes).parameters - ft = sig[1]; uw = unwrap_unionall(ft) + color = have_color && get(io, :backtrace, false) ? stackframe_function_color() : :nothing + if sig === Tuple + Base.print_with_color(color, io, name, "(...)") + return + end + sig = unwrap_unionall(sig).parameters + Base.with_output_color(color, io) do io + ft = sig[1] + uw = unwrap_unionall(ft) if ft <: Function && isa(uw,DataType) && isempty(uw.parameters) && isdefined(uw.name.module, uw.name.mt.name) && ft == typeof(getfield(uw.name.module, uw.name.mt.name)) @@ -1066,7 +1065,6 @@ function show_lambda_types(io::IO, li::Core.MethodInstance) print(io, "(::", ft, ")") end end - returned_from_do && return first = true print_style = have_color && get(io, :backtrace, false) ? :bold : :nothing print_with_color(print_style, io, "(") diff --git a/base/stacktraces.jl b/base/stacktraces.jl index 2734f7c8c5392..cdff4d5a295e9 100644 --- a/base/stacktraces.jl +++ b/base/stacktraces.jl @@ -210,7 +210,7 @@ function show_spec_linfo(io::IO, frame::StackFrame) else linfo = get(frame.linfo) if isdefined(linfo, :def) - Base.show_lambda_types(io, linfo) + Base.show_tuple_as_call(io, linfo.def.name, linfo.specTypes) else Base.show(io, linfo) end diff --git a/test/ambiguous.jl b/test/ambiguous.jl index 43afcafc98c21..69e09a99627e5 100644 --- a/test/ambiguous.jl +++ b/test/ambiguous.jl @@ -60,6 +60,8 @@ let err = try startswith(str, " ambig(x::Integer, y) in $curmod_str at") @test ambig_checkline(lines[2]) @test ambig_checkline(lines[3]) + @test lines[4] == "Possible fix, define" + @test lines[5] == " ambig(::Integer, ::Integer)" end ## Other ways of accessing functions From c1a9aa235fec173f8cde37c8c654821af97910b8 Mon Sep 17 00:00:00 2001 From: Mus M Date: Sat, 15 Apr 2017 11:45:52 -0400 Subject: [PATCH 0436/1534] Use Vector where it makes sense --- base/bitarray.jl | 8 ++--- base/channels.jl | 2 +- base/essentials.jl | 4 +-- base/linalg/tridiag.jl | 2 +- base/sparse/cholmod.jl | 2 +- base/sparse/linalg.jl | 6 ++-- base/sparse/sparsevector.jl | 62 ++++++++++++++++++------------------- 7 files changed, 43 insertions(+), 43 deletions(-) diff --git a/base/bitarray.jl b/base/bitarray.jl index 53b81513146b5..af7d2097c9266 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -17,7 +17,7 @@ mutable struct BitArray{N} <: DenseArray{Bool, N} i += 1 end nc = num_bit_chunks(n) - chunks = Array{UInt64}(nc) + chunks = Vector{UInt64}(nc) nc > 0 && (chunks[end] = UInt64(0)) b = new(chunks, n) N != 1 && (b.dims = dims) @@ -1684,7 +1684,7 @@ end function find(B::BitArray) l = length(B) nnzB = countnz(B) - I = Array{Int}(nnzB) + I = Vector{Int}(nnzB) nnzB == 0 && return I Bc = B.chunks Bcount = 1 @@ -1718,8 +1718,8 @@ findn(B::BitVector) = find(B) function findn(B::BitMatrix) nnzB = countnz(B) - I = Array{Int}(nnzB) - J = Array{Int}(nnzB) + I = Vector{Int}(nnzB) + J = Vector{Int}(nnzB) count = 1 for j = 1:size(B,2), i = 1:size(B,1) if B[i,j] diff --git a/base/channels.jl b/base/channels.jl index 9c5d2290c4251..3b686f8f7fe26 100644 --- a/base/channels.jl +++ b/base/channels.jl @@ -23,7 +23,7 @@ mutable struct Channel{T} <: AbstractChannel state::Symbol excp::Nullable{Exception} # Exception to be thrown when state != :open - data::Array{T,1} + data::Vector{T} sz_max::Int # maximum size of channel # Used when sz_max == 0, i.e., an unbuffered channel. diff --git a/base/essentials.jl b/base/essentials.jl index 007bf2d347525..bcdcf5c221328 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -163,7 +163,7 @@ function append_any(xs...) # used by apply() and quote # must be a separate function from append(), since apply() needs this # exact function. - out = Array{Any}(4) + out = Vector{Any}(4) l = 4 i = 1 for x in xs @@ -329,7 +329,7 @@ end # used by interpolating quote and some other things in the front end function vector_any(xs::ANY...) n = length(xs) - a = Array{Any}(n) + a = Vector{Any}(n) @inbounds for i = 1:n Core.arrayset(a,xs[i],i) end diff --git a/base/linalg/tridiag.jl b/base/linalg/tridiag.jl index 0542a5edc91f3..3ac3810aba47d 100644 --- a/base/linalg/tridiag.jl +++ b/base/linalg/tridiag.jl @@ -327,7 +327,7 @@ function inv_usmani{T}(a::Vector{T}, b::Vector{T}, c::Vector{T}) for i=n-1:-1:1 φ[i] = b[i]*φ[i+1]-a[i]*c[i]*φ[i+2] end - α = Array{T}(n, n) + α = Matrix{T}(n, n) for i=1:n, j=1:n sign = (i+j)%2==0 ? (+) : (-) if i sparsevec(Dict(1 => 3, 2 => 2)) """ function sparsevec{Tv,Ti<:Integer}(dict::Associative{Ti,Tv}) m = length(dict) - nzind = Array{Ti}(m) - nzval = Array{Tv}(m) + nzind = Vector{Ti}(m) + nzval = Vector{Tv}(m) cnt = 0 len = zero(Ti) @@ -206,8 +206,8 @@ end function sparsevec{Tv,Ti<:Integer}(dict::Associative{Ti,Tv}, len::Integer) m = length(dict) - nzind = Array{Ti}(m) - nzval = Array{Tv}(m) + nzind = Vector{Ti}(m) + nzval = Vector{Tv}(m) cnt = 0 maxk = convert(Ti, len) @@ -322,8 +322,8 @@ function _dense2sparsevec{Tv,Ti}(s::AbstractArray{Tv}, initcap::Ti) # pre-condition: initcap > 0; the initcap determines the index type n = length(s) cap = initcap - nzind = Array{Ti}(cap) - nzval = Array{Tv}(cap) + nzind = Vector{Ti}(cap) + nzval = Vector{Tv}(cap) c = 0 @inbounds for i = 1:n v = s[i] @@ -478,8 +478,8 @@ function Base.getindex{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, i::Integer, J::Abstract nJ = length(J) colptrA = A.colptr; rowvalA = A.rowval; nzvalA = A.nzval - nzinds = Array{Ti}(0) - nzvals = Array{Tv}(0) + nzinds = Vector{Ti}(0) + nzvals = Vector{Tv}(0) # adapted from SparseMatrixCSC's sorted_bsearch_A ptrI = 1 @@ -512,8 +512,8 @@ function _logical_index{Tv}(A::SparseMatrixCSC{Tv}, I::AbstractArray{Bool}) nnzB = min(n, nnz(A)) colptrA = A.colptr; rowvalA = A.rowval; nzvalA = A.nzval - rowvalB = Array{Int}(nnzB) - nzvalB = Array{Tv}(nnzB) + rowvalB = Vector{Int}(nnzB) + nzvalB = Vector{Tv}(nnzB) c = 1 rowB = 1 @@ -557,8 +557,8 @@ function getindex{Tv}(A::SparseMatrixCSC{Tv}, I::UnitRange) n = length(I) nnzB = min(n, nnz(A)) - rowvalB = Array{Int}(nnzB) - nzvalB = Array{Tv}(nnzB) + rowvalB = Vector{Int}(nnzB) + nzvalB = Vector{Tv}(nnzB) rowstart,colstart = ind2sub(szA, first(I)) rowend,colend = ind2sub(szA, last(I)) @@ -592,8 +592,8 @@ function getindex{Tv}(A::SparseMatrixCSC{Tv}, I::AbstractVector) n = length(I) nnzB = min(n, nnz(A)) - rowvalB = Array{Int}(nnzB) - nzvalB = Array{Tv}(nnzB) + rowvalB = Vector{Int}(nnzB) + nzvalB = Vector{Tv}(nnzB) idxB = 1 for i in 1:n @@ -622,7 +622,7 @@ end function find{Ti}(x::SparseVector{<:Any,Ti}) numnz = nnz(x) - I = Array{Ti,1}(numnz) + I = Vector{Ti}(numnz) nzind = x.nzind nzval = x.nzval @@ -646,8 +646,8 @@ end function findnz{Tv,Ti}(x::SparseVector{Tv,Ti}) numnz = nnz(x) - I = Array{Ti,1}(numnz) - V = Array{Tv,1}(numnz) + I = Vector{Ti}(numnz) + V = Vector{Tv}(numnz) nzind = x.nzind nzval = x.nzval @@ -702,8 +702,8 @@ function getindex{Tv,Ti}(x::AbstractSparseVector{Tv,Ti}, I::UnitRange) # compute the number of non-zeros jrgn = j0:j1 mr = length(jrgn) - rind = Array{Ti}(mr) - rval = Array{Tv}(mr) + rind = Vector{Ti}(mr) + rval = Vector{Tv}(mr) if mr > 0 c = 0 for j in jrgn @@ -852,9 +852,9 @@ function _absspvec_hcat{Tv,Ti}(X::AbstractSparseVector{Tv,Ti}...) end # construction - colptr = Array{Ti}(n+1) - nzrow = Array{Ti}(tnnz) - nzval = Array{Tv}(tnnz) + colptr = Vector{Ti}(n+1) + nzrow = Vector{Ti}(tnnz) + nzval = Vector{Tv}(tnnz) roff = 1 @inbounds for j = 1:n xj = X[j] @@ -884,8 +884,8 @@ function _absspvec_vcat{Tv,Ti}(X::AbstractSparseVector{Tv,Ti}...) end # construction - rnzind = Array{Ti}(tnnz) - rnzval = Array{Tv}(tnnz) + rnzind = Vector{Ti}(tnnz) + rnzval = Vector{Tv}(tnnz) ir = 0 len = 0 @inbounds for j = 1:n @@ -999,8 +999,8 @@ macro unarymap_nz2z_z2z(op, TF) xnzval = nonzeros(x) m = length(xnzind) - ynzind = Array{Ti}(m) - ynzval = Array{R}(m) + ynzind = Vector{Ti}(m) + ynzval = Vector{R}(m) ir = 0 @inbounds for j = 1:m i = xnzind[j] @@ -1089,8 +1089,8 @@ function _binarymap{Tx,Ty}(f::Function, my = length(ynzind) cap = (mode == 0 ? min(mx, my) : mx + my)::Int - rind = Array{Int}(cap) - rval = Array{R}(cap) + rind = Vector{Int}(cap) + rval = Vector{R}(cap) ir = 0 ix = 1 iy = 1 @@ -1226,7 +1226,7 @@ function _binarymap{Tx,Ty}(f::Function, ynzval = nonzeros(y) m = length(ynzind) - dst = Array{R}(n) + dst = Vector{R}(n) if mode == 0 ii = 1 @inbounds for i = 1:m @@ -1268,7 +1268,7 @@ function _binarymap{Tx,Ty}(f::Function, xnzval = nonzeros(x) m = length(xnzind) - dst = Array{R}(n) + dst = Vector{R}(n) if mode == 0 ii = 1 @inbounds for i = 1:m From e0aee185e60d8afbb53d93404ddede203d1ddfaf Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sat, 15 Apr 2017 12:24:29 -0400 Subject: [PATCH 0437/1534] a few more optimizations for package loading ref #21173 --- src/subtype.c | 21 ++++++++++++++------- src/typemap.c | 23 +++++++++++++++++++++-- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/subtype.c b/src/subtype.c index 113cb1675085e..2e522778f7219 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -239,6 +239,11 @@ static int obviously_unequal(jl_value_t *a, jl_value_t *b) return 0; } +int jl_obviously_unequal(jl_value_t *a, jl_value_t *b) +{ + return obviously_unequal(a, b); +} + static int obviously_disjoint(jl_value_t *a, jl_value_t *b, int specificity) { if (a == b || a == (jl_value_t*)jl_any_type || b == (jl_value_t*)jl_any_type) @@ -542,8 +547,9 @@ static int subtype_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_t *e, int8 // in the environment, rename to get a fresh var. while (btemp != NULL) { if (btemp->var == u->var || - (btemp->lb != jl_bottom_type && jl_has_typevar(btemp->lb, u->var)) || - (btemp->ub != (jl_value_t*)jl_any_type && jl_has_typevar(btemp->ub, u->var))) { + // outer var can only refer to inner var if bounds changed + (btemp->lb != btemp->var->lb && jl_has_typevar(btemp->lb, u->var)) || + (btemp->ub != btemp->var->ub && jl_has_typevar(btemp->ub, u->var))) { u = rename_unionall(u); break; } @@ -627,7 +633,8 @@ static int subtype_unionall(jl_value_t *t, jl_unionall_t *u, jl_stenv_t *e, int8 btemp = e->vars; while (btemp != NULL) { jl_value_t *vi = btemp->ub; - if (vi != (jl_value_t*)vb.var && vi != (jl_value_t*)jl_any_type && jl_has_typevar(vi, vb.var)) { + // TODO: this takes a significant amount of time + if (vi != (jl_value_t*)vb.var && btemp->var->ub != vi && jl_has_typevar(vi, vb.var)) { btemp->ub = jl_new_struct(jl_unionall_type, vb.var, vi); btemp->lb = jl_bottom_type; } @@ -692,11 +699,11 @@ static int subtype_tuple(jl_datatype_t *xd, jl_datatype_t *yd, jl_stenv_t *e, in jl_value_t *lastx=NULL, *lasty=NULL; while (i < lx) { jl_value_t *xi = jl_tparam(xd, i); - if (jl_is_vararg_type(xi)) vx = 1; + if (i == lx-1 && vvx) vx = 1; jl_value_t *yi = NULL; if (j < ly) { yi = jl_tparam(yd, j); - if (jl_is_vararg_type(yi)) vy = 1; + if (j == ly-1 && vvy) vy = 1; } if (vx && !vy) { if (!check_vararg_length(xi, ly+1-lx, e)) @@ -892,9 +899,9 @@ static int subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param) xd = xd->super; } if (xd == jl_any_type) return 0; - if (jl_is_tuple_type(xd)) + if (xd->name == jl_tuple_typename) return subtype_tuple(xd, yd, e, param); - if (jl_is_vararg_type((jl_value_t*)xd)) { + if (xd->name == jl_vararg_typename) { // Vararg: covariant in first parameter, invariant in second jl_value_t *xp1=jl_tparam0(xd), *xp2=jl_tparam1(xd), *yp1=jl_tparam0(yd), *yp2=jl_tparam1(yd); // in Vararg{T1} <: Vararg{T2}, need to check subtype twice to diff --git a/src/typemap.c b/src/typemap.c index b70accd357b87..b5d7fc54d625a 100644 --- a/src/typemap.c +++ b/src/typemap.c @@ -641,15 +641,34 @@ static jl_typemap_entry_t *jl_typemap_assoc_by_type_(jl_typemap_entry_t *ml, jl_ return NULL; } +int jl_obviously_unequal(jl_value_t *a, jl_value_t *b); + static jl_typemap_entry_t *jl_typemap_lookup_by_type_(jl_typemap_entry_t *ml, jl_tupletype_t *types, size_t world) { for (; ml != (void*)jl_nothing; ml = ml->next) { if (world < ml->min_world || world > ml->max_world) continue; // TODO: more efficient - if (jl_types_equal((jl_value_t*)types, (jl_value_t*)ml->sig)) { - return ml; + jl_value_t *a = (jl_value_t*)types; + jl_value_t *b = (jl_value_t*)ml->sig; + while (jl_is_unionall(a)) a = ((jl_unionall_t*)a)->body; + while (jl_is_unionall(b)) b = ((jl_unionall_t*)b)->body; + size_t na = jl_nparams(a), nb = jl_nparams(b); + assert(na > 0 && nb > 0); + if (!jl_is_vararg_type(jl_tparam(a,na-1)) && !jl_is_vararg_type(jl_tparam(b,nb-1))) { + if (na != nb) + continue; + } + if (na > 1 && nb > 1) { + if (jl_obviously_unequal(jl_tparam(a,1), jl_tparam(b,1))) + continue; + if (na > 2 && nb > 2) { + if (jl_obviously_unequal(jl_tparam(a,2), jl_tparam(b,2))) + continue; + } } + if (jl_types_equal((jl_value_t*)types, (jl_value_t*)ml->sig)) + return ml; } return NULL; } From e7e3071cf48fe0ff125eb95b320caab5daa5d16a Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 14 Apr 2017 15:14:02 -0400 Subject: [PATCH 0438/1534] fix #21382, specificity problem with `DataType` --- src/subtype.c | 11 ++++++++--- test/core.jl | 4 ++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/subtype.c b/src/subtype.c index 113cb1675085e..6ca866179f070 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -2485,16 +2485,21 @@ static int type_morespecific_(jl_value_t *a, jl_value_t *b, int invariant, jl_ty } if (jl_is_type_type(a) && !invariant) { + if (b == (jl_value_t*)jl_typeofbottom_type) + return 0; jl_value_t *tp0a = jl_tparam0(a); if (jl_is_typevar(tp0a)) { - if (b == (jl_value_t*)jl_typeofbottom_type) - return 0; jl_value_t *ub = ((jl_tvar_t*)tp0a)->ub; if (jl_is_kind(b) && !jl_subtype((jl_value_t*)jl_any_type, ub)) return 1; } + else if (tp0a == jl_bottom_type) { + if (jl_subtype(b, (jl_value_t*)jl_type_type)) + return 1; + } else { - if (jl_isa(tp0a, b) || (tp0a == jl_bottom_type && jl_subtype(b, (jl_value_t*)jl_type_type))) + if (b == (jl_value_t*)jl_datatype_type || b == (jl_value_t*)jl_unionall_type || + b == (jl_value_t*)jl_uniontype_type || jl_isa(tp0a, b)) return 1; } } diff --git a/test/core.jl b/test/core.jl index 8fd63755a1f13..856941f06e1de 100644 --- a/test/core.jl +++ b/test/core.jl @@ -74,6 +74,10 @@ _z_z_z_(::Int, c...) = 3 # issue #21016 @test args_morespecific(Tuple{IO, Core.TypeofBottom}, Tuple{IO, Type{T}} where T<:Number) +# issue #21382 +@test args_morespecific(Tuple{Type{Pair{A,B} where B}} where A, Tuple{DataType}) +@test args_morespecific(Tuple{Union{Int,String},Type{Pair{A,B} where B}} where A, Tuple{Integer,UnionAll}) + # with bound varargs _bound_vararg_specificity_1{T,N}(::Type{Array{T,N}}, d::Vararg{Int, N}) = 0 From 914485dcaf51a9e6ba6661dfcb3d96d0915acbe1 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Sat, 15 Apr 2017 12:57:31 -0700 Subject: [PATCH 0439/1534] Add test for rebase getindex and non-HEAD branch show (#21386) --- test/libgit2.jl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/libgit2.jl b/test/libgit2.jl index 3a5def70e5ab8..b5c61ecb77a37 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -710,6 +710,15 @@ mktempdir() do dir # from branch/merge_a LibGit2.branch!(repo, "master") + # test for showing a Reference to a non-HEAD branch + brref = LibGit2.GitReference(repo, "refs/heads/branch/merge_a") + @test LibGit2.name(brref) == "refs/heads/branch/merge_a" + @test !LibGit2.ishead(brref) + show_strs = split(sprint(show, brref), "\n") + @test show_strs[1] == "GitReference:" + @test show_strs[2] == "Branch with name refs/heads/branch/merge_a" + @test show_strs[3] == "Branch is not HEAD." + open(joinpath(LibGit2.path(repo), "file2"), "w") do f write(f, "222\n") end @@ -1015,6 +1024,9 @@ mktempdir() do dir @test rbo_str == "RebaseOperation($(string(rbo.id)))\nOperation type: REBASE_OPERATION_PICK\n" rb_str = sprint(show, rb) @test rb_str == "GitRebase:\nNumber: 2\nCurrently performing operation: 1\n" + rbo = rb[2] + rbo_str = sprint(show, rbo) + @test rbo_str == "RebaseOperation($(string(rbo.id)))\nOperation type: REBASE_OPERATION_PICK\n" # test rebase abort LibGit2.abort(rb) From 4f56bf5fb69bfc907a1e6bbb4e39656bc8839448 Mon Sep 17 00:00:00 2001 From: Mus M Date: Sat, 15 Apr 2017 16:03:09 -0400 Subject: [PATCH 0440/1534] Update to where syntax for math files (#21388) * Update to using where syntax in math.jl and special/exp.jl * Update to using where syntax in float.jl * Update to using where synax in floatfuncs.jl --- base/float.jl | 40 ++++++++++++++++++++-------------------- base/floatfuncs.jl | 8 ++++---- base/math.jl | 24 ++++++++++++------------ base/special/exp.jl | 2 +- 4 files changed, 37 insertions(+), 37 deletions(-) diff --git a/base/float.jl b/base/float.jl index c66a655a2380a..69a37e277c092 100644 --- a/base/float.jl +++ b/base/float.jl @@ -64,7 +64,7 @@ for t1 in (Float32, Float64) end end convert(::Type{Integer}, x::Float16) = convert(Integer, Float32(x)) -convert{T<:Integer}(::Type{T}, x::Float16) = convert(T, Float32(x)) +convert(::Type{T}, x::Float16) where {T<:Integer} = convert(T, Float32(x)) promote_rule(::Type{Float64}, ::Type{UInt128}) = Float64 @@ -197,8 +197,8 @@ end # "Fast Half Float Conversion" by Jeroen van der Zijp # ftp://ftp.fox-toolkit.org/pub/fasthalffloatconversion.pdf -const basetable = Array{UInt16}(512) -const shifttable = Array{UInt8}(512) +const basetable = Vector{UInt16}(512) +const shifttable = Vector{UInt8}(512) for i = 0:255 e = i - 127 @@ -271,7 +271,7 @@ julia> float(Int) Float64 ``` """ -float{T<:Number}(::Type{T}) = typeof(float(zero(T))) +float(::Type{T}) where {T<:Number} = typeof(float(zero(T))) for Ti in (Int8, Int16, Int32, Int64) @eval begin @@ -327,15 +327,15 @@ trunc(::Type{Unsigned}, x::Float32) = trunc(UInt,x) trunc(::Type{Unsigned}, x::Float64) = trunc(UInt,x) trunc(::Type{Integer}, x::Float32) = trunc(Int,x) trunc(::Type{Integer}, x::Float64) = trunc(Int,x) -trunc{T<:Integer}(::Type{T}, x::Float16) = trunc(T, Float32(x)) +trunc(::Type{T}, x::Float16) where {T<:Integer} = trunc(T, Float32(x)) # fallbacks -floor{T<:Integer}(::Type{T}, x::AbstractFloat) = trunc(T,floor(x)) -floor{T<:Integer}(::Type{T}, x::Float16) = floor(T, Float32(x)) -ceil{ T<:Integer}(::Type{T}, x::AbstractFloat) = trunc(T,ceil(x)) -ceil{ T<:Integer}(::Type{T}, x::Float16) = ceil(T, Float32(x)) -round{T<:Integer}(::Type{T}, x::AbstractFloat) = trunc(T,round(x)) -round{T<:Integer}(::Type{T}, x::Float16) = round(T, Float32(x)) +floor(::Type{T}, x::AbstractFloat) where {T<:Integer} = trunc(T,floor(x)) +floor(::Type{T}, x::Float16) where {T<:Integer} = floor(T, Float32(x)) +ceil(::Type{T}, x::AbstractFloat) where {T<:Integer} = trunc(T,ceil(x)) +ceil(::Type{T}, x::Float16) where {T<:Integer} = ceil(T, Float32(x)) +round(::Type{T}, x::AbstractFloat) where {T<:Integer} = trunc(T,round(x)) +round(::Type{T}, x::Float16) where {T<:Integer} = round(T, Float32(x)) trunc(x::Float64) = trunc_llvm(x) trunc(x::Float32) = trunc_llvm(x) @@ -399,9 +399,9 @@ end rem(x::Float32, y::Float32) = rem_float(x, y) rem(x::Float64, y::Float64) = rem_float(x, y) -cld{T<:AbstractFloat}(x::T, y::T) = -fld(-x,y) +cld(x::T, y::T) where {T<:AbstractFloat} = -fld(-x,y) -function mod{T<:AbstractFloat}(x::T, y::T) +function mod(x::T, y::T) where T<:AbstractFloat r = rem(x,y) if r == 0 copysign(r,y) @@ -519,7 +519,7 @@ abs(x::Float64) = abs_float(x) Test whether a floating point number is not a number (NaN). """ isnan(x::AbstractFloat) = x != x -isnan(x::Float16) = reinterpret(UInt16,x)&0x7fff > 0x7c00 +isnan(x::Float16) = reinterpret(UInt16,x)&0x7fff > 0x7c00 isnan(x::Real) = false """ @@ -563,7 +563,7 @@ hash(x::Float32, h::UInt) = hash(Float64(x), h) precision(::Type{Float16}) = 11 precision(::Type{Float32}) = 24 precision(::Type{Float64}) = 53 -precision{T<:AbstractFloat}(::T) = precision(T) +precision(::T) where {T<:AbstractFloat} = precision(T) """ uabs(x::Integer) @@ -694,8 +694,8 @@ end typemax(::Type{Float32}) = $(Inf32) typemin(::Type{Float64}) = $(-Inf64) typemax(::Type{Float64}) = $(Inf64) - typemin{T<:Real}(x::T) = typemin(T) - typemax{T<:Real}(x::T) = typemax(T) + typemin(x::T) where {T<:Real} = typemin(T) + typemax(x::T) where {T<:Real} = typemax(T) realmin(::Type{Float16}) = $(bitcast(Float16, 0x0400)) realmin(::Type{Float32}) = $(bitcast(Float32, 0x00800000)) @@ -703,8 +703,8 @@ end realmax(::Type{Float16}) = $(bitcast(Float16, 0x7bff)) realmax(::Type{Float32}) = $(bitcast(Float32, 0x7f7fffff)) realmax(::Type{Float64}) = $(bitcast(Float64, 0x7fefffffffffffff)) - realmin{T<:AbstractFloat}(x::T) = realmin(T) - realmax{T<:AbstractFloat}(x::T) = realmax(T) + realmin(x::T) where {T<:AbstractFloat} = realmin(T) + realmax(x::T) where {T<:AbstractFloat} = realmax(T) realmin() = realmin(Float64) realmax() = realmax(Float64) @@ -843,7 +843,7 @@ truncmask(x, mask) = x float(A::AbstractArray{<:AbstractFloat}) = A -function float{T}(A::AbstractArray{T}) +function float(A::AbstractArray{T}) where T if !isleaftype(T) error("`float` not defined on abstractly-typed arrays; please convert to a more specific type") end diff --git a/base/floatfuncs.jl b/base/floatfuncs.jl index 44761882c3977..8ca6fa6f8250f 100644 --- a/base/floatfuncs.jl +++ b/base/floatfuncs.jl @@ -19,7 +19,7 @@ signbit(x::Float16) = signbit(bitcast(Int16, x)) maxintfloat(::Type{Float64}) = 9007199254740992. maxintfloat(::Type{Float32}) = Float32(16777216.) maxintfloat(::Type{Float16}) = Float16(2048f0) -maxintfloat{T<:AbstractFloat}(x::T) = maxintfloat(T) +maxintfloat(x::T) where {T<:AbstractFloat} = maxintfloat(T) maxintfloat() = maxintfloat(Float64) isinteger(x::AbstractFloat) = (x - trunc(x) == 0) @@ -110,7 +110,7 @@ function round(x::AbstractFloat, ::RoundingMode{:NearestTiesUp}) y = floor(x) ifelse(x==y,y,copysign(floor(2*x-y),x)) end -round{T<:Integer}(::Type{T}, x::AbstractFloat, r::RoundingMode) = trunc(T,round(x,r)) +round(::Type{T}, x::AbstractFloat, r::RoundingMode) where {T<:Integer} = trunc(T,round(x,r)) # adapted from Matlab File Exchange roundsd: http://www.mathworks.com/matlabcentral/fileexchange/26212 # for round, og is the power of 10 relative to the decimal point @@ -208,9 +208,9 @@ const ≈ = isapprox ≉(args...; kws...) = !≈(args...; kws...) # default tolerance arguments -rtoldefault{T<:AbstractFloat}(::Type{T}) = sqrt(eps(T)) +rtoldefault(::Type{T}) where {T<:AbstractFloat} = sqrt(eps(T)) rtoldefault(::Type{<:Real}) = 0 -rtoldefault{T<:Number,S<:Number}(x::Union{T,Type{T}}, y::Union{S,Type{S}}) = max(rtoldefault(real(T)),rtoldefault(real(S))) +rtoldefault(x::Union{T,Type{T}}, y::Union{S,Type{S}}) where {T<:Number,S<:Number} = max(rtoldefault(real(T)),rtoldefault(real(S))) # fused multiply-add fma_libm(x::Float32, y::Float32, z::Float32) = diff --git a/base/math.jl b/base/math.jl index 4901c7baa5466..acfe45f7d906d 100644 --- a/base/math.jl +++ b/base/math.jl @@ -53,7 +53,7 @@ julia> clamp.([pi, 1.0, big(10.)], 2., 9.) 9.000000000000000000000000000000000000000000000000000000000000000000000000000000 ``` """ -clamp{X,L,H}(x::X, lo::L, hi::H) = +clamp(x::X, lo::L, hi::H) where {X,L,H} = ifelse(x > hi, convert(promote_type(X,L,H), hi), ifelse(x < lo, convert(promote_type(X,L,H), lo), @@ -156,7 +156,7 @@ deg2rad(z::AbstractFloat) = z * (oftype(z, pi) / 180) rad2deg(z::Real) = rad2deg(float(z)) deg2rad(z::Real) = deg2rad(float(z)) -log{T<:Number}(b::T, x::T) = log(x)/log(b) +log(b::T, x::T) where {T<:Number} = log(x)/log(b) """ log(b,x) @@ -450,7 +450,7 @@ Stacktrace: ``` """ hypot(x::Number, y::Number) = hypot(promote(x, y)...) -function hypot{T<:Number}(x::T, y::T) +function hypot(x::T, y::T) where T<:Number ax = abs(x) ay = abs(y) if ax < ay @@ -489,19 +489,19 @@ Compute the inverse tangent of `y/x`, using the signs of both `x` and `y` to det quadrant of the return value. """ atan2(y::Real, x::Real) = atan2(promote(float(y),float(x))...) -atan2{T<:AbstractFloat}(y::T, x::T) = Base.no_op_err("atan2", T) +atan2(y::T, x::T) where {T<:AbstractFloat} = Base.no_op_err("atan2", T) atan2(y::Float64, x::Float64) = ccall((:atan2,libm), Float64, (Float64, Float64,), y, x) atan2(y::Float32, x::Float32) = ccall((:atan2f,libm), Float32, (Float32, Float32), y, x) -max{T<:AbstractFloat}(x::T, y::T) = ifelse((y > x) | (signbit(y) < signbit(x)), +max(x::T, y::T) where {T<:AbstractFloat} = ifelse((y > x) | (signbit(y) < signbit(x)), ifelse(isnan(x), x, y), ifelse(isnan(y), y, x)) -min{T<:AbstractFloat}(x::T, y::T) = ifelse((y < x) | (signbit(y) > signbit(x)), +min(x::T, y::T) where {T<:AbstractFloat} = ifelse((y < x) | (signbit(y) > signbit(x)), ifelse(isnan(x), x, y), ifelse(isnan(y), y, x)) -minmax{T<:AbstractFloat}(x::T, y::T) = +minmax(x::T, y::T) where {T<:AbstractFloat} = ifelse(isnan(x) | isnan(y), ifelse(isnan(x), (x,x), (y,y)), ifelse((y > x) | (signbit(x) > signbit(y)), (x,y), (y,x))) @@ -517,7 +517,7 @@ julia> ldexp(5., 2) 20.0 ``` """ -function ldexp{T<:IEEEFloat}(x::T, e::Integer) +function ldexp(x::T, e::Integer) where T<:IEEEFloat xu = reinterpret(Unsigned, x) xs = xu & ~sign_mask(T) xs >= exponent_mask(T) && return x # NaN or Inf @@ -566,7 +566,7 @@ ldexp(x::Float16, q::Integer) = Float16(ldexp(Float32(x), q)) Get the exponent of a normalized floating-point number. """ -function exponent{T<:IEEEFloat}(x::T) +function exponent(x::T) where T<:IEEEFloat xs = reinterpret(Unsigned, x) & ~sign_mask(T) xs >= exponent_mask(T) && return throw(DomainError()) # NaN or Inf k = Int(xs >> significand_bits(T)) @@ -594,7 +594,7 @@ julia> significand(15.2)*8 15.2 ``` """ -function significand{T<:IEEEFloat}(x::T) +function significand(x::T) where T<:IEEEFloat xu = reinterpret(Unsigned, x) xs = xu & ~sign_mask(T) xs >= exponent_mask(T) && return x # NaN or Inf @@ -614,7 +614,7 @@ end Return `(x,exp)` such that `x` has a magnitude in the interval ``[1/2, 1)`` or 0, and `val` is equal to ``x \\times 2^{exp}``. """ -function frexp{T<:IEEEFloat}(x::T) +function frexp(x::T) where T<:IEEEFloat xu = reinterpret(Unsigned, x) xs = xu & ~sign_mask(T) xs >= exponent_mask(T) && return x, 0 # NaN or Inf @@ -698,7 +698,7 @@ end @inline ^(x::Float64, y::Integer) = x ^ Float64(y) @inline ^(x::Float32, y::Integer) = x ^ Float32(y) @inline ^(x::Float16, y::Integer) = Float16(Float32(x) ^ Float32(y)) -@inline literal_pow{p}(::typeof(^), x::Float16, ::Type{Val{p}}) = Float16(literal_pow(^,Float32(x),Val{p})) +@inline literal_pow(::typeof(^), x::Float16, ::Type{Val{p}}) where {p} = Float16(literal_pow(^,Float32(x),Val{p})) function angle_restrict_symm(theta) const P1 = 4 * 7.8539812564849853515625e-01 diff --git a/base/special/exp.jl b/base/special/exp.jl index 7f21519c79619..ceafa4eb50728 100644 --- a/base/special/exp.jl +++ b/base/special/exp.jl @@ -64,7 +64,7 @@ MINEXP(::Type{Float32}) = -103.97207708f0 # log 2^-150 Compute the natural base exponential of `x`, in other words ``e^x``. """ -function exp{T<:Union{Float32,Float64}}(x::T) +function exp(x::T) where T<:Union{Float32,Float64} xa = reinterpret(Unsigned, x) & ~sign_mask(T) xsb = signbit(x) From 7231eeeba653adab1a917ecb10273500acb5d742 Mon Sep 17 00:00:00 2001 From: Mus M Date: Sat, 15 Apr 2017 18:40:33 -0400 Subject: [PATCH 0441/1534] Use joinpath in math.jl --- base/math.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/base/math.jl b/base/math.jl index acfe45f7d906d..3db27f625c96a 100644 --- a/base/math.jl +++ b/base/math.jl @@ -958,12 +958,12 @@ end cbrt(a::Float16) = Float16(cbrt(Float32(a))) # More special functions -include("special/exp.jl") -include("special/trig.jl") -include("special/gamma.jl") +include(joinpath("special", "exp.jl")) +include(joinpath("special", "trig.jl")) +include(joinpath("special", "gamma.jl")) module JuliaLibm -include("special/log.jl") +include(joinpath("special", "log.jl")) end end # module From ad48ebe38fdea07559c65b9195e50a8c1ab332e7 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 9 Feb 2017 18:25:03 -0500 Subject: [PATCH 0442/1534] update sysimg symbol tables and generator script for 0.6 --- src/common_symbols1.inc | 92 ++++---- src/common_symbols2.inc | 438 ++++++++++++++++++++------------------- src/dump.c | 16 ++ src/gen_sysimg_symtab.jl | 13 +- 4 files changed, 288 insertions(+), 271 deletions(-) diff --git a/src/common_symbols1.inc b/src/common_symbols1.inc index bc8380648a201..013dfdd15dc06 100644 --- a/src/common_symbols1.inc +++ b/src/common_symbols1.inc @@ -1,63 +1,63 @@ jl_symbol("getfield"), -jl_symbol("bitcast"), -jl_symbol("apply_type"), jl_symbol("meta"), -jl_symbol("Ptr"), +jl_symbol("inbounds"), jl_symbol("push_loc"), jl_symbol("pop_loc"), -jl_symbol("abstractarray.jl"), +jl_symbol("apply_type"), jl_symbol("add_int"), +jl_symbol("Ptr"), +jl_symbol("pop"), +jl_symbol("bitcast"), +jl_symbol("==="), +jl_symbol("foreigncall"), jl_symbol("getindex"), -jl_symbol("BlasInt"), -jl_symbol("static_parameter"), jl_symbol("new"), -jl_symbol("start"), -jl_symbol("Any"), -jl_symbol("convert"), -jl_symbol("svec"), -jl_symbol("ccall"), -jl_symbol("Bool"), -jl_symbol("inbounds"), -jl_symbol("==="), -jl_symbol("typeof"), -jl_symbol("tuple.jl"), -jl_symbol("Array"), -jl_symbol("indexed_next"), -jl_symbol("sle_int"), -jl_symbol("Void"), jl_symbol("arrayref"), -jl_symbol("array.jl"), -jl_symbol("unsafe_convert"), -jl_symbol("done"), +jl_symbol("static_parameter"), +jl_symbol("abstractarray.jl"), +jl_symbol("slt_int"), +jl_symbol("convert"), +jl_symbol("start"), +jl_symbol("BlasInt"), +jl_symbol("+"), jl_symbol("not_int"), -jl_symbol("next"), -jl_symbol("dict.jl"), +jl_symbol("unsafe_convert"), +jl_symbol("isa"), +jl_symbol("sle_int"), +jl_symbol("select_value"), +jl_symbol("throw"), +jl_symbol("sub_int"), +jl_symbol("=="), +jl_symbol("!"), jl_symbol("cconvert"), jl_symbol("length"), -jl_symbol("slt_int"), -jl_symbol("sub_int"), -jl_symbol("typeassert"), -jl_symbol("Int"), -jl_symbol("size"), +jl_symbol("-"), +jl_symbol("next"), +jl_symbol("&"), +jl_symbol("indexed_next"), +jl_symbol("string"), +jl_symbol("done"), jl_symbol("colon"), -jl_symbol("pop"), -jl_symbol("throw"), -jl_symbol("setindex!"), +jl_symbol("_apply"), +jl_symbol("arrayset"), +jl_symbol("indices"), +jl_symbol("typeof"), jl_symbol("ptr_arg_unsafe_convert"), jl_symbol("ptr_arg_cconvert"), +jl_symbol("setindex!"), +jl_symbol("*"), +jl_symbol("check_top_bit"), +jl_symbol("setfield!"), jl_symbol("arraylen"), -jl_symbol("Float64"), -jl_symbol("nothing"), +jl_symbol("typeassert"), jl_symbol("and_int"), -jl_symbol("int.jl"), -jl_symbol("_apply"), +jl_symbol("jl_alloc_array_1d"), +jl_symbol("arraysize"), +jl_symbol("size"), +jl_symbol("Int"), +jl_symbol("nothing"), +jl_symbol("_expr"), +jl_symbol("args"), +jl_symbol("print"), +jl_symbol("Float64"), jl_symbol("UInt8"), -jl_symbol("string"), -jl_symbol("setfield!"), -jl_symbol("JJ"), -jl_symbol("operators.jl"), -jl_symbol("nfields"), -jl_symbol("iobuffer.jl"), -jl_symbol("Float32"), -jl_symbol("strings/io.jl"), -jl_symbol("arrayset"), diff --git a/src/common_symbols2.inc b/src/common_symbols2.inc index a53732df4e3bb..4554dfef79b5b 100644 --- a/src/common_symbols2.inc +++ b/src/common_symbols2.inc @@ -1,250 +1,252 @@ -jl_symbol("essentials.jl"), -jl_symbol("select_value"), -jl_symbol("jl_alloc_array_1d"), -jl_symbol("_expr"), -jl_symbol("check_top_bit"), -jl_symbol("Type"), -jl_symbol("Int32"), -jl_symbol("isa"), -jl_symbol("print"), -jl_symbol("data"), +jl_symbol("stop"), jl_symbol("copyast"), -jl_symbol("zext_int"), -jl_symbol("uM"), -jl_symbol("mul_int"), -jl_symbol("KJ"), -jl_symbol("Cint"), -jl_symbol("Complex128"), -jl_symbol("Complex64"), -jl_symbol("arraysize"), -jl_symbol("iterator.jl"), -jl_symbol("zero"), -jl_symbol("UInt"), +jl_symbol("!="), +jl_symbol("write"), +jl_symbol("Array"), jl_symbol("neg_int"), +jl_symbol("len"), +jl_symbol("Void"), jl_symbol("ArgumentError"), -jl_symbol("indices"), -jl_symbol("BigFloat"), -jl_symbol("write"), -jl_symbol("args"), -jl_symbol("range.jl"), -jl_symbol("stop"), -jl_symbol("J"), -jl_symbol("uR"), -jl_symbol("generator.jl"), +jl_symbol("indices1"), +jl_symbol("<"), +jl_symbol("sizeof"), +jl_symbol("Float32"), +jl_symbol("t"), +jl_symbol("mul_int"), +jl_symbol("linearindices"), +jl_symbol("o"), +jl_symbol("Type"), +jl_symbol("array.jl"), +jl_symbol("strings/string.jl"), +jl_symbol("contents"), +jl_symbol("zext_int"), +jl_symbol("push!"), +jl_symbol("iter"), +jl_symbol(">"), +jl_symbol("Base"), jl_symbol("endof"), +jl_symbol("shl_int"), +jl_symbol("Any"), +jl_symbol("Enums.jl"), +jl_symbol("zero"), +jl_symbol("strings/io.jl"), +jl_symbol("Main"), jl_symbol("leave"), -jl_symbol("count"), -jl_symbol("Base"), -jl_symbol("docs/helpdb/Base.jl"), -jl_symbol("vj"), -jl_symbol("contents"), -jl_symbol("ptr"), +jl_symbol("name"), +jl_symbol("<="), +jl_symbol("or_int"), jl_symbol("similar"), -jl_symbol("@f"), -jl_symbol("show.jl"), -jl_symbol("keys"), -jl_symbol("vector_any"), -jl_symbol("BigInt"), -jl_symbol("push!"), -jl_symbol("reduce.jl"), -jl_symbol("boot.jl"), +jl_symbol("Complex64"), +jl_symbol("Complex128"), jl_symbol("isempty"), -jl_symbol("uO"), +jl_symbol("#print_to_string#227"), +jl_symbol("pointer"), +jl_symbol("jl_value_ptr"), +jl_symbol("head"), +jl_symbol("src"), jl_symbol("sext_int"), -jl_symbol("vals"), -jl_symbol("bitarray.jl"), -jl_symbol("uf"), jl_symbol("max"), +jl_symbol("Expr"), +jl_symbol("parameters"), +jl_symbol("lshr_int"), +jl_symbol("vector_any"), +jl_symbol("count"), +jl_symbol("age"), +jl_symbol("Int32"), +jl_symbol("keys"), +jl_symbol("Tuple"), +jl_symbol("range.jl"), +jl_symbol(">>"), +jl_symbol("ptr"), +jl_symbol("data"), +jl_symbol("unsafe_write"), +jl_symbol("Const"), +jl_symbol("BigFloat"), +jl_symbol("DimensionMismatch"), jl_symbol("slots"), -jl_symbol("uN"), -jl_symbol("kwfunc"), -jl_symbol("shl_int"), -jl_symbol("sizeof"), -jl_symbol("Enums.jl"), -jl_symbol("promotion.jl"), -jl_symbol("C_NULL"), -jl_symbol("Ref"), -jl_symbol("eltype"), -jl_symbol("or_int"), -jl_symbol("#print_to_string#138"), -jl_symbol("Main"), jl_symbol("pointer.jl"), -jl_symbol("DimensionMismatch"), +jl_symbol("eltype"), +jl_symbol("Bool"), +jl_symbol("Val"), jl_symbol("stride"), -jl_symbol("uP"), -jl_symbol("III"), -jl_symbol("uW"), -jl_symbol("checked_trunc_uint"), -jl_symbol("sparse/sparsematrix.jl"), -jl_symbol("inference.jl"), -jl_symbol("Csize_t"), jl_symbol("fieldtype"), -jl_symbol("uT"), -jl_symbol("uQ"), -jl_symbol("unbox"), -jl_symbol("String"), -jl_symbol("Expr"), -jl_symbol("multidimensional.jl"), -jl_symbol("boundscheck"), -jl_symbol("multi.jl"), -jl_symbol("strings/basic.jl"), -jl_symbol("uS"), -jl_symbol("promote_type"), -jl_symbol("checked_trunc_sint"), -jl_symbol("ult_int"), -jl_symbol("reshapedarray.jl"), -jl_symbol("block"), -jl_symbol("Cstring"), -jl_symbol("LineEdit.jl"), -jl_symbol("idxfloor"), -jl_symbol("one"), -jl_symbol("UInt32"), -jl_symbol("print_to_string"), -jl_symbol("HuJ"), -jl_symbol("name"), -jl_symbol("resize!"), -jl_symbol("u]"), -jl_symbol("jl_array_grow_end"), -jl_symbol("lshr_int"), -jl_symbol("linalg/lapack.jl"), -jl_symbol("u["), -jl_symbol("enter"), -jl_symbol("Tuple"), -jl_symbol("subarray.jl"), +jl_symbol("dict.jl"), jl_symbol("checkbounds"), -jl_symbol("Symbol"), -jl_symbol("indices1"), -jl_symbol("jl_array_ptr"), -jl_symbol("reflection.jl"), -jl_symbol("hash"), -jl_symbol("ub"), +jl_symbol("map"), +jl_symbol("vals"), +jl_symbol("Cint"), +jl_symbol("copy!"), +jl_symbol("promotion.jl"), +jl_symbol("MethodError"), +jl_symbol("jl_array_grow_end"), +jl_symbol("checked_trunc_uint"), +jl_symbol("BigInt"), +jl_symbol("block"), jl_symbol("fill!"), -jl_symbol("refpointer.jl"), -jl_symbol("uU"), -jl_symbol("float.jl"), -jl_symbol("ua"), -jl_symbol("u`"), -jl_symbol("inline"), -jl_symbol("linalg/triangular.jl"), -jl_symbol("ud"), -jl_symbol("uX"), -jl_symbol("Generator"), -jl_symbol("char.jl"), -jl_symbol("_chkbnds"), -jl_symbol("uY"), -jl_symbol("head"), -jl_symbol("real"), -jl_symbol("dict"), -jl_symbol("get"), -jl_symbol("uV"), -jl_symbol("ue"), -jl_symbol("parameters"), +jl_symbol("nfields"), +jl_symbol("hash"), +jl_symbol("DataType"), jl_symbol("first"), -jl_symbol("hashing.jl"), -jl_symbol("kwerr"), +jl_symbol("<:"), +jl_symbol("in"), +jl_symbol("C_NULL"), +jl_symbol("ult_int"), +jl_symbol("broadcast"), +jl_symbol("char.jl"), +jl_symbol("val"), jl_symbol("value"), -jl_symbol("iter"), -jl_symbol("the_exception"), -jl_symbol("step"), -jl_symbol("UInt64"), -jl_symbol("eachindex"), -jl_symbol("process.jl"), -jl_symbol("Int64"), -jl_symbol("ht_keyindex"), -jl_symbol("len"), -jl_symbol("io.jl"), +jl_symbol("id"), +jl_symbol("inference.jl"), +jl_symbol("io"), +jl_symbol("kwfunc"), +jl_symbol("Symbol"), +jl_symbol("mod"), +jl_symbol("isdefined"), +jl_symbol("enter"), +jl_symbol("bitarray.jl"), +jl_symbol("/"), +jl_symbol("Ref"), +jl_symbol("typ"), +jl_symbol("generator.jl"), +jl_symbol("_ftl"), +jl_symbol("checked.jl"), +jl_symbol("UInt"), +jl_symbol("chunks"), +jl_symbol("ht"), +jl_symbol("resize!"), +jl_symbol("|"), +jl_symbol("depwarn"), +jl_symbol("Vector"), +jl_symbol("String"), +jl_symbol("checked_trunc_sint"), +jl_symbol("promote_type"), +jl_symbol("noinline"), jl_symbol("error"), -jl_symbol("copy!"), jl_symbol("BoundsError"), -jl_symbol("jl_new_array"), +jl_symbol("the_exception"), +jl_symbol("ashr_int"), +jl_symbol("dict"), +jl_symbol("mt"), +jl_symbol("<<"), +jl_symbol("Bottom"), +jl_symbol("ht_keyindex"), +jl_symbol("get"), +jl_symbol("AnyVector"), +jl_symbol("real"), +jl_symbol("one"), +jl_symbol("boundscheck"), +jl_symbol("widenconst"), +jl_symbol("Cstring"), +jl_symbol("collect_to!"), +jl_symbol("println"), +jl_symbol("tuple.jl"), +jl_symbol("."), +jl_symbol("UInt64"), +jl_symbol("idxfloor"), jl_symbol("f"), -jl_symbol("sysimg.jl"), -jl_symbol("u^"), -jl_symbol("uc"), -jl_symbol("rdims"), -jl_symbol("ul"), -jl_symbol("u_"), -jl_symbol("liblapack"), +jl_symbol("Int64"), +jl_symbol("kwerr"), +jl_symbol("AssertionError"), +jl_symbol("multidimensional.jl"), +jl_symbol("bits"), +jl_symbol("collect"), jl_symbol("copy"), -jl_symbol("strings/string.jl"), -jl_symbol("uZ"), -jl_symbol("ashr_int"), -jl_symbol("reshape"), -jl_symbol("random.jl"), -jl_symbol("K"), -jl_symbol("sparse/sparsevector.jl"), -jl_symbol("linearindices"), -jl_symbol("stream.jl"), -jl_symbol("checkindex"), -jl_symbol("ug"), -jl_symbol("_front"), +jl_symbol("jl_array_ptr"), jl_symbol("throw_boundserror"), -jl_symbol("uo"), -jl_symbol("chkstride1"), -jl_symbol("c.jl"), -jl_symbol("colptr"), -jl_symbol("Vector"), +jl_symbol("liblapack"), +jl_symbol("checkindex"), +jl_symbol("haskey"), jl_symbol("min"), +jl_symbol("last"), +jl_symbol("_length"), +jl_symbol(">="), +jl_symbol("isleaftype"), +jl_symbol("UInt32"), +jl_symbol("Generator"), +jl_symbol("TypeVar"), +jl_symbol("hashing.jl"), +jl_symbol("chkstride1"), +jl_symbol("step"), +jl_symbol("UnionAll"), +jl_symbol("typejoin"), +jl_symbol("kwsorter"), +jl_symbol("jl_rethrow_other"), +jl_symbol("var"), +jl_symbol("handle"), +jl_symbol("Csize_t"), +jl_symbol("argtail"), +jl_symbol("associative.jl"), +jl_symbol("secret_table_token"), +jl_symbol("abs"), jl_symbol("esc"), -jl_symbol("IOContext"), -jl_symbol("println"), -jl_symbol("set.jl"), -jl_symbol("nzval"), -jl_symbol("div"), -jl_symbol("skip_deleted"), -jl_symbol("uj"), -jl_symbol("uh"), -jl_symbol("un"), -jl_symbol("ref"), +jl_symbol("unwrap_unionall"), jl_symbol("maxprobe"), -jl_symbol("pointer"), -jl_symbol("abs"), -jl_symbol("multimedia.jl"), -jl_symbol("Af"), -jl_symbol("xFI"), -jl_symbol("libgit2/types.jl"), -jl_symbol("jl_rethrow_other"), -jl_symbol("mpfr.jl"), -jl_symbol("map"), -jl_symbol("DataType"), +jl_symbol("unsafe_copy!"), +jl_symbol("checked_add"), +jl_symbol("broadcast.jl"), jl_symbol("vect"), -jl_symbol("error.jl"), +jl_symbol("lock"), +jl_symbol("params"), jl_symbol("chklapackerror"), -jl_symbol("haskey"), -jl_symbol("elsize"), -jl_symbol("ut"), jl_symbol("show"), -jl_symbol("sprint"), -jl_symbol("ui"), -jl_symbol("ROUNDING_MODE"), -jl_symbol("handle"), -jl_symbol("um"), -jl_symbol("last"), -jl_symbol("Val"), -jl_symbol("ErrorException"), -jl_symbol("sort.jl"), -jl_symbol("docs/Docs.jl"), -jl_symbol("KeyError"), -jl_symbol("stat.jl"), -jl_symbol("Complex"), +jl_symbol("code"), +jl_symbol("hash_64_64"), +jl_symbol("s"), +jl_symbol("Union"), jl_symbol("checked_sadd_int"), -jl_symbol("checksquare"), -jl_symbol("II"), +jl_symbol("ndel"), +jl_symbol("ref"), +jl_symbol("istopfunction"), +jl_symbol("checked_sub"), jl_symbol("checked_ssub_int"), +jl_symbol("KeyError"), +jl_symbol("%"), +jl_symbol("eval"), +jl_symbol("pointerref"), +jl_symbol("checksquare"), +jl_symbol("status"), jl_symbol("trunc_int"), -jl_symbol("ndel"), -jl_symbol("libgit2"), -jl_symbol("Ah"), -jl_symbol("LinearFast"), -jl_symbol("linalg/blas.jl"), -jl_symbol("isless"), -jl_symbol("printf.jl"), -jl_symbol("rowval"), -jl_symbol("joinpath"), +jl_symbol("ssavaluetypes"), jl_symbol("rehash!"), -jl_symbol("chunks"), -jl_symbol("Hvz"), -jl_symbol("base.jl"), -jl_symbol("deprecated.jl"), -jl_symbol("jl_value_ptr"), -jl_symbol("REPL.jl"), +jl_symbol("show.jl"), +jl_symbol("jl_array_ptr_1d_push"), +jl_symbol("intset.jl"), +jl_symbol("I"), +jl_symbol("def"), +jl_symbol("_collect"), +jl_symbol("linfo"), +jl_symbol("jl_object_id"), +jl_symbol("div"), +jl_symbol("deserialize"), +jl_symbol("essentials.jl"), +jl_symbol("^"), +jl_symbol("macrocall"), +jl_symbol("ErrorException"), +jl_symbol("SSAValue"), +jl_symbol("read"), +jl_symbol("QuoteNode"), +jl_symbol("x"), +jl_symbol("get_chunks_id"), +jl_symbol("escape"), +jl_symbol("d"), +jl_symbol("libmpfr"), +jl_symbol("Box"), +jl_symbol("!=="), +jl_symbol("Conditional"), +jl_symbol("show_unquoted"), +jl_symbol("Slot"), +jl_symbol("nzval"), +jl_symbol("Complex"), +jl_symbol("reflection.jl"), +jl_symbol("colptr"), +jl_symbol("jl_eqtable_get"), +jl_symbol("isnan"), +jl_symbol("IndexStyle"), +jl_symbol("Dict"), +jl_symbol("promote"), +jl_symbol("offset"), +jl_symbol("NF"), +jl_symbol("isvarargtype"), +jl_symbol("n"), +jl_symbol("inferred"), +jl_symbol("eachindex"), diff --git a/src/dump.c b/src/dump.c index 698c96ca69037..bc25d92d97fb4 100644 --- a/src/dump.c +++ b/src/dump.c @@ -133,6 +133,9 @@ typedef struct { static jl_value_t *jl_idtable_type = NULL; static arraylist_t builtin_typenames; +// mark symbols for gen_sysimg_symtab.jl +//#define GEN_SYMTAB_MODE + #define write_uint8(s, n) ios_putc((n), (s)) #define read_uint8(s) ((uint8_t)ios_getc(s)) #define write_int8(s, n) write_uint8(s, n) @@ -826,7 +829,14 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li writetag(s->s, (jl_value_t*)LongSymbol_tag); write_int32(s->s, l); } +#ifdef GEN_SYMTAB_MODE + write_uint8(s->s, 0); + ios_write(s->s, "JJJ", 3); +#endif ios_write(s->s, jl_symbol_name((jl_sym_t*)v), l); +#ifdef GEN_SYMTAB_MODE + write_uint8(s->s, 0); +#endif } else if (jl_is_globalref(v)) { if (s->mode == MODE_AST && jl_globalref_mod(v) == s->tree_enclosing_module) { @@ -1601,7 +1611,13 @@ static jl_value_t *jl_deserialize_value_symbol(jl_serializer_state *s, jl_value_ else len = read_int32(s->s); char *name = (char*)(len >= 256 ? malloc(len + 1) : alloca(len + 1)); +#ifdef GEN_SYMTAB_MODE + (void)read_uint8(s->s); (void)read_uint8(s->s); (void)read_uint8(s->s); (void)read_uint8(s->s); +#endif ios_read(s->s, name, len); +#ifdef GEN_SYMTAB_MODE + (void)read_uint8(s->s); +#endif name[len] = '\0'; jl_value_t *sym = (jl_value_t*)jl_symbol(name); if (len >= 256) diff --git a/src/gen_sysimg_symtab.jl b/src/gen_sysimg_symtab.jl index 193aa947ee8c0..e8a440ce14112 100644 --- a/src/gen_sysimg_symtab.jl +++ b/src/gen_sysimg_symtab.jl @@ -3,25 +3,24 @@ # script to generate tables of common symbols from a system image # steps to rerun this: # 1. empty the contents of common_symbols*.inc -# 2. modify dump.c to write and read a '\0' after every symbol name +# 2. modify dump.c to write symbols in a clearly marked format (#define GEN_SYMTAB_MODE) # 3. build sys.ji # 4. cd src && ../julia gen_sysimg_symtab.jl ../usr/lib/julia/sys.ji fname = ARGS[1] -io,_ = open(pipeline(`strings -n 3 $fname`, - `tr -d "() \t+-"`, - `grep -v '^$'`, # rm empty lines - `grep -v '\\'`, # avoid backslashes +io,_ = open(pipeline(`strings -n 4 $fname`, + `tr -d "() \t"`, + `grep JJJ`, `sort`, `uniq -c`, `sort -g -r`, `head -n 315`)) # 63 + 252 function outputline(io, line) row = split(line, " ", keep=false) - println(io, "jl_symbol(\"", row[2], "\"),") + println(io, "jl_symbol(\"", row[2][4:end], "\"),") end lines = eachline(io) -open(f->foreach(l->outputline(f,l), take(lines,63)), "common_symbols1.inc", "w") +open(f->foreach(l->outputline(f,l), Base.Iterators.take(lines,63)), "common_symbols1.inc", "w") open(f->foreach(l->outputline(f,l), lines), "common_symbols2.inc", "w") From 336cf63bc1763db5a6e10ef5164089cdd6ee93be Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Sat, 15 Apr 2017 09:40:39 -0700 Subject: [PATCH 0443/1534] explicit cast for compiling as C++ fix a typo --- src/dump.c | 2 +- test/stacktraces.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dump.c b/src/dump.c index 698c96ca69037..5006fdfe8d0ff 100644 --- a/src/dump.c +++ b/src/dump.c @@ -1269,7 +1269,7 @@ static void jl_serialize_backedges(jl_serializer_state *s) if (callee != HT_NOTFOUND) { jl_serialize_value(s, caller); jl_serialize_value(s, callee); - *pcallee = HT_NOTFOUND; + *pcallee = (jl_array_t*) HT_NOTFOUND; for (i = 0; i < jl_array_len(callee); i++) { jl_value_t *c = jl_array_ptr_ref(callee, i); if (jl_is_method_instance(c)) diff --git a/test/stacktraces.jl b/test/stacktraces.jl index 079e0b73d388e..f388e382aed07 100644 --- a/test/stacktraces.jl +++ b/test/stacktraces.jl @@ -136,7 +136,7 @@ module StackTracesTestMod filtered_stacktrace() = StackTraces.remove_frames!(stacktrace(), StackTracesTestMod) end -# Test that `removes_frames!` can correctly remove frames from withing the module +# Test that `removes_frames!` can correctly remove frames from within the module trace = StackTracesTestMod.unfiltered_stacktrace() @test contains(string(trace), "unfiltered_stacktrace") From cd26a40cb91ded3106749454a3fc6206a4a1dd87 Mon Sep 17 00:00:00 2001 From: Mus M Date: Sun, 16 Apr 2017 00:43:43 -0400 Subject: [PATCH 0444/1534] Use Vector and Refs in misc files --- base/channels.jl | 6 +++--- base/datafmt.jl | 10 +++++----- base/inference.jl | 2 +- base/io.jl | 2 +- base/iostream.jl | 5 ++--- base/libdl.jl | 2 +- base/mpfr.jl | 4 ++-- base/multidimensional.jl | 4 ++-- base/profile.jl | 24 ++++++++++++------------ base/range.jl | 2 +- 10 files changed, 30 insertions(+), 31 deletions(-) diff --git a/base/channels.jl b/base/channels.jl index 3b686f8f7fe26..92f98a47231a2 100644 --- a/base/channels.jl +++ b/base/channels.jl @@ -27,8 +27,8 @@ mutable struct Channel{T} <: AbstractChannel sz_max::Int # maximum size of channel # Used when sz_max == 0, i.e., an unbuffered channel. - takers::Array{Task} - putters::Array{Task} + takers::Vector{Task} + putters::Vector{Task} waiters::Int function Channel{T}(sz::Float64) where T @@ -42,7 +42,7 @@ mutable struct Channel{T} <: AbstractChannel if sz < 0 throw(ArgumentError("Channel size must be either 0, a positive integer or Inf")) end - new(Condition(), Condition(), :open, Nullable{Exception}(), Array{T}(0), sz, Array{Task}(0), Array{Task}(0), 0) + new(Condition(), Condition(), :open, Nullable{Exception}(), Vector{T}(0), sz, Vector{Task}(0), Vector{Task}(0), 0) end # deprecated empty constructor diff --git a/base/datafmt.jl b/base/datafmt.jl index 6c31cc06aa133..ec847248eca4d 100644 --- a/base/datafmt.jl +++ b/base/datafmt.jl @@ -150,8 +150,8 @@ mutable struct DLMOffsets <: DLMHandler bufflen::Int function DLMOffsets(sbuff::String) - offsets = Array{Array{Int,1}}(1) - offsets[1] = Array{Int}(offs_chunk_size) + offsets = Vector{Vector{Int}}(1) + offsets[1] = Vector{Int}(offs_chunk_size) thresh = ceil(min(typemax(UInt), Base.Sys.total_memory()) / sizeof(Int) / 5) new(offsets, 1, thresh, sizeof(sbuff)) end @@ -175,7 +175,7 @@ function store_cell(dlmoffsets::DLMOffsets, row::Int, col::Int, return end end - offsets = Array{Int}(offs_chunk_size) + offsets = Vector{Int}(offs_chunk_size) push!(oarr, offsets) offidx = 1 end @@ -214,7 +214,7 @@ function DLMStore{T}(::Type{T}, dims::NTuple{2,Integer}, nrows <= 0 && throw(ArgumentError("number of rows in dims must be > 0, got $nrows")) ncols <= 0 && throw(ArgumentError("number of columns in dims must be > 0, got $ncols")) hdr_offset = has_header ? 1 : 0 - DLMStore{T}(fill(SubString(sbuff,1,0), 1, ncols), Array{T}(nrows-hdr_offset, ncols), + DLMStore{T}(fill(SubString(sbuff,1,0), 1, ncols), Matrix{T}(nrows-hdr_offset, ncols), nrows, ncols, 0, 0, hdr_offset, sbuff, auto, eol) end @@ -229,7 +229,7 @@ function store_cell{T}(dlmstore::DLMStore{T}, row::Int, col::Int, ncols = dlmstore.ncols lastcol = dlmstore.lastcol lastrow = dlmstore.lastrow - cells::Array{T,2} = dlmstore.data + cells::Matrix{T} = dlmstore.data sbuff = dlmstore.sbuff endpos = prevind(sbuff, nextind(sbuff,endpos)) diff --git a/base/inference.jl b/base/inference.jl index 9840772355935..f96aabc7034a1 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -1323,7 +1323,7 @@ function abstract_call_gf_by_type(f::ANY, atype::ANY, sv::InferenceState) p1, p2 = sigtuple.parameters, unwrap_unionall(infstate.linfo.specTypes).parameters if length(p2) == ls limitdepth = false - newsig = Array{Any}(ls) + newsig = Vector{Any}(ls) for i = 1:ls if p1[i] <: Function && type_depth(p1[i]) > type_depth(p2[i]) && isa(p1[i],DataType) diff --git a/base/io.jl b/base/io.jl index 58d443371db4c..bee7fb3899959 100644 --- a/base/io.jl +++ b/base/io.jl @@ -455,7 +455,7 @@ function readuntil(s::IO, t::AbstractString) warn("readuntil(IO,AbstractString) will perform poorly with a long string") end out = IOBuffer() - m = Array{Char}(l) # last part of stream to match + m = Vector{Char}(l) # last part of stream to match t = collect(t) i = 0 while !eof(s) diff --git a/base/iostream.jl b/base/iostream.jl index e6a56b24ee477..c14a5d21b9402 100644 --- a/base/iostream.jl +++ b/base/iostream.jl @@ -309,12 +309,12 @@ function read(s::IOStream, nb::Integer; all::Bool=true) end ## Character streams ## -const _chtmp = Array{Char}(1) +const _chtmp = Ref{Char}() function peekchar(s::IOStream) if ccall(:ios_peekutf8, Cint, (Ptr{Void}, Ptr{Char}), s, _chtmp) < 0 return typemax(Char) end - return _chtmp[1] + return _chtmp[] end function peek(s::IOStream) @@ -333,4 +333,3 @@ function skipchars(io::IOStream, pred; linecomment=nothing) end return io end - diff --git a/base/libdl.jl b/base/libdl.jl index e89c8a5a8dbb9..388950d11f2f3 100644 --- a/base/libdl.jl +++ b/base/libdl.jl @@ -231,7 +231,7 @@ if is_bsd() && !is_apple() end # bsd family function dllist() - dynamic_libraries = Array{AbstractString}(0) + dynamic_libraries = Vector{AbstractString}(0) @static if is_linux() const callback = cfunction(dl_phdr_info_callback, Cint, diff --git a/base/mpfr.jl b/base/mpfr.jl index 9141c2ad704dd..04b761a08216c 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -639,14 +639,14 @@ for f in (:sin,:cos,:tan,:sec,:csc, end # log of absolute value of gamma function -const lgamma_signp = Array{Cint}(1) +const lgamma_signp = Ref{Cint}() function lgamma(x::BigFloat) z = BigFloat() ccall((:mpfr_lgamma,:libmpfr), Cint, (Ptr{BigFloat}, Ptr{Cint}, Ptr{BigFloat}, Int32), &z, lgamma_signp, &x, ROUNDING_MODE[]) return z end -lgamma_r(x::BigFloat) = (lgamma(x), lgamma_signp[1]) +lgamma_r(x::BigFloat) = (lgamma(x), lgamma_signp[]) function atan2(y::BigFloat, x::BigFloat) z = BigFloat() diff --git a/base/multidimensional.jl b/base/multidimensional.jl index f4850926aa878..53886f69d18ab 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -513,7 +513,7 @@ end @generated function findn{T,N}(A::AbstractArray{T,N}) quote nnzA = countnz(A) - @nexprs $N d->(I_d = Array{Int}(nnzA)) + @nexprs $N d->(I_d = Vector{Int}(nnzA)) k = 1 @nloops $N i A begin @inbounds if (@nref $N A i) != zero(T) @@ -1198,7 +1198,7 @@ end @generated function findn{N}(B::BitArray{N}) quote nnzB = countnz(B) - I = ntuple(x->Array{Int}(nnzB), Val{$N}) + I = ntuple(x->Vector{Int}(nnzB), Val{$N}) if nnzB > 0 count = 1 @nloops $N i B begin diff --git a/base/profile.jl b/base/profile.jl index 76d122c066f29..55816bda55ce9 100644 --- a/base/profile.jl +++ b/base/profile.jl @@ -330,8 +330,8 @@ function count_flat{T<:Unsigned}(data::Vector{T}) end linecount[ip] = get(linecount, ip, 0)+1 end - iplist = Array{T}(0) - n = Array{Int}(0) + iplist = Vector{T}(0) + n = Vector{Int}(0) for (k,v) in linecount push!(iplist, k) push!(n, v) @@ -444,8 +444,8 @@ function tree_aggregate(data::Vector{UInt64}) treecount[tmp] = get(treecount, tmp, 0) + 1 istart = iend + 1 + btskip end - bt = Array{Vector{UInt64}}(0) - counts = Array{Int}(0) + bt = Vector{Vector{UInt64}}(0) + counts = Vector{Int}(0) for (k, v) in treecount if !isempty(k) push!(bt, k) @@ -464,7 +464,7 @@ function tree_format(lilist::Vector{StackFrame}, counts::Vector{Int}, level::Int ntext = cols - nindent - ndigcounts - ndigline - 5 widthfile = floor(Integer, 0.4ntext) widthfunc = floor(Integer, 0.6ntext) - strs = Array{String}(length(lilist)) + strs = Vector{String}(length(lilist)) showextra = false if level > nindent nextra = level - nindent @@ -528,9 +528,9 @@ function tree(io::IO, bt::Vector{Vector{UInt64}}, counts::Vector{Int}, end # Generate counts dlen = length(d) - lilist = Array{StackFrame}(dlen) - group = Array{Vector{Int}}(dlen) - n = Array{Int}(dlen) + lilist = Vector{StackFrame}(dlen) + group = Vector{Vector{Int}}(dlen) + n = Vector{Int}(dlen) i = 1 for (key, v) in d lilist[i] = key @@ -551,9 +551,9 @@ function tree(io::IO, bt::Vector{Vector{UInt64}}, counts::Vector{Int}, end # Generate counts, and do the code lookup dlen = length(d) - lilist = Array{StackFrame}(dlen) - group = Array{Vector{Int}}(dlen) - n = Array{Int}(dlen) + lilist = Vector{StackFrame}(dlen) + group = Vector{Vector{Int}}(dlen) + n = Vector{Int}(dlen) i = 1 for (key, v) in d lilist[i] = lidict[key] @@ -656,7 +656,7 @@ truncto(str::Symbol, w::Int) = truncto(string(str), w) # Order alphabetically (file, function) and then by line number function liperm(lilist::Vector{StackFrame}) - comb = Array{String}(length(lilist)) + comb = Vector{String}(length(lilist)) for i = 1:length(lilist) li = lilist[i] if li != UNKNOWN diff --git a/base/range.jl b/base/range.jl index 6d2bed9b6c743..30123077329c7 100644 --- a/base/range.jl +++ b/base/range.jl @@ -810,7 +810,7 @@ function vcat{T}(rs::Range{T}...) for ra in rs n += length(ra) end - a = Array{T}(n) + a = Vector{T}(n) i = 1 for ra in rs, x in ra @inbounds a[i] = x From 51e6e4e9ce6f19ae2222e776e8260b28decd302d Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Fri, 3 Mar 2017 22:16:12 -0500 Subject: [PATCH 0445/1534] Optimize `isassigned` and inline `jl_array_isassigned`. --- base/array.jl | 7 ++++--- src/ccall.cpp | 29 +++++++++++++++++++++++++++++ src/julia.h | 2 ++ src/julia_internal.h | 1 + 4 files changed, 36 insertions(+), 3 deletions(-) diff --git a/base/array.jl b/base/array.jl index a7e28bb6f9a93..b1393d650e399 100644 --- a/base/array.jl +++ b/base/array.jl @@ -87,9 +87,10 @@ elsize{T}(a::Array{T}) = isbits(T) ? sizeof(T) : sizeof(Ptr) sizeof(a::Array) = elsize(a) * length(a) function isassigned(a::Array, i::Int...) - ii = sub2ind(size(a), i...) - 1 <= ii <= length(a) || return false - ccall(:jl_array_isassigned, Cint, (Any, UInt), a, ii-1) == 1 + @_inline_meta + ii = (sub2ind(size(a), i...) % UInt) - 1 + ii < length(a) % UInt || return false + ccall(:jl_array_isassigned, Cint, (Any, UInt), a, ii) == 1 end ## copy ## diff --git a/src/ccall.cpp b/src/ccall.cpp index 51436ada49f82..f881411d39c5a 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -1783,6 +1783,35 @@ static jl_cgval_t emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) } JL_GC_POP(); } + if ((fptr == (void(*)(void))&jl_array_isassigned || + ((f_lib==NULL || (intptr_t)f_lib==2) + && f_name && !strcmp(f_name, "jl_array_isassigned"))) && + expr_type(args[6], ctx) == (jl_value_t*)jl_ulong_type) { + assert(nargt == 2); + jl_value_t *aryex = args[4]; + jl_value_t *idxex = args[6]; + jl_value_t *aryty = expr_type(aryex, ctx); + if (jl_is_array_type(aryty)) { + jl_value_t *ety = jl_tparam0(aryty); + if (jl_isbits(ety)) { + emit_expr(aryex, ctx); + emit_expr(idxex, ctx); + JL_GC_POP(); + return mark_or_box_ccall_result(ConstantInt::get(T_int32, 1), + false, rt, unionall, static_rt, ctx); + } + else if (!jl_has_free_typevars(ety)) { // TODO: jn/foreigncall branch has a better predicate + jl_cgval_t aryv = emit_expr(aryex, ctx); + Value *idx = emit_unbox(T_size, emit_expr(idxex, ctx), (jl_value_t*)jl_ulong_type); + Value *arrayptr = emit_bitcast(emit_arrayptr(aryv, aryex, ctx), T_ppjlvalue); + Value *slot_addr = builder.CreateGEP(arrayptr, idx); + Value *load = tbaa_decorate(tbaa_arraybuf, builder.CreateLoad(slot_addr)); + Value *res = builder.CreateZExt(builder.CreateICmpNE(load, V_null), T_int32); + JL_GC_POP(); + return mark_or_box_ccall_result(res, retboxed, rt, unionall, static_rt, ctx); + } + } + } // emit arguments jl_cgval_t *argv = (jl_cgval_t*)alloca(sizeof(jl_cgval_t) * (nargs - 3) / 2); diff --git a/src/julia.h b/src/julia.h index 9e3b6a2de60c7..3def1f10ee9d9 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1085,12 +1085,14 @@ JL_DLLEXPORT int jl_get_size(jl_value_t *val, size_t *pnt); #define jl_unbox_long(x) jl_unbox_int64(x) #define jl_is_long(x) jl_is_int64(x) #define jl_long_type jl_int64_type +#define jl_ulong_type jl_uint64_type #else #define jl_box_long(x) jl_box_int32(x) #define jl_box_ulong(x) jl_box_uint32(x) #define jl_unbox_long(x) jl_unbox_int32(x) #define jl_is_long(x) jl_is_int32(x) #define jl_long_type jl_int32_type +#define jl_ulong_type jl_uint32_type #endif // Each tuple can exist in one of 4 Vararg states: diff --git a/src/julia_internal.h b/src/julia_internal.h index e40cd82eea32c..015b740b5b650 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -784,6 +784,7 @@ JL_DLLEXPORT jl_value_t *jl_arraylen(jl_value_t *a); int jl_array_store_unboxed(jl_value_t *el_type); int jl_array_isdefined(jl_value_t **args, int nargs); JL_DLLEXPORT jl_value_t *(jl_array_data_owner)(jl_array_t *a); +JL_DLLEXPORT int jl_array_isassigned(jl_array_t *a, size_t i); // -- synchronization utilities -- // From 2d17416553c9b88da4b8c01c6f02c1e6203a33eb Mon Sep 17 00:00:00 2001 From: Mus M Date: Sun, 16 Apr 2017 15:21:35 -0400 Subject: [PATCH 0446/1534] Update to new syntax in misc files --- base/coreimg.jl | 2 +- base/gmp.jl | 8 ++++---- base/libgit2/repository.jl | 6 +++--- base/libgit2/tree.jl | 2 +- base/rounding.jl | 2 +- base/sparse/cholmod.jl | 6 +++--- base/sysimg.jl | 28 ++++++++++++++-------------- base/tuple.jl | 8 ++++---- 8 files changed, 31 insertions(+), 31 deletions(-) diff --git a/base/coreimg.jl b/base/coreimg.jl index 00b225780ebaa..fe5b5547fdce2 100644 --- a/base/coreimg.jl +++ b/base/coreimg.jl @@ -11,7 +11,7 @@ eval(m, x) = Core.eval(m, x) const include = Core.include # conditional to allow redefining Core.Inference after base exists -isdefined(Main, :Base) || ((::Type{T}){T}(arg) = convert(T, arg)::T) +isdefined(Main, :Base) || ((::Type{T})(arg) where {T} = convert(T, arg)::T) function return_type end diff --git a/base/gmp.jl b/base/gmp.jl index 8ccf5359b001e..fd3933e0cf6e4 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -207,20 +207,20 @@ function (::Type{Float64})(n::BigInt, ::RoundingMode{:ToZero}) ccall((:__gmpz_get_d, :libgmp), Float64, (Ptr{BigInt},), &n) end -function (::Type{T}){T<:Union{Float16,Float32}}(n::BigInt, ::RoundingMode{:ToZero}) +function (::Type{T})(n::BigInt, ::RoundingMode{:ToZero}) where T<:Union{Float16,Float32} T(Float64(n,RoundToZero),RoundToZero) end -function (::Type{T}){T<:CdoubleMax}(n::BigInt, ::RoundingMode{:Down}) +function (::Type{T})(n::BigInt, ::RoundingMode{:Down}) where T<:CdoubleMax x = T(n,RoundToZero) x > n ? prevfloat(x) : x end -function (::Type{T}){T<:CdoubleMax}(n::BigInt, ::RoundingMode{:Up}) +function (::Type{T})(n::BigInt, ::RoundingMode{:Up}) where T<:CdoubleMax x = T(n,RoundToZero) x < n ? nextfloat(x) : x end -function (::Type{T}){T<:CdoubleMax}(n::BigInt, ::RoundingMode{:Nearest}) +function (::Type{T})(n::BigInt, ::RoundingMode{:Nearest}) where T<:CdoubleMax x = T(n,RoundToZero) if maxintfloat(T) <= abs(x) < T(Inf) r = n-BigInt(x) diff --git a/base/libgit2/repository.jl b/base/libgit2/repository.jl index 151c5c1e56af0..30cc536c1de27 100644 --- a/base/libgit2/repository.jl +++ b/base/libgit2/repository.jl @@ -111,7 +111,7 @@ Return a `$T` object from `repo` specified by `hash`/`spec`. """ $T end -function (::Type{T}){T<:GitObject}(repo::GitRepo, spec::AbstractString) +function (::Type{T})(repo::GitRepo, spec::AbstractString) where T<:GitObject obj_ptr_ptr = Ref{Ptr{Void}}(C_NULL) @check ccall((:git_revparse_single, :libgit2), Cint, (Ptr{Ptr{Void}}, Ptr{Void}, Cstring), obj_ptr_ptr, repo.ptr, spec) @@ -123,7 +123,7 @@ function (::Type{T}){T<:GitObject}(repo::GitRepo, spec::AbstractString) return T(repo, obj_ptr_ptr[]) end -function (::Type{T}){T<:GitObject}(repo::GitRepo, oid::GitHash) +function (::Type{T})(repo::GitRepo, oid::GitHash) where T<:GitObject oid_ptr = Ref(oid) obj_ptr_ptr = Ref{Ptr{Void}}(C_NULL) @@ -133,7 +133,7 @@ function (::Type{T}){T<:GitObject}(repo::GitRepo, oid::GitHash) return T(repo, obj_ptr_ptr[]) end -function (::Type{T}){T<:GitObject}(repo::GitRepo, oid::GitShortHash) +function (::Type{T})(repo::GitRepo, oid::GitShortHash) where T<:GitObject oid_ptr = Ref(oid.hash) obj_ptr_ptr = Ref{Ptr{Void}}(C_NULL) diff --git a/base/libgit2/tree.jl b/base/libgit2/tree.jl index 64d37c8e63014..af36a46246e04 100644 --- a/base/libgit2/tree.jl +++ b/base/libgit2/tree.jl @@ -53,7 +53,7 @@ function Base.getindex(tree::GitTree, i::Integer) return GitTreeEntry(tree, te_ptr, false) end -function (::Type{T}){T<:GitObject}(te::GitTreeEntry) +function (::Type{T})(te::GitTreeEntry) where T<:GitObject repo = repository(te) obj_ptr_ptr = Ref{Ptr{Void}}(C_NULL) @check ccall((:git_tree_entry_to_object, :libgit2), Cint, diff --git a/base/rounding.jl b/base/rounding.jl index 2c24beb512aad..b56a13c482530 100644 --- a/base/rounding.jl +++ b/base/rounding.jl @@ -199,7 +199,7 @@ end # Assumes conversion is performed by rounding to nearest value. # To avoid ambiguous dispatch with methods in mpfr.jl: -(::Type{T}){T<:AbstractFloat}(x::Real,r::RoundingMode) = _convert_rounding(T,x,r) +(::Type{T})(x::Real,r::RoundingMode) where {T<:AbstractFloat} = _convert_rounding(T,x,r) _convert_rounding{T<:AbstractFloat}(::Type{T},x::Real,r::RoundingMode{:Nearest}) = convert(T,x) function _convert_rounding{T<:AbstractFloat}(::Type{T},x::Real,r::RoundingMode{:Down}) diff --git a/base/sparse/cholmod.jl b/base/sparse/cholmod.jl index 0adaa8f51f51f..578b4129a09d3 100644 --- a/base/sparse/cholmod.jl +++ b/base/sparse/cholmod.jl @@ -857,9 +857,9 @@ end convert(::Type{Dense}, A::Sparse) = sparse_to_dense(A) # This constructior assumes zero based colptr and rowval -function (::Type{Sparse}){Tv<:VTypes}(m::Integer, n::Integer, +function (::Type{Sparse})(m::Integer, n::Integer, colptr0::Vector{SuiteSparse_long}, rowval0::Vector{SuiteSparse_long}, - nzval::Vector{Tv}, stype) + nzval::Vector{Tv}, stype) where Tv<:VTypes # checks ## length of input if length(colptr0) <= n @@ -908,7 +908,7 @@ function (::Type{Sparse})(m::Integer, n::Integer, o end -function (::Type{Sparse}){Tv<:VTypes}(A::SparseMatrixCSC{Tv,SuiteSparse_long}, stype::Integer) +function (::Type{Sparse})(A::SparseMatrixCSC{Tv,SuiteSparse_long}, stype::Integer) where Tv<:VTypes ## Check length of input. This should never fail but see #20024 if length(A.colptr) <= A.n throw(ArgumentError("length of colptr must be at least size(A,2) + 1 = $(A.n + 1) but was $(length(A.colptr))")) diff --git a/base/sysimg.jl b/base/sysimg.jl index ece631fff9dca..e25ce641fa6aa 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -21,10 +21,10 @@ include("coreio.jl") eval(x) = Core.eval(Base, x) eval(m, x) = Core.eval(m, x) -(::Type{T}){T}(arg) = convert(T, arg)::T # Hidden from the REPL. -(::Type{VecElement{T}}){T}(arg) = VecElement{T}(convert(T, arg)) -convert{T<:VecElement}(::Type{T}, arg) = T(arg) -convert{T<:VecElement}(::Type{T}, arg::T) = arg +(::Type{T})(arg) where {T} = convert(T, arg)::T # Hidden from the REPL. +VecElement{T}(arg) where {T} = VecElement{T}(convert(T, arg)) +convert(::Type{T}, arg) where {T<:VecElement} = T(arg) +convert(::Type{T}, arg::T) where {T<:VecElement} = arg # init core docsystem import Core: @doc, @__doc__, @doc_str @@ -90,16 +90,16 @@ include("abstractarray.jl") include("subarray.jl") # Array convenience converting constructors -(::Type{Array{T}}){T}(m::Integer) = Array{T,1}(Int(m)) -(::Type{Array{T}}){T}(m::Integer, n::Integer) = Array{T,2}(Int(m), Int(n)) -(::Type{Array{T}}){T}(m::Integer, n::Integer, o::Integer) = Array{T,3}(Int(m), Int(n), Int(o)) -(::Type{Array{T}}){T}(d::Integer...) = Array{T}(convert(Tuple{Vararg{Int}}, d)) - -(::Type{Vector})() = Array{Any,1}(0) -(::Type{Vector{T}}){T}(m::Integer) = Array{T,1}(Int(m)) -(::Type{Vector})(m::Integer) = Array{Any,1}(Int(m)) -(::Type{Matrix{T}}){T}(m::Integer, n::Integer) = Matrix{T}(Int(m), Int(n)) -(::Type{Matrix})(m::Integer, n::Integer) = Matrix{Any}(Int(m), Int(n)) +Array{T}(m::Integer) where {T} = Array{T,1}(Int(m)) +Array{T}(m::Integer, n::Integer) where {T} = Array{T,2}(Int(m), Int(n)) +Array{T}(m::Integer, n::Integer, o::Integer) where {T} = Array{T,3}(Int(m), Int(n), Int(o)) +Array{T}(d::Integer...) where {T} = Array{T}(convert(Tuple{Vararg{Int}}, d)) + +Vector() = Array{Any,1}(0) +Vector{T}(m::Integer) where {T} = Array{T,1}(Int(m)) +Vector(m::Integer) = Array{Any,1}(Int(m)) +Matrix{T}(m::Integer, n::Integer) where {T} = Matrix{T}(Int(m), Int(n)) +Matrix(m::Integer, n::Integer) = Matrix{Any}(Int(m), Int(n)) # numeric operations include("hashing.jl") diff --git a/base/tuple.jl b/base/tuple.jl index 420a28672096a..863240034483f 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -209,10 +209,10 @@ end # only define these in Base, to avoid overwriting the constructors if isdefined(Main, :Base) -(::Type{T}){T<:Tuple}(x::Tuple) = convert(T, x) # still use `convert` for tuples +(::Type{T})(x::Tuple) where {T<:Tuple} = convert(T, x) # still use `convert` for tuples # resolve ambiguity between preceding and following methods -(::Type{All16{E,N}}){E,N}(x::Tuple) = convert(All16{E,N}, x) +(::Type{All16{E,N}})(x::Tuple) where {E,N} = convert(All16{E,N}, x) function (T::Type{All16{E,N}}){E,N}(itr) len = N+16 @@ -223,7 +223,7 @@ function (T::Type{All16{E,N}}){E,N}(itr) (elts...,) end -(::Type{T}){T<:Tuple}(itr) = _totuple(T, itr, start(itr)) +(::Type{T})(itr) where {T<:Tuple} = _totuple(T, itr, start(itr)) _totuple(::Type{Tuple{}}, itr, s) = () @@ -239,7 +239,7 @@ function _totuple(T, itr, s) (convert(tuple_type_head(T), v), _totuple(tuple_type_tail(T), itr, s)...) end -_totuple{E}(::Type{Tuple{Vararg{E}}}, itr, s) = (collect(E, Iterators.rest(itr,s))...,) +_totuple(::Type{Tuple{Vararg{E}}}, itr, s) where {E} = (collect(E, Iterators.rest(itr,s))...,) _totuple(::Type{Tuple}, itr, s) = (collect(Iterators.rest(itr,s))...,) From aa744260c64f1676800d6472e80239dc7e19178f Mon Sep 17 00:00:00 2001 From: Mus M Date: Sun, 16 Apr 2017 15:58:15 -0400 Subject: [PATCH 0447/1534] Update to use Vector and Refs in appropriate files --- base/LineEdit.jl | 2 +- base/datafmt.jl | 2 +- base/file.jl | 6 +++--- base/grisu/fastprecision.jl | 2 +- base/grisu/fastshortest.jl | 2 +- base/grisu/grisu.jl | 2 +- base/libc.jl | 4 ++-- base/linalg/blas.jl | 8 ++++---- base/pcre.jl | 2 +- base/random.jl | 2 +- base/socket.jl | 4 ++-- base/sparse/sparsematrix.jl | 6 +++--- base/sparse/umfpack.jl | 34 +++++++++++++++++----------------- base/special/gamma.jl | 8 ++++---- base/sysinfo.jl | 16 ++++++++-------- base/util.jl | 2 +- 16 files changed, 51 insertions(+), 51 deletions(-) diff --git a/base/LineEdit.jl b/base/LineEdit.jl index e1e7bedb75098..0334817dc5630 100644 --- a/base/LineEdit.jl +++ b/base/LineEdit.jl @@ -864,7 +864,7 @@ function keymap_merge(target,source) for key in setdiff(keys(source), keys(direct_keys)) # We first resolve redirects in the source value = source[key] - visited = Array{Any}(0) + visited = Vector{Any}(0) while isa(value, Union{Char,AbstractString}) value = normalize_key(value) if value in visited diff --git a/base/datafmt.jl b/base/datafmt.jl index ec847248eca4d..7637e7d36ab84 100644 --- a/base/datafmt.jl +++ b/base/datafmt.jl @@ -27,7 +27,7 @@ passing them as the second argument. function countlines(io::IO, eol::Char='\n') isascii(eol) || throw(ArgumentError("only ASCII line terminators are supported")) aeol = UInt8(eol) - a = Array{UInt8}(8192) + a = Vector{UInt8}(8192) nl = 0 while !eof(io) nb = readbytes!(io, a) diff --git a/base/file.jl b/base/file.jl index 24e26ff462dd7..e5b091b425cc2 100644 --- a/base/file.jl +++ b/base/file.jl @@ -35,7 +35,7 @@ export Get the current working directory. """ function pwd() - b = Array{UInt8}(1024) + b = Vector{UInt8}(1024) len = Ref{Csize_t}(length(b)) uv_error(:getcwd, ccall(:uv_cwd, Cint, (Ptr{UInt8}, Ptr{Csize_t}), b, len)) String(b[1:len[]]) @@ -257,7 +257,7 @@ end if is_windows() function tempdir() - temppath = Array{UInt16}(32767) + temppath = Vector{UInt16}(32767) lentemppath = ccall(:GetTempPathW,stdcall,UInt32,(UInt32,Ptr{UInt16}),length(temppath),temppath) if lentemppath >= length(temppath) || lentemppath == 0 error("GetTempPath failed: $(Libc.FormatMessage())") @@ -269,7 +269,7 @@ tempname(uunique::UInt32=UInt32(0)) = tempname(tempdir(), uunique) const temp_prefix = cwstring("jl_") function tempname(temppath::AbstractString,uunique::UInt32) tempp = cwstring(temppath) - tname = Array{UInt16}(32767) + tname = Vector{UInt16}(32767) uunique = ccall(:GetTempFileNameW,stdcall,UInt32,(Ptr{UInt16},Ptr{UInt16},UInt32,Ptr{UInt16}), tempp,temp_prefix,uunique,tname) lentname = findfirst(tname,0)-1 if uunique == 0 || lentname <= 0 diff --git a/base/grisu/fastprecision.jl b/base/grisu/fastprecision.jl index d4515f96a0b3d..3d737b1d13eb6 100644 --- a/base/grisu/fastprecision.jl +++ b/base/grisu/fastprecision.jl @@ -87,7 +87,7 @@ function digitgen(w,buffer,requested_digits=1000) return r, kappa, len end -function fastprecision(v, requested_digits, buffer = Array{UInt8}(100)) +function fastprecision(v, requested_digits, buffer = Vector{UInt8}(100)) f = normalize(Float64(v)) ten_mk_min_exp = kMinExp - (f.e + FloatSignificandSize) ten_mk_max_exp = kMaxExp - (f.e + FloatSignificandSize) diff --git a/base/grisu/fastshortest.jl b/base/grisu/fastshortest.jl index 0f4ef6c9cc80b..f9009a7703753 100644 --- a/base/grisu/fastshortest.jl +++ b/base/grisu/fastshortest.jl @@ -102,7 +102,7 @@ function digitgen(low,w,high,buffer) end end -function fastshortest(v, buffer = Array{UInt8}(17)) +function fastshortest(v, buffer = Vector{UInt8}(17)) f = normalize(Float64(v)) bound_minus, bound_plus = normalizedbound(v) ten_mk_min_exp = kMinExp - (f.e + FloatSignificandSize) diff --git a/base/grisu/grisu.jl b/base/grisu/grisu.jl index 9a806f1300a72..8bcbf428c138e 100644 --- a/base/grisu/grisu.jl +++ b/base/grisu/grisu.jl @@ -11,7 +11,7 @@ const SHORTEST = 1 const FIXED = 2 const PRECISION = 3 -const DIGITS = Array{UInt8}(309+17) +const DIGITS = Vector{UInt8}(309+17) include("grisu/float.jl") include("grisu/fastshortest.jl") diff --git a/base/libc.jl b/base/libc.jl index d811c79aae6d9..a1880755de5e0 100644 --- a/base/libc.jl +++ b/base/libc.jl @@ -153,7 +153,7 @@ library. strftime(t) = strftime("%c", t) strftime(fmt::AbstractString, t::Real) = strftime(fmt, TmStruct(t)) function strftime(fmt::AbstractString, tm::TmStruct) - timestr = Array{UInt8}(128) + timestr = Vector{UInt8}(128) n = ccall(:strftime, Int, (Ptr{UInt8}, Int, Cstring, Ptr{TmStruct}), timestr, length(timestr), fmt, &tm) if n == 0 @@ -222,7 +222,7 @@ getpid() = ccall(:jl_getpid, Int32, ()) Get the local machine's host name. """ function gethostname() - hn = Array{UInt8}(256) + hn = Vector{UInt8}(256) err = @static if is_windows() ccall(:gethostname, stdcall, Int32, (Ptr{UInt8}, UInt32), hn, length(hn)) else diff --git a/base/linalg/blas.jl b/base/linalg/blas.jl index 75c07ff7d7d12..09e7f81ad3790 100644 --- a/base/linalg/blas.jl +++ b/base/linalg/blas.jl @@ -279,11 +279,11 @@ for (fname, elty) in ((:cblas_zdotc_sub,:Complex128), # * .. Array Arguments .. # DOUBLE PRECISION DX(*),DY(*) function dotc(n::Integer, DX::Union{Ptr{$elty},DenseArray{$elty}}, incx::Integer, DY::Union{Ptr{$elty},DenseArray{$elty}}, incy::Integer) - result = Array{$elty}(1) + result = Ref{$elty}() ccall((@blasfunc($fname), libblas), Void, (BlasInt, Ptr{$elty}, BlasInt, Ptr{$elty}, BlasInt, Ptr{$elty}), n, DX, incx, DY, incy, result) - result[1] + result[] end end end @@ -297,11 +297,11 @@ for (fname, elty) in ((:cblas_zdotu_sub,:Complex128), # * .. Array Arguments .. # DOUBLE PRECISION DX(*),DY(*) function dotu(n::Integer, DX::Union{Ptr{$elty},DenseArray{$elty}}, incx::Integer, DY::Union{Ptr{$elty},DenseArray{$elty}}, incy::Integer) - result = Array{$elty}(1) + result = Ref{$elty}() ccall((@blasfunc($fname), libblas), Void, (BlasInt, Ptr{$elty}, BlasInt, Ptr{$elty}, BlasInt, Ptr{$elty}), n, DX, incx, DY, incy, result) - result[1] + result[] end end end diff --git a/base/pcre.jl b/base/pcre.jl index f857c791bb61c..07ce5e6f0cfa0 100644 --- a/base/pcre.jl +++ b/base/pcre.jl @@ -120,7 +120,7 @@ free_match_context(context) = ccall((:pcre2_match_context_free_8, PCRE_LIB), Void, (Ptr{Void},), context) function err_message(errno) - buffer = Array{UInt8}(256) + buffer = Vector{UInt8}(256) ccall((:pcre2_get_error_message_8, PCRE_LIB), Void, (Int32, Ptr{UInt8}, Csize_t), errno, buffer, sizeof(buffer)) unsafe_string(pointer(buffer)) diff --git a/base/random.jl b/base/random.jl index 9799e247f26ba..d055cca322c56 100644 --- a/base/random.jl +++ b/base/random.jl @@ -1381,7 +1381,7 @@ end function Base.repr(u::UUID) u = u.value - a = Array{UInt8}(36) + a = Vector{UInt8}(36) for i = [36:-1:25; 23:-1:20; 18:-1:15; 13:-1:10; 8:-1:1] d = u & 0xf a[i] = '0'+d+39*(d>9) diff --git a/base/socket.jl b/base/socket.jl index 37b0ff82762d3..853236673f1b8 100644 --- a/base/socket.jl +++ b/base/socket.jl @@ -598,7 +598,7 @@ function uv_getaddrinfocb(req::Ptr{Void}, status::Cint, addrinfo::Ptr{Void}) cb(IPv4(ntoh(ccall(:jl_sockaddr_host4, UInt32, (Ptr{Void},), sockaddr)))) break #elseif ccall(:jl_sockaddr_is_ip6, Int32, (Ptr{Void},), sockaddr) == 1 - # host = Array{UInt128}(1) + # host = Vector{UInt128}(1) # scope_id = ccall(:jl_sockaddr_host6, UInt32, (Ptr{Void}, Ptr{UInt128}), sockaddr, host) # cb(IPv6(ntoh(host[1]))) # break @@ -684,7 +684,7 @@ function getipaddr() return rv # Uncomment to enbable IPv6 #elseif ccall(:jl_sockaddr_in_is_ip6, Int32, (Ptr{Void},), sockaddr) == 1 - # host = Array{UInt128}(1) + # host = Vector{UInt128}(1) # ccall(:jl_sockaddr_host6, UInt32, (Ptr{Void}, Ptr{UInt128}), sockaddrr, host) # return IPv6(ntoh(host[1])) end diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl index 89bae7a60a137..f2826d7fa88c0 100644 --- a/base/sparse/sparsematrix.jl +++ b/base/sparse/sparsematrix.jl @@ -1219,7 +1219,7 @@ function sprand_IJ(r::AbstractRNG, m::Integer, n::Integer, density::AbstractFloa 0 <= density <= 1 || throw(ArgumentError("$density not in [0,1]")) N = n*m - I, J = Array{Int}(0), Array{Int}(0) # indices of nonzero elements + I, J = Vector{Int}(0), Vector{Int}(0) # indices of nonzero elements sizehint!(I, round(Int,N*density)) sizehint!(J, round(Int,N*density)) @@ -1229,7 +1229,7 @@ function sprand_IJ(r::AbstractRNG, m::Integer, n::Integer, density::AbstractFloa colsparsity = exp(m*L) # = 1 - coldensity iL = 1/L - rows = Array{Int}(0) + rows = Vector{Int}(0) for j in randsubseq(r, 1:n, coldensity) # To get the right statistics, we *must* have a nonempty column j # even if p*m << 1. To do this, we use an approach similar to @@ -1373,7 +1373,7 @@ spzeros(m::Integer, n::Integer) = spzeros(Float64, m, n) spzeros(Tv::Type, m::Integer, n::Integer) = spzeros(Tv, Int, m, n) function spzeros(Tv::Type, Ti::Type, m::Integer, n::Integer) ((m < 0) || (n < 0)) && throw(ArgumentError("invalid Array dimensions")) - SparseMatrixCSC(m, n, ones(Ti, n+1), Array{Ti}(0), Array{Tv}(0)) + SparseMatrixCSC(m, n, ones(Ti, n+1), Vector{Ti}(0), Vector{Tv}(0)) end # de-splatting variant spzeros(Tv::Type, Ti::Type, sz::Tuple{Integer,Integer}) = spzeros(Tv, Ti, sz[1], sz[2]) diff --git a/base/sparse/umfpack.jl b/base/sparse/umfpack.jl index 6cfd5ae8beddb..8e1f07c634bb5 100644 --- a/base/sparse/umfpack.jl +++ b/base/sparse/umfpack.jl @@ -285,41 +285,41 @@ for itype in UmfpackIndexTypes return x end function det(lu::UmfpackLU{Float64,$itype}) - mx = Array{Float64}(1) + mx = Ref{Float64}() @isok ccall(($det_r,:libumfpack), $itype, (Ptr{Float64},Ptr{Float64},Ptr{Void},Ptr{Float64}), mx, C_NULL, lu.numeric, umf_info) - mx[1] + mx[] end function det(lu::UmfpackLU{Complex128,$itype}) - mx = Array{Float64}(1) - mz = Array{Float64}(1) + mx = Ref{Float64}() + mz = Ref{Float64}() @isok ccall(($det_z,:libumfpack), $itype, (Ptr{Float64},Ptr{Float64},Ptr{Float64},Ptr{Void},Ptr{Float64}), mx, mz, C_NULL, lu.numeric, umf_info) - complex(mx[1], mz[1]) + complex(mx[], mz[]) end function umf_lunz(lu::UmfpackLU{Float64,$itype}) - lnz = Array{$itype}(1) - unz = Array{$itype}(1) - n_row = Array{$itype}(1) - n_col = Array{$itype}(1) - nz_diag = Array{$itype}(1) + lnz = Ref{$itype}() + unz = Ref{$itype}() + n_row = Ref{$itype}() + n_col = Ref{$itype}() + nz_diag = Ref{$itype}() @isok ccall(($lunz_r,:libumfpack), $itype, (Ptr{$itype},Ptr{$itype},Ptr{$itype},Ptr{$itype},Ptr{$itype},Ptr{Void}), lnz, unz, n_row, n_col, nz_diag, lu.numeric) - (lnz[1], unz[1], n_row[1], n_col[1], nz_diag[1]) + (lnz[], unz[], n_row[], n_col[], nz_diag[]) end function umf_lunz(lu::UmfpackLU{Complex128,$itype}) - lnz = Array{$itype}(1) - unz = Array{$itype}(1) - n_row = Array{$itype}(1) - n_col = Array{$itype}(1) - nz_diag = Array{$itype}(1) + lnz = Ref{$itype}() + unz = Ref{$itype}() + n_row = Ref{$itype}() + n_col = Ref{$itype}() + nz_diag = Ref{$itype}() @isok ccall(($lunz_z,:libumfpack), $itype, (Ptr{$itype},Ptr{$itype},Ptr{$itype},Ptr{$itype},Ptr{$itype},Ptr{Void}), lnz, unz, n_row, n_col, nz_diag, lu.numeric) - (lnz[1], unz[1], n_row[1], n_col[1], nz_diag[1]) + (lnz[], unz[], n_row[], n_col[], nz_diag[]) end function umf_extract(lu::UmfpackLU{Float64,$itype}) umfpack_numeric!(lu) # ensure the numeric decomposition exists diff --git a/base/special/gamma.jl b/base/special/gamma.jl index 7363de8a78454..6758530a7e4f6 100644 --- a/base/special/gamma.jl +++ b/base/special/gamma.jl @@ -11,14 +11,14 @@ Compute the gamma function of `x`. gamma(x::Real) = gamma(float(x)) function lgamma_r(x::Float64) - signp = Array{Int32}(1) + signp = Ref{Int32}() y = ccall((:lgamma_r,libm), Float64, (Float64, Ptr{Int32}), x, signp) - return y, signp[1] + return y, signp[] end function lgamma_r(x::Float32) - signp = Array{Int32}(1) + signp = Ref{Int32}() y = ccall((:lgammaf_r,libm), Float32, (Float32, Ptr{Int32}), x, signp) - return y, signp[1] + return y, signp[] end lgamma_r(x::Real) = lgamma_r(float(x)) lgamma_r(x::Number) = lgamma(x), 1 # lgamma does not take abs for non-real x diff --git a/base/sysinfo.jl b/base/sysinfo.jl index d23f709a140f4..97f8a75950a29 100644 --- a/base/sysinfo.jl +++ b/base/sysinfo.jl @@ -130,25 +130,25 @@ function cpu_summary(io::IO=STDOUT, cpu::Array{CPUinfo}=cpu_info()) end function cpu_info() - UVcpus = Array{Ptr{UV_cpu_info_t}}(1) - count = Array{Int32}(1) + UVcpus = Ref{Ptr{UV_cpu_info_t}}() + count = Ref{Int32}() Base.uv_error("uv_cpu_info",ccall(:uv_cpu_info, Int32, (Ptr{Ptr{UV_cpu_info_t}}, Ptr{Int32}), UVcpus, count)) - cpus = Array{CPUinfo}(count[1]) + cpus = Vector{CPUinfo}(count[]) for i = 1:length(cpus) - cpus[i] = CPUinfo(unsafe_load(UVcpus[1], i)) + cpus[i] = CPUinfo(unsafe_load(UVcpus[], i)) end - ccall(:uv_free_cpu_info, Void, (Ptr{UV_cpu_info_t}, Int32), UVcpus[1], count[1]) + ccall(:uv_free_cpu_info, Void, (Ptr{UV_cpu_info_t}, Int32), UVcpus[], count[]) return cpus end function uptime() - uptime_ = Array{Float64}(1) + uptime_ = Ref{Float64}() Base.uv_error("uv_uptime",ccall(:uv_uptime, Int32, (Ptr{Float64},), uptime_)) - return uptime_[1] + return uptime_[] end function loadavg() - loadavg_ = Array{Float64}(3) + loadavg_ = Vector{Float64}(3) ccall(:uv_loadavg, Void, (Ptr{Float64},), loadavg_) return loadavg_ end diff --git a/base/util.jl b/base/util.jl index 9a50ddf25db31..193ec1147327f 100644 --- a/base/util.jl +++ b/base/util.jl @@ -640,7 +640,7 @@ if is_windows() function getpass(prompt::AbstractString) print(prompt) flush(STDOUT) - p = Array{UInt8}(128) # mimic Unix getpass in ignoring more than 128-char passwords + p = Vector{UInt8}(128) # mimic Unix getpass in ignoring more than 128-char passwords # (also avoids any potential memory copies arising from push!) try plen = 0 From 8b287adc1b11081e4ada1afedb3c46a741f21069 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sun, 16 Apr 2017 15:57:32 -0400 Subject: [PATCH 0448/1534] fix #21397, `Nullable(Tuple)` method error This was caused by widening a signature in `jl_is_cacheable_sig` such that we ended up calling a specialization containing an unknown static parameter value. This failed when the specialization was created by inference, since it correctly stored a typevar as the value of the static parameter. However when the specialization was created by the method caching logic it accidentally worked, since the static parameter value was derived before widening. --- src/gf.c | 2 ++ test/core.jl | 5 +++++ test/nullable.jl | 3 +++ 3 files changed, 10 insertions(+) diff --git a/src/gf.c b/src/gf.c index a018ae0feebc3..0d44f879c6f47 100644 --- a/src/gf.c +++ b/src/gf.c @@ -606,6 +606,7 @@ static void jl_cacheable_sig( // avoid specializing on an argument of type Tuple // unless matching a declared type of `::Type` if (jl_is_type_type(elt) && jl_is_tuple_type(jl_tparam0(elt)) && + !jl_has_free_typevars(decl_i) && (!jl_subtype(decl_i, (jl_value_t*)jl_type_type) || jl_is_kind(decl_i))) { // Type{Tuple{...}} elt = (jl_value_t*)jl_anytuple_type_type; // Type{T} where T<:Tuple if (!*newparams) *newparams = jl_svec_copy(type->parameters); @@ -738,6 +739,7 @@ JL_DLLEXPORT int jl_is_cacheable_sig( // avoid specializing on an argument of type Tuple // unless matching a declared type of `::Type` if (jl_is_type_type(elt) && jl_is_tuple_type(jl_tparam0(elt)) && + !jl_has_free_typevars(decl_i) && (!jl_subtype(decl_i, (jl_value_t*)jl_type_type) || jl_is_kind(decl_i))) { // Type{Tuple{...}} if (!jl_types_equal(elt, (jl_value_t*)jl_anytuple_type_type)) return 0; diff --git a/test/core.jl b/test/core.jl index 856941f06e1de..1ab108579bb9b 100644 --- a/test/core.jl +++ b/test/core.jl @@ -4820,3 +4820,8 @@ f21271() = convert(Tuple{Type{Int}, Type{Float64}}, (Int, Float64))::Tuple{Type{ f21271(x) = x::Tuple{Type{Int}, Type{Float64}} @test_throws TypeError f21271() @test_throws TypeError f21271((Int, Float64)) + +# issue #21397 +bar21397(x::T) where {T} = T +foo21397(x) = bar21397(x) +@test foo21397(Tuple) == DataType diff --git a/test/nullable.jl b/test/nullable.jl index db433bf8e5bbb..3f2dc75cd6126 100644 --- a/test/nullable.jl +++ b/test/nullable.jl @@ -525,3 +525,6 @@ end let f19270{S,T}(x::S, y::T) = Base.promote_op(^, S, T) @test f19270(Nullable(0.0f0), Nullable(BigInt(0))) == Nullable{Float32} end + +# issue #21397 +@test Nullable(Tuple) === Nullable{DataType}(Tuple) From 8fb718d721c362de70d0a8c17a7e91ee2996a4b9 Mon Sep 17 00:00:00 2001 From: Mus M Date: Sun, 16 Apr 2017 21:10:07 -0400 Subject: [PATCH 0449/1534] Use where syntax in convert function --- base/abstractarray.jl | 8 ++++---- base/array.jl | 12 ++++++------ base/bitarray.jl | 14 +++++++------- base/boot.jl | 2 +- base/char.jl | 2 +- base/complex.jl | 6 +++--- base/deprecated.jl | 12 ++++++------ base/dict.jl | 4 ++-- base/essentials.jl | 4 ++-- base/gmp.jl | 4 ++-- base/irrationals.jl | 2 +- base/mpfr.jl | 2 +- base/multidimensional.jl | 6 +++--- base/nullable.jl | 16 ++++++++-------- base/pair.jl | 4 ++-- base/pointer.jl | 10 +++++----- base/range.jl | 34 +++++++++++++++++----------------- base/rational.jl | 12 ++++++------ base/refpointer.jl | 6 +++--- base/set.jl | 4 ++-- base/sharedarray.jl | 4 ++-- base/twiceprecision.jl | 12 ++++++------ base/weakkeydict.jl | 4 ++-- 23 files changed, 92 insertions(+), 92 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 3d81227c56f8b..e2ec40b8f11e6 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -824,11 +824,11 @@ isempty(a::AbstractArray) = (_length(a) == 0) ## Conversions ## -convert{T,N }(::Type{AbstractArray{T,N}}, A::AbstractArray{T,N}) = A -convert{T,S,N}(::Type{AbstractArray{T,N}}, A::AbstractArray{S,N}) = copy!(similar(A,T), A) -convert{T,S,N}(::Type{AbstractArray{T }}, A::AbstractArray{S,N}) = convert(AbstractArray{T,N}, A) +convert(::Type{AbstractArray{T,N}}, A::AbstractArray{T,N}) where {T,N } = A +convert(::Type{AbstractArray{T,N}}, A::AbstractArray{S,N}) where {T,S,N} = copy!(similar(A,T), A) +convert(::Type{AbstractArray{T }}, A::AbstractArray{S,N}) where {T,S,N} = convert(AbstractArray{T,N}, A) -convert{T,N}(::Type{Array}, A::AbstractArray{T,N}) = convert(Array{T,N}, A) +convert(::Type{Array}, A::AbstractArray{T,N}) where {T,N} = convert(Array{T,N}, A) """ of_indices(x, y) diff --git a/base/array.jl b/base/array.jl index a7e28bb6f9a93..236cefd4c5903 100644 --- a/base/array.jl +++ b/base/array.jl @@ -317,14 +317,14 @@ oneunit{T}(x::AbstractMatrix{T}) = _one(oneunit(T), x) ## Conversions ## -convert{T}(::Type{Vector}, x::AbstractVector{T}) = convert(Vector{T}, x) -convert{T}(::Type{Matrix}, x::AbstractMatrix{T}) = convert(Matrix{T}, x) +convert(::Type{Vector}, x::AbstractVector{T}) where {T} = convert(Vector{T}, x) +convert(::Type{Matrix}, x::AbstractMatrix{T}) where {T} = convert(Matrix{T}, x) -convert{T,n}(::Type{Array{T}}, x::Array{T,n}) = x -convert{T,n}(::Type{Array{T,n}}, x::Array{T,n}) = x +convert(::Type{Array{T}}, x::Array{T,n}) where {T,n} = x +convert(::Type{Array{T,n}}, x::Array{T,n}) where {T,n} = x -convert{T,n,S}(::Type{Array{T}}, x::AbstractArray{S, n}) = convert(Array{T, n}, x) -convert{T,n,S}(::Type{Array{T,n}}, x::AbstractArray{S,n}) = copy!(Array{T,n}(size(x)), x) +convert(::Type{Array{T}}, x::AbstractArray{S,n}) where {T,n,S} = convert(Array{T,n}, x) +convert(::Type{Array{T,n}}, x::AbstractArray{S,n}) where {T,n,S} = copy!(Array{T,n}(size(x)), x) promote_rule{T,n,S}(::Type{Array{T,n}}, ::Type{Array{S,n}}) = Array{promote_type(T,S),n} diff --git a/base/bitarray.jl b/base/bitarray.jl index 5c181e44b728f..99faeebf38183 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -485,8 +485,8 @@ end ## Conversions ## -convert{T,N}(::Type{Array{T}}, B::BitArray{N}) = convert(Array{T,N}, B) -convert{T,N}(::Type{Array{T,N}}, B::BitArray{N}) = _convert(Array{T,N}, B) # see #15801 +convert(::Type{Array{T}}, B::BitArray{N}) where {T,N} = convert(Array{T,N}, B) +convert(::Type{Array{T,N}}, B::BitArray{N}) where {T,N} = _convert(Array{T,N}, B) # see #15801 function _convert{T,N}(::Type{Array{T,N}}, B::BitArray{N}) A = Array{T}(size(B)) Bc = B.chunks @@ -496,8 +496,8 @@ function _convert{T,N}(::Type{Array{T,N}}, B::BitArray{N}) return A end -convert{T,N}(::Type{BitArray}, A::AbstractArray{T,N}) = convert(BitArray{N}, A) -function convert{T,N}(::Type{BitArray{N}}, A::AbstractArray{T,N}) +convert(::Type{BitArray}, A::AbstractArray{T,N}) where {T,N} = convert(BitArray{N}, A) +function convert(::Type{BitArray{N}}, A::AbstractArray{T,N}) where N where T B = BitArray(size(A)) Bc = B.chunks l = length(B) @@ -522,7 +522,7 @@ function convert{T,N}(::Type{BitArray{N}}, A::AbstractArray{T,N}) return B end -function convert{N}(::Type{BitArray{N}}, A::Array{Bool,N}) +function convert(::Type{BitArray{N}}, A::Array{Bool,N}) where N B = BitArray(size(A)) Bc = B.chunks l = length(B) @@ -531,8 +531,8 @@ function convert{N}(::Type{BitArray{N}}, A::Array{Bool,N}) return B end -convert{N}(::Type{BitArray{N}}, B::BitArray{N}) = B -convert{T,N}(::Type{AbstractArray{T,N}}, B::BitArray{N}) = convert(Array{T,N}, B) +convert(::Type{BitArray{N}}, B::BitArray{N}) where {N} = B +convert(::Type{AbstractArray{T,N}}, B::BitArray{N}) where {T,N} = convert(Array{T,N}, B) reinterpret{N}(::Type{Bool}, B::BitArray, dims::NTuple{N,Int}) = reinterpret(B, dims) reinterpret{N}(B::BitArray, dims::NTuple{N,Int}) = reshape(B, dims) diff --git a/base/boot.jl b/base/boot.jl index cd3ae8b4909bb..7c9284c91dc73 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -294,7 +294,7 @@ Task(f::ANY) = ccall(:jl_new_task, Ref{Task}, (Any, Int), f, 0) # note that there is no actual conversion defined here, # so the methods and ccall's in Core aren't permitted to use convert convert(::Type{Any}, x::ANY) = x -convert{T}(::Type{T}, x::T) = x +convert(::Type{T}, x::T) where {T} = x cconvert{T}(::Type{T}, x) = convert(T, x) unsafe_convert{T}(::Type{T}, x::T) = x diff --git a/base/char.jl b/base/char.jl index f3c3b83abab56..3e72f88608fc8 100644 --- a/base/char.jl +++ b/base/char.jl @@ -3,7 +3,7 @@ convert(::Type{Char}, x::UInt32) = reinterpret(Char, x) convert(::Type{Char}, x::Number) = Char(UInt32(x)) convert(::Type{UInt32}, x::Char) = reinterpret(UInt32, x) -convert{T<:Number}(::Type{T}, x::Char) = convert(T, UInt32(x)) +convert(::Type{T}, x::Char) where {T<:Number} = convert(T, UInt32(x)) rem{T<:Number}(x::Char, ::Type{T}) = rem(UInt32(x), T) diff --git a/base/complex.jl b/base/complex.jl index 7e5ed0874c609..3d0bf6cebcf84 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -18,9 +18,9 @@ const Complex128 = Complex{Float64} const Complex64 = Complex{Float32} const Complex32 = Complex{Float16} -convert{T<:Real}(::Type{Complex{T}}, x::Real) = Complex{T}(x,0) -convert{T<:Real}(::Type{Complex{T}}, z::Complex) = Complex{T}(real(z),imag(z)) -convert{T<:Real}(::Type{T}, z::Complex) = +convert(::Type{Complex{T}}, x::Real) where {T<:Real} = Complex{T}(x,0) +convert(::Type{Complex{T}}, z::Complex) where {T<:Real} = Complex{T}(real(z),imag(z)) +convert(::Type{T}, z::Complex) where {T<:Real} = isreal(z) ? convert(T,real(z)) : throw(InexactError()) convert(::Type{Complex}, z::Complex) = z diff --git a/base/deprecated.jl b/base/deprecated.jl index 1c8905f167136..eda5caa42f303 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1220,22 +1220,22 @@ end /(r::Use_StepRangeLen_Instead, x::Real) = Use_StepRangeLen_Instead(r.start/x, r.step/x, r.len, r.divisor) promote_rule{T1,T2}(::Type{Use_StepRangeLen_Instead{T1}},::Type{Use_StepRangeLen_Instead{T2}}) = Use_StepRangeLen_Instead{promote_type(T1,T2)} -convert{T<:AbstractFloat}(::Type{Use_StepRangeLen_Instead{T}}, r::Use_StepRangeLen_Instead{T}) = r -convert{T<:AbstractFloat}(::Type{Use_StepRangeLen_Instead{T}}, r::Use_StepRangeLen_Instead) = +convert(::Type{Use_StepRangeLen_Instead{T}}, r::Use_StepRangeLen_Instead{T}) where {T<:AbstractFloat} = r +convert(::Type{Use_StepRangeLen_Instead{T}}, r::Use_StepRangeLen_Instead) where {T<:AbstractFloat} = Use_StepRangeLen_Instead{T}(r.start,r.step,r.len,r.divisor) promote_rule{F,OR<:OrdinalRange}(::Type{Use_StepRangeLen_Instead{F}}, ::Type{OR}) = Use_StepRangeLen_Instead{promote_type(F,eltype(OR))} -convert{T<:AbstractFloat}(::Type{Use_StepRangeLen_Instead{T}}, r::OrdinalRange) = +convert(::Type{Use_StepRangeLen_Instead{T}}, r::OrdinalRange) where {T<:AbstractFloat} = Use_StepRangeLen_Instead{T}(first(r), step(r), length(r), one(T)) -convert{T}(::Type{Use_StepRangeLen_Instead}, r::OrdinalRange{T}) = +convert(::Type{Use_StepRangeLen_Instead}, r::OrdinalRange{T}) where {T} = Use_StepRangeLen_Instead{typeof(float(first(r)))}(first(r), step(r), length(r), one(T)) promote_rule{F,OR<:Use_StepRangeLen_Instead}(::Type{LinSpace{F}}, ::Type{OR}) = LinSpace{promote_type(F,eltype(OR))} -convert{T<:AbstractFloat}(::Type{LinSpace{T}}, r::Use_StepRangeLen_Instead) = +convert(::Type{LinSpace{T}}, r::Use_StepRangeLen_Instead) where {T<:AbstractFloat} = linspace(convert(T, first(r)), convert(T, last(r)), convert(T, length(r))) -convert{T<:AbstractFloat}(::Type{LinSpace}, r::Use_StepRangeLen_Instead{T}) = +convert(::Type{LinSpace}, r::Use_StepRangeLen_Instead{T}) where {T<:AbstractFloat} = convert(LinSpace{T}, r) reverse(r::Use_StepRangeLen_Instead) = Use_StepRangeLen_Instead(r.start + (r.len-1)*r.step, -r.step, r.len, r.divisor) diff --git a/base/dict.jl b/base/dict.jl index 4fe8ce2d669e3..202f844050cb4 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -193,7 +193,7 @@ similar{K,V}(d::Dict{K,V}) = Dict{K,V}() similar{K,V}(d::Dict, ::Type{Pair{K,V}}) = Dict{K,V}() # conversion between Dict types -function convert{K,V}(::Type{Dict{K,V}},d::Associative) +function convert(::Type{Dict{K,V}},d::Associative) where V where K h = Dict{K,V}() for (k,v) in d ck = convert(K,k) @@ -205,7 +205,7 @@ function convert{K,V}(::Type{Dict{K,V}},d::Associative) end return h end -convert{K,V}(::Type{Dict{K,V}},d::Dict{K,V}) = d +convert(::Type{Dict{K,V}},d::Dict{K,V}) where {K,V} = d hashindex(key, sz) = (((hash(key)%Int) & (sz-1)) + 1)::Int diff --git a/base/essentials.jl b/base/essentials.jl index bcdcf5c221328..e2349e0901234 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -26,11 +26,11 @@ macro _propagate_inbounds_meta() end convert(::Type{Any}, x::ANY) = x -convert{T}(::Type{T}, x::T) = x +convert(::Type{T}, x::T) where {T} = x convert(::Type{Tuple{}}, ::Tuple{}) = () convert(::Type{Tuple}, x::Tuple) = x -convert{T}(::Type{Tuple{Vararg{T}}}, x::Tuple) = cnvt_all(T, x...) +convert(::Type{Tuple{Vararg{T}}}, x::Tuple) where {T} = cnvt_all(T, x...) cnvt_all(T) = () cnvt_all(T, x, rest...) = tuple(convert(T,x), cnvt_all(T, rest...)...) diff --git a/base/gmp.jl b/base/gmp.jl index fd3933e0cf6e4..7232d4a416104 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -180,7 +180,7 @@ end rem(x::Integer, ::Type{BigInt}) = convert(BigInt, x) -function convert{T<:Unsigned}(::Type{T}, x::BigInt) +function convert(::Type{T}, x::BigInt) where T<:Unsigned if sizeof(T) < sizeof(Limb) convert(T, convert(Limb,x)) else @@ -189,7 +189,7 @@ function convert{T<:Unsigned}(::Type{T}, x::BigInt) end end -function convert{T<:Signed}(::Type{T}, x::BigInt) +function convert(::Type{T}, x::BigInt) where T<:Signed n = abs(x.size) if sizeof(T) < sizeof(Limb) SLimb = typeof(Signed(one(Limb))) diff --git a/base/irrationals.jl b/base/irrationals.jl index 1d61d426a4f2f..f02be49e83524 100644 --- a/base/irrationals.jl +++ b/base/irrationals.jl @@ -13,7 +13,7 @@ promote_rule{T<:Number}(::Type{<:Irrational}, ::Type{T}) = promote_type(Float64, convert(::Type{AbstractFloat}, x::Irrational) = Float64(x) convert(::Type{Float16}, x::Irrational) = Float16(Float32(x)) -convert{T<:Real}(::Type{Complex{T}}, x::Irrational) = convert(Complex{T}, convert(T,x)) +convert(::Type{Complex{T}}, x::Irrational) where {T<:Real} = convert(Complex{T}, convert(T,x)) @pure function convert{T<:Integer}(::Type{Rational{T}}, x::Irrational) o = precision(BigFloat) diff --git a/base/mpfr.jl b/base/mpfr.jl index 04b761a08216c..0a80427c20b2c 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -227,7 +227,7 @@ function convert(::Type{Integer},x::BigFloat) isinteger(x) || throw(InexactError()) trunc(Integer,x) end -function convert{T<:Integer}(::Type{T},x::BigFloat) +function convert(::Type{T},x::BigFloat) where T<:Integer isinteger(x) || throw(InexactError()) trunc(T,x) end diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 53886f69d18ab..80ff5db6f46be 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -123,11 +123,11 @@ module IteratorsMD CartesianRange{N}(rngs::NTuple{N,Union{Integer,AbstractUnitRange}}) = CartesianRange(CartesianIndex(map(first, rngs)), CartesianIndex(map(last, rngs))) - convert{N}(::Type{NTuple{N,UnitRange{Int}}}, R::CartesianRange{CartesianIndex{N}}) = + convert(::Type{NTuple{N,UnitRange{Int}}}, R::CartesianRange{CartesianIndex{N}}) where {N} = map((f,l)->f:l, first(R).I, last(R).I) - convert{N}(::Type{NTuple{N,UnitRange}}, R::CartesianRange) = + convert(::Type{NTuple{N,UnitRange}}, R::CartesianRange) where {N} = convert(NTuple{N,UnitRange{Int}}, R) - convert{N}(::Type{Tuple{Vararg{UnitRange{Int}}}}, R::CartesianRange{CartesianIndex{N}}) = + convert(::Type{Tuple{Vararg{UnitRange{Int}}}}, R::CartesianRange{CartesianIndex{N}}) where {N} = convert(NTuple{N,UnitRange{Int}}, R) convert(::Type{Tuple{Vararg{UnitRange}}}, R::CartesianRange) = convert(Tuple{Vararg{UnitRange{Int}}}, R) diff --git a/base/nullable.jl b/base/nullable.jl index 2d81ebdbfe569..911a038273478 100644 --- a/base/nullable.jl +++ b/base/nullable.jl @@ -36,21 +36,21 @@ Nullable() = Nullable{Union{}}() eltype{T}(::Type{Nullable{T}}) = T -convert{T}(::Type{Nullable{T}}, x::Nullable{T}) = x -convert( ::Type{Nullable }, x::Nullable ) = x +convert(::Type{Nullable{T}}, x::Nullable{T}) where {T} = x +convert(::Type{Nullable }, x::Nullable ) = x convert{T}(t::Type{Nullable{T}}, x::Any) = convert(t, convert(T, x)) -function convert{T}(::Type{Nullable{T}}, x::Nullable) +function convert(::Type{Nullable{T}}, x::Nullable) where T return isnull(x) ? Nullable{T}() : Nullable{T}(convert(T, get(x))) end -convert{T<:Nullable}(::Type{Nullable{T}}, x::T) = Nullable{T}(x) -convert{T}(::Type{Nullable{T}}, x::T) = Nullable{T}(x) -convert{T}(::Type{Nullable }, x::T) = Nullable{T}(x) +convert(::Type{Nullable{T}}, x::T) where {T<:Nullable} = Nullable{T}(x) +convert(::Type{Nullable{T}}, x::T) where {T} = Nullable{T}(x) +convert(::Type{Nullable }, x::T) where {T} = Nullable{T}(x) -convert{T}(::Type{Nullable{T}}, ::Void) = Nullable{T}() -convert( ::Type{Nullable }, ::Void) = Nullable{Union{}}() +convert(::Type{Nullable{T}}, ::Void) where {T} = Nullable{T}() +convert(::Type{Nullable }, ::Void) = Nullable{Union{}}() promote_rule{S,T}(::Type{Nullable{S}}, ::Type{T}) = Nullable{promote_type(S, T)} promote_rule{S,T}(::Type{Nullable{S}}, ::Type{Nullable{T}}) = Nullable{promote_type(S, T)} diff --git a/base/pair.jl b/base/pair.jl index 798694fd095c2..0236fbbe482a5 100644 --- a/base/pair.jl +++ b/base/pair.jl @@ -30,8 +30,8 @@ length(p::Pair) = 2 first(p::Pair) = p.first last(p::Pair) = p.second -convert{A,B}(::Type{Pair{A,B}}, x::Pair{A,B}) = x -function convert{A,B}(::Type{Pair{A,B}}, x::Pair) +convert(::Type{Pair{A,B}}, x::Pair{A,B}) where {A,B} = x +function convert(::Type{Pair{A,B}}, x::Pair) where A where B Pair{A, B}(convert(A, x[1]), convert(B, x[2])) end diff --git a/base/pointer.jl b/base/pointer.jl index 7bb7d20128c47..c193c3e865384 100644 --- a/base/pointer.jl +++ b/base/pointer.jl @@ -21,15 +21,15 @@ const C_NULL = bitcast(Ptr{Void}, 0) # pointer to integer convert{T<:Union{Int,UInt}}(::Type{T}, x::Ptr) = bitcast(T, x) -convert{T<:Integer}(::Type{T}, x::Ptr) = convert(T, convert(UInt, x)) +convert(::Type{T}, x::Ptr) where {T<:Integer} = convert(T, convert(UInt, x)) # integer to pointer -convert{T}(::Type{Ptr{T}}, x::UInt) = bitcast(Ptr{T}, x) -convert{T}(::Type{Ptr{T}}, x::Int) = bitcast(Ptr{T}, x) +convert(::Type{Ptr{T}}, x::UInt) where {T} = bitcast(Ptr{T}, x) +convert(::Type{Ptr{T}}, x::Int) where {T} = bitcast(Ptr{T}, x) # pointer to pointer -convert{T}(::Type{Ptr{T}}, p::Ptr{T}) = p -convert{T}(::Type{Ptr{T}}, p::Ptr) = bitcast(Ptr{T}, p) +convert(::Type{Ptr{T}}, p::Ptr{T}) where {T} = p +convert(::Type{Ptr{T}}, p::Ptr) where {T} = bitcast(Ptr{T}, p) # object to pointer (when used with ccall) unsafe_convert(::Type{Ptr{UInt8}}, x::Symbol) = ccall(:jl_symbol_name, Ptr{UInt8}, (Any,), x) diff --git a/base/range.jl b/base/range.jl index 30123077329c7..f3d5cfca90c5c 100644 --- a/base/range.jl +++ b/base/range.jl @@ -747,52 +747,52 @@ end promote_rule{T1,T2}(::Type{UnitRange{T1}},::Type{UnitRange{T2}}) = UnitRange{promote_type(T1,T2)} -convert{T<:Real}(::Type{UnitRange{T}}, r::UnitRange{T}) = r -convert{T<:Real}(::Type{UnitRange{T}}, r::UnitRange) = UnitRange{T}(r.start, r.stop) +convert(::Type{UnitRange{T}}, r::UnitRange{T}) where {T<:Real} = r +convert(::Type{UnitRange{T}}, r::UnitRange) where {T<:Real} = UnitRange{T}(r.start, r.stop) promote_rule{T1,T2}(::Type{OneTo{T1}},::Type{OneTo{T2}}) = OneTo{promote_type(T1,T2)} -convert{T<:Real}(::Type{OneTo{T}}, r::OneTo{T}) = r -convert{T<:Real}(::Type{OneTo{T}}, r::OneTo) = OneTo{T}(r.stop) +convert(::Type{OneTo{T}}, r::OneTo{T}) where {T<:Real} = r +convert(::Type{OneTo{T}}, r::OneTo) where {T<:Real} = OneTo{T}(r.stop) promote_rule{T1,UR<:AbstractUnitRange}(::Type{UnitRange{T1}}, ::Type{UR}) = UnitRange{promote_type(T1,eltype(UR))} -convert{T<:Real}(::Type{UnitRange{T}}, r::AbstractUnitRange) = UnitRange{T}(first(r), last(r)) +convert(::Type{UnitRange{T}}, r::AbstractUnitRange) where {T<:Real} = UnitRange{T}(first(r), last(r)) convert(::Type{UnitRange}, r::AbstractUnitRange) = UnitRange(first(r), last(r)) promote_rule{T1a,T1b,T2a,T2b}(::Type{StepRange{T1a,T1b}},::Type{StepRange{T2a,T2b}}) = StepRange{promote_type(T1a,T2a),promote_type(T1b,T2b)} -convert{T1,T2}(::Type{StepRange{T1,T2}}, r::StepRange{T1,T2}) = r +convert(::Type{StepRange{T1,T2}}, r::StepRange{T1,T2}) where {T1,T2} = r promote_rule{T1a,T1b,UR<:AbstractUnitRange}(::Type{StepRange{T1a,T1b}},::Type{UR}) = StepRange{promote_type(T1a,eltype(UR)),promote_type(T1b,eltype(UR))} -convert{T1,T2}(::Type{StepRange{T1,T2}}, r::Range) = +convert(::Type{StepRange{T1,T2}}, r::Range) where {T1,T2} = StepRange{T1,T2}(convert(T1, first(r)), convert(T2, step(r)), convert(T1, last(r))) -convert{T}(::Type{StepRange}, r::AbstractUnitRange{T}) = +convert(::Type{StepRange}, r::AbstractUnitRange{T}) where {T} = StepRange{T,T}(first(r), step(r), last(r)) promote_rule{T1,T2,R1,R2,S1,S2}(::Type{StepRangeLen{T1,R1,S1}},::Type{StepRangeLen{T2,R2,S2}}) = StepRangeLen{promote_type(T1,T2), promote_type(R1,R2), promote_type(S1,S2)} -convert{T,R,S}(::Type{StepRangeLen{T,R,S}}, r::StepRangeLen{T,R,S}) = r -convert{T,R,S}(::Type{StepRangeLen{T,R,S}}, r::StepRangeLen) = +convert(::Type{StepRangeLen{T,R,S}}, r::StepRangeLen{T,R,S}) where {T,R,S} = r +convert(::Type{StepRangeLen{T,R,S}}, r::StepRangeLen) where {T,R,S} = StepRangeLen{T,R,S}(convert(R, r.ref), convert(S, r.step), length(r), r.offset) -convert{T}(::Type{StepRangeLen{T}}, r::StepRangeLen) = +convert(::Type{StepRangeLen{T}}, r::StepRangeLen) where {T} = StepRangeLen(convert(T, r.ref), convert(T, r.step), length(r), r.offset) promote_rule{T,R,S,OR<:Range}(::Type{StepRangeLen{T,R,S}}, ::Type{OR}) = StepRangeLen{promote_type(T,eltype(OR)),promote_type(R,eltype(OR)),promote_type(S,eltype(OR))} -convert{T,R,S}(::Type{StepRangeLen{T,R,S}}, r::Range) = +convert(::Type{StepRangeLen{T,R,S}}, r::Range) where {T,R,S} = StepRangeLen{T,R,S}(R(first(r)), S(step(r)), length(r)) -convert{T}(::Type{StepRangeLen{T}}, r::Range) = +convert(::Type{StepRangeLen{T}}, r::Range) where {T} = StepRangeLen(T(first(r)), T(step(r)), length(r)) convert(::Type{StepRangeLen}, r::Range) = convert(StepRangeLen{eltype(r)}, r) promote_rule{T1,T2}(::Type{LinSpace{T1}},::Type{LinSpace{T2}}) = LinSpace{promote_type(T1,T2)} -convert{T}(::Type{LinSpace{T}}, r::LinSpace{T}) = r -convert{T}(::Type{LinSpace{T}}, r::Range) = +convert(::Type{LinSpace{T}}, r::LinSpace{T}) where {T} = r +convert(::Type{LinSpace{T}}, r::Range) where {T} = LinSpace{T}(first(r), last(r), length(r)) -convert{T}(::Type{LinSpace}, r::Range{T}) = +convert(::Type{LinSpace}, r::Range{T}) where {T} = convert(LinSpace{T}, r) promote_rule{T,OR<:OrdinalRange}(::Type{LinSpace{T}}, ::Type{OR}) = @@ -819,7 +819,7 @@ function vcat{T}(rs::Range{T}...) return a end -convert{T}(::Type{Array{T,1}}, r::Range{T}) = vcat(r) +convert(::Type{Array{T,1}}, r::Range{T}) where {T} = vcat(r) collect(r::Range) = vcat(r) reverse(r::OrdinalRange) = colon(last(r), -step(r), first(r)) diff --git a/base/rational.jl b/base/rational.jl index 37bc056831334..1760a6ab343ef 100644 --- a/base/rational.jl +++ b/base/rational.jl @@ -10,7 +10,7 @@ struct Rational{T<:Integer} <: Real new(div(num, g), div(den, g)) end end -Rational(n::T, d::T) where T<:Integer = Rational{T}(n,d) +Rational(n::T, d::T) where {T<:Integer} = Rational{T}(n,d) Rational(n::Integer, d::Integer) = Rational(promote(n,d)...) Rational(n::Integer) = Rational(n,one(n)) @@ -69,23 +69,23 @@ function write(s::IO, z::Rational) write(s,numerator(z),denominator(z)) end -convert{T<:Integer}(::Type{Rational{T}}, x::Rational) = Rational{T}(convert(T,x.num),convert(T,x.den)) -convert{T<:Integer}(::Type{Rational{T}}, x::Integer) = Rational{T}(convert(T,x), convert(T,1)) +convert(::Type{Rational{T}}, x::Rational) where {T<:Integer} = Rational{T}(convert(T,x.num),convert(T,x.den)) +convert(::Type{Rational{T}}, x::Integer) where {T<:Integer} = Rational{T}(convert(T,x), convert(T,1)) convert(::Type{Rational}, x::Rational) = x convert(::Type{Rational}, x::Integer) = convert(Rational{typeof(x)},x) convert(::Type{Bool}, x::Rational) = x==0 ? false : x==1 ? true : throw(InexactError()) # to resolve ambiguity convert(::Type{Integer}, x::Rational) = (isinteger(x) ? convert(Integer, x.num) : throw(InexactError())) -convert{T<:Integer}(::Type{T}, x::Rational) = (isinteger(x) ? convert(T, x.num) : throw(InexactError())) +convert(::Type{T}, x::Rational) where {T<:Integer} = (isinteger(x) ? convert(T, x.num) : throw(InexactError())) convert(::Type{AbstractFloat}, x::Rational) = float(x.num)/float(x.den) -function convert{T<:AbstractFloat,S}(::Type{T}, x::Rational{S}) +function convert(::Type{T}, x::Rational{S}) where T<:AbstractFloat where S P = promote_type(T,S) convert(T, convert(P,x.num)/convert(P,x.den)) end -function convert{T<:Integer}(::Type{Rational{T}}, x::AbstractFloat) +function convert(::Type{Rational{T}}, x::AbstractFloat) where T<:Integer r = rationalize(T, x, tol=0) x == convert(typeof(x), r) || throw(InexactError()) r diff --git a/base/refpointer.jl b/base/refpointer.jl index 5fa34cd1919d8..8f41b46e90687 100644 --- a/base/refpointer.jl +++ b/base/refpointer.jl @@ -28,7 +28,7 @@ end ### General Methods for Ref{T} type eltype{T}(x::Type{Ref{T}}) = T -convert{T}(::Type{Ref{T}}, x::Ref{T}) = x +convert(::Type{Ref{T}}, x::Ref{T}) where {T} = x # create Ref objects for general object conversion unsafe_convert{T}(::Type{Ref{T}}, x::Ref{T}) = unsafe_convert(Ptr{T}, x) @@ -50,7 +50,7 @@ Ref{T}(x::Ptr{T}, i::Integer=1) = x + (i-1)*Core.sizeof(T) Ref(x, i::Integer) = (i != 1 && error("Object only has one element"); Ref(x)) (::Type{Ref{T}}){T}() = RefValue{T}() # Ref{T}() (::Type{Ref{T}}){T}(x) = RefValue{T}(x) # Ref{T}(x) -convert{T}(::Type{Ref{T}}, x) = RefValue{T}(x) +convert(::Type{Ref{T}}, x) where {T} = RefValue{T}(x) function unsafe_convert{T}(P::Type{Ptr{T}}, b::RefValue{T}) if isbits(T) @@ -73,7 +73,7 @@ struct RefArray{T, A<:AbstractArray{T}, R} <: Ref{T} end RefArray{T}(x::AbstractArray{T},i::Int,roots::Any) = RefArray{T,typeof(x),Any}(x, i, roots) RefArray{T}(x::AbstractArray{T},i::Int=1,roots::Void=nothing) = RefArray{T,typeof(x),Void}(x, i, nothing) -convert{T}(::Type{Ref{T}}, x::AbstractArray{T}) = RefArray(x, 1) +convert(::Type{Ref{T}}, x::AbstractArray{T}) where {T} = RefArray(x, 1) Ref(x::AbstractArray, i::Integer=1) = RefArray(x, i) function unsafe_convert{T}(P::Type{Ptr{T}}, b::RefArray{T}) diff --git a/base/set.jl b/base/set.jl index f6983758c2195..c97dd61a88d27 100644 --- a/base/set.jl +++ b/base/set.jl @@ -249,5 +249,5 @@ function hash(s::Set, h::UInt) return h end -convert{T}(::Type{Set{T}}, s::Set{T}) = s -convert{T}(::Type{Set{T}}, x::Set) = Set{T}(x) +convert(::Type{Set{T}}, s::Set{T}) where {T} = s +convert(::Type{Set{T}}, x::Set) where {T} = Set{T}(x) diff --git a/base/sharedarray.jl b/base/sharedarray.jl index ce4925dd28929..bde796f3004a0 100644 --- a/base/sharedarray.jl +++ b/base/sharedarray.jl @@ -321,11 +321,11 @@ function convert(::Type{SharedArray}, A::Array) S = SharedArray{eltype(A),ndims(A)}(size(A)) copy!(S, A) end -function convert{T}(::Type{SharedArray{T}}, A::Array) +function convert(::Type{SharedArray{T}}, A::Array) where T S = SharedArray{T,ndims(A)}(size(A)) copy!(S, A) end -function convert{TS,TA,N}(::Type{SharedArray{TS,N}}, A::Array{TA,N}) +function convert(::Type{SharedArray{TS,N}}, A::Array{TA,N}) where TS where TA where N S = SharedArray{TS,ndims(A)}(size(A)) copy!(S, A) end diff --git a/base/twiceprecision.jl b/base/twiceprecision.jl index ea92f6c44d2d1..1504aa1f2eb21 100644 --- a/base/twiceprecision.jl +++ b/base/twiceprecision.jl @@ -67,12 +67,12 @@ promote_rule{R,S}(::Type{TwicePrecision{R}}, ::Type{TwicePrecision{S}}) = promote_rule{R,S}(::Type{TwicePrecision{R}}, ::Type{S}) = TwicePrecision{promote_type(R,S)} -convert{T}(::Type{TwicePrecision{T}}, x::TwicePrecision{T}) = x -convert{T}(::Type{TwicePrecision{T}}, x::TwicePrecision) = +convert(::Type{TwicePrecision{T}}, x::TwicePrecision{T}) where {T} = x +convert(::Type{TwicePrecision{T}}, x::TwicePrecision) where {T} = TwicePrecision{T}(convert(T, x.hi), convert(T, x.lo)) -convert{T<:Number}(::Type{T}, x::TwicePrecision{T}) = convert(T, x.hi + x.lo) -convert{T}(::Type{TwicePrecision{T}}, x::Number) = TwicePrecision{T}(convert(T, x), zero(T)) +convert(::Type{T}, x::TwicePrecision{T}) where {T<:Number} = convert(T, x.hi + x.lo) +convert(::Type{TwicePrecision{T}}, x::Number) where {T} = TwicePrecision{T}(convert(T, x), zero(T)) float(x::TwicePrecision{<:AbstractFloat}) = x float(x::TwicePrecision) = TwicePrecision(float(x.hi), float(x.lo)) @@ -229,9 +229,9 @@ end /(r::StepRangeLen{<:Real,<:TwicePrecision}, x::Real) = StepRangeLen(r.ref/x, twiceprecision(r.step/x, nbitslen(r)), length(r), r.offset) -convert{T<:AbstractFloat,R<:TwicePrecision,S<:TwicePrecision}(::Type{StepRangeLen{T,R,S}}, r::StepRangeLen{T,R,S}) = r +convert(::Type{StepRangeLen{T,R,S}}, r::StepRangeLen{T,R,S}) where {T<:AbstractFloat,R<:TwicePrecision,S<:TwicePrecision} = r -convert{T<:AbstractFloat,R<:TwicePrecision,S<:TwicePrecision}(::Type{StepRangeLen{T,R,S}}, r::StepRangeLen) = +convert(::Type{StepRangeLen{T,R,S}}, r::StepRangeLen) where {T<:AbstractFloat,R<:TwicePrecision,S<:TwicePrecision} = _convertSRL(StepRangeLen{T,R,S}, r) convert{T<:Union{Float16,Float32,Float64}}(::Type{StepRangeLen{T}}, r::StepRangeLen) = diff --git a/base/weakkeydict.jl b/base/weakkeydict.jl index 1eb2822e70d8a..bffa5737f115f 100644 --- a/base/weakkeydict.jl +++ b/base/weakkeydict.jl @@ -69,7 +69,7 @@ similar{K,V}(d::WeakKeyDict{K,V}) = WeakKeyDict{K,V}() similar{K,V}(d::WeakKeyDict, ::Type{Pair{K,V}}) = WeakKeyDict{K,V}() # conversion between Dict types -function convert{K,V}(::Type{WeakKeyDict{K,V}},d::Associative) +function convert(::Type{WeakKeyDict{K,V}},d::Associative) where V where K h = WeakKeyDict{K,V}() for (k,v) in d ck = convert(K,k) @@ -81,7 +81,7 @@ function convert{K,V}(::Type{WeakKeyDict{K,V}},d::Associative) end return h end -convert{K,V}(::Type{WeakKeyDict{K,V}},d::WeakKeyDict{K,V}) = d +convert(::Type{WeakKeyDict{K,V}},d::WeakKeyDict{K,V}) where {K,V} = d islocked(wkh::WeakKeyDict) = islocked(wkh.lock) lock(f, wkh::WeakKeyDict) = lock(f, wkh.lock) From 832623fd1a345f93f80b72e2c82c2a79093926fe Mon Sep 17 00:00:00 2001 From: Mus M Date: Sun, 16 Apr 2017 21:32:13 -0400 Subject: [PATCH 0450/1534] Use where syntax for unsafe_convert --- base/atomics.jl | 2 +- base/boot.jl | 2 +- base/essentials.jl | 6 +++--- base/pointer.jl | 6 +++--- base/refpointer.jl | 8 ++++---- base/reshapedarray.jl | 2 +- base/sharedarray.jl | 4 ++-- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/base/atomics.jl b/base/atomics.jl index 743bb0501e3d3..09bd9788637cd 100644 --- a/base/atomics.jl +++ b/base/atomics.jl @@ -302,7 +302,7 @@ julia> x[] """ function atomic_min! end -unsafe_convert{T}(::Type{Ptr{T}}, x::Atomic{T}) = convert(Ptr{T}, pointer_from_objref(x)) +unsafe_convert(::Type{Ptr{T}}, x::Atomic{T}) where {T} = convert(Ptr{T}, pointer_from_objref(x)) setindex!{T}(x::Atomic{T}, v) = setindex!(x, convert(T, v)) const llvmtypes = Dict( diff --git a/base/boot.jl b/base/boot.jl index 7c9284c91dc73..1e01b32f45aa2 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -296,7 +296,7 @@ Task(f::ANY) = ccall(:jl_new_task, Ref{Task}, (Any, Int), f, 0) convert(::Type{Any}, x::ANY) = x convert(::Type{T}, x::T) where {T} = x cconvert{T}(::Type{T}, x) = convert(T, x) -unsafe_convert{T}(::Type{T}, x::T) = x +unsafe_convert(::Type{T}, x::T) where {T} = x NTuple{N,T} = Tuple{Vararg{T,N}} diff --git a/base/essentials.jl b/base/essentials.jl index e2349e0901234..f2f5da38907c4 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -149,9 +149,9 @@ ptr_arg_unsafe_convert(::Type{Ptr{Void}}, x) = x cconvert(T::Type, x) = convert(T, x) # do the conversion eagerly in most cases cconvert(::Type{<:Ptr}, x) = x # but defer the conversion to Ptr to unsafe_convert -unsafe_convert{T}(::Type{T}, x::T) = x # unsafe_convert (like convert) defaults to assuming the convert occurred -unsafe_convert{T<:Ptr}(::Type{T}, x::T) = x # to resolve ambiguity with the next method -unsafe_convert{P<:Ptr}(::Type{P}, x::Ptr) = convert(P, x) +unsafe_convert(::Type{T}, x::T) where {T} = x # unsafe_convert (like convert) defaults to assuming the convert occurred +unsafe_convert(::Type{T}, x::T) where {T<:Ptr} = x # to resolve ambiguity with the next method +unsafe_convert(::Type{P}, x::Ptr) where {P<:Ptr} = convert(P, x) reinterpret{T}(::Type{T}, x) = bitcast(T, x) reinterpret(::Type{Unsigned}, x::Float16) = reinterpret(UInt16,x) diff --git a/base/pointer.jl b/base/pointer.jl index c193c3e865384..5819a2fa6429f 100644 --- a/base/pointer.jl +++ b/base/pointer.jl @@ -40,9 +40,9 @@ unsafe_convert(::Type{Ptr{Int8}}, s::String) = convert(Ptr{Int8}, pointer_from_o cconvert(::Type{Ptr{UInt8}}, s::AbstractString) = String(s) cconvert(::Type{Ptr{Int8}}, s::AbstractString) = String(s) -unsafe_convert{T}(::Type{Ptr{T}}, a::Array{T}) = ccall(:jl_array_ptr, Ptr{T}, (Any,), a) -unsafe_convert{S,T}(::Type{Ptr{S}}, a::AbstractArray{T}) = convert(Ptr{S}, unsafe_convert(Ptr{T}, a)) -unsafe_convert{T}(::Type{Ptr{T}}, a::AbstractArray{T}) = error("conversion to pointer not defined for $(typeof(a))") +unsafe_convert(::Type{Ptr{T}}, a::Array{T}) where {T} = ccall(:jl_array_ptr, Ptr{T}, (Any,), a) +unsafe_convert(::Type{Ptr{S}}, a::AbstractArray{T}) where {S,T} = convert(Ptr{S}, unsafe_convert(Ptr{T}, a)) +unsafe_convert(::Type{Ptr{T}}, a::AbstractArray{T}) where {T} = error("conversion to pointer not defined for $(typeof(a))") # unsafe pointer to array conversions """ diff --git a/base/refpointer.jl b/base/refpointer.jl index 8f41b46e90687..8671f215c595e 100644 --- a/base/refpointer.jl +++ b/base/refpointer.jl @@ -31,8 +31,8 @@ eltype{T}(x::Type{Ref{T}}) = T convert(::Type{Ref{T}}, x::Ref{T}) where {T} = x # create Ref objects for general object conversion -unsafe_convert{T}(::Type{Ref{T}}, x::Ref{T}) = unsafe_convert(Ptr{T}, x) -unsafe_convert{T}(::Type{Ref{T}}, x) = unsafe_convert(Ptr{T}, x) +unsafe_convert(::Type{Ref{T}}, x::Ref{T}) where {T} = unsafe_convert(Ptr{T}, x) +unsafe_convert(::Type{Ref{T}}, x) where {T} = unsafe_convert(Ptr{T}, x) ### Methods for a Ref object that can store a single value of any type @@ -62,7 +62,7 @@ end function unsafe_convert(P::Type{Ptr{Any}}, b::RefValue{Any}) return convert(P, data_pointer_from_objref(b)) end -unsafe_convert{T}(::Type{Ptr{Void}}, b::RefValue{T}) = convert(Ptr{Void}, unsafe_convert(Ptr{T}, b)) +unsafe_convert(::Type{Ptr{Void}}, b::RefValue{T}) where {T} = convert(Ptr{Void}, unsafe_convert(Ptr{T}, b)) ### Methods for a Ref object that is backed by an array at index i struct RefArray{T, A<:AbstractArray{T}, R} <: Ref{T} @@ -86,7 +86,7 @@ end function unsafe_convert(P::Type{Ptr{Any}}, b::RefArray{Any}) return convert(P, pointer(b.x, b.i)) end -unsafe_convert{T}(::Type{Ptr{Void}}, b::RefArray{T}) = convert(Ptr{Void}, unsafe_convert(Ptr{T}, b)) +unsafe_convert(::Type{Ptr{Void}}, b::RefArray{T}) where {T} = convert(Ptr{Void}, unsafe_convert(Ptr{T}, b)) # convert Arrays to pointer arrays for ccall function (::Type{Ref{<:Union{Ptr,Cwstring,Cstring}}})(a::Array{<:Union{Ptr,Cwstring,Cstring}}) # Ref{P<:Ptr}(a::Array{T<:Ptr}) diff --git a/base/reshapedarray.jl b/base/reshapedarray.jl index 587c568b09f4a..6681681471d07 100644 --- a/base/reshapedarray.jl +++ b/base/reshapedarray.jl @@ -234,4 +234,4 @@ setindex!(A::ReshapedRange, val, index::ReshapedIndex) = _rs_setindex!_err() _rs_setindex!_err() = error("indexed assignment fails for a reshaped range; consider calling collect") -unsafe_convert{T}(::Type{Ptr{T}}, a::ReshapedArray{T}) = unsafe_convert(Ptr{T}, parent(a)) +unsafe_convert(::Type{Ptr{T}}, a::ReshapedArray{T}) where {T} = unsafe_convert(Ptr{T}, parent(a)) diff --git a/base/sharedarray.jl b/base/sharedarray.jl index bde796f3004a0..ef3d973fc8766 100644 --- a/base/sharedarray.jl +++ b/base/sharedarray.jl @@ -314,8 +314,8 @@ for each worker process. """ localindexes(S::SharedArray) = S.pidx > 0 ? range_1dim(S, S.pidx) : 1:0 -unsafe_convert{T}(::Type{Ptr{T}}, S::SharedArray{T}) = unsafe_convert(Ptr{T}, sdata(S)) -unsafe_convert{T}(::Type{Ptr{T}}, S::SharedArray ) = unsafe_convert(Ptr{T}, sdata(S)) +unsafe_convert(::Type{Ptr{T}}, S::SharedArray{T}) where {T} = unsafe_convert(Ptr{T}, sdata(S)) +unsafe_convert(::Type{Ptr{T}}, S::SharedArray ) where {T} = unsafe_convert(Ptr{T}, sdata(S)) function convert(::Type{SharedArray}, A::Array) S = SharedArray{eltype(A),ndims(A)}(size(A)) From bdc1243fbeffd83df7f17cf86165cd5f2d8741bf Mon Sep 17 00:00:00 2001 From: Martin Holters Date: Wed, 12 Apr 2017 14:25:34 +0200 Subject: [PATCH 0451/1534] Increase union stack size This solves #21191 and similar issues, but there probably is an underlying problem yet to be solved which makes such a large stack necessary in the first place. --- src/subtype.c | 4 +++- test/inference.jl | 3 +-- test/subtype.jl | 18 ++++++++++++++++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/subtype.c b/src/subtype.c index bd8cf449f950c..7abc59859d897 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -39,10 +39,12 @@ extern "C" { // Union type decision points are discovered while the algorithm works. // If a new Union decision is encountered, the `more` flag is set to tell // the forall/exists loop to grow the stack. +// TODO: the stack probably needs to be artifically large because of some +// deeper problem (see #21191) and could be shrunk once that is fixed typedef struct { int depth; int more; - uint32_t stack[10]; // stack of bits represented as a bit vector + uint32_t stack[100]; // stack of bits represented as a bit vector } jl_unionstate_t; // Linked list storing the type variable environment. A new jl_varbinding_t diff --git a/test/inference.jl b/test/inference.jl index 062437d0a01f2..c1cbcd7172ee5 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -657,8 +657,7 @@ let A = 1:2, z = zip(A, A, A, A, A, A, A, A, A, A, A, A) end # introduce TypeVars in Unions in invariant position let T = Val{Val{Val{Union{Int8,Int16,Int32,Int64,UInt8,UInt16,UInt32,UInt64}}}} - #TODO: this test hits an assertion (see #21191) - #@test T <: Core.Inference.limit_type_depth(T, 0) + @test T <: Core.Inference.limit_type_depth(T, 0) end # issue #20704 diff --git a/test/subtype.jl b/test/subtype.jl index 4a271ee054c4d..1531837946e81 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -1076,3 +1076,21 @@ struct TT20103{X,Y} end f20103{X,Y}(::Type{TT20103{X,Y}},x::X,y::Y) = 1 f20103{X}(::Type{TT20103{X,X}},x::X) = 100 @test_broken typeintersect(Type{NTuple{N,E}} where E where N, Type{NTuple{N,E} where N} where E) == Union{} # use @testintersect once fixed +let ints = (Int, Int32, UInt, UInt32) + const Ints = Union{ints...} + vecs = [] + for i = 2:4, t in ints + push!(vecs, NTuple{i, t}) + end + const Vecs = Union{vecs...} + T = Type{Tuple{V, I}} where V <: Vecs where I <: Ints + @testintersect(T, T, T) + test{V <: Vecs, I <: Ints}(a::Type{Tuple{V, I}}) = I + test{V <: Vecs, I <: Ints}(a::Type{Tuple{V, I}}) = I +end + +# issue #21191 +let T1 = Val{Val{Val{Union{Int8,Int16,Int32,Int64,UInt8,UInt16}}}}, + T2 = Val{Val{Val{Union{Int8,Int16,Int32,Int64,UInt8, S}}}} where S + @test T1 <: T2 +end From 27d8787c7dfa385121c2d0820025087b7559b4c4 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 17 Apr 2017 13:41:41 -0400 Subject: [PATCH 0452/1534] fix #21410, need to handle static param values with free typevars --- base/inference.jl | 9 ++++++--- src/jltypes.c | 36 ++++++++++++++++++++++++++++++++++++ test/inference.jl | 4 ++++ 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index f96aabc7034a1..b80497edfc12d 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -1969,12 +1969,15 @@ function abstract_eval(e::ANY, vtypes::VarTable, sv::InferenceState) t = Any if n <= length(sv.sp) val = sv.sp[n] - if isa(val, TypeVar) + if isa(val, TypeVar) && Any <: val.ub # static param bound to typevar # if the tvar does not refer to anything more specific than Any, # the static param might actually be an integer, symbol, etc. - if !(Any <: val.ub) - t = UnionAll(val, Type{val}) + elseif has_free_typevars(val) + vs = ccall(:jl_find_free_typevars, Any, (Any,), val) + t = Type{val} + for v in vs + t = UnionAll(v, t) end else t = abstract_eval_constant(val) diff --git a/src/jltypes.c b/src/jltypes.c index c5526a59abe17..534d9cb5a70c9 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -178,6 +178,42 @@ JL_DLLEXPORT int jl_has_free_typevars(jl_value_t *v) return has_free_typevars(v, NULL); } +static void find_free_typevars(jl_value_t *v, jl_typeenv_t *env, jl_array_t *out) +{ + if (jl_typeis(v, jl_tvar_type)) { + if (v == jl_ANY_flag) return; + if (!typeenv_has(env, (jl_tvar_t*)v)) + jl_array_ptr_1d_push(out, v); + } + else if (jl_is_uniontype(v)) { + find_free_typevars(((jl_uniontype_t*)v)->a, env, out); + find_free_typevars(((jl_uniontype_t*)v)->b, env, out); + } + else if (jl_is_unionall(v)) { + jl_unionall_t *ua = (jl_unionall_t*)v; + jl_typeenv_t newenv = { ua->var, NULL, env }; + find_free_typevars(ua->var->lb, env, out); + find_free_typevars(ua->var->ub, env, out); + find_free_typevars(ua->body, &newenv, out); + } + else if (jl_is_datatype(v)) { + if (!((jl_datatype_t*)v)->hasfreetypevars) + return; + size_t i; + for (i=0; i < jl_nparams(v); i++) + find_free_typevars(jl_tparam(v,i), env, out); + } +} + +JL_DLLEXPORT jl_array_t *jl_find_free_typevars(jl_value_t *v) +{ + jl_array_t *out = jl_alloc_vec_any(0); + JL_GC_PUSH1(&out); + find_free_typevars(v, NULL, out); + JL_GC_POP(); + return out; +} + // test whether a type has vars bound by the given environment static int jl_has_bound_typevars(jl_value_t *v, jl_typeenv_t *env) { diff --git a/test/inference.jl b/test/inference.jl index 062437d0a01f2..29f29f70daa4f 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -745,3 +745,7 @@ type T10207{A, B} b::B end @test code_typed(T10207, (Int,Any))[1].second == T10207{Int,T} where T + +# issue #21410 +f21410(::V, ::Pair{V,E}) where {V, E} = E +@test code_typed(f21410, Tuple{Ref, Pair{Ref{T},Ref{T}} where T<:Number})[1].second == Type{Ref{T}} where T<:Number From 69f4655619ea41c29d6af958d74503ca641f20b8 Mon Sep 17 00:00:00 2001 From: Mus M Date: Mon, 17 Apr 2017 14:54:28 -0400 Subject: [PATCH 0453/1534] Update signature of cpu_summary --- base/sysinfo.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/sysinfo.jl b/base/sysinfo.jl index 97f8a75950a29..9e2655ec96818 100644 --- a/base/sysinfo.jl +++ b/base/sysinfo.jl @@ -117,7 +117,7 @@ function _cpu_summary(io::IO, cpu::Array{CPUinfo}, i, j) println(io) end -function cpu_summary(io::IO=STDOUT, cpu::Array{CPUinfo}=cpu_info()) +function cpu_summary(io::IO=STDOUT, cpu::AbstractVector{CPUinfo} = cpu_info()) model = cpu[1].model first = 1 for i = 2:length(cpu) From b3f81557e49df1338283ddcf83828f9885e9e541 Mon Sep 17 00:00:00 2001 From: Mus M Date: Mon, 17 Apr 2017 15:03:38 -0400 Subject: [PATCH 0454/1534] Use Refs and Vector in cholmod.jl and random.jl --- base/random.jl | 4 ++-- base/sparse/cholmod.jl | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/base/random.jl b/base/random.jl index d055cca322c56..58588042b8d13 100644 --- a/base/random.jl +++ b/base/random.jl @@ -33,7 +33,7 @@ if is_windows() struct RandomDevice <: AbstractRNG buffer::Vector{UInt128} - RandomDevice() = new(Array{UInt128}(1)) + RandomDevice() = new(Vector{UInt128}(1)) end function rand{T<:Union{Bool, Base.BitInteger}}(rd::RandomDevice, ::Type{T}) @@ -214,7 +214,7 @@ function make_seed(n::Integer) end function make_seed(filename::AbstractString, n::Integer) - read!(filename, Array{UInt32}(Int(n))) + read!(filename, Vector{UInt32}(Int(n))) end ## srand() diff --git a/base/sparse/cholmod.jl b/base/sparse/cholmod.jl index 578b4129a09d3..e1bbe0340ab85 100644 --- a/base/sparse/cholmod.jl +++ b/base/sparse/cholmod.jl @@ -246,7 +246,7 @@ mutable struct Sparse{Tv<:VTypes} <: AbstractSparseMatrix{Tv,SuiteSparse_long} new(p) end end -Sparse(p::Ptr{C_Sparse{Tv}}) where Tv<:VTypes = Sparse{Tv}(p) +Sparse(p::Ptr{C_Sparse{Tv}}) where {Tv<:VTypes} = Sparse{Tv}(p) # Factor @@ -325,7 +325,7 @@ mutable struct Factor{Tv} <: Factorization{Tv} new(p) end end -Factor(p::Ptr{C_Factor{Tv}}) where Tv<:VTypes = Factor{Tv}(p) +Factor(p::Ptr{C_Factor{Tv}}) where {Tv<:VTypes} = Factor{Tv}(p) # Define get similar to get(Nullable) to check pointers. All pointer loads # should be wrapped in get to make sure that SuiteSparse is not called with @@ -734,16 +734,16 @@ function vertcat{Tv<:VRealTypes}(A::Sparse{Tv}, B::Sparse{Tv}, values::Bool) end function symmetry{Tv<:VTypes}(A::Sparse{Tv}, option::Integer) - xmatched = Array{SuiteSparse_long}(1) - pmatched = Array{SuiteSparse_long}(1) - nzoffdiag = Array{SuiteSparse_long}(1) - nzdiag = Array{SuiteSparse_long}(1) + xmatched = Ref{SuiteSparse_long}() + pmatched = Ref{SuiteSparse_long}() + nzoffdiag = Ref{SuiteSparse_long}() + nzdiag = Ref{SuiteSparse_long}() rv = ccall((@cholmod_name("symmetry", SuiteSparse_long), :libcholmod), Cint, (Ptr{C_Sparse{Tv}}, Cint, Ptr{SuiteSparse_long}, Ptr{SuiteSparse_long}, Ptr{SuiteSparse_long}, Ptr{SuiteSparse_long}, Ptr{UInt8}), get(A.p), option, xmatched, pmatched, nzoffdiag, nzdiag, common()) - rv, xmatched[1], pmatched[1], nzoffdiag[1], nzdiag[1] + rv, xmatched[], pmatched[], nzoffdiag[], nzdiag[] end # cholmod_cholesky.h From 6baa6c80d27c926483a2069af556e08c73e4ced9 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 20 Mar 2017 18:35:02 +0100 Subject: [PATCH 0455/1534] refactor gc to only need to allocate virtual addresses on demand rather than using multiple enormous flat regions, this divides all memory into a 2-3 level page map --- src/gc-debug.c | 408 +++++++++++++++++++++++++++++++++---------------- src/gc-pages.c | 327 +++++++++++++++++++++++++-------------- src/gc.c | 136 ++++++++++++----- src/gc.h | 165 ++++++++++++++------ 4 files changed, 695 insertions(+), 341 deletions(-) diff --git a/src/gc-debug.c b/src/gc-debug.c index d1502b6459542..ef90d9384bd12 100644 --- a/src/gc-debug.c +++ b/src/gc-debug.c @@ -14,17 +14,12 @@ extern "C" { #endif -// Useful function in debugger to find page/region metadata +// Useful function in debugger to find page metadata jl_gc_pagemeta_t *jl_gc_page_metadata(void *data) { return page_metadata(data); } -region_t *jl_gc_find_region(void *ptr) -{ - return find_region(ptr); -} - // Find the memory block in the pool that owns the byte pointed to by p. // For end of object pointer (which is always the case for pointer to a // singleton object), this usually returns the same pointer which points to @@ -32,21 +27,19 @@ region_t *jl_gc_find_region(void *ptr) // the end of the page. JL_DLLEXPORT jl_taggedvalue_t *jl_gc_find_taggedvalue_pool(char *p, size_t *osize_p) { - region_t *r = find_region(p); - // Not in the pool - if (!r) + if (!page_metadata(p)) + // Not in the pool return NULL; + struct jl_gc_metadata_ext info = page_metadata_ext(p); char *page_begin = gc_page_data(p) + GC_PAGE_OFFSET; // In the page header if (p < page_begin) return NULL; size_t ofs = p - page_begin; - int pg_idx = page_index(r, page_begin); // Check if this is a free page - if (!(r->allocmap[pg_idx / 32] & (uint32_t)(1 << (pg_idx % 32)))) + if (!(info.pagetable0->allocmap[info.pagetable0_i32 / 32] & (uint32_t)(1 << info.pagetable0_i))) return NULL; - jl_gc_pagemeta_t *pagemeta = &r->meta[pg_idx]; - int osize = pagemeta->osize; + int osize = info.meta->osize; // Shouldn't be needed, just in case if (osize == 0) return NULL; @@ -104,6 +97,61 @@ void add_lostval_parent(jl_value_t *parent) // the error is caught at the first long collection static arraylist_t bits_save[4]; +static void gc_clear_mark_page(jl_gc_pagemeta_t *pg) +{ + jl_ptls_t ptls2 = jl_all_tls_states[pg->thread_n]; + jl_gc_pool_t *pool = &ptls2->heap.norm_pools[pg->pool_n]; + pv = (jl_taggedvalue_t*)(pg->data + GC_PAGE_OFFSET); + char *lim = (char*)pv + GC_PAGE_SZ - GC_PAGE_OFFSET - pool->osize; + while ((char*)pv <= lim) { + if (!gc_verifying) + arraylist_push(&bits_save[pv->bits.gc], pv); + pv->bits.gc = bits; + pv = (jl_taggedvalue_t*)((char*)pv + pool->osize); + } +} + +static void gc_clear_mark_pagetable0(pagetable0_t *pagetable0) +{ + for (int pg_i = 0; pg_i < REGION0_PG_COUNT / 32; pg_i++) { + uint32_t line = pagetable0->allocmap[pg_i]; + if (line) { + for (int j = 0; j < 32; j++) { + if ((line >> j) & 1) { + gc_clear_mark_page(pagetable0->meta[pg_i * 32 + j]); + } + } + } + } +} + +static void gc_clear_mark_pagetable1(pagetable1_t *pagetable1) +{ + for (int pg_i = 0; pg_i < REGION1_PG_COUNT / 32; pg_i++) { + uint32_t line = pagetable1->allocmap0[pg_i]; + if (line) { + for (int j = 0; j < 32; j++) { + if ((line >> j) & 1) { + gc_clear_mark_pagetable0(pagetable1->meta0[pg_i * 32 + j]); + } + } + } + } +} + +static void gc_clear_mark_pagetable(void) +{ + for (int pg_i = 0; pg_i < (REGION2_PG_COUNT + 31) / 32; pg_i++) { + uint32_t line = memory_map.allocmap1[pg_i]; + if (line) { + for (int j = 0; j < 32; j++) { + if ((line >> j) & 1) { + gc_clear_mark_pagetable1(memory_map.meta1[pg_i * 32 + j]); + } + } + } + } +} // set all mark bits to bits // record the state of the region and can replay it in restore() // restore _must_ be called as this will overwrite parts of the @@ -120,7 +168,8 @@ static void clear_mark(int bits) v = jl_all_tls_states[i]->heap.big_objects; while (v != NULL) { void *gcv = &v->header; - if (!gc_verifying) arraylist_push(&bits_save[v->bits.gc], gcv); + if (!gc_verifying) + arraylist_push(&bits_save[v->bits.gc], gcv); v->bits.gc = bits; v = v->next; } @@ -129,42 +178,19 @@ static void clear_mark(int bits) v = big_objects_marked; while (v != NULL) { void *gcv = &v->header; - if (!gc_verifying) arraylist_push(&bits_save[v->bits.gc], gcv); + if (!gc_verifying) + arraylist_push(&bits_save[v->bits.gc], gcv); v->bits.gc = bits; v = v->next; } - jl_taggedvalue_t *pv; - for (int h = 0; h < REGION_COUNT; h++) { - region_t *region = ®ions[h]; - if (!region->pages) - break; - for (int pg_i = 0; pg_i < region->pg_cnt / 32; pg_i++) { - uint32_t line = region->allocmap[pg_i]; - if (line) { - for (int j = 0; j < 32; j++) { - if ((line >> j) & 1) { - jl_gc_pagemeta_t *pg = page_metadata(region->pages[pg_i*32 + j].data + GC_PAGE_OFFSET); - jl_ptls_t ptls2 = jl_all_tls_states[pg->thread_n]; - jl_gc_pool_t *pool = &ptls2->heap.norm_pools[pg->pool_n]; - pv = (jl_taggedvalue_t*)(pg->data + GC_PAGE_OFFSET); - char *lim = (char*)pv + GC_PAGE_SZ - GC_PAGE_OFFSET - pool->osize; - while ((char*)pv <= lim) { - if (!gc_verifying) arraylist_push(&bits_save[pv->bits.gc], pv); - pv->bits.gc = bits; - pv = (jl_taggedvalue_t*)((char*)pv + pool->osize); - } - } - } - } - } - } + gc_clear_mark_pagetable(); } static void restore(void) { - for(int b = 0; b < 4; b++) { - for(int i = 0; i < bits_save[b].len; i++) { + for (int b = 0; b < 4; b++) { + for (int i = 0; i < bits_save[b].len; i++) { ((jl_taggedvalue_t*)bits_save[b].items[i])->bits.gc = b; } } @@ -259,6 +285,115 @@ void gc_verify(jl_ptls_t ptls) #ifdef MEMFENCE static uint8_t freelist_map[GC_PAGE_SZ / sizeof(void*) / 8]; static int freelist_zerod; + +static void gc_verify_tags_page(jl_gc_pagemeta_t *pg) +{ + // for all pages in use + int p_n = pg->pool_n; + int t_n = pg->thread_n; + jl_ptls_t ptls2 = jl_all_tls_states[t_n]; + jl_gc_pool_t *p = &ptls2->heap.norm_pools[p_n]; + int osize = pg->osize; + char *data = pg->data; + char *page_begin = data + GC_PAGE_OFFSET; + jl_taggedvalue_t *v = (jl_taggedvalue_t*)page_begin; + char *lim = data + GC_PAGE_SZ - osize; + // reset the freelist map to zero + if (!freelist_zerod) { + memset(freelist_map, 0, sizeof(freelist_map)); + freelist_zerod = 1; + } + // check for p in new newpages list + jl_taggedvalue_t *halfpages = p->newpages; + while (halfpages) { + char *cur_page = gc_page_data((char*)halfpages - 1); + if (cur_page == data) { + lim = (char*)halfpages - 1; + break; + } + halfpages = *(jl_taggedvalue_t**)cur_page; + } + // compute the freelist_map + if (pg->nfree) { + jl_taggedvalue_t *next = NULL; + if (gc_page_data(p->freelist) == data) { + // currently allocating on this page + next = p->freelist; + assert(page_metadata(next)->osize == osize); + freelist_zerod = 0; + } + else if (pg->fl_begin_offset != (uint16_t)-1) { + // part of free list exists on this page + next = page_pfl_beg(pg); + freelist_zerod = 0; + } + assert(halfpages || next); + while (gc_page_data(next) == data) { + int obj_idx = (((char*)next) - page_begin) / sizeof(void*); + freelist_map[obj_idx / 8] |= 1 << (obj_idx % 7); + next = next->next; + } + } + // validate all of the tags on the page + while ((char*)v <= lim) { + int obj_idx = (((char*)v) - page_begin) / sizeof(void*); + int in_freelist = freelist_map[obj_idx / 8] & (1 << (obj_idx % 7)); + if (!in_freelist) { + jl_value_t *dt = jl_typeof(jl_valueof(v)); + if (dt != (jl_value_t*)jl_buff_tag && + // the following are used by the deserializer to invalidate objects + v->header != 0x10 && v->header != 0x20 && + v->header != 0x30 && v->header != 0x40 && + v->header != 0x50) { + assert(jl_typeof(dt) == (jl_value_t*)jl_datatype_type); + } + } + v = (jl_taggedvalue_t*)((char*)v + osize); + } +} + +static void gc_verify_tags_pagetable0(pagetable0_t *pagetable0) +{ + for (int pg_i = 0; pg_i < REGION0_PG_COUNT / 32; pg_i++) { + uint32_t line = pagetable0->allocmap[pg_i]; + if (line) { + for (int j = 0; j < 32; j++) { + if ((line >> j) & 1) { + gc_verify_tags_page(pagetable0->meta[pg_i * 32 + j]); + } + } + } + } +} + +static void gc_verify_tags_pagetable1(pagetable1_t *pagetable1) +{ + for (int pg_i = 0; pg_i < REGION1_PG_COUNT / 32; pg_i++) { + uint32_t line = pagetable1->allocmap0[pg_i]; + if (line) { + for (int j = 0; j < 32; j++) { + if ((line >> j) & 1) { + gc_verify_tags_pagetable0(pagetable1->meta0[pg_i * 32 + j]); + } + } + } + } +} + +static void gc_verify_tags_pagetable(void) +{ + for (int pg_i = 0; pg_i < (REGION2_PG_COUNT + 31) / 32; pg_i++) { + uint32_t line = memory_map.allocmap1[pg_i]; + if (line) { + for (int j = 0; j < 32; j++) { + if ((line >> j) & 1) { + gc_verify_tags_pagetable1(memory_map.meta1[pg_i * 32 + j]); + } + } + } + } +} + void gc_verify_tags(void) { // verify the freelist chains look valid @@ -289,83 +424,9 @@ void gc_verify_tags(void) } } - // verify that all the objects on every page are either valid julia objects // or are part of the freelist or are on the allocated half of a page - for (int region_i = 0; region_i < REGION_COUNT; region_i++) { - if (!regions[region_i].pages) - break; - region_t *region = ®ions[region_i]; - for (int pg_i = 0; pg_i <= region->ub; pg_i++) { - uint32_t line = region->allocmap[pg_i]; - if (line) { - for (int j = 0; j < 32; j++) { - if ((line >> j) & 1) { - // for all pages in use - jl_gc_pagemeta_t *pg = ®ion->meta[pg_i*32 + j]; - int p_n = pg->pool_n; - int t_n = pg->thread_n; - jl_ptls_t ptls2 = jl_all_tls_states[t_n]; - jl_gc_pool_t *p = &ptls2->heap.norm_pools[p_n]; - int osize = pg->osize; - char *data = pg->data; - char *page_begin = data + GC_PAGE_OFFSET; - jl_taggedvalue_t *v = (jl_taggedvalue_t*)page_begin; - char *lim = data + GC_PAGE_SZ - osize; - // reset the freelist map to zero - if (!freelist_zerod) { - memset(freelist_map, 0, sizeof(freelist_map)); - freelist_zerod = 1; - } - // check for p in new newpages list - jl_taggedvalue_t *halfpages = p->newpages; - while (halfpages) { - char *cur_page = gc_page_data((char*)halfpages - 1); - if (cur_page == data) { - lim = (char*)halfpages - 1; - break; - } - halfpages = *(jl_taggedvalue_t**)cur_page; - } - // compute the freelist_map - if (pg->nfree) { - jl_taggedvalue_t *next = NULL; - if (gc_page_data(p->freelist) == data) { - // currently allocating on this page - next = p->freelist; - assert(page_metadata(next)->osize == osize); - freelist_zerod = 0; - } - else if (pg->fl_begin_offset != (uint16_t)-1) { - // part of free list exists on this page - next = page_pfl_beg(pg); - freelist_zerod = 0; - } - assert(halfpages || next); - while (gc_page_data(next) == data) { - int obj_idx = (((char*)next) - page_begin) / sizeof(void*); - freelist_map[obj_idx / 8] |= 1 << (obj_idx % 7); - next = next->next; - } - } - // validate all of the tags on the page - while ((char*)v <= lim) { - int obj_idx = (((char*)v) - page_begin) / sizeof(void*); - int in_freelist = freelist_map[obj_idx / 8] & (1 << (obj_idx % 7)); - if (!in_freelist) { - jl_value_t *dt = jl_typeof(jl_valueof(v)); - // 0x10 (type) and 0x20 (singleton) are used by the incremental serializer to invalidate objects - if (dt != (jl_value_t*)jl_buff_tag && v->header != 0x10 && v->header != 0x20) { - assert(jl_typeof(dt) == (jl_value_t*)jl_datatype_type); - } - } - v = (jl_taggedvalue_t*)((char*)v + osize); - } - } - } - } - } - } + gc_verify_tags_pagetable(); } #endif @@ -666,7 +727,9 @@ void gc_settime_postmark_end(void) #endif #ifdef GC_FINAL_STATS -#include +#ifdef _OS_LINUX_ +#include // for mallinfo +#endif static double process_t0; static size_t max_pg_count = 0; static size_t total_freed_bytes = 0; @@ -694,10 +757,55 @@ void gc_final_pause_end(int64_t t0, int64_t tend) total_mark_time += gc_premark_end - t0; } +static void gc_stats_pagetable0(pagetable0_t *pagetable0, unsigned *p0) +{ + for (int pg_i = 0; pg_i < REGION0_PG_COUNT / 32; pg_i++) { + uint32_t line = pagetable0->allocmap[pg_i] | pagetable0->freemap[pg_i]; + if (line) { + for (int j = 0; j < 32; j++) { + if ((line >> j) & 1) { + (*p0)++; + } + } + } + } +} + +static void gc_stats_pagetable1(pagetable1_t *pagetable1, unsigned *p1, unsigned *p0) +{ + for (int pg_i = 0; pg_i < REGION1_PG_COUNT / 32; pg_i++) { + uint32_t line = pagetable1->allocmap0[pg_i] | pagetable1->freemap0[pg_i]; + if (line) { + for (int j = 0; j < 32; j++) { + if ((line >> j) & 1) { + (*p1)++; + gc_stats_pagetable0(pagetable1->meta0[pg_i * 32 + j], p0); + } + } + } + } +} + +static void gc_stats_pagetable(unsigned *p2, unsigned *p1, unsigned *p0) +{ + for (int pg_i = 0; pg_i < (REGION2_PG_COUNT + 31) / 32; pg_i++) { + uint32_t line = memory_map.allocmap1[pg_i] | memory_map.freemap1[pg_i]; + if (line) { + for (int j = 0; j < 32; j++) { + if ((line >> j) & 1) { + (*p2)++; + gc_stats_pagetable1(memory_map.meta1[pg_i * 32 + j], p1, p0); + } + } + } + } +} + void jl_print_gc_stats(JL_STREAM *s) { - double gct = gc_num.total_time / 1e9; +#ifdef _OS_LINUX_ malloc_stats(); +#endif double ptime = jl_clock_now() - process_t0; jl_printf(s, "exec time\t%.5f sec\n", ptime); if (gc_num.pause > 0) { @@ -713,14 +821,20 @@ void jl_print_gc_stats(JL_STREAM *s) (int)(total_sweep_time * 100 / gc_num.total_time), (int)(total_fin_time * 100 / gc_num.total_time)); } - int i = 0; - while (i < REGION_COUNT && regions[i].pages) i++; - jl_printf(s, "max allocated regions : %d\n", i); + unsigned p2 = 0, p1 = 0, p0 = 0; + gc_stats_pagetable(&p2, &p1, &p0); + jl_printf(s, "page table max utilization : %u (%.1f%%) - %u (%.1f%%) - %u (%.1f%%)\n", + p2, p2 * 100.0 / REGION2_PG_COUNT, + p1, p1 * 100.0 / REGION1_PG_COUNT / p2, + p0, p0 * 100.0 / REGION0_PG_COUNT / p1); +#ifdef _OS_LINUX_ + double gct = gc_num.total_time / 1e9; struct mallinfo mi = mallinfo(); - jl_printf(s, "malloc size\t%d MB\n", mi.uordblks/1024/1024); - jl_printf(s, "max page alloc\t%ld MB\n", max_pg_count*GC_PAGE_SZ/1024/1024); + jl_printf(s, "malloc size\t%d MB\n", mi.uordblks / 1024 / 1024); + jl_printf(s, "max page alloc\t%ld MB\n", max_pg_count * GC_PAGE_SZ / 1024 / 1024); jl_printf(s, "total freed\t%" PRIuPTR " b\n", total_freed_bytes); - jl_printf(s, "free rate\t%.1f MB/sec\n", (total_freed_bytes/gct)/1024/1024); + jl_printf(s, "free rate\t%.1f MB/sec\n", (total_freed_bytes / gct) / 1024 / 1024); +#endif } #else void jl_print_gc_stats(JL_STREAM *s) @@ -845,7 +959,7 @@ void gc_time_sweep_pause(uint64_t gc_end_t, int64_t actual_allocd, int pct = actual_allocd ? (gc_num.freed * 100) / actual_allocd : -1; jl_printf(JL_STDOUT, "GC sweep pause %.2f ms live %" PRId64 " kB " "(freed %" PRId64 " kB EST %" PRId64 " kB " - "[error %" PRId64 "] = %d%% of allocd b %ld) " + "[error %" PRId64 "] = %d%% of allocd b %" PRIu64 ") " "(%.2f ms in post_mark) %s | next in %" PRId64 " kB\n", jl_ns2ms(sweep_pause), live_bytes / 1024, gc_num.freed / 1024, estimate_freed / 1024, @@ -1016,14 +1130,42 @@ static void gc_count_pool_page(jl_gc_pagemeta_t *pg) } } -static void gc_count_pool_region(region_t *region) +static void gc_count_pool_pagetable0(pagetable0_t *pagetable0) +{ + for (int pg_i = 0; pg_i < REGION0_PG_COUNT / 32; pg_i++) { + uint32_t line = pagetable0->allocmap[pg_i]; + if (line) { + for (int j = 0; j < 32; j++) { + if ((line >> j) & 1) { + gc_count_pool_page(pagetable0->meta[pg_i * 32 + j]); + } + } + } + } +} + +static void gc_count_pool_pagetable1(pagetable1_t *pagetable1) { - for (int pg_i = 0; pg_i < region->pg_cnt / 32; pg_i++) { - uint32_t line = region->allocmap[pg_i]; + for (int pg_i = 0; pg_i < REGION1_PG_COUNT / 32; pg_i++) { + uint32_t line = pagetable1->allocmap0[pg_i]; if (line) { for (int j = 0; j < 32; j++) { if ((line >> j) & 1) { - gc_count_pool_page(®ion->meta[pg_i*32 + j]); + gc_count_pool_pagetable0(pagetable1->meta0[pg_i * 32 + j]); + } + } + } + } +} + +static void gc_count_pool_pagetable(void) +{ + for (int pg_i = 0; pg_i < (REGION2_PG_COUNT + 31) / 32; pg_i++) { + uint32_t line = memory_map.allocmap1[pg_i]; + if (line) { + for (int j = 0; j < 32; j++) { + if ((line >> j) & 1) { + gc_count_pool_pagetable1(memory_map.meta1[pg_i * 32 + j]); } } } @@ -1034,11 +1176,7 @@ void gc_count_pool(void) { memset(&poolobj_sizes, 0, sizeof(poolobj_sizes)); empty_pages = 0; - for (int i = 0; i < REGION_COUNT; i++) { - if (!regions[i].pages) - break; - gc_count_pool_region(®ions[i]); - } + gc_count_pool_pagetable(); jl_safe_printf("****** Pool stat: ******\n"); for (int i = 0;i < 4;i++) jl_safe_printf("bits(%d): %" PRId64 "\n", i, poolobj_sizes[i]); diff --git a/src/gc-pages.c b/src/gc-pages.c index ca549e81074bc..aecf418e1ba29 100644 --- a/src/gc-pages.c +++ b/src/gc-pages.c @@ -9,190 +9,281 @@ extern "C" { #endif -// A region is contiguous storage for up to DEFAULT_REGION_PG_COUNT naturally aligned GC_PAGE_SZ pages -// It uses a very naive allocator (see jl_gc_alloc_page & jl_gc_free_page) -#if defined(_P64) -#define DEFAULT_REGION_PG_COUNT (16 * 8 * 4096) // 8 GB +// Try to allocate memory in chunks to permit faster allocation +// and improve memory locality of the pools +#ifdef _P64 +#define DEFAULT_BLOCK_PG_ALLOC (4096) // 64 MB #else -#define DEFAULT_REGION_PG_COUNT (8 * 4096) // 512 MB +#define DEFAULT_BLOCK_PG_ALLOC (1024) // 16 MB #endif -#define MIN_REGION_PG_COUNT 64 // 1 MB +#define MIN_BLOCK_PG_ALLOC (1) // 16 KB -static int region_pg_cnt = DEFAULT_REGION_PG_COUNT; +static int block_pg_cnt = DEFAULT_BLOCK_PG_ALLOC; static jl_mutex_t pagealloc_lock; static size_t current_pg_count = 0; void jl_gc_init_page(void) { -#ifndef _OS_WINDOWS_ - struct rlimit rl; - if (getrlimit(RLIMIT_AS, &rl) == 0) { - // This is not 100% precise and not the most efficient implementation - // but should be close enough and fast enough for the normal case. - while (rl.rlim_cur < region_pg_cnt * sizeof(jl_gc_page_t) * 2 && - region_pg_cnt >= MIN_REGION_PG_COUNT) { - region_pg_cnt /= 2; - } - } -#endif + if (GC_PAGE_SZ * block_pg_cnt < jl_page_size) + block_pg_cnt = jl_page_size / GC_PAGE_SZ; // exact division } #ifndef MAP_NORESERVE // not defined in POSIX, FreeBSD, etc. #define MAP_NORESERVE (0) #endif -// Try to allocate a memory block for a region with `pg_cnt` pages. +// Try to allocate a memory block for multiple pages // Return `NULL` if allocation failed. Result is aligned to `GC_PAGE_SZ`. -static char *jl_gc_try_alloc_region(int pg_cnt) +static char *jl_gc_try_alloc_pages(int pg_cnt) { - const size_t pages_sz = sizeof(jl_gc_page_t) * pg_cnt; - const size_t freemap_sz = sizeof(uint32_t) * pg_cnt / 32; - const size_t meta_sz = sizeof(jl_gc_pagemeta_t) * pg_cnt; - size_t alloc_size = pages_sz + freemap_sz + meta_sz; + size_t pages_sz = GC_PAGE_SZ * pg_cnt; #ifdef _OS_WINDOWS_ - char *mem = (char*)VirtualAlloc(NULL, alloc_size + GC_PAGE_SZ, + char *mem = (char*)VirtualAlloc(NULL, pages_sz + GC_PAGE_SZ, MEM_RESERVE, PAGE_READWRITE); if (mem == NULL) return NULL; #else if (GC_PAGE_SZ > jl_page_size) - alloc_size += GC_PAGE_SZ; - char *mem = (char*)mmap(0, alloc_size, PROT_READ | PROT_WRITE, + pages_sz += GC_PAGE_SZ; + char *mem = (char*)mmap(0, pages_sz, PROT_READ | PROT_WRITE, MAP_NORESERVE | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (mem == MAP_FAILED) return NULL; #endif - if (GC_PAGE_SZ > jl_page_size) { + if (GC_PAGE_SZ > jl_page_size) // round data pointer up to the nearest gc_page_data-aligned // boundary if mmap didn't already do so. mem = (char*)gc_page_data(mem + GC_PAGE_SZ - 1); - } return mem; } -// Allocate the memory for a `region_t`. Starts with `region_pg_cnt` number +// Allocate the memory for a new page. Starts with `block_pg_cnt` number // of pages. Decrease 4x every time so that there are enough space for a few. -// more regions (or other allocations). The final page count is recorded +// more chunks (or other allocations). The final page count is recorded // and will be used as the starting count next time. If the page count is -// smaller `MIN_REGION_PG_COUNT` a `jl_memory_exception` is thrown. -// Assume `pagealloc_lock` is acquired, the lock is released before the +// smaller `MIN_BLOCK_PG_ALLOC` a `jl_memory_exception` is thrown. +// Assumes `pagealloc_lock` is acquired, the lock is released before the // exception is thrown. -static void jl_gc_alloc_region(region_t *region) +static jl_gc_pagemeta_t *jl_gc_alloc_new_page(void) { - int pg_cnt = region_pg_cnt; + // try to allocate a large block of memory (or a small one) + unsigned pg, pg_cnt = block_pg_cnt; char *mem = NULL; while (1) { - if (__likely((mem = jl_gc_try_alloc_region(pg_cnt)))) + if (__likely((mem = jl_gc_try_alloc_pages(pg_cnt)))) break; - if (pg_cnt >= MIN_REGION_PG_COUNT * 4) { + size_t min_block_pg_alloc = MIN_BLOCK_PG_ALLOC; + if (GC_PAGE_SZ * min_block_pg_alloc < jl_page_size) + min_block_pg_alloc = jl_page_size / GC_PAGE_SZ; // exact division + if (pg_cnt >= 4 * min_block_pg_alloc) { pg_cnt /= 4; - region_pg_cnt = pg_cnt; + block_pg_cnt = pg_cnt; } - else if (pg_cnt > MIN_REGION_PG_COUNT) { - region_pg_cnt = pg_cnt = MIN_REGION_PG_COUNT; + else if (pg_cnt > min_block_pg_alloc) { + block_pg_cnt = pg_cnt = min_block_pg_alloc; } else { JL_UNLOCK_NOGC(&pagealloc_lock); jl_throw(jl_memory_exception); } } - const size_t pages_sz = sizeof(jl_gc_page_t) * pg_cnt; - const size_t allocmap_sz = sizeof(uint32_t) * pg_cnt / 32; - region->pages = (jl_gc_page_t*)mem; - region->allocmap = (uint32_t*)(mem + pages_sz); - region->meta = (jl_gc_pagemeta_t*)(mem + pages_sz +allocmap_sz); - region->lb = 0; - region->ub = 0; - region->pg_cnt = pg_cnt; -#ifdef _OS_WINDOWS_ - VirtualAlloc(region->allocmap, pg_cnt / 8, MEM_COMMIT, PAGE_READWRITE); - VirtualAlloc(region->meta, pg_cnt * sizeof(jl_gc_pagemeta_t), - MEM_COMMIT, PAGE_READWRITE); + + // now need to insert these pages into the pagetable metadata + // if any allocation fails, this just stops recording more pages from that point + // and will free (munmap) the remainder + jl_gc_pagemeta_t *page_meta = (jl_gc_pagemeta_t*)calloc(pg_cnt, sizeof(jl_gc_pagemeta_t)); + pg = 0; + if (page_meta) { + for (; pg < pg_cnt; pg++) { + struct jl_gc_metadata_ext info; + uint32_t msk; + unsigned i; + pagetable1_t **ppagetable1; + pagetable0_t **ppagetable0; + jl_gc_pagemeta_t **pmeta; + + char *ptr = mem + (GC_PAGE_SZ * pg); + page_meta[pg].data = ptr; + + // create & store the level 2 / outermost info + i = REGION_INDEX(ptr); + info.pagetable_i = i % 32; + info.pagetable_i32 = i / 32; + msk = (1 << info.pagetable_i); + if ((memory_map.freemap1[info.pagetable_i32] & msk) == 0) + memory_map.freemap1[info.pagetable_i32] |= msk; // has free + info.pagetable1 = *(ppagetable1 = &memory_map.meta1[i]); + if (!info.pagetable1) { + info.pagetable1 = (*ppagetable1 = (pagetable1_t*)calloc(1, sizeof(pagetable1_t))); + if (!info.pagetable1) + break; + } + + // create & store the level 1 info + i = REGION1_INDEX(ptr); + info.pagetable1_i = i % 32; + info.pagetable1_i32 = i / 32; + msk = (1 << info.pagetable1_i); + if ((info.pagetable1->freemap0[info.pagetable1_i32] & msk) == 0) + info.pagetable1->freemap0[info.pagetable1_i32] |= msk; // has free + info.pagetable0 = *(ppagetable0 = &info.pagetable1->meta0[i]); + if (!info.pagetable0) { + info.pagetable0 = (*ppagetable0 = (pagetable0_t*)calloc(1, sizeof(pagetable0_t))); + if (!info.pagetable0) + break; + } + + // create & store the level 0 / page info + i = REGION0_INDEX(ptr); + info.pagetable0_i = i % 32; + info.pagetable0_i32 = i / 32; + msk = (1 << info.pagetable0_i); + info.pagetable0->freemap[info.pagetable0_i32] |= msk; // is free + pmeta = &info.pagetable0->meta[i]; + info.meta = (*pmeta = &page_meta[pg]); + } + } + + if (pg < pg_cnt) { +#ifndef _OS_WINDOWS_ + // Trim the allocation to only cover the region + // that we successfully created the metadata for. + // This is not supported by the Windows kernel, + // so we have to just skip it there and just lose these virtual addresses. + munmap(mem + LLT_ALIGN(GC_PAGE_SZ * pg, jl_page_size), + GC_PAGE_SZ * pg_cnt - LLT_ALIGN(GC_PAGE_SZ * pg, jl_page_size)); #endif + if (pg == 0) { + JL_UNLOCK_NOGC(&pagealloc_lock); + jl_throw(jl_memory_exception); + } + } + return page_meta; } -NOINLINE void *jl_gc_alloc_page(void) +// get a new page, either from the freemap +// or from the kernel if none are available +NOINLINE jl_gc_pagemeta_t *jl_gc_alloc_page(void) { - int i; - region_t *region; - int region_i = 0; + struct jl_gc_metadata_ext info; JL_LOCK_NOGC(&pagealloc_lock); - while (region_i < REGION_COUNT) { - region = ®ions[region_i]; - if (region->pages == NULL) - jl_gc_alloc_region(region); - for (i = region->lb; i < region->pg_cnt / 32; i++) { - if (~region->allocmap[i]) - break; - } - if (i == region->pg_cnt / 32) { - // region full - region_i++; - continue; + + // scan over memory_map page-table for existing allocated but unused pages + for (info.pagetable_i32 = memory_map.lb; info.pagetable_i32 < (REGION2_PG_COUNT + 31) / 32; info.pagetable_i32++) { + uint32_t freemap1 = memory_map.freemap1[info.pagetable_i32]; + for (info.pagetable_i = 0; freemap1; info.pagetable_i++, freemap1 >>= 1) { + unsigned next = ffs_u32(freemap1); + info.pagetable_i += next; + freemap1 >>= next; + info.pagetable1 = memory_map.meta1[info.pagetable_i + info.pagetable_i32 * 32]; + // repeat over page-table level 1 + for (info.pagetable1_i32 = info.pagetable1->lb; info.pagetable1_i32 < REGION1_PG_COUNT / 32; info.pagetable1_i32++) { + uint32_t freemap0 = info.pagetable1->freemap0[info.pagetable1_i32]; + for (info.pagetable1_i = 0; freemap0; info.pagetable1_i++, freemap0 >>= 1) { + unsigned next = ffs_u32(freemap0); + info.pagetable1_i += next; + freemap0 >>= next; + info.pagetable0 = info.pagetable1->meta0[info.pagetable1_i + info.pagetable1_i32 * 32]; + // repeat over page-table level 0 + for (info.pagetable0_i32 = info.pagetable0->lb; info.pagetable0_i32 < REGION0_PG_COUNT / 32; info.pagetable0_i32++) { + uint32_t freemap = info.pagetable0->freemap[info.pagetable0_i32]; + if (freemap) { + info.pagetable0_i = ffs_u32(freemap); + info.meta = info.pagetable0->meta[info.pagetable0_i + info.pagetable0_i32 * 32]; + assert(info.meta->data); + // new pages available starting at min of lb and pagetable_i32 + if (memory_map.lb < info.pagetable_i32) + memory_map.lb = info.pagetable_i32; + if (info.pagetable1->lb < info.pagetable1_i32) + info.pagetable1->lb = info.pagetable1_i32; + if (info.pagetable0->lb < info.pagetable0_i32) + info.pagetable0->lb = info.pagetable0_i32; + goto have_free_page; // break out of all of these loops + } + } + info.pagetable1->freemap0[info.pagetable1_i32] &= ~(uint32_t)(1 << info.pagetable1_i); // record that this was full + } + } + memory_map.freemap1[info.pagetable_i32] &= ~(uint32_t)(1 << info.pagetable_i); // record that this was full } - break; } - if (__unlikely(region_i >= REGION_COUNT)) { - JL_UNLOCK_NOGC(&pagealloc_lock); - jl_throw(jl_memory_exception); + + // no existing pages found, allocate a new one + { + jl_gc_pagemeta_t *meta = jl_gc_alloc_new_page(); + info = page_metadata_ext(meta->data); + assert(meta == info.meta); + // new pages are now available starting at max of lb and pagetable_i32 + if (memory_map.lb > info.pagetable_i32) + memory_map.lb = info.pagetable_i32; + if (info.pagetable1->lb > info.pagetable1_i32) + info.pagetable1->lb = info.pagetable1_i32; + if (info.pagetable0->lb > info.pagetable0_i32) + info.pagetable0->lb = info.pagetable0_i32; } - if (region->lb < i) - region->lb = i; - if (region->ub < i) - region->ub = i; - -#if defined(_COMPILER_MINGW_) - int j = __builtin_ffs(~region->allocmap[i]) - 1; -#elif defined(_COMPILER_MICROSOFT_) - unsigned long j; - _BitScanForward(&j, ~region->allocmap[i]); -#else - int j = ffs(~region->allocmap[i]) - 1; -#endif - region->allocmap[i] |= (uint32_t)(1 << j); - void *ptr = region->pages[i * 32 + j].data; +have_free_page: + // in-use pages are now ending at min of ub and pagetable_i32 + if (memory_map.ub < info.pagetable_i32) + memory_map.ub = info.pagetable_i32; + if (info.pagetable1->ub < info.pagetable1_i32) + info.pagetable1->ub = info.pagetable1_i32; + if (info.pagetable0->ub < info.pagetable0_i32) + info.pagetable0->ub = info.pagetable0_i32; + + // mark this entry as in-use and not free + info.pagetable0->freemap[info.pagetable0_i32] &= ~(uint32_t)(1 << info.pagetable0_i); + info.pagetable0->allocmap[info.pagetable0_i32] |= (uint32_t)(1 << info.pagetable0_i); + info.pagetable1->allocmap0[info.pagetable1_i32] |= (uint32_t)(1 << info.pagetable1_i); + memory_map.allocmap1[info.pagetable_i32] |= (uint32_t)(1 << info.pagetable_i); + #ifdef _OS_WINDOWS_ - VirtualAlloc(ptr, GC_PAGE_SZ, MEM_COMMIT, PAGE_READWRITE); + VirtualAlloc(info.meta->data, GC_PAGE_SZ, MEM_COMMIT, PAGE_READWRITE); #endif current_pg_count++; gc_final_count_page(current_pg_count); JL_UNLOCK_NOGC(&pagealloc_lock); - return ptr; + return info.meta; } +// return a page to the freemap allocator void jl_gc_free_page(void *p) { - int pg_idx = -1; - int i; - region_t *region = regions; - for (i = 0; i < REGION_COUNT && regions[i].pages != NULL; i++) { - region = ®ions[i]; - pg_idx = page_index(region, p); - if (pg_idx >= 0 && pg_idx < region->pg_cnt) { - break; - } - } - assert(i < REGION_COUNT && region->pages != NULL); - uint32_t msk = (uint32_t)(1 << (pg_idx % 32)); - assert(region->allocmap[pg_idx/32] & msk); - region->allocmap[pg_idx/32] ^= msk; - free(region->meta[pg_idx].ages); + // update the allocmap and freemap to indicate this contains a free entry + struct jl_gc_metadata_ext info = page_metadata_ext(p); + uint32_t msk; + msk = (uint32_t)(1 << info.pagetable0_i); + assert(!(info.pagetable0->freemap[info.pagetable0_i32] & msk)); + assert(info.pagetable0->allocmap[info.pagetable0_i32] & msk); + info.pagetable0->allocmap[info.pagetable0_i32] &= ~msk; + info.pagetable0->freemap[info.pagetable0_i32] |= msk; + + msk = (uint32_t)(1 << info.pagetable1_i); + assert(info.pagetable1->allocmap0[info.pagetable1_i32] & msk); + if ((info.pagetable1->freemap0[info.pagetable1_i32] & msk) == 0) + info.pagetable1->freemap0[info.pagetable1_i32] |= msk; + + msk = (uint32_t)(1 << info.pagetable_i); + assert(memory_map.allocmap1[info.pagetable_i32] & msk); + if ((memory_map.freemap1[info.pagetable_i32] & msk) == 0) + memory_map.freemap1[info.pagetable_i32] |= msk; + + free(info.meta->ages); + info.meta->ages = NULL; + // tell the OS we don't need these pages right now size_t decommit_size = GC_PAGE_SZ; if (GC_PAGE_SZ < jl_page_size) { // ensure so we don't release more memory than intended - size_t n_pages = (GC_PAGE_SZ + jl_page_size - 1) / GC_PAGE_SZ; + size_t n_pages = jl_page_size / GC_PAGE_SZ; // exact division decommit_size = jl_page_size; - p = (void*)((uintptr_t)region->pages[pg_idx].data & ~(jl_page_size - 1)); // round down to the nearest page - pg_idx = page_index(region, p); - if (pg_idx + n_pages > region->pg_cnt) - goto no_decommit; - for (; n_pages--; pg_idx++) { - msk = (uint32_t)(1 << ((pg_idx % 32))); - if (region->allocmap[pg_idx / 32] & msk) { + p = (void*)((uintptr_t)p & ~(jl_page_size - 1)); // round down to the nearest physical page + while (n_pages--) { + struct jl_gc_metadata_ext info = page_metadata_ext(p); + msk = (uint32_t)(1 << info.pagetable0_i); + if (info.pagetable0->allocmap[info.pagetable0_i32] & msk) goto no_decommit; - } + p = (void*)((char*)p + GC_PAGE_SZ); } } #ifdef _OS_WINDOWS_ @@ -200,9 +291,15 @@ void jl_gc_free_page(void *p) #else madvise(p, decommit_size, MADV_DONTNEED); #endif + no_decommit: - if (region->lb > pg_idx / 32) - region->lb = pg_idx / 32; + // new pages are now available starting at max of lb and pagetable_i32 + if (memory_map.lb > info.pagetable_i32) + memory_map.lb = info.pagetable_i32; + if (info.pagetable1->lb > info.pagetable1_i32) + info.pagetable1->lb = info.pagetable1_i32; + if (info.pagetable0->lb > info.pagetable0_i32) + info.pagetable0->lb = info.pagetable0_i32; current_pg_count--; } diff --git a/src/gc.c b/src/gc.c index 411510710d7ca..96718ed05113b 100644 --- a/src/gc.c +++ b/src/gc.c @@ -48,7 +48,7 @@ static jl_mutex_t gc_cache_lock; jl_gc_num_t gc_num = {0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static size_t last_long_collect_interval; -region_t regions[REGION_COUNT]; +pagetable_t memory_map; // List of marked big objects. Not per-thread. Accessed only by master thread. bigval_t *big_objects_marked = NULL; @@ -404,7 +404,7 @@ static int mark_reset_age = 0; #define PROMOTE_AGE 1 // this cannot be increased as is without changing : // - sweep_page which is specialized for 1bit age -// - the size of the age storage in region_t +// - the size of the age storage in jl_gc_pagemeta_t static int64_t scanned_bytes; // young bytes scanned while marking @@ -590,7 +590,7 @@ STATIC_INLINE void gc_setmark_pool_(jl_ptls_t ptls, jl_taggedvalue_t *o, STATIC_INLINE void gc_setmark_pool(jl_ptls_t ptls, jl_taggedvalue_t *o, uint8_t mark_mode) { - gc_setmark_pool_(ptls, o, mark_mode, page_metadata(o)); + gc_setmark_pool_(ptls, o, mark_mode, page_metadata_ext(o).meta); } STATIC_INLINE void gc_setmark(jl_ptls_t ptls, jl_taggedvalue_t *o, @@ -620,7 +620,7 @@ void gc_setmark_buf(jl_ptls_t ptls, void *o, uint8_t mark_mode, size_t minsz) // sure. if (__likely(gc_setmark_tag(buf, mark_mode, tag, &bits)) && !gc_verifying) { if (minsz <= GC_MAX_SZCLASS) { - jl_gc_pagemeta_t *page = page_metadata(o); + jl_gc_pagemeta_t *page = page_metadata(buf); if (page) { gc_setmark_pool_(ptls, buf, bits, page); return; @@ -877,11 +877,7 @@ static NOINLINE jl_taggedvalue_t *add_page(jl_gc_pool_t *p) // Do not pass in `ptls` as argument. This slows down the fast path // in pool_alloc significantly jl_ptls_t ptls = jl_get_ptls_states(); - char *data = (char*)jl_gc_alloc_page(); - if (data == NULL) - jl_throw(jl_memory_exception); - jl_gc_pagemeta_t *pg = page_metadata(data + GC_PAGE_OFFSET); - pg->data = data; + jl_gc_pagemeta_t *pg = jl_gc_alloc_page(); pg->osize = p->osize; pg->ages = (uint8_t*)malloc(GC_PAGE_SZ / 8 / p->osize + 1); pg->thread_n = ptls->tid; @@ -922,7 +918,7 @@ JL_DLLEXPORT jl_value_t *jl_gc_pool_alloc(jl_ptls_t ptls, int pool_offset, if (__unlikely(gc_page_data(v) != gc_page_data(next))) { // we only update pg's fields when the freelist changes page // since pg's metadata is likely not in cache - jl_gc_pagemeta_t *pg = page_metadata(v); + jl_gc_pagemeta_t *pg = page_metadata_ext(v).meta; assert(pg->osize == p->osize); pg->nfree = 0; pg->has_young = 1; @@ -939,7 +935,7 @@ JL_DLLEXPORT jl_value_t *jl_gc_pool_alloc(jl_ptls_t ptls, int pool_offset, if (v) { // like the freelist case, // but only update the page metadata when it is full - jl_gc_pagemeta_t *pg = page_metadata((char*)v - 1); + jl_gc_pagemeta_t *pg = page_metadata_ext((char*)v - 1).meta; assert(pg->osize == p->osize); pg->nfree = 0; pg->has_young = 1; @@ -1084,37 +1080,94 @@ static jl_taggedvalue_t **sweep_page(jl_gc_pool_t *p, jl_gc_pagemeta_t *pg, jl_t return pfl; } -static void sweep_pool_region(jl_taggedvalue_t ***pfl, int region_i, int sweep_full) +// the actual sweeping over all allocated pages in a memory pool +static inline void sweep_pool_page(jl_taggedvalue_t ***pfl, jl_gc_pagemeta_t *pg, int sweep_full) { - region_t *region = ®ions[region_i]; + int p_n = pg->pool_n; + int t_n = pg->thread_n; + jl_ptls_t ptls2 = jl_all_tls_states[t_n]; + jl_gc_pool_t *p = &ptls2->heap.norm_pools[p_n]; + int osize = pg->osize; + pfl[t_n * JL_GC_N_POOLS + p_n] = sweep_page(p, pg, pfl[t_n * JL_GC_N_POOLS + p_n], sweep_full, osize); +} - // the actual sweeping - int ub = 0; - int lb = region->lb; - for (int pg_i = 0; pg_i <= region->ub; pg_i++) { - uint32_t line = region->allocmap[pg_i]; - if (line) { +// sweep over a pagetable0 for all allocated pages +static inline int sweep_pool_pagetable0(jl_taggedvalue_t ***pfl, pagetable0_t *pagetable0, int sweep_full) +{ + unsigned ub = 0; + unsigned alloc = 0; + for (unsigned pg_i = 0; pg_i <= pagetable0->ub; pg_i++) { + uint32_t line = pagetable0->allocmap[pg_i]; + unsigned j; + if (!line) + continue; + ub = pg_i; + alloc = 1; + for (j = 0; line; j++, line >>= 1) { + unsigned next = ffs_u32(line); + j += next; + line >>= next; + jl_gc_pagemeta_t *pg = pagetable0->meta[pg_i * 32 + j]; + sweep_pool_page(pfl, pg, sweep_full); + } + } + pagetable0->ub = ub; + return alloc; +} + +// sweep over pagetable1 for all pagetable0 that may contain allocated pages +static inline int sweep_pool_pagetable1(jl_taggedvalue_t ***pfl, pagetable1_t *pagetable1, int sweep_full) +{ + unsigned ub = 0; + unsigned alloc = 0; + for (unsigned pg_i = 0; pg_i <= pagetable1->ub; pg_i++) { + uint32_t line = pagetable1->allocmap0[pg_i]; + unsigned j; + for (j = 0; line; j++, line >>= 1) { + unsigned next = ffs_u32(line); + j += next; + line >>= next; + pagetable0_t *pagetable0 = pagetable1->meta0[pg_i * 32 + j]; + if (pagetable0 && !sweep_pool_pagetable0(pfl, pagetable0, sweep_full)) + pagetable1->allocmap0[pg_i] &= ~(1 << j); // no allocations found, remember that for next time + } + if (pagetable1->allocmap0[pg_i]) { ub = pg_i; - for (int j = 0; j < 32; j++) { - if ((line >> j) & 1) { - jl_gc_pagemeta_t *pg = ®ion->meta[pg_i*32 + j]; - int p_n = pg->pool_n; - int t_n = pg->thread_n; - jl_ptls_t ptls2 = jl_all_tls_states[t_n]; - jl_gc_pool_t *p = &ptls2->heap.norm_pools[p_n]; - int osize = pg->osize; - pfl[t_n * JL_GC_N_POOLS + p_n] = sweep_page(p, pg, pfl[t_n * JL_GC_N_POOLS + p_n], sweep_full, osize); - } - } + alloc = 1; } - else if (pg_i < lb) { - lb = pg_i; + } + pagetable1->ub = ub; + return alloc; +} + +// sweep over all memory for all pagetable1 that may contain allocated pages +static void sweep_pool_pagetable(jl_taggedvalue_t ***pfl, int sweep_full) +{ + if (REGION2_PG_COUNT == 1) { // compile-time optimization + pagetable1_t *pagetable1 = memory_map.meta1[0]; + sweep_pool_pagetable1(pfl, pagetable1, sweep_full); + return; + } + unsigned ub = 0; + for (unsigned pg_i = 0; pg_i <= memory_map.ub; pg_i++) { + uint32_t line = memory_map.allocmap1[pg_i]; + unsigned j; + for (j = 0; line; j++, line >>= 1) { + unsigned next = ffs_u32(line); + j += next; + line >>= next; + pagetable1_t *pagetable1 = memory_map.meta1[pg_i * 32 + j]; + if (pagetable1 && !sweep_pool_pagetable1(pfl, pagetable1, sweep_full)) + memory_map.allocmap1[pg_i] &= ~(1 << j); // no allocations found, remember that for next time + } + if (memory_map.allocmap1[pg_i]) { + ub = pg_i; } } - region->ub = ub; - region->lb = lb; + memory_map.ub = ub; } +// sweep over all memory that is being used and not in a pool static void gc_sweep_other(jl_ptls_t ptls, int sweep_full) { sweep_malloced_arrays(); @@ -1137,11 +1190,14 @@ static void gc_pool_sync_nfree(jl_gc_pagemeta_t *pg, jl_taggedvalue_t *last) pg->nfree = nfree; } +// setup the data-structures for a sweep over all memory pools static void gc_sweep_pool(int sweep_full) { gc_time_pool_start(); lazy_freed_pages = 0; + // allocate enough space to hold the end of the free list chain + // for every thread and pool size jl_taggedvalue_t ***pfl = (jl_taggedvalue_t ***) alloca(jl_n_threads * JL_GC_N_POOLS * sizeof(jl_taggedvalue_t**)); // update metadata of pages that were pointed to by freelist or newpages from a pool @@ -1152,7 +1208,7 @@ static void gc_sweep_pool(int sweep_full) jl_gc_pool_t *p = &ptls2->heap.norm_pools[i]; jl_taggedvalue_t *last = p->freelist; if (last) { - jl_gc_pagemeta_t *pg = page_metadata(last); + jl_gc_pagemeta_t *pg = page_metadata_ext(last).meta; gc_pool_sync_nfree(pg, last); pg->has_young = 1; } @@ -1162,7 +1218,7 @@ static void gc_sweep_pool(int sweep_full) last = p->newpages; if (last) { char *last_p = (char*)last; - jl_gc_pagemeta_t *pg = page_metadata(last_p - 1); + jl_gc_pagemeta_t *pg = page_metadata_ext(last_p - 1).meta; assert(last_p - gc_page_data(last_p - 1) >= GC_PAGE_OFFSET); pg->nfree = (GC_PAGE_SZ - (last_p - gc_page_data(last_p - 1))) / p->osize; pg->has_young = 1; @@ -1171,12 +1227,8 @@ static void gc_sweep_pool(int sweep_full) } } - for (int i = 0; i < REGION_COUNT; i++) { - if (!regions[i].pages) - break; - sweep_pool_region(pfl, i, sweep_full); - } - + // the actual sweeping + sweep_pool_pagetable(pfl, sweep_full); // null out terminal pointers of free lists for (int t_i = 0; t_i < jl_n_threads; t_i++) { diff --git a/src/gc.h b/src/gc.h index f49bc4f13be87..b806ef5a783ce 100644 --- a/src/gc.h +++ b/src/gc.h @@ -34,10 +34,6 @@ extern "C" { #define GC_PAGE_SZ (1 << GC_PAGE_LG2) // 16k #define GC_PAGE_OFFSET (JL_SMALL_BYTE_ALIGNMENT - (sizeof(jl_taggedvalue_t) % JL_SMALL_BYTE_ALIGNMENT)) -// 8G * 32768 = 2^48 -// It's really unlikely that we'll actually allocate that much though... -#define REGION_COUNT 32768 - #define jl_malloc_tag ((void*)0xdeadaa01) #define jl_singleton_tag ((void*)0xdeadaa02) @@ -147,33 +143,90 @@ typedef struct { uint8_t *ages; } jl_gc_pagemeta_t; -typedef struct { - char data[GC_PAGE_SZ]; -} jl_gc_page_t -#if !defined(_COMPILER_MICROSOFT_) && !(defined(_COMPILER_MINGW_) && defined(_COMPILER_CLANG_)) -__attribute__((aligned(GC_PAGE_SZ))) +// Page layout: +// Newpage freelist: sizeof(void*) +// Padding: GC_PAGE_OFFSET - sizeof(void*) +// Blocks: osize * n +// Tag: sizeof(jl_taggedvalue_t) +// Data: <= osize - sizeof(jl_taggedvalue_t) + +// Memory map: +// The complete address space is divided up into a multi-level page table. +// The three levels have similar but slightly different structures: +// - pagetable0_t: the bottom/leaf level (covers the contiguous addresses) +// - pagetable1_t: the middle level +// - pagetable2_t: the top/leaf level (covers the entire virtual address space) +// Corresponding to these similar structures is a large amount of repetitive +// code that is nearly the same but not identical. It could be made less +// repetitive with C macros, but only at the cost of debuggability. The specialized +// structure of this representation allows us to partially unroll and optimize +// various conditions at each level. + +// The following constants define the branching factors at each level. +// The constants and GC_PAGE_LG2 must therefore sum to sizeof(void*). +// They should all be multiples of 32 (sizeof(uint32_t)) except that REGION2_PG_COUNT may also be 1. +#ifdef _P64 +#define REGION0_PG_COUNT (1 << 16) +#define REGION1_PG_COUNT (1 << 16) +#define REGION2_PG_COUNT (1 << 18) +#define REGION0_INDEX(p) (((uintptr_t)(p) >> 14) & 0xFFFF) // shift by GC_PAGE_LG2 +#define REGION1_INDEX(p) (((uintptr_t)(p) >> 30) & 0xFFFF) +#define REGION_INDEX(p) (((uintptr_t)(p) >> 46) & 0x3FFFF) +#else +#define REGION0_PG_COUNT (1 << 8) +#define REGION1_PG_COUNT (1 << 10) +#define REGION2_PG_COUNT (1 << 0) +#define REGION0_INDEX(p) (((uintptr_t)(p) >> 14) & 0xFF) // shift by GC_PAGE_LG2 +#define REGION1_INDEX(p) (((uintptr_t)(p) >> 22) & 0x3FF) +#define REGION_INDEX(p) (0) #endif -; + +// define the representation of the levels of the page-table (0 to 2) +typedef struct { + jl_gc_pagemeta_t *meta[REGION0_PG_COUNT]; + uint32_t allocmap[REGION0_PG_COUNT / 32]; + uint32_t freemap[REGION0_PG_COUNT / 32]; + // store a lower bound of the first free page in each region + int lb; + // an upper bound of the last non-free page + int ub; +} pagetable0_t; + +typedef struct { + pagetable0_t *meta0[REGION1_PG_COUNT]; + uint32_t allocmap0[REGION1_PG_COUNT / 32]; + uint32_t freemap0[REGION1_PG_COUNT / 32]; + // store a lower bound of the first free page in each region + int lb; + // an upper bound of the last non-free page + int ub; +} pagetable1_t; typedef struct { - // Page layout: - // Newpage freelist: sizeof(void*) - // Padding: GC_PAGE_OFFSET - sizeof(void*) - // Blocks: osize * n - // Tag: sizeof(jl_taggedvalue_t) - // Data: <= osize - sizeof(jl_taggedvalue_t) - jl_gc_page_t *pages; // [pg_cnt]; must be first, to preserve page alignment - uint32_t *allocmap; // [pg_cnt / 32] - jl_gc_pagemeta_t *meta; // [pg_cnt] - int pg_cnt; + pagetable1_t *meta1[REGION2_PG_COUNT]; + uint32_t allocmap1[(REGION2_PG_COUNT + 31) / 32]; + uint32_t freemap1[(REGION2_PG_COUNT + 31) / 32]; // store a lower bound of the first free page in each region int lb; // an upper bound of the last non-free page int ub; -} region_t; +} pagetable_t; + +STATIC_INLINE unsigned ffs_u32(uint32_t bitvec) +{ +#if defined(_COMPILER_MINGW_) + return __builtin_ffs(bitvec) - 1; +#elif defined(_COMPILER_MICROSOFT_) + unsigned long j; + _BitScanForward(&j, bitvec); + return j; +#else + return ffs(bitvec) - 1; +#endif +} extern jl_gc_num_t gc_num; -extern region_t regions[REGION_COUNT]; +extern pagetable_t memory_map; extern bigval_t *big_objects_marked; extern arraylist_t finalizer_list_marked; extern arraylist_t to_finalize; @@ -200,11 +253,6 @@ STATIC_INLINE jl_taggedvalue_t *page_pfl_end(jl_gc_pagemeta_t *p) return (jl_taggedvalue_t*)(p->data + p->fl_end_offset); } -STATIC_INLINE int page_index(region_t *region, void *data) -{ - return (gc_page_data(data) - region->pages->data) / GC_PAGE_SZ; -} - STATIC_INLINE int gc_marked(uintptr_t bits) { return (bits & GC_MARKED) != 0; @@ -232,31 +280,50 @@ STATIC_INLINE void *gc_ptr_clear_tag(void *v, uintptr_t mask) NOINLINE uintptr_t gc_get_stack_ptr(void); -STATIC_INLINE region_t *find_region(void *ptr) +STATIC_INLINE jl_gc_pagemeta_t *page_metadata(void *_data) { - for (int i = 0; i < REGION_COUNT && regions[i].pages; i++) { - region_t *region = ®ions[i]; - char *begin = region->pages->data; - char *end = begin + region->pg_cnt * sizeof(jl_gc_page_t); - if ((char*)ptr >= begin && (char*)ptr <= end) { - return region; - } - } - return NULL; + uintptr_t data = ((uintptr_t)_data); + unsigned i; + i = REGION_INDEX(data); + pagetable1_t *r1 = memory_map.meta1[i]; + if (!r1) + return NULL; + i = REGION1_INDEX(data); + pagetable0_t *r0 = r1->meta0[i]; + if (!r0) + return NULL; + i = REGION0_INDEX(data); + return r0->meta[i]; } -STATIC_INLINE jl_gc_pagemeta_t *page_metadata(void *_data) +struct jl_gc_metadata_ext { + pagetable1_t *pagetable1; + pagetable0_t *pagetable0; + jl_gc_pagemeta_t *meta; + unsigned pagetable_i32, pagetable_i; + unsigned pagetable1_i32, pagetable1_i; + unsigned pagetable0_i32, pagetable0_i; +}; + +STATIC_INLINE struct jl_gc_metadata_ext page_metadata_ext(void *_data) { - uintptr_t data = ((uintptr_t)_data) - 1; - for (int i = 0; i < REGION_COUNT && regions[i].pages; i++) { - region_t *region = ®ions[i]; - uintptr_t begin = (uintptr_t)region->pages->data; - uintptr_t offset = data - begin; - if (offset < region->pg_cnt * sizeof(jl_gc_page_t)) { - return ®ion->meta[offset >> GC_PAGE_LG2]; - } - } - return NULL; + uintptr_t data = (uintptr_t)_data; + struct jl_gc_metadata_ext info; + unsigned i; + i = REGION_INDEX(data); + info.pagetable_i = i % 32; + info.pagetable_i32 = i / 32; + info.pagetable1 = memory_map.meta1[i]; + i = REGION1_INDEX(data); + info.pagetable1_i = i % 32; + info.pagetable1_i32 = i / 32; + info.pagetable0 = info.pagetable1->meta0[i]; + i = REGION0_INDEX(data); + info.pagetable0_i = i % 32; + info.pagetable0_i32 = i / 32; + info.meta = info.pagetable0->meta[i]; + assert(info.meta); + return info; } STATIC_INLINE void gc_big_object_unlink(const bigval_t *hdr) @@ -285,7 +352,7 @@ void jl_mark_box_caches(jl_ptls_t ptls); // GC pages void jl_gc_init_page(void); -NOINLINE void *jl_gc_alloc_page(void); +NOINLINE jl_gc_pagemeta_t *jl_gc_alloc_page(void); void jl_gc_free_page(void *p); // GC debug From ba78546b511cc34ee22a0556f4e68bddbb481320 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Tue, 18 Apr 2017 16:35:03 +0200 Subject: [PATCH 0456/1534] inline mod1 (#21409) --- base/operators.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/operators.jl b/base/operators.jl index bd8eceffbe108..b6ea643d310fd 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -641,7 +641,7 @@ julia> mod1(4, 3) """ mod1{T<:Real}(x::T, y::T) = (m = mod(x, y); ifelse(m == 0, y, m)) # efficient version for integers -mod1{T<:Integer}(x::T, y::T) = mod(x + y - T(1), y) + T(1) +mod1{T<:Integer}(x::T, y::T) = (@_inline_meta; mod(x + y - T(1), y) + T(1)) """ From 7f262469bbeb95746a7ae872bd2120eb9bb43a44 Mon Sep 17 00:00:00 2001 From: Mus M Date: Tue, 18 Apr 2017 11:39:46 -0400 Subject: [PATCH 0457/1534] Use new where syntax for a couple of misc methods (#21415) * Use new where syntax for eltype * New where syntax for some size methods * New where syntax for copy mehods --- base/abstractarray.jl | 6 +++--- base/array.jl | 14 +++++++------- base/associative.jl | 6 +++--- base/channels.jl | 2 +- base/dft.jl | 2 +- base/iterators.jl | 34 +++++++++++++++++----------------- base/multidimensional.jl | 2 +- base/nullable.jl | 2 +- base/number.jl | 2 +- base/permuteddimsarray.jl | 4 ++-- base/pointer.jl | 2 +- base/set.jl | 2 +- base/twiceprecision.jl | 2 +- 13 files changed, 40 insertions(+), 40 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index e2ec40b8f11e6..5a839d9826185 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -19,8 +19,8 @@ julia> size(A,3,2) (4, 3) ``` """ -size{T,N}(t::AbstractArray{T,N}, d) = d <= N ? size(t)[d] : 1 -size{N}(x, d1::Integer, d2::Integer, dx::Vararg{Integer, N}) = +size(t::AbstractArray{T,N}, d) where {T,N} = d <= N ? size(t)[d] : 1 +size(x, d1::Integer, d2::Integer, dx::Vararg{Integer, N}) where {N} = (size(x, d1), size(x, d2), ntuple(k->size(x, dx[k]), Val{N})...) """ @@ -91,7 +91,7 @@ julia> extrema(b) linearindices(A) = (@_inline_meta; OneTo(_length(A))) linearindices(A::AbstractVector) = (@_inline_meta; indices1(A)) eltype(::Type{<:AbstractArray{E}}) where {E} = E -elsize{T}(::AbstractArray{T}) = sizeof(T) +elsize(::AbstractArray{T}) where {T} = sizeof(T) """ ndims(A::AbstractArray) -> Integer diff --git a/base/array.jl b/base/array.jl index 236cefd4c5903..5ef169180bc66 100644 --- a/base/array.jl +++ b/base/array.jl @@ -74,8 +74,8 @@ size(a::Array, d) = arraysize(a, d) size(a::Vector) = (arraysize(a,1),) size(a::Matrix) = (arraysize(a,1), arraysize(a,2)) size(a::Array) = (@_inline_meta; _size((), a)) -_size{_,N}(out::NTuple{N}, A::Array{_,N}) = out -function _size{_,M,N}(out::NTuple{M}, A::Array{_,N}) +_size(out::NTuple{N}, A::Array{_,N}) where {_,N} = out +function _size(out::NTuple{M}, A::Array{_,N}) where _ where M where N @_inline_meta _size((out..., size(A,M+1)), A) end @@ -83,7 +83,7 @@ end asize_from(a::Array, n) = n > ndims(a) ? () : (arraysize(a,n), asize_from(a, n+1)...) length(a::Array) = arraylen(a) -elsize{T}(a::Array{T}) = isbits(T) ? sizeof(T) : sizeof(Ptr) +elsize(a::Array{T}) where {T} = isbits(T) ? sizeof(T) : sizeof(Ptr) sizeof(a::Array) = elsize(a) * length(a) function isassigned(a::Array, i::Int...) @@ -94,7 +94,7 @@ end ## copy ## -function unsafe_copy!{T}(dest::Ptr{T}, src::Ptr{T}, n) +function unsafe_copy!(dest::Ptr{T}, src::Ptr{T}, n) where T # Do not use this to copy data between pointer arrays. # It can't be made safe no matter how carefully you checked. ccall(:memmove, Ptr{Void}, (Ptr{Void}, Ptr{Void}, UInt), @@ -102,7 +102,7 @@ function unsafe_copy!{T}(dest::Ptr{T}, src::Ptr{T}, n) return dest end -function unsafe_copy!{T}(dest::Array{T}, doffs, src::Array{T}, soffs, n) +function unsafe_copy!(dest::Array{T}, doffs, src::Array{T}, soffs, n) where T if isbits(T) unsafe_copy!(pointer(dest, doffs), pointer(src, soffs), n) else @@ -121,9 +121,9 @@ function copy!{T}(dest::Array{T}, doffs::Integer, src::Array{T}, soffs::Integer, unsafe_copy!(dest, doffs, src, soffs, n) end -copy!{T}(dest::Array{T}, src::Array{T}) = copy!(dest, 1, src, 1, length(src)) +copy!(dest::Array{T}, src::Array{T}) where {T} = copy!(dest, 1, src, 1, length(src)) -copy{T<:Array}(a::T) = ccall(:jl_array_copy, Ref{T}, (Any,), a) +copy(a::T) where {T<:Array} = ccall(:jl_array_copy, Ref{T}, (Any,), a) function reinterpret{T,S}(::Type{T}, a::Array{S,1}) nel = Int(div(length(a)*sizeof(S),sizeof(T))) diff --git a/base/associative.jl b/base/associative.jl index 896e62d12e8cb..1815f03bc3517 100644 --- a/base/associative.jl +++ b/base/associative.jl @@ -41,8 +41,8 @@ length(v::Union{KeyIterator,ValueIterator}) = length(v.dict) isempty(v::Union{KeyIterator,ValueIterator}) = isempty(v.dict) _tt1{A,B}(::Type{Pair{A,B}}) = A _tt2{A,B}(::Type{Pair{A,B}}) = B -eltype{D}(::Type{KeyIterator{D}}) = _tt1(eltype(D)) -eltype{D}(::Type{ValueIterator{D}}) = _tt2(eltype(D)) +eltype(::Type{KeyIterator{D}}) where {D} = _tt1(eltype(D)) +eltype(::Type{ValueIterator{D}}) where {D} = _tt2(eltype(D)) start(v::Union{KeyIterator,ValueIterator}) = start(v.dict) done(v::Union{KeyIterator,ValueIterator}, state) = done(v.dict, state) @@ -318,7 +318,7 @@ function filter(f, d::Associative) return df end -eltype{K,V}(::Type{Associative{K,V}}) = Pair{K,V} +eltype(::Type{Associative{K,V}}) where {K,V} = Pair{K,V} function isequal(l::Associative, r::Associative) l === r && return true diff --git a/base/channels.jl b/base/channels.jl index 92f98a47231a2..a6c8859b20abe 100644 --- a/base/channels.jl +++ b/base/channels.jl @@ -380,7 +380,7 @@ function notify_error(c::Channel, err) end notify_error(c::Channel) = notify_error(c, get(c.excp)) -eltype{T}(::Type{Channel{T}}) = T +eltype(::Type{Channel{T}}) where {T} = T show(io::IO, c::Channel) = print(io, "$(typeof(c))(sz_max:$(c.sz_max),sz_curr:$(n_avail(c)))") diff --git a/base/dft.jl b/base/dft.jl index e846ff54f335c..39857d3905dd1 100644 --- a/base/dft.jl +++ b/base/dft.jl @@ -8,7 +8,7 @@ abstract type Plan{T} end import Base: show, summary, size, ndims, length, eltype, *, A_mul_B!, inv, \, A_ldiv_B! -eltype{T}(::Type{Plan{T}}) = T +eltype(::Type{Plan{T}}) where {T} = T # size(p) should return the size of the input array for p size(p::Plan, d) = size(p)[d] diff --git a/base/iterators.jl b/base/iterators.jl index 6ad54b5cd00cf..e9c2426079ff8 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -65,7 +65,7 @@ size(e::Enumerate) = size(e.itr) end @inline done(e::Enumerate, state) = done(e.itr, state[2]) -eltype{I}(::Type{Enumerate{I}}) = Tuple{Int, eltype(I)} +eltype(::Type{Enumerate{I}}) where {I} = Tuple{Int, eltype(I)} iteratorsize{I}(::Type{Enumerate{I}}) = iteratorsize(I) iteratoreltype{I}(::Type{Enumerate{I}}) = iteratoreltype(I) @@ -135,7 +135,7 @@ size(v::IndexValue) = size(v.itr) end @inline done(v::IndexValue, state) = done(v.itr, state) -eltype{I,A}(::Type{IndexValue{I,A}}) = Tuple{eltype(I), eltype(A)} +eltype(::Type{IndexValue{I,A}}) where {I,A} = Tuple{eltype(I), eltype(A)} iteratorsize{I}(::Type{IndexValue{I}}) = iteratorsize(I) iteratoreltype{I}(::Type{IndexValue{I}}) = iteratoreltype(I) @@ -158,7 +158,7 @@ zip(a) = Zip1(a) length(z::Zip1) = length(z.a) size(z::Zip1) = size(z.a) indices(z::Zip1) = indices(z.a) -eltype{I}(::Type{Zip1{I}}) = Tuple{eltype(I)} +eltype(::Type{Zip1{I}}) where {I} = Tuple{eltype(I)} @inline start(z::Zip1) = start(z.a) @inline function next(z::Zip1, st) n = next(z.a,st) @@ -177,7 +177,7 @@ zip(a, b) = Zip2(a, b) length(z::Zip2) = _min_length(z.a, z.b, iteratorsize(z.a), iteratorsize(z.b)) size(z::Zip2) = promote_shape(size(z.a), size(z.b)) indices(z::Zip2) = promote_shape(indices(z.a), indices(z.b)) -eltype{I1,I2}(::Type{Zip2{I1,I2}}) = Tuple{eltype(I1), eltype(I2)} +eltype(::Type{Zip2{I1,I2}}) where {I1,I2} = Tuple{eltype(I1), eltype(I2)} @inline start(z::Zip2) = (start(z.a), start(z.b)) @inline function next(z::Zip2, st) n1 = next(z.a,st[1]) @@ -228,7 +228,7 @@ zip(a, b, c...) = Zip(a, zip(b, c...)) length(z::Zip) = _min_length(z.a, z.z, iteratorsize(z.a), iteratorsize(z.z)) size(z::Zip) = promote_shape(size(z.a), size(z.z)) indices(z::Zip) = promote_shape(indices(z.a), indices(z.z)) -eltype{I,Z}(::Type{Zip{I,Z}}) = tuple_type_cons(eltype(I), eltype(Z)) +eltype(::Type{Zip{I,Z}}) where {I,Z} = tuple_type_cons(eltype(I), eltype(Z)) @inline start(z::Zip) = tuple(start(z.a), start(z.z)) @inline function next(z::Zip, st) n1 = next(z.a, st[1]) @@ -277,7 +277,7 @@ end done(f::Filter, s) = s[1] -eltype{F,I}(::Type{Filter{F,I}}) = eltype(I) +eltype(::Type{Filter{F,I}}) where {F,I} = eltype(I) iteratoreltype{F,I}(::Type{Filter{F,I}}) = iteratoreltype(I) iteratorsize(::Type{<:Filter}) = SizeUnknown() @@ -299,7 +299,7 @@ start(i::Rest) = i.st next(i::Rest, st) = next(i.itr, st) done(i::Rest, st) = done(i.itr, st) -eltype{I}(::Type{Rest{I}}) = eltype(I) +eltype(::Type{Rest{I}}) where {I} = eltype(I) iteratoreltype{I,S}(::Type{Rest{I,S}}) = iteratoreltype(I) rest_iteratorsize(a) = SizeUnknown() rest_iteratorsize(::IsInfinite) = IsInfinite() @@ -322,7 +322,7 @@ countfrom(start::Number, step::Number) = Count(promote(start, step)...) countfrom(start::Number) = Count(start, oneunit(start)) countfrom() = Count(1, 1) -eltype{S}(::Type{Count{S}}) = S +eltype(::Type{Count{S}}) where {S} = S start(it::Count) = it.start next(it::Count, state) = (state, state + it.step) @@ -365,7 +365,7 @@ julia> collect(Iterators.take(a,3)) take(xs, n::Integer) = Take(xs, Int(n)) take(xs::Take, n::Integer) = Take(xs.xs, min(Int(n), xs.n)) -eltype{I}(::Type{Take{I}}) = eltype(I) +eltype(::Type{Take{I}}) where {I} = eltype(I) iteratoreltype{I}(::Type{Take{I}}) = iteratoreltype(I) take_iteratorsize(a) = HasLength() take_iteratorsize(::SizeUnknown) = SizeUnknown() @@ -420,7 +420,7 @@ drop(xs, n::Integer) = Drop(xs, Int(n)) drop(xs::Take, n::Integer) = Take(drop(xs.xs, Int(n)), max(0, xs.n - Int(n))) drop(xs::Drop, n::Integer) = Drop(xs.xs, Int(n) + xs.n) -eltype{I}(::Type{Drop{I}}) = eltype(I) +eltype(::Type{Drop{I}}) where {I} = eltype(I) iteratoreltype{I}(::Type{Drop{I}}) = iteratoreltype(I) drop_iteratorsize(::SizeUnknown) = SizeUnknown() drop_iteratorsize(::Union{HasShape, HasLength}) = HasLength() @@ -456,7 +456,7 @@ An iterator that cycles through `iter` forever. """ cycle(xs) = Cycle(xs) -eltype{I}(::Type{Cycle{I}}) = eltype(I) +eltype(::Type{Cycle{I}}) where {I} = eltype(I) iteratoreltype{I}(::Type{Cycle{I}}) = iteratoreltype(I) iteratorsize{I}(::Type{Cycle{I}}) = IsInfinite() @@ -503,7 +503,7 @@ julia> collect(a) """ repeated(x, n::Integer) = take(repeated(x), Int(n)) -eltype{O}(::Type{Repeated{O}}) = O +eltype(::Type{Repeated{O}}) where {O} = O start(it::Repeated) = nothing next(it::Repeated, state) = (it.x, nothing) @@ -552,7 +552,7 @@ struct Prod1{I} <: AbstractProdIterator end product(a) = Prod1(a) -eltype{I}(::Type{Prod1{I}}) = Tuple{eltype(I)} +eltype(::Type{Prod1{I}}) where {I} = Tuple{eltype(I)} size(p::Prod1) = _prod_size(p.a, iteratorsize(p.a)) indices(p::Prod1) = _prod_indices(p.a, iteratorsize(p.a)) @@ -588,7 +588,7 @@ julia> collect(Iterators.product(1:2,3:5)) """ product(a, b) = Prod2(a, b) -eltype{I1,I2}(::Type{Prod2{I1,I2}}) = Tuple{eltype(I1), eltype(I2)} +eltype(::Type{Prod2{I1,I2}}) where {I1,I2} = Tuple{eltype(I1), eltype(I2)} iteratoreltype{I1,I2}(::Type{Prod2{I1,I2}}) = and_iteratoreltype(iteratoreltype(I1),iteratoreltype(I2)) iteratorsize{I1,I2}(::Type{Prod2{I1,I2}}) = prod_iteratorsize(iteratorsize(I1),iteratorsize(I2)) @@ -625,7 +625,7 @@ struct Prod{I1, I2<:AbstractProdIterator} <: AbstractProdIterator end product(a, b, c...) = Prod(a, product(b, c...)) -eltype{I1,I2}(::Type{Prod{I1,I2}}) = tuple_type_cons(eltype(I1), eltype(I2)) +eltype(::Type{Prod{I1,I2}}) where {I1,I2} = tuple_type_cons(eltype(I1), eltype(I2)) iteratoreltype{I1,I2}(::Type{Prod{I1,I2}}) = and_iteratoreltype(iteratoreltype(I1),iteratoreltype(I2)) iteratorsize{I1,I2}(::Type{Prod{I1,I2}}) = prod_iteratorsize(iteratorsize(I1),iteratorsize(I2)) @@ -667,7 +667,7 @@ julia> collect(Iterators.flatten((1:2, 8:9))) """ flatten(itr) = Flatten(itr) -eltype{I}(::Type{Flatten{I}}) = eltype(eltype(I)) +eltype(::Type{Flatten{I}}) where {I} = eltype(eltype(I)) iteratorsize{I}(::Type{Flatten{I}}) = SizeUnknown() iteratoreltype{I}(::Type{Flatten{I}}) = _flatteneltype(I, iteratoreltype(I)) _flatteneltype(I, ::HasEltype) = iteratoreltype(eltype(I)) @@ -725,7 +725,7 @@ mutable struct PartitionIterator{T} n::Int end -eltype{T}(::Type{PartitionIterator{T}}) = Vector{eltype(T)} +eltype(::Type{PartitionIterator{T}}) where {T} = Vector{eltype(T)} function length(itr::PartitionIterator) l = length(itr.c) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 80ff5db6f46be..e519f293c834d 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -146,7 +146,7 @@ module IteratorsMD @inline maxt(a::Tuple, b::Tuple{}) = a @inline maxt(a::Tuple, b::Tuple) = (max(a[1], b[1]), maxt(tail(a), tail(b))...) - eltype{I}(::Type{CartesianRange{I}}) = I + eltype(::Type{CartesianRange{I}}) where {I} = I iteratorsize(::Type{<:CartesianRange}) = Base.HasShape() @inline function start(iter::CartesianRange{<:CartesianIndex}) diff --git a/base/nullable.jl b/base/nullable.jl index 911a038273478..478e41da2d058 100644 --- a/base/nullable.jl +++ b/base/nullable.jl @@ -34,7 +34,7 @@ Nullable{Int64} Nullable{T}(value::T, hasvalue::Bool=true) = Nullable{T}(value, hasvalue) Nullable() = Nullable{Union{}}() -eltype{T}(::Type{Nullable{T}}) = T +eltype(::Type{Nullable{T}}) where {T} = T convert(::Type{Nullable{T}}, x::Nullable{T}) where {T} = x convert(::Type{Nullable }, x::Nullable ) = x diff --git a/base/number.jl b/base/number.jl index 687d76d59a115..bd5deb2bca776 100644 --- a/base/number.jl +++ b/base/number.jl @@ -25,7 +25,7 @@ size(x::Number) = () size(x::Number,d) = convert(Int,d)<1 ? throw(BoundsError()) : 1 indices(x::Number) = () indices(x::Number,d) = convert(Int,d)<1 ? throw(BoundsError()) : OneTo(1) -eltype{T<:Number}(::Type{T}) = T +eltype(::Type{T}) where {T<:Number} = T ndims(x::Number) = 0 ndims(::Type{<:Number}) = 0 length(x::Number) = 1 diff --git a/base/permuteddimsarray.jl b/base/permuteddimsarray.jl index eb80321fbca39..506b4c4a43b6b 100644 --- a/base/permuteddimsarray.jl +++ b/base/permuteddimsarray.jl @@ -46,8 +46,8 @@ function PermutedDimsArray(data::AbstractArray{T,N}, perm) where {T,N} end Base.parent(A::PermutedDimsArray) = A.parent -Base.size{T,N,perm}(A::PermutedDimsArray{T,N,perm}) = genperm(size(parent(A)), perm) -Base.indices{T,N,perm}(A::PermutedDimsArray{T,N,perm}) = genperm(indices(parent(A)), perm) +Base.size(A::PermutedDimsArray{T,N,perm}) where {T,N,perm} = genperm(size(parent(A)), perm) +Base.indices(A::PermutedDimsArray{T,N,perm}) where {T,N,perm} = genperm(indices(parent(A)), perm) Base.unsafe_convert{T}(::Type{Ptr{T}}, A::PermutedDimsArray{T}) = Base.unsafe_convert(Ptr{T}, parent(A)) diff --git a/base/pointer.jl b/base/pointer.jl index 5819a2fa6429f..4f14eb562431b 100644 --- a/base/pointer.jl +++ b/base/pointer.jl @@ -115,7 +115,7 @@ remains referenced for the whole time that the `Ptr` will be used. pointer_from_objref(x::ANY) = ccall(:jl_value_ptr, Ptr{Void}, (Any,), x) data_pointer_from_objref(x::ANY) = pointer_from_objref(x)::Ptr{Void} -eltype{T}(::Type{Ptr{T}}) = T +eltype(::Type{Ptr{T}}) where {T} = T ## limited pointer arithmetic & comparison ## diff --git a/base/set.jl b/base/set.jl index c97dd61a88d27..eae1e45a53402 100644 --- a/base/set.jl +++ b/base/set.jl @@ -14,7 +14,7 @@ function Set(g::Generator) return Set{T}(g) end -eltype{T}(::Type{Set{T}}) = T +eltype(::Type{Set{T}}) where {T} = T similar{T}(s::Set{T}) = Set{T}() similar(s::Set, T::Type) = Set{T}() diff --git a/base/twiceprecision.jl b/base/twiceprecision.jl index 1504aa1f2eb21..74f0829a49261 100644 --- a/base/twiceprecision.jl +++ b/base/twiceprecision.jl @@ -60,7 +60,7 @@ nbitslen(::Type{Float32}, len, offset) = min(12, nbitslen(len, offset)) nbitslen(::Type{Float16}, len, offset) = min(5, nbitslen(len, offset)) nbitslen(len, offset) = len < 2 ? 0 : ceil(Int, log2(max(offset-1, len-offset))) -eltype{T}(::Type{TwicePrecision{T}}) = T +eltype(::Type{TwicePrecision{T}}) where {T} = T promote_rule{R,S}(::Type{TwicePrecision{R}}, ::Type{TwicePrecision{S}}) = TwicePrecision{promote_type(R,S)} From b0c708424b962be47efc818b40d5d8815acf215c Mon Sep 17 00:00:00 2001 From: George Date: Tue, 18 Apr 2017 20:33:19 +0300 Subject: [PATCH 0458/1534] Improve perf of Diagonal' * Vector|Matrix (#21302) Includes tests Only addresses diagonal part of 21286, not sparse matrices --- base/linalg/diagonal.jl | 10 ++++++++++ test/linalg/diagonal.jl | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/base/linalg/diagonal.jl b/base/linalg/diagonal.jl index 66fe02e8f5e99..421328e9a1044 100644 --- a/base/linalg/diagonal.jl +++ b/base/linalg/diagonal.jl @@ -225,6 +225,16 @@ A_mul_B!(A::AbstractMatrix,B::Diagonal) = scale!(A,B.diag) A_mul_Bt!(A::AbstractMatrix,B::Diagonal) = scale!(A,B.diag) A_mul_Bc!(A::AbstractMatrix,B::Diagonal) = scale!(A,conj(B.diag)) +# Get ambiguous method if try to unify AbstractVector/AbstractMatrix here using AbstractVecOrMat +A_mul_B!(out::AbstractVector, A::Diagonal, in::AbstractVector) = out .= A.diag .* in +Ac_mul_B!(out::AbstractVector, A::Diagonal, in::AbstractVector) = out .= ctranspose.(A.diag) .* in +At_mul_B!(out::AbstractVector, A::Diagonal, in::AbstractVector) = out .= transpose.(A.diag) .* in + +A_mul_B!(out::AbstractMatrix, A::Diagonal, in::AbstractMatrix) = out .= A.diag .* in +Ac_mul_B!(out::AbstractMatrix, A::Diagonal, in::AbstractMatrix) = out .= ctranspose.(A.diag) .* in +At_mul_B!(out::AbstractMatrix, A::Diagonal, in::AbstractMatrix) = out .= transpose.(A.diag) .* in + + /(Da::Diagonal, Db::Diagonal) = Diagonal(Da.diag ./ Db.diag) function A_ldiv_B!{T}(D::Diagonal{T}, v::AbstractVector{T}) if length(v) != length(D.diag) diff --git a/test/linalg/diagonal.jl b/test/linalg/diagonal.jl index 502adf31c408c..a1ae78ed41eef 100644 --- a/test/linalg/diagonal.jl +++ b/test/linalg/diagonal.jl @@ -137,6 +137,17 @@ srand(1) #division of two Diagonals @test D/D2 ≈ Diagonal(D.diag./D2.diag) @test D\D2 ≈ Diagonal(D2.diag./D.diag) + + # Performance specialisations for A*_mul_B! + vv = similar(v) + @test (r = full(D) * v ; A_mul_B!(vv, D, v) ≈ r ≈ vv) + @test (r = full(D)' * v ; Ac_mul_B!(vv, D, v) ≈ r ≈ vv) + @test (r = full(D).' * v ; At_mul_B!(vv, D, v) ≈ r ≈ vv) + + UU = similar(U) + @test (r = full(D) * U ; A_mul_B!(UU, D, U) ≈ r ≈ UU) + @test (r = full(D)' * U ; Ac_mul_B!(UU, D, U) ≈ r ≈ UU) + @test (r = full(D).' * U ; At_mul_B!(UU, D, U) ≈ r ≈ UU) end @testset "triu/tril" begin @test istriu(D) @@ -177,6 +188,9 @@ srand(1) @test Array(conj(D)) ≈ conj(DM) @test ctranspose(D) == conj(D) end + # Translates to Ac/t_mul_B, which is specialized after issue 21286 + @test(D' * v == conj(D) * v) + @test(D.' * v == D * v) end #logdet @@ -316,6 +330,10 @@ end @test Dsym' == Diagonal([[1 1-im; 1-im 1], [1 1-im; 1-im 1]]) @test Dsym.' == Dsym + v = [[1, 2], [3, 4]] + @test Dherm' * v == Dherm * v + @test D.' * v == [[7, 10], [15, 22]] + @test issymmetric(D) == false @test issymmetric(Dherm) == false @test issymmetric(Dsym) == true From b61689344cad8c6265701c9d2228baef41d4c45b Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Tue, 11 Apr 2017 10:22:20 -0400 Subject: [PATCH 0459/1534] Protect DWARF lookup with codegen lock LLVM is not thread safe (at least we build it don't way), so we need to make sure we can't possibly be accessing LLVM simulateneously on different threads. The easiest way to ensure that is to lock this with the codegen lock. --- src/debuginfo.cpp | 6 +++++- src/julia_threads.h | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/debuginfo.cpp b/src/debuginfo.cpp index aca5b74e6b978..a503b23487937 100644 --- a/src/debuginfo.cpp +++ b/src/debuginfo.cpp @@ -761,6 +761,7 @@ static int lookup_pointer(DIContext *context, jl_frame_t **frames, } return 1; } + jl_mutex_lock_maybe_nogc(&codegen_lock); #if JL_LLVM_VERSION >= 30500 DILineInfoSpecifier infoSpec(DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, DILineInfoSpecifier::FunctionNameKind::ShortName); @@ -774,9 +775,11 @@ static int lookup_pointer(DIContext *context, jl_frame_t **frames, int fromC = (*frames)[0].fromC; int n_frames = inlineInfo.getNumberOfFrames(); - if (n_frames == 0) + if (n_frames == 0) { + jl_mutex_unlock_maybe_nogc(&codegen_lock); // no line number info available in the context, return without the context return lookup_pointer(NULL, frames, pointer, demangle, noInline); + } if (noInline) n_frames = 1; if (n_frames > 1) { @@ -834,6 +837,7 @@ static int lookup_pointer(DIContext *context, jl_frame_t **frames, else jl_copy_str(&frame->file_name, file_name.c_str()); } + jl_mutex_unlock_maybe_nogc(&codegen_lock); return n_frames; } diff --git a/src/julia_threads.h b/src/julia_threads.h index 6a0e6923c17af..b8c9087076efb 100644 --- a/src/julia_threads.h +++ b/src/julia_threads.h @@ -557,6 +557,18 @@ static inline void jl_mutex_lock(jl_mutex_t *lock) jl_gc_enable_finalizers(ptls, 0); } +/* Call this function for code that could be called from either a managed + or an unmanaged thread */ +static inline void jl_mutex_lock_maybe_nogc(jl_mutex_t *lock) +{ + jl_ptls_t ptls = jl_get_ptls_states(); + if (ptls->safepoint) { + jl_mutex_lock(lock); + } else { + jl_mutex_lock_nogc(lock); + } +} + static inline void jl_mutex_unlock_nogc(jl_mutex_t *lock) { assert(lock->owner == jl_thread_self() && @@ -576,6 +588,15 @@ static inline void jl_mutex_unlock(jl_mutex_t *lock) JL_SIGATOMIC_END(); } +static inline void jl_mutex_unlock_maybe_nogc(jl_mutex_t *lock) { + jl_ptls_t ptls = jl_get_ptls_states(); + if (ptls->safepoint) { + jl_mutex_unlock(lock); + } else { + jl_mutex_unlock_nogc(lock); + } +} + static inline void jl_mutex_init(jl_mutex_t *lock) { lock->owner = 0; From 085876ee900285a62991aa477ef9212403c5173f Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Tue, 18 Apr 2017 21:04:37 -0400 Subject: [PATCH 0460/1534] Update src to work with latest LLVM 5. (#21366) Define using integerPart = llvm::APInt::WordType. Define integerPartWidth for now. Should eventually become lvm::APInt::APINT_BITS_PER_WORD. See https://github.com/llvm-mirror/llvm/commit/6b60db9e917fdc394d19a990d49563fce37d4c25 AllocaInst now requires an addrspace argument. See https://github.com/llvm-mirror/llvm/commit/e1b3c335a27ae50c4f339ffb81c18662bc983e52 --- src/APInt-C.cpp | 5 +++++ src/APInt-C.h | 4 ++++ src/codegen.cpp | 16 +++++++++++++++- src/llvm-gcroot.cpp | 8 ++++++++ 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/APInt-C.cpp b/src/APInt-C.cpp index 07868aee1506d..c911c8586c459 100644 --- a/src/APInt-C.cpp +++ b/src/APInt-C.cpp @@ -19,6 +19,11 @@ inline uint64_t RoundUpToAlignment(uint64_t Value, uint64_t Align, uint64_t Skew } #endif +#if JL_LLVM_VERSION >= 50000 +const unsigned int integerPartWidth = llvm::APInt::APINT_BITS_PER_WORD; +const unsigned int host_char_bit = 8; +#endif + /* create "APInt s" from "integerPart *ps" */ #define CREATE(s) \ APInt s; \ diff --git a/src/APInt-C.h b/src/APInt-C.h index af0a778ddfc5e..2228c274cd11a 100644 --- a/src/APInt-C.h +++ b/src/APInt-C.h @@ -9,7 +9,11 @@ extern "C" { #include "dtypes.h" #ifdef LLVM_VERSION_MAJOR +# if JL_LLVM_VERSION >= 50000 +using integerPart = llvm::APInt::WordType; +# else using llvm::integerPart; +# endif #else typedef void integerPart; #endif diff --git a/src/codegen.cpp b/src/codegen.cpp index 1f31875dd9e8e..af7d2579da71d 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -686,7 +686,11 @@ static GlobalVariable *get_pointer_to_constant(Constant *val, StringRef name, Mo static AllocaInst *emit_static_alloca(Type *lty, int arraysize, jl_codectx_t *ctx) { +#if JL_LLVM_VERSION >= 50000 + return new AllocaInst(lty, 0, ConstantInt::get(T_int32, arraysize), "", /*InsertBefore=*/ctx->ptlsStates); +#else return new AllocaInst(lty, ConstantInt::get(T_int32, arraysize), "", /*InsertBefore=*/ctx->ptlsStates); +#endif } static AllocaInst *emit_static_alloca(Type *lty, jl_codectx_t *ctx) { @@ -694,8 +698,13 @@ static AllocaInst *emit_static_alloca(Type *lty, jl_codectx_t *ctx) } static AllocaInst *emit_static_alloca(Type *lty) { +#if JL_LLVM_VERSION >= 50000 + return new AllocaInst(lty, 0, "", + /*InsertBefore=*/&*builder.GetInsertBlock()->getParent()->getEntryBlock().getFirstInsertionPt()); +#else return new AllocaInst(lty, "", /*InsertBefore=*/&*builder.GetInsertBlock()->getParent()->getEntryBlock().getFirstInsertionPt()); +#endif } static inline jl_cgval_t ghostValue(jl_value_t *typ) @@ -5587,7 +5596,12 @@ static std::unique_ptr emit_function( specsig || // for arguments, give them stack slots if they aren't in `argArray` (otherwise, will use that pointer) (va && (int)i == ctx.vaSlot && varinfo.escapes) || // or it's the va arg tuple (s != unused_sym && i == 0)) { // or it is the first argument (which isn't in `argArray`) - AllocaInst *av = new AllocaInst(T_pjlvalue, jl_symbol_name(s), /*InsertBefore*/ctx.ptlsStates); +#if JL_LLVM_VERSION >= 50000 + AllocaInst *av = new AllocaInst(T_pjlvalue, 0, +#else + AllocaInst *av = new AllocaInst(T_pjlvalue, +#endif + jl_symbol_name(s), /*InsertBefore*/ctx.ptlsStates); varinfo.boxroot = av; #if JL_LLVM_VERSION >= 30600 if (ctx.debug_enabled && varinfo.dinfo) { diff --git a/src/llvm-gcroot.cpp b/src/llvm-gcroot.cpp index 57c34f53e2e50..a23b5d5d7ef71 100644 --- a/src/llvm-gcroot.cpp +++ b/src/llvm-gcroot.cpp @@ -137,7 +137,11 @@ class JuliaGCAllocator { T_int64(Type::getInt64Ty(F.getContext())), V_null(T_pjlvalue ? Constant::getNullValue(T_pjlvalue) : nullptr), ptlsStates(ptlsStates), +#if JL_LLVM_VERSION >= 50000 + gcframe(ptlsStates ? new AllocaInst(T_pjlvalue, 0, ConstantInt::get(T_int32, 0)) : nullptr), +#else gcframe(ptlsStates ? new AllocaInst(T_pjlvalue, ConstantInt::get(T_int32, 0)) : nullptr), +#endif gcroot_func(M.getFunction("julia.gc_root_decl")), gckill_func(M.getFunction("julia.gc_root_kill")), jlcall_frame_func(M.getFunction("julia.jlcall_frame_decl")), @@ -344,7 +348,11 @@ void JuliaGCAllocator::lowerHandlers() Instruction *firstInst = &F.getEntryBlock().front(); while (!handlers.empty()) { processing.clear(); +#if JL_LLVM_VERSION >= 50000 + auto buff = new AllocaInst(T_int8, 0, handler_sz, "", firstInst); +#else auto buff = new AllocaInst(T_int8, handler_sz, "", firstInst); +#endif buff->setAlignment(16); // Collect the list of frames to process. for (auto &hdlr: handlers) { From ece60d08c29c53e8250d4275b40bfd8fa1aa347d Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 17 Apr 2017 19:01:27 -0400 Subject: [PATCH 0461/1534] correct the codegen of floating point subtypes ensures that alignment is consistent in the LLVM struct representation as in the Julia struct representation computation also helps ensure that the floating point NaN payload bits won't accidentally get discarded for non-IEEE-754 subtypes of AbstractFloat fix #21216 --- doc/src/manual/embedding.md | 10 +++++++--- examples/embedding/embedding.c | 14 ++++---------- src/abi_aarch64.cpp | 1 + src/abi_arm.cpp | 2 ++ src/cgutils.cpp | 17 ++++------------- src/intrinsics.cpp | 24 +++++++++++------------- src/julia.h | 4 ---- test/core.jl | 31 +++++++++++++++++++++++++++++++ 8 files changed, 60 insertions(+), 43 deletions(-) diff --git a/doc/src/manual/embedding.md b/doc/src/manual/embedding.md index 7aa1d755ed9d8..14e8d65e79a2f 100644 --- a/doc/src/manual/embedding.md +++ b/doc/src/manual/embedding.md @@ -146,13 +146,17 @@ square root of 2 in Julia and reads back the result in C looks as follows: ``` jl_value_t *ret = jl_eval_string("sqrt(2.0)"); -if (jl_is_float64(ret)) { +if (jl_typeis(ret, jl_float64_type)) { double ret_unboxed = jl_unbox_float64(ret); printf("sqrt(2.0) in C: %e \n", ret_unboxed); } +else { + printf("ERROR: unexpected return type from sqrt(::Float64)\n"); +} ``` -In order to check whether `ret` is of a specific Julia type, we can use the `jl_is_...` functions. +In order to check whether `ret` is of a specific Julia type, we can use the +`jl_isa`, `jl_typeis`, or `jl_is_...` functions. By typing `typeof(sqrt(2.0))` into the Julia shell we can see that the return type is `Float64` (`double` in C). To convert the boxed Julia value into a C double the `jl_unbox_float64` function is used in the above code snippet. @@ -387,7 +391,7 @@ When writing Julia callable functions, it might be necessary to validate argumen to indicate errors. A typical type check looks like: ``` -if (!jl_is_float64(val)) { +if (!jl_typeis(val, jl_float64_type)) { jl_type_error(function_name, (jl_value_t*)jl_float64_type, val); } ``` diff --git a/examples/embedding/embedding.c b/examples/embedding/embedding.c index 3fc8c80d673ec..d0018e2e743c0 100644 --- a/examples/embedding/embedding.c +++ b/examples/embedding/embedding.c @@ -26,11 +26,8 @@ int main() // Accessing the return value jl_value_t *ret = jl_eval_string("sqrt(2.0)"); - - if (jl_is_float64(ret)) { - double retDouble = jl_unbox_float64(ret); - printf("sqrt(2.0) in C: %e\n", retDouble); - } + double retDouble = jl_unbox_float64(ret); + printf("sqrt(2.0) in C: %e\n", retDouble); } { @@ -39,11 +36,8 @@ int main() jl_function_t *func = jl_get_function(jl_base_module, "sqrt"); jl_value_t* argument = jl_box_float64(2.0); jl_value_t* ret = jl_call1(func, argument); - - if (jl_is_float64(ret)) { - double retDouble = jl_unbox_float64(ret); - printf("sqrt(2.0) in C: %e\n", retDouble); - } + double retDouble = jl_unbox_float64(ret); + printf("sqrt(2.0) in C: %e\n", retDouble); } { diff --git a/src/abi_aarch64.cpp b/src/abi_aarch64.cpp index 03938491cf64b..affdb93202001 100644 --- a/src/abi_aarch64.cpp +++ b/src/abi_aarch64.cpp @@ -58,6 +58,7 @@ Type *get_llvm_vectype(jl_datatype_t *dt) const return lltype; } +#define jl_is_floattype(v) jl_subtype(v,(jl_value_t*)jl_floatingpoint_type) Type *get_llvm_fptype(jl_datatype_t *dt) const { // Assume jl_is_datatype(dt) && !jl_is_abstracttype(dt) diff --git a/src/abi_arm.cpp b/src/abi_arm.cpp index feb0bbfedfe11..f2eb01d46745a 100644 --- a/src/abi_arm.cpp +++ b/src/abi_arm.cpp @@ -28,6 +28,8 @@ bool needPassByRef(jl_datatype_t *dt, AttrBuilder &ab) override return false; } +#define jl_is_floattype(v) jl_subtype(v,(jl_value_t*)jl_floatingpoint_type) + Type *get_llvm_fptype(jl_datatype_t *dt) const { // Assume jl_is_datatype(dt) && !jl_is_abstracttype(dt) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index e61e82f9f9fae..1561f7883f1eb 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -402,6 +402,10 @@ static Type *bitstype_to_llvm(jl_value_t *bt) return T_int8; if (bt == (jl_value_t*)jl_long_type) return T_size; + if (bt == (jl_value_t*)jl_float32_type) + return T_float32; + if (bt == (jl_value_t*)jl_float64_type) + return T_float64; if (jl_is_cpointer_type(bt)) { Type *lt = julia_type_to_llvm(jl_tparam0(bt)); if (lt == T_void) @@ -409,19 +413,6 @@ static Type *bitstype_to_llvm(jl_value_t *bt) return PointerType::get(lt, 0); } int nb = jl_datatype_size(bt); - if (jl_is_floattype(bt)) { -#ifndef DISABLE_FLOAT16 - if (nb == 2) - return T_float16; - else -#endif - if (nb == 4) - return T_float32; - else if (nb == 8) - return T_float64; - else if (nb == 16) - return T_float128; - } return Type::getIntNTy(jl_LLVMContext, nb * 8); } diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index 7dd108e7bb4bd..1853abead3452 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -154,8 +154,10 @@ static Value *uint_cnvt(Type *to, Value *x) #endif static Constant *julia_const_to_llvm(void *ptr, jl_value_t *bt) { - // assume `jl_isbits(bt)`. + // assumes `jl_isbits(bt)`. // `ptr` can point to a inline field, do not read the tag from it. + // make sure to return exactly the type specified by + // julia_type_to_llvm as this will be assumed by the callee. if (bt == (jl_value_t*)jl_bool_type) return ConstantInt::get(T_int8, (*(uint8_t*)ptr) ? 1 : 0); @@ -177,22 +179,22 @@ static Constant *julia_const_to_llvm(void *ptr, jl_value_t *bt) } case 2: { uint16_t data16 = *(uint16_t*)ptr; -#ifndef DISABLE_FLOAT16 - if (jl_is_floattype(bt)) - return ConstantFP::get(jl_LLVMContext, LLVM_FP(APFloat::IEEEhalf,APInt(16,data16))); -#endif return ConstantInt::get(T_int16, data16); } case 4: { uint32_t data32 = *(uint32_t*)ptr; - if (jl_is_floattype(bt)) - return ConstantFP::get(jl_LLVMContext, LLVM_FP(APFloat::IEEEsingle,APInt(32,data32))); + if (bt == (jl_value_t*)jl_float32_type) + return ConstantFP::get(jl_LLVMContext, + LLVM_FP(APFloat::IEEEsingle, + APInt(32, data32))); return ConstantInt::get(T_int32, data32); } case 8: { uint64_t data64 = *(uint64_t*)ptr; - if (jl_is_floattype(bt)) - return ConstantFP::get(jl_LLVMContext, LLVM_FP(APFloat::IEEEdouble,APInt(64,data64))); + if (bt == (jl_value_t*)jl_float64_type) + return ConstantFP::get(jl_LLVMContext, + LLVM_FP(APFloat::IEEEdouble, + APInt(64, data64))); return ConstantInt::get(T_int64, data64); } default: @@ -212,10 +214,6 @@ static Constant *julia_const_to_llvm(void *ptr, jl_value_t *bt) else #endif val = APInt(8*nb, ArrayRef(data, nw)); - if (nb == 16 && jl_is_floattype(bt)) { - return ConstantFP::get(jl_LLVMContext,LLVM_FP(APFloat::IEEEquad,val)); - // If we have a floating point type that's not hardware supported, just treat it like an integer for LLVM purposes - } return ConstantInt::get(IntegerType::get(jl_LLVMContext,8*nb),val); } } diff --git a/src/julia.h b/src/julia.h index f5ec511f337d9..d5488e2a8601c 100644 --- a/src/julia.h +++ b/src/julia.h @@ -847,10 +847,6 @@ static inline uint32_t jl_fielddesc_size(int8_t fielddesc_type) #define jl_is_uint16(v) jl_typeis(v,jl_uint16_type) #define jl_is_uint32(v) jl_typeis(v,jl_uint32_type) #define jl_is_uint64(v) jl_typeis(v,jl_uint64_type) -#define jl_is_float(v) jl_isa(v,(jl_value_t*)jl_floatingpoint_type) -#define jl_is_floattype(v) jl_subtype(v,(jl_value_t*)jl_floatingpoint_type) -#define jl_is_float32(v) jl_typeis(v,jl_float32_type) -#define jl_is_float64(v) jl_typeis(v,jl_float64_type) #define jl_is_bool(v) jl_typeis(v,jl_bool_type) #define jl_is_symbol(v) jl_typeis(v,jl_sym_type) #define jl_is_ssavalue(v) jl_typeis(v,jl_ssavalue_type) diff --git a/test/core.jl b/test/core.jl index 1ab108579bb9b..72b1a5195ec6d 100644 --- a/test/core.jl +++ b/test/core.jl @@ -4825,3 +4825,34 @@ f21271(x) = x::Tuple{Type{Int}, Type{Float64}} bar21397(x::T) where {T} = T foo21397(x) = bar21397(x) @test foo21397(Tuple) == DataType + +# issue 21216 +primitive type FP128test <: AbstractFloat 128 end +struct FP128align <: AbstractFloat + i::Int # cause forced misalignment + fp::FP128test +end +let ni128 = sizeof(FP128test) ÷ sizeof(Int), + ns128 = sizeof(FP128align) ÷ sizeof(Int), + nbit = sizeof(Int) * 8, + arr = reinterpret(FP128align, collect(Int, 1:(2 * ns128))), + offset = Base.datatype_alignment(FP128test) ÷ sizeof(Int), + little, + expected + @test sizeof(FP128test) == 16 + @test length(arr) == 2 + @test arr[1].i == 1 + @test arr[2].i == 1 + ns128 + expected = UInt128(0) + for little in ni128:-1:1 + little += offset + expected = (expected << nbit) + little + end + @test arr[1].fp == reinterpret(FP128test, expected) + expected = UInt128(0) + for little in ni128:-1:1 + little += offset + ns128 + expected = (expected << nbit) + little + end + @test reinterpret(UInt128, arr[2].fp) == expected +end From ceccddf2f7853b44b8f86430f7b70e37fb05c820 Mon Sep 17 00:00:00 2001 From: Mus M Date: Wed, 19 Apr 2017 03:01:04 -0400 Subject: [PATCH 0462/1534] Do not use light version of colors by default (#21433) --- base/REPL.jl | 4 ++-- base/version.jl | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/base/REPL.jl b/base/REPL.jl index 7a4eb61b46d6c..229bc76b799b4 100644 --- a/base/REPL.jl +++ b/base/REPL.jl @@ -268,7 +268,7 @@ terminal(r::LineEditREPL) = r.t LineEditREPL(t::TextTerminal, envcolors = false) = LineEditREPL(t, true, - Base.text_colors[:light_green], + Base.text_colors[:green], Base.input_color(), Base.answer_color(), Base.text_colors[:red], @@ -960,7 +960,7 @@ mutable struct StreamREPL <: AbstractREPL waserror::Bool StreamREPL(stream,pc,ic,ac) = new(stream,pc,ic,ac,false) end -StreamREPL(stream::IO) = StreamREPL(stream, Base.text_colors[:light_green], Base.input_color(), Base.answer_color()) +StreamREPL(stream::IO) = StreamREPL(stream, Base.text_colors[:green], Base.input_color(), Base.answer_color()) run_repl(stream::IO) = run_repl(StreamREPL(stream)) outstream(s::StreamREPL) = s.stream diff --git a/base/version.jl b/base/version.jl index 956763ce27344..39f7bee2ef62c 100644 --- a/base/version.jl +++ b/base/version.jl @@ -248,10 +248,10 @@ function banner(io::IO = STDOUT) c = text_colors tx = c[:normal] # text jl = c[:normal] # julia - d1 = c[:bold] * c[:light_blue] # first dot - d2 = c[:bold] * c[:light_red] # second dot - d3 = c[:bold] * c[:light_green] # third dot - d4 = c[:bold] * c[:light_magenta] # fourth dot + d1 = c[:bold] * c[:blue] # first dot + d2 = c[:bold] * c[:red] # second dot + d3 = c[:bold] * c[:green] # third dot + d4 = c[:bold] * c[:magenta] # fourth dot print(io,""" $(d3)_$(tx) $(d1)_$(tx) $(jl)_$(tx) $(d2)_$(d3)(_)$(d4)_$(tx) | A fresh approach to technical computing From 109456de61f12875be836deca2948786ebe5d11c Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 18 Apr 2017 21:30:56 -0400 Subject: [PATCH 0463/1534] fix #21155, parse `using` with leading dots and line breaks --- src/julia-parser.scm | 2 +- test/parse.jl | 31 +++++++++++++++++++++++++------ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/julia-parser.scm b/src/julia-parser.scm index afdd40ad2dd46..c6d50a7dfc751 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -1443,7 +1443,7 @@ (define (parse-import-dots s) (let loop ((l '()) - (t (peek-token s))) + (t (require-token s))) ;; skip newlines (cond ((eq? t '|.|) (begin (take-token s) (loop (list* '|.| l) (peek-token s)))) diff --git a/test/parse.jl b/test/parse.jl index 75beb92f6f003..2a96a60876ab2 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -574,13 +574,13 @@ f16517() = try error(); catch 0; end # issue #16671 @test parse("1.") === 1.0 +isline(x) = isa(x,Expr) && x.head === :line + # issue #16672 -let isline(x) = isa(x,Expr) && x.head === :line - @test count(isline, parse("begin end").args) == 1 - @test count(isline, parse("begin; end").args) == 1 - @test count(isline, parse("begin; x+2; end").args) == 1 - @test count(isline, parse("begin; x+2; y+1; end").args) == 2 -end +@test count(isline, parse("begin end").args) == 1 +@test count(isline, parse("begin; end").args) == 1 +@test count(isline, parse("begin; x+2; end").args) == 1 +@test count(isline, parse("begin; x+2; y+1; end").args) == 2 # issue #16736 let @@ -1084,3 +1084,22 @@ let prim = parse("primitive type X 8 end") @test parse("primitive type X 8\nend") == prim @test parse(string("primitive type X 8", "\n"^5, "end")) == prim end + +# issue #21155 +@test filter(!isline, + parse("module B + using ..x, + ..y + end").args[3].args)[1] == + Expr(:toplevel, + Expr(:using, Symbol("."), Symbol("."), :x), + Expr(:using, Symbol("."), Symbol("."), :y)) + +@test filter(!isline, + parse("module A + using .B, + .C + end").args[3].args)[1] == + Expr(:toplevel, + Expr(:using, Symbol("."), :B), + Expr(:using, Symbol("."), :C)) From e3dae81d9661c40bba65ee42164a4d22bf6eb28d Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 19 Apr 2017 13:01:21 -0400 Subject: [PATCH 0464/1534] avoid an extra copy in some cases of `readstring` --- base/iobuffer.jl | 2 +- base/iostream.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/base/iobuffer.jl b/base/iobuffer.jl index d8b584c56a0f9..dd061652a3785 100644 --- a/base/iobuffer.jl +++ b/base/iobuffer.jl @@ -75,7 +75,7 @@ optionally specifying a size beyond which the underlying `Array` may not be grow """ PipeBuffer(data::Vector{UInt8}=UInt8[], maxsize::Int=typemax(Int)) = AbstractIOBuffer(data,true,true,false,true,maxsize) -PipeBuffer(maxsize::Int) = (x = PipeBuffer(Vector{UInt8}(maxsize),maxsize); x.size=0; x) +PipeBuffer(maxsize::Int) = (x = PipeBuffer(StringVector(maxsize),maxsize); x.size=0; x) function copy(b::AbstractIOBuffer) ret = typeof(b)(b.writable ? copy(b.data) : b.data, diff --git a/base/iostream.jl b/base/iostream.jl index c14a5d21b9402..b2474765a2a58 100644 --- a/base/iostream.jl +++ b/base/iostream.jl @@ -287,7 +287,7 @@ function read(s::IOStream) sz -= pos end end - b = Array{UInt8,1}(sz<=0 ? 1024 : sz) + b = StringVector(sz<=0 ? 1024 : sz) nr = readbytes_all!(s, b, typemax(Int)) resize!(b, nr) end From e6f81800de8bd87015aeb7e6bb20a07730c86ebd Mon Sep 17 00:00:00 2001 From: Rory Finnegan Date: Wed, 19 Apr 2017 13:15:14 -0500 Subject: [PATCH 0465/1534] Added kwargs support to `retry`. (#21419) * Added kwargs support to `retry`. * Updated retry example in doc string and added a couple tests. --- base/error.jl | 6 +++--- test/error.jl | 5 +++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/base/error.jl b/base/error.jl index e5d1cb36a7f59..cd2e41b21a6d5 100644 --- a/base/error.jl +++ b/base/error.jl @@ -128,15 +128,15 @@ retry(f, delays=fill(5.0, 3)) retry(f, delays=rand(5:10, 2)) retry(f, delays=Base.ExponentialBackOff(n=3, first_delay=5, max_delay=1000)) retry(http_get, check=(s,e)->e.status == "503")(url) -retry(read, check=(s,e)->isa(e, UVError))(io) +retry(read, check=(s,e)->isa(e, UVError))(io, 128; all=false) ``` """ function retry(f::Function; delays=ExponentialBackOff(), check=nothing) - (args...) -> begin + (args...; kwargs...) -> begin state = start(delays) while true try - return f(args...) + return f(args...; kwargs...) catch e done(delays, state) && rethrow(e) if check !== nothing diff --git a/test/error.jl b/test/error.jl index be9f13e73aee1..4e251f76d93b3 100644 --- a/test/error.jl +++ b/test/error.jl @@ -63,4 +63,9 @@ let @test typeof(ex) == ErrorException @test ex.msg == "foo" @test c[1] == 1 + + # Functions with keyword arguments + foo_kwargs(x; y=5) = x + y + @test retry(foo_kwargs)(3) == 8 + @test retry(foo_kwargs)(3; y=4) == 7 end From 72d264bcfd2344f9ba48cc4a7b4ed4829e9eff07 Mon Sep 17 00:00:00 2001 From: Wonseok Shin Date: Wed, 19 Apr 2017 14:54:02 -0400 Subject: [PATCH 0466/1534] =?UTF-8?q?Add=20inlined=20methods=20for=20ntupl?= =?UTF-8?q?e(f,=20Val{N})=20for=201=20=E2=89=A4=20N=20=E2=89=A4=2010?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- base/tuple.jl | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/base/tuple.jl b/base/tuple.jl index 420a28672096a..6c0a340f94be6 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -123,6 +123,17 @@ end _ntuple(f, n) = (@_noinline_meta; ([f(i) for i = 1:n]...)) # inferrable ntuple +ntuple{F}(f::F, ::Type{Val{1}}) = (@_inline_meta; (f(1),)) +ntuple{F}(f::F, ::Type{Val{2}}) = (@_inline_meta; (f(1), f(2))) +ntuple{F}(f::F, ::Type{Val{3}}) = (@_inline_meta; (f(1), f(2), f(3))) +ntuple{F}(f::F, ::Type{Val{4}}) = (@_inline_meta; (f(1), f(2), f(3), f(4))) +ntuple{F}(f::F, ::Type{Val{5}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5))) +ntuple{F}(f::F, ::Type{Val{6}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6))) +ntuple{F}(f::F, ::Type{Val{7}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7))) +ntuple{F}(f::F, ::Type{Val{8}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8))) +ntuple{F}(f::F, ::Type{Val{9}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9))) +ntuple{F}(f::F, ::Type{Val{10}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10))) + function ntuple{F,N}(f::F, ::Type{Val{N}}) Core.typeassert(N, Int) _ntuple((), f, Val{N}) From 8a3b6c11cd4c90f5eabb86657b9b320fdf8cb801 Mon Sep 17 00:00:00 2001 From: Patrick Kofod Mogensen Date: Wed, 19 Apr 2017 22:45:12 +0200 Subject: [PATCH 0467/1534] Fix sparse right multiplication of Symmetric and Hermitian matrices (#21431). (#21432) --- base/sparse/cholmod.jl | 7 +++++++ test/sparse/cholmod.jl | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/base/sparse/cholmod.jl b/base/sparse/cholmod.jl index e1bbe0340ab85..1586a0a838018 100644 --- a/base/sparse/cholmod.jl +++ b/base/sparse/cholmod.jl @@ -1715,4 +1715,11 @@ end (*){Ti}(A::Hermitian{Float64,SparseMatrixCSC{Float64,Ti}}, B::SparseVecOrMat{Float64,Ti}) = sparse(Sparse(A)*Sparse(B)) +(*){Ti}(A::SparseVecOrMat{Float64,Ti}, + B::Symmetric{Float64,SparseMatrixCSC{Float64,Ti}}) = sparse(Sparse(A)*Sparse(B)) +(*){Ti}(A::SparseVecOrMat{Complex{Float64},Ti}, + B::Hermitian{Complex{Float64},SparseMatrixCSC{Complex{Float64},Ti}}) = sparse(Sparse(A)*Sparse(B)) +(*){Ti}(A::SparseVecOrMat{Float64,Ti}, + B::Hermitian{Float64,SparseMatrixCSC{Float64,Ti}}) = sparse(Sparse(A)*Sparse(B)) + end #module diff --git a/test/sparse/cholmod.jl b/test/sparse/cholmod.jl index 817eb4e9883a8..973620132359e 100644 --- a/test/sparse/cholmod.jl +++ b/test/sparse/cholmod.jl @@ -702,3 +702,11 @@ end @test_throws ArgumentError CHOLMOD.Sparse(A) end +@testset "sparse right multiplication of Symmetric and Hermitian matrices #21431" begin + @test issparse(speye(2)*speye(2)*speye(2)) + for T in (Symmetric, Hermitian) + @test issparse(speye(2)*T(speye(2))*speye(2)) + @test issparse(speye(2)*(T(speye(2))*speye(2))) + @test issparse((speye(2)*T(speye(2)))*speye(2)) + end +end From 4f256eefd79dbf9095e41cd9dade4e74a897d3b5 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 18 Apr 2017 15:17:26 -0400 Subject: [PATCH 0468/1534] fix #21369, exception state overwritten by caught internal errors --- src/codegen.cpp | 22 +++++++++------------- src/gc.c | 12 ++++++++++++ src/gf.c | 2 +- src/julia_internal.h | 2 ++ src/rtutils.c | 29 +++++++++++++++++++++++++++++ test/inference.jl | 28 ++++++++++++++++++++++++++++ 6 files changed, 81 insertions(+), 14 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 1f31875dd9e8e..1775210587f9f 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -2145,24 +2145,20 @@ static jl_value_t *static_eval(jl_value_t *ex, jl_codectx_t *ctx, int sparams=tr if (!allow_alloc) return NULL; jl_value_t **v; - JL_GC_PUSHARGS(v, n); + JL_GC_PUSHARGS(v, n+1); + v[0] = f; for (i = 0; i < n; i++) { - v[i] = static_eval(jl_exprarg(e, i+1), ctx, sparams, allow_alloc); - if (v[i] == NULL) { + v[i+1] = static_eval(jl_exprarg(e, i+1), ctx, sparams, allow_alloc); + if (v[i+1] == NULL) { JL_GC_POP(); return NULL; } } - jl_value_t *result; - JL_TRY { - if (f == jl_builtin_tuple) - result = jl_f_tuple(NULL, v, n); - else - result = jl_f_apply_type(NULL, v, n); - } - JL_CATCH { - result = NULL; - } + size_t last_age = jl_get_ptls_states()->world_age; + // here we know we're calling specific builtin functions that work in world 1. + jl_get_ptls_states()->world_age = 1; + jl_value_t *result = jl_apply_with_saved_exception_state(v, n+1, 1); + jl_get_ptls_states()->world_age = last_age; JL_GC_POP(); return result; } diff --git a/src/gc.c b/src/gc.c index 96718ed05113b..01b50408f5452 100644 --- a/src/gc.c +++ b/src/gc.c @@ -190,8 +190,20 @@ static void jl_gc_run_finalizers_in_list(jl_ptls_t ptls, arraylist_t *list) jl_value_t **items = (jl_value_t**)list->items; jl_gc_push_arraylist(ptls, list); JL_UNLOCK_NOGC(&finalizers_lock); + // from jl_apply_with_saved_exception_state; to hoist state saving out of the loop + jl_value_t *exc = ptls->exception_in_transit; + jl_array_t *bt = NULL; + JL_GC_PUSH2(&exc, &bt); + if (ptls->bt_size > 0) + bt = (jl_array_t*)jl_get_backtrace(); for (size_t i = 2;i < len;i += 2) run_finalizer(ptls, items[i], items[i + 1]); + ptls->exception_in_transit = exc; + if (bt != NULL) { + ptls->bt_size = jl_array_len(bt); + memcpy(ptls->bt_data, bt->data, ptls->bt_size * sizeof(void*)); + } + JL_GC_POP(); JL_GC_POP(); } diff --git a/src/gf.c b/src/gf.c index 0d44f879c6f47..d2be995dfdd96 100644 --- a/src/gf.c +++ b/src/gf.c @@ -266,7 +266,7 @@ jl_code_info_t *jl_type_infer(jl_method_instance_t **pli, size_t world, int forc } #endif jl_get_ptls_states()->world_age = jl_typeinf_world; - jl_svec_t *linfo_src_rettype = (jl_svec_t*)jl_apply(fargs, 3); + jl_svec_t *linfo_src_rettype = (jl_svec_t*)jl_apply_with_saved_exception_state(fargs, 3, 0); jl_get_ptls_states()->world_age = last_age; assert((li->def || li->inInference == 0) && "inference failed on a toplevel expr"); if (jl_is_svec(linfo_src_rettype) && jl_svec_len(linfo_src_rettype) == 3 && diff --git a/src/julia_internal.h b/src/julia_internal.h index e40cd82eea32c..54926651b08a2 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -640,6 +640,8 @@ size_t rec_backtrace_ctx(uintptr_t *data, size_t maxsize, bt_context_t *ctx); #ifdef LIBOSXUNWIND size_t rec_backtrace_ctx_dwarf(uintptr_t *data, size_t maxsize, bt_context_t *ctx); #endif +JL_DLLEXPORT jl_value_t *jl_get_backtrace(void); +JL_DLLEXPORT jl_value_t *jl_apply_with_saved_exception_state(jl_value_t **args, uint32_t nargs, int catch_exceptions); void jl_critical_error(int sig, bt_context_t *context, uintptr_t *bt_data, size_t *bt_size); JL_DLLEXPORT void jl_raise_debugger(void); int jl_getFunctionInfo(jl_frame_t **frames, uintptr_t pointer, int skipC, int noInline); diff --git a/src/rtutils.c b/src/rtutils.c index 66cb6bb3b7f39..935250ef8baf0 100644 --- a/src/rtutils.c +++ b/src/rtutils.c @@ -236,6 +236,35 @@ JL_DLLEXPORT void jl_pop_handler(int n) jl_eh_restore_state(eh); } +JL_DLLEXPORT jl_value_t *jl_apply_with_saved_exception_state(jl_value_t **args, uint32_t nargs, int catch_exceptions) +{ + jl_ptls_t ptls = jl_get_ptls_states(); + jl_value_t *exc = ptls->exception_in_transit; + jl_array_t *bt = NULL; + JL_GC_PUSH2(&exc, &bt); + if (ptls->bt_size > 0) + bt = (jl_array_t*)jl_get_backtrace(); + jl_value_t *v; + if (catch_exceptions) { + JL_TRY { + v = jl_apply(args, nargs); + } + JL_CATCH { + v = NULL; + } + } + else { + v = jl_apply(args, nargs); + } + ptls->exception_in_transit = exc; + if (bt != NULL) { + ptls->bt_size = jl_array_len(bt); + memcpy(ptls->bt_data, bt->data, ptls->bt_size * sizeof(void*)); + } + JL_GC_POP(); + return v; +} + // misc ----------------------------------------------------------------------- // perform f(args...) on stack diff --git a/test/inference.jl b/test/inference.jl index de62b81c68c41..1e34d4d664a3b 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -748,3 +748,31 @@ end # issue #21410 f21410(::V, ::Pair{V,E}) where {V, E} = E @test code_typed(f21410, Tuple{Ref, Pair{Ref{T},Ref{T}} where T<:Number})[1].second == Type{Ref{T}} where T<:Number + +# issue #21369 +function inf_error_21369(arg) + if arg + # invalid instantiation, causing throw during inference + Complex{String} + end +end +function break_21369() + try + error("uhoh") + catch + eval(:(inf_error_21369(false))) + bt = catch_backtrace() + i = 1 + local fr + while true + fr = Base.StackTraces.lookup(bt[i])[end] + if !fr.from_c + break + end + i += 1 + end + @test fr.func === :break_21369 + rethrow() + end +end +@test_throws ErrorException break_21369() # not TypeError From ebbe118a7e3579c5dc2936c228b06db292fc5979 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Sun, 5 Mar 2017 00:47:01 -0500 Subject: [PATCH 0469/1534] Precompute number of fields to skip in GC at the begin and end of a type --- src/datatype.c | 29 ++++++++++++++++++++++++----- src/dump.c | 10 +++++++++- src/gc.c | 11 ++++++----- src/julia_internal.h | 6 ++++++ 4 files changed, 45 insertions(+), 11 deletions(-) diff --git a/src/datatype.c b/src/datatype.c index 5052433517430..69c571aa04c04 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -97,12 +97,23 @@ static jl_datatype_layout_t *jl_get_layout(uint32_t nfields, { // compute the smallest fielddesc type that can hold the layout description int fielddesc_type = 0; + uint32_t npointers = 0; + // First pointer field + uint32_t first_ptr = (uint32_t)-1; + // Last pointer field + uint32_t last_ptr = 0; if (nfields > 0) { uint32_t max_size = 0; uint32_t max_offset = desc[nfields - 1].offset; for (size_t i = 0; i < nfields; i++) { if (desc[i].size > max_size) max_size = desc[i].size; + if (desc[i].isptr) { + npointers++; + if (first_ptr == (uint32_t)-1) + first_ptr = i; + last_ptr = i; + } } jl_fielddesc8_t maxdesc8 = { 0, max_size, max_offset }; jl_fielddesc16_t maxdesc16 = { 0, max_size, max_offset }; @@ -120,8 +131,20 @@ static jl_datatype_layout_t *jl_get_layout(uint32_t nfields, // allocate a new descriptor uint32_t fielddesc_size = jl_fielddesc_size(fielddesc_type); + int has_padding = nfields && npointers; jl_datatype_layout_t *flddesc = - (jl_datatype_layout_t*)jl_gc_perm_alloc(sizeof(jl_datatype_layout_t) + nfields * fielddesc_size); + (jl_datatype_layout_t*)jl_gc_perm_alloc(sizeof(jl_datatype_layout_t) + + nfields * fielddesc_size + + (has_padding ? sizeof(uint32_t) : 0)); + if (has_padding) { + if (first_ptr > UINT16_MAX) + first_ptr = UINT16_MAX; + last_ptr = nfields - last_ptr - 1; + if (last_ptr > UINT16_MAX) + last_ptr = UINT16_MAX; + flddesc = (jl_datatype_layout_t*)(((char*)flddesc) + sizeof(uint32_t)); + jl_datatype_layout_n_nonptr(flddesc) = (first_ptr << 16) | last_ptr; + } flddesc->nfields = nfields; flddesc->alignment = alignment; flddesc->haspadding = haspadding; @@ -131,7 +154,6 @@ static jl_datatype_layout_t *jl_get_layout(uint32_t nfields, jl_fielddesc8_t* desc8 = (jl_fielddesc8_t*)jl_dt_layout_fields(flddesc); jl_fielddesc16_t* desc16 = (jl_fielddesc16_t*)jl_dt_layout_fields(flddesc); jl_fielddesc32_t* desc32 = (jl_fielddesc32_t*)jl_dt_layout_fields(flddesc); - uint32_t npointers = 0; for (size_t i = 0; i < nfields; i++) { if (fielddesc_type == 0) { desc8[i].offset = desc[i].offset; @@ -148,9 +170,6 @@ static jl_datatype_layout_t *jl_get_layout(uint32_t nfields, desc32[i].size = desc[i].size; desc32[i].isptr = desc[i].isptr; } - if (desc[i].isptr) { - npointers++; - } } uint32_t nexp = 0; while (npointers >= 0x10000) { diff --git a/src/dump.c b/src/dump.c index 9cd3a6019a57f..1874926fddec0 100644 --- a/src/dump.c +++ b/src/dump.c @@ -638,6 +638,8 @@ static void jl_serialize_datatype(jl_serializer_state *s, jl_datatype_t *dt) write_int32(s->s, nf); uint32_t alignment = ((uint32_t*)dt->layout)[1]; write_int32(s->s, alignment); + if (dt->layout->npointers && nf) + write_int32(s->s, ((uint32_t*)dt->layout)[-1]); size_t fieldsize = jl_fielddesc_size(dt->layout->fielddesc_type); ios_write(s->s, (char*)(&dt->layout[1]), nf * fieldsize); } @@ -1495,10 +1497,16 @@ static jl_value_t *jl_deserialize_datatype(jl_serializer_state *s, int pos, jl_v } header; header.buffer.nf = nf; header.buffer.alignment = alignment; + int has_padding = header.layout.npointers && nf; uint8_t fielddesc_type = header.layout.fielddesc_type; size_t fielddesc_size = nf > 0 ? jl_fielddesc_size(fielddesc_type) : 0; jl_datatype_layout_t *layout = (jl_datatype_layout_t*)jl_gc_perm_alloc( - sizeof(jl_datatype_layout_t) + nf * fielddesc_size); + sizeof(jl_datatype_layout_t) + nf * fielddesc_size + + (has_padding ? sizeof(uint32_t) : 0)); + if (has_padding) { + layout = (jl_datatype_layout_t*)(((char*)layout) + sizeof(uint32_t)); + jl_datatype_layout_n_nonptr(layout) = read_int32(s->s); + } *layout = header.layout; ios_read(s->s, (char*)&layout[1], nf * fielddesc_size); dt->layout = layout; diff --git a/src/gc.c b/src/gc.c index 01b50408f5452..18408c6b50b6f 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1533,7 +1533,8 @@ static void gc_scan_obj_(jl_ptls_t ptls, jl_value_t *v, int d, if (vt == jl_weakref_type) return; // fast path - if (vt->layout->npointers == 0) + uint32_t npointers = vt->layout->npointers; + if (npointers == 0) return; d++; if (d >= MAX_MARK_DEPTH) @@ -1602,12 +1603,12 @@ static void gc_scan_obj_(jl_ptls_t ptls, jl_value_t *v, int d, } else { int nf = (int)jl_datatype_nfields(vt); - uint32_t npointers = vt->layout->npointers; nptr += (npointers & 0xff) << (npointers & 0x300); - for(int i=0; i < nf; i++) { + uint32_t offsets = jl_datatype_layout_n_nonptr(vt->layout); + nf -= offsets & 0xffff; + for (int i = (offsets >> 16); i < nf; i++) { if (jl_field_isptr(vt, i)) { - jl_value_t **slot = (jl_value_t**)((char*)v + - jl_field_offset(vt, i)); + jl_value_t **slot = (jl_value_t**)((char*)v + jl_field_offset(vt, i)); jl_value_t *fld = *slot; if (fld) { verify_parent2("object", v, slot, "field(%d)", i); diff --git a/src/julia_internal.h b/src/julia_internal.h index 96af6776dbcde..32312b7fb046e 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -263,6 +263,12 @@ STATIC_INLINE void *jl_gc_alloc_buf(jl_ptls_t ptls, size_t sz) return jl_gc_alloc(ptls, sz, (void*)jl_buff_tag); } +// Returns a int32 where the high 16 bits are a lower bound of the number of non-pointer fields +// at the beginning of the type and the low 16 bits are a lower bound on the number of non-pointer +// fields at the end of the type. This field only exists for a layout that has at least one +// pointer fields. +#define jl_datatype_layout_n_nonptr(layout) ((uint32_t*)(layout))[-1] + jl_value_t *jl_gc_realloc_string(jl_value_t *s, size_t sz); jl_code_info_t *jl_type_infer(jl_method_instance_t **li, size_t world, int force); From 60ec35caf8d23e218fc8c538485e3c2a5da65c2b Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Wed, 19 Apr 2017 23:04:20 -0400 Subject: [PATCH 0470/1534] Allow armv8 and armv8-a as CPU targets on aarch64 [ci skip] --- src/codegen.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index c694299a885a4..a42f4923ffa8a 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -7111,7 +7111,11 @@ static inline void checkARMArchFeature(std::string &cpu, HostFeatures[cpu] = true; } #else - HostFeatures[cpu.substr(3)] = true; + // These two are allowed on 32bit. Allow them on 64bits too for consistency since + // they basically mean "generic" on aarch64. + // In particular, "armv8-a" is the generic value for the GCC `-march` option. + if (cpu != "armv8" && cpu != "armv8-a") + HostFeatures[cpu.substr(3)] = true; #endif cpu = "generic"; } From 6b0fbd2b9fb8fb7698cd23df338f4d6aaea45b55 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Sun, 16 Apr 2017 15:27:37 -0400 Subject: [PATCH 0471/1534] Optimize `Threads.threadid()` --- src/ccall.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/ccall.cpp b/src/ccall.cpp index f881411d39c5a..4691aeb4a6e6e 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -1676,6 +1676,20 @@ static jl_cgval_t emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) emit_bitcast(ctx->ptlsStates, lrt), retboxed, rt, unionall, static_rt, ctx); } + if (fptr == (void(*)(void))&jl_threadid || + ((!f_lib || (intptr_t)f_lib == 2) && f_name && + strcmp(f_name, "jl_threadid") == 0)) { + assert(lrt == T_int16); + assert(!isVa && !llvmcall); + assert(nargt == 0); + JL_GC_POP(); + Value *ptls_i16 = emit_bitcast(ctx->ptlsStates, T_pint16); + const int tid_offset = offsetof(jl_tls_states_t, tid); + Value *ptid = builder.CreateGEP(ptls_i16, ConstantInt::get(T_size, tid_offset / 2)); + return mark_or_box_ccall_result( + tbaa_decorate(tbaa_const, builder.CreateLoad(ptid)), + retboxed, rt, unionall, static_rt, ctx); + } if (fptr == &jl_sigatomic_begin || ((!f_lib || (intptr_t)f_lib == 2) && f_name && strcmp(f_name, "jl_sigatomic_begin") == 0)) { From 5306a6142774796ecb6ce81c24cb3bd2b2aadee5 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Thu, 20 Apr 2017 08:45:42 -0400 Subject: [PATCH 0472/1534] fix manual typo --- doc/src/manual/calling-c-and-fortran-code.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/manual/calling-c-and-fortran-code.md b/doc/src/manual/calling-c-and-fortran-code.md index e6fc2ee62a8c5..17d00fbc95f9b 100644 --- a/doc/src/manual/calling-c-and-fortran-code.md +++ b/doc/src/manual/calling-c-and-fortran-code.md @@ -965,7 +965,7 @@ wait(cond) ``` The callback you pass to C should only execute a [`ccall`](@ref) to `:uv_async_send`, passing -`cb.handle` as the argument, taking care to avoid any allocations or other interactions with the +`cond.handle` as the argument, taking care to avoid any allocations or other interactions with the Julia runtime. Note that events may be coalesced, so multiple calls to `uv_async_send` may result in a single wakeup From 8b2ee7126cc293893aae9acceb102fa766ccc6bf Mon Sep 17 00:00:00 2001 From: Mus M Date: Thu, 20 Apr 2017 09:32:31 -0400 Subject: [PATCH 0473/1534] Ref and Vector in a few places in lapack and arpack (#21420) --- base/linalg/arpack.jl | 34 +++++++++++----------- base/linalg/lapack.jl | 66 +++++++++++++++++++++---------------------- 2 files changed, 50 insertions(+), 50 deletions(-) diff --git a/base/linalg/arpack.jl b/base/linalg/arpack.jl index f03c0f28deeee..4b5d1d147e4e4 100644 --- a/base/linalg/arpack.jl +++ b/base/linalg/arpack.jl @@ -12,20 +12,20 @@ function aupd_wrapper(T, matvecA!::Function, matvecB::Function, solveSI::Functio tol::Real, maxiter::Integer, mode::Integer, v0::Vector) lworkl = cmplx ? ncv * (3*ncv + 5) : (sym ? ncv * (ncv + 8) : ncv * (3*ncv + 6) ) TR = cmplx ? T.types[1] : T - TOL = Array{TR}(1) - TOL[1] = tol + TOL = Ref{TR}() + TOL[] = tol - v = Array{T}(n, ncv) - workd = Array{T}(3*n) - workl = Array{T}(lworkl) - rwork = cmplx ? Array{TR}(ncv) : Array{TR}(0) + v = Matrix{T}(n, ncv) + workd = Vector{T}(3*n) + workl = Vector{T}(lworkl) + rwork = cmplx ? Vector{TR}(ncv) : Vector{TR}(0) if isempty(v0) - resid = Array{T}(n) - info = zeros(BlasInt, 1) + resid = Vector{T}(n) + info = zeros(BlasInt, 1) else - resid = deepcopy(v0) - info = ones(BlasInt, 1) + resid = deepcopy(v0) + info = ones(BlasInt, 1) end iparam = zeros(BlasInt, 11) ipntr = zeros(BlasInt, (sym && !cmplx) ? 11 : 14) @@ -106,7 +106,7 @@ end function eupd_wrapper(T, n::Integer, sym::Bool, cmplx::Bool, bmat::String, nev::Integer, which::String, ritzvec::Bool, - TOL::Array, resid, ncv::Integer, v, ldv, sigma, iparam, ipntr, + TOL::Ref, resid, ncv::Integer, v, ldv, sigma, iparam, ipntr, workd, workl, lworkl, rwork) howmny = "A" select = Array{BlasInt}(ncv) @@ -203,7 +203,7 @@ for (T, saupd_name, seupd_name, naupd_name, neupd_name) in ((:Float64, :dsaupd_, :dseupd_, :dnaupd_, :dneupd_), (:Float32, :ssaupd_, :sseupd_, :snaupd_, :sneupd_)) @eval begin - function naupd(ido, bmat, n, evtype, nev, TOL::Array{$T}, resid::Array{$T}, ncv, v::Array{$T}, ldv, + function naupd(ido, bmat, n, evtype, nev, TOL::Ref{$T}, resid::Array{$T}, ncv, v::Array{$T}, ldv, iparam, ipntr, workd::Array{$T}, workl::Array{$T}, lworkl, info) ccall(($(string(naupd_name)), :libarpack), Void, (Ptr{BlasInt}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{UInt8}, Ptr{BlasInt}, @@ -214,7 +214,7 @@ for (T, saupd_name, seupd_name, naupd_name, neupd_name) in end function neupd(rvec, howmny, select, dr, di, z, ldz, sigmar, sigmai, - workev::Array{$T}, bmat, n, evtype, nev, TOL::Array{$T}, resid::Array{$T}, ncv, v, ldv, + workev::Array{$T}, bmat, n, evtype, nev, TOL::Ref{$T}, resid::Array{$T}, ncv, v, ldv, iparam, ipntr, workd::Array{$T}, workl::Array{$T}, lworkl, info) ccall(($(string(neupd_name)), :libarpack), Void, (Ptr{BlasInt}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{$T}, Ptr{$T}, Ptr{$T}, @@ -228,7 +228,7 @@ for (T, saupd_name, seupd_name, naupd_name, neupd_name) in sizeof(howmny), sizeof(bmat), sizeof(evtype)) end - function saupd(ido, bmat, n, which, nev, TOL::Array{$T}, resid::Array{$T}, ncv, v::Array{$T}, ldv, + function saupd(ido, bmat, n, which, nev, TOL::Ref{$T}, resid::Array{$T}, ncv, v::Array{$T}, ldv, iparam, ipntr, workd::Array{$T}, workl::Array{$T}, lworkl, info) ccall(($(string(saupd_name)), :libarpack), Void, (Ptr{BlasInt}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{UInt8}, Ptr{BlasInt}, @@ -239,7 +239,7 @@ for (T, saupd_name, seupd_name, naupd_name, neupd_name) in end function seupd(rvec, howmny, select, d, z, ldz, sigma, - bmat, n, evtype, nev, TOL::Array{$T}, resid::Array{$T}, ncv, v::Array{$T}, ldv, + bmat, n, evtype, nev, TOL::Ref{$T}, resid::Array{$T}, ncv, v::Array{$T}, ldv, iparam, ipntr, workd::Array{$T}, workl::Array{$T}, lworkl, info) ccall(($(string(seupd_name)), :libarpack), Void, (Ptr{BlasInt}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{$T}, Ptr{$T}, Ptr{BlasInt}, Ptr{$T}, @@ -257,7 +257,7 @@ for (T, TR, naupd_name, neupd_name) in ((:Complex128, :Float64, :znaupd_, :zneupd_), (:Complex64, :Float32, :cnaupd_, :cneupd_)) @eval begin - function naupd(ido, bmat, n, evtype, nev, TOL::Array{$TR}, resid::Array{$T}, ncv, v::Array{$T}, ldv, + function naupd(ido, bmat, n, evtype, nev, TOL::Ref{$TR}, resid::Array{$T}, ncv, v::Array{$T}, ldv, iparam, ipntr, workd::Array{$T}, workl::Array{$T}, lworkl, rwork::Array{$TR}, info) ccall(($(string(naupd_name)), :libarpack), Void, @@ -270,7 +270,7 @@ for (T, TR, naupd_name, neupd_name) in end function neupd(rvec, howmny, select, d, z, ldz, sigma, workev::Array{$T}, - bmat, n, evtype, nev, TOL::Array{$TR}, resid::Array{$T}, ncv, v::Array{$T}, ldv, + bmat, n, evtype, nev, TOL::Ref{$TR}, resid::Array{$T}, ncv, v::Array{$T}, ldv, iparam, ipntr, workd::Array{$T}, workl::Array{$T}, lworkl, rwork::Array{$TR}, info) ccall(($(string(neupd_name)), :libarpack), Void, diff --git a/base/linalg/lapack.jl b/base/linalg/lapack.jl index 5282ec8ba22f2..4b5c937767ce8 100644 --- a/base/linalg/lapack.jl +++ b/base/linalg/lapack.jl @@ -196,8 +196,8 @@ for (gebal, gebak, elty, relty) in chkstride1(A) n = checksquare(A) chkfinite(A) # balancing routines don't support NaNs and Infs - ihi = Array{BlasInt}(1) - ilo = Array{BlasInt}(1) + ihi = Ref{BlasInt}() + ilo = Ref{BlasInt}() scale = similar(A, $relty, n) info = Ref{BlasInt}() ccall((@blasfunc($gebal), liblapack), Void, @@ -205,7 +205,7 @@ for (gebal, gebak, elty, relty) in Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$relty}, Ptr{BlasInt}), &job, &n, A, &max(1,stride(A,2)), ilo, ihi, scale, info) chklapackerror(info[]) - ilo[1], ihi[1], scale + ilo[], ihi[], scale end # SUBROUTINE DGEBAK( JOB, SIDE, N, ILO, IHI, SCALE, M, V, LDV, INFO ) @@ -1965,10 +1965,10 @@ for (geevx, ggev, elty) in throw(ArgumentError("jobvr must be 'V' or 'N', but $jobvr was passed")) end VR = similar(A, $elty, ldvr, n) - ilo = Array{BlasInt}(1) - ihi = Array{BlasInt}(1) + ilo = Ref{BlasInt}() + ihi = Ref{BlasInt}() scale = similar(A, $elty, n) - abnrm = Array{$elty}(1) + abnrm = Ref{$elty}() rconde = similar(A, $elty, n) rcondv = similar(A, $elty, n) work = Array{$elty}(1) @@ -2003,7 +2003,7 @@ for (geevx, ggev, elty) in work = Array{$elty}(lwork) end end - A, wr, wi, VL, VR, ilo[1], ihi[1], scale, abnrm[1], rconde, rcondv + A, wr, wi, VL, VR, ilo[], ihi[], scale, abnrm[], rconde, rcondv end # SUBROUTINE DGGEV( JOBVL, JOBVR, N, A, LDA, B, LDB, ALPHAR, ALPHAI, @@ -2118,10 +2118,10 @@ for (geevx, ggev, elty, relty) in throw(ArgumentError("sense must be 'N', 'E', 'V' or 'B', but $sense was passed")) end VR = similar(A, $elty, ldvr, n) - ilo = Array{BlasInt}(1) - ihi = Array{BlasInt}(1) + ilo = Ref{BlasInt}() + ihi = Ref{BlasInt}() scale = similar(A, $relty, n) - abnrm = Array{$relty}(1) + abnrm = Ref{$relty}() rconde = similar(A, $relty, n) rcondv = similar(A, $relty, n) work = Array{$elty}(1) @@ -2148,7 +2148,7 @@ for (geevx, ggev, elty, relty) in work = Array{$elty}(lwork) end end - A, w, VL, VR, ilo[1], ihi[1], scale, abnrm[1], rconde, rcondv + A, w, VL, VR, ilo[], ihi[], scale, abnrm[], rconde, rcondv end # SUBROUTINE ZGGEV( JOBVL, JOBVR, N, A, LDA, B, LDB, ALPHA, BETA, @@ -3372,7 +3372,7 @@ for (trcon, trevc, trrfs, elty) in chkstride1(T, select) # Allocate - m = Array{BlasInt}(1) + m = Ref{BlasInt}() work = Array{$elty}(3n) info = Ref{BlasInt}() @@ -3390,19 +3390,19 @@ for (trcon, trevc, trrfs, elty) in #Decide what exactly to return if howmny == 'S' #compute selected eigenvectors if side == 'L' #left eigenvectors only - return select, VL[:,1:m[1]] + return select, VL[:,1:m[]] elseif side == 'R' #right eigenvectors only - return select, VR[:,1:m[1]] + return select, VR[:,1:m[]] else #side == 'B' #both eigenvectors - return select, VL[:,1:m[1]], VR[:,1:m[1]] + return select, VL[:,1:m[]], VR[:,1:m[]] end else #compute all eigenvectors if side == 'L' #left eigenvectors only - return VL[:,1:m[1]] + return VL[:,1:m[]] elseif side == 'R' #right eigenvectors only - return VR[:,1:m[1]] + return VR[:,1:m[]] else #side == 'B' #both eigenvectors - return VL[:,1:m[1]], VR[:,1:m[1]] + return VL[:,1:m[]], VR[:,1:m[]] end end end @@ -3501,7 +3501,7 @@ for (trcon, trevc, trrfs, elty, relty) in end # Allocate - m = Array{BlasInt}(1) + m = Ref{BlasInt}() work = Array{$elty}(2n) rwork = Array{$relty}(n) info = Ref{BlasInt}() @@ -3519,19 +3519,19 @@ for (trcon, trevc, trrfs, elty, relty) in #Decide what exactly to return if howmny == 'S' #compute selected eigenvectors if side == 'L' #left eigenvectors only - return select, VL[:,1:m[1]] + return select, VL[:,1:m[]] elseif side == 'R' #right eigenvectors only - return select, VR[:,1:m[1]] + return select, VR[:,1:m[]] else #side=='B' #both eigenvectors - return select, VL[:,1:m[1]], VR[:,1:m[1]] + return select, VL[:,1:m[]], VR[:,1:m[]] end else #compute all eigenvectors if side == 'L' #left eigenvectors only - return VL[:,1:m[1]] + return VL[:,1:m[]] elseif side == 'R' #right eigenvectors only - return VR[:,1:m[1]] + return VR[:,1:m[]] else #side=='B' #both eigenvectors - return VL[:,1:m[1]], VR[:,1:m[1]] + return VL[:,1:m[]], VR[:,1:m[]] end end end @@ -3648,7 +3648,7 @@ for (stev, stebz, stegr, stein, elty) in if length(ev) != n - 1 throw(DimensionMismatch("ev has length $(length(ev)) but needs one less than dv's length, $n)")) end - m = Array{BlasInt}(1) + m = Ref{BlasInt}() nsplit = Array{BlasInt}(1) w = similar(dv, $elty, n) tmp = 0.0 @@ -3669,7 +3669,7 @@ for (stev, stebz, stegr, stein, elty) in w, iblock, isplit, work, iwork, info) chklapackerror(info[]) - w[1:m[1]], iblock[1:m[1]], isplit[1:nsplit[1]] + w[1:m[]], iblock[1:m[]], isplit[1:nsplit[1]] end function stegr!(jobz::Char, range::Char, dv::StridedVector{$elty}, ev::StridedVector{$elty}, vl::Real, vu::Real, il::Integer, iu::Integer) @@ -3680,7 +3680,7 @@ for (stev, stebz, stegr, stein, elty) in end eev = [ev; zero($elty)] abstol = Array{$elty}(1) - m = Array{BlasInt}(1) + m = Ref{BlasInt}() w = similar(dv, $elty, n) ldz = jobz == 'N' ? 1 : n Z = similar(dv, $elty, ldz, range == 'I' ? iu-il+1 : n) @@ -3710,7 +3710,7 @@ for (stev, stebz, stegr, stein, elty) in iwork = Array{BlasInt}(liwork) end end - m[1] == length(w) ? w : w[1:m[1]], m[1] == size(Z, 2) ? Z : Z[:,1:m[1]] + m[] == length(w) ? w : w[1:m[]], m[] == size(Z, 2) ? Z : Z[:,1:m[]] end function stein!(dv::StridedVector{$elty}, ev_in::StridedVector{$elty}, w_in::StridedVector{$elty}, iblock_in::StridedVector{BlasInt}, isplit_in::StridedVector{BlasInt}) @@ -4824,7 +4824,7 @@ for (syev, syevr, sygvd, elty) in throw(ArgumentError("lower boundary, $vl, must be less than upper boundary, $vu")) end lda = stride(A,2) - m = Array{BlasInt}(1) + m = Ref{BlasInt}() w = similar(A, $elty, n) ldz = n if jobz == 'N' @@ -4860,7 +4860,7 @@ for (syev, syevr, sygvd, elty) in iwork = Array{BlasInt}(liwork) end end - w[1:m[1]], Z[:,1:(jobz == 'V' ? m[1] : 0)] + w[1:m[]], Z[:,1:(jobz == 'V' ? m[] : 0)] end syevr!(jobz::Char, A::StridedMatrix{$elty}) = syevr!(jobz, 'A', 'U', A, 0.0, 0.0, 0, 0, -1.0) @@ -4971,7 +4971,7 @@ for (syev, syevr, sygvd, elty, relty) in throw(ArgumentError("lower boundary, $vl, must be less than upper boundary, $vu")) end lda = max(1,stride(A,2)) - m = Array{BlasInt}(1) + m = Ref{BlasInt}() w = similar(A, $relty, n) if jobz == 'N' ldz = 1 @@ -5012,7 +5012,7 @@ for (syev, syevr, sygvd, elty, relty) in iwork = Array{BlasInt}(liwork) end end - w[1:m[1]], Z[:,1:(jobz == 'V' ? m[1] : 0)] + w[1:m[]], Z[:,1:(jobz == 'V' ? m[] : 0)] end syevr!(jobz::Char, A::StridedMatrix{$elty}) = syevr!(jobz, 'A', 'U', A, 0.0, 0.0, 0, 0, -1.0) From 82159d635d9dd80a0be6b9ac946a2341e9153dd5 Mon Sep 17 00:00:00 2001 From: Jim Garrison Date: Thu, 20 Apr 2017 12:46:53 -0400 Subject: [PATCH 0474/1534] Update doc: logabsdet works on complex matrices now too (#21451) Ref: #14198 [av skip] --- base/linalg/generic.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/linalg/generic.jl b/base/linalg/generic.jl index da32703c0e9c6..547a7774ef866 100644 --- a/base/linalg/generic.jl +++ b/base/linalg/generic.jl @@ -1166,7 +1166,7 @@ det(x::Number) = x """ logabsdet(M) -Log of absolute value of determinant of real matrix. Equivalent to +Log of absolute value of matrix determinant. Equivalent to `(log(abs(det(M))), sign(det(M)))`, but may provide increased accuracy and/or speed. """ logabsdet(A::AbstractMatrix) = logabsdet(lufact(A)) From a2c1e333772c9ce03df2babc78c3c9f7e1056c89 Mon Sep 17 00:00:00 2001 From: Mus M Date: Thu, 20 Apr 2017 12:48:46 -0400 Subject: [PATCH 0475/1534] Consistently use joinpath in base (#21405) --- base/dft.jl | 2 +- base/docs/helpdb.jl | 2 +- base/grisu/grisu.jl | 12 ++++++------ base/markdown/Markdown.jl | 24 ++++++++++++------------ base/pkg/resolve.jl | 6 +++--- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/base/dft.jl b/base/dft.jl index 39857d3905dd1..6239a3b4e23ba 100644 --- a/base/dft.jl +++ b/base/dft.jl @@ -580,7 +580,7 @@ module FFTW """ function plan_r2r end - Base.USE_GPL_LIBS && include("fft/FFTW.jl") + Base.USE_GPL_LIBS && include(joinpath("fft", "FFTW.jl")) end importall .FFTW diff --git a/base/docs/helpdb.jl b/base/docs/helpdb.jl index 713de51e6b985..42e7b76d29df0 100644 --- a/base/docs/helpdb.jl +++ b/base/docs/helpdb.jl @@ -1,3 +1,3 @@ # This file is a part of Julia. License is MIT: http://julialang.org/license -include("helpdb/Base.jl") +include(joinpath("helpdb", "Base.jl")) diff --git a/base/grisu/grisu.jl b/base/grisu/grisu.jl index 8bcbf428c138e..b9a834a07bb9f 100644 --- a/base/grisu/grisu.jl +++ b/base/grisu/grisu.jl @@ -13,12 +13,12 @@ const PRECISION = 3 const DIGITS = Vector{UInt8}(309+17) -include("grisu/float.jl") -include("grisu/fastshortest.jl") -include("grisu/fastprecision.jl") -include("grisu/fastfixed.jl") -include("grisu/bignums.jl") -include("grisu/bignum.jl") +include(joinpath("grisu", "float.jl")) +include(joinpath("grisu", "fastshortest.jl")) +include(joinpath("grisu", "fastprecision.jl")) +include(joinpath("grisu", "fastfixed.jl")) +include(joinpath("grisu", "bignums.jl")) +include(joinpath("grisu", "bignum.jl")) const BIGNUMS = [Bignums.Bignum(),Bignums.Bignum(),Bignums.Bignum(),Bignums.Bignum()] diff --git a/base/markdown/Markdown.jl b/base/markdown/Markdown.jl index 453bbc59106a0..ba3bbca697d38 100644 --- a/base/markdown/Markdown.jl +++ b/base/markdown/Markdown.jl @@ -5,21 +5,21 @@ module Markdown import Base: show, == import Core: @doc_str -include("parse/config.jl") -include("parse/util.jl") -include("parse/parse.jl") +include(joinpath("parse", "config.jl")) +include(joinpath("parse", "util.jl")) +include(joinpath("parse", "parse.jl")) -include("Common/Common.jl") -include("GitHub/GitHub.jl") -include("IPython/IPython.jl") -include("Julia/Julia.jl") +include(joinpath("Common", "Common.jl")) +include(joinpath("GitHub", "GitHub.jl")) +include(joinpath("IPython", "IPython.jl")) +include(joinpath("Julia", "Julia.jl")) -include("render/plain.jl") -include("render/html.jl") -include("render/latex.jl") -include("render/rst.jl") +include(joinpath("render", "plain.jl")) +include(joinpath("render", "html.jl")) +include(joinpath("render", "latex.jl")) +include(joinpath("render", "rst.jl")) -include("render/terminal/render.jl") +include(joinpath("render", "terminal", "render.jl")) export readme, license, @md_str, @doc_str diff --git a/base/pkg/resolve.jl b/base/pkg/resolve.jl index 84bcf42ff21f6..ddb18f46c0b22 100644 --- a/base/pkg/resolve.jl +++ b/base/pkg/resolve.jl @@ -2,9 +2,9 @@ module Resolve -include("resolve/versionweight.jl") -include("resolve/interface.jl") -include("resolve/maxsum.jl") +include(joinpath("resolve", "versionweight.jl")) +include(joinpath("resolve", "interface.jl")) +include(joinpath("resolve", "maxsum.jl")) using ..Types, ..Query, .PkgToMaxSumInterface, .MaxSum import ...Pkg.PkgError From d24238dde3971e01f51a828f2fe2452d387b0656 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Wed, 19 Apr 2017 09:18:28 -0500 Subject: [PATCH 0476/1534] Create show_supertypes --- base/show.jl | 10 ++++++++++ test/show.jl | 3 +++ 2 files changed, 13 insertions(+) diff --git a/base/show.jl b/base/show.jl index fc81db8fb4018..1325c40a90cc8 100644 --- a/base/show.jl +++ b/base/show.jl @@ -236,6 +236,16 @@ function show_datatype(io::IO, x::DataType) end end +function show_supertypes(io::IO, typ::DataType) + print(io, typ) + while typ != Any + typ = supertype(typ) + print(io, " <: ", typ) + end +end + +show_supertypes(typ::DataType) = show_supertypes(STDOUT, typ) + macro show(exs...) blk = Expr(:block) for ex in exs diff --git a/test/show.jl b/test/show.jl index e70904452b64b..960282b2d57fc 100644 --- a/test/show.jl +++ b/test/show.jl @@ -670,3 +670,6 @@ let m = which(T20332{Int}(), (Int,)), end @test sprint(show, Main) == "Main" + +@test sprint(Base.show_supertypes, Int64) == "Int64 <: Signed <: Integer <: Real <: Number <: Any" +@test sprint(Base.show_supertypes, Vector{String}) == "Array{String,1} <: DenseArray{String,1} <: AbstractArray{String,1} <: Any" From 7d0c945362960dbf71f73b52d11dd250733ac8fb Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Thu, 20 Apr 2017 12:03:47 -0700 Subject: [PATCH 0477/1534] A few stylistic and syntactic updates to the manual (#21456) --- doc/src/manual/control-flow.md | 8 +-- doc/src/manual/conversion-and-promotion.md | 24 ++++----- doc/src/manual/methods.md | 58 +++++++++++----------- doc/src/manual/style-guide.md | 10 ++-- doc/src/manual/variables.md | 2 + 5 files changed, 52 insertions(+), 50 deletions(-) diff --git a/doc/src/manual/control-flow.md b/doc/src/manual/control-flow.md index 0d71040c604d3..1bf0923b6cb40 100644 --- a/doc/src/manual/control-flow.md +++ b/doc/src/manual/control-flow.md @@ -60,11 +60,11 @@ value of a boolean expression. Here is the anatomy of the `if`-`elseif`-`else` c ```julia if x < y - println("x is less than y") + println("x is less than y") elseif x > y - println("x is greater than y") + println("x is greater than y") else - println("x is equal to y") + println("x is equal to y") end ``` @@ -777,7 +777,7 @@ try bad() catch; x end try bad() catch - x + x end ``` diff --git a/doc/src/manual/conversion-and-promotion.md b/doc/src/manual/conversion-and-promotion.md index c71024df14a2b..663a8e7388dd8 100644 --- a/doc/src/manual/conversion-and-promotion.md +++ b/doc/src/manual/conversion-and-promotion.md @@ -132,8 +132,8 @@ especially for parametric types. The example above is meant to be pedagogical, a actual Julia behaviour. This is the actual implementation in Julia: ```julia -convert{T<:Real}(::Type{T}, z::Complex) = (imag(z)==0 ? convert(T,real(z)) : - throw(InexactError())) +convert(::Type{T}, z::Complex) where {T<:Real} = + (imag(z) == 0 ? convert(T, real(z)) : throw(InexactError())) julia> convert(Bool, 1im) ERROR: InexactError() @@ -147,10 +147,10 @@ To continue our case study of Julia's `Rational` type, here are the conversions right after the declaration of the type and its constructors: ```julia -convert{T<:Integer}(::Type{Rational{T}}, x::Rational) = Rational(convert(T,x.num),convert(T,x.den)) -convert{T<:Integer}(::Type{Rational{T}}, x::Integer) = Rational(convert(T,x), convert(T,1)) +convert(::Type{Rational{T}}, x::Rational) where {T<:Integer} = Rational(convert(T,x.num),convert(T,x.den)) +convert(::Type{Rational{T}}, x::Integer) where {T<:Integer} = Rational(convert(T,x), convert(T,1)) -function convert{T<:Integer}(::Type{Rational{T}}, x::AbstractFloat, tol::Real) +function convert(::Type{Rational{T}}, x::AbstractFloat, tol::Real) where T<:Integer if isnan(x); return zero(T)//zero(T); end if isinf(x); return sign(x)//zero(T); end y = x @@ -165,10 +165,10 @@ function convert{T<:Integer}(::Type{Rational{T}}, x::AbstractFloat, tol::Real) y = 1/y end end -convert{T<:Integer}(rt::Type{Rational{T}}, x::AbstractFloat) = convert(rt,x,eps(x)) +convert(rt::Type{Rational{T}}, x::AbstractFloat) where {T<:Integer} = convert(rt,x,eps(x)) -convert{T<:AbstractFloat}(::Type{T}, x::Rational) = convert(T,x.num)/convert(T,x.den) -convert{T<:Integer}(::Type{T}, x::Rational) = div(convert(T,x.num),convert(T,x.den)) +convert(::Type{T}, x::Rational) where {T<:AbstractFloat} = convert(T,x.num)/convert(T,x.den) +convert(::Type{T}, x::Rational) where {T<:Integer} = div(convert(T,x.num),convert(T,x.den)) ``` The initial four convert methods provide conversions to rational types. The first method converts @@ -280,7 +280,7 @@ another type object, such that instances of the argument types will be promoted type. Thus, by defining the rule: ```julia -promote_rule(::Type{Float64}, ::Type{Float32} ) = Float64 +promote_rule(::Type{Float64}, ::Type{Float32}) = Float64 ``` one declares that when 64-bit and 32-bit floating-point values are promoted together, they should @@ -318,9 +318,9 @@ Finally, we finish off our ongoing case study of Julia's rational number type, w sophisticated use of the promotion mechanism with the following promotion rules: ```julia -promote_rule{T<:Integer,S<:Integer}(::Type{Rational{T}}, ::Type{S}) = Rational{promote_type(T,S)} -promote_rule{T<:Integer,S<:Integer}(::Type{Rational{T}}, ::Type{Rational{S}}) = Rational{promote_type(T,S)} -promote_rule{T<:Integer,S<:AbstractFloat}(::Type{Rational{T}}, ::Type{S}) = promote_type(T,S) +promote_rule(::Type{Rational{T}}, ::Type{S}) where {T<:Integer,S<:Integer} = Rational{promote_type(T,S)} +promote_rule(::Type{Rational{T}}, ::Type{Rational{S}}) where {T<:Integer,S<:Integer} = Rational{promote_type(T,S)} +promote_rule(::Type{Rational{T}}, ::Type{S}) where {T<:Integer,S<:AbstractFloat} = promote_type(T,S) ``` The first rule says that promoting a rational number with any other integer type promotes to a diff --git a/doc/src/manual/methods.md b/doc/src/manual/methods.md index 6f03e442989bb..330ec3a7746b8 100644 --- a/doc/src/manual/methods.md +++ b/doc/src/manual/methods.md @@ -194,27 +194,27 @@ most powerful and central feature of the Julia language. Core operations typical of methods: ```julia - julia> methods(+) - # 166 methods for generic function "+": - +(a::Float16, b::Float16) at float16.jl:136 - +(x::Float32, y::Float32) at float.jl:206 - +(x::Float64, y::Float64) at float.jl:207 - +(x::Bool, z::Complex{Bool}) at complex.jl:126 - +(x::Bool, y::Bool) at bool.jl:48 - +(x::Bool) at bool.jl:45 - +{T<:AbstractFloat}(x::Bool, y::T) at bool.jl:55 - +(x::Bool, z::Complex) at complex.jl:133 - +(x::Bool, A::AbstractArray{Bool,N<:Any}) at arraymath.jl:105 - +(x::Char, y::Integer) at char.jl:40 - +{T<:Union{Int128,Int16,Int32,Int64,Int8,UInt128,UInt16,UInt32,UInt64,UInt8}}(x::T, y::T) at int.jl:32 - +(z::Complex, w::Complex) at complex.jl:115 - +(z::Complex, x::Bool) at complex.jl:134 - +(x::Real, z::Complex{Bool}) at complex.jl:140 - +(x::Real, z::Complex) at complex.jl:152 - +(z::Complex, x::Real) at complex.jl:153 - +(x::Rational, y::Rational) at rational.jl:179 - ... - +(a, b, c, xs...) at operators.jl:119 +julia> methods(+) +# 180 methods for generic function "+": ++(x::Bool, z::Complex{Bool}) in Base at complex.jl:224 ++(x::Bool, y::Bool) in Base at bool.jl:89 ++(x::Bool) in Base at bool.jl:86 ++(x::Bool, y::T) where T<:AbstractFloat in Base at bool.jl:96 ++(x::Bool, z::Complex) in Base at complex.jl:231 ++(a::Float16, b::Float16) in Base at float.jl:372 ++(x::Float32, y::Float32) in Base at float.jl:374 ++(x::Float64, y::Float64) in Base at float.jl:375 ++(z::Complex{Bool}, x::Bool) in Base at complex.jl:225 ++(z::Complex{Bool}, x::Real) in Base at complex.jl:239 ++(x::Char, y::Integer) in Base at char.jl:40 ++(c::BigInt, x::BigFloat) in Base.MPFR at mpfr.jl:303 ++(a::BigInt, b::BigInt, c::BigInt, d::BigInt, e::BigInt) in Base.GMP at gmp.jl:303 ++(a::BigInt, b::BigInt, c::BigInt, d::BigInt) in Base.GMP at gmp.jl:296 ++(a::BigInt, b::BigInt, c::BigInt) in Base.GMP at gmp.jl:290 ++(x::BigInt, y::BigInt) in Base.GMP at gmp.jl:258 ++(x::BigInt, c::Union{UInt16, UInt32, UInt64, UInt8}) in Base.GMP at gmp.jl:315 +... ++(a, b, c, xs...) at operators.jl:119 ``` Multiple dispatch together with the flexible parametric type system give Julia its ability to @@ -545,7 +545,7 @@ Closest candidates are: More usefully, it is possible to constrain varargs methods by a parameter. For example: ```julia -function getindex{T,N}(A::AbstractArray{T,N}, indexes::Vararg{Number,N}) +function getindex(A::AbstractArray{T,N}, indexes::Vararg{Number,N}) where {T,N} ``` would be called only when the number of `indexes` matches the dimensionality of the array. @@ -666,8 +666,8 @@ Below we discuss particular challenges and some alternative ways to resolve such `Tuple` (and `NTuple`) arguments present special challenges. For example, ```julia -f{N}(x::NTuple{N,Int}) = 1 -f{N}(x::NTuple{N,Float64}) = 2 +f(x::NTuple{N,Int}) where {N} = 1 +f(x::NTuple{N,Float64}) where {N} = 2 ``` are ambiguous because of the possibility that `N == 0`: there are no @@ -683,7 +683,7 @@ Alternatively, for all methods but one you can insist that there is at least one element in the tuple: ```julia -f{N}(x::NTuple{N,Int}) = 1 # this is the fallback +f(x::NTuple{N,Int}) where {N} = 1 # this is the fallback f(x::Tuple{Float64, Vararg{Float64}}) = 2 # this requires at least one Float64 ``` @@ -721,7 +721,7 @@ A related strategy exploits `promote` to bring `x` and `y` to a common type: ```julia -f{T}(x::T, y::T) = ... +f(x::T, y::T) where {T} = ... f(x, y) = f(promote(x, y)...) ``` @@ -761,13 +761,13 @@ Where possible, try to avoid defining methods that dispatch on specific element types of abstract containers. For example, ```julia --{T<:Date}(A::AbstractArray{T}, b::Date) +-(A::AbstractArray{T}, b::Date) where {T<:Date} ``` generates ambiguities for anyone who defines a method ```julia --{T}(A::MyArrayType{T}, b::T) +-(A::MyArrayType{T}, b::T) where {T} ``` The best approach is to avoid defining *either* of these methods: @@ -784,7 +784,7 @@ can't be modified or eliminated. As a last resort, one developer can define the "band-aid" method ```julia --{T<:Date}(A::MyArrayType{T}, b::Date) = ... +-(A::MyArrayType{T}, b::Date) where {T<:Date} = ... ``` that resolves the ambiguity by brute force. diff --git a/doc/src/manual/style-guide.md b/doc/src/manual/style-guide.md index eb6a41f62aea3..86181bcdc8d82 100644 --- a/doc/src/manual/style-guide.md +++ b/doc/src/manual/style-guide.md @@ -90,7 +90,7 @@ is that declaring more specific types leaves more "space" for future method defi Instead of: ```julia -function double{T<:Number}(a::AbstractArray{T}) +function double(a::AbstractArray{<:Number}) for i = 1:endof(a) a[i] *= 2 end @@ -101,7 +101,7 @@ end use: ```julia -function double!{T<:Number}(a::AbstractArray{T}) +function double!(a::AbstractArray{<:Number}) for i = 1:endof(a) a[i] *= 2 end @@ -123,7 +123,7 @@ Types such as `Union{Function,AbstractString}` are often a sign that some design When creating a type such as: ```julia -type MyType +struct MyType ... x::Union{Void,T} end @@ -194,7 +194,7 @@ is already iterable it is often even better to leave it alone, and not convert i A function signature: ```julia -foo{T<:Real}(x::T) = ... +foo(x::T) where {T<:Real} = ... ``` should be written as: @@ -243,7 +243,7 @@ it will naturally have access to the run-time values it needs. If you have a type that uses a native pointer: ```julia -type NativeType +mutable struct NativeType p::Ptr{UInt8} ... end diff --git a/doc/src/manual/variables.md b/doc/src/manual/variables.md index 61ac187c54764..49c7a9f01167d 100644 --- a/doc/src/manual/variables.md +++ b/doc/src/manual/variables.md @@ -129,3 +129,5 @@ conventions: * Functions that write to their arguments have names that end in `!`. These are sometimes called "mutating" or "in-place" functions because they are intended to produce changes in their arguments after the function is called, not just return a value. + +For more information about stylistic conventions, see the [Style Guide](@ref). From 8add7400a3839b18a86066a55bce617654182f12 Mon Sep 17 00:00:00 2001 From: Wonseok Shin Date: Thu, 20 Apr 2017 16:38:32 -0400 Subject: [PATCH 0478/1534] =?UTF-8?q?Add=20cases=20for=20N=20=3D=200=20and?= =?UTF-8?q?=2011=20=E2=89=A4=20N=20=E2=89=A4=2015?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- base/tuple.jl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/base/tuple.jl b/base/tuple.jl index 8bac0ddb4f34b..88463ee3cc00e 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -123,6 +123,7 @@ end _ntuple(f, n) = (@_noinline_meta; ([f(i) for i = 1:n]...)) # inferrable ntuple +ntuple{F}(f::F, ::Type{Val{0}}) = (@_inline_meta; ()) ntuple{F}(f::F, ::Type{Val{1}}) = (@_inline_meta; (f(1),)) ntuple{F}(f::F, ::Type{Val{2}}) = (@_inline_meta; (f(1), f(2))) ntuple{F}(f::F, ::Type{Val{3}}) = (@_inline_meta; (f(1), f(2), f(3))) @@ -133,6 +134,11 @@ ntuple{F}(f::F, ::Type{Val{7}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), ntuple{F}(f::F, ::Type{Val{8}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8))) ntuple{F}(f::F, ::Type{Val{9}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9))) ntuple{F}(f::F, ::Type{Val{10}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10))) +ntuple{F}(f::F, ::Type{Val{11}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10), f(11))) +ntuple{F}(f::F, ::Type{Val{12}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10), f(11), f(12))) +ntuple{F}(f::F, ::Type{Val{13}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10), f(11), f(12), f(13))) +ntuple{F}(f::F, ::Type{Val{14}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10), f(11), f(12), f(13), f(14))) +ntuple{F}(f::F, ::Type{Val{15}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10), f(11), f(12), f(13), f(14), f(15))) function ntuple{F,N}(f::F, ::Type{Val{N}}) Core.typeassert(N, Int) From c50612c867c2d657a19f08e42d1c5784e310dce6 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Thu, 20 Apr 2017 17:33:07 -0400 Subject: [PATCH 0479/1534] Evaluate thread range only once --- base/threadingconstructs.jl | 3 ++- test/threads.jl | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/base/threadingconstructs.jl b/base/threadingconstructs.jl index 678e9c3d92c3b..895b667c14aa9 100644 --- a/base/threadingconstructs.jl +++ b/base/threadingconstructs.jl @@ -23,9 +23,10 @@ function _threadsfor(iter,lbody) lidx = iter.args[1] # index range = iter.args[2] quote + range = $(esc(range)) function $fun() tid = threadid() - r = $(esc(range)) + r = range # Load into local variable # divide loop iterations among threads len, rem = divrem(length(r), nthreads()) # not enough iterations for all the threads? diff --git a/test/threads.jl b/test/threads.jl index d0626fdbc3d79..9c587ede557e3 100644 --- a/test/threads.jl +++ b/test/threads.jl @@ -390,6 +390,20 @@ else @test_throws ErrorException cglobal(:jl_tls_states) end +function test_thread_range() + a = zeros(Int, nthreads()) + @threads for i in 1:threadid() + a[i] = 1 + end + for i in 1:threadid() + @test a[i] == 1 + end + for i in (threadid() + 1):nthreads() + @test a[i] == 0 + end +end +test_thread_range() + # Thread safety of `jl_load_and_lookup`. function test_load_and_lookup_18020(n) @threads for i in 1:n From bc36ca3be50cb569617d89bc7357c2d8b7b8105e Mon Sep 17 00:00:00 2001 From: Sascha Mann Date: Fri, 21 Apr 2017 01:15:20 +0200 Subject: [PATCH 0480/1534] =?UTF-8?q?Add=20=E2=8A=87,=20=E2=8A=89,=20?= =?UTF-8?q?=E2=8A=8B=20analogous=20to=20=E2=8A=86,=20=E2=8A=88,=20?= =?UTF-8?q?=E2=8A=8A.=20(#21461)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- base/exports.jl | 3 +++ base/set.jl | 3 +++ test/sets.jl | 4 ++++ 3 files changed, 10 insertions(+) diff --git a/base/exports.jl b/base/exports.jl index f38b87fe2bff0..67e60c13c5c18 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -729,6 +729,9 @@ export ⊆, ⊈, ⊊, + ⊇, + ⊉, + ⊋, ∩, ∪, diff --git a/base/set.jl b/base/set.jl index eae1e45a53402..63f3534700456 100644 --- a/base/set.jl +++ b/base/set.jl @@ -108,6 +108,9 @@ end const ⊆ = issubset ⊊(l::Set, r::Set) = <(l, r) ⊈(l::Set, r::Set) = !⊆(l, r) +⊇(l, r) = issubset(r, l) +⊉(l::Set, r::Set) = !⊇(l, r) +⊋(l::Set, r::Set) = <(r, l) """ unique(itr) diff --git a/test/sets.jl b/test/sets.jl index c5abf4df21308..7cefbae2d1231 100644 --- a/test/sets.jl +++ b/test/sets.jl @@ -203,6 +203,10 @@ end @test ⊊(Set([1]), Set([1,2])) @test !⊊(Set([1]), Set([1])) @test ⊈(Set([1]), Set([2])) +@test ⊇(Set([1,2]), Set([1])) +@test ⊋(Set([1,2]), Set([1])) +@test !⊋(Set([1]), Set([1])) +@test ⊉(Set([1]), Set([2])) @test symdiff(Set([1,2,3,4]), Set([2,4,5,6])) == Set([1,3,5,6]) # unique From ced691be721a11191a58a589d8ab5cd9322e96eb Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Thu, 20 Apr 2017 17:53:22 -0400 Subject: [PATCH 0481/1534] Make sure the codegen lock is acquired when calling LLVM in cfunction. --- src/codegen.cpp | 11 ++++++++--- test/threads.jl | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index a42f4923ffa8a..5de00ef196c3f 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1544,9 +1544,12 @@ void *jl_function_ptr(jl_function_t *f, jl_value_t *rt, jl_value_t *argt) // TODO: maybe deprecation warning, better checking argt = (jl_value_t*)jl_apply_tuple_type_v((jl_value_t**)jl_data_ptr(argt), jl_nfields(argt)); } + JL_LOCK(&codegen_lock); Function *llvmf = jl_cfunction_object(f, rt, (jl_tupletype_t*)argt); JL_GC_POP(); - return (void*)getAddressForFunction(llvmf); + void *ptr = (void*)getAddressForFunction(llvmf); + JL_UNLOCK(&codegen_lock); + return ptr; } @@ -1565,6 +1568,7 @@ extern "C" JL_DLLEXPORT void jl_extern_c(jl_function_t *f, jl_value_t *rt, jl_value_t *argt, char *name) { assert(jl_is_tuple_type(argt)); + JL_LOCK(&codegen_lock); Function *llvmf = jl_cfunction_object(f, rt, (jl_tupletype_t*)argt); // force eager emission of the function (llvm 3.3 gets confused otherwise and tries to do recursive compilation) uint64_t Addr = getAddressForFunction(llvmf); @@ -1594,6 +1598,7 @@ void jl_extern_c(jl_function_t *f, jl_value_t *rt, jl_value_t *argt, char *name) #else (void)GA; (void)Addr; #endif + JL_UNLOCK(&codegen_lock); } // --- native code info, and dump function to IR and ASM --- @@ -4787,6 +4792,8 @@ const struct jl_typemap_info cfunction_cache = { // here argt does not include the leading function type argument static Function *jl_cfunction_object(jl_function_t *ff, jl_value_t *declrt, jl_tupletype_t *argt) { + // Assumes the codegen lock is acquired. The caller is responsible for that. + // validate and unpack the arguments JL_TYPECHK(cfunction, type, declrt); JL_TYPECHK(cfunction, type, (jl_value_t*)argt); @@ -4856,7 +4863,6 @@ static Function *jl_cfunction_object(jl_function_t *ff, jl_value_t *declrt, jl_t } // Backup the info for the nested compile - JL_LOCK(&codegen_lock); IRBuilderBase::InsertPoint old = builder.saveAndClearIP(); DebugLoc olddl = builder.getCurrentDebugLocation(); bool last_n_c = nested_compile; @@ -4872,7 +4878,6 @@ static Function *jl_cfunction_object(jl_function_t *ff, jl_value_t *declrt, jl_t builder.restoreIP(old); builder.SetCurrentDebugLocation(olddl); nested_compile = last_n_c; - JL_UNLOCK(&codegen_lock); // Might GC JL_GC_POP(); if (f == NULL) jl_rethrow(); diff --git a/test/threads.jl b/test/threads.jl index d0626fdbc3d79..41d8a67069686 100644 --- a/test/threads.jl +++ b/test/threads.jl @@ -381,6 +381,23 @@ for period in (0.06, Dates.Millisecond(60)) end end +complex_cfunction = function(a) + s = zero(eltype(a)) + @inbounds @simd for i in a + s += muladd(a[i], a[i], -2) + end + return s +end +function test_thread_cfunction() + @threads for i in 1:1000 + # Make sure this is not inferrable + # and a runtime call to `jl_function_ptr` will be created + ccall(:jl_function_ptr, Ptr{Void}, (Any, Any, Any), + complex_cfunction, Float64, Tuple{Ref{Vector{Float64}}}) + end +end +test_thread_cfunction() + # Compare the two ways of checking if threading is enabled. # `jl_tls_states` should only be defined on non-threading build. if ccall(:jl_threading_enabled, Cint, ()) == 0 From d1686b918341d55752aa2e173a19267a89b285b1 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Thu, 20 Apr 2017 22:01:23 -0400 Subject: [PATCH 0482/1534] Give symbolic name to special libname on windows. Clean up ccall special case generation conditions. --- src/ccall.cpp | 74 ++++++++++++++++++------------------------- src/dlload.c | 4 +-- src/julia_internal.h | 3 ++ src/runtime_ccall.cpp | 4 +-- 4 files changed, 37 insertions(+), 48 deletions(-) diff --git a/src/ccall.cpp b/src/ccall.cpp index 4691aeb4a6e6e..60ddb2c9f6474 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -815,7 +815,7 @@ static jl_cgval_t emit_cglobal(jl_value_t **args, size_t nargs, jl_codectx_t *ct msg << sym.f_name; if (sym.f_lib != NULL) { #ifdef _OS_WINDOWS_ - assert((intptr_t)sym.f_lib != 1 && (intptr_t)sym.f_lib != 2); + assert(sym.f_lib != JL_EXE_LIBNAME && sym.f_lib != JL_DL_LIBNAME); #endif msg << " in library "; msg << sym.f_lib; @@ -1584,10 +1584,24 @@ static jl_cgval_t emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) if (rt != args[2] && rt != (jl_value_t*)jl_any_type) jl_add_method_root(ctx, rt); + auto _is_libjulia_func = [&] (uintptr_t ptr, const char *name) { + if ((uintptr_t)fptr == ptr) + return true; + return (!f_lib || f_lib == JL_DL_LIBNAME) && f_name && !strcmp(f_name, name); + }; +#define is_libjulia_func(name) _is_libjulia_func((uintptr_t)&(name), #name) + +#ifdef _OS_LINUX_ + // directly accessing the address of an ifunc can cause linker issue on + // some configurations (e.g. AArch64 + -Bsymbolic-functions). + static const auto ptls_getter = jl_dlsym_e(jl_dlopen(nullptr, 0), + "jl_get_ptls_states"); +#else + static const auto ptls_getter = &jl_get_ptls_states; +#endif + // some special functions - if (fptr == (void(*)(void))&jl_array_ptr || - ((f_lib==NULL || (intptr_t)f_lib==2) - && f_name && !strcmp(f_name,"jl_array_ptr"))) { + if (is_libjulia_func(jl_array_ptr)) { assert(lrt->isPointerTy()); assert(!isVa && !llvmcall); assert(nargt==1); @@ -1598,9 +1612,7 @@ static jl_cgval_t emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) return mark_or_box_ccall_result(emit_bitcast(emit_arrayptr(ary, ctx), lrt), retboxed, rt, unionall, static_rt, ctx); } - if (fptr == (void(*)(void))&jl_value_ptr || - ((f_lib==NULL || (intptr_t)f_lib==2) - && f_name && !strcmp(f_name,"jl_value_ptr"))) { + else if (is_libjulia_func(jl_value_ptr)) { assert(lrt->isPointerTy()); assert(!isVa && !llvmcall); assert(nargt==1); @@ -1635,18 +1647,14 @@ static jl_cgval_t emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) return mark_or_box_ccall_result(emit_bitcast(ary, lrt), retboxed, rt, unionall, static_rt, ctx); } - if (JL_CPU_WAKE_NOOP && - (fptr == &jl_cpu_wake || ((!f_lib || (intptr_t)f_lib == 2) && - f_name && !strcmp(f_name, "jl_cpu_wake")))) { + else if (JL_CPU_WAKE_NOOP && is_libjulia_func(jl_cpu_wake)) { assert(lrt == T_void); assert(!isVa && !llvmcall); assert(nargt == 0); JL_GC_POP(); return ghostValue(jl_void_type); } - if (fptr == &jl_gc_safepoint || - ((!f_lib || (intptr_t)f_lib == 2) && f_name && - strcmp(f_name, "jl_gc_safepoint") == 0)) { + else if (is_libjulia_func(jl_gc_safepoint)) { assert(lrt == T_void); assert(!isVa && !llvmcall); assert(nargt == 0); @@ -1657,17 +1665,7 @@ static jl_cgval_t emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) emit_signal_fence(); return ghostValue(jl_void_type); } -#ifdef _OS_LINUX_ - // directly access the address of a ifunc can cause linker issue on - // some configurations (e.g. AArch64 + -Bsymbolic-functions). - static const auto ptls_getter = jl_dlsym_e(jl_dlopen(nullptr, 0), - "jl_get_ptls_states"); -#else - static const auto ptls_getter = &jl_get_ptls_states; -#endif - if (fptr == (void(*)(void))(uintptr_t)ptls_getter || - ((!f_lib || (intptr_t)f_lib == 2) && f_name && - strcmp(f_name, "jl_get_ptls_states") == 0)) { + else if (_is_libjulia_func((uintptr_t)ptls_getter, "jl_get_ptls_states")) { assert(lrt == T_pint8); assert(!isVa && !llvmcall); assert(nargt == 0); @@ -1676,9 +1674,7 @@ static jl_cgval_t emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) emit_bitcast(ctx->ptlsStates, lrt), retboxed, rt, unionall, static_rt, ctx); } - if (fptr == (void(*)(void))&jl_threadid || - ((!f_lib || (intptr_t)f_lib == 2) && f_name && - strcmp(f_name, "jl_threadid") == 0)) { + else if (is_libjulia_func(jl_threadid)) { assert(lrt == T_int16); assert(!isVa && !llvmcall); assert(nargt == 0); @@ -1690,9 +1686,7 @@ static jl_cgval_t emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) tbaa_decorate(tbaa_const, builder.CreateLoad(ptid)), retboxed, rt, unionall, static_rt, ctx); } - if (fptr == &jl_sigatomic_begin || - ((!f_lib || (intptr_t)f_lib == 2) && f_name && - strcmp(f_name, "jl_sigatomic_begin") == 0)) { + else if (is_libjulia_func(jl_sigatomic_begin)) { assert(lrt == T_void); assert(!isVa && !llvmcall); assert(nargt == 0); @@ -1706,9 +1700,7 @@ static jl_cgval_t emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) emit_signal_fence(); return ghostValue(jl_void_type); } - if (fptr == &jl_sigatomic_end || - ((!f_lib || (intptr_t)f_lib == 2) && f_name && - strcmp(f_name, "jl_sigatomic_end") == 0)) { + else if (is_libjulia_func(jl_sigatomic_end)) { assert(lrt == T_void); assert(!isVa && !llvmcall); assert(nargt == 0); @@ -1737,9 +1729,7 @@ static jl_cgval_t emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) builder.SetInsertPoint(contBB); return ghostValue(jl_void_type); } - if (fptr == (void(*)(void))&jl_is_leaf_type || - ((f_lib==NULL || (intptr_t)f_lib==2) - && f_name && !strcmp(f_name, "jl_is_leaf_type"))) { + else if (is_libjulia_func(jl_is_leaf_type)) { assert(nargt == 1); assert(!isVa && !llvmcall); jl_value_t *arg = args[4]; @@ -1751,9 +1741,7 @@ static jl_cgval_t emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) false, rt, unionall, static_rt, ctx); } } - if (fptr == (void(*)(void))&jl_function_ptr || - ((f_lib==NULL || (intptr_t)f_lib==2) - && f_name && !strcmp(f_name, "jl_function_ptr"))) { + else if (is_libjulia_func(jl_function_ptr)) { assert(nargt == 3); assert(!isVa && !llvmcall); jl_value_t *f = static_eval(args[4], ctx, false, false); @@ -1797,10 +1785,8 @@ static jl_cgval_t emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) } JL_GC_POP(); } - if ((fptr == (void(*)(void))&jl_array_isassigned || - ((f_lib==NULL || (intptr_t)f_lib==2) - && f_name && !strcmp(f_name, "jl_array_isassigned"))) && - expr_type(args[6], ctx) == (jl_value_t*)jl_ulong_type) { + else if (is_libjulia_func(jl_array_isassigned) && + expr_type(args[6], ctx) == (jl_value_t*)jl_ulong_type) { assert(nargt == 2); jl_value_t *aryex = args[4]; jl_value_t *idxex = args[6]; @@ -2053,7 +2039,7 @@ jl_cgval_t function_sig_t::emit_a_ccall( msg << symarg.f_name; if (symarg.f_lib != NULL) { #ifdef _OS_WINDOWS_ - assert((intptr_t)symarg.f_lib != 1 && (intptr_t)symarg.f_lib != 2); + assert(symarg.f_lib != JL_EXE_LIBNAME && symarg.f_lib != JL_DL_LIBNAME); #endif msg << " in library "; msg << symarg.f_lib; diff --git a/src/dlload.c b/src/dlload.c index a73813ba33684..c88f901ba9cce 100644 --- a/src/dlload.c +++ b/src/dlload.c @@ -243,9 +243,9 @@ JL_DLLEXPORT void *jl_dlsym(void *handle, const char *symbol) const char *jl_dlfind_win32(const char *f_name) { if (jl_dlsym_e(jl_exe_handle, f_name)) - return (const char*)1; + return JL_EXE_LIBNAME; if (jl_dlsym_e(jl_dl_handle, f_name)) - return (const char*)2; + return JL_DL_LIBNAME; if (jl_dlsym_e(jl_kernel32_handle, f_name)) return "kernel32"; if (jl_dlsym_e(jl_ntdll_handle, f_name)) diff --git a/src/julia_internal.h b/src/julia_internal.h index 32312b7fb046e..fd931962af465 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -684,6 +684,9 @@ extern void *jl_winsock_handle; void *jl_get_library(const char *f_lib); JL_DLLEXPORT void *jl_load_and_lookup(const char *f_lib, const char *f_name, void **hnd); +// Windows only +#define JL_EXE_LIBNAME ((const char*)1) +#define JL_DL_LIBNAME ((const char*)2) const char *jl_dlfind_win32(const char *name); void *jl_dlopen_soname(const char *pfx, size_t n, unsigned flags); diff --git a/src/runtime_ccall.cpp b/src/runtime_ccall.cpp index 470652d6357da..89e10381fee8b 100644 --- a/src/runtime_ccall.cpp +++ b/src/runtime_ccall.cpp @@ -140,9 +140,9 @@ void *jl_get_library(const char *f_lib) { void *hnd; #ifdef _OS_WINDOWS_ - if ((intptr_t)f_lib == 1) + if (f_lib == JL_EXE_LIBNAME) return jl_exe_handle; - if ((intptr_t)f_lib == 2) + if (f_lib == JL_DL_LIBNAME) return jl_dl_handle; #endif if (f_lib == NULL) From 2ba1f3270eb6e2087bb508733590a73013f3620d Mon Sep 17 00:00:00 2001 From: Wonseok Shin Date: Fri, 21 Apr 2017 01:28:56 -0400 Subject: [PATCH 0483/1534] =?UTF-8?q?Add=20tests=20for=20ntuple(f,=20Val{N?= =?UTF-8?q?})=20for=200=20=E2=89=A4=20N=20=E2=89=A4=2015?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- base/tuple.jl | 32 ++++++++++++++++---------------- test/tuple.jl | 5 +++++ 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/base/tuple.jl b/base/tuple.jl index 88463ee3cc00e..f6a6e6ee130f4 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -123,22 +123,22 @@ end _ntuple(f, n) = (@_noinline_meta; ([f(i) for i = 1:n]...)) # inferrable ntuple -ntuple{F}(f::F, ::Type{Val{0}}) = (@_inline_meta; ()) -ntuple{F}(f::F, ::Type{Val{1}}) = (@_inline_meta; (f(1),)) -ntuple{F}(f::F, ::Type{Val{2}}) = (@_inline_meta; (f(1), f(2))) -ntuple{F}(f::F, ::Type{Val{3}}) = (@_inline_meta; (f(1), f(2), f(3))) -ntuple{F}(f::F, ::Type{Val{4}}) = (@_inline_meta; (f(1), f(2), f(3), f(4))) -ntuple{F}(f::F, ::Type{Val{5}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5))) -ntuple{F}(f::F, ::Type{Val{6}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6))) -ntuple{F}(f::F, ::Type{Val{7}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7))) -ntuple{F}(f::F, ::Type{Val{8}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8))) -ntuple{F}(f::F, ::Type{Val{9}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9))) -ntuple{F}(f::F, ::Type{Val{10}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10))) -ntuple{F}(f::F, ::Type{Val{11}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10), f(11))) -ntuple{F}(f::F, ::Type{Val{12}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10), f(11), f(12))) -ntuple{F}(f::F, ::Type{Val{13}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10), f(11), f(12), f(13))) -ntuple{F}(f::F, ::Type{Val{14}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10), f(11), f(12), f(13), f(14))) -ntuple{F}(f::F, ::Type{Val{15}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10), f(11), f(12), f(13), f(14), f(15))) +ntuple(f, ::Type{Val{0}}) = (@_inline_meta; ()) +ntuple(f, ::Type{Val{1}}) = (@_inline_meta; (f(1),)) +ntuple(f, ::Type{Val{2}}) = (@_inline_meta; (f(1), f(2))) +ntuple(f, ::Type{Val{3}}) = (@_inline_meta; (f(1), f(2), f(3))) +ntuple(f, ::Type{Val{4}}) = (@_inline_meta; (f(1), f(2), f(3), f(4))) +ntuple(f, ::Type{Val{5}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5))) +ntuple(f, ::Type{Val{6}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6))) +ntuple(f, ::Type{Val{7}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7))) +ntuple(f, ::Type{Val{8}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8))) +ntuple(f, ::Type{Val{9}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9))) +ntuple(f, ::Type{Val{10}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10))) +ntuple(f, ::Type{Val{11}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10), f(11))) +ntuple(f, ::Type{Val{12}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10), f(11), f(12))) +ntuple(f, ::Type{Val{13}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10), f(11), f(12), f(13))) +ntuple(f, ::Type{Val{14}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10), f(11), f(12), f(13), f(14))) +ntuple(f, ::Type{Val{15}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10), f(11), f(12), f(13), f(14), f(15))) function ntuple{F,N}(f::F, ::Type{Val{N}}) Core.typeassert(N, Int) diff --git a/test/tuple.jl b/test/tuple.jl index 7756797e9af4d..ec94dd8e28413 100644 --- a/test/tuple.jl +++ b/test/tuple.jl @@ -251,3 +251,8 @@ end tuple16int = (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) @test Tuple16Int(tuple16int) isa Tuple16Int end + +# PR #21446 +for n = 0:15 + @test ntuple(identity, Val{n}) == ntuple(identity, n) +end From 64d33748a019303ae603709a9b2dde24903cc021 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Fri, 21 Apr 2017 06:13:36 -0400 Subject: [PATCH 0484/1534] Change all julialang.org links to https --- CONTRIBUTING.md | 18 +++++++------- HISTORY.md | 14 +++++------ Makefile | 2 +- NEWS.md | 2 +- README.md | 24 +++++++++---------- README.windows.md | 6 ++--- base/Enums.jl | 2 +- base/LineEdit.jl | 2 +- base/REPL.jl | 2 +- base/REPLCompletions.jl | 2 +- base/Terminals.jl | 2 +- base/abstractarray.jl | 2 +- base/abstractarraymath.jl | 2 +- base/array.jl | 2 +- base/arraymath.jl | 2 +- base/associative.jl | 2 +- base/asyncmap.jl | 2 +- base/atomics.jl | 2 +- base/base.jl | 2 +- base/base64.jl | 2 +- base/bitarray.jl | 2 +- base/bool.jl | 2 +- base/boot.jl | 2 +- base/broadcast.jl | 2 +- base/c.jl | 2 +- base/cartesian.jl | 2 +- base/channels.jl | 2 +- base/char.jl | 2 +- base/checked.jl | 2 +- base/client.jl | 2 +- base/combinatorics.jl | 2 +- base/complex.jl | 2 +- base/coreimg.jl | 2 +- base/coreio.jl | 2 +- base/ctypes.jl | 2 +- base/dSFMT.jl | 2 +- base/datafmt.jl | 2 +- base/dates/Dates.jl | 2 +- base/dates/accessors.jl | 2 +- base/dates/adjusters.jl | 2 +- base/dates/arithmetic.jl | 2 +- base/dates/conversions.jl | 2 +- base/dates/io.jl | 2 +- base/dates/parse.jl | 2 +- base/dates/periods.jl | 2 +- base/dates/query.jl | 2 +- base/dates/ranges.jl | 2 +- base/dates/rounding.jl | 2 +- base/dates/types.jl | 2 +- base/deepcopy.jl | 2 +- base/deprecated.jl | 2 +- base/dft.jl | 2 +- base/dict.jl | 2 +- base/distributed/Distributed.jl | 2 +- base/distributed/cluster.jl | 2 +- base/distributed/clusterserialize.jl | 2 +- base/distributed/macros.jl | 2 +- base/distributed/managers.jl | 2 +- base/distributed/messages.jl | 2 +- base/distributed/pmap.jl | 2 +- base/distributed/process_messages.jl | 2 +- base/distributed/remotecall.jl | 2 +- base/distributed/workerpool.jl | 2 +- base/docs/Docs.jl | 2 +- base/docs/basedocs.jl | 6 ++--- base/docs/bindings.jl | 2 +- base/docs/core.jl | 2 +- base/docs/helpdb.jl | 2 +- base/docs/helpdb/Base.jl | 2 +- base/docs/utils.jl | 2 +- base/dsp.jl | 2 +- base/emoji_symbols.jl | 2 +- base/env.jl | 2 +- base/errno.jl | 2 +- base/error.jl | 2 +- base/essentials.jl | 2 +- base/event.jl | 2 +- base/exports.jl | 2 +- base/expr.jl | 2 +- base/fastmath.jl | 2 +- base/fft/FFTW.jl | 2 +- base/fft/dct.jl | 2 +- base/file.jl | 2 +- base/filesystem.jl | 2 +- base/float.jl | 2 +- base/floatfuncs.jl | 2 +- base/generator.jl | 2 +- base/gmp.jl | 2 +- base/grisu/grisu.jl | 2 +- base/hashing.jl | 2 +- base/hashing2.jl | 2 +- base/i18n.jl | 2 +- base/indices.jl | 4 ++-- base/inference.jl | 2 +- base/initdefs.jl | 2 +- base/int.jl | 2 +- base/interactiveutil.jl | 2 +- base/intfuncs.jl | 2 +- base/intset.jl | 2 +- base/io.jl | 2 +- base/iobuffer.jl | 2 +- base/iostream.jl | 2 +- base/irrationals.jl | 2 +- base/iterators.jl | 2 +- base/latex_symbols.jl | 2 +- base/libc.jl | 2 +- base/libdl.jl | 2 +- base/libgit2/blob.jl | 2 +- base/libgit2/callbacks.jl | 2 +- base/libgit2/commit.jl | 2 +- base/libgit2/config.jl | 2 +- base/libgit2/consts.jl | 2 +- base/libgit2/diff.jl | 2 +- base/libgit2/error.jl | 2 +- base/libgit2/index.jl | 2 +- base/libgit2/libgit2.jl | 2 +- base/libgit2/merge.jl | 2 +- base/libgit2/oid.jl | 2 +- base/libgit2/rebase.jl | 2 +- base/libgit2/reference.jl | 2 +- base/libgit2/remote.jl | 2 +- base/libgit2/repository.jl | 2 +- base/libgit2/signature.jl | 2 +- base/libgit2/status.jl | 2 +- base/libgit2/strarray.jl | 2 +- base/libgit2/tag.jl | 2 +- base/libgit2/tree.jl | 2 +- base/libgit2/types.jl | 2 +- base/libgit2/utils.jl | 2 +- base/libgit2/walker.jl | 2 +- base/libuv.jl | 2 +- base/linalg/arnoldi.jl | 2 +- base/linalg/arpack.jl | 2 +- base/linalg/bidiag.jl | 2 +- base/linalg/bitarray.jl | 2 +- base/linalg/blas.jl | 2 +- base/linalg/bunchkaufman.jl | 2 +- base/linalg/cholesky.jl | 2 +- base/linalg/conjarray.jl | 2 +- base/linalg/dense.jl | 2 +- base/linalg/diagonal.jl | 2 +- base/linalg/eigen.jl | 2 +- base/linalg/exceptions.jl | 2 +- base/linalg/factorization.jl | 2 +- base/linalg/generic.jl | 2 +- base/linalg/givens.jl | 2 +- base/linalg/hessenberg.jl | 2 +- base/linalg/lapack.jl | 2 +- base/linalg/ldlt.jl | 2 +- base/linalg/linalg.jl | 2 +- base/linalg/lq.jl | 2 +- base/linalg/lu.jl | 2 +- base/linalg/matmul.jl | 2 +- base/linalg/qr.jl | 2 +- base/linalg/rowvector.jl | 2 +- base/linalg/schur.jl | 2 +- base/linalg/special.jl | 2 +- base/linalg/svd.jl | 2 +- base/linalg/symmetric.jl | 2 +- base/linalg/transpose.jl | 2 +- base/linalg/triangular.jl | 2 +- base/linalg/tridiag.jl | 2 +- base/linalg/uniformscaling.jl | 2 +- base/loading.jl | 2 +- base/lock.jl | 2 +- base/locks.jl | 2 +- base/markdown/Common/Common.jl | 2 +- base/markdown/Common/block.jl | 2 +- base/markdown/Common/inline.jl | 2 +- base/markdown/GitHub/GitHub.jl | 2 +- base/markdown/GitHub/table.jl | 2 +- base/markdown/IPython/IPython.jl | 2 +- base/markdown/Julia/Julia.jl | 2 +- base/markdown/Julia/interp.jl | 2 +- base/markdown/Markdown.jl | 2 +- base/markdown/parse/config.jl | 2 +- base/markdown/parse/parse.jl | 2 +- base/markdown/parse/util.jl | 2 +- base/markdown/render/html.jl | 2 +- base/markdown/render/latex.jl | 2 +- base/markdown/render/plain.jl | 2 +- base/markdown/render/rich.jl | 2 +- base/markdown/render/rst.jl | 2 +- base/markdown/render/terminal/formatting.jl | 2 +- base/markdown/render/terminal/render.jl | 2 +- base/math.jl | 2 +- base/meta.jl | 2 +- base/methodshow.jl | 2 +- base/mmap.jl | 2 +- base/mpfr.jl | 2 +- base/multidimensional.jl | 2 +- base/multimedia.jl | 2 +- base/multinverses.jl | 2 +- base/nofloat_hashing.jl | 2 +- base/nullable.jl | 2 +- base/number.jl | 2 +- base/operators.jl | 2 +- base/options.jl | 2 +- base/ordering.jl | 2 +- base/osutils.jl | 2 +- base/pair.jl | 2 +- base/parse.jl | 2 +- base/path.jl | 2 +- base/pcre.jl | 2 +- base/permuteddimsarray.jl | 2 +- base/pkg/cache.jl | 2 +- base/pkg/dir.jl | 2 +- base/pkg/entry.jl | 2 +- base/pkg/pkg.jl | 2 +- base/pkg/query.jl | 2 +- base/pkg/read.jl | 2 +- base/pkg/reqs.jl | 2 +- base/pkg/resolve.jl | 2 +- base/pkg/resolve/fieldvalue.jl | 2 +- base/pkg/resolve/interface.jl | 2 +- base/pkg/resolve/maxsum.jl | 2 +- base/pkg/resolve/versionweight.jl | 2 +- base/pkg/types.jl | 2 +- base/pkg/write.jl | 2 +- base/pointer.jl | 2 +- base/poll.jl | 2 +- base/precompile.jl | 2 +- base/printf.jl | 2 +- base/process.jl | 2 +- base/profile.jl | 2 +- base/promotion.jl | 2 +- base/random.jl | 2 +- base/range.jl | 2 +- base/rational.jl | 2 +- base/reduce.jl | 2 +- base/reducedim.jl | 2 +- base/reflection.jl | 2 +- base/refpointer.jl | 2 +- base/regex.jl | 2 +- base/replutil.jl | 2 +- base/reshapedarray.jl | 2 +- base/rounding.jl | 2 +- base/serialize.jl | 2 +- base/set.jl | 2 +- base/sharedarray.jl | 2 +- base/shell.jl | 2 +- base/show.jl | 2 +- base/simdloop.jl | 2 +- base/socket.jl | 2 +- base/sort.jl | 2 +- base/sparse/abstractsparse.jl | 2 +- base/sparse/cholmod.jl | 2 +- base/sparse/cholmod_h.jl | 2 +- base/sparse/higherorderfns.jl | 2 +- base/sparse/linalg.jl | 2 +- base/sparse/sparse.jl | 2 +- base/sparse/sparsematrix.jl | 2 +- base/sparse/sparsevector.jl | 2 +- base/sparse/spqr.jl | 2 +- base/sparse/umfpack.jl | 2 +- base/sparse/umfpack_h.jl | 2 +- base/special/gamma.jl | 2 +- base/special/log.jl | 2 +- base/special/trig.jl | 2 +- base/stacktraces.jl | 2 +- base/stat.jl | 2 +- base/statistics.jl | 2 +- base/stream.jl | 2 +- base/strings/basic.jl | 2 +- base/strings/errors.jl | 2 +- base/strings/io.jl | 2 +- base/strings/search.jl | 2 +- base/strings/string.jl | 2 +- base/strings/strings.jl | 2 +- base/strings/types.jl | 2 +- base/strings/utf8proc.jl | 2 +- base/strings/util.jl | 2 +- base/subarray.jl | 2 +- base/summarysize.jl | 2 +- base/sysimg.jl | 2 +- base/sysinfo.jl | 2 +- base/task.jl | 2 +- base/test.jl | 2 +- base/threadcall.jl | 2 +- base/threadingconstructs.jl | 2 +- base/threads.jl | 2 +- base/traits.jl | 2 +- base/tuple.jl | 2 +- base/twiceprecision.jl | 2 +- base/util.jl | 2 +- base/version.jl | 6 ++--- base/version_git.sh | 2 +- base/weakkeydict.jl | 2 +- contrib/add_license_to_files.jl | 2 +- contrib/build_sysimg.jl | 2 +- contrib/check-whitespace.sh | 2 +- contrib/commit-name.sh | 2 +- contrib/download_cmake.sh | 2 +- contrib/filterArgs.sh | 2 +- contrib/fixup-libgfortran.sh | 2 +- contrib/fixup-libstdc++.sh | 2 +- contrib/install.sh | 2 +- contrib/julia-config.jl | 2 +- contrib/julia.appdata.xml | 4 ++-- contrib/julia.lang | 10 ++++---- contrib/mac/juliarc.jl | 2 +- contrib/mac/mac-gtk.sh | 2 +- contrib/prepare_release.sh | 2 +- contrib/relative_path.sh | 2 +- contrib/stringreplace.c | 2 +- contrib/travis_fastfail.sh | 2 +- contrib/windows/get_toolchain.sh | 2 +- contrib/windows/msys_build.sh | 2 +- contrib/windows/winrpm.sh | 2 +- doc/README.md | 2 +- doc/man/julia.1 | 6 ++--- doc/src/devdocs/cartesian.md | 2 +- doc/src/manual/arrays.md | 2 +- doc/src/manual/calling-c-and-fortran-code.md | 2 +- doc/src/manual/dates.md | 4 ++-- doc/src/manual/faq.md | 2 +- doc/src/manual/getting-started.md | 6 ++--- doc/src/manual/interacting-with-julia.md | 2 +- examples/ModInts.jl | 2 +- examples/bubblesort.jl | 2 +- examples/clustermanager/0mq/ZMQCM.jl | 2 +- examples/clustermanager/0mq/broker.jl | 2 +- examples/clustermanager/0mq/head.jl | 2 +- examples/clustermanager/0mq/worker.jl | 2 +- .../clustermanager/simple/UnixDomainCM.jl | 2 +- examples/clustermanager/simple/head.jl | 2 +- examples/clustermanager/simple/test_simple.jl | 2 +- examples/dictchannel.jl | 2 +- examples/embedding/embedding.c | 2 +- examples/juliatypes.jl | 2 +- examples/lru.jl | 2 +- examples/lru_test.jl | 2 +- examples/ndgrid.jl | 2 +- examples/queens.jl | 2 +- examples/quine.jl | 6 ++--- examples/staged.jl | 2 +- examples/time.jl | 2 +- examples/typetree.jl | 2 +- examples/wordcount.jl | 2 +- src/APInt-C.cpp | 2 +- src/APInt-C.h | 2 +- src/abi_aarch64.cpp | 2 +- src/abi_arm.cpp | 2 +- src/anticodegen.c | 2 +- src/array.c | 2 +- src/ast.c | 2 +- src/builtin_proto.h | 2 +- src/builtins.c | 2 +- src/ccall.cpp | 2 +- src/ccalltest.c | 2 +- src/cgmemmgr.cpp | 2 +- src/cgutils.cpp | 2 +- src/codegen.cpp | 2 +- src/codegen_internal.h | 2 +- src/datatype.c | 2 +- src/debuginfo.cpp | 2 +- src/dlload.c | 2 +- src/dump.c | 2 +- src/file_constants.h | 2 +- src/fix_llvm_assert.h | 2 +- src/gc-debug.c | 2 +- src/gc-pages.c | 2 +- src/gc.c | 2 +- src/gc.h | 2 +- src/gen_sysimg_symtab.jl | 2 +- src/gf.c | 2 +- src/init.c | 2 +- src/interpreter.c | 2 +- src/intrinsics.cpp | 2 +- src/intrinsics.h | 2 +- src/jitlayers.cpp | 2 +- src/jitlayers.h | 2 +- src/jl_uv.c | 2 +- src/jlapi.c | 2 +- src/jloptions.c | 2 +- src/jltypes.c | 2 +- src/julia.h | 2 +- src/julia_internal.h | 2 +- src/julia_threads.h | 2 +- src/llvm-gcroot.cpp | 2 +- src/llvm-ptls.cpp | 2 +- src/llvm-simdloop.cpp | 2 +- src/llvm-version.h | 2 +- src/method.c | 2 +- src/module.c | 2 +- src/options.h | 2 +- src/precompile.c | 2 +- src/rtutils.c | 2 +- src/runtime_ccall.cpp | 2 +- src/runtime_intrinsics.c | 2 +- src/safepoint.c | 2 +- src/signal-handling.c | 2 +- src/signals-mach.c | 2 +- src/signals-unix.c | 2 +- src/signals-win.c | 2 +- src/simplevector.c | 2 +- src/stackwalk.c | 2 +- src/subtype.c | 2 +- src/support/arraylist.c | 2 +- src/support/arraylist.h | 2 +- src/support/bitvector.c | 2 +- src/support/bitvector.h | 2 +- src/support/crc32c-tables.c | 2 +- src/support/crc32c.h | 2 +- src/support/dirpath.h | 2 +- src/support/dtypes.h | 2 +- src/support/hashing.c | 2 +- src/support/hashing.h | 2 +- src/support/htable.c | 2 +- src/support/htable.h | 2 +- src/support/int2str.c | 2 +- src/support/ios.c | 2 +- src/support/ios.h | 2 +- src/support/libsupport.h | 2 +- src/support/libsupportinit.c | 2 +- src/support/operators.c | 2 +- src/support/platform.h | 2 +- src/support/ptrhash.c | 2 +- src/support/ptrhash.h | 2 +- src/support/strtod.h | 2 +- src/support/timefuncs.c | 2 +- src/support/timefuncs.h | 2 +- src/support/utf8.h | 2 +- src/support/utils.h | 2 +- src/support/wsasocketpair.c | 2 +- src/symbol.c | 2 +- src/sys.c | 2 +- src/table.c | 2 +- src/task.c | 2 +- src/threadgroup.c | 2 +- src/threadgroup.h | 2 +- src/threading.c | 2 +- src/threading.h | 2 +- src/timing.c | 2 +- src/timing.h | 2 +- src/toplevel.c | 2 +- src/typemap.c | 2 +- src/uv_constants.h | 2 +- test/TestHelpers.jl | 4 ++-- test/abstractarray.jl | 2 +- test/ambiguous.jl | 2 +- test/arrayops.jl | 2 +- test/asmvariant.jl | 2 +- test/backtrace.jl | 2 +- test/base64.jl | 2 +- test/bigfloat.jl | 2 +- test/bigint.jl | 2 +- test/bitarray.jl | 2 +- test/blas.jl | 2 +- test/boundscheck.jl | 2 +- test/boundscheck_exec.jl | 2 +- test/broadcast.jl | 2 +- test/cartesian.jl | 2 +- test/ccall.jl | 2 +- test/channels.jl | 2 +- test/char.jl | 2 +- test/checked.jl | 2 +- test/choosetests.jl | 2 +- test/cmdlineargs.jl | 2 +- test/combinatorics.jl | 2 +- test/compile.jl | 2 +- test/complex.jl | 2 +- test/copy.jl | 2 +- test/core.jl | 2 +- test/datafmt.jl | 2 +- test/dates/accessors.jl | 2 +- test/dates/adjusters.jl | 2 +- test/dates/arithmetic.jl | 2 +- test/dates/conversions.jl | 2 +- test/dates/io.jl | 2 +- test/dates/periods.jl | 2 +- test/dates/query.jl | 2 +- test/dates/ranges.jl | 2 +- test/dates/rounding.jl | 2 +- test/dates/types.jl | 2 +- test/dict.jl | 2 +- test/dimensionful.jl | 2 +- test/distributed.jl | 2 +- test/distributed_exec.jl | 2 +- test/docs.jl | 2 +- test/download.jl | 2 +- test/dsp.jl | 2 +- test/embedding.jl | 2 ++ test/enums.jl | 2 +- test/env.jl | 2 +- test/error.jl | 2 +- test/euler.jl | 2 +- test/examples.jl | 2 +- test/fastmath.jl | 2 +- test/fft.jl | 2 +- test/file.jl | 2 +- test/float16.jl | 2 +- test/floatapprox.jl | 2 +- test/floatfuncs.jl | 2 +- test/functional.jl | 2 +- test/goto.jl | 2 +- test/grisu.jl | 2 +- test/hashing.jl | 2 +- test/i18n.jl | 2 +- test/inference.jl | 2 +- test/inline.jl | 2 +- test/int.jl | 2 +- test/intfuncs.jl | 2 +- test/intrinsics.jl | 2 +- test/intset.jl | 2 +- test/iobuffer.jl | 2 +- test/iostream.jl | 2 +- test/iterators.jl | 2 +- test/keywordargs.jl | 2 +- test/libdl.jl | 2 +- test/libgit2-helpers.jl | 2 +- test/libgit2-online.jl | 2 +- test/libgit2.jl | 2 +- test/linalg/arnoldi.jl | 2 +- test/linalg/bidiag.jl | 2 +- test/linalg/bunchkaufman.jl | 2 +- test/linalg/cholesky.jl | 2 +- test/linalg/conjarray.jl | 2 +- test/linalg/dense.jl | 2 +- test/linalg/diagonal.jl | 2 +- test/linalg/eigen.jl | 2 +- test/linalg/generic.jl | 2 +- test/linalg/givens.jl | 2 +- test/linalg/hessenberg.jl | 2 +- test/linalg/lapack.jl | 2 +- test/linalg/lq.jl | 2 +- test/linalg/lu.jl | 2 +- test/linalg/matmul.jl | 2 +- test/linalg/pinv.jl | 2 +- test/linalg/qr.jl | 2 +- test/linalg/rowvector.jl | 2 +- test/linalg/schur.jl | 2 +- test/linalg/special.jl | 2 +- test/linalg/svd.jl | 2 +- test/linalg/symmetric.jl | 2 +- test/linalg/triangular.jl | 2 +- test/linalg/tridiag.jl | 2 +- test/linalg/uniformscaling.jl | 2 +- test/lineedit.jl | 2 +- test/llvmcall.jl | 2 +- test/llvmcall2.jl | 2 +- test/loading.jl | 2 +- test/markdown.jl | 2 +- test/math.jl | 2 +- test/meta.jl | 2 +- test/misc.jl | 2 +- test/mmap.jl | 2 +- test/mod2pi.jl | 2 +- test/mpfr.jl | 2 +- test/netload/memtest.jl | 2 +- test/netload/nettest.jl | 2 +- test/nullable.jl | 2 +- test/numbers.jl | 2 +- test/offsetarray.jl | 2 +- test/operators.jl | 2 +- test/osutils.jl | 2 +- test/parse.jl | 2 +- test/path.jl | 2 +- test/perf/README.md | 2 +- test/perf/array/indexing.jl | 2 +- test/perf/array/perf.jl | 2 +- test/perf/blas/level1.jl | 2 +- test/perf/blas/level2.jl | 2 +- test/perf/blas/level3.jl | 2 +- test/perf/blas/perf.jl | 2 +- test/perf/cat/perf.jl | 2 +- test/perf/kernel/actor_centrality.jl | 2 +- test/perf/kernel/bench_eu.jl | 2 +- test/perf/kernel/getdivgrad.jl | 2 +- test/perf/kernel/gk.jl | 2 +- test/perf/kernel/go_benchmark.c | 2 +- test/perf/kernel/go_benchmark.jl | 2 +- test/perf/kernel/indexing.jl | 2 +- test/perf/kernel/json.jl | 2 +- test/perf/kernel/laplace.jl | 2 +- test/perf/kernel/laplace/c_laplace.c | 2 +- .../laplace/c_laplace_parallel_update.c | 2 +- .../c_laplace_parallel_update_pointer.c | 2 +- test/perf/kernel/laplace/cilk_laplace.c | 2 +- test/perf/kernel/perf.jl | 2 +- test/perf/kernel/raytracer.jl | 2 +- test/perf/kernel/simplex.jl | 2 +- test/perf/kernel/stockcorr.jl | 2 +- test/perf/kernel/ziggurat.jl | 2 +- test/perf/lapack/eig.jl | 2 +- test/perf/lapack/factorizations.jl | 2 +- test/perf/lapack/perf.jl | 2 +- test/perf/micro/java/setup.sh | 2 +- test/perf/micro/perf.c | 2 +- test/perf/micro/perf.jl | 2 +- test/perf/micro/scala/build.sbt | 2 +- .../micro/scala/src/main/scala/perf.scala | 2 +- test/perf/perfcomp.jl | 2 +- test/perf/perfgeneric.jl | 2 +- test/perf/perfutil.jl | 2 +- test/perf/report.jl | 2 +- test/perf/shootout/binary_trees.jl | 2 +- test/perf/shootout/fannkuch.jl | 2 +- test/perf/shootout/fasta.jl | 2 +- test/perf/shootout/k_nucleotide.jl | 2 +- test/perf/shootout/mandelbrot.jl | 2 +- test/perf/shootout/meteor_contest.jl | 2 +- test/perf/shootout/nbody.jl | 2 +- test/perf/shootout/nbody_vec.jl | 2 +- test/perf/shootout/perf.jl | 2 +- test/perf/shootout/pidigits.jl | 2 +- test/perf/shootout/regex_dna.jl | 2 +- test/perf/shootout/revcomp.jl | 2 +- test/perf/shootout/spectralnorm.jl | 2 +- test/perf/simd/axpy.jl | 2 +- test/perf/simd/inner.jl | 2 +- test/perf/simd/perf.jl | 2 +- test/perf/simd/seismic_fdtd.jl | 2 +- test/perf/simd/sum_reduce.jl | 2 +- test/perf/sort/perf.jl | 2 +- test/perf/sparse/fem.jl | 2 +- test/perf/sparse/getindex.jl | 2 +- test/perf/sparse/getindex_skinny.jl | 2 +- test/perf/sparse/perf.jl | 2 +- test/perf/spell/perf.jl | 2 +- test/perf/threads/laplace3d/laplace3d.c | 2 +- test/perf/threads/laplace3d/laplace3d.jl | 2 +- test/perf/threads/lbm3d/circshift.jl | 2 +- test/perf/threads/lbm3d/lbm3d.jl | 2 +- test/perf/threads/stockcorr/pstockcorr.jl | 2 +- test/pkg.jl | 2 +- test/pollfd.jl | 2 +- test/printf.jl | 2 +- test/profile.jl | 2 +- test/random.jl | 2 +- test/ranges.jl | 2 +- test/read.jl | 2 +- test/reduce.jl | 2 +- test/reducedim.jl | 2 +- test/reflection.jl | 2 +- test/regex.jl | 2 +- test/repl.jl | 2 +- test/replcompletions.jl | 2 +- test/replutil.jl | 2 +- test/resolve.jl | 2 +- test/rounding.jl | 2 +- test/runtests.jl | 2 +- test/serialize.jl | 2 +- test/sets.jl | 2 +- test/show.jl | 2 +- test/simdloop.jl | 2 +- test/socket.jl | 2 +- test/sorting.jl | 2 +- test/sparse/cholmod.jl | 2 +- test/sparse/higherorderfns.jl | 2 +- test/sparse/sparse.jl | 2 +- test/sparse/sparsevector.jl | 2 +- test/sparse/spqr.jl | 2 +- test/sparse/umfpack.jl | 2 +- test/spawn.jl | 2 +- test/stacktraces.jl | 2 +- test/staged.jl | 2 +- test/statistics.jl | 2 +- test/strings/basic.jl | 2 +- test/strings/io.jl | 2 +- test/strings/search.jl | 2 +- test/strings/types.jl | 2 +- test/strings/util.jl | 2 +- test/subarray.jl | 2 +- test/subtype.jl | 2 +- test/sysinfo.jl | 2 +- test/test.jl | 2 +- test/test_exec.jl | 2 +- test/test_sourcepath.jl | 2 +- test/testdefs.jl | 2 +- test/threads.jl | 2 +- test/topology.jl | 2 +- test/triplequote.jl | 2 +- test/tuple.jl | 2 +- test/unicode/UnicodeError.jl | 2 +- test/unicode/utf8.jl | 2 +- test/unicode/utf8proc.jl | 2 +- test/util/segfault.jl | 2 +- test/util/throw_error_exception.jl | 2 +- test/vecelement.jl | 2 +- test/version.jl | 2 +- test/workspace.jl | 2 +- test/worlds.jl | 2 +- ui/repl.c | 2 +- 684 files changed, 730 insertions(+), 728 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4a050793693b8..1227328ef56a8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,10 +1,10 @@ # Notes for Julia Contributors -Hi! If you are new to the Julia community: welcome, and thanks for trying Julia. Please be sure to respect our [community standards](http://julialang.org/community/standards/) in all interactions. +Hi! If you are new to the Julia community: welcome, and thanks for trying Julia. Please be sure to respect our [community standards](https://julialang.org/community/standards/) in all interactions. ## Learning Julia -[The learning page](http://julialang.org/learning/) has a great list of resources for new and experienced users alike. [This tutorial video](https://www.youtube.com/watch?v=vWkgEddb4-A) is one recommended starting point, as is the "[Invitation to Julia](https://www.youtube.com/watch?v=gQ1y5NUD_RI)" workshop video from JuliaCon 2015 ([slide materials here](https://github.com/dpsanders/invitation_to_julia)). The [Julia documentation](http://docs.Julialang.org/en/latest/) covers the language and core library features, and is [searchable](http://docs.Julialang.org/en/latest/search/). (note: Javascript required). +[The learning page](https://julialang.org/learning/) has a great list of resources for new and experienced users alike. [This tutorial video](https://www.youtube.com/watch?v=vWkgEddb4-A) is one recommended starting point, as is the "[Invitation to Julia](https://www.youtube.com/watch?v=gQ1y5NUD_RI)" workshop video from JuliaCon 2015 ([slide materials here](https://github.com/dpsanders/invitation_to_julia)). The [Julia documentation](http://docs.Julialang.org/en/latest/) covers the language and core library features, and is [searchable](http://docs.Julialang.org/en/latest/search/). (note: Javascript required). ## Before filing an issue @@ -12,7 +12,7 @@ Hi! If you are new to the Julia community: welcome, and thanks for trying Julia. - Contributing code? Be sure to review the [contributor checklist](https://github.com/JuliaLang/julia/blob/master/CONTRIBUTING.md#contributor-checklist) for helpful tips on the tools we use to build Julia. -- Library feature requests are generally not accepted on this issue tracker. New libraries should be developed as [packages](http://docs.julialang.org/en/release-0.4/manual/packages/#package-development). Discuss ideas for libraries at the [Julia Discourse forum](https://discourse.julialang.org/). Doing so will often lead to pointers to existing projects and bring together collaborators with common interests. +- Library feature requests are generally not accepted on this issue tracker. New libraries should be developed as [packages](https://docs.julialang.org/en/release-0.4/manual/packages/#package-development). Discuss ideas for libraries at the [Julia Discourse forum](https://discourse.julialang.org/). Doing so will often lead to pointers to existing projects and bring together collaborators with common interests. ## Contributor Checklist @@ -56,7 +56,7 @@ A useful bug report filed as a GitHub issue provides information about how to re ### Contributing a Julia package -Julia has a built-in [package manager](https://github.com/JuliaLang/METADATA.jl) based on `git`. A number of [packages](http://pkg.julialang.org/) across many domains are already available for Julia. Developers are encouraged to provide their libraries as a Julia package. The Julia manual provides instructions on [creating Julia packages](http://docs.julialang.org/en/latest/manual/packages/). +Julia has a built-in [package manager](https://github.com/JuliaLang/METADATA.jl) based on `git`. A number of [packages](http://pkg.julialang.org/) across many domains are already available for Julia. Developers are encouraged to provide their libraries as a Julia package. The Julia manual provides instructions on [creating Julia packages](https://docs.julialang.org/en/latest/manual/packages/). For developers who need to wrap C libraries so that they can be called from Julia, the [Clang.jl](https://github.com/ihnorton/Clang.jl) package can help generate the wrappers automatically from the C header files. @@ -262,19 +262,19 @@ Make sure that [Travis](http://www.travis-ci.org) greenlights the pull request w ## Resources * Julia - - **Homepage:** - - **Community:** + - **Homepage:** + - **Community:** - **IRC:** - **Source code:** - **Git clone URL:** - - **Documentation:** + - **Documentation:** - **Status:** - **Code coverage:** * Design of Julia - [Julia: A Fresh Approach to Numerical Computing](http://arxiv.org/pdf/1411.1607v3.pdf) - - [Julia: A Fast Dynamic Language for Technical Computing](http://julialang.org/images/julia-dynamic-2012-tr.pdf) - - [All Julia Publications](http://julialang.org/publications/) + - [Julia: A Fast Dynamic Language for Technical Computing](https://julialang.org/images/julia-dynamic-2012-tr.pdf) + - [All Julia Publications](https://julialang.org/publications/) * Using GitHub - [Using Julia with GitHub (video)](http://www.youtube.com/watch?v=wnFYV3ZKtOg&feature=youtu.be) diff --git a/HISTORY.md b/HISTORY.md index 03c5a849cd5c2..64383dcfaa848 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -51,7 +51,7 @@ Experimental language features ------------------------------ * Support for - [multi-threading](http://docs.julialang.org/en/latest/manual/parallel-computing/#multi-threading-experimental). + [multi-threading](https://docs.julialang.org/en/latest/manual/parallel-computing/#multi-threading-experimental). Loops with independent iterations can be easily parallelized with the `Threads.@threads` macro. @@ -453,7 +453,7 @@ Deprecated or removed * `@unix_only` is deprecated in favor of `if is_unix()` * `@osx_only` is deprecated in favor of `if is_apple()` * `@linux_only` is deprecated in favor of `if is_linux()` - * NOTE: Using `@static` could be useful/necessary when used in a function's local scope. See details at the section entitled [Handling Operating System Variation](http://docs.julialang.org/en/latest/manual/handling-operating-system-variation/#man-handling-operating-system-variation) in the manual. + * NOTE: Using `@static` could be useful/necessary when used in a function's local scope. See details at the section entitled [Handling Operating System Variation](https://docs.julialang.org/en/latest/manual/handling-operating-system-variation/#man-handling-operating-system-variation) in the manual. Command-line option changes --------------------------- @@ -510,7 +510,7 @@ New language features types instead of to their values. The function then returns an expression forming the body of the function to be called at run time ([#7311]). - * [Documentation system](http://docs.julialang.org/en/latest/manual/documentation/) + * [Documentation system](https://docs.julialang.org/en/latest/manual/documentation/) for functions, methods, types and macros in packages and user code ([#8791]). * The syntax `function foo end` can be used to introduce a generic function without @@ -540,11 +540,11 @@ New language features * `++` is now parsed as an infix operator, but does not yet have a default definition ([#11030], [#11686]). * Support for inter-task communication using `Channels` ([#12264]). - See http://docs.julialang.org/en/latest/manual/parallel-computing/#channels for details. + See https://docs.julialang.org/en/latest/manual/parallel-computing/#channels for details. * `RemoteRef`s now point to remote channels. The remote channels can be of length greater than 1. Default continues to be of length 1 ([#12385]). - See http://docs.julialang.org/en/latest/manual/parallel-computing/#remoterefs-and-abstractchannels for details. + See https://docs.julialang.org/en/latest/manual/parallel-computing/#remoterefs-and-abstractchannels for details. * `@__LINE__` special macro now available to reflect invocation source line number ([#12727]). @@ -1745,8 +1745,8 @@ Bugfixes and performance updates Too numerous to mention. -[packages chapter]: http://docs.julialang.org/en/latest/manual/packages/ -[sorting functions]: http://docs.julialang.org/en/latest/stdlib/sort/ +[packages chapter]: https://docs.julialang.org/en/latest/manual/packages/ +[sorting functions]: https://docs.julialang.org/en/latest/stdlib/sort/ [pairwise summation]: https://en.wikipedia.org/wiki/Pairwise_summation [a448e080]: https://github.com/JuliaLang/julia/commit/a448e080dc736c7fb326426dfcb2528be36973d3 [5e3f074b]: https://github.com/JuliaLang/julia/commit/5e3f074b9173044a0a4219f9b285879ff7cec041 diff --git a/Makefile b/Makefile index 337643c272bb7..59be4206adc1b 100644 --- a/Makefile +++ b/Makefile @@ -155,7 +155,7 @@ release-candidate: release testall @echo 6. Clean out old .tar.gz files living in deps/, "\`git clean -fdx\`" seems to work #"` @echo 7. Replace github release tarball with tarballs created from make light-source-dist and make full-source-dist @echo 8. Follow packaging instructions in DISTRIBUTING.md to create binary packages for all platforms - @echo 9. Upload to AWS, update http://julialang.org/downloads and http://status.julialang.org/stable links + @echo 9. Upload to AWS, update https://julialang.org/downloads and http://status.julialang.org/stable links @echo 10. Update checksums on AWS for tarball and packaged binaries @echo 11. Announce on mailing lists @echo 12. Change master to release-0.X in base/version.jl and base/version_git.sh as in 4cb1e20 diff --git a/NEWS.md b/NEWS.md index 9f9811b9188f9..e48a0b28245fb 100644 --- a/NEWS.md +++ b/NEWS.md @@ -276,7 +276,7 @@ Library improvements `JULIA_INPUT_COLOR` and `JULIA_ANSWER_COLOR` to `"bold"`. For example, one way of doing this is adding `ENV["JULIA_INPUT_COLOR"] = :bold` and `ENV["JULIA_ANSWER_COLOR"] = :bold` to the `.juliarc.jl` file. See the - [manual section on customizing colors](http://docs.julialang.org/en/latest/manual/interacting-with-julia#Customizing-Colors-1) + [manual section on customizing colors](https://docs.julialang.org/en/latest/manual/interacting-with-julia#Customizing-Colors-1) for more information. * The default color for info messages has been changed from blue to cyan diff --git a/README.md b/README.md index e2e9f95a8f737..d5533a3992263 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ @@ -14,19 +14,19 @@ Code Coverage: [![Coverage Status](https://coveralls.io/repos/JuliaLang/julia/ba ## The Julia Language Julia is a high-level, high-performance dynamic language for technical computing. -The main homepage for Julia can be found at [julialang.org](http://julialang.org/). +The main homepage for Julia can be found at [julialang.org](https://julialang.org/). This is the GitHub repository of Julia source code, including instructions for compiling and installing Julia, below. ## Resources -- **Homepage:** -- **Binaries:** -- **Documentation:** +- **Homepage:** +- **Binaries:** +- **Documentation:** - **Packages:** - **Source code:** - **Git clone URL:** - **Discussion forum:** -- **Mailing lists:** +- **Mailing lists:** - **Gitter:** - **IRC:** - **Code coverage:** @@ -100,7 +100,7 @@ the `julia` source directory, type `make testall`. You should see output that lists a series of tests being run; if they complete without error, you should be in good shape to start using Julia. -You can read about [getting started](http://docs.julialang.org/en/stable/manual/getting-started/) in the manual. +You can read about [getting started](https://docs.julialang.org/en/stable/manual/getting-started/) in the manual. If you are building a Julia package for distribution on Linux, OS X, or Windows, take a look at the detailed notes in @@ -317,7 +317,7 @@ Julia uses the following external libraries, which are automatically downloaded [MPFR]: http://www.mpfr.org [libuv]: https://github.com/JuliaLang/libuv [libgit2]: https://libgit2.github.com/ -[utf8proc]: http://julialang.org/utf8proc/ +[utf8proc]: https://julialang.org/utf8proc/ [libosxunwind]: https://github.com/JuliaLang/libosxunwind [libunwind]: http://www.nongnu.org/libunwind [libssh2]: https://www.libssh2.org @@ -373,7 +373,7 @@ The Julia source code is organized as follows: ## Binary Installation -If you would rather not compile the latest Julia from source, platform-specific tarballs with pre-compiled binaries are also [available for download](http://julialang.org/downloads/). +If you would rather not compile the latest Julia from source, platform-specific tarballs with pre-compiled binaries are also [available for download](https://julialang.org/downloads/). You can either run the `julia` executable using its full path in the directory created above, or add that directory to your executable path so that you can run the Julia program from anywhere (in the current shell session): @@ -386,7 +386,7 @@ Now you should be able to run Julia like this: On Windows, double-click `usr/bin/julia.exe`. If everything works correctly, you will see a Julia banner and an interactive prompt into which you can enter expressions for evaluation. -You can read about [getting started](http://julialang.org/manual/getting-started) in the manual. +You can read about [getting started](https://julialang.org/manual/getting-started) in the manual. The following distributions include julia, but the versions may be out of date due to rapid development: @@ -427,4 +427,4 @@ is available through [Sublime-IJulia](https://github.com/quinnj/Sublime-IJulia) plugin enables interaction between IJulia and Sublime Text. -In the terminal, Julia makes great use of both control-key and meta-key bindings. To make the meta-key bindings more accessible, many terminal emulator programs (e.g., `Terminal`, `iTerm`, `xterm`, etc.) allow you to use the alt or option key as meta. See the section in the manual on [interacting with Julia](http://docs.julialang.org/en/latest/manual/interacting-with-julia/) for more details. +In the terminal, Julia makes great use of both control-key and meta-key bindings. To make the meta-key bindings more accessible, many terminal emulator programs (e.g., `Terminal`, `iTerm`, `xterm`, etc.) allow you to use the alt or option key as meta. See the section in the manual on [interacting with Julia](https://docs.julialang.org/en/latest/manual/interacting-with-julia/) for more details. diff --git a/README.windows.md b/README.windows.md index 36aab711e0984..96ccc1a7f9f17 100644 --- a/README.windows.md +++ b/README.windows.md @@ -4,7 +4,7 @@ This file describes how to install, or build, and use Julia on Windows. For more general information about Julia, please see the [main README](https://github.com/JuliaLang/julia/blob/master/README.md) -or the [documentation](http://docs.julialang.org/). +or the [documentation](https://docs.julialang.org/). ## General Information for Windows @@ -56,7 +56,7 @@ Both the 32-bit and 64-bit versions are supported. The 32-bit (i686) binary will run on either a 32-bit and 64-bit operating system. The 64-bit (x86_64) binary will only run on 64-bit Windows and will otherwise refuse to launch. - 1. [Download](http://julialang.org/downloads) the latest version of Julia. + 1. [Download](https://julialang.org/downloads) the latest version of Julia. Extract the binary to a reasonable destination folder, e.g. `C:\julia`. 2. Double-click the `julia` shortcut to launch Julia. @@ -161,7 +161,7 @@ The 64-bit (x86_64) binary will only run on 64-bit Windows and will otherwise re 5. Setup Package Development Environment 1. The `Pkg` module in Base provides many convenient tools for [developing - and publishing packages](http://docs.julialang.org/en/latest/manual/packages/). + and publishing packages](https://docs.julialang.org/en/latest/manual/packages/). One of the packages added through pacman above was `openssh`, which will allow secure access to GitHub APIs. Follow GitHub's [guide]( https://help.github.com/articles/generating-ssh-keys) to setting up SSH diff --git a/base/Enums.jl b/base/Enums.jl index 48e9e63ecda60..e29efb296e087 100644 --- a/base/Enums.jl +++ b/base/Enums.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Enums diff --git a/base/LineEdit.jl b/base/LineEdit.jl index 0334817dc5630..5df447d9837a6 100644 --- a/base/LineEdit.jl +++ b/base/LineEdit.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module LineEdit diff --git a/base/REPL.jl b/base/REPL.jl index 229bc76b799b4..90f97799a8408 100644 --- a/base/REPL.jl +++ b/base/REPL.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module REPL diff --git a/base/REPLCompletions.jl b/base/REPLCompletions.jl index 1d5adf2f81ee6..f5626e5f5c57a 100644 --- a/base/REPLCompletions.jl +++ b/base/REPLCompletions.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module REPLCompletions diff --git a/base/Terminals.jl b/base/Terminals.jl index a4f2747b7152c..479d3c30914c2 100644 --- a/base/Terminals.jl +++ b/base/Terminals.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Terminals diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 5a839d9826185..992a4102ae009 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## Basic functions ## diff --git a/base/abstractarraymath.jl b/base/abstractarraymath.jl index ec0b6440de291..03e753c052e5e 100644 --- a/base/abstractarraymath.jl +++ b/base/abstractarraymath.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## Basic functions ## diff --git a/base/array.jl b/base/array.jl index 450f35db02128..798ff605b946b 100644 --- a/base/array.jl +++ b/base/array.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## array.jl: Dense arrays diff --git a/base/arraymath.jl b/base/arraymath.jl index 762a582b53791..5357b0c43ae4d 100644 --- a/base/arraymath.jl +++ b/base/arraymath.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## Unary operators ## diff --git a/base/associative.jl b/base/associative.jl index 1815f03bc3517..b49c5b54bfd47 100644 --- a/base/associative.jl +++ b/base/associative.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # generic operations on associative collections diff --git a/base/asyncmap.jl b/base/asyncmap.jl index fcfeedd24d0be..19846ab7a0ced 100644 --- a/base/asyncmap.jl +++ b/base/asyncmap.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Iterators.Enumerate diff --git a/base/atomics.jl b/base/atomics.jl index 09bd9788637cd..c053857922f51 100644 --- a/base/atomics.jl +++ b/base/atomics.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Core.Intrinsics: llvmcall diff --git a/base/base.jl b/base/base.jl index 652b9106a18c1..c8e046d2cd687 100644 --- a/base/base.jl +++ b/base/base.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license """ SystemError(prefix::AbstractString, [errno::Int32]) diff --git a/base/base64.jl b/base/base64.jl index 743f055ca9f11..99f507e48b7df 100644 --- a/base/base64.jl +++ b/base/base64.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Base64 import Base: read, write, close, eof, empty! diff --git a/base/bitarray.jl b/base/bitarray.jl index 99faeebf38183..450222cd396cc 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## BitArray diff --git a/base/bool.jl b/base/bool.jl index a874de0ca6bec..4ea9c0911b6d8 100644 --- a/base/bool.jl +++ b/base/bool.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## boolean conversions ## diff --git a/base/boot.jl b/base/boot.jl index 1e01b32f45aa2..5c7af3b10cd4b 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # commented-out definitions are implemented in C diff --git a/base/broadcast.jl b/base/broadcast.jl index 53927084de7f9..30a73573e27aa 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Broadcast diff --git a/base/c.jl b/base/c.jl index 34d4f86c80c4a..edd149dda1929 100644 --- a/base/c.jl +++ b/base/c.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # definitions related to C interface diff --git a/base/cartesian.jl b/base/cartesian.jl index 18e31f0f161f9..86068a28baded 100644 --- a/base/cartesian.jl +++ b/base/cartesian.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Cartesian diff --git a/base/channels.jl b/base/channels.jl index a6c8859b20abe..bad26f9abae59 100644 --- a/base/channels.jl +++ b/base/channels.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license abstract type AbstractChannel end diff --git a/base/char.jl b/base/char.jl index 3e72f88608fc8..6add31b91019a 100644 --- a/base/char.jl +++ b/base/char.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license convert(::Type{Char}, x::UInt32) = reinterpret(Char, x) convert(::Type{Char}, x::Number) = Char(UInt32(x)) diff --git a/base/checked.jl b/base/checked.jl index 37310d0a35e90..b466ff8c3a1d6 100644 --- a/base/checked.jl +++ b/base/checked.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Support for checked integer arithmetic diff --git a/base/client.jl b/base/client.jl index 268a24d692373..9a7cfa39816e4 100644 --- a/base/client.jl +++ b/base/client.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## client.jl - frontend handling command line options, environment setup, ## and REPL diff --git a/base/combinatorics.jl b/base/combinatorics.jl index 7388e7ecd1b56..920f6c23d944e 100644 --- a/base/combinatorics.jl +++ b/base/combinatorics.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Factorials diff --git a/base/complex.jl b/base/complex.jl index 3d0bf6cebcf84..e763b99d251ef 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license struct Complex{T<:Real} <: Number re::T diff --git a/base/coreimg.jl b/base/coreimg.jl index fe5b5547fdce2..8b552d51252e7 100644 --- a/base/coreimg.jl +++ b/base/coreimg.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license Main.Core.eval(Main.Core, :(baremodule Inference using Core.Intrinsics diff --git a/base/coreio.jl b/base/coreio.jl index f47286f9ea62d..b15fca1ea1003 100644 --- a/base/coreio.jl +++ b/base/coreio.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license show(x) = show(STDOUT::IO, x) print(xs...) = print(STDOUT::IO, xs...) diff --git a/base/ctypes.jl b/base/ctypes.jl index 6dccd586459ca..387fdd9d8c7dd 100644 --- a/base/ctypes.jl +++ b/base/ctypes.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # essential type definitions for interacting with C code # (platform- or OS-dependent types are defined in c.jl) diff --git a/base/dSFMT.jl b/base/dSFMT.jl index bf58595fd4a2b..c95b372d9b6a5 100644 --- a/base/dSFMT.jl +++ b/base/dSFMT.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module dSFMT diff --git a/base/datafmt.jl b/base/datafmt.jl index 7637e7d36ab84..71c7db57b2c19 100644 --- a/base/datafmt.jl +++ b/base/datafmt.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## file formats ## diff --git a/base/dates/Dates.jl b/base/dates/Dates.jl index 355ef1760b51e..c8a5321432a3a 100644 --- a/base/dates/Dates.jl +++ b/base/dates/Dates.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Dates diff --git a/base/dates/accessors.jl b/base/dates/accessors.jl index 4022f4172beb3..d6ca886643001 100644 --- a/base/dates/accessors.jl +++ b/base/dates/accessors.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Convert # of Rata Die days to proleptic Gregorian calendar y,m,d,w # Reference: http://mysite.verizon.net/aesir_research/date/date0.htm diff --git a/base/dates/adjusters.jl b/base/dates/adjusters.jl index eebc68b59b5ad..357faec442a27 100644 --- a/base/dates/adjusters.jl +++ b/base/dates/adjusters.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ### truncation Base.trunc(dt::Date, p::Type{Year}) = Date(UTD(totaldays(year(dt), 1, 1))) diff --git a/base/dates/arithmetic.jl b/base/dates/arithmetic.jl index ac59b4971e3ab..7171ea8cb8fba 100644 --- a/base/dates/arithmetic.jl +++ b/base/dates/arithmetic.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Instant arithmetic (+)(x::Instant) = x diff --git a/base/dates/conversions.jl b/base/dates/conversions.jl index b406d1d47b78c..9016c5600d149 100644 --- a/base/dates/conversions.jl +++ b/base/dates/conversions.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Conversion/Promotion diff --git a/base/dates/io.jl b/base/dates/io.jl index 608d509ec4c64..0a6292bc5058d 100644 --- a/base/dates/io.jl +++ b/base/dates/io.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license """ AbstractDateToken diff --git a/base/dates/parse.jl b/base/dates/parse.jl index f81a827c4d1e4..1dc76323521e8 100644 --- a/base/dates/parse.jl +++ b/base/dates/parse.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ### Parsing utilities diff --git a/base/dates/periods.jl b/base/dates/periods.jl index 0779d8446fed6..0091f54476dae 100644 --- a/base/dates/periods.jl +++ b/base/dates/periods.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license #Period types value(x::Period) = x.value diff --git a/base/dates/query.jl b/base/dates/query.jl index 5862196583f3a..effdd68a1bbdf 100644 --- a/base/dates/query.jl +++ b/base/dates/query.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Date Locales diff --git a/base/dates/ranges.jl b/base/dates/ranges.jl index 3f9717fb21495..e58d3e7a0f841 100644 --- a/base/dates/ranges.jl +++ b/base/dates/ranges.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Date/DateTime Ranges diff --git a/base/dates/rounding.jl b/base/dates/rounding.jl index 0f10cf5ca93b1..b1714fff075ef 100644 --- a/base/dates/rounding.jl +++ b/base/dates/rounding.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # The epochs used for date rounding are based ISO 8601's "year zero" notation const DATEEPOCH = value(Date(0)) diff --git a/base/dates/types.jl b/base/dates/types.jl index 3a2d67415339f..2550b4a9ae412 100644 --- a/base/dates/types.jl +++ b/base/dates/types.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license abstract type AbstractTime end diff --git a/base/deepcopy.jl b/base/deepcopy.jl index 42d169be30a57..929f67c8cf67b 100644 --- a/base/deepcopy.jl +++ b/base/deepcopy.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # deep copying diff --git a/base/deprecated.jl b/base/deprecated.jl index eda5caa42f303..17e49108f1434 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Deprecated functions and objects # diff --git a/base/dft.jl b/base/dft.jl index 6239a3b4e23ba..99897b7e2174f 100644 --- a/base/dft.jl +++ b/base/dft.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module DFT diff --git a/base/dict.jl b/base/dict.jl index 202f844050cb4..07e2d5923d2c3 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license function _truncate_at_width_or_chars(str, width, chars="", truncmark="…") truncwidth = strwidth(truncmark) diff --git a/base/distributed/Distributed.jl b/base/distributed/Distributed.jl index 1405ab11867b5..36e4bcba53fc9 100644 --- a/base/distributed/Distributed.jl +++ b/base/distributed/Distributed.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Distributed diff --git a/base/distributed/cluster.jl b/base/distributed/cluster.jl index 2d1d4fe1a38e4..053f600da025a 100644 --- a/base/distributed/cluster.jl +++ b/base/distributed/cluster.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license abstract type ClusterManager end diff --git a/base/distributed/clusterserialize.jl b/base/distributed/clusterserialize.jl index 043ca57abf576..7d44c17b56f73 100644 --- a/base/distributed/clusterserialize.jl +++ b/base/distributed/clusterserialize.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Serializer: known_object_data, object_number, serialize_cycle, deserialize_cycle, writetag, __deserialized_types__, serialize_typename, deserialize_typename, diff --git a/base/distributed/macros.jl b/base/distributed/macros.jl index 51e5405c0f09a..e0f7b82f1f068 100644 --- a/base/distributed/macros.jl +++ b/base/distributed/macros.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license let nextidx = 0 global nextproc diff --git a/base/distributed/managers.jl b/base/distributed/managers.jl index bf66ead246bcd..aa0104f16218c 100644 --- a/base/distributed/managers.jl +++ b/base/distributed/managers.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Built-in SSH and Local Managers diff --git a/base/distributed/messages.jl b/base/distributed/messages.jl index dc95b032e2efa..aee31cec8bf50 100644 --- a/base/distributed/messages.jl +++ b/base/distributed/messages.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license abstract type AbstractMsg end diff --git a/base/distributed/pmap.jl b/base/distributed/pmap.jl index 9e8c6530796f1..e470ae24d8309 100644 --- a/base/distributed/pmap.jl +++ b/base/distributed/pmap.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license mutable struct BatchProcessingError <: Exception data diff --git a/base/distributed/process_messages.jl b/base/distributed/process_messages.jl index d9bac73f9545e..121467676a64f 100644 --- a/base/distributed/process_messages.jl +++ b/base/distributed/process_messages.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # data stored by the owner of a remote reference def_rv_channel() = Channel(1) diff --git a/base/distributed/remotecall.jl b/base/distributed/remotecall.jl index d740d9720c6f2..67d4476d0cc18 100644 --- a/base/distributed/remotecall.jl +++ b/base/distributed/remotecall.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license """ client_refs diff --git a/base/distributed/workerpool.jl b/base/distributed/workerpool.jl index 2c5f772f706a0..ba43ef788bf67 100644 --- a/base/distributed/workerpool.jl +++ b/base/distributed/workerpool.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license abstract type AbstractWorkerPool end diff --git a/base/docs/Docs.jl b/base/docs/Docs.jl index 2e7a47946a464..a40e1e8ee9189 100644 --- a/base/docs/Docs.jl +++ b/base/docs/Docs.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license """ The Docs module provides the `@doc` macro which can be used to set and retrieve diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index f67777940bca1..5938cd2d18205 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module BaseDocs @@ -10,11 +10,11 @@ macro kw_str(text) Keyword(Symbol(text)) end """ **Welcome to Julia $(string(VERSION)).** The full manual is available at - http://docs.julialang.org/ + https://docs.julialang.org/ as well many great tutorials and learning resources: - http://julialang.org/learning/ + https://julialang.org/learning/ For help on a specific function or macro, type `?` followed by its name, e.g. `?fft`, or `?@time`, and press enter. diff --git a/base/docs/bindings.jl b/base/docs/bindings.jl index 40ca52cd09e0a..ac7fbab7f6bfd 100644 --- a/base/docs/bindings.jl +++ b/base/docs/bindings.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license export @var diff --git a/base/docs/core.jl b/base/docs/core.jl index 81993ae2ef2c3..9b8cf34c7f48a 100644 --- a/base/docs/core.jl +++ b/base/docs/core.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module CoreDocs diff --git a/base/docs/helpdb.jl b/base/docs/helpdb.jl index 42e7b76d29df0..5e2a4fe44b28a 100644 --- a/base/docs/helpdb.jl +++ b/base/docs/helpdb.jl @@ -1,3 +1,3 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license include(joinpath("helpdb", "Base.jl")) diff --git a/base/docs/helpdb/Base.jl b/base/docs/helpdb/Base.jl index d5f9000b947be..83019ba7d477b 100644 --- a/base/docs/helpdb/Base.jl +++ b/base/docs/helpdb/Base.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Base diff --git a/base/docs/utils.jl b/base/docs/utils.jl index 973c49eb2ee06..f07a370d258dd 100644 --- a/base/docs/utils.jl +++ b/base/docs/utils.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Text / HTML objects diff --git a/base/dsp.jl b/base/dsp.jl index f7d32406dcc38..c4cf7fceb8514 100644 --- a/base/dsp.jl +++ b/base/dsp.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module DSP diff --git a/base/emoji_symbols.jl b/base/emoji_symbols.jl index e65d9b9be476b..f8a5043f19f36 100644 --- a/base/emoji_symbols.jl +++ b/base/emoji_symbols.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license #= import JSON diff --git a/base/env.jl b/base/env.jl index e4bc18e39df8e..985347f37dca6 100644 --- a/base/env.jl +++ b/base/env.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license if is_windows() const ERROR_ENVVAR_NOT_FOUND = UInt32(203) diff --git a/base/errno.jl b/base/errno.jl index 99986995832c7..19da1239109a6 100644 --- a/base/errno.jl +++ b/base/errno.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license include("errno_h.jl") export diff --git a/base/error.jl b/base/error.jl index cd2e41b21a6d5..108f5c83716d4 100644 --- a/base/error.jl +++ b/base/error.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # pseudo-definitions to show how everything behaves # diff --git a/base/essentials.jl b/base/essentials.jl index f2f5da38907c4..a7034b2ad8ccb 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Core: CodeInfo diff --git a/base/event.jl b/base/event.jl index 940340ec162c4..c9fab5701bc86 100644 --- a/base/event.jl +++ b/base/event.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## condition variables diff --git a/base/exports.jl b/base/exports.jl index f38b87fe2bff0..5a807c0724394 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license export # Modules diff --git a/base/expr.jl b/base/expr.jl index 55b9e23359c88..21d66ec4a445c 100644 --- a/base/expr.jl +++ b/base/expr.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## symbols ## diff --git a/base/fastmath.jl b/base/fastmath.jl index 7d51eba54a6d4..1471addca0eba 100644 --- a/base/fastmath.jl +++ b/base/fastmath.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Support for @fastmath diff --git a/base/fft/FFTW.jl b/base/fft/FFTW.jl index 712f7e6ebe850..2c5cb0c79885f 100644 --- a/base/fft/FFTW.jl +++ b/base/fft/FFTW.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license import Base: show, *, convert, unsafe_convert, size, strides, ndims, pointer, A_mul_B! diff --git a/base/fft/dct.jl b/base/fft/dct.jl index 6ce51e5ab25c3..5c5470d18cb92 100644 --- a/base/fft/dct.jl +++ b/base/fft/dct.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # (This is part of the FFTW module.) diff --git a/base/file.jl b/base/file.jl index e5b091b425cc2..dd4ebe089d3f1 100644 --- a/base/file.jl +++ b/base/file.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Operations with the file system (paths) ## diff --git a/base/filesystem.jl b/base/filesystem.jl index 1f6bc997156ff..bdbd8a0d6d305 100644 --- a/base/filesystem.jl +++ b/base/filesystem.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## File Operations (Libuv-based) ## diff --git a/base/float.jl b/base/float.jl index 69a37e277c092..16919ea9fe253 100644 --- a/base/float.jl +++ b/base/float.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## floating point traits ## diff --git a/base/floatfuncs.jl b/base/floatfuncs.jl index 8ca6fa6f8250f..e75486a46257c 100644 --- a/base/floatfuncs.jl +++ b/base/floatfuncs.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## floating-point functions ## diff --git a/base/generator.jl b/base/generator.jl index 53d69e9adde54..d2cbed7609e0e 100644 --- a/base/generator.jl +++ b/base/generator.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license """ Generator(f, iter) diff --git a/base/gmp.jl b/base/gmp.jl index 7232d4a416104..365de9154fd51 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module GMP diff --git a/base/grisu/grisu.jl b/base/grisu/grisu.jl index b9a834a07bb9f..40ddf401ce865 100644 --- a/base/grisu/grisu.jl +++ b/base/grisu/grisu.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Grisu diff --git a/base/hashing.jl b/base/hashing.jl index 2417124bef64a..efc87a46568cd 100644 --- a/base/hashing.jl +++ b/base/hashing.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## hashing a single value ## diff --git a/base/hashing2.jl b/base/hashing2.jl index 96bd4ed55e56b..37a401ac974f0 100644 --- a/base/hashing2.jl +++ b/base/hashing2.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## efficient value-based hashing of integers ## diff --git a/base/i18n.jl b/base/i18n.jl index 66f650b90d808..d4488cc1ce832 100644 --- a/base/i18n.jl +++ b/base/i18n.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module I18n diff --git a/base/indices.jl b/base/indices.jl index e01b6699592b0..e55a64dd38597 100644 --- a/base/indices.jl +++ b/base/indices.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license Dims{N} = NTuple{N,Int} DimsInteger{N} = NTuple{N,Integer} @@ -237,7 +237,7 @@ unsafe_indices(S::Slice) = (S.indices,) indices1(S::Slice) = S.indices first(S::Slice) = first(S.indices) last(S::Slice) = last(S.indices) -errmsg(A) = error("size not supported for arrays with indices $(indices(A)); see http://docs.julialang.org/en/latest/devdocs/offset-arrays/") +errmsg(A) = error("size not supported for arrays with indices $(indices(A)); see https://docs.julialang.org/en/latest/devdocs/offset-arrays/") size(S::Slice) = first(S.indices) == 1 ? (length(S.indices),) : errmsg(S) length(S::Slice) = first(S.indices) == 1 ? length(S.indices) : errmsg(S) unsafe_length(S::Slice) = first(S.indices) == 1 ? unsafe_length(S.indices) : errmsg(S) diff --git a/base/inference.jl b/base/inference.jl index b80497edfc12d..cb6275e0ea723 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license import Core: _apply, svec, apply_type, Builtin, IntrinsicFunction, MethodInstance diff --git a/base/initdefs.jl b/base/initdefs.jl index 0259b131de91f..20437a4e57cba 100644 --- a/base/initdefs.jl +++ b/base/initdefs.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## initdefs.jl - initialization and runtime management definitions diff --git a/base/int.jl b/base/int.jl index 88b20efc85995..f6afa44d13a08 100644 --- a/base/int.jl +++ b/base/int.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## integer arithmetic ## diff --git a/base/interactiveutil.jl b/base/interactiveutil.jl index 1d12a95249976..2d82b0bdd05b6 100644 --- a/base/interactiveutil.jl +++ b/base/interactiveutil.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # editing files diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 53b46e4f1ff5e..98ce409fb1dc3 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## number-theoretic functions ## diff --git a/base/intset.jl b/base/intset.jl index 1bb2016d0a11a..13b9fce6325d9 100644 --- a/base/intset.jl +++ b/base/intset.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license struct IntSet <: AbstractSet{Int} bits::BitVector diff --git a/base/io.jl b/base/io.jl index bee7fb3899959..3e57236326a1a 100644 --- a/base/io.jl +++ b/base/io.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Generic IO stubs -- all subtypes should implement these (if meaningful) diff --git a/base/iobuffer.jl b/base/iobuffer.jl index dd061652a3785..0c51079a7dca7 100644 --- a/base/iobuffer.jl +++ b/base/iobuffer.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## work with AbstractVector{UInt8} via I/O primitives ## diff --git a/base/iostream.jl b/base/iostream.jl index b2474765a2a58..7517fd1175934 100644 --- a/base/iostream.jl +++ b/base/iostream.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## IOStream diff --git a/base/irrationals.jl b/base/irrationals.jl index f02be49e83524..1077696cb88ac 100644 --- a/base/irrationals.jl +++ b/base/irrationals.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## general machinery for irrational mathematical constants diff --git a/base/iterators.jl b/base/iterators.jl index e9c2426079ff8..54cf8a9f0cb7b 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Iterators diff --git a/base/latex_symbols.jl b/base/latex_symbols.jl index 2e2d2af8da657..65b237f28a9d3 100644 --- a/base/latex_symbols.jl +++ b/base/latex_symbols.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Mapping from LaTeX math symbol to the corresponding Unicode codepoint. # This is used for tab substitution in the REPL. diff --git a/base/libc.jl b/base/libc.jl index a1880755de5e0..d0414f45fd54b 100644 --- a/base/libc.jl +++ b/base/libc.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Libc diff --git a/base/libdl.jl b/base/libdl.jl index 388950d11f2f3..88846f0cd7f34 100644 --- a/base/libdl.jl +++ b/base/libdl.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Libdl diff --git a/base/libgit2/blob.jl b/base/libgit2/blob.jl index 207eb9c56b3d9..999a58da63f86 100644 --- a/base/libgit2/blob.jl +++ b/base/libgit2/blob.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license function Base.length(blob::GitBlob) return ccall((:git_blob_rawsize, :libgit2), Int64, (Ptr{Void},), blob.ptr) diff --git a/base/libgit2/callbacks.jl b/base/libgit2/callbacks.jl index da74f2e88071f..0a78f48949f47 100644 --- a/base/libgit2/callbacks.jl +++ b/base/libgit2/callbacks.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license """Mirror callback function diff --git a/base/libgit2/commit.jl b/base/libgit2/commit.jl index 28592fe933c00..39feb982a3e4f 100644 --- a/base/libgit2/commit.jl +++ b/base/libgit2/commit.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license function message(c::GitCommit, raw::Bool=false) local msg_ptr::Cstring diff --git a/base/libgit2/config.jl b/base/libgit2/config.jl index 7c01664042cc4..27b7b7a318ab2 100644 --- a/base/libgit2/config.jl +++ b/base/libgit2/config.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license function GitConfig(path::AbstractString, level::Consts.GIT_CONFIG = Consts.CONFIG_LEVEL_APP, diff --git a/base/libgit2/consts.jl b/base/libgit2/consts.jl index 0e563e35ebeb4..b5aa73c41f9eb 100644 --- a/base/libgit2/consts.jl +++ b/base/libgit2/consts.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Consts diff --git a/base/libgit2/diff.jl b/base/libgit2/diff.jl index 49836e2df4d3d..c01e2268d841b 100644 --- a/base/libgit2/diff.jl +++ b/base/libgit2/diff.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # TODO: make this a general purpose solution function Base.cconvert(::Type{Ptr{DiffOptionsStruct}}, pathspecs::AbstractString) diff --git a/base/libgit2/error.jl b/base/libgit2/error.jl index 8e91bec65821c..2f5739e0af879 100644 --- a/base/libgit2/error.jl +++ b/base/libgit2/error.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Error diff --git a/base/libgit2/index.jl b/base/libgit2/index.jl index f3ca053d91f2c..c7e04c33f0c32 100644 --- a/base/libgit2/index.jl +++ b/base/libgit2/index.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license function GitIndex(repo::GitRepo) idx_ptr_ptr = Ref{Ptr{Void}}(C_NULL) diff --git a/base/libgit2/libgit2.jl b/base/libgit2/libgit2.jl index 0721ab7b8e4c2..85f5e6cc76a37 100644 --- a/base/libgit2/libgit2.jl +++ b/base/libgit2/libgit2.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module LibGit2 diff --git a/base/libgit2/merge.jl b/base/libgit2/merge.jl index cf5ab1040babd..2760a4015b855 100644 --- a/base/libgit2/merge.jl +++ b/base/libgit2/merge.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license function GitAnnotated(repo::GitRepo, commit_id::GitHash) ann_ptr_ptr = Ref{Ptr{Void}}(C_NULL) diff --git a/base/libgit2/oid.jl b/base/libgit2/oid.jl index 351a4584da26d..21e527c7cb08d 100644 --- a/base/libgit2/oid.jl +++ b/base/libgit2/oid.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license function GitHash(ptr::Ptr{UInt8}) if ptr == C_NULL diff --git a/base/libgit2/rebase.jl b/base/libgit2/rebase.jl index 7c4ef40c18a85..c794e3f1ebc11 100644 --- a/base/libgit2/rebase.jl +++ b/base/libgit2/rebase.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license function GitRebase(repo::GitRepo, branch::GitAnnotated, upstream::GitAnnotated; onto::Nullable{GitAnnotated}=Nullable{GitAnnotated}(), diff --git a/base/libgit2/reference.jl b/base/libgit2/reference.jl index 3b44dd1ad763b..be6336815eef5 100644 --- a/base/libgit2/reference.jl +++ b/base/libgit2/reference.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license function GitReference(repo::GitRepo, refname::AbstractString) ref_ptr_ptr = Ref{Ptr{Void}}(C_NULL) diff --git a/base/libgit2/remote.jl b/base/libgit2/remote.jl index 8951fb079f758..85062caced0bd 100644 --- a/base/libgit2/remote.jl +++ b/base/libgit2/remote.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license """ GitRemote(repo::GitRepo, rmt_name::AbstractString, rmt_url::AbstractString) -> GitRemote diff --git a/base/libgit2/repository.jl b/base/libgit2/repository.jl index 30cc536c1de27..5f1f938c475b3 100644 --- a/base/libgit2/repository.jl +++ b/base/libgit2/repository.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license """ LibGit2.GitRepo(path::AbstractString) diff --git a/base/libgit2/signature.jl b/base/libgit2/signature.jl index 8fd7d88a1aa01..2e6395c3758d5 100644 --- a/base/libgit2/signature.jl +++ b/base/libgit2/signature.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license function Signature(ptr::Ptr{SignatureStruct}) sig = unsafe_load(ptr)::SignatureStruct diff --git a/base/libgit2/status.jl b/base/libgit2/status.jl index c0d547d1c0d90..a006770cd55fb 100644 --- a/base/libgit2/status.jl +++ b/base/libgit2/status.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license """ LibGit2.GitStatus(repo::GitRepo; status_opts=StatusOptions()) diff --git a/base/libgit2/strarray.jl b/base/libgit2/strarray.jl index deee54fd8e4eb..db0803680f72b 100644 --- a/base/libgit2/strarray.jl +++ b/base/libgit2/strarray.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license function Base.cconvert(::Type{Ptr{StrArrayStruct}}, x::Vector) diff --git a/base/libgit2/tag.jl b/base/libgit2/tag.jl index 098bfd03837e9..b76a5db932204 100644 --- a/base/libgit2/tag.jl +++ b/base/libgit2/tag.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license """ LibGit2.tag_list(repo::GitRepo) -> Vector{String} diff --git a/base/libgit2/tree.jl b/base/libgit2/tree.jl index af36a46246e04..3f9162f3823b9 100644 --- a/base/libgit2/tree.jl +++ b/base/libgit2/tree.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license """ Traverse the entries in a tree and its subtrees in post or pre order. diff --git a/base/libgit2/types.jl b/base/libgit2/types.jl index be76f294c8a0e..3bfede4b20367 100644 --- a/base/libgit2/types.jl +++ b/base/libgit2/types.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license import Base.@kwdef import .Consts: GIT_SUBMODULE_IGNORE, GIT_MERGE_FILE_FAVOR, GIT_MERGE_FILE diff --git a/base/libgit2/utils.jl b/base/libgit2/utils.jl index 4dd3504e707ec..59b84bf905427 100644 --- a/base/libgit2/utils.jl +++ b/base/libgit2/utils.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Parse "GIT URLs" syntax (URLs and a scp-like syntax). For details see: # https://git-scm.com/docs/git-clone#_git_urls_a_id_urls_a diff --git a/base/libgit2/walker.jl b/base/libgit2/walker.jl index 8649b35cf9ca8..41b44fcbc14b4 100644 --- a/base/libgit2/walker.jl +++ b/base/libgit2/walker.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license function GitRevWalker(repo::GitRepo) w_ptr = Ref{Ptr{Void}}(C_NULL) diff --git a/base/libuv.jl b/base/libuv.jl index 1037e7ce03d9c..0b800bb6d2d11 100644 --- a/base/libuv.jl +++ b/base/libuv.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Core definitions for interacting with the libuv library from Julia diff --git a/base/linalg/arnoldi.jl b/base/linalg/arnoldi.jl index 935d6fd79ea2a..103152d4bc75a 100644 --- a/base/linalg/arnoldi.jl +++ b/base/linalg/arnoldi.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using .ARPACK diff --git a/base/linalg/arpack.jl b/base/linalg/arpack.jl index 4b5d1d147e4e4..c1deed960c30a 100644 --- a/base/linalg/arpack.jl +++ b/base/linalg/arpack.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module ARPACK diff --git a/base/linalg/bidiag.jl b/base/linalg/bidiag.jl index ae566dda9a5c1..7ce28fd707b81 100644 --- a/base/linalg/bidiag.jl +++ b/base/linalg/bidiag.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Bidiagonal matrices mutable struct Bidiagonal{T} <: AbstractMatrix{T} diff --git a/base/linalg/bitarray.jl b/base/linalg/bitarray.jl index 2b053e52745de..bb0eb96579438 100644 --- a/base/linalg/bitarray.jl +++ b/base/linalg/bitarray.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license function dot(x::BitVector, y::BitVector) # simplest way to mimic Array dot behavior diff --git a/base/linalg/blas.jl b/base/linalg/blas.jl index 09e7f81ad3790..51e00ef1b25f3 100644 --- a/base/linalg/blas.jl +++ b/base/linalg/blas.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module BLAS diff --git a/base/linalg/bunchkaufman.jl b/base/linalg/bunchkaufman.jl index 8d6cbf8f32a21..68c8b4157f102 100644 --- a/base/linalg/bunchkaufman.jl +++ b/base/linalg/bunchkaufman.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## Create an extractor that extracts the modified original matrix, e.g. ## LD for BunchKaufman, UL for CholeskyDense, LU for LUDense and diff --git a/base/linalg/cholesky.jl b/base/linalg/cholesky.jl index 5e4bdfd199b03..c22b91140eab5 100644 --- a/base/linalg/cholesky.jl +++ b/base/linalg/cholesky.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ########################## # Cholesky Factorization # diff --git a/base/linalg/conjarray.jl b/base/linalg/conjarray.jl index 065795042e44a..a1afac5a054f1 100644 --- a/base/linalg/conjarray.jl +++ b/base/linalg/conjarray.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license """ ConjArray(array) diff --git a/base/linalg/dense.jl b/base/linalg/dense.jl index e2516fee049da..aec70ee82b05b 100644 --- a/base/linalg/dense.jl +++ b/base/linalg/dense.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Linear algebra functions for dense matrices in column major format diff --git a/base/linalg/diagonal.jl b/base/linalg/diagonal.jl index 421328e9a1044..9003cc1825d64 100644 --- a/base/linalg/diagonal.jl +++ b/base/linalg/diagonal.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## Diagonal matrices diff --git a/base/linalg/eigen.jl b/base/linalg/eigen.jl index 6354df70be150..40d66d423139c 100644 --- a/base/linalg/eigen.jl +++ b/base/linalg/eigen.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Eigendecomposition struct Eigen{T,V,S<:AbstractMatrix,U<:AbstractVector} <: Factorization{T} diff --git a/base/linalg/exceptions.jl b/base/linalg/exceptions.jl index 40320246f420b..ea3cb5f84fabf 100644 --- a/base/linalg/exceptions.jl +++ b/base/linalg/exceptions.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license export LAPACKException, ARPACKException, diff --git a/base/linalg/factorization.jl b/base/linalg/factorization.jl index 7a3a2d881fc61..c088e92cfccc8 100644 --- a/base/linalg/factorization.jl +++ b/base/linalg/factorization.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## Matrix factorizations and decompositions diff --git a/base/linalg/generic.jl b/base/linalg/generic.jl index 547a7774ef866..8892b5d9e0a44 100644 --- a/base/linalg/generic.jl +++ b/base/linalg/generic.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## linalg.jl: Some generic Linear Algebra definitions diff --git a/base/linalg/givens.jl b/base/linalg/givens.jl index dc98cfece3bd8..fd3737c7739ec 100644 --- a/base/linalg/givens.jl +++ b/base/linalg/givens.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # givensAlgorithm functions are derived from LAPACK, see below abstract type AbstractRotation{T} end diff --git a/base/linalg/hessenberg.jl b/base/linalg/hessenberg.jl index 87743b87c0230..fd06f1032a280 100644 --- a/base/linalg/hessenberg.jl +++ b/base/linalg/hessenberg.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license struct Hessenberg{T,S<:AbstractMatrix} <: Factorization{T} factors::S diff --git a/base/linalg/lapack.jl b/base/linalg/lapack.jl index 4b5c937767ce8..357f28e2d7813 100644 --- a/base/linalg/lapack.jl +++ b/base/linalg/lapack.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## The LAPACK module of interfaces to LAPACK subroutines module LAPACK diff --git a/base/linalg/ldlt.jl b/base/linalg/ldlt.jl index 55260cc46142e..0436078970d3f 100644 --- a/base/linalg/ldlt.jl +++ b/base/linalg/ldlt.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license struct LDLt{T,S<:AbstractMatrix} <: Factorization{T} data::S diff --git a/base/linalg/linalg.jl b/base/linalg/linalg.jl index 1f63661d53f09..b4004f008536e 100644 --- a/base/linalg/linalg.jl +++ b/base/linalg/linalg.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module LinAlg diff --git a/base/linalg/lq.jl b/base/linalg/lq.jl index 6ee36ffadde3f..b15798dbf9a67 100644 --- a/base/linalg/lq.jl +++ b/base/linalg/lq.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # LQ Factorizations diff --git a/base/linalg/lu.jl b/base/linalg/lu.jl index ff5d3202a8130..0939d7664c861 100644 --- a/base/linalg/lu.jl +++ b/base/linalg/lu.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license #################### # LU Factorization # diff --git a/base/linalg/matmul.jl b/base/linalg/matmul.jl index d688811173245..f1cb201591649 100644 --- a/base/linalg/matmul.jl +++ b/base/linalg/matmul.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # matmul.jl: Everything to do with dense matrix multiplication diff --git a/base/linalg/qr.jl b/base/linalg/qr.jl index 191d138e3a271..123d0fe6bb024 100644 --- a/base/linalg/qr.jl +++ b/base/linalg/qr.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # QR and Hessenberg Factorizations diff --git a/base/linalg/rowvector.jl b/base/linalg/rowvector.jl index dd8607fad9349..4c29691406520 100644 --- a/base/linalg/rowvector.jl +++ b/base/linalg/rowvector.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license """ RowVector(vector) diff --git a/base/linalg/schur.jl b/base/linalg/schur.jl index 50c4a6e74cc45..ad6cd33b800cb 100644 --- a/base/linalg/schur.jl +++ b/base/linalg/schur.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Schur decomposition struct Schur{Ty,S<:AbstractMatrix} <: Factorization{Ty} diff --git a/base/linalg/special.jl b/base/linalg/special.jl index 662637ec1b9f4..3d5fc802007c2 100644 --- a/base/linalg/special.jl +++ b/base/linalg/special.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Methods operating on different special matrix types diff --git a/base/linalg/svd.jl b/base/linalg/svd.jl index 96df0b82a89fc..d517cdf5a0b11 100644 --- a/base/linalg/svd.jl +++ b/base/linalg/svd.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Singular Value Decomposition struct SVD{T,Tr,M<:AbstractArray} <: Factorization{T} diff --git a/base/linalg/symmetric.jl b/base/linalg/symmetric.jl index 4664ad505354a..c11680f1bfc79 100644 --- a/base/linalg/symmetric.jl +++ b/base/linalg/symmetric.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license #Symmetric and Hermitian matrices struct Symmetric{T,S<:AbstractMatrix} <: AbstractMatrix{T} diff --git a/base/linalg/transpose.jl b/base/linalg/transpose.jl index d15c54dab8dc6..4bafa9e4e6c7b 100644 --- a/base/linalg/transpose.jl +++ b/base/linalg/transpose.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ctranspose(a::AbstractArray) = error("ctranspose not defined for $(typeof(a)). Consider using `permutedims` for higher-dimensional arrays.") transpose(a::AbstractArray) = error("transpose not defined for $(typeof(a)). Consider using `permutedims` for higher-dimensional arrays.") diff --git a/base/linalg/triangular.jl b/base/linalg/triangular.jl index 53dc720c2138c..e2a5bd4bb1c48 100644 --- a/base/linalg/triangular.jl +++ b/base/linalg/triangular.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## Triangular diff --git a/base/linalg/tridiag.jl b/base/linalg/tridiag.jl index 3ac3810aba47d..3b1bc28859ed7 100644 --- a/base/linalg/tridiag.jl +++ b/base/linalg/tridiag.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license #### Specialized matrix types #### diff --git a/base/linalg/uniformscaling.jl b/base/linalg/uniformscaling.jl index d976aacc43f6f..1adeec8cfa9c9 100644 --- a/base/linalg/uniformscaling.jl +++ b/base/linalg/uniformscaling.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license import Base: copy, ctranspose, getindex, show, transpose, one, zero, inv, @_pure_meta, hcat, vcat, hvcat diff --git a/base/loading.jl b/base/loading.jl index 4242121aa6b08..9bda0da89d14f 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Base.require is the implementation for the `import` statement diff --git a/base/lock.jl b/base/lock.jl index 00d0fb9a93d95..533795a1cf072 100644 --- a/base/lock.jl +++ b/base/lock.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Advisory reentrant lock """ diff --git a/base/locks.jl b/base/locks.jl index c6c8d2b0552d2..e674d5d877191 100644 --- a/base/locks.jl +++ b/base/locks.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license import Base: _uv_hook_close, unsafe_convert, lock, trylock, unlock, islocked diff --git a/base/markdown/Common/Common.jl b/base/markdown/Common/Common.jl index de021f7be1f2e..10e4e7b492712 100644 --- a/base/markdown/Common/Common.jl +++ b/base/markdown/Common/Common.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license include("block.jl") include("inline.jl") diff --git a/base/markdown/Common/block.jl b/base/markdown/Common/block.jl index 0594ffe48fabc..6815ac87a9b56 100644 --- a/base/markdown/Common/block.jl +++ b/base/markdown/Common/block.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # –––––––––– # Paragraphs diff --git a/base/markdown/Common/inline.jl b/base/markdown/Common/inline.jl index 1ef1171a9f647..276504cc5a13e 100644 --- a/base/markdown/Common/inline.jl +++ b/base/markdown/Common/inline.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # –––––––– # Emphasis diff --git a/base/markdown/GitHub/GitHub.jl b/base/markdown/GitHub/GitHub.jl index e29fdf62cad6b..ae2cfd1120f3a 100644 --- a/base/markdown/GitHub/GitHub.jl +++ b/base/markdown/GitHub/GitHub.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license include("table.jl") diff --git a/base/markdown/GitHub/table.jl b/base/markdown/GitHub/table.jl index dc31fad954143..31898506507f1 100644 --- a/base/markdown/GitHub/table.jl +++ b/base/markdown/GitHub/table.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license mutable struct Table rows::Vector{Vector{Any}} diff --git a/base/markdown/IPython/IPython.jl b/base/markdown/IPython/IPython.jl index 1cceb3e616d4d..665c45b84c6c8 100644 --- a/base/markdown/IPython/IPython.jl +++ b/base/markdown/IPython/IPython.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license mutable struct LaTeX formula::String diff --git a/base/markdown/Julia/Julia.jl b/base/markdown/Julia/Julia.jl index ab18b8d92eeaa..abc4b84385d30 100644 --- a/base/markdown/Julia/Julia.jl +++ b/base/markdown/Julia/Julia.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # This file contains markdown extensions designed to make documenting # Julia easy peasy. diff --git a/base/markdown/Julia/interp.jl b/base/markdown/Julia/interp.jl index 26be8e4a180a4..b41ec5f9ffe1e 100644 --- a/base/markdown/Julia/interp.jl +++ b/base/markdown/Julia/interp.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license function Base.parse(stream::IO; greedy::Bool = true, raise::Bool = true) pos = position(stream) diff --git a/base/markdown/Markdown.jl b/base/markdown/Markdown.jl index ba3bbca697d38..d32ae9fa8d983 100644 --- a/base/markdown/Markdown.jl +++ b/base/markdown/Markdown.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Markdown diff --git a/base/markdown/parse/config.jl b/base/markdown/parse/config.jl index 0defc1f1fac08..eabba133a46fe 100644 --- a/base/markdown/parse/config.jl +++ b/base/markdown/parse/config.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license const InnerConfig = Dict{Char, Vector{Function}} diff --git a/base/markdown/parse/parse.jl b/base/markdown/parse/parse.jl index c061ee6d10ee8..052fda3642ce5 100644 --- a/base/markdown/parse/parse.jl +++ b/base/markdown/parse/parse.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license mutable struct MD content::Vector{Any} diff --git a/base/markdown/parse/util.jl b/base/markdown/parse/util.jl index 9b5598bbf9754..38f1a38da6000 100644 --- a/base/markdown/parse/util.jl +++ b/base/markdown/parse/util.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license import Base: peek diff --git a/base/markdown/render/html.jl b/base/markdown/render/html.jl index 7e2f256f4aa5c..ee3ec7e93e335 100644 --- a/base/markdown/render/html.jl +++ b/base/markdown/render/html.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license include("rich.jl") diff --git a/base/markdown/render/latex.jl b/base/markdown/render/latex.jl index ae1277eeb6d83..e41f4b5e75844 100644 --- a/base/markdown/render/latex.jl +++ b/base/markdown/render/latex.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license export latex diff --git a/base/markdown/render/plain.jl b/base/markdown/render/plain.jl index 01a3a8994d939..f6a4247cffe18 100644 --- a/base/markdown/render/plain.jl +++ b/base/markdown/render/plain.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license plain(x) = sprint(plain, x) diff --git a/base/markdown/render/rich.jl b/base/markdown/render/rich.jl index f3bdcefad460e..01617b5c81404 100644 --- a/base/markdown/render/rich.jl +++ b/base/markdown/render/rich.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license function tohtml(io::IO, m::MIME"text/html", x) show(io, m, x) diff --git a/base/markdown/render/rst.jl b/base/markdown/render/rst.jl index ca5661520beff..58269df48aaee 100644 --- a/base/markdown/render/rst.jl +++ b/base/markdown/render/rst.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license rst(x) = sprint(rst, x) diff --git a/base/markdown/render/terminal/formatting.jl b/base/markdown/render/terminal/formatting.jl index 1d14f1d60be21..36a4d390a7138 100644 --- a/base/markdown/render/terminal/formatting.jl +++ b/base/markdown/render/terminal/formatting.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Styles diff --git a/base/markdown/render/terminal/render.jl b/base/markdown/render/terminal/render.jl index c3f97fa5c38b8..76be8ec471f8f 100644 --- a/base/markdown/render/terminal/render.jl +++ b/base/markdown/render/terminal/render.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license include("formatting.jl") diff --git a/base/math.jl b/base/math.jl index 3db27f625c96a..4d8eb64fc8d32 100644 --- a/base/math.jl +++ b/base/math.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Math diff --git a/base/meta.jl b/base/meta.jl index 84bcc86255dad..6daaa8330c0e4 100644 --- a/base/meta.jl +++ b/base/meta.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Meta # diff --git a/base/methodshow.jl b/base/methodshow.jl index 6429133a0ebe9..c9f304a509c9e 100644 --- a/base/methodshow.jl +++ b/base/methodshow.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Method and method table pretty-printing diff --git a/base/mmap.jl b/base/mmap.jl index ca56126812f56..b91e67a1bad97 100644 --- a/base/mmap.jl +++ b/base/mmap.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Mmap diff --git a/base/mpfr.jl b/base/mpfr.jl index 0a80427c20b2c..1f9a91cc735b1 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module MPFR diff --git a/base/multidimensional.jl b/base/multidimensional.jl index e519f293c834d..dd8141bddad28 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ### Multidimensional iterators module IteratorsMD diff --git a/base/multimedia.jl b/base/multimedia.jl index 9314d4b5ab553..ff6df76a0a2f9 100644 --- a/base/multimedia.jl +++ b/base/multimedia.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Multimedia diff --git a/base/multinverses.jl b/base/multinverses.jl index 39109d16bcac8..1a47151dd085d 100644 --- a/base/multinverses.jl +++ b/base/multinverses.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module MultiplicativeInverses diff --git a/base/nofloat_hashing.jl b/base/nofloat_hashing.jl index 675c27560a30d..3ef707d1c440f 100644 --- a/base/nofloat_hashing.jl +++ b/base/nofloat_hashing.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## hashing small, built-in numeric types ## for a system image built without floating point support diff --git a/base/nullable.jl b/base/nullable.jl index 478e41da2d058..3b8b7ab570c3c 100644 --- a/base/nullable.jl +++ b/base/nullable.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license struct NullException <: Exception end diff --git a/base/number.jl b/base/number.jl index bd5deb2bca776..de5ce27c3662f 100644 --- a/base/number.jl +++ b/base/number.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## generic operations on numbers ## """ diff --git a/base/operators.jl b/base/operators.jl index b6ea643d310fd..4fb6464cdd086 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## types ## diff --git a/base/options.jl b/base/options.jl index af18585939ce6..ef3c88bc96110 100644 --- a/base/options.jl +++ b/base/options.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # NOTE: This type needs to be kept in sync with jl_options in src/julia.h struct JLOptions diff --git a/base/ordering.jl b/base/ordering.jl index 227bc48e8521d..a2e772500896d 100644 --- a/base/ordering.jl +++ b/base/ordering.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Order diff --git a/base/osutils.jl b/base/osutils.jl index 0373c6d6c53ea..4a133a4bd9a7f 100644 --- a/base/osutils.jl +++ b/base/osutils.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license """ is_unix([os]) diff --git a/base/pair.jl b/base/pair.jl index 0236fbbe482a5..7fb81226902e5 100644 --- a/base/pair.jl +++ b/base/pair.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license struct Pair{A,B} first::A diff --git a/base/parse.jl b/base/parse.jl index 493410e2fd87f..2cc5f6be8e5d6 100644 --- a/base/parse.jl +++ b/base/parse.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license import Base.Checked: add_with_overflow, mul_with_overflow diff --git a/base/path.jl b/base/path.jl index 6b04246a5f777..5a1861d64c675 100644 --- a/base/path.jl +++ b/base/path.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license export abspath, diff --git a/base/pcre.jl b/base/pcre.jl index 07ce5e6f0cfa0..36e169e824364 100644 --- a/base/pcre.jl +++ b/base/pcre.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## low-level pcre2 interface ## diff --git a/base/permuteddimsarray.jl b/base/permuteddimsarray.jl index 506b4c4a43b6b..e9649d1c23928 100644 --- a/base/permuteddimsarray.jl +++ b/base/permuteddimsarray.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module PermutedDimsArrays diff --git a/base/pkg/cache.jl b/base/pkg/cache.jl index c3d15899f8bb7..b4535579cd636 100644 --- a/base/pkg/cache.jl +++ b/base/pkg/cache.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Cache diff --git a/base/pkg/dir.jl b/base/pkg/dir.jl index 2eb9a5312aaed..76b8b57d21bc4 100644 --- a/base/pkg/dir.jl +++ b/base/pkg/dir.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Dir diff --git a/base/pkg/entry.jl b/base/pkg/entry.jl index b794d25012f3b..926f77c83ed5d 100644 --- a/base/pkg/entry.jl +++ b/base/pkg/entry.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Entry diff --git a/base/pkg/pkg.jl b/base/pkg/pkg.jl index 53d23f5dd61e0..af1a8ec27e31d 100644 --- a/base/pkg/pkg.jl +++ b/base/pkg/pkg.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Pkg diff --git a/base/pkg/query.jl b/base/pkg/query.jl index 60af3e120715f..5f8eee36d6721 100644 --- a/base/pkg/query.jl +++ b/base/pkg/query.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Query diff --git a/base/pkg/read.jl b/base/pkg/read.jl index a9e9144c8a313..dc4046fa3db92 100644 --- a/base/pkg/read.jl +++ b/base/pkg/read.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Read diff --git a/base/pkg/reqs.jl b/base/pkg/reqs.jl index 61a108cf44881..286f64d481ed5 100644 --- a/base/pkg/reqs.jl +++ b/base/pkg/reqs.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Reqs diff --git a/base/pkg/resolve.jl b/base/pkg/resolve.jl index ddb18f46c0b22..8cd453fa20d25 100644 --- a/base/pkg/resolve.jl +++ b/base/pkg/resolve.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Resolve diff --git a/base/pkg/resolve/fieldvalue.jl b/base/pkg/resolve/fieldvalue.jl index ca64085644101..584a3d295e62a 100644 --- a/base/pkg/resolve/fieldvalue.jl +++ b/base/pkg/resolve/fieldvalue.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module FieldValues diff --git a/base/pkg/resolve/interface.jl b/base/pkg/resolve/interface.jl index 67eda62e39ddc..c29b758c8a200 100644 --- a/base/pkg/resolve/interface.jl +++ b/base/pkg/resolve/interface.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module PkgToMaxSumInterface diff --git a/base/pkg/resolve/maxsum.jl b/base/pkg/resolve/maxsum.jl index 55c02a2925a9c..a688b15e3f5af 100644 --- a/base/pkg/resolve/maxsum.jl +++ b/base/pkg/resolve/maxsum.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module MaxSum diff --git a/base/pkg/resolve/versionweight.jl b/base/pkg/resolve/versionweight.jl index 4b93f257f94cd..cca61bfa151bd 100644 --- a/base/pkg/resolve/versionweight.jl +++ b/base/pkg/resolve/versionweight.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module VersionWeights diff --git a/base/pkg/types.jl b/base/pkg/types.jl index 7434d84817eb7..1e55a0b308694 100644 --- a/base/pkg/types.jl +++ b/base/pkg/types.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Types diff --git a/base/pkg/write.jl b/base/pkg/write.jl index c762b5598b3a5..635ef6a677798 100644 --- a/base/pkg/write.jl +++ b/base/pkg/write.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Write diff --git a/base/pointer.jl b/base/pointer.jl index 4f14eb562431b..9c8c66da62cdb 100644 --- a/base/pointer.jl +++ b/base/pointer.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license """ Ptr{T} diff --git a/base/poll.jl b/base/poll.jl index 6cda7fa4ad8ca..a670a10f0a979 100644 --- a/base/poll.jl +++ b/base/poll.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # filesystem operations diff --git a/base/precompile.jl b/base/precompile.jl index 01f9470161758..2342279959196 100644 --- a/base/precompile.jl +++ b/base/precompile.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Steps to regenerate this file: # 1. Remove all `precompile` calls diff --git a/base/printf.jl b/base/printf.jl index 738b758400f44..c5df8f402b0b0 100644 --- a/base/printf.jl +++ b/base/printf.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Printf using Base.Grisu diff --git a/base/process.jl b/base/process.jl index cd15390ca42d6..fa1cce13f27a9 100644 --- a/base/process.jl +++ b/base/process.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license abstract type AbstractCmd end diff --git a/base/profile.jl b/base/profile.jl index 55816bda55ce9..094d2bc53ab42 100644 --- a/base/profile.jl +++ b/base/profile.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Profile diff --git a/base/promotion.jl b/base/promotion.jl index 2f78d66354aec..f2263ff957032 100644 --- a/base/promotion.jl +++ b/base/promotion.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## type join (closest common ancestor, or least upper bound) ## diff --git a/base/random.jl b/base/random.jl index 58588042b8d13..62e1433cef42d 100644 --- a/base/random.jl +++ b/base/random.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Random diff --git a/base/range.jl b/base/range.jl index f3d5cfca90c5c..f72aebab4dc38 100644 --- a/base/range.jl +++ b/base/range.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license colon(a::Real, b::Real) = colon(promote(a,b)...) diff --git a/base/rational.jl b/base/rational.jl index 1760a6ab343ef..bcfa304abcdab 100644 --- a/base/rational.jl +++ b/base/rational.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license struct Rational{T<:Integer} <: Real num::T diff --git a/base/reduce.jl b/base/reduce.jl index 188d9c52eff9a..53d0e68999c6b 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## reductions ## diff --git a/base/reducedim.jl b/base/reducedim.jl index b6592764952b1..9474ae9cd70d5 100644 --- a/base/reducedim.jl +++ b/base/reducedim.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## Functions to compute the reduced shape diff --git a/base/reflection.jl b/base/reflection.jl index 3d4b35c7bc3f4..77de6bdf36cb6 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # name and module reflection diff --git a/base/refpointer.jl b/base/refpointer.jl index 8671f215c595e..da79be015b4d0 100644 --- a/base/refpointer.jl +++ b/base/refpointer.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license """ Ref{T} diff --git a/base/regex.jl b/base/regex.jl index e2161c90874f3..775d610131af9 100644 --- a/base/regex.jl +++ b/base/regex.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## object-oriented Regex interface ## diff --git a/base/replutil.jl b/base/replutil.jl index d79c32263bc4c..2923e8db186fa 100644 --- a/base/replutil.jl +++ b/base/replutil.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # fallback text/plain representation of any type: show(io::IO, ::MIME"text/plain", x) = show(io, x) diff --git a/base/reshapedarray.jl b/base/reshapedarray.jl index 6681681471d07..a68e5929bf963 100644 --- a/base/reshapedarray.jl +++ b/base/reshapedarray.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.MultiplicativeInverses: SignedMultiplicativeInverse diff --git a/base/rounding.jl b/base/rounding.jl index b56a13c482530..2e1876c037a7b 100644 --- a/base/rounding.jl +++ b/base/rounding.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Rounding diff --git a/base/serialize.jl b/base/serialize.jl index df85a9659874b..fbdf533283f8f 100644 --- a/base/serialize.jl +++ b/base/serialize.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Serializer diff --git a/base/set.jl b/base/set.jl index eae1e45a53402..733ca0aa92a71 100644 --- a/base/set.jl +++ b/base/set.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license mutable struct Set{T} <: AbstractSet{T} dict::Dict{T,Void} diff --git a/base/sharedarray.jl b/base/sharedarray.jl index ef3d973fc8766..045b28f23dc7f 100644 --- a/base/sharedarray.jl +++ b/base/sharedarray.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license import .Serializer: serialize_cycle_header, serialize_type, writetag, UNDEFREF_TAG diff --git a/base/shell.jl b/base/shell.jl index 234d6a8428a5f..b103a22472781 100644 --- a/base/shell.jl +++ b/base/shell.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## shell-like command parsing ## diff --git a/base/show.jl b/base/show.jl index fc81db8fb4018..fa9277feab17b 100644 --- a/base/show.jl +++ b/base/show.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license print(io::IO, s::Symbol) = (write(io,s); nothing) diff --git a/base/simdloop.jl b/base/simdloop.jl index 9f1946e35ee15..d83f51916acd5 100644 --- a/base/simdloop.jl +++ b/base/simdloop.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Support for @simd for diff --git a/base/socket.jl b/base/socket.jl index 853236673f1b8..ed990e9945d7e 100644 --- a/base/socket.jl +++ b/base/socket.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## IP ADDRESS HANDLING ## abstract type IPAddr end diff --git a/base/sort.jl b/base/sort.jl index 6f014276f09ee..f323d636b83c8 100644 --- a/base/sort.jl +++ b/base/sort.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Sort diff --git a/base/sparse/abstractsparse.jl b/base/sparse/abstractsparse.jl index 9e7281e392f59..e2f0cd9000f63 100644 --- a/base/sparse/abstractsparse.jl +++ b/base/sparse/abstractsparse.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license abstract type AbstractSparseArray{Tv,Ti,N} <: AbstractArray{Tv,N} end diff --git a/base/sparse/cholmod.jl b/base/sparse/cholmod.jl index 1586a0a838018..df859295ed5f8 100644 --- a/base/sparse/cholmod.jl +++ b/base/sparse/cholmod.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module CHOLMOD diff --git a/base/sparse/cholmod_h.jl b/base/sparse/cholmod_h.jl index f0e7a4d44ae2c..477ab4d07e3f3 100644 --- a/base/sparse/cholmod_h.jl +++ b/base/sparse/cholmod_h.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## CHOLMOD const TRUE = Int32(1) diff --git a/base/sparse/higherorderfns.jl b/base/sparse/higherorderfns.jl index abc148485a195..dd5cc1fb46e70 100644 --- a/base/sparse/higherorderfns.jl +++ b/base/sparse/higherorderfns.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module HigherOrderFns diff --git a/base/sparse/linalg.jl b/base/sparse/linalg.jl index 4ec09cc01d8eb..2ffde9fe6c909 100644 --- a/base/sparse/linalg.jl +++ b/base/sparse/linalg.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license import Base.LinAlg: checksquare diff --git a/base/sparse/sparse.jl b/base/sparse/sparse.jl index 2425d02dae46d..23e7c8c54ec6f 100644 --- a/base/sparse/sparse.jl +++ b/base/sparse/sparse.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module SparseArrays diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl index f2826d7fa88c0..0c7abb8dc0a32 100644 --- a/base/sparse/sparsematrix.jl +++ b/base/sparse/sparsematrix.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Compressed sparse columns data structure # Assumes that no zeros are stored in the data structure diff --git a/base/sparse/sparsevector.jl b/base/sparse/sparsevector.jl index 722f064a0ec14..89f21ea2ece2b 100644 --- a/base/sparse/sparsevector.jl +++ b/base/sparse/sparsevector.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ### Common definitions diff --git a/base/sparse/spqr.jl b/base/sparse/spqr.jl index 66deb05e5d320..05ccdbe57dc32 100644 --- a/base/sparse/spqr.jl +++ b/base/sparse/spqr.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module SPQR diff --git a/base/sparse/umfpack.jl b/base/sparse/umfpack.jl index 8e1f07c634bb5..a3deb6a37a567 100644 --- a/base/sparse/umfpack.jl +++ b/base/sparse/umfpack.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module UMFPACK diff --git a/base/sparse/umfpack_h.jl b/base/sparse/umfpack_h.jl index c4abdae0a5bf8..ec3a7c5382a42 100644 --- a/base/sparse/umfpack_h.jl +++ b/base/sparse/umfpack_h.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## UMFPACK diff --git a/base/special/gamma.jl b/base/special/gamma.jl index 6758530a7e4f6..778a00ae62391 100644 --- a/base/special/gamma.jl +++ b/base/special/gamma.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license gamma(x::Float64) = nan_dom_err(ccall((:tgamma,libm), Float64, (Float64,), x), x) gamma(x::Float32) = nan_dom_err(ccall((:tgammaf,libm), Float32, (Float32,), x), x) diff --git a/base/special/log.jl b/base/special/log.jl index dc3473828335b..d317101794155 100644 --- a/base/special/log.jl +++ b/base/special/log.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Implementation of # "Table-driven Implementation of the Logarithm Function in IEEE Floating-point Arithmetic" diff --git a/base/special/trig.jl b/base/special/trig.jl index 80a0d9073bf61..2ca08479a9f49 100644 --- a/base/special/trig.jl +++ b/base/special/trig.jl @@ -1,5 +1,5 @@ # This file is a part of Julia. Except for the *_kernel functions (see below), -# license is MIT: http://julialang.org/license +# license is MIT: https://julialang.org/license struct DoubleFloat64 hi::Float64 diff --git a/base/stacktraces.jl b/base/stacktraces.jl index cdff4d5a295e9..5b5fab65731bb 100644 --- a/base/stacktraces.jl +++ b/base/stacktraces.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module StackTraces diff --git a/base/stat.jl b/base/stat.jl index 3a54b213cea53..3cf4c1664633b 100644 --- a/base/stat.jl +++ b/base/stat.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # filesystem operations diff --git a/base/statistics.jl b/base/statistics.jl index 12bf64921a026..bcffca64ae2ed 100644 --- a/base/statistics.jl +++ b/base/statistics.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ##### mean ##### diff --git a/base/stream.jl b/base/stream.jl index b695ac664cb8a..9f08ccb8f2196 100644 --- a/base/stream.jl +++ b/base/stream.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license import .Libc: RawFD, dup if is_windows() diff --git a/base/strings/basic.jl b/base/strings/basic.jl index c4cfcf280e27d..e4f830b204045 100644 --- a/base/strings/basic.jl +++ b/base/strings/basic.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## core string functions ## diff --git a/base/strings/errors.jl b/base/strings/errors.jl index 8f80e5b1f8c30..2d3aa42455286 100644 --- a/base/strings/errors.jl +++ b/base/strings/errors.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## Error messages for Unicode / UTF support diff --git a/base/strings/io.jl b/base/strings/io.jl index 124a865daa00e..281b2149bac60 100644 --- a/base/strings/io.jl +++ b/base/strings/io.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## core text I/O ## diff --git a/base/strings/search.jl b/base/strings/search.jl index 16ee1019eadc1..c57b3768a4888 100644 --- a/base/strings/search.jl +++ b/base/strings/search.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license const Chars = Union{Char,Tuple{Vararg{Char}},AbstractVector{Char},Set{Char}} diff --git a/base/strings/string.jl b/base/strings/string.jl index 4573045acfb56..a78f2372e77e2 100644 --- a/base/strings/string.jl +++ b/base/strings/string.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license const ByteArray = Union{Vector{UInt8},Vector{Int8}} diff --git a/base/strings/strings.jl b/base/strings/strings.jl index 2f175900e37d5..bc1f302b7a6ad 100644 --- a/base/strings/strings.jl +++ b/base/strings/strings.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license include("strings/errors.jl") include("strings/types.jl") diff --git a/base/strings/types.jl b/base/strings/types.jl index 6b51d60176527..433009a69ac26 100644 --- a/base/strings/types.jl +++ b/base/strings/types.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # SubString and RevString types diff --git a/base/strings/utf8proc.jl b/base/strings/utf8proc.jl index 591d0b5793dd8..a0ed24c914fba 100644 --- a/base/strings/utf8proc.jl +++ b/base/strings/utf8proc.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Various Unicode functionality from the utf8proc library module UTF8proc diff --git a/base/strings/util.jl b/base/strings/util.jl index d4c1431b072ba..9d24e0da0667e 100644 --- a/base/strings/util.jl +++ b/base/strings/util.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # starts with and ends with predicates diff --git a/base/subarray.jl b/base/subarray.jl index 536c569f11920..c697040ccfc17 100644 --- a/base/subarray.jl +++ b/base/subarray.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license abstract type AbstractCartesianIndex{N} end # This is a hacky forward declaration for CartesianIndex const ViewIndex = Union{Real, AbstractArray} diff --git a/base/summarysize.jl b/base/summarysize.jl index 7fd7a6e71c304..a7c0e216e19b1 100644 --- a/base/summarysize.jl +++ b/base/summarysize.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license struct SummarySize seen::ObjectIdDict diff --git a/base/sysimg.jl b/base/sysimg.jl index e25ce641fa6aa..d9851dbf30a0d 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license baremodule Base diff --git a/base/sysinfo.jl b/base/sysinfo.jl index 9e2655ec96818..fb9119dd668b5 100644 --- a/base/sysinfo.jl +++ b/base/sysinfo.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Sys diff --git a/base/task.jl b/base/task.jl index a25bc78cd65b6..90d45576e5389 100644 --- a/base/task.jl +++ b/base/task.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## basic task functions and TLS diff --git a/base/test.jl b/base/test.jl index fa639f97b3863..c680f0415282e 100644 --- a/base/test.jl +++ b/base/test.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license """ Simple unit testing functionality: diff --git a/base/threadcall.jl b/base/threadcall.jl index c6dcfaedef2ba..0fff4e3d5c31d 100644 --- a/base/threadcall.jl +++ b/base/threadcall.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license const max_ccall_threads = parse(Int, get(ENV, "UV_THREADPOOL_SIZE", "4")) const thread_notifiers = [Nullable{Condition}() for i in 1:max_ccall_threads] diff --git a/base/threadingconstructs.jl b/base/threadingconstructs.jl index 678e9c3d92c3b..b3c1f0d76247f 100644 --- a/base/threadingconstructs.jl +++ b/base/threadingconstructs.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license export threadid, nthreads, @threads diff --git a/base/threads.jl b/base/threads.jl index ef9f6957fa3b7..d36cade097735 100644 --- a/base/threads.jl +++ b/base/threads.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Threads diff --git a/base/traits.jl b/base/traits.jl index da5de84cf58c0..b9643f7ba6742 100644 --- a/base/traits.jl +++ b/base/traits.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## numeric/object traits # trait for objects that have an ordering diff --git a/base/tuple.jl b/base/tuple.jl index 863240034483f..ce329a3fb1e98 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Document NTuple here where we have everything needed for the doc system """ diff --git a/base/twiceprecision.jl b/base/twiceprecision.jl index 74f0829a49261..caa6fe4e0bcf5 100644 --- a/base/twiceprecision.jl +++ b/base/twiceprecision.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Twice-precision arithmetic. diff --git a/base/util.jl b/base/util.jl index 57b6b5fc9f363..4da8294563e6d 100644 --- a/base/util.jl +++ b/base/util.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # timing diff --git a/base/version.jl b/base/version.jl index 39f7bee2ef62c..480faa91796e8 100644 --- a/base/version.jl +++ b/base/version.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## semantic version numbers (http://semver.org) @@ -255,7 +255,7 @@ function banner(io::IO = STDOUT) print(io,""" $(d3)_$(tx) $(d1)_$(tx) $(jl)_$(tx) $(d2)_$(d3)(_)$(d4)_$(tx) | A fresh approach to technical computing - $(d1)(_)$(jl) | $(d2)(_)$(tx) $(d4)(_)$(tx) | Documentation: http://docs.julialang.org + $(d1)(_)$(jl) | $(d2)(_)$(tx) $(d4)(_)$(tx) | Documentation: https://docs.julialang.org $(jl)_ _ _| |_ __ _$(tx) | Type \"?help\" for help. $(jl)| | | | | | |/ _` |$(tx) | $(jl)| | |_| | | | (_| |$(tx) | Version $(VERSION)$(commit_date) @@ -267,7 +267,7 @@ function banner(io::IO = STDOUT) print(io,""" _ _ _ _(_)_ | A fresh approach to technical computing - (_) | (_) (_) | Documentation: http://docs.julialang.org + (_) | (_) (_) | Documentation: https://docs.julialang.org _ _ _| |_ __ _ | Type \"?help\" for help. | | | | | | |/ _` | | | | |_| | | | (_| | | Version $(VERSION)$(commit_date) diff --git a/base/version_git.sh b/base/version_git.sh index 35f54e92bf177..5335c8f8abed5 100644 --- a/base/version_git.sh +++ b/base/version_git.sh @@ -1,5 +1,5 @@ #!/bin/sh -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # This file collects git info and create a julia file with the GIT_VERSION_INFO struct diff --git a/base/weakkeydict.jl b/base/weakkeydict.jl index bffa5737f115f..4d62020a91845 100644 --- a/base/weakkeydict.jl +++ b/base/weakkeydict.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # weak key dictionaries diff --git a/contrib/add_license_to_files.jl b/contrib/add_license_to_files.jl index 2bfc43da2d934..2dd7020d54dcb 100644 --- a/contrib/add_license_to_files.jl +++ b/contrib/add_license_to_files.jl @@ -70,7 +70,7 @@ const ext_prefix = Dict([ (".cpp", "\/\/ "), ]) -const new_license = "This file is a part of Julia. License is MIT: http://julialang.org/license" +const new_license = "This file is a part of Julia. License is MIT: https://julialang.org/license" # Old License text if such should be first removed - or empty string const old_license = "" diff --git a/contrib/build_sysimg.jl b/contrib/build_sysimg.jl index 3fa8efafdb7f6..2805695612273 100644 --- a/contrib/build_sysimg.jl +++ b/contrib/build_sysimg.jl @@ -1,5 +1,5 @@ #!/usr/bin/env julia -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Build a system image binary at sysimg_path.dlext. Allow insertion of a userimg via # userimg_path. If sysimg_path.dlext is currently loaded into memory, don't continue diff --git a/contrib/check-whitespace.sh b/contrib/check-whitespace.sh index fc085e935e7d9..c380d7bdd2969 100755 --- a/contrib/check-whitespace.sh +++ b/contrib/check-whitespace.sh @@ -1,5 +1,5 @@ #!/bin/sh -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Check for trailing white space in source files; # report an error if so diff --git a/contrib/commit-name.sh b/contrib/commit-name.sh index 1b81c846b8a5e..7a139eee276a5 100755 --- a/contrib/commit-name.sh +++ b/contrib/commit-name.sh @@ -1,5 +1,5 @@ #!/bin/sh -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Needs to be run from a julia repo clone # First argument (optional) is a ref to the commit diff --git a/contrib/download_cmake.sh b/contrib/download_cmake.sh index 73105af6fb83e..d122e1e0f07d4 100755 --- a/contrib/download_cmake.sh +++ b/contrib/download_cmake.sh @@ -1,5 +1,5 @@ #!/bin/sh -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Script to download newest version of cmake on linux (or mac) # saves you the trouble of compiling it if you don't have root diff --git a/contrib/filterArgs.sh b/contrib/filterArgs.sh index 658a21d3d7eb9..823745e004e6e 100755 --- a/contrib/filterArgs.sh +++ b/contrib/filterArgs.sh @@ -1,5 +1,5 @@ #!/bin/sh -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Loop over all command line arguments for i in "$@"; do diff --git a/contrib/fixup-libgfortran.sh b/contrib/fixup-libgfortran.sh index a7ee7025b9a7f..4f426e9e7d647 100755 --- a/contrib/fixup-libgfortran.sh +++ b/contrib/fixup-libgfortran.sh @@ -1,5 +1,5 @@ #!/bin/sh -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Run as: fixup-libgfortran.sh <$private_libdir> diff --git a/contrib/fixup-libstdc++.sh b/contrib/fixup-libstdc++.sh index d1953bf09767e..ee84094169b61 100755 --- a/contrib/fixup-libstdc++.sh +++ b/contrib/fixup-libstdc++.sh @@ -1,5 +1,5 @@ #!/bin/sh -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Run as: fixup-libstdc++.sh diff --git a/contrib/install.sh b/contrib/install.sh index 702b207fbb5aa..f4e11b6089efb 100755 --- a/contrib/install.sh +++ b/contrib/install.sh @@ -1,5 +1,5 @@ #!/bin/sh -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Usage: very similar to `install` # install.sh 755 src1 src2 ... dest diff --git a/contrib/julia-config.jl b/contrib/julia-config.jl index a61727213c187..8b8ae445d64d1 100755 --- a/contrib/julia-config.jl +++ b/contrib/julia-config.jl @@ -1,5 +1,5 @@ #!/usr/bin/env julia -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license const options = [ diff --git a/contrib/julia.appdata.xml b/contrib/julia.appdata.xml index aa36b84bf2a65..576d88358ee7c 100644 --- a/contrib/julia.appdata.xml +++ b/contrib/julia.appdata.xml @@ -21,8 +21,8 @@

- http://julialang.org/images/julia-gnome.png + https://julialang.org/images/julia-gnome.png - http://julialang.org/ + https://julialang.org/ julia-dev@googlegroups.com diff --git a/contrib/julia.lang b/contrib/julia.lang index 95fed9c9c0fd5..80dff29ce6057 100644 --- a/contrib/julia.lang +++ b/contrib/julia.lang @@ -104,7 +104,7 @@ nothing - + ARGS LOAD_PATH CPU_CORES @@ -121,7 +121,7 @@ ANY - + @@ -135,7 +135,7 @@ - + \(|\) | @@ -185,7 +185,7 @@ using - + ` ` @@ -214,7 +214,7 @@ - + Base Core Main diff --git a/contrib/mac/juliarc.jl b/contrib/mac/juliarc.jl index da5bc9a95dd4c..066a50cda9e7a 100644 --- a/contrib/mac/juliarc.jl +++ b/contrib/mac/juliarc.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Set up environment for Julia OSX binary distribution let diff --git a/contrib/mac/mac-gtk.sh b/contrib/mac/mac-gtk.sh index f17f106c372d6..86be8aa8e1670 100644 --- a/contrib/mac/mac-gtk.sh +++ b/contrib/mac/mac-gtk.sh @@ -1,5 +1,5 @@ #!/bin/sh -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # This script will attempt to download and build GTK+-3, # including dependencies, in ~/gtk (also puts stuff in diff --git a/contrib/prepare_release.sh b/contrib/prepare_release.sh index f0c1dd037b2cd..9cd2b96a1b167 100755 --- a/contrib/prepare_release.sh +++ b/contrib/prepare_release.sh @@ -1,5 +1,5 @@ #!/bin/sh -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # script to prepare binaries and source tarballs for a Julia release # aka "bucket dance" julianightlies -> julialang diff --git a/contrib/relative_path.sh b/contrib/relative_path.sh index 34e526b7f1e31..ebb3095a7e45f 100755 --- a/contrib/relative_path.sh +++ b/contrib/relative_path.sh @@ -1,5 +1,5 @@ #!/bin/sh -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # both $1 and $2 are absolute paths beginning with / # returns relative path to $2/$target from $1/$source diff --git a/contrib/stringreplace.c b/contrib/stringreplace.c index 8ebee3fac7430..8067132818151 100644 --- a/contrib/stringreplace.c +++ b/contrib/stringreplace.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include #include diff --git a/contrib/travis_fastfail.sh b/contrib/travis_fastfail.sh index 6eb349a49b1ff..410cbe2bccafc 100755 --- a/contrib/travis_fastfail.sh +++ b/contrib/travis_fastfail.sh @@ -1,5 +1,5 @@ #!/bin/sh -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license curlhdr="Accept: application/vnd.travis-ci.2+json" endpoint="https://api.travis-ci.org/repos/$TRAVIS_REPO_SLUG" diff --git a/contrib/windows/get_toolchain.sh b/contrib/windows/get_toolchain.sh index 09155935fb1cb..290a18195ef58 100755 --- a/contrib/windows/get_toolchain.sh +++ b/contrib/windows/get_toolchain.sh @@ -1,5 +1,5 @@ #!/bin/sh -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # download mingw-w64 compilers from opensuse build service, usage: # ./get_toolchain.sh 64 diff --git a/contrib/windows/msys_build.sh b/contrib/windows/msys_build.sh index 500171f72c4d7..36dd0eaeb7762 100755 --- a/contrib/windows/msys_build.sh +++ b/contrib/windows/msys_build.sh @@ -1,5 +1,5 @@ #!/bin/sh -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Script to compile Windows Julia, using binary dependencies from nightlies. # Should work in MSYS assuming 7zip is installed and on the path, diff --git a/contrib/windows/winrpm.sh b/contrib/windows/winrpm.sh index a329220c03370..ef5ae6e227b20 100755 --- a/contrib/windows/winrpm.sh +++ b/contrib/windows/winrpm.sh @@ -1,5 +1,5 @@ #!/bin/sh -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # build-time mini version of WinRPM, usage: # ./winrpm.sh http://download.opensuse.org/repositories/windows:/mingw:/win64/openSUSE_13.2/ mingw64-zlib1 diff --git a/doc/README.md b/doc/README.md index 0d55ec84c9b05..19a732f8800ba 100644 --- a/doc/README.md +++ b/doc/README.md @@ -1,6 +1,6 @@ # Julia Documentation README -Julia's documentation is written in Markdown. A reference of all supported syntax can be found in the [manual](http://docs.julialang.org/en/latest/manual/documentation/#markdown-syntax). All documentation can be found in the Markdown files in `doc/src/` and the docstrings in Julia source files in `base/`. +Julia's documentation is written in Markdown. A reference of all supported syntax can be found in the [manual](https://docs.julialang.org/en/latest/manual/documentation/#markdown-syntax). All documentation can be found in the Markdown files in `doc/src/` and the docstrings in Julia source files in `base/`. ## Requirements diff --git a/doc/man/julia.1 b/doc/man/julia.1 index ab01e94afe746..cc77d36e07969 100644 --- a/doc/man/julia.1 +++ b/doc/man/julia.1 @@ -23,14 +23,14 @@ .TH JULIA 1 2013-12-10 Julia "Julia Programmers' Reference Guide" -.\" from the front page of http://julialang.org/ +.\" from the front page of https://julialang.org/ .SH NAME julia - high-level, high-performance dynamic programming language for technical computing .SH SYNOPSIS julia [option] [program] [args..] -.\" Taken almost verbatim from the front page of http://julialang.org/ +.\" Taken almost verbatim from the front page of https://julialang.org/ .SH DESCRIPTION Julia is a high-level, high-performance dynamic programming language for technical computing, with syntax that is familiar to users @@ -47,7 +47,7 @@ by defining functions and overloading them for different combinations of argument types, which can also be user-defined. For a more in-depth discussion of the rationale and advantages of Julia over other systems, please see the online manual: -http://docs.julialang.org/en/latest/manual/ +https://docs.julialang.org/en/latest/manual/ If a Julia source file is given as a \fIprogram\fP (optionally followed by arguments in \fIargs\fP) Julia will execute the program and exit. diff --git a/doc/src/devdocs/cartesian.md b/doc/src/devdocs/cartesian.md index c63df3f188283..779ca66656881 100644 --- a/doc/src/devdocs/cartesian.md +++ b/doc/src/devdocs/cartesian.md @@ -63,7 +63,7 @@ julia> macroexpand(:(@nref 2 A i)) The first argument to both of these macros is the number of expressions, which must be an integer. When you're writing a function that you intend to work in multiple dimensions, this may not be something you want to hard-code. If you're writing code that you need to work with older Julia -versions, currently you should use the `@ngenerate` macro described in [an older version of this documentation](http://docs.julialang.org/en/release-0.3/devdocs/cartesian/#supplying-the-number-of-expressions). +versions, currently you should use the `@ngenerate` macro described in [an older version of this documentation](https://docs.julialang.org/en/release-0.3/devdocs/cartesian/#supplying-the-number-of-expressions). Starting in Julia 0.4-pre, the recommended approach is to use a `@generated function`. Here's an example: diff --git a/doc/src/manual/arrays.md b/doc/src/manual/arrays.md index d2dd09906b16f..fcdbaac0905c6 100644 --- a/doc/src/manual/arrays.md +++ b/doc/src/manual/arrays.md @@ -376,7 +376,7 @@ multidimensional index. When combined with other indexing forms and iterators that yield `CartesianIndex`es, however, this can lead directly to very elegant and efficient code. See [Iteration](@ref) below, and for some more advanced examples, see [this blog post on multidimensional algorithms and -iteration](http://julialang.org/blog/2016/02/iteration). +iteration](https://julialang.org/blog/2016/02/iteration). Arrays of `CartesianIndex{N}` are also supported. They represent a collection of scalar indices that each span `N` dimensions, enabling a form of indexing diff --git a/doc/src/manual/calling-c-and-fortran-code.md b/doc/src/manual/calling-c-and-fortran-code.md index 17d00fbc95f9b..8c9c83c74f562 100644 --- a/doc/src/manual/calling-c-and-fortran-code.md +++ b/doc/src/manual/calling-c-and-fortran-code.md @@ -973,7 +973,7 @@ notification to the condition. ## More About Callbacks -For more details on how to pass callbacks to C libraries, see this [blog post](http://julialang.org/blog/2013/05/callback). +For more details on how to pass callbacks to C libraries, see this [blog post](https://julialang.org/blog/2013/05/callback). ## C++ diff --git a/doc/src/manual/dates.md b/doc/src/manual/dates.md index 6c4e4a84a40a8..39738aaf5f2ad 100644 --- a/doc/src/manual/dates.md +++ b/doc/src/manual/dates.md @@ -559,7 +559,7 @@ julia> round(DateTime(2016, 8, 6, 20, 15), Dates.Day) Unlike the numeric [`round()`](@ref) method, which breaks ties toward the even number by default, the [`TimeType`](@ref)[`round()`](@ref) method uses the `RoundNearestTiesUp` rounding mode. (It's difficult to guess what breaking ties to nearest "even" [`TimeType`](@ref) would entail.) Further -details on the available `RoundingMode` s can be found in the [API reference](http://docs.julialang.org/en/latest/stdlib/dates.html). +details on the available `RoundingMode` s can be found in the [API reference](https://docs.julialang.org/en/latest/stdlib/dates.html). Rounding should generally behave as expected, but there are a few cases in which the expected behaviour is not obvious. @@ -624,5 +624,5 @@ will result in the months field having an odd value. Because both months and yea an irregular number of days, whether rounding to an even number of days will result in an even value in the days field is uncertain. -See the [API reference](http://docs.julialang.org/en/latest/stdlib/dates.html) for additional information +See the [API reference](https://docs.julialang.org/en/latest/stdlib/dates.html) for additional information on methods exported from the `Dates` module. diff --git a/doc/src/manual/faq.md b/doc/src/manual/faq.md index cf2f4b78f3710..69473a4e08406 100644 --- a/doc/src/manual/faq.md +++ b/doc/src/manual/faq.md @@ -710,7 +710,7 @@ Finally, you may also consider building Julia from source for yourself. This opt for those individuals who are comfortable at the command line, or interested in learning. If this describes you, you may also be interested in reading our [guidelines for contributing](https://github.com/JuliaLang/julia/blob/master/CONTRIBUTING.md). -Links to each of these download types can be found on the download page at [http://julialang.org/downloads/](http://julialang.org/downloads/). +Links to each of these download types can be found on the download page at [https://julialang.org/downloads/](https://julialang.org/downloads/). Note that not all versions of Julia are available for all platforms. ### When are deprecated functions removed? diff --git a/doc/src/manual/getting-started.md b/doc/src/manual/getting-started.md index 8dc9b7d9e53fc..d41d6b1bdfa03 100644 --- a/doc/src/manual/getting-started.md +++ b/doc/src/manual/getting-started.md @@ -1,7 +1,7 @@ # Getting Started Julia installation is straightforward, whether using precompiled binaries or compiling from source. -Download and install Julia by following the instructions at [http://julialang.org/downloads/](http://julialang.org/downloads/). +Download and install Julia by following the instructions at [https://julialang.org/downloads/](https://julialang.org/downloads/). The easiest way to learn and experiment with Julia is by starting an interactive session (also known as a read-eval-print loop or "repl") by double-clicking the Julia executable or running @@ -11,7 +11,7 @@ known as a read-eval-print loop or "repl") by double-clicking the Julia executab $ julia _ _ _ _(_)_ | A fresh approach to technical computing - (_) | (_) (_) | Documentation: http://docs.julialang.org + (_) | (_) (_) | Documentation: https://docs.julialang.org _ _ _| |_ __ _ | Type "?help" for help. | | | | | | |/ _` | | | | |_| | | | (_| | | Version 0.5.0-dev+2440 (2016-02-01 02:22 UTC) @@ -151,5 +151,5 @@ with Julia: * [Hands-on Julia](https://github.com/dpsanders/hands_on_julia) * [Tutorial for Homer Reid's numerical analysis class](http://homerreid.dyndns.org/teaching/18.330/JuliaProgramming.shtml) * [An introductory presentation](https://raw.githubusercontent.com/ViralBShah/julia-presentations/master/Fifth-Elephant-2013/Fifth-Elephant-2013.pdf) - * [Videos from the Julia tutorial at MIT](http://julialang.org/blog/2013/03/julia-tutorial-MIT) + * [Videos from the Julia tutorial at MIT](https://julialang.org/blog/2013/03/julia-tutorial-MIT) * [YouTube videos from the JuliaCons](https://www.youtube.com/user/JuliaLanguage/playlists) diff --git a/doc/src/manual/interacting-with-julia.md b/doc/src/manual/interacting-with-julia.md index b214e6ec9d052..4d0c0d0df0b35 100644 --- a/doc/src/manual/interacting-with-julia.md +++ b/doc/src/manual/interacting-with-julia.md @@ -10,7 +10,7 @@ on the executable: $ julia _ _ _ _(_)_ | A fresh approach to technical computing - (_) | (_) (_) | Documentation: http://docs.julialang.org + (_) | (_) (_) | Documentation: https://docs.julialang.org _ _ _| |_ __ _ | Type "?help" for help. | | | | | | |/ _` | | | | |_| | | | (_| | | Version 0.6.0-dev.2493 (2017-01-31 18:53 UTC) diff --git a/examples/ModInts.jl b/examples/ModInts.jl index d811722814843..a6894cd9bfa76 100644 --- a/examples/ModInts.jl +++ b/examples/ModInts.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module ModInts export ModInt diff --git a/examples/bubblesort.jl b/examples/bubblesort.jl index 8b39e6793ded4..6b7c244da1fa9 100644 --- a/examples/bubblesort.jl +++ b/examples/bubblesort.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license import Base.Sort struct BubbleSortAlg <: Sort.Algorithm end diff --git a/examples/clustermanager/0mq/ZMQCM.jl b/examples/clustermanager/0mq/ZMQCM.jl index 4d89de0ed029c..d18e7b66d58d0 100644 --- a/examples/clustermanager/0mq/ZMQCM.jl +++ b/examples/clustermanager/0mq/ZMQCM.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using ZMQ diff --git a/examples/clustermanager/0mq/broker.jl b/examples/clustermanager/0mq/broker.jl index 6801700b762c5..87d2849046356 100644 --- a/examples/clustermanager/0mq/broker.jl +++ b/examples/clustermanager/0mq/broker.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license include("ZMQCM.jl") start_broker() diff --git a/examples/clustermanager/0mq/head.jl b/examples/clustermanager/0mq/head.jl index b8929c47889ff..ff0f718eb10b5 100644 --- a/examples/clustermanager/0mq/head.jl +++ b/examples/clustermanager/0mq/head.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license include("ZMQCM.jl") diff --git a/examples/clustermanager/0mq/worker.jl b/examples/clustermanager/0mq/worker.jl index e541044b009f2..bbb2ebca60a85 100644 --- a/examples/clustermanager/0mq/worker.jl +++ b/examples/clustermanager/0mq/worker.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license include("ZMQCM.jl") diff --git a/examples/clustermanager/simple/UnixDomainCM.jl b/examples/clustermanager/simple/UnixDomainCM.jl index f96c6e0fcf7a6..d1e27e2c6fa2c 100644 --- a/examples/clustermanager/simple/UnixDomainCM.jl +++ b/examples/clustermanager/simple/UnixDomainCM.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license import Base: launch, manage, connect, exit diff --git a/examples/clustermanager/simple/head.jl b/examples/clustermanager/simple/head.jl index b42331ef9fcf1..cb16b8eb4d740 100644 --- a/examples/clustermanager/simple/head.jl +++ b/examples/clustermanager/simple/head.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license include("UnixDomainCM.jl") diff --git a/examples/clustermanager/simple/test_simple.jl b/examples/clustermanager/simple/test_simple.jl index faca7e168fc98..57e8a8a0f28fe 100644 --- a/examples/clustermanager/simple/test_simple.jl +++ b/examples/clustermanager/simple/test_simple.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license cmanpath = joinpath(dirname(@__FILE__), "UnixDomainCM.jl") include(cmanpath) diff --git a/examples/dictchannel.jl b/examples/dictchannel.jl index 83c8e1eebc70c..f1b9bfd68a6ca 100644 --- a/examples/dictchannel.jl +++ b/examples/dictchannel.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license import Base: put!, wait, isready, take!, fetch diff --git a/examples/embedding/embedding.c b/examples/embedding/embedding.c index d0018e2e743c0..5bb70aadc04c2 100644 --- a/examples/embedding/embedding.c +++ b/examples/embedding/embedding.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include #include diff --git a/examples/juliatypes.jl b/examples/juliatypes.jl index efd924c18e828..09f6fc582947e 100644 --- a/examples/juliatypes.jl +++ b/examples/juliatypes.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license import Base: convert, show diff --git a/examples/lru.jl b/examples/lru.jl index dd682ba5177e7..7fa54ff7eae9b 100644 --- a/examples/lru.jl +++ b/examples/lru.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module LRUExample # An LRU (Least Recently Used) cache is an associative data structure which diff --git a/examples/lru_test.jl b/examples/lru_test.jl index 62aa29fbf6a03..3370220719dcd 100644 --- a/examples/lru_test.jl +++ b/examples/lru_test.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using .LRUExample diff --git a/examples/ndgrid.jl b/examples/ndgrid.jl index 228c609ee7fa2..3bce2fce36d50 100644 --- a/examples/ndgrid.jl +++ b/examples/ndgrid.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ndgrid(v::AbstractVector) = copy(v) diff --git a/examples/queens.jl b/examples/queens.jl index 0e70d7d5eb895..418637a2be8db 100644 --- a/examples/queens.jl +++ b/examples/queens.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # n-queens (nqueens) solver, for nsquaresx-by-nsquaresy board diff --git a/examples/quine.jl b/examples/quine.jl index be60f8baca92a..aae47e3dbfdbf 100644 --- a/examples/quine.jl +++ b/examples/quine.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license -x="println(\"# This file is a part of Julia. License is MIT: http://julialang.org/license\\n\\nx=\$(repr(x))\\n\$x\")" -println("# This file is a part of Julia. License is MIT: http://julialang.org/license\n\nx=$(repr(x))\n$x") +x="println(\"# This file is a part of Julia. License is MIT: https://julialang.org/license\\n\\nx=\$(repr(x))\\n\$x\")" +println("# This file is a part of Julia. License is MIT: https://julialang.org/license\n\nx=$(repr(x))\n$x") diff --git a/examples/staged.jl b/examples/staged.jl index f65db5942687e..5b14f1d1117d3 100644 --- a/examples/staged.jl +++ b/examples/staged.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license function add_method(gf, an, at, body) argexs = [Expr(Symbol("::"), an[i], at[i]) for i=1:length(an)] diff --git a/examples/time.jl b/examples/time.jl index 98f14449c8d81..45bd30ff9fce5 100644 --- a/examples/time.jl +++ b/examples/time.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module Time export TimeDelta diff --git a/examples/typetree.jl b/examples/typetree.jl index 08c05b946f7bd..1ca8714833291 100644 --- a/examples/typetree.jl +++ b/examples/typetree.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module TypeTrees ## diff --git a/examples/wordcount.jl b/examples/wordcount.jl index 601ffc3321a60..2011c885a1442 100644 --- a/examples/wordcount.jl +++ b/examples/wordcount.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # wordcount.jl # diff --git a/src/APInt-C.cpp b/src/APInt-C.cpp index c911c8586c459..9d7092d5338a5 100644 --- a/src/APInt-C.cpp +++ b/src/APInt-C.cpp @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include "llvm-version.h" #include diff --git a/src/APInt-C.h b/src/APInt-C.h index 2228c274cd11a..9db0094a81690 100644 --- a/src/APInt-C.h +++ b/src/APInt-C.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #ifndef APINT_C_H #define APINT_C_H diff --git a/src/abi_aarch64.cpp b/src/abi_aarch64.cpp index affdb93202001..346dbf1ec5276 100644 --- a/src/abi_aarch64.cpp +++ b/src/abi_aarch64.cpp @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license //===----------------------------------------------------------------------===// // diff --git a/src/abi_arm.cpp b/src/abi_arm.cpp index f2eb01d46745a..c89a24cd928ad 100644 --- a/src/abi_arm.cpp +++ b/src/abi_arm.cpp @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license //===----------------------------------------------------------------------===// // diff --git a/src/anticodegen.c b/src/anticodegen.c index 03e1178ea45d8..b40e9b7fb343a 100644 --- a/src/anticodegen.c +++ b/src/anticodegen.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include "julia.h" #include "julia_internal.h" diff --git a/src/array.c b/src/array.c index 51690ddb5774f..447fa98301ebd 100644 --- a/src/array.c +++ b/src/array.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license /* array constructors and primitives diff --git a/src/ast.c b/src/ast.c index b8845d2e26ca8..6b9ac084649ff 100644 --- a/src/ast.c +++ b/src/ast.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license /* AST diff --git a/src/builtin_proto.h b/src/builtin_proto.h index 0ac2a70c4b19b..001cf160ea15a 100644 --- a/src/builtin_proto.h +++ b/src/builtin_proto.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #ifndef BUILTIN_PROTO_H #define BUILTIN_PROTO_H diff --git a/src/builtins.c b/src/builtins.c index 12a1b7b43e70e..e117eae5dd54e 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license /* implementations of built-in functions diff --git a/src/ccall.cpp b/src/ccall.cpp index 4691aeb4a6e6e..87282e432fb17 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license // --- the ccall, cglobal, and llvm intrinsics --- diff --git a/src/ccalltest.c b/src/ccalltest.c index b8781567fcf40..91b804e0742b4 100644 --- a/src/ccalltest.c +++ b/src/ccalltest.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include #include diff --git a/src/cgmemmgr.cpp b/src/cgmemmgr.cpp index 95f0fbdfc17b5..bd74bada042ba 100644 --- a/src/cgmemmgr.cpp +++ b/src/cgmemmgr.cpp @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include "llvm-version.h" #include "platform.h" diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 1561f7883f1eb..616b247533d41 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license // utility procedures used in code generation diff --git a/src/codegen.cpp b/src/codegen.cpp index a42f4923ffa8a..ee4552d0b083c 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include "llvm-version.h" #include "platform.h" diff --git a/src/codegen_internal.h b/src/codegen_internal.h index 3932884788726..f2175991f4138 100644 --- a/src/codegen_internal.h +++ b/src/codegen_internal.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #if defined(USE_ORCJIT) && JL_LLVM_VERSION <= 30800 # include diff --git a/src/datatype.c b/src/datatype.c index 69c571aa04c04..71d865cb1db98 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license /* defining DataTypes diff --git a/src/debuginfo.cpp b/src/debuginfo.cpp index a503b23487937..11ac809029e56 100644 --- a/src/debuginfo.cpp +++ b/src/debuginfo.cpp @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include "platform.h" diff --git a/src/dlload.c b/src/dlload.c index a73813ba33684..a4cecc52f5216 100644 --- a/src/dlload.c +++ b/src/dlload.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include #include diff --git a/src/dump.c b/src/dump.c index 1874926fddec0..4c58d5bb8be1c 100644 --- a/src/dump.c +++ b/src/dump.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license /* saving and restoring system images diff --git a/src/file_constants.h b/src/file_constants.h index 27f6b0bc4cdde..846404befd2fd 100644 --- a/src/file_constants.h +++ b/src/file_constants.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include #include diff --git a/src/fix_llvm_assert.h b/src/fix_llvm_assert.h index 8ed8a5ce4e144..776b127c15846 100644 --- a/src/fix_llvm_assert.h +++ b/src/fix_llvm_assert.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license // Include this file after every blocks of LLVM includes to set the assertion back. diff --git a/src/gc-debug.c b/src/gc-debug.c index ef90d9384bd12..876474606eaf5 100644 --- a/src/gc-debug.c +++ b/src/gc-debug.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include "gc.h" #include diff --git a/src/gc-pages.c b/src/gc-pages.c index aecf418e1ba29..7a668dbc3ef8b 100644 --- a/src/gc-pages.c +++ b/src/gc-pages.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include "gc.h" #ifndef _OS_WINDOWS_ diff --git a/src/gc.c b/src/gc.c index 18408c6b50b6f..b75aa0f6f541c 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include "gc.h" diff --git a/src/gc.h b/src/gc.h index b806ef5a783ce..48cc90547f229 100644 --- a/src/gc.h +++ b/src/gc.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license /* allocation and garbage collection diff --git a/src/gen_sysimg_symtab.jl b/src/gen_sysimg_symtab.jl index e8a440ce14112..4df1ac3c7df67 100644 --- a/src/gen_sysimg_symtab.jl +++ b/src/gen_sysimg_symtab.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # script to generate tables of common symbols from a system image # steps to rerun this: diff --git a/src/gf.c b/src/gf.c index d2be995dfdd96..0a4f78878574a 100644 --- a/src/gf.c +++ b/src/gf.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license /* Generic Functions diff --git a/src/init.c b/src/init.c index 7fe5098264584..29edd9b93f1ca 100644 --- a/src/init.c +++ b/src/init.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license /* init.c diff --git a/src/interpreter.c b/src/interpreter.c index be288ce5252aa..a4743edcec4b4 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include #include diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index 1853abead3452..d36bb5839a807 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license namespace JL_I { #include "intrinsics.h" diff --git a/src/intrinsics.h b/src/intrinsics.h index 15ea45dc2d73d..44e3c128e8926 100644 --- a/src/intrinsics.h +++ b/src/intrinsics.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #define INTRINSICS \ /* wrap and unwrap */ \ diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index ddb71b565c807..b049c5da6db04 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include "llvm-version.h" #include "platform.h" diff --git a/src/jitlayers.h b/src/jitlayers.h index 6a110e092d898..02a38275d6218 100644 --- a/src/jitlayers.h +++ b/src/jitlayers.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include #include diff --git a/src/jl_uv.c b/src/jl_uv.c index 249d63a98678c..d1008481db2d9 100644 --- a/src/jl_uv.c +++ b/src/jl_uv.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include "platform.h" diff --git a/src/jlapi.c b/src/jlapi.c index 7bdbc82e43a70..703ec688aad8c 100644 --- a/src/jlapi.c +++ b/src/jlapi.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license /* jlapi.c diff --git a/src/jloptions.c b/src/jloptions.c index fca0657b59c49..38333570e52c9 100644 --- a/src/jloptions.c +++ b/src/jloptions.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include diff --git a/src/jltypes.c b/src/jltypes.c index 534d9cb5a70c9..01724a722571e 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license /* Types diff --git a/src/julia.h b/src/julia.h index 2368117e58029..0d2ad22fc4e00 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #ifndef JULIA_H #define JULIA_H diff --git a/src/julia_internal.h b/src/julia_internal.h index 32312b7fb046e..163d0f449afee 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #ifndef JULIA_INTERNAL_H #define JULIA_INTERNAL_H diff --git a/src/julia_threads.h b/src/julia_threads.h index b8c9087076efb..2dc65a12cecc9 100644 --- a/src/julia_threads.h +++ b/src/julia_threads.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license // Meant to be included in #ifndef JULIA_THREADS_H diff --git a/src/llvm-gcroot.cpp b/src/llvm-gcroot.cpp index a23b5d5d7ef71..7e6bc07a8c492 100644 --- a/src/llvm-gcroot.cpp +++ b/src/llvm-gcroot.cpp @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #define DEBUG_TYPE "lower_gcroot" #undef DEBUG diff --git a/src/llvm-ptls.cpp b/src/llvm-ptls.cpp index 8452b1428159f..750ed613c707d 100644 --- a/src/llvm-ptls.cpp +++ b/src/llvm-ptls.cpp @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #define DEBUG_TYPE "lower_ptls" #undef DEBUG diff --git a/src/llvm-simdloop.cpp b/src/llvm-simdloop.cpp index f5f9d90cdd54e..913887fa62ffb 100644 --- a/src/llvm-simdloop.cpp +++ b/src/llvm-simdloop.cpp @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #define DEBUG_TYPE "lower_simd_loop" #undef DEBUG diff --git a/src/llvm-version.h b/src/llvm-version.h index 02817494c2999..308aa42e14bdd 100644 --- a/src/llvm-version.h +++ b/src/llvm-version.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include #include "fix_llvm_assert.h" diff --git a/src/method.c b/src/method.c index 65caef3a10986..723750cd8ce96 100644 --- a/src/method.c +++ b/src/method.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license /* Defining and adding methods diff --git a/src/module.c b/src/module.c index ec64c58dcc866..c3cde491b9e30 100644 --- a/src/module.c +++ b/src/module.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license /* modules and top-level bindings diff --git a/src/options.h b/src/options.h index f285e32855065..aea15e51fd70e 100644 --- a/src/options.h +++ b/src/options.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #ifndef JL_OPTIONS_H #define JL_OPTIONS_H diff --git a/src/precompile.c b/src/precompile.c index 8994941d15514..747f2dfb4c970 100644 --- a/src/precompile.c +++ b/src/precompile.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license /* precompile.c diff --git a/src/rtutils.c b/src/rtutils.c index 935250ef8baf0..954c352186e52 100644 --- a/src/rtutils.c +++ b/src/rtutils.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license /* utility functions used by the runtime system, generated code, and Base library diff --git a/src/runtime_ccall.cpp b/src/runtime_ccall.cpp index 470652d6357da..3c5d4bec6d7b3 100644 --- a/src/runtime_ccall.cpp +++ b/src/runtime_ccall.cpp @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include "llvm-version.h" #include diff --git a/src/runtime_intrinsics.c b/src/runtime_intrinsics.c index f391588c12d6b..d38c733df0db4 100644 --- a/src/runtime_intrinsics.c +++ b/src/runtime_intrinsics.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license // This is in implementation of the Julia intrinsic functions against boxed types // excluding the native function call interface (ccall, llvmcall) diff --git a/src/safepoint.c b/src/safepoint.c index 2874266ebe4b5..b4281af0c966e 100644 --- a/src/safepoint.c +++ b/src/safepoint.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include "julia.h" #include "julia_internal.h" diff --git a/src/signal-handling.c b/src/signal-handling.c index 78968c05ed91e..75c551bcf1b38 100644 --- a/src/signal-handling.c +++ b/src/signal-handling.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include #include diff --git a/src/signals-mach.c b/src/signals-mach.c index cd7cb1b826557..eb88e187b7505 100644 --- a/src/signals-mach.c +++ b/src/signals-mach.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include #include diff --git a/src/signals-unix.c b/src/signals-unix.c index 2c50ff9ba7b68..00beeb9babd90 100644 --- a/src/signals-unix.c +++ b/src/signals-unix.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include #include diff --git a/src/signals-win.c b/src/signals-win.c index c8901e153ef3c..a54d7e5736d5c 100644 --- a/src/signals-win.c +++ b/src/signals-win.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license // Windows diff --git a/src/simplevector.c b/src/simplevector.c index 9322692059840..805d8d3aa4163 100644 --- a/src/simplevector.c +++ b/src/simplevector.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include #include diff --git a/src/stackwalk.c b/src/stackwalk.c index d3b8cf12a2f13..85e85b3663de3 100644 --- a/src/stackwalk.c +++ b/src/stackwalk.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license /* stackwalk.c diff --git a/src/subtype.c b/src/subtype.c index 7abc59859d897..ab5b83f806802 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license /* subtyping predicate diff --git a/src/support/arraylist.c b/src/support/arraylist.c index 7b7229a63bd36..bb8bf77bd1af4 100644 --- a/src/support/arraylist.c +++ b/src/support/arraylist.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include #include diff --git a/src/support/arraylist.h b/src/support/arraylist.h index 3440367e90849..61ffba1043954 100644 --- a/src/support/arraylist.h +++ b/src/support/arraylist.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #ifndef ARRAYLIST_H #define ARRAYLIST_H diff --git a/src/support/bitvector.c b/src/support/bitvector.c index de13c8e285732..d72006cc1bfa5 100644 --- a/src/support/bitvector.c +++ b/src/support/bitvector.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license /* bit vector primitives diff --git a/src/support/bitvector.h b/src/support/bitvector.h index 10bbdfaea83f5..76c4bdec11818 100644 --- a/src/support/bitvector.h +++ b/src/support/bitvector.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #ifndef BITVECTOR_H #define BITVECTOR_H diff --git a/src/support/crc32c-tables.c b/src/support/crc32c-tables.c index 539b3577175b6..7ff68ffa92774 100644 --- a/src/support/crc32c-tables.c +++ b/src/support/crc32c-tables.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license /* Pregenerated tables for crc32c.c, produced by compiling with -DGEN_CRC32C_TABLES. */ #if POLY != 0x82f63b78 diff --git a/src/support/crc32c.h b/src/support/crc32c.h index 559cf35903a00..9dbf41c9b2811 100644 --- a/src/support/crc32c.h +++ b/src/support/crc32c.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #ifndef CRC32C_H #define CRC32C_H 1 diff --git a/src/support/dirpath.h b/src/support/dirpath.h index 782bf8adf9a1b..ec31dbedf0f22 100644 --- a/src/support/dirpath.h +++ b/src/support/dirpath.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #ifndef DIRPATH_H #define DIRPATH_H diff --git a/src/support/dtypes.h b/src/support/dtypes.h index 56b5ddfb93612..04ffc605e4baa 100644 --- a/src/support/dtypes.h +++ b/src/support/dtypes.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #ifndef DTYPES_H #define DTYPES_H diff --git a/src/support/hashing.c b/src/support/hashing.c index da76f3a793867..632eb2ae12c19 100644 --- a/src/support/hashing.c +++ b/src/support/hashing.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license /* Hashing diff --git a/src/support/hashing.h b/src/support/hashing.h index 5f9b41d6f700d..9532a35abb48e 100644 --- a/src/support/hashing.h +++ b/src/support/hashing.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #ifndef HASHING_H #define HASHING_H diff --git a/src/support/htable.c b/src/support/htable.c index 3e1c9022ca6c7..b5ae094e448dd 100644 --- a/src/support/htable.c +++ b/src/support/htable.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license /* functions common to all hash table instantiations diff --git a/src/support/htable.h b/src/support/htable.h index eb5bfd259a684..968ffb287234d 100644 --- a/src/support/htable.h +++ b/src/support/htable.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #ifndef HTABLE_H #define HTABLE_H diff --git a/src/support/int2str.c b/src/support/int2str.c index 0c74546af18af..13152ee36ccf2 100644 --- a/src/support/int2str.c +++ b/src/support/int2str.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include #include "dtypes.h" diff --git a/src/support/ios.c b/src/support/ios.c index 32cba8fceb618..9dffebc8c808d 100644 --- a/src/support/ios.c +++ b/src/support/ios.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include #include diff --git a/src/support/ios.h b/src/support/ios.h index 02480237a3389..66003f81d82d2 100644 --- a/src/support/ios.h +++ b/src/support/ios.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #ifndef IOS_H #define IOS_H diff --git a/src/support/libsupport.h b/src/support/libsupport.h index 0e8071740f36d..c93527aa8617a 100644 --- a/src/support/libsupport.h +++ b/src/support/libsupport.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #ifndef LIBSUPPORT_H #define LIBSUPPORT_H diff --git a/src/support/libsupportinit.c b/src/support/libsupportinit.c index 78add620116c5..34c6c9cc93ef4 100644 --- a/src/support/libsupportinit.c +++ b/src/support/libsupportinit.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include #include "libsupport.h" diff --git a/src/support/operators.c b/src/support/operators.c index 161fd987f96b8..d1099e5d1d6ff 100644 --- a/src/support/operators.c +++ b/src/support/operators.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include #include diff --git a/src/support/platform.h b/src/support/platform.h index c0e95343c855d..3a4751a5cca3c 100644 --- a/src/support/platform.h +++ b/src/support/platform.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #ifndef PLATFORM_H #define PLATFORM_H diff --git a/src/support/ptrhash.c b/src/support/ptrhash.c index c61f2dd6c1651..b32ed8afe42f8 100644 --- a/src/support/ptrhash.c +++ b/src/support/ptrhash.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license /* pointer hash table diff --git a/src/support/ptrhash.h b/src/support/ptrhash.h index 6929d02d7d615..062287eef6e9f 100644 --- a/src/support/ptrhash.h +++ b/src/support/ptrhash.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #ifndef PTRHASH_H #define PTRHASH_H diff --git a/src/support/strtod.h b/src/support/strtod.h index a63d22447f537..1d4f08df9659a 100644 --- a/src/support/strtod.h +++ b/src/support/strtod.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #ifndef STRTOD_H #define STRTOD_H diff --git a/src/support/timefuncs.c b/src/support/timefuncs.c index 4548577de719f..031967638ec9e 100644 --- a/src/support/timefuncs.c +++ b/src/support/timefuncs.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include #include diff --git a/src/support/timefuncs.h b/src/support/timefuncs.h index 45d22184d29b1..12533e307be84 100644 --- a/src/support/timefuncs.h +++ b/src/support/timefuncs.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #ifndef TIMEFUNCS_H #define TIMEFUNCS_H diff --git a/src/support/utf8.h b/src/support/utf8.h index 8593b35c8d3ae..486243b1d3555 100644 --- a/src/support/utf8.h +++ b/src/support/utf8.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #ifndef UTF8_H #define UTF8_H diff --git a/src/support/utils.h b/src/support/utils.h index 1d48da321162e..930f54fd750ce 100644 --- a/src/support/utils.h +++ b/src/support/utils.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #ifndef UTILS_H #define UTILS_H diff --git a/src/support/wsasocketpair.c b/src/support/wsasocketpair.c index 72cf35daed8ab..77ce3cbc96c98 100644 --- a/src/support/wsasocketpair.c +++ b/src/support/wsasocketpair.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license // This is a compatibility implementation of the unix "socketpair" // function using the Windows Sockets 2 API. diff --git a/src/symbol.c b/src/symbol.c index 4950b1163a1a6..21bc89186b946 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license /* Symbol table diff --git a/src/sys.c b/src/sys.c index 0e984cef70d3a..a1cdc280cc7fb 100644 --- a/src/sys.c +++ b/src/sys.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license /* sys.c diff --git a/src/table.c b/src/table.c index 37738f9816d71..fc136403ad93f 100644 --- a/src/table.c +++ b/src/table.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #define hash_size(h) (jl_array_len(h)/2) diff --git a/src/task.c b/src/task.c index be99b9afdda9a..ae2da1897b82e 100644 --- a/src/task.c +++ b/src/task.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license /* task.c diff --git a/src/threadgroup.c b/src/threadgroup.c index 57e995065a321..eca3be05f398d 100644 --- a/src/threadgroup.c +++ b/src/threadgroup.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license /* threading infrastructure diff --git a/src/threadgroup.h b/src/threadgroup.h index 72e76d2dcfc8a..a0f1ead2881f9 100644 --- a/src/threadgroup.h +++ b/src/threadgroup.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #ifndef THREADGROUP_H #define THREADGROUP_H diff --git a/src/threading.c b/src/threading.c index 81a47b55977e6..a2febf7c9178a 100644 --- a/src/threading.c +++ b/src/threading.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license /* threading infrastructure diff --git a/src/threading.h b/src/threading.h index 803a54a006919..17d0a1c9efbab 100644 --- a/src/threading.h +++ b/src/threading.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #ifndef THREADING_H #define THREADING_H diff --git a/src/timing.c b/src/timing.c index 6c23e5c97eac2..a9ee6d7685a10 100644 --- a/src/timing.c +++ b/src/timing.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include #include "julia.h" diff --git a/src/timing.h b/src/timing.h index e9677cc7da9be..a7f550e9476a8 100644 --- a/src/timing.h +++ b/src/timing.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #ifndef ENABLE_TIMINGS #define JL_TIMING(owner) diff --git a/src/toplevel.c b/src/toplevel.c index 37cf7f97e440f..18ac6021b3ec2 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license /* evaluating top-level expressions, loading source files diff --git a/src/typemap.c b/src/typemap.c index d7d4ecb1d0756..b06be06415d76 100644 --- a/src/typemap.c +++ b/src/typemap.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include #include diff --git a/src/uv_constants.h b/src/uv_constants.h index 569966d6ec5a2..873e2af28b44f 100644 --- a/src/uv_constants.h +++ b/src/uv_constants.h @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include "uv.h" #define XX(uc,lc) :UV_##uc, diff --git a/test/TestHelpers.jl b/test/TestHelpers.jl index 422cd085410ff..3279d8c6d5987 100644 --- a/test/TestHelpers.jl +++ b/test/TestHelpers.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module TestHelpers @@ -138,7 +138,7 @@ parenttype(A::OffsetArray) = parenttype(typeof(A)) Base.parent(A::OffsetArray) = A.parent -errmsg(A) = error("size not supported for arrays with indices $(indices(A)); see http://docs.julialang.org/en/latest/devdocs/offset-arrays/") +errmsg(A) = error("size not supported for arrays with indices $(indices(A)); see https://docs.julialang.org/en/latest/devdocs/offset-arrays/") Base.size(A::OffsetArray) = errmsg(A) Base.size(A::OffsetArray, d) = errmsg(A) Base.eachindex(::IndexCartesian, A::OffsetArray) = CartesianRange(indices(A)) diff --git a/test/abstractarray.jl b/test/abstractarray.jl index 276c074d91dd0..24a181a58b76b 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license A = rand(5,4,3) @testset "Bounds checking" begin diff --git a/test/ambiguous.jl b/test/ambiguous.jl index 69e09a99627e5..e799da798e3d5 100644 --- a/test/ambiguous.jl +++ b/test/ambiguous.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # DO NOT ALTER ORDER OR SPACING OF METHODS BELOW const lineoffset = @__LINE__ + 0 # XXX: __LINE__ at the end of a line is off-by-one diff --git a/test/arrayops.jl b/test/arrayops.jl index ca9bc0636ad2b..6b6e2e241b976 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Array test diff --git a/test/asmvariant.jl b/test/asmvariant.jl index bf1b9116d37e0..27209997511c8 100644 --- a/test/asmvariant.jl +++ b/test/asmvariant.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test diff --git a/test/backtrace.jl b/test/backtrace.jl index 8fbcf9003dea3..140d8c2098f5e 100644 --- a/test/backtrace.jl +++ b/test/backtrace.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license bt = backtrace() have_backtrace = false diff --git a/test/base64.jl b/test/base64.jl index 952e4e056ecd5..c35bce359bdde 100644 --- a/test/base64.jl +++ b/test/base64.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license const inputText = "Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure." const encodedMaxLine76 = diff --git a/test/bigfloat.jl b/test/bigfloat.jl index 64b09a7c4de58..bef4c0ce63fa8 100644 --- a/test/bigfloat.jl +++ b/test/bigfloat.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license @test big(2.0)^big(3) == 8 diff --git a/test/bigint.jl b/test/bigint.jl index aecb932708f75..4bf485ccb8e29 100644 --- a/test/bigint.jl +++ b/test/bigint.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license a = parse(BigInt,"123456789012345678901234567890") b = parse(BigInt,"123456789012345678901234567891") diff --git a/test/bitarray.jl b/test/bitarray.jl index 32bbacfc197bf..9a0541ef7b92c 100644 --- a/test/bitarray.jl +++ b/test/bitarray.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module BitArrayTests diff --git a/test/blas.jl b/test/blas.jl index 780b62dab46fc..56ebdde4ab6ff 100644 --- a/test/blas.jl +++ b/test/blas.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license import Base.LinAlg, Base.LinAlg.BlasReal, Base.LinAlg.BlasComplex diff --git a/test/boundscheck.jl b/test/boundscheck.jl index 80181e21f734d..a1ca1b8051536 100644 --- a/test/boundscheck.jl +++ b/test/boundscheck.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # run boundscheck tests on separate workers launched with --check-bounds={default,yes,no} diff --git a/test/boundscheck_exec.jl b/test/boundscheck_exec.jl index c8d41f184bd55..e6ec13fd2da41 100644 --- a/test/boundscheck_exec.jl +++ b/test/boundscheck_exec.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module TestBoundsCheck diff --git a/test/broadcast.jl b/test/broadcast.jl index a9a25093a4c2b..8e89a12e65a89 100644 --- a/test/broadcast.jl +++ b/test/broadcast.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module TestBroadcastInternals diff --git a/test/cartesian.jl b/test/cartesian.jl index 3180a4f4dccfc..be2605d200143 100644 --- a/test/cartesian.jl +++ b/test/cartesian.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license @test Base.Cartesian.exprresolve(:(1 + 3)) == 4 ex = Base.Cartesian.exprresolve(:(if 5 > 4; :x; else :y; end)) diff --git a/test/ccall.jl b/test/ccall.jl index 3e6ce1bbadbfd..38b4cd15f91f6 100644 --- a/test/ccall.jl +++ b/test/ccall.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license import Base.copy, Base.== diff --git a/test/channels.jl b/test/channels.jl index d3260f57920a1..447215cc12b95 100644 --- a/test/channels.jl +++ b/test/channels.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Test various constructors c=Channel(1) diff --git a/test/char.jl b/test/char.jl index 8a8a2f825cbd3..c40f60de3be23 100644 --- a/test/char.jl +++ b/test/char.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license #tests for /base/char.jl diff --git a/test/checked.jl b/test/checked.jl index 3e98a7b2ea445..43e897ea807fb 100644 --- a/test/checked.jl +++ b/test/checked.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Checked integer arithmetic diff --git a/test/choosetests.jl b/test/choosetests.jl index 1c820e38a7fce..7974eee36f60e 100644 --- a/test/choosetests.jl +++ b/test/choosetests.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license @doc """ diff --git a/test/cmdlineargs.jl b/test/cmdlineargs.jl index 47dda4097da81..802f9ad31d070 100644 --- a/test/cmdlineargs.jl +++ b/test/cmdlineargs.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license catcmd = `cat` if is_windows() diff --git a/test/combinatorics.jl b/test/combinatorics.jl index eaa9e5884f562..95fc8c5046ddd 100644 --- a/test/combinatorics.jl +++ b/test/combinatorics.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license @testset "binomial" begin @test binomial(5,-1) == 0 diff --git a/test/compile.jl b/test/compile.jl index 0e058899537f5..a762f39c43c24 100644 --- a/test/compile.jl +++ b/test/compile.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test diff --git a/test/complex.jl b/test/complex.jl index 6df11be21f99b..fa4d31a63cd57 100644 --- a/test/complex.jl +++ b/test/complex.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license @test reim(2 + 3im) == (2, 3) diff --git a/test/copy.jl b/test/copy.jl index 2e48fc9912afe..ae7ce7d58b7db 100644 --- a/test/copy.jl +++ b/test/copy.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license mainres = ([4, 5, 3], [1, 5, 3]) diff --git a/test/core.jl b/test/core.jl index 72b1a5195ec6d..d685007287bd4 100644 --- a/test/core.jl +++ b/test/core.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # test core language features const Bottom = Union{} diff --git a/test/datafmt.jl b/test/datafmt.jl index 27412b8fa883b..8f936d6be19ee 100644 --- a/test/datafmt.jl +++ b/test/datafmt.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # countlines @test countlines(IOBuffer("\n")) == 1 diff --git a/test/dates/accessors.jl b/test/dates/accessors.jl index 2abfc649d745b..4e6ab4a6eba79 100644 --- a/test/dates/accessors.jl +++ b/test/dates/accessors.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # yearmonthday is the opposite of totaldays # taking Rata Die Day # and returning proleptic Gregorian date diff --git a/test/dates/adjusters.jl b/test/dates/adjusters.jl index 46c7045d2221e..5d94dc821adb6 100644 --- a/test/dates/adjusters.jl +++ b/test/dates/adjusters.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license #trunc dt = Dates.Date(2012, 12, 21) diff --git a/test/dates/arithmetic.jl b/test/dates/arithmetic.jl index d5db8f895cd44..98732fe3fe204 100644 --- a/test/dates/arithmetic.jl +++ b/test/dates/arithmetic.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Time arithmetic a = Dates.Time(23, 59, 59) diff --git a/test/dates/conversions.jl b/test/dates/conversions.jl index 26124cbc82460..d092ec6749fc6 100644 --- a/test/dates/conversions.jl +++ b/test/dates/conversions.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Test conversion to and from unix @test Dates.unix2datetime(Dates.datetime2unix(DateTime(2000, 1, 1))) == DateTime(2000, 1, 1) diff --git a/test/dates/io.jl b/test/dates/io.jl index a27fd23711f74..e7494f94ec7e0 100644 --- a/test/dates/io.jl +++ b/test/dates/io.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Test string/show representation of Date @test string(Dates.Date(1, 1, 1)) == "0001-01-01" # January 1st, 1 AD/CE diff --git a/test/dates/periods.jl b/test/dates/periods.jl index f951790b85696..e4bb9d9bb30b2 100644 --- a/test/dates/periods.jl +++ b/test/dates/periods.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Period testing @test -Dates.Year(1) == Dates.Year(-1) diff --git a/test/dates/query.jl b/test/dates/query.jl index 967e04c391be7..7931612c8fd54 100644 --- a/test/dates/query.jl +++ b/test/dates/query.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Name functions Jan = Dates.DateTime(2013, 1, 1) # Tuesday diff --git a/test/dates/ranges.jl b/test/dates/ranges.jl index 87ed8beaa0d9f..74b2a1983db6f 100644 --- a/test/dates/ranges.jl +++ b/test/dates/ranges.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license let for T in (Dates.Date, Dates.DateTime) diff --git a/test/dates/rounding.jl b/test/dates/rounding.jl index d6faed688eeed..e32f592a0f301 100644 --- a/test/dates/rounding.jl +++ b/test/dates/rounding.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Test conversion to and from the rounding epoch (ISO 8601 year 0000) @test Dates.epochdays2date(-1) == Dates.Date(-1, 12, 31) diff --git a/test/dates/types.jl b/test/dates/types.jl index 0b32a6753ca55..21d7918225a4a 100644 --- a/test/dates/types.jl +++ b/test/dates/types.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Date internal algorithms @test Dates.totaldays(0, 2, 28) == -307 diff --git a/test/dict.jl b/test/dict.jl index dc6e2ab66aad7..ebbdab44273b4 100644 --- a/test/dict.jl +++ b/test/dict.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Pair p = Pair(10,20) diff --git a/test/dimensionful.jl b/test/dimensionful.jl index f7450b896401f..d55defc19e159 100644 --- a/test/dimensionful.jl +++ b/test/dimensionful.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Here we implement a minimal dimensionful type Furlong, which is used # to test dimensional correctness of various functions in Base. Furlong diff --git a/test/distributed.jl b/test/distributed.jl index a3a2cb8cbad8c..99a02ee6b662a 100644 --- a/test/distributed.jl +++ b/test/distributed.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Run the distributed test outside of the main driver since it needs its own # set of dedicated workers. diff --git a/test/distributed_exec.jl b/test/distributed_exec.jl index ca77ab2fd433a..42e8f2ce23fd1 100644 --- a/test/distributed_exec.jl +++ b/test/distributed_exec.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test diff --git a/test/docs.jl b/test/docs.jl index d851b662215da..82e550490521b 100644 --- a/test/docs.jl +++ b/test/docs.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license import Base.Docs: meta, @var, DocStr, parsedoc diff --git a/test/download.jl b/test/download.jl index 317179f172dbd..e982dbfbcc53f 100644 --- a/test/download.jl +++ b/test/download.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license mktempdir() do temp_dir # Download a file diff --git a/test/dsp.jl b/test/dsp.jl index e1a9ee650c439..ced0c8273aa3e 100644 --- a/test/dsp.jl +++ b/test/dsp.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Filter b = [1., 2., 3., 4.] diff --git a/test/embedding.jl b/test/embedding.jl index 628aa3e3781bd..4212589e3f52a 100644 --- a/test/embedding.jl +++ b/test/embedding.jl @@ -1,3 +1,5 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + # test that the embedding example runs without error let if is_windows() diff --git a/test/enums.jl b/test/enums.jl index 5f0573097ef14..cdd64fa3928e9 100644 --- a/test/enums.jl +++ b/test/enums.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license const curmod = current_module() const curmod_name = fullname(curmod) diff --git a/test/env.jl b/test/env.jl index 86eb0ba9b89c6..10c75d4da66b8 100644 --- a/test/env.jl +++ b/test/env.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license @test !("f=a=k=e=n=a=m=e" ∈ keys(ENV)) diff --git a/test/error.jl b/test/error.jl index 4e251f76d93b3..e92aa93bd695c 100644 --- a/test/error.jl +++ b/test/error.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license @test length(ExponentialBackOff(n=10)) == 10 @test collect(ExponentialBackOff(n=10, first_delay=0.01))[1] == 0.01 diff --git a/test/euler.jl b/test/euler.jl index d4ef4744831f7..52b9bd0a3702c 100644 --- a/test/euler.jl +++ b/test/euler.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## Project Euler # diff --git a/test/examples.jl b/test/examples.jl index e66787eb69688..fd63c59f460cd 100644 --- a/test/examples.jl +++ b/test/examples.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license dir = joinpath(JULIA_HOME, Base.DOCDIR, "examples") diff --git a/test/fastmath.jl b/test/fastmath.jl index 754e84362c5e6..1a89a83503eda 100644 --- a/test/fastmath.jl +++ b/test/fastmath.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # fast math diff --git a/test/fft.jl b/test/fft.jl index db165ba93b5ef..0e673ab40d2d1 100644 --- a/test/fft.jl +++ b/test/fft.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # issue #19892 # (test this first to make sure it happens before set_num_threads) diff --git a/test/file.jl b/test/file.jl index ca1429605cd25..269d5fe2ae9cd 100644 --- a/test/file.jl +++ b/test/file.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ############################################# # Create some temporary files & directories # diff --git a/test/float16.jl b/test/float16.jl index b07d7b38cab0d..e9a188329c978 100644 --- a/test/float16.jl +++ b/test/float16.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test diff --git a/test/floatapprox.jl b/test/floatapprox.jl index ddc338e70c94b..0f09312c1d55a 100644 --- a/test/floatapprox.jl +++ b/test/floatapprox.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Floating point numbers - basic tests @test 4.00000000000001 ≈ 4.0 diff --git a/test/floatfuncs.jl b/test/floatfuncs.jl index 94a751ad447ce..3fee77d56dbe3 100644 --- a/test/floatfuncs.jl +++ b/test/floatfuncs.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test diff --git a/test/functional.jl b/test/functional.jl index cdf529ffbd4c3..5256a54167473 100644 --- a/test/functional.jl +++ b/test/functional.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # tests related to functional programming functions and styles diff --git a/test/goto.jl b/test/goto.jl index b2395853a5f74..69a181756036f 100644 --- a/test/goto.jl +++ b/test/goto.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Basic goto tests diff --git a/test/grisu.jl b/test/grisu.jl index 3cf09b0d893c0..5fb6332de6a41 100644 --- a/test/grisu.jl +++ b/test/grisu.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Grisu diff --git a/test/hashing.jl b/test/hashing.jl index 82be0e4c7dffd..de532dba449b7 100644 --- a/test/hashing.jl +++ b/test/hashing.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license types = Any[ Bool, diff --git a/test/i18n.jl b/test/i18n.jl index 55b1f9ad90b98..0ff3d6046c211 100644 --- a/test/i18n.jl +++ b/test/i18n.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.I18n diff --git a/test/inference.jl b/test/inference.jl index 1e34d4d664a3b..bdcabb2ff7a72 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # tests for Core.Inference correctness and precision diff --git a/test/inline.jl b/test/inline.jl index 1de15c909d3e1..2defba2f3852f 100644 --- a/test/inline.jl +++ b/test/inline.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test diff --git a/test/int.jl b/test/int.jl index 09291a3b18bb6..ad2e9a1e8f1f2 100644 --- a/test/int.jl +++ b/test/int.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Test integer conversion routines from int.jl diff --git a/test/intfuncs.jl b/test/intfuncs.jl index 3d80ba1a4860d..547e826480c52 100644 --- a/test/intfuncs.jl +++ b/test/intfuncs.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Int32 and Int64 take different code paths -- test both for T in (Int32, Int64) diff --git a/test/intrinsics.jl b/test/intrinsics.jl index 03f306c1ba684..c1bf0525c87cc 100644 --- a/test/intrinsics.jl +++ b/test/intrinsics.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # intrinsic functions const curmod = current_module() diff --git a/test/intset.jl b/test/intset.jl index 559d6a7e52459..1b8bab5557ec8 100644 --- a/test/intset.jl +++ b/test/intset.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Test functionality of IntSet diff --git a/test/iobuffer.jl b/test/iobuffer.jl index 752fdcb70ea7c..5921b3714b4be 100644 --- a/test/iobuffer.jl +++ b/test/iobuffer.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ioslength(io::IOBuffer) = (io.seekable ? io.size : nb_available(io)) diff --git a/test/iostream.jl b/test/iostream.jl index 1b817ce26d2b6..2eb307f6536b9 100644 --- a/test/iostream.jl +++ b/test/iostream.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Test skipchars for IOStreams mktemp() do path, file diff --git a/test/iterators.jl b/test/iterators.jl index d3e8baf65dd1d..fd0ec31499827 100644 --- a/test/iterators.jl +++ b/test/iterators.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Iterators diff --git a/test/keywordargs.jl b/test/keywordargs.jl index 5045cff21a8cc..14199e2bc7a66 100644 --- a/test/keywordargs.jl +++ b/test/keywordargs.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # simple keyword args case kwf1(ones; tens=0, hundreds=0) = ones + 10*tens + 100*hundreds diff --git a/test/libdl.jl b/test/libdl.jl index b4382d670504b..4aba53527335c 100644 --- a/test/libdl.jl +++ b/test/libdl.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # these could fail on an embedded installation # but for now, we don't handle that case diff --git a/test/libgit2-helpers.jl b/test/libgit2-helpers.jl index a5756250257c1..1f0cae51163df 100644 --- a/test/libgit2-helpers.jl +++ b/test/libgit2-helpers.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license import Base.LibGit2: AbstractCredentials, UserPasswordCredentials, SSHCredentials, CachedCredentials diff --git a/test/libgit2-online.jl b/test/libgit2-online.jl index b8ad3069f2954..cd1c48b0daf3e 100644 --- a/test/libgit2-online.jl +++ b/test/libgit2-online.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ######### # TESTS # diff --git a/test/libgit2.jl b/test/libgit2.jl index b5c61ecb77a37..12d981c6a6e5c 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license isdefined(Main, :TestHelpers) || @eval Main include(joinpath(dirname(@__FILE__), "TestHelpers.jl")) import TestHelpers: challenge_prompt diff --git a/test/linalg/arnoldi.jl b/test/linalg/arnoldi.jl index b5da8bfb8c979..6f895a1d130a5 100644 --- a/test/linalg/arnoldi.jl +++ b/test/linalg/arnoldi.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test diff --git a/test/linalg/bidiag.jl b/test/linalg/bidiag.jl index 73f972b998f4a..7e128844eec7a 100644 --- a/test/linalg/bidiag.jl +++ b/test/linalg/bidiag.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test import Base.LinAlg: BlasReal, BlasFloat diff --git a/test/linalg/bunchkaufman.jl b/test/linalg/bunchkaufman.jl index 9fd6878dcb43f..233447c99f66a 100644 --- a/test/linalg/bunchkaufman.jl +++ b/test/linalg/bunchkaufman.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test diff --git a/test/linalg/cholesky.jl b/test/linalg/cholesky.jl index f0a8c7a85cb75..e6aabd7f8ff17 100644 --- a/test/linalg/cholesky.jl +++ b/test/linalg/cholesky.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license debug = false diff --git a/test/linalg/conjarray.jl b/test/linalg/conjarray.jl index e7c8e7c1359f0..4ba4ac90ad5bb 100644 --- a/test/linalg/conjarray.jl +++ b/test/linalg/conjarray.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license @testset "Core" begin m = [1+im 2; 2 4-im] diff --git a/test/linalg/dense.jl b/test/linalg/dense.jl index 68092b25c8a8c..fdf107d743469 100644 --- a/test/linalg/dense.jl +++ b/test/linalg/dense.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test diff --git a/test/linalg/diagonal.jl b/test/linalg/diagonal.jl index a1ae78ed41eef..6c2f8b2977bcb 100644 --- a/test/linalg/diagonal.jl +++ b/test/linalg/diagonal.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test import Base.LinAlg: BlasFloat, BlasComplex, SingularException diff --git a/test/linalg/eigen.jl b/test/linalg/eigen.jl index 3ae52efb28c80..c44563e5676f2 100644 --- a/test/linalg/eigen.jl +++ b/test/linalg/eigen.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test diff --git a/test/linalg/generic.jl b/test/linalg/generic.jl index d6441fd442e88..89fa70944225b 100644 --- a/test/linalg/generic.jl +++ b/test/linalg/generic.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license import Base: -, *, /, \ using Base.Test diff --git a/test/linalg/givens.jl b/test/linalg/givens.jl index 03420a492683f..06ad1b9399903 100644 --- a/test/linalg/givens.jl +++ b/test/linalg/givens.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test diff --git a/test/linalg/hessenberg.jl b/test/linalg/hessenberg.jl index 0e700fcd4c781..aca74a74199ef 100644 --- a/test/linalg/hessenberg.jl +++ b/test/linalg/hessenberg.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test diff --git a/test/linalg/lapack.jl b/test/linalg/lapack.jl index b0749da0133cb..4bc46b9e8a9aa 100644 --- a/test/linalg/lapack.jl +++ b/test/linalg/lapack.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test diff --git a/test/linalg/lq.jl b/test/linalg/lq.jl index 6b27927b8c9dc..a9cfcdd54b34f 100644 --- a/test/linalg/lq.jl +++ b/test/linalg/lq.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test diff --git a/test/linalg/lu.jl b/test/linalg/lu.jl index 3a6b2d5d09176..674a5e71cf636 100644 --- a/test/linalg/lu.jl +++ b/test/linalg/lu.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license debug = false diff --git a/test/linalg/matmul.jl b/test/linalg/matmul.jl index 7ee9e13b85eeb..c97f69d224212 100644 --- a/test/linalg/matmul.jl +++ b/test/linalg/matmul.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test diff --git a/test/linalg/pinv.jl b/test/linalg/pinv.jl index e01c0e253c1bd..f1f7745658061 100644 --- a/test/linalg/pinv.jl +++ b/test/linalg/pinv.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # # Test the pseudo-inverse diff --git a/test/linalg/qr.jl b/test/linalg/qr.jl index e3c4becd32502..2de9f65fa774c 100644 --- a/test/linalg/qr.jl +++ b/test/linalg/qr.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license debug = false using Base.Test diff --git a/test/linalg/rowvector.jl b/test/linalg/rowvector.jl index 8bd6e5c91e333..e63bae94a35b6 100644 --- a/test/linalg/rowvector.jl +++ b/test/linalg/rowvector.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license @testset "Core" begin v = [1,2,3] diff --git a/test/linalg/schur.jl b/test/linalg/schur.jl index 92027cad6b430..9b48443f278c7 100644 --- a/test/linalg/schur.jl +++ b/test/linalg/schur.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test diff --git a/test/linalg/special.jl b/test/linalg/special.jl index f7d073bd05b28..3d58d5f89cc2a 100644 --- a/test/linalg/special.jl +++ b/test/linalg/special.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test debug = false diff --git a/test/linalg/svd.jl b/test/linalg/svd.jl index 5e26babf44cd6..f8d1611fc9a1a 100644 --- a/test/linalg/svd.jl +++ b/test/linalg/svd.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test diff --git a/test/linalg/symmetric.jl b/test/linalg/symmetric.jl index 0ec3b7beaf2d5..cc03937982cde 100644 --- a/test/linalg/symmetric.jl +++ b/test/linalg/symmetric.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test diff --git a/test/linalg/triangular.jl b/test/linalg/triangular.jl index 829b8bee7e02a..f6dbe41552cc0 100644 --- a/test/linalg/triangular.jl +++ b/test/linalg/triangular.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license debug = false using Base.Test diff --git a/test/linalg/tridiag.jl b/test/linalg/tridiag.jl index 284c58053eefc..4ffdd3f38a561 100644 --- a/test/linalg/tridiag.jl +++ b/test/linalg/tridiag.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license module TridiagTest using Base.Test diff --git a/test/linalg/uniformscaling.jl b/test/linalg/uniformscaling.jl index 30d732e3da0a1..4049a44f79284 100644 --- a/test/linalg/uniformscaling.jl +++ b/test/linalg/uniformscaling.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test diff --git a/test/lineedit.jl b/test/lineedit.jl index f2c31f3f7d935..4aeca1b38797c 100644 --- a/test/lineedit.jl +++ b/test/lineedit.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.LineEdit isdefined(Main, :TestHelpers) || @eval Main include(joinpath(dirname(@__FILE__), "TestHelpers.jl")) diff --git a/test/llvmcall.jl b/test/llvmcall.jl index 1565f25992c36..ac75a3575ac29 100644 --- a/test/llvmcall.jl +++ b/test/llvmcall.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.llvmcall diff --git a/test/llvmcall2.jl b/test/llvmcall2.jl index b365129919541..a0129f270d21a 100644 --- a/test/llvmcall2.jl +++ b/test/llvmcall2.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license function declared_floor(x::Float64) return ccall("llvm.floor.f64", llvmcall, Float64, (Float64,), x) diff --git a/test/loading.jl b/test/loading.jl index 4fbb04d083bd6..618700d228411 100644 --- a/test/loading.jl +++ b/test/loading.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test diff --git a/test/markdown.jl b/test/markdown.jl index 7a4711663dba5..4eba7019798e2 100644 --- a/test/markdown.jl +++ b/test/markdown.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Markdown import Base.Markdown: MD, Paragraph, Header, Italic, Bold, LineBreak, plain, term, html, rst, Table, Code, LaTeX, Footnote diff --git a/test/math.jl b/test/math.jl index 744ce7d7a4be4..04ce580e47346 100644 --- a/test/math.jl +++ b/test/math.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license @testset "clamp" begin @test clamp(0, 1, 3) == 1 diff --git a/test/meta.jl b/test/meta.jl index 17deda5d2099e..0efa06566e959 100644 --- a/test/meta.jl +++ b/test/meta.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # test meta-expressions that annotate blocks of code diff --git a/test/misc.jl b/test/misc.jl index a1e2b99096f77..f03edaa1ea34b 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Tests that do not really go anywhere else diff --git a/test/mmap.jl b/test/mmap.jl index f79a1154baf21..eb6c37fbb955c 100644 --- a/test/mmap.jl +++ b/test/mmap.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license file = tempname() write(file, "Hello World\n") diff --git a/test/mod2pi.jl b/test/mod2pi.jl index 05e8229159e86..103402fde67ba 100644 --- a/test/mod2pi.jl +++ b/test/mod2pi.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # NOTES on range reduction # [1] compute numbers near pi: http://www.cs.berkeley.edu/~wkahan/testpi/nearpi.c diff --git a/test/mpfr.jl b/test/mpfr.jl index 521eb0f69c2ea..d25f7a67a23ff 100644 --- a/test/mpfr.jl +++ b/test/mpfr.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license import Base.MPFR # constructors diff --git a/test/netload/memtest.jl b/test/netload/memtest.jl index b69b35dec658f..b024df4980e55 100644 --- a/test/netload/memtest.jl +++ b/test/netload/memtest.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license struct RUsage ru_utime_sec::Clong # user CPU time used diff --git a/test/netload/nettest.jl b/test/netload/nettest.jl index 0cc50fd450aa2..0f7394def95c8 100644 --- a/test/netload/nettest.jl +++ b/test/netload/nettest.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Run various networking tests checking to see how we perform under large loads addprocs(1) diff --git a/test/nullable.jl b/test/nullable.jl index 3f2dc75cd6126..6c118ec9620e8 100644 --- a/test/nullable.jl +++ b/test/nullable.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # "is a null with type T", curried on 2nd argument isnull_oftype(x::Nullable, T::Type) = eltype(x) == T && isnull(x) diff --git a/test/numbers.jl b/test/numbers.jl index 738d22dfb6f6e..9bd260bcb659d 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license const ≣ = isequal # convenient for comparing NaNs diff --git a/test/offsetarray.jl b/test/offsetarray.jl index edb61d47263ef..bb755579d63a2 100644 --- a/test/offsetarray.jl +++ b/test/offsetarray.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license isdefined(Main, :TestHelpers) || @eval Main include(joinpath(dirname(@__FILE__), "TestHelpers.jl")) using TestHelpers.OAs diff --git a/test/operators.jl b/test/operators.jl index a95e2a24dc3da..66fbe1aae8a47 100644 --- a/test/operators.jl +++ b/test/operators.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license @test ifelse(true, 1, 2) == 1 @test ifelse(false, 1, 2) == 2 diff --git a/test/osutils.jl b/test/osutils.jl index 3eba2323a9a3e..270680c54b601 100644 --- a/test/osutils.jl +++ b/test/osutils.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license @test !Base.is_unix(:Windows) @test !Base.is_linux(:Windows) diff --git a/test/parse.jl b/test/parse.jl index 2a96a60876ab2..8b17393113e60 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # tests for parser and syntax lowering diff --git a/test/path.jl b/test/path.jl index f401c03ddf7b5..a2444e7810681 100644 --- a/test/path.jl +++ b/test/path.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license for S in (String, GenericString) dir = pwd() diff --git a/test/perf/README.md b/test/perf/README.md index d523394f6304f..7d2f2abfc355d 100644 --- a/test/perf/README.md +++ b/test/perf/README.md @@ -29,7 +29,7 @@ Tests generally go into one of the following suites: - `micro`: A set of micro-benchmarks commonly used to compare programming languages; these results are shown on - [http://julialang.org/](http://julialang.org/). + [https://julialang.org/](https://julialang.org/). - `blas`, `lapack`: Performance tests for linear algebra tasks from low-level operations such as matrix multiplies to higher-level operations like eigenvalue problems. diff --git a/test/perf/array/indexing.jl b/test/perf/array/indexing.jl index 5e5956c3b5ddb..36527b0036a8d 100644 --- a/test/perf/array/indexing.jl +++ b/test/perf/array/indexing.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Performance testing diff --git a/test/perf/array/perf.jl b/test/perf/array/perf.jl index 07b36606faf3a..001b69c078b62 100644 --- a/test/perf/array/perf.jl +++ b/test/perf/array/perf.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license include("../perfutil.jl") diff --git a/test/perf/blas/level1.jl b/test/perf/blas/level1.jl index 5d2531ac01bac..0d1f6837eecb6 100644 --- a/test/perf/blas/level1.jl +++ b/test/perf/blas/level1.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license function dottest(n, iter) a = rand(n) diff --git a/test/perf/blas/level2.jl b/test/perf/blas/level2.jl index dd80bad63220a..afa99a662122e 100644 --- a/test/perf/blas/level2.jl +++ b/test/perf/blas/level2.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license function gemvtest(n, iter) A = rand(n,n) diff --git a/test/perf/blas/level3.jl b/test/perf/blas/level3.jl index 642307918e8f1..a9c07a27841d3 100644 --- a/test/perf/blas/level3.jl +++ b/test/perf/blas/level3.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # gemm on various size matrices diff --git a/test/perf/blas/perf.jl b/test/perf/blas/perf.jl index b28a72602521d..96847f24c7f98 100644 --- a/test/perf/blas/perf.jl +++ b/test/perf/blas/perf.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license include("../perfutil.jl") diff --git a/test/perf/cat/perf.jl b/test/perf/cat/perf.jl index 33c2bc43d0491..e29db267fa138 100644 --- a/test/perf/cat/perf.jl +++ b/test/perf/cat/perf.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license include("../perfutil.jl") diff --git a/test/perf/kernel/actor_centrality.jl b/test/perf/kernel/actor_centrality.jl index a49f0eb306795..82185c9b823c9 100644 --- a/test/perf/kernel/actor_centrality.jl +++ b/test/perf/kernel/actor_centrality.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license mutable struct Node name::String diff --git a/test/perf/kernel/bench_eu.jl b/test/perf/kernel/bench_eu.jl index ddc7d61880b51..e0280db040a56 100644 --- a/test/perf/kernel/bench_eu.jl +++ b/test/perf/kernel/bench_eu.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Benchmark European option # https://groups.google.com/forum/?hl=en&fromgroups=#!topic/julia-dev/ImhGsqX_IHc diff --git a/test/perf/kernel/getdivgrad.jl b/test/perf/kernel/getdivgrad.jl index 091e40b7712f3..04ba5663d8ab6 100644 --- a/test/perf/kernel/getdivgrad.jl +++ b/test/perf/kernel/getdivgrad.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # https://github.com/JuliaLang/julia/issues/4707 diff --git a/test/perf/kernel/gk.jl b/test/perf/kernel/gk.jl index ec8126e061eec..f54ab5c737333 100644 --- a/test/perf/kernel/gk.jl +++ b/test/perf/kernel/gk.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Grigoriadis Khachiyan Matrix Games. # diff --git a/test/perf/kernel/go_benchmark.c b/test/perf/kernel/go_benchmark.c index a1b2a93dfb52d..ebf8b6596f597 100644 --- a/test/perf/kernel/go_benchmark.c +++ b/test/perf/kernel/go_benchmark.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license /* Benchmark implementing the board logic for the game of go and * exercising it by playing random games. Derived from diff --git a/test/perf/kernel/go_benchmark.jl b/test/perf/kernel/go_benchmark.jl index 53ebec7fe988e..03b0acb03bfbd 100644 --- a/test/perf/kernel/go_benchmark.jl +++ b/test/perf/kernel/go_benchmark.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Benchmark implementing the board logic for the game of go and # exercising it by playing random games. Derived from diff --git a/test/perf/kernel/indexing.jl b/test/perf/kernel/indexing.jl index 3a60f4033e0d4..1ffc422fa51f7 100644 --- a/test/perf/kernel/indexing.jl +++ b/test/perf/kernel/indexing.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license function add1!(x,y) x[y] .+= 1 diff --git a/test/perf/kernel/json.jl b/test/perf/kernel/json.jl index ef46eab03011f..2520ee2e87cc1 100644 --- a/test/perf/kernel/json.jl +++ b/test/perf/kernel/json.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license #JSON Parser #Adapted from http://www.mathworks.com/matlabcentral/fileexchange/23393 diff --git a/test/perf/kernel/laplace.jl b/test/perf/kernel/laplace.jl index 73e3c4ed66915..010adc2bd43e0 100644 --- a/test/perf/kernel/laplace.jl +++ b/test/perf/kernel/laplace.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license function laplace_iter_devec(u, dx2, dy2, Niter, N) uout = copy(u) diff --git a/test/perf/kernel/laplace/c_laplace.c b/test/perf/kernel/laplace/c_laplace.c index fb94668022b68..d0721f330d3ef 100644 --- a/test/perf/kernel/laplace/c_laplace.c +++ b/test/perf/kernel/laplace/c_laplace.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include #include diff --git a/test/perf/kernel/laplace/c_laplace_parallel_update.c b/test/perf/kernel/laplace/c_laplace_parallel_update.c index 4aa5baeb02dc6..b4f6434bcdc57 100644 --- a/test/perf/kernel/laplace/c_laplace_parallel_update.c +++ b/test/perf/kernel/laplace/c_laplace_parallel_update.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include #include "parameter.h" diff --git a/test/perf/kernel/laplace/c_laplace_parallel_update_pointer.c b/test/perf/kernel/laplace/c_laplace_parallel_update_pointer.c index 1a5f682fd26bb..2935f7f341969 100644 --- a/test/perf/kernel/laplace/c_laplace_parallel_update_pointer.c +++ b/test/perf/kernel/laplace/c_laplace_parallel_update_pointer.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include #include diff --git a/test/perf/kernel/laplace/cilk_laplace.c b/test/perf/kernel/laplace/cilk_laplace.c index af59525add16d..51204fd176cf3 100644 --- a/test/perf/kernel/laplace/cilk_laplace.c +++ b/test/perf/kernel/laplace/cilk_laplace.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include #include diff --git a/test/perf/kernel/perf.jl b/test/perf/kernel/perf.jl index 620a508365a7d..cf539d1f628ba 100644 --- a/test/perf/kernel/perf.jl +++ b/test/perf/kernel/perf.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license include("../perfutil.jl") diff --git a/test/perf/kernel/raytracer.jl b/test/perf/kernel/raytracer.jl index 5601143bf7a22..78c1a131f95a5 100644 --- a/test/perf/kernel/raytracer.jl +++ b/test/perf/kernel/raytracer.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # raytracer.jl # This is a translation from Java/C++ of the raytracer located at diff --git a/test/perf/kernel/simplex.jl b/test/perf/kernel/simplex.jl index 4d369024a55ce..9fd8c86bf81dd 100644 --- a/test/perf/kernel/simplex.jl +++ b/test/perf/kernel/simplex.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license const Basic = 1 const AtLower = 2 diff --git a/test/perf/kernel/stockcorr.jl b/test/perf/kernel/stockcorr.jl index 5df022c1c669a..991578de021c2 100644 --- a/test/perf/kernel/stockcorr.jl +++ b/test/perf/kernel/stockcorr.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## Test case from Issue #445 diff --git a/test/perf/kernel/ziggurat.jl b/test/perf/kernel/ziggurat.jl index abca7429cf359..1ed2529ba05d0 100644 --- a/test/perf/kernel/ziggurat.jl +++ b/test/perf/kernel/ziggurat.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Based on http://m.seehuhn.de/data/ziggurat/gauss.c diff --git a/test/perf/lapack/eig.jl b/test/perf/lapack/eig.jl index 1a9d9bfb7c79b..48036c481e19c 100644 --- a/test/perf/lapack/eig.jl +++ b/test/perf/lapack/eig.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Real function realeigtest(n, iter) diff --git a/test/perf/lapack/factorizations.jl b/test/perf/lapack/factorizations.jl index 91a0988e321a7..a0894c74aefb0 100644 --- a/test/perf/lapack/factorizations.jl +++ b/test/perf/lapack/factorizations.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license function svdtest(n, iter) A = rand(n,n) diff --git a/test/perf/lapack/perf.jl b/test/perf/lapack/perf.jl index 98fd5340597f3..c856be899bbfe 100644 --- a/test/perf/lapack/perf.jl +++ b/test/perf/lapack/perf.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license include("../perfutil.jl") diff --git a/test/perf/micro/java/setup.sh b/test/perf/micro/java/setup.sh index cce248094e900..0e8065660e317 100755 --- a/test/perf/micro/java/setup.sh +++ b/test/perf/micro/java/setup.sh @@ -1,5 +1,5 @@ #!/bin/sh -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license mvn compile exec:java # requires maven and java 7 diff --git a/test/perf/micro/perf.c b/test/perf/micro/perf.c index fa9621bbb1333..df572e9e366c8 100644 --- a/test/perf/micro/perf.c +++ b/test/perf/micro/perf.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license #include diff --git a/test/perf/micro/perf.jl b/test/perf/micro/perf.jl index 72d6c7b4c237a..5f10f1023b3cf 100644 --- a/test/perf/micro/perf.jl +++ b/test/perf/micro/perf.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test diff --git a/test/perf/micro/scala/build.sbt b/test/perf/micro/scala/build.sbt index c98322a85653e..794c50491c323 100644 --- a/test/perf/micro/scala/build.sbt +++ b/test/perf/micro/scala/build.sbt @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license libraryDependencies ++= Seq( "org.scalanlp" %% "breeze" % "0.10", diff --git a/test/perf/micro/scala/src/main/scala/perf.scala b/test/perf/micro/scala/src/main/scala/perf.scala index 73fd84fee4296..c6ed3797d8617 100644 --- a/test/perf/micro/scala/src/main/scala/perf.scala +++ b/test/perf/micro/scala/src/main/scala/perf.scala @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license import scala.util._ import java.io._ diff --git a/test/perf/perfcomp.jl b/test/perf/perfcomp.jl index 7575107d90948..d07de14286524 100644 --- a/test/perf/perfcomp.jl +++ b/test/perf/perfcomp.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # usage: perfcomp.jl [] # This will run the specified suite (default "all") and compare it to stored diff --git a/test/perf/perfgeneric.jl b/test/perf/perfgeneric.jl index a114a6d703723..4e7dba0fa8051 100644 --- a/test/perf/perfgeneric.jl +++ b/test/perf/perfgeneric.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license #Generic benchmark driver for (testfunc, testname, longtestname, problem_sizes) in testdata diff --git a/test/perf/perfutil.jl b/test/perf/perfutil.jl index 316c1528e9f94..98a4c49b4b833 100644 --- a/test/perf/perfutil.jl +++ b/test/perf/perfutil.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license const mintrials = 5 const mintime = 2000.0 diff --git a/test/perf/report.jl b/test/perf/report.jl index 34513c53d0a8a..ff8872290ab3f 100644 --- a/test/perf/report.jl +++ b/test/perf/report.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using HTTPClient.HTTPC diff --git a/test/perf/shootout/binary_trees.jl b/test/perf/shootout/binary_trees.jl index 9200748615648..042fd81568514 100644 --- a/test/perf/shootout/binary_trees.jl +++ b/test/perf/shootout/binary_trees.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # # The Computer Language Benchmarks Game diff --git a/test/perf/shootout/fannkuch.jl b/test/perf/shootout/fannkuch.jl index 9db19200bdad5..fcafc75dbb32a 100644 --- a/test/perf/shootout/fannkuch.jl +++ b/test/perf/shootout/fannkuch.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # # The Computer Language Benchmarks Game diff --git a/test/perf/shootout/fasta.jl b/test/perf/shootout/fasta.jl index fe8129d1d74c7..1dab880d9e28f 100644 --- a/test/perf/shootout/fasta.jl +++ b/test/perf/shootout/fasta.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license const line_width = 60 diff --git a/test/perf/shootout/k_nucleotide.jl b/test/perf/shootout/k_nucleotide.jl index b28555b1e1c20..73b298d38dda6 100644 --- a/test/perf/shootout/k_nucleotide.jl +++ b/test/perf/shootout/k_nucleotide.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # The Computer Language Benchmarks Game # http://shootout.alioth.debian.org/ diff --git a/test/perf/shootout/mandelbrot.jl b/test/perf/shootout/mandelbrot.jl index 37332cd680f4b..62e76de8a89e0 100644 --- a/test/perf/shootout/mandelbrot.jl +++ b/test/perf/shootout/mandelbrot.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # The Computer Language Benchmarks Game # http://shootout.alioth.debian.org/ diff --git a/test/perf/shootout/meteor_contest.jl b/test/perf/shootout/meteor_contest.jl index ab9a235a28f68..08ca2b9b2ae19 100644 --- a/test/perf/shootout/meteor_contest.jl +++ b/test/perf/shootout/meteor_contest.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # The Computer Language Benchmarks Game # http://shootout.alioth.debian.org/ diff --git a/test/perf/shootout/nbody.jl b/test/perf/shootout/nbody.jl index 156d666daf4be..9d32837ca51b6 100644 --- a/test/perf/shootout/nbody.jl +++ b/test/perf/shootout/nbody.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # # The Computer Language Benchmarks Game diff --git a/test/perf/shootout/nbody_vec.jl b/test/perf/shootout/nbody_vec.jl index 7f1fda5f0646e..657f67c33bbd4 100644 --- a/test/perf/shootout/nbody_vec.jl +++ b/test/perf/shootout/nbody_vec.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # # The Computer Language Benchmarks Game diff --git a/test/perf/shootout/perf.jl b/test/perf/shootout/perf.jl index 21966c6c7b38d..f53182c579b01 100644 --- a/test/perf/shootout/perf.jl +++ b/test/perf/shootout/perf.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license include("../perfutil.jl") diff --git a/test/perf/shootout/pidigits.jl b/test/perf/shootout/pidigits.jl index 76c7975df84c7..175445d4248c0 100644 --- a/test/perf/shootout/pidigits.jl +++ b/test/perf/shootout/pidigits.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license function pidigits(N::Int, printOut::Bool) """ diff --git a/test/perf/shootout/regex_dna.jl b/test/perf/shootout/regex_dna.jl index 348c14187ccd5..14e566bb1de55 100644 --- a/test/perf/shootout/regex_dna.jl +++ b/test/perf/shootout/regex_dna.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # The Computer Language Benchmarks Game # http://shootout.alioth.debian.org/ diff --git a/test/perf/shootout/revcomp.jl b/test/perf/shootout/revcomp.jl index b9fc342cb9728..84c54c7d4b95a 100644 --- a/test/perf/shootout/revcomp.jl +++ b/test/perf/shootout/revcomp.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # The Computer Language Benchmarks Game # http://shootout.alioth.debian.org/ diff --git a/test/perf/shootout/spectralnorm.jl b/test/perf/shootout/spectralnorm.jl index 6acb77c14f43a..52b05c63381dd 100644 --- a/test/perf/shootout/spectralnorm.jl +++ b/test/perf/shootout/spectralnorm.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # # The Computer Language Benchmarks Game diff --git a/test/perf/simd/axpy.jl b/test/perf/simd/axpy.jl index 991684d6dd591..69cd62c84a81e 100644 --- a/test/perf/simd/axpy.jl +++ b/test/perf/simd/axpy.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Compute y += a*x using @simd for vectors x and y function simd_axpy( a, x, y ) diff --git a/test/perf/simd/inner.jl b/test/perf/simd/inner.jl index 94b8a423491ce..d8113958560f2 100644 --- a/test/perf/simd/inner.jl +++ b/test/perf/simd/inner.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Inner produce of x and y function inner( x, y ) diff --git a/test/perf/simd/perf.jl b/test/perf/simd/perf.jl index 8d544d53a159f..ebcb1de773884 100644 --- a/test/perf/simd/perf.jl +++ b/test/perf/simd/perf.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license include("../perfutil.jl") diff --git a/test/perf/simd/seismic_fdtd.jl b/test/perf/simd/seismic_fdtd.jl index 966199cd9c160..2386115b16276 100644 --- a/test/perf/simd/seismic_fdtd.jl +++ b/test/perf/simd/seismic_fdtd.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Finite-difference time-domain seismic simulation in 2D using a staggered grid. # The intent is to test performance of @simd on the inner loop of a 2D loop nest. diff --git a/test/perf/simd/sum_reduce.jl b/test/perf/simd/sum_reduce.jl index b57502fccd1df..9ad02e7c9fb7a 100644 --- a/test/perf/simd/sum_reduce.jl +++ b/test/perf/simd/sum_reduce.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license function sum_reduce(x, istart, iend) s = zero(eltype(x)) diff --git a/test/perf/sort/perf.jl b/test/perf/sort/perf.jl index 81ab363141c8b..7ac3087ba7743 100644 --- a/test/perf/sort/perf.jl +++ b/test/perf/sort/perf.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license import Base.Sort: QuickSort, MergeSort, InsertionSort diff --git a/test/perf/sparse/fem.jl b/test/perf/sparse/fem.jl index 179a81514ca2a..77fb47e7c6782 100644 --- a/test/perf/sparse/fem.jl +++ b/test/perf/sparse/fem.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## FEM benchmark from https://github.com/JuliaLang/julia/issues/9668 diff --git a/test/perf/sparse/getindex.jl b/test/perf/sparse/getindex.jl index af3254e628d2a..03d6a6f36b267 100644 --- a/test/perf/sparse/getindex.jl +++ b/test/perf/sparse/getindex.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## getindex const rep = 20 diff --git a/test/perf/sparse/getindex_skinny.jl b/test/perf/sparse/getindex_skinny.jl index 2666836ba0bf0..94d48cdc55ce6 100644 --- a/test/perf/sparse/getindex_skinny.jl +++ b/test/perf/sparse/getindex_skinny.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Test getindex for skinny sparse matrix function sparse_getindex_skinny_perf() diff --git a/test/perf/sparse/perf.jl b/test/perf/sparse/perf.jl index 5de1774ad565a..6fd0bba1c370b 100644 --- a/test/perf/sparse/perf.jl +++ b/test/perf/sparse/perf.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## Sparse matrix performance include("../perfutil.jl") diff --git a/test/perf/spell/perf.jl b/test/perf/spell/perf.jl index e6ee7bb4bf373..c5a8dee8dc028 100644 --- a/test/perf/spell/perf.jl +++ b/test/perf/spell/perf.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Peter Norvig's Spelling Corrector # based off of the python implementation at http://norvig.com/spell-correct.html diff --git a/test/perf/threads/laplace3d/laplace3d.c b/test/perf/threads/laplace3d/laplace3d.c index 73dddf6a43430..99f83fcfff5b1 100644 --- a/test/perf/threads/laplace3d/laplace3d.c +++ b/test/perf/threads/laplace3d/laplace3d.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license // GCC command line: gcc -fopenmp -mavx2 laplace3d.c -o laplace3d diff --git a/test/perf/threads/laplace3d/laplace3d.jl b/test/perf/threads/laplace3d/laplace3d.jl index c27956b25205d..52287cb36c8e7 100644 --- a/test/perf/threads/laplace3d/laplace3d.jl +++ b/test/perf/threads/laplace3d/laplace3d.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## 3D Laplace equation diff --git a/test/perf/threads/lbm3d/circshift.jl b/test/perf/threads/lbm3d/circshift.jl index ccd4ec7686b44..144ba82754c46 100644 --- a/test/perf/threads/lbm3d/circshift.jl +++ b/test/perf/threads/lbm3d/circshift.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # An in-place version of circshift. Needs generalization -- currently # works only on a 3D hyperplane of a 4D array and supports only unit diff --git a/test/perf/threads/lbm3d/lbm3d.jl b/test/perf/threads/lbm3d/lbm3d.jl index 7639cdd2719de..14df2cea3c46f 100644 --- a/test/perf/threads/lbm3d/lbm3d.jl +++ b/test/perf/threads/lbm3d/lbm3d.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # 3D Lattice Boltzmann (BGK) model of a fluid. # (http://exolete.com/lbm/) diff --git a/test/perf/threads/stockcorr/pstockcorr.jl b/test/perf/threads/stockcorr/pstockcorr.jl index 076feb7cc58b2..0b00c158f82e8 100644 --- a/test/perf/threads/stockcorr/pstockcorr.jl +++ b/test/perf/threads/stockcorr/pstockcorr.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## Test case from Issue #445 ## diff --git a/test/pkg.jl b/test/pkg.jl index afbf89adef932..9e81abeedd5e9 100644 --- a/test/pkg.jl +++ b/test/pkg.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license import Base.Pkg.PkgError diff --git a/test/pollfd.jl b/test/pollfd.jl index 7051c2fc1739d..5f470f0a276f4 100644 --- a/test/pollfd.jl +++ b/test/pollfd.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # This script does the following # Sets up n unix pipes diff --git a/test/printf.jl b/test/printf.jl index 312b8698c1ba4..4a50982aa368b 100644 --- a/test/printf.jl +++ b/test/printf.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # printf # int diff --git a/test/profile.jl b/test/profile.jl index f9a731c1c5427..b4d53a6cbd8cd 100644 --- a/test/profile.jl +++ b/test/profile.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license function busywait(t, n_tries) iter = 0 diff --git a/test/random.jl b/test/random.jl index 330a569e8800c..1403af94cfa19 100644 --- a/test/random.jl +++ b/test/random.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Issue #6573 srand(0); rand(); x = rand(384) diff --git a/test/ranges.jl b/test/ranges.jl index d990f0fad3410..895ee4d873299 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # ranges @test size(10:1:0) == (0,) diff --git a/test/read.jl b/test/read.jl index f88863be4d7a8..6f794a84f59bd 100644 --- a/test/read.jl +++ b/test/read.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license mktempdir() do dir diff --git a/test/reduce.jl b/test/reduce.jl index 9bd2130a6c5bb..d27ef930c929f 100644 --- a/test/reduce.jl +++ b/test/reduce.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # fold(l|r) & mapfold(l|r) @test foldl(+, Int64[]) === Int64(0) # In reference to issues #7465/#20144 (PR #20160) diff --git a/test/reducedim.jl b/test/reducedim.jl index 77a9dc537b5a5..4da34397991ef 100644 --- a/test/reducedim.jl +++ b/test/reducedim.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # main tests diff --git a/test/reflection.jl b/test/reflection.jl index 40c06c87306db..57f2a93534503 100644 --- a/test/reflection.jl +++ b/test/reflection.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # code_native / code_llvm (issue #8239) # It's hard to really test these, but just running them should be diff --git a/test/regex.jl b/test/regex.jl index 636c25da954a7..39fa2ad4871cb 100644 --- a/test/regex.jl +++ b/test/regex.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license function collect_eachmatch(re, str, overlap=false) [m.match for m in collect(eachmatch(re, str, overlap))] diff --git a/test/repl.jl b/test/repl.jl index 15733ad2feefd..ff42c4c69fc3d 100644 --- a/test/repl.jl +++ b/test/repl.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license const curmod = current_module() const curmod_name = fullname(curmod) diff --git a/test/replcompletions.jl b/test/replcompletions.jl index 1fdebef6872f5..6e0d9a38ebda3 100644 --- a/test/replcompletions.jl +++ b/test/replcompletions.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.REPLCompletions diff --git a/test/replutil.jl b/test/replutil.jl index 468aa48aa3fdd..1a403ed17d6cf 100644 --- a/test/replutil.jl +++ b/test/replutil.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license const curmod = current_module() const curmod_name = fullname(curmod) diff --git a/test/resolve.jl b/test/resolve.jl index 059e23a90cecb..c36220ccb9239 100644 --- a/test/resolve.jl +++ b/test/resolve.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Pkg.Types using Base.Pkg.Query diff --git a/test/rounding.jl b/test/rounding.jl index 63dc10e419a53..32a19d10b1a1b 100644 --- a/test/rounding.jl +++ b/test/rounding.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Small sanity tests to ensure changing the rounding of float functions work using Base.Test diff --git a/test/runtests.jl b/test/runtests.jl index 72585cf098959..e481d4f3e7ceb 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test include("choosetests.jl") diff --git a/test/serialize.jl b/test/serialize.jl index 63aac82a3f55e..dbd1e92ca8440 100644 --- a/test/serialize.jl +++ b/test/serialize.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test diff --git a/test/sets.jl b/test/sets.jl index c5abf4df21308..e4050fe731099 100644 --- a/test/sets.jl +++ b/test/sets.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Set tests diff --git a/test/show.jl b/test/show.jl index e70904452b64b..d9960abdd184b 100644 --- a/test/show.jl +++ b/test/show.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license const curmod = current_module() const curmod_name = fullname(curmod) diff --git a/test/simdloop.jl b/test/simdloop.jl index 4ea2f82ba8355..57be1d59bd79a 100644 --- a/test/simdloop.jl +++ b/test/simdloop.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license function simd_loop_example_from_manual(x, y, z) s = zero(eltype(z)) diff --git a/test/socket.jl b/test/socket.jl index 70bc4a03c505e..aeb76aeff2166 100644 --- a/test/socket.jl +++ b/test/socket.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license @test ip"127.0.0.1" == IPv4(127,0,0,1) @test ip"192.0" == IPv4(192,0,0,0) diff --git a/test/sorting.jl b/test/sorting.jl index 635eea81d127a..28d7020d25458 100644 --- a/test/sorting.jl +++ b/test/sorting.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Order: Forward diff --git a/test/sparse/cholmod.jl b/test/sparse/cholmod.jl index 973620132359e..3f782fa63c18f 100644 --- a/test/sparse/cholmod.jl +++ b/test/sparse/cholmod.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license srand(123) diff --git a/test/sparse/higherorderfns.jl b/test/sparse/higherorderfns.jl index 7e77ed2263bfa..4b9e0a711af7a 100644 --- a/test/sparse/higherorderfns.jl +++ b/test/sparse/higherorderfns.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # These tests cover the higher order functions specialized for sparse arrays defined in # base/sparse/higherorderfns.jl, particularly map[!]/broadcast[!] for SparseVectors and diff --git a/test/sparse/sparse.jl b/test/sparse/sparse.jl index 42b62dab12313..f0ae30b96c99c 100644 --- a/test/sparse/sparse.jl +++ b/test/sparse/sparse.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license @testset "issparse" begin @test issparse(sparse(ones(5,5))) diff --git a/test/sparse/sparsevector.jl b/test/sparse/sparsevector.jl index a2c429dad196f..ca2f1217ceb29 100644 --- a/test/sparse/sparsevector.jl +++ b/test/sparse/sparsevector.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ### Data diff --git a/test/sparse/spqr.jl b/test/sparse/spqr.jl index 2b137d028c28c..eaa659dadd65c 100644 --- a/test/sparse/spqr.jl +++ b/test/sparse/spqr.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.SparseArrays.SPQR using Base.SparseArrays.CHOLMOD diff --git a/test/sparse/umfpack.jl b/test/sparse/umfpack.jl index b1bfd48d64be7..adbce3839a962 100644 --- a/test/sparse/umfpack.jl +++ b/test/sparse/umfpack.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license se33 = speye(3) do33 = ones(3) diff --git a/test/spawn.jl b/test/spawn.jl index 8b7582b191ad0..f6c514c21bc1a 100644 --- a/test/spawn.jl +++ b/test/spawn.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ################################### # Cross Platform tests for spawn. # diff --git a/test/stacktraces.jl b/test/stacktraces.jl index f388e382aed07..ac1814354f12c 100644 --- a/test/stacktraces.jl +++ b/test/stacktraces.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Tests for /base/stacktraces.jl diff --git a/test/staged.jl b/test/staged.jl index 28bb661fe361e..debc3ae58d165 100644 --- a/test/staged.jl +++ b/test/staged.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license @generated function staged_t1(a,b) if a == Int diff --git a/test/statistics.jl b/test/statistics.jl index d6fd138ae7951..9e7dbf09f6374 100644 --- a/test/statistics.jl +++ b/test/statistics.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test diff --git a/test/strings/basic.jl b/test/strings/basic.jl index 7ecb5bebbf13e..b45b6757d80af 100644 --- a/test/strings/basic.jl +++ b/test/strings/basic.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # constructors @test String([0x61,0x62,0x63,0x21]) == "abc!" diff --git a/test/strings/io.jl b/test/strings/io.jl index dedb7463d48b0..1634e7f7cfa8a 100644 --- a/test/strings/io.jl +++ b/test/strings/io.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # string escaping & unescaping cx = Any[ diff --git a/test/strings/search.jl b/test/strings/search.jl index 8fcfe9c62d5d3..98d4736237509 100644 --- a/test/strings/search.jl +++ b/test/strings/search.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # some test strings astr = "Hello, world.\n" diff --git a/test/strings/types.jl b/test/strings/types.jl index 36289bc000a84..c4ff5227a02e2 100644 --- a/test/strings/types.jl +++ b/test/strings/types.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license ## SubString, RevString and Cstring tests ## diff --git a/test/strings/util.jl b/test/strings/util.jl index 21072a524bf4c..92298b767b07b 100644 --- a/test/strings/util.jl +++ b/test/strings/util.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # padding (lpad and rpad) @test lpad("foo", 3) == "foo" diff --git a/test/subarray.jl b/test/subarray.jl index 4c1ada86728df..fb2d8d8300017 100644 --- a/test/subarray.jl +++ b/test/subarray.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test diff --git a/test/subtype.jl b/test/subtype.jl index 1531837946e81..ec133c33d026b 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Bottom using Base.Test diff --git a/test/sysinfo.jl b/test/sysinfo.jl index 261935ac715f1..a34adf572abe4 100644 --- a/test/sysinfo.jl +++ b/test/sysinfo.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # We can't guarantee that these are correct, but we can at least check # that they run diff --git a/test/test.jl b/test/test.jl index 36ca3498929fb..3fbc5f9a96ed3 100644 --- a/test/test.jl +++ b/test/test.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # Test @test @test true diff --git a/test/test_exec.jl b/test/test_exec.jl index 0e53cf236c61d..529f9f63ea493 100644 --- a/test/test_exec.jl +++ b/test/test_exec.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test # Check that the fallback test set throws immediately diff --git a/test/test_sourcepath.jl b/test/test_sourcepath.jl index 1e4f55b5b287c..60985b823a9ce 100644 --- a/test/test_sourcepath.jl +++ b/test/test_sourcepath.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # source path in tasks path = Base.source_path()::String # this variable is leaked to the source script diff --git a/test/testdefs.jl b/test/testdefs.jl index ba48564fb9b3d..e9d7a1bdfadd9 100644 --- a/test/testdefs.jl +++ b/test/testdefs.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license function runtests(name, isolate=true) old_print_setting = Base.Test.TESTSET_PRINT_ENABLE[] diff --git a/test/threads.jl b/test/threads.jl index d0626fdbc3d79..6ce64798ae600 100644 --- a/test/threads.jl +++ b/test/threads.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test using Base.Threads diff --git a/test/topology.jl b/test/topology.jl index 66273149e25a0..00a53daa9ea51 100644 --- a/test/topology.jl +++ b/test/topology.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license include("testdefs.jl") addprocs(4; topology="master_slave") diff --git a/test/triplequote.jl b/test/triplequote.jl index 074afec18a22c..35bc1fa593b7a 100644 --- a/test/triplequote.jl +++ b/test/triplequote.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # triple-quote delimited strings @test """abc""" == "abc" diff --git a/test/tuple.jl b/test/tuple.jl index 7756797e9af4d..ca15da42a44c0 100644 --- a/test/tuple.jl +++ b/test/tuple.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license @test convert(Tuple, (1,2)) == (1,2) @testset "indexing" begin diff --git a/test/unicode/UnicodeError.jl b/test/unicode/UnicodeError.jl index 14a4a3db362ca..a5665dff49bbe 100644 --- a/test/unicode/UnicodeError.jl +++ b/test/unicode/UnicodeError.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license @testset "invalid utf8" begin let io = IOBuffer() diff --git a/test/unicode/utf8.jl b/test/unicode/utf8.jl index 1a95da78bd577..093c899e0f3ee 100644 --- a/test/unicode/utf8.jl +++ b/test/unicode/utf8.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license @testset "cesu8 input" begin let ch = 0x10000 diff --git a/test/unicode/utf8proc.jl b/test/unicode/utf8proc.jl index 8e2834b954993..403c2775f9897 100644 --- a/test/unicode/utf8proc.jl +++ b/test/unicode/utf8proc.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license @testset "string normalization" begin # normalize_string (Unicode normalization etc.): diff --git a/test/util/segfault.jl b/test/util/segfault.jl index ebc1a5d8edb90..fef390870776f 100644 --- a/test/util/segfault.jl +++ b/test/util/segfault.jl @@ -1,3 +1,3 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license unsafe_load(convert(Ptr{UInt8},C_NULL)) diff --git a/test/util/throw_error_exception.jl b/test/util/throw_error_exception.jl index 035afea8388ff..d0acea8f647f0 100644 --- a/test/util/throw_error_exception.jl +++ b/test/util/throw_error_exception.jl @@ -1,3 +1,3 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license error("This purposefully dies") diff --git a/test/vecelement.jl b/test/vecelement.jl index 6476beade9ad7..95209b143c28b 100644 --- a/test/vecelement.jl +++ b/test/vecelement.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license make_value{T<:Integer}(::Type{T}, i::Integer) = 3*i%T make_value{T<:AbstractFloat}(::Type{T},i::Integer) = T(3*i) diff --git a/test/version.jl b/test/version.jl index 7f7f691ba775e..5620d66dadb81 100644 --- a/test/version.jl +++ b/test/version.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # parsing tests @test v"2" == VersionNumber(2) diff --git a/test/workspace.jl b/test/workspace.jl index 01d5fb843e241..bf6dd461b35fa 100644 --- a/test/workspace.jl +++ b/test/workspace.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license script = """ # Issue #11948 diff --git a/test/worlds.jl b/test/worlds.jl index 28a89b2e5c9dc..13bb28597c090 100644 --- a/test/worlds.jl +++ b/test/worlds.jl @@ -1,4 +1,4 @@ -# This file is a part of Julia. License is MIT: http://julialang.org/license +# This file is a part of Julia. License is MIT: https://julialang.org/license # tests for accurate updating of method tables diff --git a/ui/repl.c b/ui/repl.c index 5f8f066cccb46..dfa4427a9452a 100644 --- a/ui/repl.c +++ b/ui/repl.c @@ -1,4 +1,4 @@ -// This file is a part of Julia. License is MIT: http://julialang.org/license +// This file is a part of Julia. License is MIT: https://julialang.org/license /* repl.c From 1a8481b11500360bf655404d910e3c85807e1dc6 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Fri, 21 Apr 2017 08:40:39 -0400 Subject: [PATCH 0485/1534] Fix unusually capitalized Julialang.org link and remove separate link to docs search which doesn't exist with new doc system --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1227328ef56a8..c0a9a7f2d7793 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,7 +4,7 @@ Hi! If you are new to the Julia community: welcome, and thanks for trying Julia. ## Learning Julia -[The learning page](https://julialang.org/learning/) has a great list of resources for new and experienced users alike. [This tutorial video](https://www.youtube.com/watch?v=vWkgEddb4-A) is one recommended starting point, as is the "[Invitation to Julia](https://www.youtube.com/watch?v=gQ1y5NUD_RI)" workshop video from JuliaCon 2015 ([slide materials here](https://github.com/dpsanders/invitation_to_julia)). The [Julia documentation](http://docs.Julialang.org/en/latest/) covers the language and core library features, and is [searchable](http://docs.Julialang.org/en/latest/search/). (note: Javascript required). +[The learning page](https://julialang.org/learning/) has a great list of resources for new and experienced users alike. [This tutorial video](https://www.youtube.com/watch?v=vWkgEddb4-A) is one recommended starting point, as is the "[Invitation to Julia](https://www.youtube.com/watch?v=gQ1y5NUD_RI)" workshop video from JuliaCon 2015 ([slide materials here](https://github.com/dpsanders/invitation_to_julia)). The [Julia documentation](https://docs.julialang.org/en/latest/) covers the language and core library features, and is searchable. ## Before filing an issue From ca77f516459bd01b7d8a4a674498d9017255d5bb Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Thu, 20 Apr 2017 11:30:28 -0400 Subject: [PATCH 0486/1534] Band aid to make threaded loop a little easier to work with * Print a warning if an error occurs in the threaded loop (Helps #17532) * Make recursive threaded loops "work" (Fix #18335). The proper fix will be tracked by #21017 --- base/threadingconstructs.jl | 29 +++++++++++++++++++++++------ src/threading.c | 15 ++++++++++++++- test/threads.jl | 17 +++++++++++++++++ 3 files changed, 54 insertions(+), 7 deletions(-) diff --git a/base/threadingconstructs.jl b/base/threadingconstructs.jl index 895b667c14aa9..7d013ed2e30bd 100644 --- a/base/threadingconstructs.jl +++ b/base/threadingconstructs.jl @@ -18,17 +18,25 @@ on `threadid()`. """ nthreads() = Int(unsafe_load(cglobal(:jl_n_threads, Cint))) +# Only read/written by the main thread +const in_threaded_loop = Ref(false) + function _threadsfor(iter,lbody) - fun = gensym("_threadsfor") lidx = iter.args[1] # index range = iter.args[2] quote range = $(esc(range)) - function $fun() - tid = threadid() + function threadsfor_fun(onethread=false) r = range # Load into local variable + lenr = length(r) # divide loop iterations among threads - len, rem = divrem(length(r), nthreads()) + if onethread + tid = 1 + len, rem = lenr, 0 + else + tid = threadid() + len, rem = divrem(lenr, nthreads()) + end # not enough iterations for all the threads? if len == 0 if tid > rem @@ -55,7 +63,17 @@ function _threadsfor(iter,lbody) $(esc(lbody)) end end - ccall(:jl_threading_run, Ref{Void}, (Any,), $fun) + # Hack to make nested threaded loops kinda work + if threadid() != 1 || in_threaded_loop[] + # We are in a nested threaded loop + threadsfor_fun(true) + else + in_threaded_loop[] = true + # the ccall is not expected to throw + ccall(:jl_threading_run, Ref{Void}, (Any,), threadsfor_fun) + in_threaded_loop[] = false + end + nothing end end """ @@ -81,4 +99,3 @@ macro threads(args...) throw(ArgumentError("unrecognized argument to @threads")) end end - diff --git a/src/threading.c b/src/threading.c index 81a47b55977e6..f2fdaf96eb3e6 100644 --- a/src/threading.c +++ b/src/threading.c @@ -316,7 +316,20 @@ static jl_value_t *ti_run_fun(const jl_generic_fptr_t *fptr, jl_method_instance_ jl_call_fptr_internal(fptr, mfunc, args, nargs); } JL_CATCH { - return ptls->exception_in_transit; + // Lock this output since we know it'll likely happen on multiple threads + static jl_mutex_t lock; + JL_LOCK_NOGC(&lock); + jl_jmp_buf *old_buf = ptls->safe_restore; + jl_jmp_buf buf; + if (!jl_setjmp(buf, 0)) { + // Set up the safe_restore context so that the printing uses the thread safe version + ptls->safe_restore = &buf; + jl_printf(JL_STDERR, "\nError thrown in threaded loop on thread %d: ", + (int)ptls->tid); + jl_static_show(JL_STDERR, ptls->exception_in_transit); + } + ptls->safe_restore = old_buf; + JL_UNLOCK_NOGC(&lock); } return jl_nothing; } diff --git a/test/threads.jl b/test/threads.jl index 9c587ede557e3..ff38963c09b04 100644 --- a/test/threads.jl +++ b/test/threads.jl @@ -415,3 +415,20 @@ function test_load_and_lookup_18020(n) end end test_load_and_lookup_18020(10000) + +# Nested threaded loops +# This may not be efficient/fully supported but should work without crashing..... +function test_nested_loops() + a = zeros(Int, 100, 100) + @threads for i in 1:100 + @threads for j in 1:100 + a[j, i] = i + j + end + end + for i in 1:100 + for j in 1:100 + @test a[j, i] == i + j + end + end +end +test_nested_loops() From 6955932fe782fea117cb30dc1ad5aa15782ac949 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 20 Apr 2017 22:15:40 -0400 Subject: [PATCH 0487/1534] fix #21440, parsing `+(x::T,y::T) where {T}` --- src/julia-parser.scm | 19 +++++++++++-------- test/parse.jl | 4 ++++ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/julia-parser.scm b/src/julia-parser.scm index c6d50a7dfc751..4bd9723fce02f 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -25,9 +25,11 @@ (define prec-bitshift (add-dots '(<< >> >>>))) (define prec-times (add-dots '(* / ÷ % & ⋅ ∘ × |\\| ∩ ∧ ⊗ ⊘ ⊙ ⊚ ⊛ ⊠ ⊡ ⊓ ∗ ∙ ∤ ⅋ ≀ ⊼ ⋄ ⋆ ⋇ ⋉ ⋊ ⋋ ⋌ ⋏ ⋒ ⟑ ⦸ ⦼ ⦾ ⦿ ⧶ ⧷ ⨇ ⨰ ⨱ ⨲ ⨳ ⨴ ⨵ ⨶ ⨷ ⨸ ⨻ ⨼ ⨽ ⩀ ⩃ ⩄ ⩋ ⩍ ⩎ ⩑ ⩓ ⩕ ⩘ ⩚ ⩜ ⩞ ⩟ ⩠ ⫛ ⊍ ▷ ⨝ ⟕ ⟖ ⟗))) (define prec-rational (add-dots '(//))) +;; `where` +;; unary (define prec-power (add-dots '(^ ↑ ↓ ⇵ ⟰ ⟱ ⤈ ⤉ ⤊ ⤋ ⤒ ⤓ ⥉ ⥌ ⥍ ⥏ ⥑ ⥔ ⥕ ⥘ ⥙ ⥜ ⥝ ⥠ ⥡ ⥣ ⥥ ⥮ ⥯ ↑ ↓))) (define prec-decl '(|::|)) -;; `where` +;; `where` occurring after `::` (define prec-dot '(|.|)) (define prec-names '(prec-assignment @@ -593,8 +595,9 @@ (peek-token s)))) ex)))) -(define (parse-where s) - (let ((ex (parse-call s))) +(define (parse-where s down) + ;; `where` needs to be below unary for `+(x::T,y::T) where {T} = ...` to work + (let ((ex (down s))) (if (and where-enabled (eq? (peek-token s) 'where)) (parse-where-chain s ex) @@ -819,7 +822,7 @@ (define (parse-term s) (parse-with-chains s parse-rational is-prec-times? '(*))) -(define (parse-rational s) (parse-LtoR s parse-unary is-prec-rational?)) +(define (parse-rational s) (parse-LtoR s (lambda (s) (parse-where s parse-unary)) is-prec-rational?)) (define (parse-pipes s) (parse-LtoR s parse-range is-prec-pipe?)) @@ -954,11 +957,11 @@ (parse-factor-h s parse-decl is-prec-power?)) (define (parse-decl s) - (let loop ((ex (parse-where s))) + (let loop ((ex (parse-call s))) (let ((t (peek-token s))) (case t ((|::|) (take-token s) - (loop (list t ex (parse-where s)))) + (loop (list t ex (parse-where s parse-call)))) ((->) (take-token s) ;; -> is unusual: it binds tightly on the left and ;; loosely on the right. @@ -973,7 +976,7 @@ (begin (take-token s) (cond ((let ((next (peek-token s))) (or (closing-token? next) (newline? next))) op) - ((memq op '(& |::|)) (list op (parse-where s))) + ((memq op '(& |::|)) (list op (parse-where s parse-call))) (else (list op (parse-unary-prefix s))))) (parse-atom s)))) @@ -1312,7 +1315,7 @@ (list 'bitstype nb spec))) ((typealias) (let ((lhs (with-space-sensitive (parse-call s))) - (rhs (parse-where s))) + (rhs (parse-where s parse-call))) (syntax-deprecation s (string "typealias " (deparse lhs) " " (deparse rhs)) (string (if (symbol? lhs) "const " "") (deparse lhs) " = " (deparse rhs))) diff --git a/test/parse.jl b/test/parse.jl index 2a96a60876ab2..769bb5195c97c 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -1103,3 +1103,7 @@ end Expr(:toplevel, Expr(:using, Symbol("."), :B), Expr(:using, Symbol("."), :C)) + +# issue #21440 +@test parse("+(x::T,y::T) where {T} = 0") == parse("(+)(x::T,y::T) where {T} = 0") +@test parse("a::b::c") == Expr(:(::), Expr(:(::), :a, :b), :c) From e2c93f0c4e9555d632e9bdb8b52f5ef0debe11c1 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Fri, 21 Apr 2017 12:51:11 -0400 Subject: [PATCH 0488/1534] Put worker threads to sleep immediately on startup --- src/threadgroup.c | 5 +++-- src/threadgroup.h | 2 +- src/threading.c | 9 ++++++--- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/threadgroup.c b/src/threadgroup.c index 57e995065a321..038e92d925bda 100644 --- a/src/threadgroup.c +++ b/src/threadgroup.c @@ -116,7 +116,7 @@ int ti_threadgroup_size(ti_threadgroup_t *tg, int16_t *tgsize) return 0; } -int ti_threadgroup_fork(ti_threadgroup_t *tg, int16_t ext_tid, void **bcast_val) +int ti_threadgroup_fork(ti_threadgroup_t *tg, int16_t ext_tid, void **bcast_val, int init) { uint8_t *group_sense = &tg->group_sense; int16_t tid = tg->tid_map[ext_tid]; @@ -147,13 +147,14 @@ int ti_threadgroup_fork(ti_threadgroup_t *tg, int16_t ext_tid, void **bcast_val) } spin_ns = uv_hrtime() - spin_start; // In case uv_hrtime is not monotonic, we'll sleep earlier - if (spin_ns >= tg->sleep_threshold) { + if (init || spin_ns >= tg->sleep_threshold) { uv_mutex_lock(&tg->alarm_lock); if (jl_atomic_load_acquire(group_sense) != thread_sense) { uv_cond_wait(&tg->alarm, &tg->alarm_lock); } uv_mutex_unlock(&tg->alarm_lock); spin_start = 0; + init = 0; continue; } } diff --git a/src/threadgroup.h b/src/threadgroup.h index 72e76d2dcfc8a..9ab7618e0e007 100644 --- a/src/threadgroup.h +++ b/src/threadgroup.h @@ -37,7 +37,7 @@ int ti_threadgroup_member(ti_threadgroup_t *tg, int16_t ext_tid, int16_t *tgtid); int ti_threadgroup_size(ti_threadgroup_t *tg, int16_t *tgsize); int ti_threadgroup_fork(ti_threadgroup_t *tg, int16_t ext_tid, - void **bcast_val); + void **bcast_val, int init); int ti_threadgroup_join(ti_threadgroup_t *tg, int16_t ext_tid); int ti_threadgroup_destroy(ti_threadgroup_t *tg); diff --git a/src/threading.c b/src/threading.c index 81a47b55977e6..56236c75a7714 100644 --- a/src/threading.c +++ b/src/threading.c @@ -378,13 +378,16 @@ void ti_threadfun(void *arg) // free the thread argument here free(ta); + int init = 1; + // work loop for (; ;) { #if PROFILE_JL_THREADING uint64_t tstart = uv_hrtime(); #endif - ti_threadgroup_fork(tg, ptls->tid, (void **)&work); + ti_threadgroup_fork(tg, ptls->tid, (void **)&work, init); + init = 0; #if PROFILE_JL_THREADING uint64_t tfork = uv_hrtime(); @@ -632,7 +635,7 @@ void jl_shutdown_threading(void) ti_threadwork_t *work = &threadwork; work->command = TI_THREADWORK_DONE; - ti_threadgroup_fork(tgworld, ptls->tid, (void **)&work); + ti_threadgroup_fork(tgworld, ptls->tid, (void **)&work, 0); sleep(1); @@ -691,7 +694,7 @@ JL_DLLEXPORT jl_value_t *jl_threading_run(jl_value_t *_args) // fork the world thread group ti_threadwork_t *tw = &threadwork; - ti_threadgroup_fork(tgworld, ptls->tid, (void **)&tw); + ti_threadgroup_fork(tgworld, ptls->tid, (void **)&tw, 0); #if PROFILE_JL_THREADING uint64_t tfork = uv_hrtime(); From 5482f911c3d2f8c0dfd7102932cfece31fc4fd24 Mon Sep 17 00:00:00 2001 From: Mus M Date: Fri, 21 Apr 2017 12:55:59 -0400 Subject: [PATCH 0489/1534] Use new where syntax in misc files (#21428) --- base/abstractarray.jl | 106 +++++++++++++++++----------------- base/abstractarraymath.jl | 4 +- base/array.jl | 94 +++++++++++++++--------------- base/arraymath.jl | 2 +- base/atomics.jl | 8 +-- base/base.jl | 2 +- base/bitarray.jl | 8 +-- base/bool.jl | 8 +-- base/boot.jl | 28 ++++----- base/broadcast.jl | 10 ++-- base/c.jl | 4 +- base/channels.jl | 2 +- base/complex.jl | 14 ++--- base/datafmt.jl | 10 ++-- base/dates/arithmetic.jl | 12 ++-- base/dates/periods.jl | 6 +- base/dates/types.jl | 6 +- base/deprecated.jl | 10 ++-- base/dft.jl | 18 +++--- base/dict.jl | 50 ++++++++-------- base/docs/utils.jl | 4 +- base/essentials.jl | 10 ++-- base/fft/FFTW.jl | 20 +++---- base/fft/dct.jl | 8 +-- base/generator.jl | 4 +- base/int.jl | 64 ++++++++++---------- base/intfuncs.jl | 24 ++++---- base/iobuffer.jl | 2 +- base/irrationals.jl | 16 ++--- base/iterators.jl | 58 +++++++++---------- base/libgit2/config.jl | 2 +- base/linalg/arnoldi.jl | 2 +- base/linalg/bidiag.jl | 30 +++++----- base/linalg/bunchkaufman.jl | 8 +-- base/linalg/cholesky.jl | 16 ++--- base/linalg/diagonal.jl | 14 ++--- base/linalg/factorization.jl | 4 +- base/linalg/givens.jl | 18 +++--- base/linalg/hessenberg.jl | 18 +++--- base/linalg/ldlt.jl | 8 +-- base/linalg/lq.jl | 44 +++++++------- base/linalg/lu.jl | 20 +++---- base/linalg/matmul.jl | 92 ++++++++++++++--------------- base/linalg/qr.jl | 58 +++++++++---------- base/linalg/rowvector.jl | 4 +- base/linalg/special.jl | 8 +-- base/linalg/svd.jl | 2 +- base/linalg/symmetric.jl | 18 +++--- base/linalg/triangular.jl | 20 +++---- base/linalg/tridiag.jl | 28 ++++----- base/linalg/uniformscaling.jl | 28 ++++----- base/markdown/render/html.jl | 6 +- base/multidimensional.jl | 54 ++++++++--------- base/multimedia.jl | 2 +- base/multinverses.jl | 8 +-- base/nullable.jl | 8 +-- base/number.jl | 10 ++-- base/pair.jl | 8 +-- base/pointer.jl | 2 +- base/profile.jl | 2 +- base/promotion.jl | 64 ++++++++++---------- base/range.jl | 88 ++++++++++++++-------------- base/rational.jl | 14 ++--- base/reduce.jl | 24 ++++---- base/reducedim.jl | 4 +- base/refpointer.jl | 18 +++--- base/reshapedarray.jl | 16 ++--- base/rounding.jl | 14 ++--- base/set.jl | 2 +- base/sharedarray.jl | 26 ++++----- base/sparse/cholmod.jl | 36 ++++++------ base/sparse/higherorderfns.jl | 88 ++++++++++++++-------------- base/sparse/linalg.jl | 6 +- base/sparse/sparsematrix.jl | 50 ++++++++-------- base/sparse/sparsevector.jl | 94 +++++++++++++++--------------- base/statistics.jl | 20 +++---- base/strings/basic.jl | 2 +- base/strings/types.jl | 4 +- base/strings/utf8proc.jl | 6 +- base/subarray.jl | 6 +- base/test.jl | 15 ++--- base/twiceprecision.jl | 18 +++--- base/util.jl | 6 +- base/weakkeydict.jl | 28 ++++----- 84 files changed, 900 insertions(+), 903 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 5a839d9826185..80ce357c2cc17 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -35,7 +35,7 @@ julia> indices(A,2) Base.OneTo(6) ``` """ -function indices{T,N}(A::AbstractArray{T,N}, d) +function indices(A::AbstractArray{T,N}, d) where {T,N} @_inline_meta d <= N ? indices(A)[d] : OneTo(1) end @@ -105,9 +105,9 @@ julia> ndims(A) 3 ``` """ -ndims{T,N}(::AbstractArray{T,N}) = N -ndims{T,N}(::Type{AbstractArray{T,N}}) = N -ndims{T<:AbstractArray}(::Type{T}) = ndims(supertype(T)) +ndims(::AbstractArray{T,N}) where {T,N} = N +ndims(::Type{AbstractArray{T,N}}) where {T,N} = N +ndims(::Type{T}) where {T<:AbstractArray} = ndims(supertype(T)) """ length(A::AbstractArray) -> Integer @@ -509,14 +509,14 @@ julia> similar(falses(10), Float64, 2, 4) ``` """ -similar{T}(a::AbstractArray{T}) = similar(a, T) -similar{T}(a::AbstractArray, ::Type{T}) = similar(a, T, to_shape(indices(a))) -similar{T}(a::AbstractArray{T}, dims::Tuple) = similar(a, T, to_shape(dims)) -similar{T}(a::AbstractArray{T}, dims::DimOrInd...) = similar(a, T, to_shape(dims)) -similar{T}(a::AbstractArray, ::Type{T}, dims::DimOrInd...) = similar(a, T, to_shape(dims)) -similar{T}(a::AbstractArray, ::Type{T}, dims::NeedsShaping) = similar(a, T, to_shape(dims)) +similar(a::AbstractArray{T}) where {T} = similar(a, T) +similar(a::AbstractArray, ::Type{T}) where {T} = similar(a, T, to_shape(indices(a))) +similar(a::AbstractArray{T}, dims::Tuple) where {T} = similar(a, T, to_shape(dims)) +similar(a::AbstractArray{T}, dims::DimOrInd...) where {T} = similar(a, T, to_shape(dims)) +similar(a::AbstractArray, ::Type{T}, dims::DimOrInd...) where {T} = similar(a, T, to_shape(dims)) +similar(a::AbstractArray, ::Type{T}, dims::NeedsShaping) where {T} = similar(a, T, to_shape(dims)) # similar creates an Array by default -similar{T,N}(a::AbstractArray, ::Type{T}, dims::Dims{N}) = Array{T,N}(dims) +similar(a::AbstractArray, ::Type{T}, dims::Dims{N}) where {T,N} = Array{T,N}(dims) to_shape(::Tuple{}) = () to_shape(dims::Dims) = dims @@ -740,7 +740,7 @@ function copymutable(a::AbstractArray) end copymutable(itr) = collect(itr) -zero{T}(x::AbstractArray{T}) = fill!(similar(x), zero(T)) +zero(x::AbstractArray{T}) where {T} = fill!(similar(x), zero(T)) ## iteration support for arrays by iterating over `eachindex` in the array ## # Allows fast iteration by default for both IndexLinear and IndexCartesian arrays @@ -841,10 +841,10 @@ full(x::AbstractArray) = x ## range conversions ## -map{T<:Real}(::Type{T}, r::StepRange) = T(r.start):T(r.step):T(last(r)) -map{T<:Real}(::Type{T}, r::UnitRange) = T(r.start):T(last(r)) -map{T<:AbstractFloat}(::Type{T}, r::StepRangeLen) = convert(StepRangeLen{T}, r) -function map{T<:AbstractFloat}(::Type{T}, r::LinSpace) +map(::Type{T}, r::StepRange) where {T<:Real} = T(r.start):T(r.step):T(last(r)) +map(::Type{T}, r::UnitRange) where {T<:Real} = T(r.start):T(last(r)) +map(::Type{T}, r::StepRangeLen) where {T<:AbstractFloat} = convert(StepRangeLen{T}, r) +function map(::Type{T}, r::LinSpace) where T<:AbstractFloat LinSpace(T(r.start), T(r.stop), length(r)) end @@ -901,7 +901,7 @@ function _getindex(::IndexLinear, A::AbstractArray, I::Int...) end _to_linear_index(A::AbstractArray, i::Int) = i _to_linear_index(A::AbstractVector, i::Int, I::Int...) = i # TODO: DEPRECATE FOR #14770 -_to_linear_index{T,N}(A::AbstractArray{T,N}, I::Vararg{Int,N}) = (@_inline_meta; sub2ind(A, I...)) +_to_linear_index(A::AbstractArray{T,N}, I::Vararg{Int,N}) where {T,N} = (@_inline_meta; sub2ind(A, I...)) _to_linear_index(A::AbstractArray) = 1 # TODO: DEPRECATE FOR #14770 _to_linear_index(A::AbstractArray, I::Int...) = (@_inline_meta; sub2ind(A, I...)) # TODO: DEPRECATE FOR #14770 @@ -916,16 +916,16 @@ function _getindex(::IndexCartesian, A::AbstractArray, I::Int...) @inbounds r = getindex(A, _to_subscript_indices(A, I...)...) r end -function _getindex{T,N}(::IndexCartesian, A::AbstractArray{T,N}, I::Vararg{Int, N}) +function _getindex(::IndexCartesian, A::AbstractArray{T,N}, I::Vararg{Int, N}) where {T,N} @_propagate_inbounds_meta getindex(A, I...) end _to_subscript_indices(A::AbstractArray, i::Int) = (@_inline_meta; _unsafe_ind2sub(A, i)) -_to_subscript_indices{T,N}(A::AbstractArray{T,N}) = (@_inline_meta; fill_to_length((), 1, Val{N})) # TODO: DEPRECATE FOR #14770 -_to_subscript_indices{T}(A::AbstractArray{T,0}) = () # TODO: REMOVE FOR #14770 -_to_subscript_indices{T}(A::AbstractArray{T,0}, i::Int) = () # TODO: REMOVE FOR #14770 -_to_subscript_indices{T}(A::AbstractArray{T,0}, I::Int...) = () # TODO: DEPRECATE FOR #14770 -function _to_subscript_indices{T,N}(A::AbstractArray{T,N}, I::Int...) # TODO: DEPRECATE FOR #14770 +_to_subscript_indices(A::AbstractArray{T,N}) where {T,N} = (@_inline_meta; fill_to_length((), 1, Val{N})) # TODO: DEPRECATE FOR #14770 +_to_subscript_indices(A::AbstractArray{T,0}) where {T} = () # TODO: REMOVE FOR #14770 +_to_subscript_indices(A::AbstractArray{T,0}, i::Int) where {T} = () # TODO: REMOVE FOR #14770 +_to_subscript_indices(A::AbstractArray{T,0}, I::Int...) where {T} = () # TODO: DEPRECATE FOR #14770 +function _to_subscript_indices(A::AbstractArray{T,N}, I::Int...) where {T,N} # TODO: DEPRECATE FOR #14770 @_inline_meta J, Jrem = IteratorsMD.split(I, Val{N}) _to_subscript_indices(A, J, Jrem) @@ -946,7 +946,7 @@ function __to_subscript_indices(A::AbstractArray, (J..., map(first, tail(_remaining_size(J, indices(A))))...) end _to_subscript_indices(A, J::Tuple, Jrem::Tuple) = J # already bounds-checked, safe to drop -_to_subscript_indices{T,N}(A::AbstractArray{T,N}, I::Vararg{Int,N}) = I +_to_subscript_indices(A::AbstractArray{T,N}, I::Vararg{Int,N}) where {T,N} = I _remaining_size(::Tuple{Any}, t::Tuple) = t _remaining_size(h::Tuple, t::Tuple) = (@_inline_meta; _remaining_size(tail(h), tail(t))) _unsafe_ind2sub(::Tuple{}, i) = () # ind2sub may throw(BoundsError()) in this case @@ -979,7 +979,7 @@ function _setindex!(::IndexLinear, A::AbstractArray, v, I::Int...) end # IndexCartesian Scalar indexing -function _setindex!{T,N}(::IndexCartesian, A::AbstractArray{T,N}, v, I::Vararg{Int, N}) +function _setindex!(::IndexCartesian, A::AbstractArray{T,N}, v, I::Vararg{Int, N}) where {T,N} @_propagate_inbounds_meta setindex!(A, v, I...) end @@ -1003,7 +1003,7 @@ get(A::AbstractArray, i::Integer, default) = checkbounds(Bool, A, i) ? A[i] : de get(A::AbstractArray, I::Tuple{}, default) = similar(A, typeof(default), 0) get(A::AbstractArray, I::Dims, default) = checkbounds(Bool, A, I...) ? A[I...] : default -function get!{T}(X::AbstractVector{T}, A::AbstractVector, I::Union{Range, AbstractVector{Int}}, default::T) +function get!(X::AbstractVector{T}, A::AbstractVector, I::Union{Range, AbstractVector{Int}}, default::T) where T # 1d is not linear indexing ind = findin(I, indices1(A)) X[ind] = A[I[ind]] @@ -1012,7 +1012,7 @@ function get!{T}(X::AbstractVector{T}, A::AbstractVector, I::Union{Range, Abstra X[last(ind)+1:last(Xind)] = default X end -function get!{T}(X::AbstractArray{T}, A::AbstractArray, I::Union{Range, AbstractVector{Int}}, default::T) +function get!(X::AbstractArray{T}, A::AbstractArray, I::Union{Range, AbstractVector{Int}}, default::T) where T # Linear indexing ind = findin(I, 1:length(A)) X[ind] = A[I[ind]] @@ -1024,7 +1024,7 @@ end get(A::AbstractArray, I::Range, default) = get!(similar(A, typeof(default), index_shape(I)), A, I, default) # TODO: DEPRECATE FOR #14770 (just the partial linear indexing part) -function get!{T}(X::AbstractArray{T}, A::AbstractArray, I::RangeVecIntList, default::T) +function get!(X::AbstractArray{T}, A::AbstractArray, I::RangeVecIntList, default::T) where T fill!(X, default) dst, src = indcopy(size(A), I) X[dst...] = A[src...] @@ -1051,24 +1051,24 @@ promote_eltype(v1, vs...) = promote_type(eltype(v1), promote_eltype(vs...)) #TODO: ERROR CHECK cat(catdim::Integer) = Array{Any,1}(0) -typed_vcat{T}(::Type{T}) = Array{T,1}(0) -typed_hcat{T}(::Type{T}) = Array{T,1}(0) +typed_vcat(::Type{T}) where {T} = Array{T,1}(0) +typed_hcat(::Type{T}) where {T} = Array{T,1}(0) ## cat: special cases -vcat{T}(X::T...) = T[ X[i] for i=1:length(X) ] -vcat{T<:Number}(X::T...) = T[ X[i] for i=1:length(X) ] -hcat{T}(X::T...) = T[ X[j] for i=1:1, j=1:length(X) ] -hcat{T<:Number}(X::T...) = T[ X[j] for i=1:1, j=1:length(X) ] +vcat(X::T...) where {T} = T[ X[i] for i=1:length(X) ] +vcat(X::T...) where {T<:Number} = T[ X[i] for i=1:length(X) ] +hcat(X::T...) where {T} = T[ X[j] for i=1:1, j=1:length(X) ] +hcat(X::T...) where {T<:Number} = T[ X[j] for i=1:1, j=1:length(X) ] vcat(X::Number...) = hvcat_fill(Array{promote_typeof(X...)}(length(X)), X) hcat(X::Number...) = hvcat_fill(Array{promote_typeof(X...)}(1,length(X)), X) -typed_vcat{T}(::Type{T}, X::Number...) = hvcat_fill(Array{T,1}(length(X)), X) -typed_hcat{T}(::Type{T}, X::Number...) = hvcat_fill(Array{T,2}(1,length(X)), X) +typed_vcat(::Type{T}, X::Number...) where {T} = hvcat_fill(Array{T,1}(length(X)), X) +typed_hcat(::Type{T}, X::Number...) where {T} = hvcat_fill(Array{T,2}(1,length(X)), X) vcat(V::AbstractVector...) = typed_vcat(promote_eltype(V...), V...) -vcat{T}(V::AbstractVector{T}...) = typed_vcat(T, V...) +vcat(V::AbstractVector{T}...) where {T} = typed_vcat(T, V...) -function typed_vcat{T}(::Type{T}, V::AbstractVector...) +function typed_vcat(::Type{T}, V::AbstractVector...) where T n::Int = 0 for Vk in V n += length(Vk) @@ -1085,9 +1085,9 @@ function typed_vcat{T}(::Type{T}, V::AbstractVector...) end hcat(A::AbstractVecOrMat...) = typed_hcat(promote_eltype(A...), A...) -hcat{T}(A::AbstractVecOrMat{T}...) = typed_hcat(T, A...) +hcat(A::AbstractVecOrMat{T}...) where {T} = typed_hcat(T, A...) -function typed_hcat{T}(::Type{T}, A::AbstractVecOrMat...) +function typed_hcat(::Type{T}, A::AbstractVecOrMat...) where T nargs = length(A) nrows = size(A[1], 1) ncols = 0 @@ -1122,9 +1122,9 @@ function typed_hcat{T}(::Type{T}, A::AbstractVecOrMat...) end vcat(A::AbstractMatrix...) = typed_vcat(promote_eltype(A...), A...) -vcat{T}(A::AbstractMatrix{T}...) = typed_vcat(T, A...) +vcat(A::AbstractMatrix{T}...) where {T} = typed_vcat(T, A...) -function typed_vcat{T}(::Type{T}, A::AbstractMatrix...) +function typed_vcat(::Type{T}, A::AbstractMatrix...) where T nargs = length(A) nrows = sum(a->size(a, 1), A)::Int ncols = size(A[1], 2) @@ -1200,7 +1200,7 @@ function cat_t(dims, T::Type, X...) return _cat(A, shape, catdims, X...) end -function _cat{N}(A, shape::NTuple{N}, catdims, X...) +function _cat(A, shape::NTuple{N}, catdims, X...) where N offsets = zeros(Int, N) inds = Vector{UnitRange{Int}}(N) concat = copy!(zeros(Bool, N), catdims) @@ -1295,7 +1295,7 @@ hcat(X...) = cat(Val{2}, X...) typed_vcat(T::Type, X...) = cat_t(Val{1}, T, X...) typed_hcat(T::Type, X...) = cat_t(Val{2}, T, X...) -cat{T}(catdims, A::AbstractArray{T}...) = cat_t(catdims, T, A...) +cat(catdims, A::AbstractArray{T}...) where {T} = cat_t(catdims, T, A...) # The specializations for 1 and 2 inputs are important # especially when running with --inline=no, see #11158 @@ -1362,9 +1362,9 @@ If the first argument is a single integer `n`, then all block rows are assumed t block columns. """ hvcat(rows::Tuple{Vararg{Int}}, xs::AbstractVecOrMat...) = typed_hvcat(promote_eltype(xs...), rows, xs...) -hvcat{T}(rows::Tuple{Vararg{Int}}, xs::AbstractVecOrMat{T}...) = typed_hvcat(T, rows, xs...) +hvcat(rows::Tuple{Vararg{Int}}, xs::AbstractVecOrMat{T}...) where {T} = typed_hvcat(T, rows, xs...) -function typed_hvcat{T}(::Type{T}, rows::Tuple{Vararg{Int}}, as::AbstractVecOrMat...) +function typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}, as::AbstractVecOrMat...) where T nbr = length(rows) # number of block rows nc = 0 @@ -1408,9 +1408,9 @@ function typed_hvcat{T}(::Type{T}, rows::Tuple{Vararg{Int}}, as::AbstractVecOrMa end hvcat(rows::Tuple{Vararg{Int}}) = [] -typed_hvcat{T}(::Type{T}, rows::Tuple{Vararg{Int}}) = Array{T,1}(0) +typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}) where {T} = Array{T,1}(0) -function hvcat{T<:Number}(rows::Tuple{Vararg{Int}}, xs::T...) +function hvcat(rows::Tuple{Vararg{Int}}, xs::T...) where T<:Number nr = length(rows) nc = rows[1] @@ -1445,7 +1445,7 @@ end hvcat(rows::Tuple{Vararg{Int}}, xs::Number...) = typed_hvcat(promote_typeof(xs...), rows, xs...) -function typed_hvcat{T}(::Type{T}, rows::Tuple{Vararg{Int}}, xs::Number...) +function typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}, xs::Number...) where T nr = length(rows) nc = rows[1] for i = 2:nr @@ -1472,7 +1472,7 @@ function hvcat(rows::Tuple{Vararg{Int}}, as...) vcat(rs...) end -function typed_hvcat{T}(::Type{T}, rows::Tuple{Vararg{Int}}, as...) +function typed_hvcat(::Type{T}, rows::Tuple{Vararg{Int}}, as...) where T nbr = length(rows) # number of block rows rs = Array{Any,1}(nbr) a = 1 @@ -1847,7 +1847,7 @@ end ## 1 argument -function map!{F}(f::F, dest::AbstractArray, A::AbstractArray) +function map!(f::F, dest::AbstractArray, A::AbstractArray) where F for (i,j) in zip(eachindex(dest),eachindex(A)) dest[i] = f(A[j]) end @@ -1881,7 +1881,7 @@ julia> map(+, [1, 2, 3], [10, 20, 30]) map(f, A) = collect(Generator(f,A)) ## 2 argument -function map!{F}(f::F, dest::AbstractArray, A::AbstractArray, B::AbstractArray) +function map!(f::F, dest::AbstractArray, A::AbstractArray, B::AbstractArray) where F for (i, j, k) in zip(eachindex(dest), eachindex(A), eachindex(B)) dest[i] = f(A[j], B[k]) end @@ -1918,7 +1918,7 @@ julia> x 6.0 ``` """ -map!{F}(f::F, dest::AbstractArray, As::AbstractArray...) = map_n!(f, dest, As) +map!(f::F, dest::AbstractArray, As::AbstractArray...) where {F} = map_n!(f, dest, As) map(f) = f() map(f, iters...) = collect(Generator(f, iters...)) diff --git a/base/abstractarraymath.jl b/base/abstractarraymath.jl index ec0b6440de291..07b55a77bd767 100644 --- a/base/abstractarraymath.jl +++ b/base/abstractarraymath.jl @@ -210,7 +210,7 @@ function circshift(a::AbstractArray, shiftamt) end # Uses K-B-N summation -function cumsum_kbn{T<:AbstractFloat}(v::AbstractVector{T}) +function cumsum_kbn(v::AbstractVector{T}) where T<:AbstractFloat r = similar(v) if isempty(v); return r; end @@ -241,7 +241,7 @@ end Cumulative sum along a dimension, using the Kahan-Babuska-Neumaier compensated summation algorithm for additional accuracy. The dimension defaults to 1. """ -function cumsum_kbn{T<:AbstractFloat}(A::AbstractArray{T}, axis::Integer=1) +function cumsum_kbn(A::AbstractArray{T}, axis::Integer=1) where T<:AbstractFloat dimsA = size(A) ndimsA = ndims(A) axis_size = dimsA[axis] diff --git a/base/array.jl b/base/array.jl index 450f35db02128..a6961462f0ef2 100644 --- a/base/array.jl +++ b/base/array.jl @@ -113,7 +113,7 @@ function unsafe_copy!(dest::Array{T}, doffs, src::Array{T}, soffs, n) where T return dest end -function copy!{T}(dest::Array{T}, doffs::Integer, src::Array{T}, soffs::Integer, n::Integer) +function copy!(dest::Array{T}, doffs::Integer, src::Array{T}, soffs::Integer, n::Integer) where T n == 0 && return dest n > 0 || throw(ArgumentError(string("tried to copy n=", n, " elements, but n should be nonnegative"))) if soffs < 1 || doffs < 1 || soffs+n-1 > length(src) || doffs+n-1 > length(dest) @@ -126,20 +126,20 @@ copy!(dest::Array{T}, src::Array{T}) where {T} = copy!(dest, 1, src, 1, length(s copy(a::T) where {T<:Array} = ccall(:jl_array_copy, Ref{T}, (Any,), a) -function reinterpret{T,S}(::Type{T}, a::Array{S,1}) +function reinterpret(::Type{T}, a::Array{S,1}) where T where S nel = Int(div(length(a)*sizeof(S),sizeof(T))) # TODO: maybe check that remainder is zero? return reinterpret(T, a, (nel,)) end -function reinterpret{T,S}(::Type{T}, a::Array{S}) +function reinterpret(::Type{T}, a::Array{S}) where T where S if sizeof(S) != sizeof(T) throw(ArgumentError("result shape not specified")) end reinterpret(T, a, size(a)) end -function reinterpret{T,S,N}(::Type{T}, a::Array{S}, dims::NTuple{N,Int}) +function reinterpret(::Type{T}, a::Array{S}, dims::NTuple{N,Int}) where T where S where N if !isbits(T) throw(ArgumentError("cannot reinterpret Array{$(S)} to ::Type{Array{$(T)}}, type $(T) is not a bits type")) end @@ -154,7 +154,7 @@ function reinterpret{T,S,N}(::Type{T}, a::Array{S}, dims::NTuple{N,Int}) end # reshaping to same # of dimensions -function reshape{T,N}(a::Array{T,N}, dims::NTuple{N,Int}) +function reshape(a::Array{T,N}, dims::NTuple{N,Int}) where T where N if prod(dims) != length(a) throw(DimensionMismatch("new dimensions $(dims) must be consistent with array size $(length(a))")) end @@ -165,7 +165,7 @@ function reshape{T,N}(a::Array{T,N}, dims::NTuple{N,Int}) end # reshaping to different # of dimensions -function reshape{T,N}(a::Array{T}, dims::NTuple{N,Int}) +function reshape(a::Array{T}, dims::NTuple{N,Int}) where T where N if prod(dims) != length(a) throw(DimensionMismatch("new dimensions $(dims) must be consistent with array size $(length(a))")) end @@ -174,16 +174,16 @@ end ## Constructors ## -similar{T}(a::Array{T,1}) = Array{T,1}(size(a,1)) -similar{T}(a::Array{T,2}) = Array{T,2}(size(a,1), size(a,2)) -similar{T}(a::Array{T,1}, S::Type) = Array{S,1}(size(a,1)) -similar{T}(a::Array{T,2}, S::Type) = Array{S,2}(size(a,1), size(a,2)) -similar{T}(a::Array{T}, m::Int) = Array{T,1}(m) -similar{N}(a::Array, T::Type, dims::Dims{N}) = Array{T,N}(dims) -similar{T,N}(a::Array{T}, dims::Dims{N}) = Array{T,N}(dims) +similar(a::Array{T,1}) where {T} = Array{T,1}(size(a,1)) +similar(a::Array{T,2}) where {T} = Array{T,2}(size(a,1), size(a,2)) +similar(a::Array{T,1}, S::Type) where {T} = Array{S,1}(size(a,1)) +similar(a::Array{T,2}, S::Type) where {T} = Array{S,2}(size(a,1), size(a,2)) +similar(a::Array{T}, m::Int) where {T} = Array{T,1}(m) +similar(a::Array, T::Type, dims::Dims{N}) where {N} = Array{T,N}(dims) +similar(a::Array{T}, dims::Dims{N}) where {T,N} = Array{T,N}(dims) # T[x...] constructs Array{T,1} -function getindex{T}(::Type{T}, vals...) +function getindex(::Type{T}, vals...) where T a = Array{T,1}(length(vals)) @inbounds for i = 1:length(vals) a[i] = vals[i] @@ -191,10 +191,10 @@ function getindex{T}(::Type{T}, vals...) return a end -getindex{T}(::Type{T}) = (@_inline_meta; Array{T,1}(0)) -getindex{T}(::Type{T}, x) = (@_inline_meta; a = Array{T,1}(1); @inbounds a[1] = x; a) -getindex{T}(::Type{T}, x, y) = (@_inline_meta; a = Array{T,1}(2); @inbounds (a[1] = x; a[2] = y); a) -getindex{T}(::Type{T}, x, y, z) = (@_inline_meta; a = Array{T,1}(3); @inbounds (a[1] = x; a[2] = y; a[3] = z); a) +getindex(::Type{T}) where {T} = (@_inline_meta; Array{T,1}(0)) +getindex(::Type{T}, x) where {T} = (@_inline_meta; a = Array{T,1}(1); @inbounds a[1] = x; a) +getindex(::Type{T}, x, y) where {T} = (@_inline_meta; a = Array{T,1}(2); @inbounds (a[1] = x; a[2] = y); a) +getindex(::Type{T}, x, y, z) where {T} = (@_inline_meta; a = Array{T,1}(3); @inbounds (a[1] = x; a[2] = y; a[3] = z); a) function getindex(::Type{Any}, vals::ANY...) a = Array{Any,1}(length(vals)) @@ -210,7 +210,7 @@ function fill!(a::Union{Array{UInt8}, Array{Int8}}, x::Integer) return a end -function fill!{T<:Union{Integer,AbstractFloat}}(a::Array{T}, x) +function fill!(a::Array{T}, x) where T<:Union{Integer,AbstractFloat} xT = convert(T, x) for i in eachindex(a) @inbounds a[i] = xT @@ -261,7 +261,7 @@ end `m`-by-`n` identity matrix. The default element type is `Float64`. """ -function eye{T}(::Type{T}, m::Integer, n::Integer) +function eye(::Type{T}, m::Integer, n::Integer) where T a = zeros(T,m,n) for i = 1:min(m,n) a[i,i] = oneunit(T) @@ -275,7 +275,7 @@ end `m`-by-`n` identity matrix. """ eye(m::Integer, n::Integer) = eye(Float64, m, n) -eye{T}(::Type{T}, n::Integer) = eye(T, n, n) +eye(::Type{T}, n::Integer) where {T} = eye(T, n, n) """ eye([T::Type=Float64,] n::Integer) @@ -305,16 +305,16 @@ julia> eye(A) Note the difference from [`ones`](@ref). """ -eye{T}(x::AbstractMatrix{T}) = eye(typeof(one(T)), size(x, 1), size(x, 2)) +eye(x::AbstractMatrix{T}) where {T} = eye(typeof(one(T)), size(x, 1), size(x, 2)) -function _one{T}(unit::T, x::AbstractMatrix) +function _one(unit::T, x::AbstractMatrix) where T m,n = size(x) m==n || throw(DimensionMismatch("multiplicative identity defined only for square matrices")) eye(T, m) end -one{T}(x::AbstractMatrix{T}) = _one(one(T), x) -oneunit{T}(x::AbstractMatrix{T}) = _one(oneunit(T), x) +one(x::AbstractMatrix{T}) where {T} = _one(one(T), x) +oneunit(x::AbstractMatrix{T}) where {T} = _one(oneunit(T), x) ## Conversions ## @@ -327,7 +327,7 @@ convert(::Type{Array{T,n}}, x::Array{T,n}) where {T,n} = x convert(::Type{Array{T}}, x::AbstractArray{S,n}) where {T,n,S} = convert(Array{T,n}, x) convert(::Type{Array{T,n}}, x::AbstractArray{S,n}) where {T,n,S} = copy!(Array{T,n}(size(x)), x) -promote_rule{T,n,S}(::Type{Array{T,n}}, ::Type{Array{S,n}}) = Array{promote_type(T,S),n} +promote_rule(::Type{Array{T,n}}, ::Type{Array{S,n}}) where {T,n,S} = Array{promote_type(T,S),n} ## copying iterators to containers @@ -345,11 +345,11 @@ julia> collect(Float64, 1:2:5) 5.0 ``` """ -collect{T}(::Type{T}, itr) = _collect(T, itr, iteratorsize(itr)) +collect(::Type{T}, itr) where {T} = _collect(T, itr, iteratorsize(itr)) -_collect{T}(::Type{T}, itr, isz::HasLength) = copy!(Array{T,1}(Int(length(itr)::Integer)), itr) -_collect{T}(::Type{T}, itr, isz::HasShape) = copy!(similar(Array{T}, indices(itr)), itr) -function _collect{T}(::Type{T}, itr, isz::SizeUnknown) +_collect(::Type{T}, itr, isz::HasLength) where {T} = copy!(Array{T,1}(Int(length(itr)::Integer)), itr) +_collect(::Type{T}, itr, isz::HasShape) where {T} = copy!(similar(Array{T}, indices(itr)), itr) +function _collect(::Type{T}, itr, isz::SizeUnknown) where T a = Array{T,1}(0) for x in itr push!(a,x) @@ -413,8 +413,8 @@ else _default_eltype(itr::ANY) = Any end -_array_for{T}(::Type{T}, itr, ::HasLength) = Array{T,1}(Int(length(itr)::Integer)) -_array_for{T}(::Type{T}, itr, ::HasShape) = similar(Array{T}, indices(itr)) +_array_for(::Type{T}, itr, ::HasLength) where {T} = Array{T,1}(Int(length(itr)::Integer)) +_array_for(::Type{T}, itr, ::HasShape) where {T} = similar(Array{T}, indices(itr)) function collect(itr::Generator) isz = iteratorsize(itr.iter) @@ -454,7 +454,7 @@ function collect_to_with_first!(dest, v1, itr, st) return grow_to!(dest, itr, st) end -function collect_to!{T}(dest::AbstractArray{T}, itr, offs, st) +function collect_to!(dest::AbstractArray{T}, itr, offs, st) where T # collect to dest array, checking the type of each result. if a result does not # match, widen the result type and re-dispatch. i = offs @@ -529,13 +529,13 @@ function getindex(A::Array, c::Colon) end # This is redundant with the abstract fallbacks, but needed for bootstrap -function getindex{S}(A::Array{S}, I::Range{Int}) +function getindex(A::Array{S}, I::Range{Int}) where S return S[ A[i] for i in I ] end ## Indexing: setindex! ## -setindex!{T}(A::Array{T}, x, i1::Int) = arrayset(A, convert(T,x)::T, i1) -setindex!{T}(A::Array{T}, x, i1::Int, i2::Int, I::Int...) = (@_inline_meta; arrayset(A, convert(T,x)::T, i1, i2, I...)) # TODO: REMOVE FOR #14770 +setindex!(A::Array{T}, x, i1::Int) where {T} = arrayset(A, convert(T,x)::T, i1) +setindex!(A::Array{T}, x, i1::Int, i2::Int, I::Int...) where {T} = (@_inline_meta; arrayset(A, convert(T,x)::T, i1, i2, I...)) # TODO: REMOVE FOR #14770 # These are redundant with the abstract fallbacks but needed for bootstrap function setindex!(A::Array, x, I::AbstractVector{Int}) @@ -565,7 +565,7 @@ function setindex!(A::Array, X::AbstractArray, I::AbstractVector{Int}) end # Faster contiguous setindex! with copy! -function setindex!{T}(A::Array{T}, X::Array{T}, I::UnitRange{Int}) +function setindex!(A::Array{T}, X::Array{T}, I::UnitRange{Int}) where T @_inline_meta @boundscheck checkbounds(A, I) lI = length(I) @@ -575,7 +575,7 @@ function setindex!{T}(A::Array{T}, X::Array{T}, I::UnitRange{Int}) end return A end -function setindex!{T}(A::Array{T}, X::Array{T}, c::Colon) +function setindex!(A::Array{T}, X::Array{T}, c::Colon) where T @_inline_meta lI = length(A) @boundscheck setindex_shape_check(X, lI) @@ -586,7 +586,7 @@ function setindex!{T}(A::Array{T}, X::Array{T}, c::Colon) end setindex!(A::Array, x::Number, ::Colon) = fill!(A, x) -setindex!{T, N}(A::Array{T, N}, x::Number, ::Vararg{Colon, N}) = fill!(A, x) +setindex!(A::Array{T, N}, x::Number, ::Vararg{Colon, N}) where {T, N} = fill!(A, x) # efficiently grow an array @@ -600,7 +600,7 @@ _deleteat!(a::Vector, i::Integer, delta::Integer) = ## Dequeue functionality ## -function push!{T}(a::Array{T,1}, item) +function push!(a::Array{T,1}, item) where T # convert first so we don't grow the array if the assignment won't work itemT = convert(T, item) ccall(:jl_array_grow_end, Void, (Any, UInt), a, 1) @@ -762,7 +762,7 @@ julia> unshift!([1, 2, 3, 4], 5, 6) 4 ``` """ -function unshift!{T}(a::Array{T,1}, item) +function unshift!(a::Array{T,1}, item) where T item = convert(T, item) ccall(:jl_array_grow_beg, Void, (Any, UInt), a, 1) a[1] = item @@ -795,7 +795,7 @@ julia> insert!([6, 5, 4, 2, 1], 4, 3) 1 ``` """ -function insert!{T}(a::Array{T,1}, i::Integer, item) +function insert!(a::Array{T,1}, i::Integer, item) where T # Throw convert error before changing the shape of the array _item = convert(T, item) _growat!(a, i, 1) @@ -1039,13 +1039,13 @@ function lexcmp(a::Array{UInt8,1}, b::Array{UInt8,1}) end # use memcmp for == on bit integer types -function =={T<:BitInteger,N}(a::Array{T,N}, b::Array{T,N}) +function ==(a::Array{T,N}, b::Array{T,N}) where T<:BitInteger where N size(a) == size(b) && 0 == ccall( :memcmp, Int32, (Ptr{T}, Ptr{T}, UInt), a, b, sizeof(T) * length(a)) end # this is ~20% faster than the generic implementation above for very small arrays -function =={T<:BitInteger}(a::Array{T,1}, b::Array{T,1}) +function ==(a::Array{T,1}, b::Array{T,1}) where T<:BitInteger len = length(a) len == length(b) && 0 == ccall( :memcmp, Int32, (Ptr{T}, Ptr{T}, UInt), a, b, sizeof(T) * len) @@ -1091,7 +1091,7 @@ end vcat() = Array{Any,1}(0) hcat() = Array{Any,1}(0) -function hcat{T}(V::Vector{T}...) +function hcat(V::Vector{T}...) where T height = length(V[1]) for j = 2:length(V) if length(V[j]) != height @@ -1101,7 +1101,7 @@ function hcat{T}(V::Vector{T}...) return [ V[j][i]::T for i=1:length(V[1]), j=1:length(V) ] end -function vcat{T}(arrays::Vector{T}...) +function vcat(arrays::Vector{T}...) where T n = 0 for a in arrays n += length(a) @@ -1551,7 +1551,7 @@ julia> findnz(A) ([1, 1, 3, 2], [1, 2, 2, 3], [1, 2, 4, 3]) ``` """ -function findnz{T}(A::AbstractMatrix{T}) +function findnz(A::AbstractMatrix{T}) where T nnzA = countnz(A) I = zeros(Int, nnzA) J = zeros(Int, nnzA) diff --git a/base/arraymath.jl b/base/arraymath.jl index 762a582b53791..1d286bda5063b 100644 --- a/base/arraymath.jl +++ b/base/arraymath.jl @@ -50,7 +50,7 @@ end ## data movement ## -function flipdim{T}(A::Array{T}, d::Integer) +function flipdim(A::Array{T}, d::Integer) where T nd = ndims(A) 1 ≤ d ≤ nd || throw(ArgumentError("dimension $d is not 1 ≤ $d ≤ $nd")) sd = size(A, d) diff --git a/base/atomics.jl b/base/atomics.jl index 09bd9788637cd..1fc7f7a64d3ed 100644 --- a/base/atomics.jl +++ b/base/atomics.jl @@ -303,7 +303,7 @@ julia> x[] function atomic_min! end unsafe_convert(::Type{Ptr{T}}, x::Atomic{T}) where {T} = convert(Ptr{T}, pointer_from_objref(x)) -setindex!{T}(x::Atomic{T}, v) = setindex!(x, convert(T, v)) +setindex!(x::Atomic{T}, v) where {T} = setindex!(x, convert(T, v)) const llvmtypes = Dict( Bool => "i1", @@ -316,13 +316,13 @@ const llvmtypes = Dict( Float32 => "float", Float64 => "double", ) -inttype{T<:Integer}(::Type{T}) = T +inttype(::Type{T}) where {T<:Integer} = T inttype(::Type{Float16}) = Int16 inttype(::Type{Float32}) = Int32 inttype(::Type{Float64}) = Int64 -alignment{T}(::Type{T}) = ccall(:jl_alignment, Cint, (Csize_t,), sizeof(T)) +alignment(::Type{T}) where {T} = ccall(:jl_alignment, Cint, (Csize_t,), sizeof(T)) # All atomic operations have acquire and/or release semantics, depending on # whether the load or store values. Most of the time, this is what one wants @@ -447,7 +447,7 @@ end const opnames = Dict{Symbol, Symbol}(:+ => :add, :- => :sub) for op in [:+, :-, :max, :min] opname = get(opnames, op, op) - @eval function $(Symbol("atomic_", opname, "!")){T<:FloatTypes}(var::Atomic{T}, val::T) + @eval function $(Symbol("atomic_", opname, "!"))(var::Atomic{T}, val::T) where T<:FloatTypes IT = inttype(T) old = var[] while true diff --git a/base/base.jl b/base/base.jl index 652b9106a18c1..fd04ea496b6ad 100644 --- a/base/base.jl +++ b/base/base.jl @@ -129,7 +129,7 @@ function finalizer(o::ANY, f::ANY) ccall(:jl_gc_add_finalizer_th, Void, (Ptr{Void}, Any, Any), Core.getptls(), o, f) end -function finalizer{T}(o::T, f::Ptr{Void}) +function finalizer(o::T, f::Ptr{Void}) where T @_inline_meta if isimmutable(T) error("objects of type ", T, " cannot be finalized") diff --git a/base/bitarray.jl b/base/bitarray.jl index 99faeebf38183..1fa5700044656 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -472,7 +472,7 @@ function copy!(dest::BitArray, src::Array) return unsafe_copy!(dest, 1, src, 1, length(src)) end -function reshape{N}(B::BitArray, dims::NTuple{N,Int}) +function reshape(B::BitArray, dims::NTuple{N,Int}) where N prod(dims) == length(B) || throw(DimensionMismatch("new dimensions $(dims) must be consistent with array size $(length(B))")) dims == size(B) && return B @@ -487,7 +487,7 @@ end convert(::Type{Array{T}}, B::BitArray{N}) where {T,N} = convert(Array{T,N}, B) convert(::Type{Array{T,N}}, B::BitArray{N}) where {T,N} = _convert(Array{T,N}, B) # see #15801 -function _convert{T,N}(::Type{Array{T,N}}, B::BitArray{N}) +function _convert(::Type{Array{T,N}}, B::BitArray{N}) where {T,N} A = Array{T}(size(B)) Bc = B.chunks @inbounds for i = 1:length(A) @@ -534,8 +534,8 @@ end convert(::Type{BitArray{N}}, B::BitArray{N}) where {N} = B convert(::Type{AbstractArray{T,N}}, B::BitArray{N}) where {T,N} = convert(Array{T,N}, B) -reinterpret{N}(::Type{Bool}, B::BitArray, dims::NTuple{N,Int}) = reinterpret(B, dims) -reinterpret{N}(B::BitArray, dims::NTuple{N,Int}) = reshape(B, dims) +reinterpret(::Type{Bool}, B::BitArray, dims::NTuple{N,Int}) where {N} = reinterpret(B, dims) +reinterpret(B::BitArray, dims::NTuple{N,Int}) where {N} = reshape(B, dims) ## Constructors from generic iterables ## diff --git a/base/bool.jl b/base/bool.jl index a874de0ca6bec..b73ccee81a45e 100644 --- a/base/bool.jl +++ b/base/bool.jl @@ -7,7 +7,7 @@ convert(::Type{Bool}, x::Float16) = x==0 ? false : x==1 ? true : throw(InexactEr convert(::Type{Bool}, x::Real) = x==0 ? false : x==1 ? true : throw(InexactError()) # promote Bool to any other numeric type -promote_rule{T<:Number}(::Type{Bool}, ::Type{T}) = T +promote_rule(::Type{Bool}, ::Type{T}) where {T<:Number} = T typemin(::Type{Bool}) = false typemax(::Type{Bool}) = true @@ -92,15 +92,15 @@ iszero(x::Bool) = !x ^(x::Bool, y::Bool) = x | !y ^(x::Integer, y::Bool) = ifelse(y, x, one(x)) -function +{T<:AbstractFloat}(x::Bool, y::T)::promote_type(Bool,T) +function +(x::Bool, y::T)::promote_type(Bool,T) where T<:AbstractFloat return ifelse(x, oneunit(y) + y, y) end +(y::AbstractFloat, x::Bool) = x + y -function *{T<:Number}(x::Bool, y::T)::promote_type(Bool,T) +function *(x::Bool, y::T)::promote_type(Bool,T) where T<:Number return ifelse(x, y, copysign(zero(y), y)) end -function *{T<:Unsigned}(x::Bool, y::T)::promote_type(Bool,T) +function *(x::Bool, y::T)::promote_type(Bool,T) where T<:Unsigned return ifelse(x, y, zero(y)) end *(y::Number, x::Bool) = x * y diff --git a/base/boot.jl b/base/boot.jl index 1e01b32f45aa2..32de033195dbc 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -295,32 +295,32 @@ Task(f::ANY) = ccall(:jl_new_task, Ref{Task}, (Any, Int), f, 0) # so the methods and ccall's in Core aren't permitted to use convert convert(::Type{Any}, x::ANY) = x convert(::Type{T}, x::T) where {T} = x -cconvert{T}(::Type{T}, x) = convert(T, x) +cconvert(::Type{T}, x) where {T} = convert(T, x) unsafe_convert(::Type{T}, x::T) where {T} = x NTuple{N,T} = Tuple{Vararg{T,N}} # primitive array constructors -(::Type{Array{T,N}}){T,N}(d::NTuple{N,Int}) = +(::Type{Array{T,N}})(d::NTuple{N,Int}) where {T,N} = ccall(:jl_new_array, Array{T,N}, (Any,Any), Array{T,N}, d) -(::Type{Array{T,1}}){T}(d::NTuple{1,Int}) = Array{T,1}(getfield(d,1)) -(::Type{Array{T,2}}){T}(d::NTuple{2,Int}) = Array{T,2}(getfield(d,1), getfield(d,2)) -(::Type{Array{T,3}}){T}(d::NTuple{3,Int}) = Array{T,3}(getfield(d,1), getfield(d,2), getfield(d,3)) -(::Type{Array{T,N}}){T,N}(d::Vararg{Int, N}) = ccall(:jl_new_array, Array{T,N}, (Any,Any), Array{T,N}, d) -(::Type{Array{T,1}}){T}(m::Int) = +(::Type{Array{T,1}})(d::NTuple{1,Int}) where {T} = Array{T,1}(getfield(d,1)) +(::Type{Array{T,2}})(d::NTuple{2,Int}) where {T} = Array{T,2}(getfield(d,1), getfield(d,2)) +(::Type{Array{T,3}})(d::NTuple{3,Int}) where {T} = Array{T,3}(getfield(d,1), getfield(d,2), getfield(d,3)) +(::Type{Array{T,N}})(d::Vararg{Int, N}) where {T,N} = ccall(:jl_new_array, Array{T,N}, (Any,Any), Array{T,N}, d) +(::Type{Array{T,1}})(m::Int) where {T} = ccall(:jl_alloc_array_1d, Array{T,1}, (Any,Int), Array{T,1}, m) -(::Type{Array{T,2}}){T}(m::Int, n::Int) = +(::Type{Array{T,2}})(m::Int, n::Int) where {T} = ccall(:jl_alloc_array_2d, Array{T,2}, (Any,Int,Int), Array{T,2}, m, n) -(::Type{Array{T,3}}){T}(m::Int, n::Int, o::Int) = +(::Type{Array{T,3}})(m::Int, n::Int, o::Int) where {T} = ccall(:jl_alloc_array_3d, Array{T,3}, (Any,Int,Int,Int), Array{T,3}, m, n, o) -(::Type{Array{T}}){T,N}(d::NTuple{N,Int}) = Array{T,N}(d) -(::Type{Array{T}}){T}(m::Int) = Array{T,1}(m) -(::Type{Array{T}}){T}(m::Int, n::Int) = Array{T,2}(m, n) -(::Type{Array{T}}){T}(m::Int, n::Int, o::Int) = Array{T,3}(m, n, o) +(::Type{Array{T}})(d::NTuple{N,Int}) where {T,N} = Array{T,N}(d) +(::Type{Array{T}})(m::Int) where {T} = Array{T,1}(m) +(::Type{Array{T}})(m::Int, n::Int) where {T} = Array{T,2}(m, n) +(::Type{Array{T}})(m::Int, n::Int, o::Int) where {T} = Array{T,3}(m, n, o) -(::Type{Array{T,1}}){T}() = Array{T,1}(0) +(::Type{Array{T,1}})() where {T} = Array{T,1}(0) # primitive Symbol constructors function Symbol(s::String) diff --git a/base/broadcast.jl b/base/broadcast.jl index 53927084de7f9..436bed3068d59 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -14,7 +14,7 @@ const ScalarType = Union{Type{Any}, Type{Nullable}} ## Broadcasting utilities ## # fallbacks for some special cases @inline broadcast(f, x::Number...) = f(x...) -@inline broadcast{N}(f, t::NTuple{N,Any}, ts::Vararg{NTuple{N,Any}}) = map(f, t, ts...) +@inline broadcast(f, t::NTuple{N,Any}, ts::Vararg{NTuple{N,Any}}) where {N} = map(f, t, ts...) broadcast!{T,S,N}(::typeof(identity), x::Array{T,N}, y::Array{S,N}) = size(x) == size(y) ? copy!(x, y) : broadcast_c!(identity, Array, Array, x, y) @@ -201,9 +201,9 @@ Note that `dest` is only used to store the result, and does not supply arguments to `f` unless it is also listed in the `As`, as in `broadcast!(f, A, A, B)` to perform `A[:] = broadcast(f, A, B)`. """ -@inline broadcast!{N}(f, C::AbstractArray, A, Bs::Vararg{Any,N}) = +@inline broadcast!(f, C::AbstractArray, A, Bs::Vararg{Any,N}) where {N} = broadcast_c!(f, containertype(C), containertype(A, Bs...), C, A, Bs...) -@inline function broadcast_c!{N}(f, ::Type, ::Type, C, A, Bs::Vararg{Any,N}) +@inline function broadcast_c!(f, ::Type, ::Type, C, A, Bs::Vararg{Any,N}) where N shape = indices(C) @boundscheck check_broadcast_indices(shape, A, Bs...) keeps, Idefaults = map_newindexer(shape, A, Bs) @@ -335,9 +335,9 @@ end @inline broadcast_c(f, ::Type{Any}, a...) = f(a...) @inline broadcast_c(f, ::Type{Tuple}, A, Bs...) = tuplebroadcast(f, first_tuple(A, Bs...), A, Bs...) -@inline tuplebroadcast{N}(f, ::NTuple{N,Any}, As...) = +@inline tuplebroadcast(f, ::NTuple{N,Any}, As...) where {N} = ntuple(k -> f(tuplebroadcast_getargs(As, k)...), Val{N}) -@inline tuplebroadcast{N,T}(f, ::NTuple{N,Any}, ::Type{T}, As...) = +@inline tuplebroadcast(f, ::NTuple{N,Any}, ::Type{T}, As...) where {N,T} = ntuple(k -> f(T, tuplebroadcast_getargs(As, k)...), Val{N}) first_tuple(A::Tuple, Bs...) = A @inline first_tuple(A, Bs...) = first_tuple(Bs...) diff --git a/base/c.jl b/base/c.jl index 34d4f86c80c4a..dba82413d88bb 100644 --- a/base/c.jl +++ b/base/c.jl @@ -63,11 +63,11 @@ end # construction from typed pointers convert(::Type{Cstring}, p::Ptr{<:Union{Int8,UInt8}}) = bitcast(Cstring, p) convert(::Type{Cwstring}, p::Ptr{Cwchar_t}) = bitcast(Cwstring, p) -convert{T<:Union{Int8,UInt8}}(::Type{Ptr{T}}, p::Cstring) = bitcast(Ptr{T}, p) +convert(::Type{Ptr{T}}, p::Cstring) where {T<:Union{Int8,UInt8}} = bitcast(Ptr{T}, p) convert(::Type{Ptr{Cwchar_t}}, p::Cwstring) = bitcast(Ptr{Cwchar_t}, p) # construction from untyped pointers -convert{T<:Union{Cstring,Cwstring}}(::Type{T}, p::Ptr{Void}) = bitcast(T, p) +convert(::Type{T}, p::Ptr{Void}) where {T<:Union{Cstring,Cwstring}} = bitcast(T, p) pointer(p::Cstring) = convert(Ptr{UInt8}, p) pointer(p::Cwstring) = convert(Ptr{Cwchar_t}, p) diff --git a/base/channels.jl b/base/channels.jl index a6c8859b20abe..403dc73190bc2 100644 --- a/base/channels.jl +++ b/base/channels.jl @@ -390,7 +390,7 @@ mutable struct ChannelIterState{T} ChannelIterState{T}(has::Bool) where {T} = new(has) end -start{T}(c::Channel{T}) = ChannelIterState{T}(false) +start(c::Channel{T}) where {T} = ChannelIterState{T}(false) function done(c::Channel, state::ChannelIterState) try # we are waiting either for more data or channel to be closed diff --git a/base/complex.jl b/base/complex.jl index 3d0bf6cebcf84..eb27aeff7b7fa 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -26,9 +26,9 @@ convert(::Type{T}, z::Complex) where {T<:Real} = convert(::Type{Complex}, z::Complex) = z convert(::Type{Complex}, x::Real) = Complex(x) -promote_rule{T<:Real,S<:Real}(::Type{Complex{T}}, ::Type{S}) = +promote_rule(::Type{Complex{T}}, ::Type{S}) where {T<:Real,S<:Real} = Complex{promote_type(T,S)} -promote_rule{T<:Real,S<:Real}(::Type{Complex{T}}, ::Type{Complex{S}}) = +promote_rule(::Type{Complex{T}}, ::Type{Complex{S}}) where {T<:Real,S<:Real} = Complex{promote_type(T,S)} widen{T}(::Type{Complex{T}}) = Complex{widen(T)} @@ -267,10 +267,10 @@ muladd(z::Complex, w::Complex, x::Real) = Complex(muladd(real(z), real(w), x) - imag(z)*imag(w), # TODO: use mulsub given #15985 muladd(real(z), imag(w), imag(z) * real(w))) -/{R<:Real,S<:Complex}(a::R, z::S) = (T = promote_type(R,S); a*inv(T(z))) +/(a::R, z::S) where {R<:Real,S<:Complex} = (T = promote_type(R,S); a*inv(T(z))) /(z::Complex, x::Real) = Complex(real(z)/x, imag(z)/x) -function /{T<:Real}(a::Complex{T}, b::Complex{T}) +function /(a::Complex{T}, b::Complex{T}) where T<:Real are = real(a); aim = imag(a); bre = real(b); bim = imag(b) if abs(bre) <= abs(bim) if isinf(bre) && isinf(bim) @@ -294,7 +294,7 @@ end inv(z::Complex{<:Union{Float16,Float32}}) = oftype(z, conj(widen(z))/abs2(widen(z))) -/{T<:Union{Float16,Float32}}(z::Complex{T}, w::Complex{T}) = +/(z::Complex{T}, w::Complex{T}) where {T<:Union{Float16,Float32}} = oftype(z, widen(z)*inv(widen(w))) # robust complex division for double precision @@ -554,7 +554,7 @@ function log1p{T}(z::Complex{T}) end end -function ^{T<:AbstractFloat}(z::Complex{T}, p::Complex{T})::Complex{T} +function ^(z::Complex{T}, p::Complex{T})::Complex{T} where T<:AbstractFloat if p == 2 #square zr, zi = reim(z) x = (zr-zi)*(zr+zi) @@ -601,7 +601,7 @@ function exp10{T}(z::Complex{T}) Complex(er*cos(theta), er*sin(theta)) end -function ^{T<:Complex}(z::T, p::T) +function ^(z::T, p::T) where T<:Complex if isinteger(p) rp = real(p) if rp < 0 diff --git a/base/datafmt.jl b/base/datafmt.jl index 7637e7d36ab84..a80bd1f5328d2 100644 --- a/base/datafmt.jl +++ b/base/datafmt.jl @@ -222,8 +222,8 @@ _chrinstr(sbuff::String, chr::UInt8, startpos::Int, endpos::Int) = (endpos >= startpos) && (C_NULL != ccall(:memchr, Ptr{UInt8}, (Ptr{UInt8}, Int32, Csize_t), pointer(sbuff)+startpos-1, chr, endpos-startpos+1)) -function store_cell{T}(dlmstore::DLMStore{T}, row::Int, col::Int, - quoted::Bool, startpos::Int, endpos::Int) +function store_cell(dlmstore::DLMStore{T}, row::Int, col::Int, + quoted::Bool, startpos::Int, endpos::Int) where T drow = row - dlmstore.hdr_offset ncols = dlmstore.ncols @@ -291,7 +291,7 @@ function store_cell{T}(dlmstore::DLMStore{T}, row::Int, col::Int, nothing end -function result{T}(dlmstore::DLMStore{T}) +function result(dlmstore::DLMStore{T}) where T nrows = dlmstore.nrows - dlmstore.hdr_offset ncols = dlmstore.ncols lastcol = dlmstore.lastcol @@ -456,9 +456,9 @@ function colval(sbuff::String, startpos::Int, endpos::Int, cells::Array{<:Char,2 end colval(sbuff::String, startpos::Int, endpos::Int, cells::Array, row::Int, col::Int) = true -function dlm_parse{D}(dbuff::String, eol::D, dlm::D, qchar::D, cchar::D, +function dlm_parse(dbuff::String, eol::D, dlm::D, qchar::D, cchar::D, ign_adj_dlm::Bool, allow_quote::Bool, allow_comments::Bool, - skipstart::Int, skipblanks::Bool, dh::DLMHandler) + skipstart::Int, skipblanks::Bool, dh::DLMHandler) where D ncols = nrows = col = 0 is_default_dlm = (dlm == invalid_dlm(D)) error_str = "" diff --git a/base/dates/arithmetic.jl b/base/dates/arithmetic.jl index ac59b4971e3ab..e1a611af0828f 100644 --- a/base/dates/arithmetic.jl +++ b/base/dates/arithmetic.jl @@ -2,11 +2,11 @@ # Instant arithmetic (+)(x::Instant) = x -(-){T<:Instant}(x::T, y::T) = x.periods - y.periods +(-)(x::T, y::T) where {T<:Instant} = x.periods - y.periods # TimeType arithmetic (+)(x::TimeType) = x -(-){T<:TimeType}(x::T, y::T) = x.instant - y.instant +(-)(x::T, y::T) where {T<:TimeType} = x.instant - y.instant # Date-Time arithmetic """ @@ -90,9 +90,9 @@ end (-)(x::StridedArray{<:GeneralPeriod}, y::TimeType) = x .- y # TimeType, AbstractArray{TimeType} -(-){T<:TimeType}(x::AbstractArray{T}, y::T) = x .- y -(-){T<:TimeType}(y::T, x::AbstractArray{T}) = y .- x +(-)(x::AbstractArray{T}, y::T) where {T<:TimeType} = x .- y +(-)(y::T, x::AbstractArray{T}) where {T<:TimeType} = y .- x # AbstractArray{TimeType}, AbstractArray{TimeType} -(-){T<:TimeType}(x::OrdinalRange{T}, y::OrdinalRange{T}) = collect(x) - collect(y) -(-){T<:TimeType}(x::Range{T}, y::Range{T}) = collect(x) - collect(y) +(-)(x::OrdinalRange{T}, y::OrdinalRange{T}) where {T<:TimeType} = collect(x) - collect(y) +(-)(x::Range{T}, y::Range{T}) where {T<:TimeType} = collect(x) - collect(y) diff --git a/base/dates/periods.jl b/base/dates/periods.jl index 0779d8446fed6..e2c40726e7adf 100644 --- a/base/dates/periods.jl +++ b/base/dates/periods.jl @@ -58,9 +58,9 @@ function default end default{T<:DatePeriod}(p::Union{T,Type{T}}) = T(1) default{T<:TimePeriod}(p::Union{T,Type{T}}) = T(0) -(-){P<:Period}(x::P) = P(-value(x)) +(-)(x::P) where {P<:Period} = P(-value(x)) Base.isless{P<:Period}(x::P, y::P) = isless(value(x), value(y)) -=={P<:Period}(x::P, y::P) = value(x) == value(y) +==(x::P, y::P) where {P<:Period} = value(x) == value(y) # Period Arithmetic, grouped by dimensionality: import Base: div, fld, mod, rem, gcd, lcm, +, -, *, /, % @@ -82,7 +82,7 @@ for op in (:rem, :mod) end end -*{P<:Period}(x::P, y::Real) = P(value(x) * Int64(y)) +*(x::P, y::Real) where {P<:Period} = P(value(x) * Int64(y)) *(y::Real, x::Period) = x * y for (op, Ty, Tz) in ((:*, Real, :P), (:/, :P, Float64), (:/, Real, :P)) diff --git a/base/dates/types.jl b/base/dates/types.jl index 3a2d67415339f..4bfa5c5339d8f 100644 --- a/base/dates/types.jl +++ b/base/dates/types.jl @@ -294,11 +294,11 @@ Base.typemin(::Union{Date, Type{Date}}) = Date(-252522163911150, 1, 1) Base.typemax(::Union{Time, Type{Time}}) = Time(23, 59, 59, 999, 999, 999) Base.typemin(::Union{Time, Type{Time}}) = Time(0) # Date-DateTime promotion, isless, == -Base.eltype{T<:Period}(::Type{T}) = T +Base.eltype(::Type{T}) where {T<:Period} = T Base.promote_rule(::Type{Date}, x::Type{DateTime}) = DateTime -Base.isless{T<:TimeType}(x::T, y::T) = isless(value(x), value(y)) +Base.isless(x::T, y::T) where {T<:TimeType} = isless(value(x), value(y)) Base.isless(x::TimeType, y::TimeType) = isless(Base.promote_noncircular(x, y)...) -=={T<:TimeType}(x::T, y::T) = ==(value(x), value(y)) +==(x::T, y::T) where {T<:TimeType} = ==(value(x), value(y)) function ==(a::Time, b::Time) return hour(a) == hour(b) && minute(a) == minute(b) && second(a) == second(b) && millisecond(a) == millisecond(b) && diff --git a/base/deprecated.jl b/base/deprecated.jl index eda5caa42f303..fe3d2e7e5e655 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1196,10 +1196,10 @@ last{T}(r::Use_StepRangeLen_Instead{T}) = convert(T, (r.start + (r.len-1)*r.step start(r::Use_StepRangeLen_Instead) = 0 done(r::Use_StepRangeLen_Instead, i::Int) = length(r) <= i -next{T}(r::Use_StepRangeLen_Instead{T}, i::Int) = +next(r::Use_StepRangeLen_Instead{T}, i::Int) where {T} = (convert(T, (r.start + i*r.step)/r.divisor), i+1) -function getindex{T}(r::Use_StepRangeLen_Instead{T}, i::Integer) +function getindex(r::Use_StepRangeLen_Instead{T}, i::Integer) where T @_inline_meta @boundscheck checkbounds(r, i) convert(T, (r.start + (i-1)*r.step)/r.divisor) @@ -1218,20 +1218,20 @@ end *(x::Real, r::Use_StepRangeLen_Instead) = Use_StepRangeLen_Instead(x*r.start, x*r.step, r.len, r.divisor) *(r::Use_StepRangeLen_Instead, x::Real) = x * r /(r::Use_StepRangeLen_Instead, x::Real) = Use_StepRangeLen_Instead(r.start/x, r.step/x, r.len, r.divisor) -promote_rule{T1,T2}(::Type{Use_StepRangeLen_Instead{T1}},::Type{Use_StepRangeLen_Instead{T2}}) = +promote_rule(::Type{Use_StepRangeLen_Instead{T1}},::Type{Use_StepRangeLen_Instead{T2}}) where {T1,T2} = Use_StepRangeLen_Instead{promote_type(T1,T2)} convert(::Type{Use_StepRangeLen_Instead{T}}, r::Use_StepRangeLen_Instead{T}) where {T<:AbstractFloat} = r convert(::Type{Use_StepRangeLen_Instead{T}}, r::Use_StepRangeLen_Instead) where {T<:AbstractFloat} = Use_StepRangeLen_Instead{T}(r.start,r.step,r.len,r.divisor) -promote_rule{F,OR<:OrdinalRange}(::Type{Use_StepRangeLen_Instead{F}}, ::Type{OR}) = +promote_rule(::Type{Use_StepRangeLen_Instead{F}}, ::Type{OR}) where {F,OR<:OrdinalRange} = Use_StepRangeLen_Instead{promote_type(F,eltype(OR))} convert(::Type{Use_StepRangeLen_Instead{T}}, r::OrdinalRange) where {T<:AbstractFloat} = Use_StepRangeLen_Instead{T}(first(r), step(r), length(r), one(T)) convert(::Type{Use_StepRangeLen_Instead}, r::OrdinalRange{T}) where {T} = Use_StepRangeLen_Instead{typeof(float(first(r)))}(first(r), step(r), length(r), one(T)) -promote_rule{F,OR<:Use_StepRangeLen_Instead}(::Type{LinSpace{F}}, ::Type{OR}) = +promote_rule(::Type{LinSpace{F}}, ::Type{OR}) where {F,OR<:Use_StepRangeLen_Instead} = LinSpace{promote_type(F,eltype(OR))} convert(::Type{LinSpace{T}}, r::Use_StepRangeLen_Instead) where {T<:AbstractFloat} = linspace(convert(T, first(r)), convert(T, last(r)), convert(T, length(r))) diff --git a/base/dft.jl b/base/dft.jl index 6239a3b4e23ba..3f40878c51bae 100644 --- a/base/dft.jl +++ b/base/dft.jl @@ -22,24 +22,24 @@ export fft, ifft, bfft, fft!, ifft!, bfft!, const FFTWFloat = Union{Float32,Float64} fftwfloat(x) = _fftwfloat(float(x)) -_fftwfloat{T<:FFTWFloat}(::Type{T}) = T +_fftwfloat(::Type{T}) where {T<:FFTWFloat} = T _fftwfloat(::Type{Float16}) = Float32 -_fftwfloat{T}(::Type{Complex{T}}) = Complex{_fftwfloat(T)} -_fftwfloat{T}(::Type{T}) = error("type $T not supported") -_fftwfloat{T}(x::T) = _fftwfloat(T)(x) +_fftwfloat(::Type{Complex{T}}) where {T} = Complex{_fftwfloat(T)} +_fftwfloat(::Type{T}) where {T} = error("type $T not supported") +_fftwfloat(x::T) where {T} = _fftwfloat(T)(x) complexfloat(x::StridedArray{Complex{<:FFTWFloat}}) = x realfloat(x::StridedArray{<:FFTWFloat}) = x # return an Array, rather than similar(x), to avoid an extra copy for FFTW # (which only works on StridedArray types). -complexfloat{T<:Complex}(x::AbstractArray{T}) = copy1(typeof(fftwfloat(zero(T))), x) -complexfloat{T<:Real}(x::AbstractArray{T}) = copy1(typeof(complex(fftwfloat(zero(T)))), x) +complexfloat(x::AbstractArray{T}) where {T<:Complex} = copy1(typeof(fftwfloat(zero(T))), x) +complexfloat(x::AbstractArray{T}) where {T<:Real} = copy1(typeof(complex(fftwfloat(zero(T)))), x) -realfloat{T<:Real}(x::AbstractArray{T}) = copy1(typeof(fftwfloat(zero(T))), x) +realfloat(x::AbstractArray{T}) where {T<:Real} = copy1(typeof(fftwfloat(zero(T))), x) # copy to a 1-based array, using circular permutation -function copy1{T}(::Type{T}, x) +function copy1(::Type{T}, x) where T y = Array{T}(map(length, indices(x))) Base.circcopy!(y, x) end @@ -211,7 +211,7 @@ rfft(x::AbstractArray{<:Union{Integer,Rational}}, region=1:ndims(x)) = rfft(real plan_rfft(x::AbstractArray, region; kws...) = plan_rfft(realfloat(x), region; kws...) # only require implementation to provide *(::Plan{T}, ::Array{T}) -*{T}(p::Plan{T}, x::AbstractArray) = p * copy1(T, x) +*(p::Plan{T}, x::AbstractArray) where {T} = p * copy1(T, x) # Implementations should also implement A_mul_B!(Y, plan, X) so as to support # pre-allocated output arrays. We don't define * in terms of A_mul_B! diff --git a/base/dict.jl b/base/dict.jl index 202f844050cb4..bfe6ca4322a73 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -23,7 +23,7 @@ function _truncate_at_width_or_chars(str, width, chars="", truncmark="…") end end -function show{K,V}(io::IO, t::Associative{K,V}) +function show(io::IO, t::Associative{K,V}) where V where K recur_io = IOContext(io, :SHOWN_SET => t) limit::Bool = get(io, :limit, false) if !haskey(io, :compact) @@ -154,12 +154,12 @@ end TP{K,V} = Union{Type{Tuple{K,V}},Type{Pair{K,V}}} -associative_with_eltype{K,V}(DT_apply, kv, ::TP{K,V}) = DT_apply(K, V)(kv) -associative_with_eltype{K,V}(DT_apply, kv::Generator, ::TP{K,V}) = DT_apply(K, V)(kv) -associative_with_eltype{K,V}(DT_apply, ::Type{Pair{K,V}}) = DT_apply(K, V)() +associative_with_eltype(DT_apply, kv, ::TP{K,V}) where {K,V} = DT_apply(K, V)(kv) +associative_with_eltype(DT_apply, kv::Generator, ::TP{K,V}) where {K,V} = DT_apply(K, V)(kv) +associative_with_eltype(DT_apply, ::Type{Pair{K,V}}) where {K,V} = DT_apply(K, V)() associative_with_eltype(DT_apply, ::Type) = DT_apply(Any, Any)() -associative_with_eltype{F}(DT_apply::F, kv, t) = grow_to!(associative_with_eltype(DT_apply, _default_eltype(typeof(kv))), kv) -function associative_with_eltype{F}(DT_apply::F, kv::Generator, t) +associative_with_eltype(DT_apply::F, kv, t) where {F} = grow_to!(associative_with_eltype(DT_apply, _default_eltype(typeof(kv))), kv) +function associative_with_eltype(DT_apply::F, kv::Generator, t) where F T = _default_eltype(typeof(kv)) if T <: Union{Pair, Tuple{Any, Any}} && isleaftype(T) return associative_with_eltype(DT_apply, kv, T) @@ -174,7 +174,7 @@ function grow_to!(dest::Associative, itr) return isempty(out) ? dest : out end -function grow_to!{K,V}(dest::Associative{K,V}, itr, st) +function grow_to!(dest::Associative{K,V}, itr, st) where V where K while !done(itr, st) (k,v), st = next(itr, st) if isa(k,K) && isa(v,V) @@ -189,8 +189,8 @@ function grow_to!{K,V}(dest::Associative{K,V}, itr, st) return dest end -similar{K,V}(d::Dict{K,V}) = Dict{K,V}() -similar{K,V}(d::Dict, ::Type{Pair{K,V}}) = Dict{K,V}() +similar(d::Dict{K,V}) where {K,V} = Dict{K,V}() +similar(d::Dict, ::Type{Pair{K,V}}) where {K,V} = Dict{K,V}() # conversion between Dict types function convert(::Type{Dict{K,V}},d::Associative) where V where K @@ -300,7 +300,7 @@ julia> A Dict{String,Int64} with 0 entries ``` """ -function empty!{K,V}(h::Dict{K,V}) +function empty!(h::Dict{K,V}) where V where K fill!(h.slots, 0x0) sz = length(h.slots) empty!(h.keys) @@ -315,7 +315,7 @@ function empty!{K,V}(h::Dict{K,V}) end # get the index where a key is stored, or -1 if not present -function ht_keyindex{K,V}(h::Dict{K,V}, key) +function ht_keyindex(h::Dict{K,V}, key) where V where K sz = length(h.keys) iter = 0 maxprobe = h.maxprobe @@ -340,7 +340,7 @@ end # get the index where a key is stored, or -pos if not present # and the key would be inserted at pos # This version is for use by setindex! and get! -function ht_keyindex2{K,V}(h::Dict{K,V}, key) +function ht_keyindex2(h::Dict{K,V}, key) where V where K age0 = h.age sz = length(h.keys) iter = 0 @@ -408,7 +408,7 @@ function _setindex!(h::Dict, v, key, index) end end -function setindex!{K,V}(h::Dict{K,V}, v0, key0) +function setindex!(h::Dict{K,V}, v0, key0) where V where K key = convert(K, key0) if !isequal(key, key0) throw(ArgumentError("$key0 is not a valid key for type $K")) @@ -416,7 +416,7 @@ function setindex!{K,V}(h::Dict{K,V}, v0, key0) setindex!(h, v0, key) end -function setindex!{K,V}(h::Dict{K,V}, v0, key::K) +function setindex!(h::Dict{K,V}, v0, key::K) where V where K v = convert(V, v0) index = ht_keyindex2(h, key) @@ -431,8 +431,8 @@ function setindex!{K,V}(h::Dict{K,V}, v0, key::K) return h end -get!{K,V}(h::Dict{K,V}, key0, default) = get!(()->default, h, key0) -function get!{K,V}(default::Callable, h::Dict{K,V}, key0) +get!(h::Dict{K,V}, key0, default) where {K,V} = get!(()->default, h, key0) +function get!(default::Callable, h::Dict{K,V}, key0) where V where K key = convert(K, key0) if !isequal(key, key0) throw(ArgumentError("$key0 is not a valid key for type $K")) @@ -440,7 +440,7 @@ function get!{K,V}(default::Callable, h::Dict{K,V}, key0) return get!(default, h, key) end -function get!{K,V}(default::Callable, h::Dict{K,V}, key::K) +function get!(default::Callable, h::Dict{K,V}, key::K) where V where K index = ht_keyindex2(h, key) index > 0 && return h.vals[index] @@ -469,17 +469,17 @@ macro get!(h, key0, default) end -function getindex{K,V}(h::Dict{K,V}, key) +function getindex(h::Dict{K,V}, key) where V where K index = ht_keyindex(h, key) return (index < 0) ? throw(KeyError(key)) : h.vals[index]::V end -function get{K,V}(h::Dict{K,V}, key, default) +function get(h::Dict{K,V}, key, default) where V where K index = ht_keyindex(h, key) return (index < 0) ? default : h.vals[index]::V end -function get{K,V}(default::Callable, h::Dict{K,V}, key) +function get(default::Callable, h::Dict{K,V}, key) where V where K index = ht_keyindex(h, key) return (index < 0) ? default() : h.vals[index]::V end @@ -523,7 +523,7 @@ julia> getkey(a,'d','a') 'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase) ``` """ -function getkey{K,V}(h::Dict{K,V}, key, default) +function getkey(h::Dict{K,V}, key, default) where V where K index = ht_keyindex(h, key) return (index<0) ? default : h.keys[index]::K end @@ -576,7 +576,7 @@ function start(t::Dict) return i end done(t::Dict, i) = i > length(t.vals) -next{K,V}(t::Dict{K,V}, i) = (Pair{K,V}(t.keys[i],t.vals[i]), skip_deleted(t,i+1)) +next(t::Dict{K,V}, i) where {K,V} = (Pair{K,V}(t.keys[i],t.vals[i]), skip_deleted(t,i+1)) isempty(t::Dict) = (t.count == 0) length(t::Dict) = t.count @@ -595,8 +595,8 @@ function filter!(f, d::Union{ObjectIdDict,Dict}) return d end -struct ImmutableDict{K, V} <: Associative{K,V} - parent::ImmutableDict{K, V} +struct ImmutableDict{K,V} <: Associative{K,V} + parent::ImmutableDict{K,V} key::K value::V ImmutableDict{K,V}() where {K,V} = new() # represents an empty dictionary @@ -660,7 +660,7 @@ end # this actually defines reverse iteration (e.g. it should not be used for merge/copy/filter type operations) start(t::ImmutableDict) = t -next{K,V}(::ImmutableDict{K,V}, t) = (Pair{K,V}(t.key, t.value), t.parent) +next(::ImmutableDict{K,V}, t) where {K,V} = (Pair{K,V}(t.key, t.value), t.parent) done(::ImmutableDict, t) = !isdefined(t, :parent) length(t::ImmutableDict) = count(x->true, t) isempty(t::ImmutableDict) = done(t, start(t)) diff --git a/base/docs/utils.jl b/base/docs/utils.jl index 973c49eb2ee06..2802e5bf8c4c5 100644 --- a/base/docs/utils.jl +++ b/base/docs/utils.jl @@ -72,8 +72,8 @@ print(io::IO, t::Text) = print(io, t.content) print(io::IO, t::Text{<:Function}) = t.content(io) show(io::IO, t::Text) = print(io, t) -=={T<:Union{HTML, Text}}(t1::T, t2::T) = t1.content == t2.content -hash{T<:Union{HTML, Text}}(t::T, h::UInt) = hash(T, hash(t.content, h)) +==(t1::T, t2::T) where {T<:Union{HTML,Text}} = t1.content == t2.content +hash(t::T, h::UInt) where {T<:Union{HTML,Text}} = hash(T, hash(t.content, h)) """ @text_str -> Docs.Text diff --git a/base/essentials.jl b/base/essentials.jl index f2f5da38907c4..a944e84d07416 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -133,9 +133,9 @@ function typename(a::Union) end typename(union::UnionAll) = typename(union.body) -convert{T<:Tuple{Any,Vararg{Any}}}(::Type{T}, x::Tuple{Any, Vararg{Any}}) = +convert(::Type{T}, x::Tuple{Any,Vararg{Any}}) where {T<:Tuple{Any,Vararg{Any}}} = tuple(convert(tuple_type_head(T),x[1]), convert(tuple_type_tail(T), tail(x))...) -convert{T<:Tuple{Any,Vararg{Any}}}(::Type{T}, x::T) = x +convert(::Type{T}, x::T) where {T<:Tuple{Any,Vararg{Any}}} = x oftype(x,c) = convert(typeof(x),c) @@ -143,8 +143,8 @@ unsigned(x::Int) = reinterpret(UInt, x) signed(x::UInt) = reinterpret(Int, x) # conversions used by ccall -ptr_arg_cconvert{T}(::Type{Ptr{T}}, x) = cconvert(T, x) -ptr_arg_unsafe_convert{T}(::Type{Ptr{T}}, x) = unsafe_convert(T, x) +ptr_arg_cconvert(::Type{Ptr{T}}, x) where {T} = cconvert(T, x) +ptr_arg_unsafe_convert(::Type{Ptr{T}}, x) where {T} = unsafe_convert(T, x) ptr_arg_unsafe_convert(::Type{Ptr{Void}}, x) = x cconvert(T::Type, x) = convert(T, x) # do the conversion eagerly in most cases @@ -153,7 +153,7 @@ unsafe_convert(::Type{T}, x::T) where {T} = x # unsafe_convert (like convert) de unsafe_convert(::Type{T}, x::T) where {T<:Ptr} = x # to resolve ambiguity with the next method unsafe_convert(::Type{P}, x::Ptr) where {P<:Ptr} = convert(P, x) -reinterpret{T}(::Type{T}, x) = bitcast(T, x) +reinterpret(::Type{T}, x) where {T} = bitcast(T, x) reinterpret(::Type{Unsigned}, x::Float16) = reinterpret(UInt16,x) reinterpret(::Type{Signed}, x::Float16) = reinterpret(Int16,x) diff --git a/base/fft/FFTW.jl b/base/fft/FFTW.jl index 712f7e6ebe850..bcf93a7e05a80 100644 --- a/base/fft/FFTW.jl +++ b/base/fft/FFTW.jl @@ -74,7 +74,7 @@ struct FakeArray{T, N} <: DenseArray{T, N} end size(a::FakeArray) = a.sz strides(a::FakeArray) = a.st -unsafe_convert{T}(::Type{Ptr{T}}, a::FakeArray{T}) = convert(Ptr{T}, C_NULL) +unsafe_convert(::Type{Ptr{T}}, a::FakeArray{T}) where {T} = convert(Ptr{T}, C_NULL) pointer{T}(a::FakeArray{T}) = convert(Ptr{T}, C_NULL) FakeArray{T, N}(::Type{T}, sz::NTuple{N, Int}) = FakeArray{T, N}(sz, colmajorstrides(sz)) @@ -299,14 +299,14 @@ function sprint_plan(plan::FFTWPlan) return str end -function show{T,K,inplace}(io::IO, p::cFFTWPlan{T,K,inplace}) +function show(io::IO, p::cFFTWPlan{T,K,inplace}) where {T,K,inplace} print(io, inplace ? "FFTW in-place " : "FFTW ", K < 0 ? "forward" : "backward", " plan for ") showfftdims(io, p.sz, p.istride, T) version >= v"3.3.4" && print(io, "\n", sprint_plan(p)) end -function show{T,K,inplace}(io::IO, p::rFFTWPlan{T,K,inplace}) +function show(io::IO, p::rFFTWPlan{T,K,inplace}) where {T,K,inplace} print(io, inplace ? "FFTW in-place " : "FFTW ", K < 0 ? "real-to-complex" : "complex-to-real", " plan for ") @@ -314,7 +314,7 @@ function show{T,K,inplace}(io::IO, p::rFFTWPlan{T,K,inplace}) version >= v"3.3.4" && print(io, "\n", sprint_plan(p)) end -function show{T,K,inplace}(io::IO, p::r2rFFTWPlan{T,K,inplace}) +function show(io::IO, p::r2rFFTWPlan{T,K,inplace}) where {T,K,inplace} print(io, inplace ? "FFTW in-place r2r " : "FFTW r2r ") if isempty(K) print(io, "0-dimensional") @@ -618,20 +618,20 @@ for (f,direction) in ((:fft,FORWARD), (:bfft,BACKWARD)) end end -function A_mul_B!{T}(y::StridedArray{T}, p::cFFTWPlan{T}, x::StridedArray{T}) +function A_mul_B!(y::StridedArray{T}, p::cFFTWPlan{T}, x::StridedArray{T}) where T assert_applicable(p, x, y) unsafe_execute!(p, x, y) return y end -function *{T,K,N}(p::cFFTWPlan{T,K,false}, x::StridedArray{T,N}) +function *(p::cFFTWPlan{T,K,false}, x::StridedArray{T,N}) where {T,K,N} assert_applicable(p, x) y = Array{T}(p.osz)::Array{T,N} unsafe_execute!(p, x, y) return y end -function *{T,K}(p::cFFTWPlan{T,K,true}, x::StridedArray{T}) +function *(p::cFFTWPlan{T,K,true}, x::StridedArray{T}) where {T,K} assert_applicable(p, x) unsafe_execute!(p, x, x) return x @@ -781,20 +781,20 @@ function plan_inv{T<:fftwNumber,K,inplace,N}(p::r2rFFTWPlan{T,K,inplace,N}) 1:length(iK))) end -function A_mul_B!{T}(y::StridedArray{T}, p::r2rFFTWPlan{T}, x::StridedArray{T}) +function A_mul_B!(y::StridedArray{T}, p::r2rFFTWPlan{T}, x::StridedArray{T}) where T assert_applicable(p, x, y) unsafe_execute!(p, x, y) return y end -function *{T,K,N}(p::r2rFFTWPlan{T,K,false}, x::StridedArray{T,N}) +function *(p::r2rFFTWPlan{T,K,false}, x::StridedArray{T,N}) where {T,K,N} assert_applicable(p, x) y = Array{T}(p.osz)::Array{T,N} unsafe_execute!(p, x, y) return y end -function *{T,K}(p::r2rFFTWPlan{T,K,true}, x::StridedArray{T}) +function *(p::r2rFFTWPlan{T,K,true}, x::StridedArray{T}) where {T,K} assert_applicable(p, x) unsafe_execute!(p, x, x) return x diff --git a/base/fft/dct.jl b/base/fft/dct.jl index 6ce51e5ab25c3..d548c265fbc49 100644 --- a/base/fft/dct.jl +++ b/base/fft/dct.jl @@ -20,7 +20,7 @@ end size(p::DCTPlan) = size(p.plan) -function show{T,K,inplace}(io::IO, p::DCTPlan{T,K,inplace}) +function show(io::IO, p::DCTPlan{T,K,inplace}) where {T,K,inplace} print(io, inplace ? "FFTW in-place " : "FFTW ", K == REDFT10 ? "DCT (DCT-II)" : "IDCT (DCT-III)", " plan for ") showfftdims(io, p.plan.sz, p.plan.istride, eltype(p)) @@ -94,10 +94,10 @@ function A_mul_B!{T}(y::StridedArray{T}, p::DCTPlan{T,REDFT01}, return y end -*{T}(p::DCTPlan{T,REDFT10,false}, x::StridedArray{T}) = +*(p::DCTPlan{T,REDFT10,false}, x::StridedArray{T}) where {T} = A_mul_B!(Array{T}(p.plan.osz), p, x) -*{T}(p::DCTPlan{T,REDFT01,false}, x::StridedArray{T}) = +*(p::DCTPlan{T,REDFT01,false}, x::StridedArray{T}) where {T} = A_mul_B!(Array{T}(p.plan.osz), p, copy(x)) # need copy to preserve input -*{T,K}(p::DCTPlan{T,K,true}, x::StridedArray{T}) = A_mul_B!(x, p, x) +*(p::DCTPlan{T,K,true}, x::StridedArray{T}) where {T,K} = A_mul_B!(x, p, x) diff --git a/base/generator.jl b/base/generator.jl index 53d69e9adde54..378419c13b6ea 100644 --- a/base/generator.jl +++ b/base/generator.jl @@ -109,10 +109,10 @@ iteratoreltype(x) = iteratoreltype(typeof(x)) iteratoreltype(::Type) = HasEltype() # HasEltype is the default iteratorsize(::Type{<:AbstractArray}) = HasShape() -iteratorsize{I,F}(::Type{Generator{I,F}}) = iteratorsize(I) +iteratorsize(::Type{Generator{I,F}}) where {I,F} = iteratorsize(I) length(g::Generator) = length(g.iter) size(g::Generator) = size(g.iter) indices(g::Generator) = indices(g.iter) ndims(g::Generator) = ndims(g.iter) -iteratoreltype{I,T}(::Type{Generator{I,T}}) = EltypeUnknown() +iteratoreltype(::Type{Generator{I,T}}) where {I,T} = EltypeUnknown() diff --git a/base/int.jl b/base/int.jl index 88b20efc85995..3c1084b2dc7e9 100644 --- a/base/int.jl +++ b/base/int.jl @@ -25,17 +25,17 @@ const BitUnsigned64T = Union{Type{UInt8}, Type{UInt16}, Type{UInt32}, Type{UInt6 ## integer comparisons ## -<{T<:BitSigned}(x::T, y::T) = slt_int(x, y) +(<)(x::T, y::T) where {T<:BitSigned} = slt_int(x, y) --(x::BitInteger) = neg_int(x) --{T<:BitInteger}(x::T, y::T) = sub_int(x, y) -+{T<:BitInteger}(x::T, y::T) = add_int(x, y) -*{T<:BitInteger}(x::T, y::T) = mul_int(x, y) +(-)(x::BitInteger) = neg_int(x) +(-)(x::T, y::T) where {T<:BitInteger} = sub_int(x, y) +(+)(x::T, y::T) where {T<:BitInteger} = add_int(x, y) +(*)(x::T, y::T) where {T<:BitInteger} = mul_int(x, y) inv(x::Integer) = float(one(x)) / float(x) -/{T<:Integer}(x::T, y::T) = float(x) / float(y) +(/)(x::T, y::T) where {T<:Integer} = float(x) / float(y) # skip promotion for system integer types -/(x::BitInteger, y::BitInteger) = float(x) / float(y) +(/)(x::BitInteger, y::BitInteger) = float(x) / float(y) """ isodd(x::Integer) -> Bool @@ -70,7 +70,7 @@ iseven(n::Integer) = !isodd(n) signbit(x::Integer) = x < 0 signbit(x::Unsigned) = false -flipsign{T<:BitSigned}(x::T, y::T) = flipsign_int(x, y) +flipsign(x::T, y::T) where {T<:BitSigned} = flipsign_int(x, y) flipsign(x::Signed, y::Signed) = convert(typeof(x), flipsign(promote_noncircular(x, y)...)) flipsign(x::Signed, y::Float16) = flipsign(x, bitcast(Int16, y)) @@ -166,38 +166,38 @@ julia> mod(-eps(), 3) 3.0 ``` """ -function mod{T<:Integer}(x::T, y::T) +function mod(x::T, y::T) where T<:Integer y == -1 && return T(0) # avoid potential overflow in fld return x - fld(x, y) * y end mod(x::Signed, y::Unsigned) = rem(y + unsigned(rem(x, y)), y) mod(x::Unsigned, y::Signed) = rem(y + signed(rem(x, y)), y) -mod{T<:Unsigned}(x::T, y::T) = rem(x, y) +mod(x::T, y::T) where {T<:Unsigned} = rem(x, y) cld(x::Signed, y::Unsigned) = div(x, y) + (!signbit(x) & (rem(x, y) != 0)) cld(x::Unsigned, y::Signed) = div(x, y) + (!signbit(y) & (rem(x, y) != 0)) # Don't promote integers for div/rem/mod since there is no danger of overflow, # while there is a substantial performance penalty to 64-bit promotion. -div{T<:BitSigned64}(x::T, y::T) = checked_sdiv_int(x, y) -rem{T<:BitSigned64}(x::T, y::T) = checked_srem_int(x, y) -div{T<:BitUnsigned64}(x::T, y::T) = checked_udiv_int(x, y) -rem{T<:BitUnsigned64}(x::T, y::T) = checked_urem_int(x, y) +div(x::T, y::T) where {T<:BitSigned64} = checked_sdiv_int(x, y) +rem(x::T, y::T) where {T<:BitSigned64} = checked_srem_int(x, y) +div(x::T, y::T) where {T<:BitUnsigned64} = checked_udiv_int(x, y) +rem(x::T, y::T) where {T<:BitUnsigned64} = checked_urem_int(x, y) # fld(x,y) == div(x,y) - ((x>=0) != (y>=0) && rem(x,y) != 0 ? 1 : 0) -fld{T<:Unsigned}(x::T, y::T) = div(x,y) -function fld{T<:Integer}(x::T, y::T) +fld(x::T, y::T) where {T<:Unsigned} = div(x,y) +function fld(x::T, y::T) where T<:Integer d = div(x, y) return d - (signbit(x ⊻ y) & (d * y != x)) end # cld(x,y) = div(x,y) + ((x>0) == (y>0) && rem(x,y) != 0 ? 1 : 0) -function cld{T<:Unsigned}(x::T, y::T) +function cld(x::T, y::T) where T<:Unsigned d = div(x, y) return d + (d * y != x) end -function cld{T<:Integer}(x::T, y::T) +function cld(x::T, y::T) where T<:Integer d = div(x, y) return d + (((x > 0) == (y > 0)) & (d * y != x)) end @@ -205,9 +205,9 @@ end ## integer bitwise operations ## (~)(x::BitInteger) = not_int(x) -(&){T<:BitInteger}(x::T, y::T) = and_int(x, y) -(|){T<:BitInteger}(x::T, y::T) = or_int(x, y) -xor{T<:BitInteger}(x::T, y::T) = xor_int(x, y) +(&)(x::T, y::T) where {T<:BitInteger} = and_int(x, y) +(|)(x::T, y::T) where {T<:BitInteger} = or_int(x, y) +xor(x::T, y::T) where {T<:BitInteger} = xor_int(x, y) bswap(x::Union{Int8, UInt8}) = x bswap(x::Union{Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128}) = @@ -287,9 +287,9 @@ trailing_ones(x::Integer) = trailing_zeros(~x) ## integer comparisons ## -<{T<:BitUnsigned}(x::T, y::T) = ult_int(x, y) -<={T<:BitSigned}(x::T, y::T) = sle_int(x, y) -<={T<:BitUnsigned}(x::T, y::T) = ule_int(x, y) +(< )(x::T, y::T) where {T<:BitUnsigned} = ult_int(x, y) +(<=)(x::T, y::T) where {T<:BitSigned} = sle_int(x, y) +(<=)(x::T, y::T) where {T<:BitUnsigned} = ule_int(x, y) ==(x::Signed, y::Unsigned) = (x >= 0) & (unsigned(x) == y) ==(x::Unsigned, y::Signed ) = (y >= 0) & (x == unsigned(y)) @@ -380,11 +380,11 @@ isdefined(Main, :Base) && for fname in (:mod, :rem) """ -> $fname(x::Integer, T::Type{<:Integer}) end -rem{T<:Integer}(x::T, ::Type{T}) = x +rem(x::T, ::Type{T}) where {T<:Integer} = x rem(x::Integer, ::Type{Bool}) = ((x & 1) != 0) -mod{T<:Integer}(x::Integer, ::Type{T}) = rem(x, T) +mod(x::Integer, ::Type{T}) where {T<:Integer} = rem(x, T) -unsafe_trunc{T<:Integer}(::Type{T}, x::Integer) = rem(x, T) +unsafe_trunc(::Type{T}, x::Integer) where {T<:Integer} = rem(x, T) for (Ts, Tu) in ((Int8, UInt8), (Int16, UInt16), (Int32, UInt32), (Int64, UInt64), (Int128, UInt128)) @eval convert(::Type{Signed}, x::$Tu) = convert($Ts, x) @eval convert(::Type{Unsigned}, x::$Ts) = convert($Tu, x) @@ -401,10 +401,10 @@ trunc(x::Integer) = x floor(x::Integer) = x ceil(x::Integer) = x -round{T<:Integer}(::Type{T}, x::Integer) = convert(T, x) -trunc{T<:Integer}(::Type{T}, x::Integer) = convert(T, x) -floor{T<:Integer}(::Type{T}, x::Integer) = convert(T, x) - ceil{T<:Integer}(::Type{T}, x::Integer) = convert(T, x) +round(::Type{T}, x::Integer) where {T<:Integer} = convert(T, x) +trunc(::Type{T}, x::Integer) where {T<:Integer} = convert(T, x) +floor(::Type{T}, x::Integer) where {T<:Integer} = convert(T, x) + ceil(::Type{T}, x::Integer) where {T<:Integer} = convert(T, x) ## integer construction ## @@ -564,7 +564,7 @@ if Core.sizeof(Int) == 4 return Int128(mod(BigInt(x), BigInt(y))) end else - *{T<:Union{Int128,UInt128}}(x::T, y::T) = mul_int(x, y) + *(x::T, y::T) where {T<:Union{Int128,UInt128}} = mul_int(x, y) div(x::Int128, y::Int128) = checked_sdiv_int(x, y) div(x::UInt128, y::UInt128) = checked_udiv_int(x, y) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 53b46e4f1ff5e..48de70ca99ac4 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -15,7 +15,7 @@ julia> gcd(6,-9) 3 ``` """ -function gcd{T<:Integer}(a::T, b::T) +function gcd(a::T, b::T) where T<:Integer while b != 0 t = b b = rem(a, b) @@ -26,7 +26,7 @@ end # binary GCD (aka Stein's) algorithm # about 1.7x (2.1x) faster for random Int64s (Int128s) -function gcd{T<:Union{Int64,UInt64,Int128,UInt128}}(a::T, b::T) +function gcd(a::T, b::T) where T<:Union{Int64,UInt64,Int128,UInt128} a == 0 && return abs(b) b == 0 && return abs(a) za = trailing_zeros(a) @@ -59,7 +59,7 @@ julia> lcm(-2,3) 6 ``` """ -function lcm{T<:Integer}(a::T, b::T) +function lcm(a::T, b::T) where T<:Integer # explicit a==0 test is to handle case of lcm(0,0) correctly if a == 0 return a @@ -107,7 +107,7 @@ julia> gcdx(240, 46) their `typemax`, and the identity then holds only via the unsigned integers' modulo arithmetic. """ -function gcdx{T<:Integer}(a::T, b::T) +function gcdx(a::T, b::T) where T<:Integer # a0, b0 = a, b s0, s1 = oneunit(T), zero(T) t0, t1 = s1, s0 @@ -142,7 +142,7 @@ julia> invmod(5,6) 5 ``` """ -function invmod{T<:Integer}(n::T, m::T) +function invmod(n::T, m::T) where T<:Integer g, x, y = gcdx(n, m) (g != 1 || m == 0) && throw(DomainError()) # Note that m might be negative here. @@ -191,7 +191,7 @@ function power_by_squaring(x::Bool, p::Integer) return (p==0) | x end -^{T<:Integer}(x::T, p::T) = power_by_squaring(x,p) +^(x::T, p::T) where {T<:Integer} = power_by_squaring(x,p) ^(x::Number, p::Integer) = power_by_squaring(x,p) ^(x, p::Integer) = power_by_squaring(x,p) @@ -202,7 +202,7 @@ end # We mark these @inline since if the target is marked @inline, # we want to make sure that gets propagated, # even if it is over the inlining threshold. -@inline literal_pow{p}(f, x, ::Type{Val{p}}) = f(x,p) +@inline literal_pow(f, x, ::Type{Val{p}}) where {p} = f(x,p) # Restrict inlining to hardware-supported arithmetic types, which # are fast enough to benefit from inlining. @@ -225,7 +225,7 @@ const HWNumber = Union{HWReal, Complex{<:HWReal}, Rational{<:HWReal}} Compute ``x^p \\pmod m``. """ -function powermod{T<:Integer}(x::Integer, p::Integer, m::T) +function powermod(x::Integer, p::Integer, m::T) where T<:Integer p < 0 && return powermod(invmod(x, m), -p, m) p == 0 && return mod(one(m),m) (m == 1 || m == -1) && return zero(m) @@ -542,9 +542,9 @@ Returns an array with element type `T` (default `Int`) of the digits of `n` in t base, optionally padded with zeros to a specified size. More significant digits are at higher indexes, such that `n == sum([digits[k]*base^(k-1) for k=1:length(digits)])`. """ -digits{T<:Integer}(n::Integer, base::T=10, pad::Integer=1) = digits(T, n, base, pad) +digits(n::Integer, base::T=10, pad::Integer=1) where {T<:Integer} = digits(T, n, base, pad) -function digits{T<:Integer}(::Type{T}, n::Integer, base::Integer=10, pad::Integer=1) +function digits(::Type{T}, n::Integer, base::Integer=10, pad::Integer=1) where T<:Integer 2 <= base || throw(ArgumentError("base must be ≥ 2, got $base")) digits!(zeros(T, max(pad, ndigits0z(n,base))), n, base) end @@ -556,7 +556,7 @@ Fills an array of the digits of `n` in the given base. More significant digits a indexes. If the array length is insufficient, the least significant digits are filled up to the array length. If the array length is excessive, the excess portion is filled with zeros. """ -function digits!{T<:Integer}(a::AbstractArray{T,1}, n::Integer, base::Integer=10) +function digits!(a::AbstractArray{T,1}, n::Integer, base::Integer=10) where T<:Integer 2 <= base || throw(ArgumentError("base must be ≥ 2, got $base")) base - 1 <= typemax(T) || throw(ArgumentError("type $T too small for base $base")) for i in eachindex(a) @@ -602,7 +602,7 @@ end Number of ways to choose `k` out of `n` items. """ -function binomial{T<:Integer}(n::T, k::T) +function binomial(n::T, k::T) where T<:Integer k < 0 && return zero(T) sgn = one(T) if n < 0 diff --git a/base/iobuffer.jl b/base/iobuffer.jl index dd061652a3785..496977a0faee0 100644 --- a/base/iobuffer.jl +++ b/base/iobuffer.jl @@ -107,7 +107,7 @@ function unsafe_read(from::AbstractIOBuffer, p::Ptr{UInt8}, nb::UInt) nothing end -function read_sub{T}(from::AbstractIOBuffer, a::AbstractArray{T}, offs, nel) +function read_sub(from::AbstractIOBuffer, a::AbstractArray{T}, offs, nel) where T from.readable || throw(ArgumentError("read failed, IOBuffer is not readable")) if offs+nel-1 > length(a) || offs < 1 || nel < 0 throw(BoundsError()) diff --git a/base/irrationals.jl b/base/irrationals.jl index f02be49e83524..c9fd585e79f94 100644 --- a/base/irrationals.jl +++ b/base/irrationals.jl @@ -4,18 +4,18 @@ struct Irrational{sym} <: Real end -show{sym}(io::IO, x::Irrational{sym}) = print(io, "$sym = $(string(float(x))[1:15])...") +show(io::IO, x::Irrational{sym}) where {sym} = print(io, "$sym = $(string(float(x))[1:15])...") promote_rule(::Type{<:Irrational}, ::Type{Float16}) = Float16 promote_rule(::Type{<:Irrational}, ::Type{Float32}) = Float32 promote_rule(::Type{<:Irrational}, ::Type{<:Irrational}) = Float64 -promote_rule{T<:Number}(::Type{<:Irrational}, ::Type{T}) = promote_type(Float64, T) +promote_rule(::Type{<:Irrational}, ::Type{T}) where {T<:Number} = promote_type(Float64, T) convert(::Type{AbstractFloat}, x::Irrational) = Float64(x) convert(::Type{Float16}, x::Irrational) = Float16(Float32(x)) convert(::Type{Complex{T}}, x::Irrational) where {T<:Real} = convert(Complex{T}, convert(T,x)) -@pure function convert{T<:Integer}(::Type{Rational{T}}, x::Irrational) +@pure function convert(::Type{Rational{T}}, x::Irrational) where T<:Integer o = precision(BigFloat) p = 256 while true @@ -31,13 +31,13 @@ convert(::Type{Complex{T}}, x::Irrational) where {T<:Real} = convert(Complex{T}, end convert(::Type{Rational{BigInt}}, x::Irrational) = throw(ArgumentError("Cannot convert an Irrational to a Rational{BigInt}: use rationalize(Rational{BigInt}, x) instead")) -@pure function (t::Type{T}){T<:Union{Float32,Float64}}(x::Irrational, r::RoundingMode) +@pure function (t::Type{T})(x::Irrational, r::RoundingMode) where T<:Union{Float32,Float64} setprecision(BigFloat, 256) do T(BigFloat(x), r) end end -=={s}(::Irrational{s}, ::Irrational{s}) = true +==(::Irrational{s}, ::Irrational{s}) where {s} = true ==(::Irrational, ::Irrational) = false # Irrationals, by definition, can't have a finite representation equal them exactly @@ -62,7 +62,7 @@ end <=(x::AbstractFloat, y::Irrational) = x < y # Irrational vs Rational -@pure function rationalize{T<:Integer}(::Type{T}, x::Irrational; tol::Real=0) +@pure function rationalize(::Type{T}, x::Irrational; tol::Real=0) where T return rationalize(T, big(x), tol=tol) end @pure function lessrational(rx::Rational{<:Integer}, x::Irrational) @@ -70,7 +70,7 @@ end # an irrational number required rounding up or down return rx < big(x) end -function <{T}(x::Irrational, y::Rational{T}) +function <(x::Irrational, y::Rational{T}) where T T <: Unsigned && x < 0.0 && return true rx = rationalize(T, x) if lessrational(rx, x) @@ -79,7 +79,7 @@ function <{T}(x::Irrational, y::Rational{T}) return rx <= y end end -function <{T}(x::Rational{T}, y::Irrational) +function <(x::Rational{T}, y::Irrational) where T T <: Unsigned && y < 0.0 && return false ry = rationalize(T, y) if lessrational(ry, y) diff --git a/base/iterators.jl b/base/iterators.jl index e9c2426079ff8..08fc609ced843 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -23,7 +23,7 @@ and_iteratorsize(::HasLength, ::HasShape) = HasLength() and_iteratorsize(::HasShape, ::HasLength) = HasLength() and_iteratorsize(a, b) = SizeUnknown() -and_iteratoreltype{T}(iel::T, ::T) = iel +and_iteratoreltype(iel::T, ::T) where {T} = iel and_iteratoreltype(a, b) = EltypeUnknown() # enumerate @@ -67,8 +67,8 @@ end eltype(::Type{Enumerate{I}}) where {I} = Tuple{Int, eltype(I)} -iteratorsize{I}(::Type{Enumerate{I}}) = iteratorsize(I) -iteratoreltype{I}(::Type{Enumerate{I}}) = iteratoreltype(I) +iteratorsize(::Type{Enumerate{I}}) where {I} = iteratorsize(I) +iteratoreltype(::Type{Enumerate{I}}) where {I} = iteratoreltype(I) struct IndexValue{I,A<:AbstractArray} data::A @@ -137,8 +137,8 @@ end eltype(::Type{IndexValue{I,A}}) where {I,A} = Tuple{eltype(I), eltype(A)} -iteratorsize{I}(::Type{IndexValue{I}}) = iteratorsize(I) -iteratoreltype{I}(::Type{IndexValue{I}}) = iteratoreltype(I) +iteratorsize(::Type{IndexValue{I}}) where {I} = iteratorsize(I) +iteratoreltype(::Type{IndexValue{I}}) where {I} = iteratoreltype(I) # zip @@ -166,8 +166,8 @@ eltype(::Type{Zip1{I}}) where {I} = Tuple{eltype(I)} end @inline done(z::Zip1, st) = done(z.a,st) -iteratorsize{I}(::Type{Zip1{I}}) = iteratorsize(I) -iteratoreltype{I}(::Type{Zip1{I}}) = iteratoreltype(I) +iteratorsize(::Type{Zip1{I}}) where {I} = iteratorsize(I) +iteratoreltype(::Type{Zip1{I}}) where {I} = iteratoreltype(I) struct Zip2{I1, I2} <: AbstractZipIterator a::I1 @@ -186,8 +186,8 @@ eltype(::Type{Zip2{I1,I2}}) where {I1,I2} = Tuple{eltype(I1), eltype(I2)} end @inline done(z::Zip2, st) = done(z.a,st[1]) | done(z.b,st[2]) -iteratorsize{I1,I2}(::Type{Zip2{I1,I2}}) = zip_iteratorsize(iteratorsize(I1),iteratorsize(I2)) -iteratoreltype{I1,I2}(::Type{Zip2{I1,I2}}) = and_iteratoreltype(iteratoreltype(I1),iteratoreltype(I2)) +iteratorsize(::Type{Zip2{I1,I2}}) where {I1,I2} = zip_iteratorsize(iteratorsize(I1),iteratorsize(I2)) +iteratoreltype(::Type{Zip2{I1,I2}}) where {I1,I2} = and_iteratoreltype(iteratoreltype(I1),iteratoreltype(I2)) struct Zip{I, Z<:AbstractZipIterator} <: AbstractZipIterator a::I @@ -237,8 +237,8 @@ eltype(::Type{Zip{I,Z}}) where {I,Z} = tuple_type_cons(eltype(I), eltype(Z)) end @inline done(z::Zip, st) = done(z.a,st[1]) | done(z.z,st[2]) -iteratorsize{I1,I2}(::Type{Zip{I1,I2}}) = zip_iteratorsize(iteratorsize(I1),iteratorsize(I2)) -iteratoreltype{I1,I2}(::Type{Zip{I1,I2}}) = and_iteratoreltype(iteratoreltype(I1),iteratoreltype(I2)) +iteratorsize(::Type{Zip{I1,I2}}) where {I1,I2} = zip_iteratorsize(iteratorsize(I1),iteratorsize(I2)) +iteratoreltype(::Type{Zip{I1,I2}}) where {I1,I2} = and_iteratoreltype(iteratoreltype(I1),iteratoreltype(I2)) # filter @@ -278,7 +278,7 @@ end done(f::Filter, s) = s[1] eltype(::Type{Filter{F,I}}) where {F,I} = eltype(I) -iteratoreltype{F,I}(::Type{Filter{F,I}}) = iteratoreltype(I) +iteratoreltype(::Type{Filter{F,I}}) where {F,I} = iteratoreltype(I) iteratorsize(::Type{<:Filter}) = SizeUnknown() # Rest -- iterate starting at the given state @@ -300,10 +300,10 @@ next(i::Rest, st) = next(i.itr, st) done(i::Rest, st) = done(i.itr, st) eltype(::Type{Rest{I}}) where {I} = eltype(I) -iteratoreltype{I,S}(::Type{Rest{I,S}}) = iteratoreltype(I) +iteratoreltype(::Type{Rest{I,S}}) where {I,S} = iteratoreltype(I) rest_iteratorsize(a) = SizeUnknown() rest_iteratorsize(::IsInfinite) = IsInfinite() -iteratorsize{I,S}(::Type{Rest{I,S}}) = rest_iteratorsize(iteratorsize(I)) +iteratorsize(::Type{Rest{I,S}}) where {I,S} = rest_iteratorsize(iteratorsize(I)) # Count -- infinite counting @@ -366,10 +366,10 @@ take(xs, n::Integer) = Take(xs, Int(n)) take(xs::Take, n::Integer) = Take(xs.xs, min(Int(n), xs.n)) eltype(::Type{Take{I}}) where {I} = eltype(I) -iteratoreltype{I}(::Type{Take{I}}) = iteratoreltype(I) +iteratoreltype(::Type{Take{I}}) where {I} = iteratoreltype(I) take_iteratorsize(a) = HasLength() take_iteratorsize(::SizeUnknown) = SizeUnknown() -iteratorsize{I}(::Type{Take{I}}) = take_iteratorsize(iteratorsize(I)) +iteratorsize(::Type{Take{I}}) where {I} = take_iteratorsize(iteratorsize(I)) length(t::Take) = _min_length(t.xs, 1:t.n, iteratorsize(t.xs), HasLength()) start(it::Take) = (it.n, start(it.xs)) @@ -421,11 +421,11 @@ drop(xs::Take, n::Integer) = Take(drop(xs.xs, Int(n)), max(0, xs.n - Int(n))) drop(xs::Drop, n::Integer) = Drop(xs.xs, Int(n) + xs.n) eltype(::Type{Drop{I}}) where {I} = eltype(I) -iteratoreltype{I}(::Type{Drop{I}}) = iteratoreltype(I) +iteratoreltype(::Type{Drop{I}}) where {I} = iteratoreltype(I) drop_iteratorsize(::SizeUnknown) = SizeUnknown() drop_iteratorsize(::Union{HasShape, HasLength}) = HasLength() drop_iteratorsize(::IsInfinite) = IsInfinite() -iteratorsize{I}(::Type{Drop{I}}) = drop_iteratorsize(iteratorsize(I)) +iteratorsize(::Type{Drop{I}}) where {I} = drop_iteratorsize(iteratorsize(I)) length(d::Drop) = _diff_length(d.xs, 1:d.n, iteratorsize(d.xs), HasLength()) function start(it::Drop) @@ -457,8 +457,8 @@ An iterator that cycles through `iter` forever. cycle(xs) = Cycle(xs) eltype(::Type{Cycle{I}}) where {I} = eltype(I) -iteratoreltype{I}(::Type{Cycle{I}}) = iteratoreltype(I) -iteratorsize{I}(::Type{Cycle{I}}) = IsInfinite() +iteratoreltype(::Type{Cycle{I}}) where {I} = iteratoreltype(I) +iteratorsize(::Type{Cycle{I}}) where {I} = IsInfinite() function start(it::Cycle) s = start(it.xs) @@ -563,8 +563,8 @@ indices(p::Prod1) = _prod_indices(p.a, iteratorsize(p.a)) end @inline done(p::Prod1, st) = done(p.a, st) -iteratoreltype{I}(::Type{Prod1{I}}) = iteratoreltype(I) -iteratorsize{I}(::Type{Prod1{I}}) = iteratorsize(I) +iteratoreltype(::Type{Prod1{I}}) where {I} = iteratoreltype(I) +iteratorsize(::Type{Prod1{I}}) where {I} = iteratorsize(I) # two iterators struct Prod2{I1, I2} <: AbstractProdIterator @@ -590,8 +590,8 @@ product(a, b) = Prod2(a, b) eltype(::Type{Prod2{I1,I2}}) where {I1,I2} = Tuple{eltype(I1), eltype(I2)} -iteratoreltype{I1,I2}(::Type{Prod2{I1,I2}}) = and_iteratoreltype(iteratoreltype(I1),iteratoreltype(I2)) -iteratorsize{I1,I2}(::Type{Prod2{I1,I2}}) = prod_iteratorsize(iteratorsize(I1),iteratorsize(I2)) +iteratoreltype(::Type{Prod2{I1,I2}}) where {I1,I2} = and_iteratoreltype(iteratoreltype(I1),iteratoreltype(I2)) +iteratorsize(::Type{Prod2{I1,I2}}) where {I1,I2} = prod_iteratorsize(iteratorsize(I1),iteratorsize(I2)) function start(p::AbstractProdIterator) s1, s2 = start(p.a), start(p.b) @@ -627,8 +627,8 @@ product(a, b, c...) = Prod(a, product(b, c...)) eltype(::Type{Prod{I1,I2}}) where {I1,I2} = tuple_type_cons(eltype(I1), eltype(I2)) -iteratoreltype{I1,I2}(::Type{Prod{I1,I2}}) = and_iteratoreltype(iteratoreltype(I1),iteratoreltype(I2)) -iteratorsize{I1,I2}(::Type{Prod{I1,I2}}) = prod_iteratorsize(iteratorsize(I1),iteratorsize(I2)) +iteratoreltype(::Type{Prod{I1,I2}}) where {I1,I2} = and_iteratoreltype(iteratoreltype(I1),iteratoreltype(I2)) +iteratorsize(::Type{Prod{I1,I2}}) where {I1,I2} = prod_iteratorsize(iteratorsize(I1),iteratorsize(I2)) @inline function next{I1,I2}(p::Prod{I1,I2}, st) x = prod_next(p, st) @@ -668,8 +668,8 @@ julia> collect(Iterators.flatten((1:2, 8:9))) flatten(itr) = Flatten(itr) eltype(::Type{Flatten{I}}) where {I} = eltype(eltype(I)) -iteratorsize{I}(::Type{Flatten{I}}) = SizeUnknown() -iteratoreltype{I}(::Type{Flatten{I}}) = _flatteneltype(I, iteratoreltype(I)) +iteratorsize(::Type{Flatten{I}}) where {I} = SizeUnknown() +iteratoreltype(::Type{Flatten{I}}) where {I} = _flatteneltype(I, iteratoreltype(I)) _flatteneltype(I, ::HasEltype) = iteratoreltype(eltype(I)) _flatteneltype(I, et) = EltypeUnknown() @@ -717,7 +717,7 @@ julia> collect(Iterators.partition([1,2,3,4,5], 2)) [5] ``` """ -partition{T}(c::T, n::Integer) = PartitionIterator{T}(c, Int(n)) +partition(c::T, n::Integer) where {T} = PartitionIterator{T}(c, Int(n)) mutable struct PartitionIterator{T} diff --git a/base/libgit2/config.jl b/base/libgit2/config.jl index 7c01664042cc4..dcb4045c797e9 100644 --- a/base/libgit2/config.jl +++ b/base/libgit2/config.jl @@ -82,7 +82,7 @@ function get(::Type{Int64}, c::GitConfig, name::AbstractString) return val_ptr[] end -function get{T}(c::GitConfig, name::AbstractString, default::T) +function get(c::GitConfig, name::AbstractString, default::T) where T res = default try res = get(T,c,name) end return res diff --git a/base/linalg/arnoldi.jl b/base/linalg/arnoldi.jl index 935d6fd79ea2a..e01e3ff31987f 100644 --- a/base/linalg/arnoldi.jl +++ b/base/linalg/arnoldi.jl @@ -315,7 +315,7 @@ function SVDOperator(A::AbstractMatrix{T}) where T SVDOperator{Tnew,typeof(Anew)}(Anew) end -function A_mul_B!{T}(u::StridedVector{T}, s::SVDOperator{T}, v::StridedVector{T}) +function A_mul_B!(u::StridedVector{T}, s::SVDOperator{T}, v::StridedVector{T}) where T a, b = s.m, length(v) A_mul_B!(view(u,1:a), s.X, view(v,a+1:b)) # left singular vector Ac_mul_B!(view(u,a+1:b), s.X, view(v,1:a)) # right singular vector diff --git a/base/linalg/bidiag.jl b/base/linalg/bidiag.jl index ae566dda9a5c1..9448bec2dee09 100644 --- a/base/linalg/bidiag.jl +++ b/base/linalg/bidiag.jl @@ -144,7 +144,7 @@ julia> Bidiagonal(A, false) #contains the main diagonal and first subdiagonal of """ Bidiagonal(A::AbstractMatrix, isupper::Bool)=Bidiagonal(diag(A), diag(A, isupper?1:-1), isupper) -function getindex{T}(A::Bidiagonal{T}, i::Integer, j::Integer) +function getindex(A::Bidiagonal{T}, i::Integer, j::Integer) where T if !((1 <= i <= size(A,2)) && (1 <= j <= size(A,2))) throw(BoundsError(A,(i,j))) end @@ -182,7 +182,7 @@ function Base.replace_in_print_matrix(A::Bidiagonal,i::Integer,j::Integer,s::Abs end #Converting from Bidiagonal to dense Matrix -function convert{T}(::Type{Matrix{T}}, A::Bidiagonal) +function convert(::Type{Matrix{T}}, A::Bidiagonal) where T n = size(A, 1) B = zeros(T, n, n) for i = 1:n - 1 @@ -196,29 +196,29 @@ function convert{T}(::Type{Matrix{T}}, A::Bidiagonal) B[n,n] = A.dv[n] return B end -convert{T}(::Type{Matrix}, A::Bidiagonal{T}) = convert(Matrix{T}, A) +convert(::Type{Matrix}, A::Bidiagonal{T}) where {T} = convert(Matrix{T}, A) convert(::Type{Array}, A::Bidiagonal) = convert(Matrix, A) full(A::Bidiagonal) = convert(Array, A) -promote_rule{T,S}(::Type{Matrix{T}}, ::Type{Bidiagonal{S}})=Matrix{promote_type(T,S)} +promote_rule(::Type{Matrix{T}}, ::Type{Bidiagonal{S}}) where {T,S} = Matrix{promote_type(T,S)} #Converting from Bidiagonal to Tridiagonal Tridiagonal(M::Bidiagonal{T}) where {T} = convert(Tridiagonal{T}, M) -function convert{T}(::Type{Tridiagonal{T}}, A::Bidiagonal) +function convert(::Type{Tridiagonal{T}}, A::Bidiagonal) where T z = zeros(T, size(A)[1]-1) A.isupper ? Tridiagonal(z, convert(Vector{T},A.dv), convert(Vector{T},A.ev)) : Tridiagonal(convert(Vector{T},A.ev), convert(Vector{T},A.dv), z) end -promote_rule{T,S}(::Type{Tridiagonal{T}}, ::Type{Bidiagonal{S}})=Tridiagonal{promote_type(T,S)} +promote_rule(::Type{Tridiagonal{T}}, ::Type{Bidiagonal{S}}) where {T,S} = Tridiagonal{promote_type(T,S)} # No-op for trivial conversion Bidiagonal{T} -> Bidiagonal{T} -convert{T}(::Type{Bidiagonal{T}}, A::Bidiagonal{T}) = A +convert(::Type{Bidiagonal{T}}, A::Bidiagonal{T}) where {T} = A # Convert Bidiagonal to Bidiagonal{T} by constructing a new instance with converted elements -convert{T}(::Type{Bidiagonal{T}}, A::Bidiagonal) = Bidiagonal(convert(Vector{T}, A.dv), convert(Vector{T}, A.ev), A.isupper) +convert(::Type{Bidiagonal{T}}, A::Bidiagonal) where {T} = Bidiagonal(convert(Vector{T}, A.dv), convert(Vector{T}, A.ev), A.isupper) # When asked to convert Bidiagonal to AbstractMatrix{T}, preserve structure by converting to Bidiagonal{T} <: AbstractMatrix{T} -convert{T}(::Type{AbstractMatrix{T}}, A::Bidiagonal) = convert(Bidiagonal{T}, A) +convert(::Type{AbstractMatrix{T}}, A::Bidiagonal) where {T} = convert(Bidiagonal{T}, A) broadcast(::typeof(big), B::Bidiagonal) = Bidiagonal(big.(B.dv), big.(B.ev), B.isupper) -similar{T}(B::Bidiagonal, ::Type{T}) = Bidiagonal{T}(similar(B.dv, T), similar(B.ev, T), B.isupper) +similar(B::Bidiagonal, ::Type{T}) where {T} = Bidiagonal{T}(similar(B.dv, T), similar(B.ev, T), B.isupper) ################### # LAPACK routines # @@ -327,7 +327,7 @@ function diag{T}(M::Bidiagonal{T}, n::Integer=0) end function +(A::Bidiagonal, B::Bidiagonal) - if A.isupper==B.isupper + if A.isupper == B.isupper Bidiagonal(A.dv+B.dv, A.ev+B.ev, A.isupper) else Tridiagonal((A.isupper ? (B.ev,A.dv+B.dv,A.ev) : (A.ev,A.dv+B.dv,B.ev))...) @@ -335,7 +335,7 @@ function +(A::Bidiagonal, B::Bidiagonal) end function -(A::Bidiagonal, B::Bidiagonal) - if A.isupper==B.isupper + if A.isupper == B.isupper Bidiagonal(A.dv-B.dv, A.ev-B.ev, A.isupper) else Tridiagonal((A.isupper ? (-B.ev,A.dv-B.dv,A.ev) : (A.ev,A.dv-B.dv,-B.ev))...) @@ -373,11 +373,11 @@ function check_A_mul_B!_sizes(C, A, B) nA, mA = size(A) nB, mB = size(B) nC, mC = size(C) - if !(nA == nC) + if nA != nC throw(DimensionMismatch("sizes size(A)=$(size(A)) and size(C) = $(size(C)) must match at first entry.")) - elseif !(mA == nB) + elseif mA != nB throw(DimensionMismatch("second entry of size(A)=$(size(A)) and first entry of size(B) = $(size(B)) must match.")) - elseif !(mB == mC) + elseif mB != mC throw(DimensionMismatch("sizes size(B)=$(size(B)) and size(C) = $(size(C)) must match at first second entry.")) end end diff --git a/base/linalg/bunchkaufman.jl b/base/linalg/bunchkaufman.jl index 8d6cbf8f32a21..5c52e6441dba6 100644 --- a/base/linalg/bunchkaufman.jl +++ b/base/linalg/bunchkaufman.jl @@ -77,11 +77,11 @@ bkfact{T}(A::StridedMatrix{T}, uplo::Symbol=:U, symmetric::Bool=issymmetric(A), bkfact!(convert(Matrix{promote_type(Float32, typeof(sqrt(one(T))))}, A), uplo, symmetric, rook) -convert{T}(::Type{BunchKaufman{T}}, B::BunchKaufman{T}) = B -convert{T}(::Type{BunchKaufman{T}}, B::BunchKaufman) = +convert(::Type{BunchKaufman{T}}, B::BunchKaufman{T}) where {T} = B +convert(::Type{BunchKaufman{T}}, B::BunchKaufman) where {T} = BunchKaufman(convert(Matrix{T}, B.LD), B.ipiv, B.uplo, B.symmetric, B.rook, B.info) -convert{T}(::Type{Factorization{T}}, B::BunchKaufman{T}) = B -convert{T}(::Type{Factorization{T}}, B::BunchKaufman) = convert(BunchKaufman{T}, B) +convert(::Type{Factorization{T}}, B::BunchKaufman{T}) where {T} = B +convert(::Type{Factorization{T}}, B::BunchKaufman) where {T} = convert(BunchKaufman{T}, B) size(B::BunchKaufman) = size(B.LD) size(B::BunchKaufman, d::Integer) = size(B.LD, d) diff --git a/base/linalg/cholesky.jl b/base/linalg/cholesky.jl index 5e4bdfd199b03..e9fb53b556023 100644 --- a/base/linalg/cholesky.jl +++ b/base/linalg/cholesky.jl @@ -386,17 +386,17 @@ function cholfact(x::Number, uplo::Symbol=:U) end -function convert{T}(::Type{Cholesky{T}}, C::Cholesky) +function convert(::Type{Cholesky{T}}, C::Cholesky) where T Cnew = convert(AbstractMatrix{T}, C.factors) Cholesky{T, typeof(Cnew)}(Cnew, C.uplo) end -convert{T}(::Type{Factorization{T}}, C::Cholesky{T}) = C -convert{T}(::Type{Factorization{T}}, C::Cholesky) = convert(Cholesky{T}, C) -convert{T}(::Type{CholeskyPivoted{T}},C::CholeskyPivoted{T}) = C -convert{T}(::Type{CholeskyPivoted{T}},C::CholeskyPivoted) = +convert(::Type{Factorization{T}}, C::Cholesky{T}) where {T} = C +convert(::Type{Factorization{T}}, C::Cholesky) where {T} = convert(Cholesky{T}, C) +convert(::Type{CholeskyPivoted{T}},C::CholeskyPivoted{T}) where {T} = C +convert(::Type{CholeskyPivoted{T}},C::CholeskyPivoted) where {T} = CholeskyPivoted(AbstractMatrix{T}(C.factors),C.uplo,C.piv,C.rank,C.tol,C.info) -convert{T}(::Type{Factorization{T}}, C::CholeskyPivoted{T}) = C -convert{T}(::Type{Factorization{T}}, C::CholeskyPivoted) = convert(CholeskyPivoted{T}, C) +convert(::Type{Factorization{T}}, C::CholeskyPivoted{T}) where {T} = C +convert(::Type{Factorization{T}}, C::CholeskyPivoted) where {T} = convert(CholeskyPivoted{T}, C) convert(::Type{AbstractMatrix}, C::Cholesky) = C.uplo == 'U' ? C[:U]'C[:U] : C[:L]*C[:L]' convert(::Type{AbstractArray}, C::Cholesky) = convert(AbstractMatrix, C) @@ -425,7 +425,7 @@ function getindex(C::Cholesky, d::Symbol) d == :UL && return Symbol(C.uplo) == :U ? UpperTriangular(C.factors) : LowerTriangular(C.factors) throw(KeyError(d)) end -function getindex{T<:BlasFloat}(C::CholeskyPivoted{T}, d::Symbol) +function getindex(C::CholeskyPivoted{T}, d::Symbol) where T<:BlasFloat d == :U && return UpperTriangular(Symbol(C.uplo) == d ? C.factors : C.factors') d == :L && return LowerTriangular(Symbol(C.uplo) == d ? C.factors : C.factors') d == :p && return C.piv diff --git a/base/linalg/diagonal.jl b/base/linalg/diagonal.jl index 421328e9a1044..c52ef944d96b4 100644 --- a/base/linalg/diagonal.jl +++ b/base/linalg/diagonal.jl @@ -48,14 +48,14 @@ julia> Diagonal(V) """ Diagonal(V::AbstractVector) = Diagonal(collect(V)) -convert{T}(::Type{Diagonal{T}}, D::Diagonal{T}) = D -convert{T}(::Type{Diagonal{T}}, D::Diagonal) = Diagonal{T}(convert(Vector{T}, D.diag)) -convert{T}(::Type{AbstractMatrix{T}}, D::Diagonal) = convert(Diagonal{T}, D) +convert(::Type{Diagonal{T}}, D::Diagonal{T}) where {T} = D +convert(::Type{Diagonal{T}}, D::Diagonal) where {T} = Diagonal{T}(convert(Vector{T}, D.diag)) +convert(::Type{AbstractMatrix{T}}, D::Diagonal) where {T} = convert(Diagonal{T}, D) convert(::Type{Matrix}, D::Diagonal) = diagm(D.diag) convert(::Type{Array}, D::Diagonal) = convert(Matrix, D) full(D::Diagonal) = convert(Array, D) -function similar{T}(D::Diagonal, ::Type{T}) +function similar(D::Diagonal, ::Type{T}) where T return Diagonal{T}(similar(D.diag, T)) end @@ -79,8 +79,8 @@ end end r end -diagzero{T}(::Diagonal{T},i,j) = zero(T) -diagzero{T}(D::Diagonal{Matrix{T}},i,j) = zeros(T, size(D.diag[i], 1), size(D.diag[j], 2)) +diagzero(::Diagonal{T},i,j) where {T} = zero(T) +diagzero(D::Diagonal{Matrix{T}},i,j) where {T} = zeros(T, size(D.diag[i], 1), size(D.diag[j], 2)) function setindex!(D::Diagonal, v, i::Int, j::Int) @boundscheck checkbounds(D, i, j) @@ -286,7 +286,7 @@ function logdet(D::Diagonal{<:Complex}) # make sure branch cut is correct complex(real(z), rem2pi(imag(z), RoundNearest)) end # identity matrices via eye(Diagonal{type},n) -eye{T}(::Type{Diagonal{T}}, n::Int) = Diagonal(ones(T,n)) +eye(::Type{Diagonal{T}}, n::Int) where {T} = Diagonal(ones(T,n)) expm(D::Diagonal) = Diagonal(exp.(D.diag)) expm(D::Diagonal{<:AbstractMatrix}) = Diagonal(expm.(D.diag)) diff --git a/base/linalg/factorization.jl b/base/linalg/factorization.jl index 7a3a2d881fc61..d160f2c3cd839 100644 --- a/base/linalg/factorization.jl +++ b/base/linalg/factorization.jl @@ -4,7 +4,7 @@ abstract type Factorization{T} end -eltype{T}(::Type{Factorization{T}}) = T +eltype(::Type{Factorization{T}}) where {T} = T transpose(F::Factorization) = error("transpose not implemented for $(typeof(F))") ctranspose(F::Factorization) = error("ctranspose not implemented for $(typeof(F))") @@ -27,7 +27,7 @@ function det(F::Factorization) end ### General promotion rules -convert{T}(::Type{Factorization{T}}, F::Factorization{T}) = F +convert(::Type{Factorization{T}}, F::Factorization{T}) where {T} = F inv{T}(F::Factorization{T}) = A_ldiv_B!(F, eye(T, size(F,1))) # With a real lhs and complex rhs with the same precision, we can reinterpret diff --git a/base/linalg/givens.jl b/base/linalg/givens.jl index dc98cfece3bd8..f372710dc9787 100644 --- a/base/linalg/givens.jl +++ b/base/linalg/givens.jl @@ -5,11 +5,11 @@ abstract type AbstractRotation{T} end transpose(R::AbstractRotation) = error("transpose not implemented for $(typeof(R)). Consider using conjugate transpose (') instead of transpose (.').") -function *{T,S}(R::AbstractRotation{T}, A::AbstractVecOrMat{S}) +function *(R::AbstractRotation{T}, A::AbstractVecOrMat{S}) where {T,S} TS = typeof(zero(T)*zero(S) + zero(T)*zero(S)) A_mul_B!(convert(AbstractRotation{TS}, R), TS == S ? copy(A) : convert(AbstractArray{TS}, A)) end -function A_mul_Bc{T,S}(A::AbstractVecOrMat{T}, R::AbstractRotation{S}) +function A_mul_Bc(A::AbstractVecOrMat{T}, R::AbstractRotation{S}) where {T,S} TS = typeof(zero(T)*zero(S) + zero(T)*zero(S)) A_mul_Bc!(TS == T ? copy(A) : convert(AbstractArray{TS}, A), convert(AbstractRotation{TS}, R)) end @@ -34,12 +34,12 @@ mutable struct Rotation{T} <: AbstractRotation{T} rotations::Vector{Givens{T}} end -convert{T}(::Type{Givens{T}}, G::Givens{T}) = G -convert{T}(::Type{Givens{T}}, G::Givens) = Givens(G.i1, G.i2, convert(T, G.c), convert(T, G.s)) -convert{T}(::Type{Rotation{T}}, R::Rotation{T}) = R -convert{T}(::Type{Rotation{T}}, R::Rotation) = Rotation{T}([convert(Givens{T}, g) for g in R.rotations]) -convert{T}(::Type{AbstractRotation{T}}, G::Givens) = convert(Givens{T}, G) -convert{T}(::Type{AbstractRotation{T}}, R::Rotation) = convert(Rotation{T}, R) +convert(::Type{Givens{T}}, G::Givens{T}) where {T} = G +convert(::Type{Givens{T}}, G::Givens) where {T} = Givens(G.i1, G.i2, convert(T, G.c), convert(T, G.s)) +convert(::Type{Rotation{T}}, R::Rotation{T}) where {T} = R +convert(::Type{Rotation{T}}, R::Rotation) where {T} = Rotation{T}([convert(Givens{T}, g) for g in R.rotations]) +convert(::Type{AbstractRotation{T}}, G::Givens) where {T} = convert(Givens{T}, G) +convert(::Type{AbstractRotation{T}}, R::Rotation) where {T} = convert(Rotation{T}, R) ctranspose(G::Givens) = Givens(G.i1, G.i2, conj(G.c), -G.s) ctranspose{T}(R::Rotation{T}) = Rotation{T}(reverse!([ctranspose(r) for r in R.rotations])) @@ -360,4 +360,4 @@ function A_mul_Bc!(A::AbstractMatrix, R::Rotation) end return A end -*{T}(G1::Givens{T}, G2::Givens{T}) = Rotation(push!(push!(Givens{T}[], G2), G1)) +*(G1::Givens{T}, G2::Givens{T}) where {T} = Rotation(push!(push!(Givens{T}[], G2), G1)) diff --git a/base/linalg/hessenberg.jl b/base/linalg/hessenberg.jl index 87743b87c0230..658338b009d07 100644 --- a/base/linalg/hessenberg.jl +++ b/base/linalg/hessenberg.jl @@ -48,7 +48,7 @@ julia> F[:Q] * F[:H] * F[:Q]' 4.0 3.0 2.0 ``` """ -function hessfact{T}(A::StridedMatrix{T}) +function hessfact(A::StridedMatrix{T}) where T S = promote_type(Float32, typeof(zero(T)/norm(one(T)))) return hessfact!(copy_oftype(A, S)) end @@ -87,29 +87,29 @@ convert(::Type{Matrix}, F::Hessenberg) = convert(Array, convert(AbstractArray, F convert(::Type{Array}, F::Hessenberg) = convert(Matrix, F) full(F::Hessenberg) = convert(AbstractArray, F) -A_mul_B!{T<:BlasFloat}(Q::HessenbergQ{T}, X::StridedVecOrMat{T}) = +A_mul_B!(Q::HessenbergQ{T}, X::StridedVecOrMat{T}) where {T<:BlasFloat} = LAPACK.ormhr!('L', 'N', 1, size(Q.factors, 1), Q.factors, Q.τ, X) -A_mul_B!{T<:BlasFloat}(X::StridedMatrix{T}, Q::HessenbergQ{T}) = +A_mul_B!(X::StridedMatrix{T}, Q::HessenbergQ{T}) where {T<:BlasFloat} = LAPACK.ormhr!('R', 'N', 1, size(Q.factors, 1), Q.factors, Q.τ, X) -Ac_mul_B!{T<:BlasFloat}(Q::HessenbergQ{T}, X::StridedVecOrMat{T}) = +Ac_mul_B!(Q::HessenbergQ{T}, X::StridedVecOrMat{T}) where {T<:BlasFloat} = LAPACK.ormhr!('L', ifelse(T<:Real, 'T', 'C'), 1, size(Q.factors, 1), Q.factors, Q.τ, X) -A_mul_Bc!{T<:BlasFloat}(X::StridedMatrix{T}, Q::HessenbergQ{T}) = +A_mul_Bc!(X::StridedMatrix{T}, Q::HessenbergQ{T}) where {T<:BlasFloat} = LAPACK.ormhr!('R', ifelse(T<:Real, 'T', 'C'), 1, size(Q.factors, 1), Q.factors, Q.τ, X) -function (*){T,S}(Q::HessenbergQ{T}, X::StridedVecOrMat{S}) +function (*)(Q::HessenbergQ{T}, X::StridedVecOrMat{S}) where {T,S} TT = typeof(zero(T)*zero(S) + zero(T)*zero(S)) return A_mul_B!(Q, copy_oftype(X, TT)) end -function (*){T,S}(X::StridedVecOrMat{S}, Q::HessenbergQ{T}) +function (*)(X::StridedVecOrMat{S}, Q::HessenbergQ{T}) where {T,S} TT = typeof(zero(T)*zero(S) + zero(T)*zero(S)) return A_mul_B!(copy_oftype(X, TT), Q) end -function Ac_mul_B{T,S}(Q::HessenbergQ{T}, X::StridedVecOrMat{S}) +function Ac_mul_B(Q::HessenbergQ{T}, X::StridedVecOrMat{S}) where {T,S} TT = typeof(zero(T)*zero(S) + zero(T)*zero(S)) return Ac_mul_B!(Q, copy_oftype(X, TT)) end -function A_mul_Bc{T,S}(X::StridedVecOrMat{S}, Q::HessenbergQ{T}) +function A_mul_Bc(X::StridedVecOrMat{S}, Q::HessenbergQ{T}) where {T,S} TT = typeof(zero(T)*zero(S) + zero(T)*zero(S)) return A_mul_Bc!(copy_oftype(X, TT), Q) end diff --git a/base/linalg/ldlt.jl b/base/linalg/ldlt.jl index 55260cc46142e..e4d1e0c1236b8 100644 --- a/base/linalg/ldlt.jl +++ b/base/linalg/ldlt.jl @@ -7,13 +7,13 @@ end size(S::LDLt) = size(S.data) size(S::LDLt, i::Integer) = size(S.data, i) -convert{T,S}(::Type{LDLt{T,S}}, F::LDLt) = LDLt{T,S}(convert(S, F.data)) +convert(::Type{LDLt{T,S}}, F::LDLt) where {T,S} = LDLt{T,S}(convert(S, F.data)) # NOTE: the annotaion <:AbstractMatrix shouldn't be necessary, it is introduced # to avoid an ambiguity warning (see issue #6383) -convert{T,S,U<:AbstractMatrix}(::Type{LDLt{T}}, F::LDLt{S,U}) = convert(LDLt{T,U}, F) +convert(::Type{LDLt{T}}, F::LDLt{S,U}) where {T,S,U<:AbstractMatrix} = convert(LDLt{T,U}, F) -convert{T}(::Type{Factorization{T}}, F::LDLt{T}) = F -convert{T,S,U}(::Type{Factorization{T}}, F::LDLt{S,U}) = convert(LDLt{T,U}, F) +convert(::Type{Factorization{T}}, F::LDLt{T}) where {T} = F +convert(::Type{Factorization{T}}, F::LDLt{S,U}) where {T,S,U} = convert(LDLt{T,U}, F) # SymTridiagonal """ diff --git a/base/linalg/lq.jl b/base/linalg/lq.jl index 6ee36ffadde3f..42844b41294f7 100644 --- a/base/linalg/lq.jl +++ b/base/linalg/lq.jl @@ -47,9 +47,9 @@ end copy(A::LQ) = LQ(copy(A.factors), copy(A.τ)) -convert{T}(::Type{LQ{T}},A::LQ) = LQ(convert(AbstractMatrix{T}, A.factors), convert(Vector{T}, A.τ)) -convert{T}(::Type{Factorization{T}}, A::LQ{T}) = A -convert{T}(::Type{Factorization{T}}, A::LQ) = convert(LQ{T}, A) +convert(::Type{LQ{T}},A::LQ) where {T} = LQ(convert(AbstractMatrix{T}, A.factors), convert(Vector{T}, A.τ)) +convert(::Type{Factorization{T}}, A::LQ{T}) where {T} = A +convert(::Type{Factorization{T}}, A::LQ) where {T} = convert(LQ{T}, A) convert(::Type{AbstractMatrix}, A::LQ) = A[:L]*A[:Q] convert(::Type{AbstractArray}, A::LQ) = convert(AbstractMatrix, A) convert(::Type{Matrix}, A::LQ) = convert(Array, convert(AbstractArray, A)) @@ -86,8 +86,8 @@ function show(io::IO, C::LQ) show(io, C[:Q]) end -convert{T}(::Type{LQPackedQ{T}}, Q::LQPackedQ) = LQPackedQ(convert(AbstractMatrix{T}, Q.factors), convert(Vector{T}, Q.τ)) -convert{T}(::Type{AbstractMatrix{T}}, Q::LQPackedQ) = convert(LQPackedQ{T}, Q) +convert(::Type{LQPackedQ{T}}, Q::LQPackedQ) where {T} = LQPackedQ(convert(AbstractMatrix{T}, Q.factors), convert(Vector{T}, Q.τ)) +convert(::Type{AbstractMatrix{T}}, Q::LQPackedQ) where {T} = convert(LQPackedQ{T}, Q) convert(::Type{Matrix}, A::LQPackedQ) = LAPACK.orglq!(copy(A.factors),A.τ) convert(::Type{Array}, A::LQPackedQ) = convert(Matrix, A) function full{T}(A::LQPackedQ{T}; thin::Bool = true) @@ -119,33 +119,33 @@ end size(A::LQPackedQ) = size(A.factors) ## Multiplication by LQ -A_mul_B!{T<:BlasFloat}(A::LQ{T}, B::StridedVecOrMat{T}) = A[:L]*LAPACK.ormlq!('L','N',A.factors,A.τ,B) -A_mul_B!{T<:BlasFloat}(A::LQ{T}, B::QR{T}) = A[:L]*LAPACK.ormlq!('L','N',A.factors,A.τ,full(B)) -A_mul_B!{T<:BlasFloat}(A::QR{T}, B::LQ{T}) = A_mul_B!(zeros(full(A)), full(A), full(B)) -function *{TA,TB}(A::LQ{TA},B::StridedVecOrMat{TB}) +A_mul_B!(A::LQ{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = A[:L]*LAPACK.ormlq!('L','N',A.factors,A.τ,B) +A_mul_B!(A::LQ{T}, B::QR{T}) where {T<:BlasFloat} = A[:L]*LAPACK.ormlq!('L','N',A.factors,A.τ,full(B)) +A_mul_B!(A::QR{T}, B::LQ{T}) where {T<:BlasFloat} = A_mul_B!(zeros(full(A)), full(A), full(B)) +function *(A::LQ{TA},B::StridedVecOrMat{TB}) where {TA,TB} TAB = promote_type(TA, TB) A_mul_B!(convert(Factorization{TAB},A), copy_oftype(B, TAB)) end -function *{TA,TB}(A::LQ{TA},B::QR{TB}) +function *(A::LQ{TA},B::QR{TB}) where {TA,TB} TAB = promote_type(TA, TB) A_mul_B!(convert(Factorization{TAB},A), convert(Factorization{TAB},B)) end -function *{TA,TB}(A::QR{TA},B::LQ{TB}) +function *(A::QR{TA},B::LQ{TB}) where {TA,TB} TAB = promote_type(TA, TB) A_mul_B!(convert(Factorization{TAB},A), convert(Factorization{TAB},B)) end ## Multiplication by Q ### QB -A_mul_B!{T<:BlasFloat}(A::LQPackedQ{T}, B::StridedVecOrMat{T}) = LAPACK.ormlq!('L','N',A.factors,A.τ,B) +A_mul_B!(A::LQPackedQ{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = LAPACK.ormlq!('L','N',A.factors,A.τ,B) function (*)(A::LQPackedQ,B::StridedVecOrMat) TAB = promote_type(eltype(A), eltype(B)) A_mul_B!(convert(AbstractMatrix{TAB}, A), copy_oftype(B, TAB)) end ### QcB -Ac_mul_B!{T<:BlasReal}(A::LQPackedQ{T}, B::StridedVecOrMat{T}) = LAPACK.ormlq!('L','T',A.factors,A.τ,B) -Ac_mul_B!{T<:BlasComplex}(A::LQPackedQ{T}, B::StridedVecOrMat{T}) = LAPACK.ormlq!('L','C',A.factors,A.τ,B) +Ac_mul_B!(A::LQPackedQ{T}, B::StridedVecOrMat{T}) where {T<:BlasReal} = LAPACK.ormlq!('L','T',A.factors,A.τ,B) +Ac_mul_B!(A::LQPackedQ{T}, B::StridedVecOrMat{T}) where {T<:BlasComplex} = LAPACK.ormlq!('L','C',A.factors,A.τ,B) function Ac_mul_B(A::LQPackedQ, B::StridedVecOrMat) TAB = promote_type(eltype(A), eltype(B)) if size(B,1) == size(A.factors,2) @@ -171,8 +171,8 @@ for (f1, f2) in ((:A_mul_Bc, :A_mul_B!), end ### AQ -A_mul_B!{T<:BlasFloat}(A::StridedMatrix{T}, B::LQPackedQ{T}) = LAPACK.ormlq!('R', 'N', B.factors, B.τ, A) -function *{TA,TB}(A::StridedMatrix{TA},B::LQPackedQ{TB}) +A_mul_B!(A::StridedMatrix{T}, B::LQPackedQ{T}) where {T<:BlasFloat} = LAPACK.ormlq!('R', 'N', B.factors, B.τ, A) +function *(A::StridedMatrix{TA},B::LQPackedQ{TB}) where {TA,TB} TAB = promote_type(TA,TB) if size(B.factors,2) == size(A,2) A_mul_B!(copy_oftype(A, TAB),convert(AbstractMatrix{TAB},B)) @@ -184,9 +184,9 @@ function *{TA,TB}(A::StridedMatrix{TA},B::LQPackedQ{TB}) end ### AQc -A_mul_Bc!{T<:BlasReal}(A::StridedMatrix{T}, B::LQPackedQ{T}) = LAPACK.ormlq!('R','T',B.factors,B.τ,A) -A_mul_Bc!{T<:BlasComplex}(A::StridedMatrix{T}, B::LQPackedQ{T}) = LAPACK.ormlq!('R','C',B.factors,B.τ,A) -function A_mul_Bc{TA<:Number,TB<:Number}( A::StridedVecOrMat{TA}, B::LQPackedQ{TB}) +A_mul_Bc!(A::StridedMatrix{T}, B::LQPackedQ{T}) where {T<:BlasReal} = LAPACK.ormlq!('R','T',B.factors,B.τ,A) +A_mul_Bc!(A::StridedMatrix{T}, B::LQPackedQ{T}) where {T<:BlasComplex} = LAPACK.ormlq!('R','C',B.factors,B.τ,A) +function A_mul_Bc( A::StridedVecOrMat{TA}, B::LQPackedQ{TB}) where {TA<:Number,TB<:Number} TAB = promote_type(TA,TB) A_mul_Bc!(copy_oftype(A, TAB), convert(AbstractMatrix{TAB},(B))) end @@ -204,7 +204,7 @@ for (f1, f2) in ((:Ac_mul_B, :A_mul_B!), end end -function \{TA,Tb}(A::LQ{TA}, b::StridedVector{Tb}) +function (\)(A::LQ{TA}, b::StridedVector{Tb}) where {TA,Tb} S = promote_type(TA,Tb) m = checksquare(A) m == length(b) || throw(DimensionMismatch("left hand side has $m rows, but right hand side has length $(length(b))")) @@ -212,7 +212,7 @@ function \{TA,Tb}(A::LQ{TA}, b::StridedVector{Tb}) x = A_ldiv_B!(AA, copy_oftype(b, S)) return x end -function \{TA,TB}(A::LQ{TA},B::StridedMatrix{TB}) +function (\)(A::LQ{TA},B::StridedMatrix{TB}) where {TA,TB} S = promote_type(TA,TB) m = checksquare(A) m == size(B,1) || throw(DimensionMismatch("left hand side has $m rows, but right hand side has $(size(B,1)) rows")) @@ -222,7 +222,7 @@ function \{TA,TB}(A::LQ{TA},B::StridedMatrix{TB}) end # With a real lhs and complex rhs with the same precision, we can reinterpret # the complex rhs as a real rhs with twice the number of columns -function (\){T<:BlasReal}(F::LQ{T}, B::VecOrMat{Complex{T}}) +function (\)(F::LQ{T}, B::VecOrMat{Complex{T}}) where T<:BlasReal c2r = reshape(transpose(reinterpret(T, B, (2, length(B)))), size(B, 1), 2*size(B, 2)) x = A_ldiv_B!(F, c2r) return reinterpret(Complex{T}, transpose(reshape(x, div(length(x), 2), 2)), diff --git a/base/linalg/lu.jl b/base/linalg/lu.jl index ff5d3202a8130..acedcc395ad72 100644 --- a/base/linalg/lu.jl +++ b/base/linalg/lu.jl @@ -190,13 +190,13 @@ function lu(A::AbstractMatrix, pivot::Union{Type{Val{false}}, Type{Val{true}}} = F[:L], F[:U], F[:p] end -function convert{T}(::Type{LU{T}}, F::LU) +function convert(::Type{LU{T}}, F::LU) where T M = convert(AbstractMatrix{T}, F.factors) LU{T,typeof(M)}(M, F.ipiv, F.info) end -convert{T,S}(::Type{LU{T,S}}, F::LU) = LU{T,S}(convert(S, F.factors), F.ipiv, F.info) -convert{T}(::Type{Factorization{T}}, F::LU{T}) = F -convert{T}(::Type{Factorization{T}}, F::LU) = convert(LU{T}, F) +convert(::Type{LU{T,S}}, F::LU) where {T,S} = LU{T,S}(convert(S, F.factors), F.ipiv, F.info) +convert(::Type{Factorization{T}}, F::LU{T}) where {T} = F +convert(::Type{Factorization{T}}, F::LU) where {T} = convert(LU{T}, F) size(A::LU) = size(A.factors) @@ -383,7 +383,7 @@ end factorize(A::Tridiagonal) = lufact(A) -function getindex{T}(F::Base.LinAlg.LU{T,Tridiagonal{T}}, d::Symbol) +function getindex(F::Base.LinAlg.LU{T,Tridiagonal{T}}, d::Symbol) where T m, n = size(F) if d == :L L = Array(Bidiagonal(ones(T, n), F.factors.dl, false)) @@ -517,7 +517,7 @@ convert(::Type{Matrix}, F::LU) = convert(Array, convert(AbstractArray, F)) convert(::Type{Array}, F::LU) = convert(Matrix, F) full(F::LU) = convert(AbstractArray, F) -function convert{T}(::Type{Tridiagonal}, F::Base.LinAlg.LU{T,Tridiagonal{T}}) +function convert(::Type{Tridiagonal}, F::Base.LinAlg.LU{T,Tridiagonal{T}}) where T n = size(F, 1) dl = copy(F.factors.dl) @@ -551,12 +551,12 @@ function convert{T}(::Type{Tridiagonal}, F::Base.LinAlg.LU{T,Tridiagonal{T}}) end return Tridiagonal(dl, d, du) end -convert{T}(::Type{AbstractMatrix}, F::Base.LinAlg.LU{T,Tridiagonal{T}}) = +convert(::Type{AbstractMatrix}, F::Base.LinAlg.LU{T,Tridiagonal{T}}) where {T} = convert(Tridiagonal, F) -convert{T}(::Type{AbstractArray}, F::Base.LinAlg.LU{T,Tridiagonal{T}}) = +convert(::Type{AbstractArray}, F::Base.LinAlg.LU{T,Tridiagonal{T}}) where {T} = convert(AbstractMatrix, F) -convert{T}(::Type{Matrix}, F::Base.LinAlg.LU{T,Tridiagonal{T}}) = +convert(::Type{Matrix}, F::Base.LinAlg.LU{T,Tridiagonal{T}}) where {T} = convert(Array, convert(AbstractArray, F)) -convert{T}(::Type{Array}, F::Base.LinAlg.LU{T,Tridiagonal{T}}) = +convert(::Type{Array}, F::Base.LinAlg.LU{T,Tridiagonal{T}}) where {T} = convert(Matrix, F) full{T}(F::Base.LinAlg.LU{T,Tridiagonal{T}}) = convert(AbstractArray, F) diff --git a/base/linalg/matmul.jl b/base/linalg/matmul.jl index d688811173245..f7dd618f0178e 100644 --- a/base/linalg/matmul.jl +++ b/base/linalg/matmul.jl @@ -40,10 +40,10 @@ end # Dot products -vecdot{T<:BlasReal}(x::Union{DenseArray{T},StridedVector{T}}, y::Union{DenseArray{T},StridedVector{T}}) = BLAS.dot(x, y) -vecdot{T<:BlasComplex}(x::Union{DenseArray{T},StridedVector{T}}, y::Union{DenseArray{T},StridedVector{T}}) = BLAS.dotc(x, y) +vecdot(x::Union{DenseArray{T},StridedVector{T}}, y::Union{DenseArray{T},StridedVector{T}}) where {T<:BlasReal} = BLAS.dot(x, y) +vecdot(x::Union{DenseArray{T},StridedVector{T}}, y::Union{DenseArray{T},StridedVector{T}}) where {T<:BlasComplex} = BLAS.dotc(x, y) -function dot{T<:BlasReal, TI<:Integer}(x::Vector{T}, rx::Union{UnitRange{TI},Range{TI}}, y::Vector{T}, ry::Union{UnitRange{TI},Range{TI}}) +function dot(x::Vector{T}, rx::Union{UnitRange{TI},Range{TI}}, y::Vector{T}, ry::Union{UnitRange{TI},Range{TI}}) where {T<:BlasReal,TI<:Integer} if length(rx) != length(ry) throw(DimensionMismatch("length of rx, $(length(rx)), does not equal length of ry, $(length(ry))")) end @@ -56,7 +56,7 @@ function dot{T<:BlasReal, TI<:Integer}(x::Vector{T}, rx::Union{UnitRange{TI},Ran BLAS.dot(length(rx), pointer(x)+(first(rx)-1)*sizeof(T), step(rx), pointer(y)+(first(ry)-1)*sizeof(T), step(ry)) end -function dot{T<:BlasComplex, TI<:Integer}(x::Vector{T}, rx::Union{UnitRange{TI},Range{TI}}, y::Vector{T}, ry::Union{UnitRange{TI},Range{TI}}) +function dot(x::Vector{T}, rx::Union{UnitRange{TI},Range{TI}}, y::Vector{T}, ry::Union{UnitRange{TI},Range{TI}}) where {T<:BlasComplex,TI<:Integer} if length(rx) != length(ry) throw(DimensionMismatch("length of rx, $(length(rx)), does not equal length of ry, $(length(ry))")) end @@ -69,14 +69,14 @@ function dot{T<:BlasComplex, TI<:Integer}(x::Vector{T}, rx::Union{UnitRange{TI}, BLAS.dotc(length(rx), pointer(x)+(first(rx)-1)*sizeof(T), step(rx), pointer(y)+(first(ry)-1)*sizeof(T), step(ry)) end -At_mul_B{T<:BlasComplex}(x::StridedVector{T}, y::StridedVector{T}) = BLAS.dotu(x, y) +At_mul_B(x::StridedVector{T}, y::StridedVector{T}) where {T<:BlasComplex} = BLAS.dotu(x, y) # Matrix-vector multiplication -function (*){T<:BlasFloat,S}(A::StridedMatrix{T}, x::StridedVector{S}) +function (*)(A::StridedMatrix{T}, x::StridedVector{S}) where {T<:BlasFloat,S} TS = promote_op(matprod, T, S) A_mul_B!(similar(x, TS, size(A,1)), A, convert(AbstractVector{TS}, x)) end -function (*){T,S}(A::AbstractMatrix{T}, x::AbstractVector{S}) +function (*)(A::AbstractMatrix{T}, x::AbstractVector{S}) where {T,S} TS = promote_op(matprod, T, S) A_mul_B!(similar(x,TS,size(A,1)),A,x) end @@ -88,7 +88,7 @@ A_mul_Bc(a::AbstractVector, B::AbstractMatrix) = A_mul_Bc(reshape(a,length(a),1) A_mul_Bc(A::AbstractMatrix, b::AbstractVector) = A_mul_Bc(A,reshape(b,length(b),1)) (*)(a::AbstractVector, B::AbstractMatrix) = reshape(a,length(a),1)*B -A_mul_B!{T<:BlasFloat}(y::StridedVector{T}, A::StridedVecOrMat{T}, x::StridedVector{T}) = gemv!(y, 'N', A, x) +A_mul_B!(y::StridedVector{T}, A::StridedVecOrMat{T}, x::StridedVector{T}) where {T<:BlasFloat} = gemv!(y, 'N', A, x) for elty in (Float32,Float64) @eval begin function A_mul_B!(y::StridedVector{Complex{$elty}}, A::StridedVecOrMat{Complex{$elty}}, x::StridedVector{$elty}) @@ -101,28 +101,28 @@ for elty in (Float32,Float64) end A_mul_B!(y::AbstractVector, A::AbstractVecOrMat, x::AbstractVector) = generic_matvecmul!(y, 'N', A, x) -function At_mul_B{T<:BlasFloat,S}(A::StridedMatrix{T}, x::StridedVector{S}) +function At_mul_B(A::StridedMatrix{T}, x::StridedVector{S}) where {T<:BlasFloat,S} TS = promote_op(matprod, T, S) At_mul_B!(similar(x,TS,size(A,2)), A, convert(AbstractVector{TS}, x)) end -function At_mul_B{T,S}(A::AbstractMatrix{T}, x::AbstractVector{S}) +function At_mul_B(A::AbstractMatrix{T}, x::AbstractVector{S}) where {T,S} TS = promote_op(matprod, T, S) At_mul_B!(similar(x,TS,size(A,2)), A, x) end -At_mul_B!{T<:BlasFloat}(y::StridedVector{T}, A::StridedVecOrMat{T}, x::StridedVector{T}) = gemv!(y, 'T', A, x) +At_mul_B!(y::StridedVector{T}, A::StridedVecOrMat{T}, x::StridedVector{T}) where {T<:BlasFloat} = gemv!(y, 'T', A, x) At_mul_B!(y::AbstractVector, A::AbstractVecOrMat, x::AbstractVector) = generic_matvecmul!(y, 'T', A, x) -function Ac_mul_B{T<:BlasFloat,S}(A::StridedMatrix{T}, x::StridedVector{S}) +function Ac_mul_B(A::StridedMatrix{T}, x::StridedVector{S}) where {T<:BlasFloat,S} TS = promote_op(matprod, T, S) Ac_mul_B!(similar(x,TS,size(A,2)),A,convert(AbstractVector{TS},x)) end -function Ac_mul_B{T,S}(A::AbstractMatrix{T}, x::AbstractVector{S}) +function Ac_mul_B(A::AbstractMatrix{T}, x::AbstractVector{S}) where {T,S} TS = promote_op(matprod, T, S) Ac_mul_B!(similar(x,TS,size(A,2)), A, x) end -Ac_mul_B!{T<:BlasReal}(y::StridedVector{T}, A::StridedVecOrMat{T}, x::StridedVector{T}) = At_mul_B!(y, A, x) -Ac_mul_B!{T<:BlasComplex}(y::StridedVector{T}, A::StridedVecOrMat{T}, x::StridedVector{T}) = gemv!(y, 'C', A, x) +Ac_mul_B!(y::StridedVector{T}, A::StridedVecOrMat{T}, x::StridedVector{T}) where {T<:BlasReal} = At_mul_B!(y, A, x) +Ac_mul_B!(y::StridedVector{T}, A::StridedVecOrMat{T}, x::StridedVector{T}) where {T<:BlasComplex} = gemv!(y, 'C', A, x) Ac_mul_B!(y::AbstractVector, A::AbstractVecOrMat, x::AbstractVector) = generic_matvecmul!(y, 'C', A, x) # Matrix-matrix multiplication @@ -143,11 +143,11 @@ julia> [1 1; 0 1] * [1 0; 1 1] 1 1 ``` """ -function (*){T,S}(A::AbstractMatrix{T}, B::AbstractMatrix{S}) +function (*)(A::AbstractMatrix{T}, B::AbstractMatrix{S}) where {T,S} TS = promote_op(matprod, T, S) A_mul_B!(similar(B, TS, (size(A,1), size(B,2))), A, B) end -A_mul_B!{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) = gemm_wrapper!(C, 'N', 'N', A, B) +A_mul_B!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = gemm_wrapper!(C, 'N', 'N', A, B) for elty in (Float32,Float64) @eval begin function A_mul_B!(C::StridedMatrix{Complex{$elty}}, A::StridedVecOrMat{Complex{$elty}}, B::StridedVecOrMat{$elty}) @@ -179,18 +179,18 @@ julia> Y """ A_mul_B!(C::AbstractMatrix, A::AbstractVecOrMat, B::AbstractVecOrMat) = generic_matmatmul!(C, 'N', 'N', A, B) -function At_mul_B{T,S}(A::AbstractMatrix{T}, B::AbstractMatrix{S}) +function At_mul_B(A::AbstractMatrix{T}, B::AbstractMatrix{S}) where {T,S} TS = promote_op(matprod, T, S) At_mul_B!(similar(B, TS, (size(A,2), size(B,2))), A, B) end -At_mul_B!{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) = A===B ? syrk_wrapper!(C, 'T', A) : gemm_wrapper!(C, 'T', 'N', A, B) +At_mul_B!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = A===B ? syrk_wrapper!(C, 'T', A) : gemm_wrapper!(C, 'T', 'N', A, B) At_mul_B!(C::AbstractMatrix, A::AbstractVecOrMat, B::AbstractVecOrMat) = generic_matmatmul!(C, 'T', 'N', A, B) -function A_mul_Bt{T,S}(A::AbstractMatrix{T}, B::AbstractMatrix{S}) +function A_mul_Bt(A::AbstractMatrix{T}, B::AbstractMatrix{S}) where {T,S} TS = promote_op(matprod, T, S) A_mul_Bt!(similar(B, TS, (size(A,1), size(B,1))), A, B) end -A_mul_Bt!{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) = A===B ? syrk_wrapper!(C, 'N', A) : gemm_wrapper!(C, 'N', 'T', A, B) +A_mul_Bt!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = A===B ? syrk_wrapper!(C, 'N', A) : gemm_wrapper!(C, 'N', 'T', A, B) for elty in (Float32,Float64) @eval begin function A_mul_Bt!(C::StridedMatrix{Complex{$elty}}, A::StridedVecOrMat{Complex{$elty}}, B::StridedVecOrMat{$elty}) @@ -203,34 +203,34 @@ for elty in (Float32,Float64) end A_mul_Bt!(C::AbstractVecOrMat, A::AbstractVecOrMat, B::AbstractVecOrMat) = generic_matmatmul!(C, 'N', 'T', A, B) -function At_mul_Bt{T,S}(A::AbstractMatrix{T}, B::AbstractVecOrMat{S}) +function At_mul_Bt(A::AbstractMatrix{T}, B::AbstractVecOrMat{S}) where {T,S} TS = promote_op(matprod, T, S) At_mul_Bt!(similar(B, TS, (size(A,2), size(B,1))), A, B) end -At_mul_Bt!{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) = gemm_wrapper!(C, 'T', 'T', A, B) +At_mul_Bt!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = gemm_wrapper!(C, 'T', 'T', A, B) At_mul_Bt!(C::AbstractMatrix, A::AbstractVecOrMat, B::AbstractVecOrMat) = generic_matmatmul!(C, 'T', 'T', A, B) -Ac_mul_B{T<:BlasReal}(A::StridedMatrix{T}, B::StridedMatrix{T}) = At_mul_B(A, B) -Ac_mul_B!{T<:BlasReal}(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) = At_mul_B!(C, A, B) -function Ac_mul_B{T,S}(A::AbstractMatrix{T}, B::AbstractMatrix{S}) +Ac_mul_B(A::StridedMatrix{T}, B::StridedMatrix{T}) where {T<:BlasReal} = At_mul_B(A, B) +Ac_mul_B!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) where {T<:BlasReal} = At_mul_B!(C, A, B) +function Ac_mul_B(A::AbstractMatrix{T}, B::AbstractMatrix{S}) where {T,S} TS = promote_op(matprod, T, S) Ac_mul_B!(similar(B, TS, (size(A,2), size(B,2))), A, B) end -Ac_mul_B!{T<:BlasComplex}(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) = A===B ? herk_wrapper!(C,'C',A) : gemm_wrapper!(C,'C', 'N', A, B) +Ac_mul_B!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) where {T<:BlasComplex} = A===B ? herk_wrapper!(C,'C',A) : gemm_wrapper!(C,'C', 'N', A, B) Ac_mul_B!(C::AbstractMatrix, A::AbstractVecOrMat, B::AbstractVecOrMat) = generic_matmatmul!(C, 'C', 'N', A, B) A_mul_Bc(A::StridedMatrix{<:BlasFloat}, B::StridedMatrix{<:BlasReal}) = A_mul_Bt(A, B) -A_mul_Bc!{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{<:BlasReal}) = A_mul_Bt!(C, A, B) -function A_mul_Bc{T,S}(A::AbstractMatrix{T}, B::AbstractMatrix{S}) +A_mul_Bc!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{<:BlasReal}) where {T<:BlasFloat} = A_mul_Bt!(C, A, B) +function A_mul_Bc(A::AbstractMatrix{T}, B::AbstractMatrix{S}) where {T,S} TS = promote_op(matprod, T, S) A_mul_Bc!(similar(B,TS,(size(A,1),size(B,1))),A,B) end -A_mul_Bc!{T<:BlasComplex}(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) = A===B ? herk_wrapper!(C, 'N', A) : gemm_wrapper!(C, 'N', 'C', A, B) +A_mul_Bc!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) where {T<:BlasComplex} = A===B ? herk_wrapper!(C, 'N', A) : gemm_wrapper!(C, 'N', 'C', A, B) A_mul_Bc!(C::AbstractMatrix, A::AbstractVecOrMat, B::AbstractVecOrMat) = generic_matmatmul!(C, 'N', 'C', A, B) -Ac_mul_Bc{T,S}(A::AbstractMatrix{T}, B::AbstractMatrix{S}) = +Ac_mul_Bc(A::AbstractMatrix{T}, B::AbstractMatrix{S}) where {T,S} = Ac_mul_Bc!(similar(B, promote_op(matprod, T, S), (size(A,2), size(B,1))), A, B) -Ac_mul_Bc!{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) = gemm_wrapper!(C, 'C', 'C', A, B) +Ac_mul_Bc!(C::StridedMatrix{T}, A::StridedVecOrMat{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = gemm_wrapper!(C, 'C', 'C', A, B) Ac_mul_Bc!(C::AbstractMatrix, A::AbstractVecOrMat, B::AbstractVecOrMat) = generic_matmatmul!(C, 'C', 'C', A, B) Ac_mul_Bt!(C::AbstractMatrix, A::AbstractVecOrMat, B::AbstractVecOrMat) = generic_matmatmul!(C, 'C', 'T', A, B) # Supporting functions for matrix multiplication @@ -251,7 +251,7 @@ function copytri!(A::AbstractMatrix, uplo::Char, conjugate::Bool=false) A end -function gemv!{T<:BlasFloat}(y::StridedVector{T}, tA::Char, A::StridedVecOrMat{T}, x::StridedVector{T}) +function gemv!(y::StridedVector{T}, tA::Char, A::StridedVecOrMat{T}, x::StridedVector{T}) where T<:BlasFloat mA, nA = lapack_size(tA, A) if nA != length(x) throw(DimensionMismatch("second dimension of A, $nA, does not match length of x, $(length(x))")) @@ -269,7 +269,7 @@ function gemv!{T<:BlasFloat}(y::StridedVector{T}, tA::Char, A::StridedVecOrMat{T return generic_matvecmul!(y, tA, A, x) end -function syrk_wrapper!{T<:BlasFloat}(C::StridedMatrix{T}, tA::Char, A::StridedVecOrMat{T}) +function syrk_wrapper!(C::StridedMatrix{T}, tA::Char, A::StridedVecOrMat{T}) where T<:BlasFloat nC = checksquare(C) if tA == 'T' (nA, mA) = size(A,1), size(A,2) @@ -297,7 +297,7 @@ function syrk_wrapper!{T<:BlasFloat}(C::StridedMatrix{T}, tA::Char, A::StridedVe return generic_matmatmul!(C, tA, tAt, A, A) end -function herk_wrapper!{T<:BlasReal}(C::Union{StridedMatrix{T}, StridedMatrix{Complex{T}}}, tA::Char, A::Union{StridedVecOrMat{T}, StridedVecOrMat{Complex{T}}}) +function herk_wrapper!(C::Union{StridedMatrix{T}, StridedMatrix{Complex{T}}}, tA::Char, A::Union{StridedVecOrMat{T}, StridedVecOrMat{Complex{T}}}) where T<:BlasReal nC = checksquare(C) if tA == 'C' (nA, mA) = size(A,1), size(A,2) @@ -328,18 +328,18 @@ function herk_wrapper!{T<:BlasReal}(C::Union{StridedMatrix{T}, StridedMatrix{Com return generic_matmatmul!(C,tA, tAt, A, A) end -function gemm_wrapper{T<:BlasFloat}(tA::Char, tB::Char, - A::StridedVecOrMat{T}, - B::StridedVecOrMat{T}) +function gemm_wrapper(tA::Char, tB::Char, + A::StridedVecOrMat{T}, + B::StridedVecOrMat{T}) where T<:BlasFloat mA, nA = lapack_size(tA, A) mB, nB = lapack_size(tB, B) C = similar(B, T, mA, nB) gemm_wrapper!(C, tA, tB, A, B) end -function gemm_wrapper!{T<:BlasFloat}(C::StridedVecOrMat{T}, tA::Char, tB::Char, - A::StridedVecOrMat{T}, - B::StridedVecOrMat{T}) +function gemm_wrapper!(C::StridedVecOrMat{T}, tA::Char, tB::Char, + A::StridedVecOrMat{T}, + B::StridedVecOrMat{T}) where T<:BlasFloat mA, nA = lapack_size(tA, A) mB, nB = lapack_size(tB, B) @@ -402,7 +402,7 @@ end # NOTE: the generic version is also called as fallback for # strides != 1 cases -function generic_matvecmul!{R}(C::AbstractVector{R}, tA, A::AbstractVecOrMat, B::AbstractVector) +function generic_matvecmul!(C::AbstractVector{R}, tA, A::AbstractVecOrMat, B::AbstractVector) where R mB = length(B) mA, nA = lapack_size(tA, A) if mB != nA @@ -459,7 +459,7 @@ function generic_matvecmul!{R}(C::AbstractVector{R}, tA, A::AbstractVecOrMat, B: C end -function generic_matmatmul{T,S}(tA, tB, A::AbstractVecOrMat{T}, B::AbstractMatrix{S}) +function generic_matmatmul(tA, tB, A::AbstractVecOrMat{T}, B::AbstractMatrix{S}) where {T,S} mA, nA = lapack_size(tA, A) mB, nB = lapack_size(tB, B) C = similar(B, promote_op(matprod, T, S), mA, nB) @@ -487,7 +487,7 @@ end generic_matmatmul!(C::AbstractVecOrMat, tA, tB, A::AbstractVecOrMat, B::AbstractVecOrMat) = _generic_matmatmul!(C, tA, tB, A, B) -function _generic_matmatmul!{T,S,R}(C::AbstractVecOrMat{R}, tA, tB, A::AbstractVecOrMat{T}, B::AbstractVecOrMat{S}) +function _generic_matmatmul!(C::AbstractVecOrMat{R}, tA, tB, A::AbstractVecOrMat{T}, B::AbstractVecOrMat{S}) where {T,S,R} mA, nA = lapack_size(tA, A) mB, nB = lapack_size(tB, B) if mB != nA @@ -655,7 +655,7 @@ end # multiply 2x2 matrices -function matmul2x2{T,S}(tA, tB, A::AbstractMatrix{T}, B::AbstractMatrix{S}) +function matmul2x2(tA, tB, A::AbstractMatrix{T}, B::AbstractMatrix{S}) where {T,S} matmul2x2!(similar(B, promote_op(matprod, T, S), 2, 2), tA, tB, A, B) end @@ -687,7 +687,7 @@ function matmul2x2!(C::AbstractMatrix, tA, tB, A::AbstractMatrix, B::AbstractMat end # Multiply 3x3 matrices -function matmul3x3{T,S}(tA, tB, A::AbstractMatrix{T}, B::AbstractMatrix{S}) +function matmul3x3(tA, tB, A::AbstractMatrix{T}, B::AbstractMatrix{S}) where {T,S} matmul3x3!(similar(B, promote_op(matprod, T, S), 3, 3), tA, tB, A, B) end diff --git a/base/linalg/qr.jl b/base/linalg/qr.jl index 191d138e3a271..e693496c7c052 100644 --- a/base/linalg/qr.jl +++ b/base/linalg/qr.jl @@ -271,20 +271,20 @@ function qr!(v::AbstractVector) end # Conversions -convert{T}(::Type{QR{T}}, A::QR) = QR(convert(AbstractMatrix{T}, A.factors), convert(Vector{T}, A.τ)) -convert{T}(::Type{Factorization{T}}, A::QR{T}) = A -convert{T}(::Type{Factorization{T}}, A::QR) = convert(QR{T}, A) -convert{T}(::Type{QRCompactWY{T}}, A::QRCompactWY) = QRCompactWY(convert(AbstractMatrix{T}, A.factors), convert(AbstractMatrix{T}, A.T)) -convert{T}(::Type{Factorization{T}}, A::QRCompactWY{T}) = A -convert{T}(::Type{Factorization{T}}, A::QRCompactWY) = convert(QRCompactWY{T}, A) +convert(::Type{QR{T}}, A::QR) where {T} = QR(convert(AbstractMatrix{T}, A.factors), convert(Vector{T}, A.τ)) +convert(::Type{Factorization{T}}, A::QR{T}) where {T} = A +convert(::Type{Factorization{T}}, A::QR) where {T} = convert(QR{T}, A) +convert(::Type{QRCompactWY{T}}, A::QRCompactWY) where {T} = QRCompactWY(convert(AbstractMatrix{T}, A.factors), convert(AbstractMatrix{T}, A.T)) +convert(::Type{Factorization{T}}, A::QRCompactWY{T}) where {T} = A +convert(::Type{Factorization{T}}, A::QRCompactWY) where {T} = convert(QRCompactWY{T}, A) convert(::Type{AbstractMatrix}, F::Union{QR,QRCompactWY}) = F[:Q] * F[:R] convert(::Type{AbstractArray}, F::Union{QR,QRCompactWY}) = convert(AbstractMatrix, F) convert(::Type{Matrix}, F::Union{QR,QRCompactWY}) = convert(Array, convert(AbstractArray, F)) convert(::Type{Array}, F::Union{QR,QRCompactWY}) = convert(Matrix, F) full(F::Union{QR,QRCompactWY}) = convert(AbstractArray, F) -convert{T}(::Type{QRPivoted{T}}, A::QRPivoted) = QRPivoted(convert(AbstractMatrix{T}, A.factors), convert(Vector{T}, A.τ), A.jpvt) -convert{T}(::Type{Factorization{T}}, A::QRPivoted{T}) = A -convert{T}(::Type{Factorization{T}}, A::QRPivoted) = convert(QRPivoted{T}, A) +convert(::Type{QRPivoted{T}}, A::QRPivoted) where {T} = QRPivoted(convert(AbstractMatrix{T}, A.factors), convert(Vector{T}, A.τ), A.jpvt) +convert(::Type{Factorization{T}}, A::QRPivoted{T}) where {T} = A +convert(::Type{Factorization{T}}, A::QRPivoted) where {T} = convert(QRPivoted{T}, A) convert(::Type{AbstractMatrix}, F::QRPivoted) = (F[:Q] * F[:R])[:,invperm(F[:p])] convert(::Type{AbstractArray}, F::QRPivoted) = convert(AbstractMatrix, F) convert(::Type{Matrix}, F::QRPivoted) = convert(Array, convert(AbstractArray, F)) @@ -318,7 +318,7 @@ function getindex(A::QRCompactWY, d::Symbol) throw(KeyError(d)) end end -function getindex{T}(A::QRPivoted{T}, d::Symbol) +function getindex(A::QRPivoted{T}, d::Symbol) where T m, n = size(A) if d == :R return triu!(A.factors[1:min(m,n), 1:n]) @@ -357,13 +357,13 @@ struct QRCompactWYQ{S, M<:AbstractMatrix} <: AbstractMatrix{S} end QRCompactWYQ(factors::AbstractMatrix{S}, T::Matrix{S}) where {S} = QRCompactWYQ{S,typeof(factors)}(factors, T) -convert{T}(::Type{QRPackedQ{T}}, Q::QRPackedQ) = QRPackedQ(convert(AbstractMatrix{T}, Q.factors), convert(Vector{T}, Q.τ)) -convert{T}(::Type{AbstractMatrix{T}}, Q::QRPackedQ{T}) = Q -convert{T}(::Type{AbstractMatrix{T}}, Q::QRPackedQ) = convert(QRPackedQ{T}, Q) -convert{S}(::Type{QRCompactWYQ{S}}, Q::QRCompactWYQ) = QRCompactWYQ(convert(AbstractMatrix{S}, Q.factors), convert(AbstractMatrix{S}, Q.T)) -convert{S}(::Type{AbstractMatrix{S}}, Q::QRCompactWYQ{S}) = Q -convert{S}(::Type{AbstractMatrix{S}}, Q::QRCompactWYQ) = convert(QRCompactWYQ{S}, Q) -convert{T}(::Type{Matrix}, A::Union{QRPackedQ{T},QRCompactWYQ{T}}) = A_mul_B!(A, eye(T, size(A.factors, 1), minimum(size(A.factors)))) +convert(::Type{QRPackedQ{T}}, Q::QRPackedQ) where {T} = QRPackedQ(convert(AbstractMatrix{T}, Q.factors), convert(Vector{T}, Q.τ)) +convert(::Type{AbstractMatrix{T}}, Q::QRPackedQ{T}) where {T} = Q +convert(::Type{AbstractMatrix{T}}, Q::QRPackedQ) where {T} = convert(QRPackedQ{T}, Q) +convert(::Type{QRCompactWYQ{S}}, Q::QRCompactWYQ) where {S} = QRCompactWYQ(convert(AbstractMatrix{S}, Q.factors), convert(AbstractMatrix{S}, Q.T)) +convert(::Type{AbstractMatrix{S}}, Q::QRCompactWYQ{S}) where {S} = Q +convert(::Type{AbstractMatrix{S}}, Q::QRCompactWYQ) where {S} = convert(QRCompactWYQ{S}, Q) +convert(::Type{Matrix}, A::Union{QRPackedQ{T},QRCompactWYQ{T}}) where {T} = A_mul_B!(A, eye(T, size(A.factors, 1), minimum(size(A.factors)))) convert(::Type{Array}, A::Union{QRPackedQ,QRCompactWYQ}) = convert(Matrix, A) """ @@ -401,8 +401,8 @@ end ## Multiplication by Q ### QB -A_mul_B!{T<:BlasFloat}(A::QRCompactWYQ{T}, B::StridedVecOrMat{T}) = LAPACK.gemqrt!('L','N',A.factors,A.T,B) -A_mul_B!{T<:BlasFloat}(A::QRPackedQ{T}, B::StridedVecOrMat{T}) = LAPACK.ormqr!('L','N',A.factors,A.τ,B) +A_mul_B!(A::QRCompactWYQ{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = LAPACK.gemqrt!('L','N',A.factors,A.T,B) +A_mul_B!(A::QRPackedQ{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = LAPACK.ormqr!('L','N',A.factors,A.τ,B) function A_mul_B!(A::QRPackedQ, B::AbstractVecOrMat) mA, nA = size(A.factors) mB, nB = size(B,1), size(B,2) @@ -454,10 +454,10 @@ function (*)(A::Union{QRPackedQ,QRCompactWYQ}, B::StridedMatrix) end ### QcB -Ac_mul_B!{T<:BlasReal}(A::QRCompactWYQ{T}, B::StridedVecOrMat{T}) = LAPACK.gemqrt!('L','T',A.factors,A.T,B) -Ac_mul_B!{T<:BlasComplex}(A::QRCompactWYQ{T}, B::StridedVecOrMat{T}) = LAPACK.gemqrt!('L','C',A.factors,A.T,B) -Ac_mul_B!{T<:BlasReal}(A::QRPackedQ{T}, B::StridedVecOrMat{T}) = LAPACK.ormqr!('L','T',A.factors,A.τ,B) -Ac_mul_B!{T<:BlasComplex}(A::QRPackedQ{T}, B::StridedVecOrMat{T}) = LAPACK.ormqr!('L','C',A.factors,A.τ,B) +Ac_mul_B!(A::QRCompactWYQ{T}, B::StridedVecOrMat{T}) where {T<:BlasReal} = LAPACK.gemqrt!('L','T',A.factors,A.T,B) +Ac_mul_B!(A::QRCompactWYQ{T}, B::StridedVecOrMat{T}) where {T<:BlasComplex} = LAPACK.gemqrt!('L','C',A.factors,A.T,B) +Ac_mul_B!(A::QRPackedQ{T}, B::StridedVecOrMat{T}) where {T<:BlasReal} = LAPACK.ormqr!('L','T',A.factors,A.τ,B) +Ac_mul_B!(A::QRPackedQ{T}, B::StridedVecOrMat{T}) where {T<:BlasComplex} = LAPACK.ormqr!('L','C',A.factors,A.τ,B) function Ac_mul_B!(A::QRPackedQ, B::AbstractVecOrMat) mA, nA = size(A.factors) mB, nB = size(B,1), size(B,2) @@ -501,8 +501,8 @@ for (f1, f2) in ((:A_mul_Bc, :A_mul_B!), end ### AQ -A_mul_B!{T<:BlasFloat}(A::StridedVecOrMat{T}, B::QRCompactWYQ{T}) = LAPACK.gemqrt!('R','N', B.factors, B.T, A) -A_mul_B!{T<:BlasFloat}(A::StridedVecOrMat{T}, B::QRPackedQ{T}) = LAPACK.ormqr!('R', 'N', B.factors, B.τ, A) +A_mul_B!(A::StridedVecOrMat{T}, B::QRCompactWYQ{T}) where {T<:BlasFloat} = LAPACK.gemqrt!('R','N', B.factors, B.T, A) +A_mul_B!(A::StridedVecOrMat{T}, B::QRPackedQ{T}) where {T<:BlasFloat} = LAPACK.ormqr!('R', 'N', B.factors, B.τ, A) function A_mul_B!(A::StridedMatrix,Q::QRPackedQ) mQ, nQ = size(Q.factors) mA, nA = size(A,1), size(A,2) @@ -534,10 +534,10 @@ function (*)(A::StridedMatrix, Q::Union{QRPackedQ,QRCompactWYQ}) end ### AQc -A_mul_Bc!{T<:BlasReal}(A::StridedVecOrMat{T}, B::QRCompactWYQ{T}) = LAPACK.gemqrt!('R','T',B.factors,B.T,A) -A_mul_Bc!{T<:BlasComplex}(A::StridedVecOrMat{T}, B::QRCompactWYQ{T}) = LAPACK.gemqrt!('R','C',B.factors,B.T,A) -A_mul_Bc!{T<:BlasReal}(A::StridedVecOrMat{T}, B::QRPackedQ{T}) = LAPACK.ormqr!('R','T',B.factors,B.τ,A) -A_mul_Bc!{T<:BlasComplex}(A::StridedVecOrMat{T}, B::QRPackedQ{T}) = LAPACK.ormqr!('R','C',B.factors,B.τ,A) +A_mul_Bc!(A::StridedVecOrMat{T}, B::QRCompactWYQ{T}) where {T<:BlasReal} = LAPACK.gemqrt!('R','T',B.factors,B.T,A) +A_mul_Bc!(A::StridedVecOrMat{T}, B::QRCompactWYQ{T}) where {T<:BlasComplex} = LAPACK.gemqrt!('R','C',B.factors,B.T,A) +A_mul_Bc!(A::StridedVecOrMat{T}, B::QRPackedQ{T}) where {T<:BlasReal} = LAPACK.ormqr!('R','T',B.factors,B.τ,A) +A_mul_Bc!(A::StridedVecOrMat{T}, B::QRPackedQ{T}) where {T<:BlasComplex} = LAPACK.ormqr!('R','C',B.factors,B.τ,A) function A_mul_Bc!(A::AbstractMatrix,Q::QRPackedQ) mQ, nQ = size(Q.factors) mA, nA = size(A,1), size(A,2) diff --git a/base/linalg/rowvector.jl b/base/linalg/rowvector.jl index dd8607fad9349..3e33d1c43af12 100644 --- a/base/linalg/rowvector.jl +++ b/base/linalg/rowvector.jl @@ -45,7 +45,7 @@ ConjRowVector{T, CV <: ConjVector} = RowVector{T, CV} error("RowVector expects 1×N size, got $n") # Conversion of underlying storage -convert{T,V<:AbstractVector}(::Type{RowVector{T,V}}, rowvec::RowVector) = +convert(::Type{RowVector{T,V}}, rowvec::RowVector) where {T,V<:AbstractVector} = RowVector{T,V}(convert(V,rowvec.vec)) # similar tries to maintain the RowVector wrapper and the parent type @@ -204,7 +204,7 @@ At_mul_B(::RowVector, ::AbstractVector) = throw(DimensionMismatch("Cannot multip @inline At_mul_B(rowvec1::RowVector, rowvec2::RowVector) = transpose(rowvec1) * rowvec2 At_mul_B(vec::AbstractVector, rowvec::RowVector) = throw(DimensionMismatch( "Cannot multiply two transposed vectors")) -@inline At_mul_B{T<:Real}(vec1::AbstractVector{T}, vec2::AbstractVector{T}) = +@inline At_mul_B(vec1::AbstractVector{T}, vec2::AbstractVector{T}) where {T<:Real} = reduce(+, map(At_mul_B, vec1, vec2)) # Seems to be overloaded... @inline At_mul_B(vec1::AbstractVector, vec2::AbstractVector) = transpose(vec1) * vec2 diff --git a/base/linalg/special.jl b/base/linalg/special.jl index 662637ec1b9f4..c4fd2c6e09bb1 100644 --- a/base/linalg/special.jl +++ b/base/linalg/special.jl @@ -3,11 +3,11 @@ # Methods operating on different special matrix types # Interconversion between special matrix types -convert{T}(::Type{Bidiagonal}, A::Diagonal{T}) = +convert(::Type{Bidiagonal}, A::Diagonal{T}) where {T} = Bidiagonal(A.diag, zeros(T, size(A.diag,1)-1), true) -convert{T}(::Type{SymTridiagonal}, A::Diagonal{T}) = +convert(::Type{SymTridiagonal}, A::Diagonal{T}) where {T} = SymTridiagonal(A.diag, zeros(T, size(A.diag,1)-1)) -convert{T}(::Type{Tridiagonal}, A::Diagonal{T}) = +convert(::Type{Tridiagonal}, A::Diagonal{T}) where {T} = Tridiagonal(zeros(T, size(A.diag,1)-1), A.diag, zeros(T, size(A.diag,1)-1)) function convert(::Type{Diagonal}, A::Union{Bidiagonal, SymTridiagonal}) @@ -24,7 +24,7 @@ function convert(::Type{SymTridiagonal}, A::Bidiagonal) SymTridiagonal(A.dv, A.ev) end -convert{T}(::Type{Tridiagonal}, A::Bidiagonal{T}) = +convert(::Type{Tridiagonal}, A::Bidiagonal{T}) where {T} = Tridiagonal(A.isupper ? zeros(T, size(A.dv,1)-1) : A.ev, A.dv, A.isupper ? A.ev:zeros(T, size(A.dv,1)-1)) diff --git a/base/linalg/svd.jl b/base/linalg/svd.jl index 96df0b82a89fc..7bc1a42f45486 100644 --- a/base/linalg/svd.jl +++ b/base/linalg/svd.jl @@ -249,7 +249,7 @@ function svd(A::AbstractMatrix, B::AbstractMatrix) F[:U], F[:V], F[:Q], F[:D1], F[:D2], F[:R0] end -function getindex{T}(obj::GeneralizedSVD{T}, d::Symbol) +function getindex(obj::GeneralizedSVD{T}, d::Symbol) where T if d == :U return obj.U elseif d == :V diff --git a/base/linalg/symmetric.jl b/base/linalg/symmetric.jl index 4664ad505354a..10e2dd5a5fc6a 100644 --- a/base/linalg/symmetric.jl +++ b/base/linalg/symmetric.jl @@ -114,10 +114,10 @@ function setindex!(A::Hermitian, v, i::Integer, j::Integer) end end -similar{T}(A::Symmetric, ::Type{T}) = Symmetric(similar(A.data, T)) +similar(A::Symmetric, ::Type{T}) where {T} = Symmetric(similar(A.data, T)) # Hermitian version can be simplified when check for imaginary part of # diagonal in Hermitian has been removed -function similar{T}(A::Hermitian, ::Type{T}) +function similar(A::Hermitian, ::Type{T}) where T B = similar(A.data, T) for i = 1:size(A,1) B[i,i] = 0 @@ -131,12 +131,12 @@ convert(::Type{Matrix}, A::Hermitian) = copytri!(convert(Matrix, copy(A.data)), convert(::Type{Array}, A::Union{Symmetric,Hermitian}) = convert(Matrix, A) full(A::Union{Symmetric,Hermitian}) = convert(Array, A) parent(A::HermOrSym) = A.data -convert{T,S<:AbstractMatrix}(::Type{Symmetric{T,S}},A::Symmetric{T,S}) = A -convert{T,S<:AbstractMatrix}(::Type{Symmetric{T,S}},A::Symmetric) = Symmetric{T,S}(convert(S,A.data),A.uplo) -convert{T}(::Type{AbstractMatrix{T}}, A::Symmetric) = Symmetric(convert(AbstractMatrix{T}, A.data), Symbol(A.uplo)) -convert{T,S<:AbstractMatrix}(::Type{Hermitian{T,S}},A::Hermitian{T,S}) = A -convert{T,S<:AbstractMatrix}(::Type{Hermitian{T,S}},A::Hermitian) = Hermitian{T,S}(convert(S,A.data),A.uplo) -convert{T}(::Type{AbstractMatrix{T}}, A::Hermitian) = Hermitian(convert(AbstractMatrix{T}, A.data), Symbol(A.uplo)) +convert(::Type{Symmetric{T,S}},A::Symmetric{T,S}) where {T,S<:AbstractMatrix} = A +convert(::Type{Symmetric{T,S}},A::Symmetric) where {T,S<:AbstractMatrix} = Symmetric{T,S}(convert(S,A.data),A.uplo) +convert(::Type{AbstractMatrix{T}}, A::Symmetric) where {T} = Symmetric(convert(AbstractMatrix{T}, A.data), Symbol(A.uplo)) +convert(::Type{Hermitian{T,S}},A::Hermitian{T,S}) where {T,S<:AbstractMatrix} = A +convert(::Type{Hermitian{T,S}},A::Hermitian) where {T,S<:AbstractMatrix} = Hermitian{T,S}(convert(S,A.data),A.uplo) +convert(::Type{AbstractMatrix{T}}, A::Hermitian) where {T} = Hermitian(convert(AbstractMatrix{T}, A.data), Symbol(A.uplo)) copy{T,S}(A::Symmetric{T,S}) = (B = copy(A.data); Symmetric{T,typeof(B)}(B,A.uplo)) copy{T,S}(A::Hermitian{T,S}) = (B = copy(A.data); Hermitian{T,typeof(B)}(B,A.uplo)) @@ -230,7 +230,7 @@ function triu(A::Symmetric, k::Integer=0) end end --{Tv,S<:AbstractMatrix}(A::Symmetric{Tv,S}) = Symmetric{Tv,S}(-A.data, A.uplo) +(-)(A::Symmetric{Tv,S}) where {Tv,S<:AbstractMatrix} = Symmetric{Tv,S}(-A.data, A.uplo) ## Matvec A_mul_B!{T<:BlasFloat}(y::StridedVector{T}, A::Symmetric{T,<:StridedMatrix}, x::StridedVector{T}) = BLAS.symv!(A.uplo, one(T), A.data, x, zero(T), y) diff --git a/base/linalg/triangular.jl b/base/linalg/triangular.jl index 53dc720c2138c..dec4a33a91978 100644 --- a/base/linalg/triangular.jl +++ b/base/linalg/triangular.jl @@ -61,13 +61,13 @@ parent(A::AbstractTriangular) = A.data # then handle all methods that requires specific handling of upper/lower and unit diagonal -function convert{T}(::Type{Matrix{T}}, A::LowerTriangular) +function convert(::Type{Matrix{T}}, A::LowerTriangular) where T B = Array{T}(size(A, 1), size(A, 1)) copy!(B, A.data) tril!(B) B end -function convert{T}(::Type{Matrix{T}}, A::UnitLowerTriangular) +function convert(::Type{Matrix{T}}, A::UnitLowerTriangular) where T B = Array{T}(size(A, 1), size(A, 1)) copy!(B, A.data) tril!(B) @@ -76,13 +76,13 @@ function convert{T}(::Type{Matrix{T}}, A::UnitLowerTriangular) end B end -function convert{T}(::Type{Matrix{T}}, A::UpperTriangular) +function convert(::Type{Matrix{T}}, A::UpperTriangular) where T B = Array{T}(size(A, 1), size(A, 1)) copy!(B, A.data) triu!(B) B end -function convert{T}(::Type{Matrix{T}}, A::UnitUpperTriangular) +function convert(::Type{Matrix{T}}, A::UnitUpperTriangular) where T B = Array{T}(size(A, 1), size(A, 1)) copy!(B, A.data) triu!(B) @@ -119,11 +119,11 @@ function full!(A::UnitUpperTriangular) B end -getindex{T}(A::UnitLowerTriangular{T}, i::Integer, j::Integer) = +getindex(A::UnitLowerTriangular{T}, i::Integer, j::Integer) where {T} = i > j ? A.data[i,j] : ifelse(i == j, oneunit(T), zero(T)) getindex(A::LowerTriangular, i::Integer, j::Integer) = i >= j ? A.data[i,j] : zero(A.data[j,i]) -getindex{T}(A::UnitUpperTriangular{T}, i::Integer, j::Integer) = +getindex(A::UnitUpperTriangular{T}, i::Integer, j::Integer) where {T} = i < j ? A.data[i,j] : ifelse(i == j, oneunit(T), zero(T)) getindex(A::UpperTriangular, i::Integer, j::Integer) = i <= j ? A.data[i,j] : zero(A.data[j,i]) @@ -324,7 +324,7 @@ function -(A::UnitUpperTriangular) end # copy and scale -function copy!{T<:Union{UpperTriangular, UnitUpperTriangular}}(A::T, B::T) +function copy!(A::T, B::T) where T<:Union{UpperTriangular,UnitUpperTriangular} n = size(B,1) for j = 1:n for i = 1:(isa(B, UnitUpperTriangular)?j-1:j) @@ -333,7 +333,7 @@ function copy!{T<:Union{UpperTriangular, UnitUpperTriangular}}(A::T, B::T) end return A end -function copy!{T<:Union{LowerTriangular, UnitLowerTriangular}}(A::T, B::T) +function copy!(A::T, B::T) where T<:Union{LowerTriangular,UnitLowerTriangular} n = size(B,1) for j = 1:n for i = (isa(B, UnitLowerTriangular)?j+1:j):n @@ -343,7 +343,7 @@ function copy!{T<:Union{LowerTriangular, UnitLowerTriangular}}(A::T, B::T) return A end -function scale!(A::UpperTriangular, B::Union{UpperTriangular, UnitUpperTriangular}, c::Number) +function scale!(A::UpperTriangular, B::Union{UpperTriangular,UnitUpperTriangular}, c::Number) n = checksquare(B) for j = 1:n if isa(B, UnitUpperTriangular) @@ -355,7 +355,7 @@ function scale!(A::UpperTriangular, B::Union{UpperTriangular, UnitUpperTriangula end return A end -function scale!(A::LowerTriangular, B::Union{LowerTriangular, UnitLowerTriangular}, c::Number) +function scale!(A::LowerTriangular, B::Union{LowerTriangular,UnitLowerTriangular}, c::Number) n = checksquare(B) for j = 1:n if isa(B, UnitLowerTriangular) diff --git a/base/linalg/tridiag.jl b/base/linalg/tridiag.jl index 3ac3810aba47d..faa5d53624706 100644 --- a/base/linalg/tridiag.jl +++ b/base/linalg/tridiag.jl @@ -61,11 +61,11 @@ function SymTridiagonal(A::AbstractMatrix) end end -convert{T}(::Type{SymTridiagonal{T}}, S::SymTridiagonal) = +convert(::Type{SymTridiagonal{T}}, S::SymTridiagonal) where {T} = SymTridiagonal(convert(Vector{T}, S.dv), convert(Vector{T}, S.ev)) -convert{T}(::Type{AbstractMatrix{T}}, S::SymTridiagonal) = +convert(::Type{AbstractMatrix{T}}, S::SymTridiagonal) where {T} = SymTridiagonal(convert(Vector{T}, S.dv), convert(Vector{T}, S.ev)) -function convert{T}(::Type{Matrix{T}}, M::SymTridiagonal{T}) +function convert(::Type{Matrix{T}}, M::SymTridiagonal{T}) where T n = size(M, 1) Mf = zeros(T, n, n) @inbounds begin @@ -78,7 +78,7 @@ function convert{T}(::Type{Matrix{T}}, M::SymTridiagonal{T}) end return Mf end -convert{T}(::Type{Matrix}, M::SymTridiagonal{T}) = convert(Matrix{T}, M) +convert(::Type{Matrix}, M::SymTridiagonal{T}) where {T} = convert(Matrix{T}, M) convert(::Type{Array}, M::SymTridiagonal) = convert(Matrix, M) full(M::SymTridiagonal) = convert(Array, M) @@ -93,7 +93,7 @@ function size(A::SymTridiagonal, d::Integer) end end -similar{T}(S::SymTridiagonal, ::Type{T}) = SymTridiagonal{T}(similar(S.dv, T), similar(S.ev, T)) +similar(S::SymTridiagonal, ::Type{T}) where {T} = SymTridiagonal{T}(similar(S.dv, T), similar(S.ev, T)) #Elementary operations broadcast(::typeof(abs), M::SymTridiagonal) = SymTridiagonal(abs.(M.dv), abs.(M.ev)) @@ -359,7 +359,7 @@ end inv(A::SymTridiagonal) = inv_usmani(A.ev, A.dv, A.ev) det(A::SymTridiagonal) = det_usmani(A.ev, A.dv, A.ev) -function getindex{T}(A::SymTridiagonal{T}, i::Integer, j::Integer) +function getindex(A::SymTridiagonal{T}, i::Integer, j::Integer) where T if !(1 <= i <= size(A,2) && 1 <= j <= size(A,2)) throw(BoundsError(A, (i,j))) end @@ -485,7 +485,7 @@ function size(M::Tridiagonal, d::Integer) end end -function convert{T}(::Type{Matrix{T}}, M::Tridiagonal{T}) +function convert(::Type{Matrix{T}}, M::Tridiagonal{T}) where T A = zeros(T, size(M)) for i = 1:length(M.d) A[i,i] = M.d[i] @@ -496,10 +496,10 @@ function convert{T}(::Type{Matrix{T}}, M::Tridiagonal{T}) end A end -convert{T}(::Type{Matrix}, M::Tridiagonal{T}) = convert(Matrix{T}, M) +convert(::Type{Matrix}, M::Tridiagonal{T}) where {T} = convert(Matrix{T}, M) convert(::Type{Array}, M::Tridiagonal) = convert(Matrix, M) full(M::Tridiagonal) = convert(Array, M) -function similar{T}(M::Tridiagonal, ::Type{T}) +function similar(M::Tridiagonal, ::Type{T}) where T Tridiagonal{T}(similar(M.dl, T), similar(M.d, T), similar(M.du, T), similar(M.du2, T)) end @@ -543,7 +543,7 @@ function diag{T}(M::Tridiagonal{T}, n::Integer=0) end end -function getindex{T}(A::Tridiagonal{T}, i::Integer, j::Integer) +function getindex(A::Tridiagonal{T}, i::Integer, j::Integer) where T if !(1 <= i <= size(A,2) && 1 <= j <= size(A,2)) throw(BoundsError(A, (i,j))) end @@ -634,10 +634,10 @@ end inv(A::Tridiagonal) = inv_usmani(A.dl, A.d, A.du) det(A::Tridiagonal) = det_usmani(A.dl, A.d, A.du) -convert{T}(::Type{Tridiagonal{T}},M::Tridiagonal) = Tridiagonal(convert(Vector{T}, M.dl), convert(Vector{T}, M.d), convert(Vector{T}, M.du), convert(Vector{T}, M.du2)) -convert{T}(::Type{AbstractMatrix{T}},M::Tridiagonal) = convert(Tridiagonal{T}, M) -convert{T}(::Type{Tridiagonal{T}}, M::SymTridiagonal{T}) = Tridiagonal(M) -function convert{T}(::Type{SymTridiagonal{T}}, M::Tridiagonal) +convert(::Type{Tridiagonal{T}},M::Tridiagonal) where {T} = Tridiagonal(convert(Vector{T}, M.dl), convert(Vector{T}, M.d), convert(Vector{T}, M.du), convert(Vector{T}, M.du2)) +convert(::Type{AbstractMatrix{T}},M::Tridiagonal) where {T} = convert(Tridiagonal{T}, M) +convert(::Type{Tridiagonal{T}}, M::SymTridiagonal{T}) where {T} = Tridiagonal(M) +function convert(::Type{SymTridiagonal{T}}, M::Tridiagonal) where T if M.dl == M.du return SymTridiagonal(convert(Vector{T},M.d), convert(Vector{T},M.dl)) else diff --git a/base/linalg/uniformscaling.jl b/base/linalg/uniformscaling.jl index d976aacc43f6f..fb4d2fd661bef 100644 --- a/base/linalg/uniformscaling.jl +++ b/base/linalg/uniformscaling.jl @@ -27,7 +27,7 @@ julia> [1 2im 3; 1im 2 3] * I """ const I = UniformScaling(1) -eltype{T}(::Type{UniformScaling{T}}) = T +eltype(::Type{UniformScaling{T}}) where {T} = T ndims(J::UniformScaling) = 2 getindex(J::UniformScaling, i::Integer,j::Integer) = ifelse(i==j,J.λ,zero(J.λ)) @@ -37,12 +37,12 @@ copy(J::UniformScaling) = UniformScaling(J.λ) transpose(J::UniformScaling) = J ctranspose(J::UniformScaling) = UniformScaling(conj(J.λ)) -one{T}(::Type{UniformScaling{T}}) = UniformScaling(one(T)) -one{T}(J::UniformScaling{T}) = one(UniformScaling{T}) -oneunit{T}(::Type{UniformScaling{T}}) = UniformScaling(oneunit(T)) -oneunit{T}(J::UniformScaling{T}) = oneunit(UniformScaling{T}) -zero{T}(::Type{UniformScaling{T}}) = UniformScaling(zero(T)) -zero{T}(J::UniformScaling{T}) = zero(UniformScaling{T}) +one(::Type{UniformScaling{T}}) where {T} = UniformScaling(one(T)) +one(J::UniformScaling{T}) where {T} = one(UniformScaling{T}) +oneunit(::Type{UniformScaling{T}}) where {T} = UniformScaling(oneunit(T)) +oneunit(J::UniformScaling{T}) where {T} = oneunit(UniformScaling{T}) +zero(::Type{UniformScaling{T}}) where {T} = UniformScaling(zero(T)) +zero(J::UniformScaling{T}) where {T} = zero(UniformScaling{T}) istriu(::UniformScaling) = true istril(::UniformScaling) = true @@ -109,7 +109,7 @@ function (-)(J::UniformScaling, UL::Union{LowerTriangular,UnitLowerTriangular}) return LowerTriangular(ULnew) end -function (+){TA,TJ}(A::AbstractMatrix{TA}, J::UniformScaling{TJ}) +function (+)(A::AbstractMatrix{TA}, J::UniformScaling{TJ}) where {TA,TJ} n = checksquare(A) B = similar(A, promote_type(TA,TJ)) copy!(B,A) @@ -119,7 +119,7 @@ function (+){TA,TJ}(A::AbstractMatrix{TA}, J::UniformScaling{TJ}) B end -function (-){TA,TJ<:Number}(A::AbstractMatrix{TA}, J::UniformScaling{TJ}) +function (-)(A::AbstractMatrix{TA}, J::UniformScaling{TJ}) where {TA,TJ<:Number} n = checksquare(A) B = similar(A, promote_type(TA,TJ)) copy!(B, A) @@ -128,7 +128,7 @@ function (-){TA,TJ<:Number}(A::AbstractMatrix{TA}, J::UniformScaling{TJ}) end B end -function (-){TA,TJ<:Number}(J::UniformScaling{TJ}, A::AbstractMatrix{TA}) +function (-)(J::UniformScaling{TJ}, A::AbstractMatrix{TA}) where {TA,TJ<:Number} n = checksquare(A) B = convert(AbstractMatrix{promote_type(TJ,TA)}, -A) @inbounds for j = 1:n @@ -154,7 +154,7 @@ inv(J::UniformScaling) = UniformScaling(inv(J.λ)) /(J::UniformScaling, x::Number) = UniformScaling(J.λ/x) \(J1::UniformScaling, J2::UniformScaling) = J1.λ == 0 ? throw(SingularException(1)) : UniformScaling(J1.λ\J2.λ) -\{T<:Number}(A::Union{Bidiagonal{T},AbstractTriangular{T}}, J::UniformScaling) = scale!(inv(A), J.λ) +\(A::Union{Bidiagonal{T},AbstractTriangular{T}}, J::UniformScaling) where {T<:Number} = scale!(inv(A), J.λ) \(J::UniformScaling, A::AbstractVecOrMat) = J.λ == 0 ? throw(SingularException(1)) : J.λ\A \(A::AbstractMatrix, J::UniformScaling) = scale!(inv(A), J.λ) @@ -167,8 +167,8 @@ broadcast(::typeof(/), J::UniformScaling,x::Number) = UniformScaling(J.λ/x) ==(J1::UniformScaling,J2::UniformScaling) = (J1.λ == J2.λ) -function isapprox{T<:Number,S<:Number}(J1::UniformScaling{T}, J2::UniformScaling{S}; - rtol::Real=Base.rtoldefault(T,S), atol::Real=0, nans::Bool=false) +function isapprox(J1::UniformScaling{T}, J2::UniformScaling{S}; + rtol::Real=Base.rtoldefault(T,S), atol::Real=0, nans::Bool=false) where {T<:Number,S<:Number} isapprox(J1.λ, J2.λ, rtol=rtol, atol=atol, nans=nans) end @@ -182,7 +182,7 @@ function copy!(A::AbstractMatrix, J::UniformScaling) return A end -function cond{T}(J::UniformScaling{T}) +function cond(J::UniformScaling{T}) where T onereal = inv(one(real(J.λ))) return J.λ ≠ zero(T) ? onereal : oftype(onereal, Inf) end diff --git a/base/markdown/render/html.jl b/base/markdown/render/html.jl index 7e2f256f4aa5c..fc1962270da52 100644 --- a/base/markdown/render/html.jl +++ b/base/markdown/render/html.jl @@ -39,12 +39,12 @@ end function htmlesc(io::IO, s::Symbol) htmlesc(io, string(s)) end -function htmlesc(io::IO, xs::Union{AbstractString, Symbol}...) +function htmlesc(io::IO, xs::Union{AbstractString,Symbol}...) for s in xs htmlesc(io, s) end end -function htmlesc(s::Union{AbstractString, Symbol}) +function htmlesc(s::Union{AbstractString,Symbol}) sprint(htmlesc, s) end @@ -139,7 +139,7 @@ function htmlinline(io::IO, code::Code) end end -function htmlinline(io::IO, md::Union{Symbol, AbstractString}) +function htmlinline(io::IO, md::Union{Symbol,AbstractString}) htmlesc(io, md) end diff --git a/base/multidimensional.jl b/base/multidimensional.jl index e519f293c834d..bf275c92701b0 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -59,33 +59,33 @@ module IteratorsMD getindex(index::CartesianIndex, i::Integer) = index.I[i] # zeros and ones - zero{N}(::CartesianIndex{N}) = zero(CartesianIndex{N}) - zero{N}(::Type{CartesianIndex{N}}) = CartesianIndex(ntuple(x -> 0, Val{N})) - one{N}(::CartesianIndex{N}) = one(CartesianIndex{N}) - one{N}(::Type{CartesianIndex{N}}) = CartesianIndex(ntuple(x -> 1, Val{N})) + zero(::CartesianIndex{N}) where {N} = zero(CartesianIndex{N}) + zero(::Type{CartesianIndex{N}}) where {N} = CartesianIndex(ntuple(x -> 0, Val{N})) + one(::CartesianIndex{N}) where {N} = one(CartesianIndex{N}) + one(::Type{CartesianIndex{N}}) where {N} = CartesianIndex(ntuple(x -> 1, Val{N})) # arithmetic, min/max - @inline (-){N}(index::CartesianIndex{N}) = + @inline (-)(index::CartesianIndex{N}) where {N} = CartesianIndex{N}(map(-, index.I)) - @inline (+){N}(index1::CartesianIndex{N}, index2::CartesianIndex{N}) = + @inline (+)(index1::CartesianIndex{N}, index2::CartesianIndex{N}) where {N} = CartesianIndex{N}(map(+, index1.I, index2.I)) - @inline (-){N}(index1::CartesianIndex{N}, index2::CartesianIndex{N}) = + @inline (-)(index1::CartesianIndex{N}, index2::CartesianIndex{N}) where {N} = CartesianIndex{N}(map(-, index1.I, index2.I)) - @inline min{N}(index1::CartesianIndex{N}, index2::CartesianIndex{N}) = + @inline min(index1::CartesianIndex{N}, index2::CartesianIndex{N}) where {N} = CartesianIndex{N}(map(min, index1.I, index2.I)) - @inline max{N}(index1::CartesianIndex{N}, index2::CartesianIndex{N}) = + @inline max(index1::CartesianIndex{N}, index2::CartesianIndex{N}) where {N} = CartesianIndex{N}(map(max, index1.I, index2.I)) @inline (+)(i::Integer, index::CartesianIndex) = index+i - @inline (+){N}(index::CartesianIndex{N}, i::Integer) = CartesianIndex{N}(map(x->x+i, index.I)) - @inline (-){N}(index::CartesianIndex{N}, i::Integer) = CartesianIndex{N}(map(x->x-i, index.I)) - @inline (-){N}(i::Integer, index::CartesianIndex{N}) = CartesianIndex{N}(map(x->i-x, index.I)) - @inline (*){N}(a::Integer, index::CartesianIndex{N}) = CartesianIndex{N}(map(x->a*x, index.I)) - @inline (*)(index::CartesianIndex,a::Integer)=*(a,index) + @inline (+)(index::CartesianIndex{N}, i::Integer) where {N} = CartesianIndex{N}(map(x->x+i, index.I)) + @inline (-)(index::CartesianIndex{N}, i::Integer) where {N} = CartesianIndex{N}(map(x->x-i, index.I)) + @inline (-)(i::Integer, index::CartesianIndex{N}) where {N} = CartesianIndex{N}(map(x->i-x, index.I)) + @inline (*)(a::Integer, index::CartesianIndex{N}) where {N} = CartesianIndex{N}(map(x->a*x, index.I)) + @inline (*)(index::CartesianIndex, a::Integer) = *(a,index) # comparison - @inline isless{N}(I1::CartesianIndex{N}, I2::CartesianIndex{N}) = _isless(0, I1.I, I2.I) - @inline function _isless{N}(ret, I1::NTuple{N,Int}, I2::NTuple{N,Int}) + @inline isless(I1::CartesianIndex{N}, I2::CartesianIndex{N}) where {N} = _isless(0, I1.I, I2.I) + @inline function _isless(ret, I1::NTuple{N,Int}, I2::NTuple{N,Int}) where N newret = ifelse(ret==0, icmp(I1[N], I2[N]), ret) _isless(newret, Base.front(I1), Base.front(I2)) end @@ -133,7 +133,7 @@ module IteratorsMD convert(Tuple{Vararg{UnitRange{Int}}}, R) ndims(R::CartesianRange) = length(R.start) - ndims{I<:CartesianIndex}(::Type{CartesianRange{I}}) = length(I) + ndims(::Type{CartesianRange{I}}) where {I<:CartesianIndex} = length(I) eachindex(::IndexCartesian, A::AbstractArray) = CartesianRange(indices(A)) @@ -155,7 +155,7 @@ module IteratorsMD end iter.start end - @inline function next{I<:CartesianIndex}(iter::CartesianRange{I}, state) + @inline function next(iter::CartesianRange{I}, state) where I<:CartesianIndex state, I(inc(state.I, iter.start.I, iter.stop.I)) end # increment & carry @@ -283,7 +283,7 @@ end @inline function index_ndims(i1::CartesianIndex, I...) (map(x->true, i1.I)..., index_ndims(I...)...) end -@inline function index_ndims{N}(i1::AbstractArray{CartesianIndex{N}}, I...) +@inline function index_ndims(i1::AbstractArray{CartesianIndex{N}}, I...) where N (ntuple(x->true, Val{N})..., index_ndims(I...)...) end index_ndims() = () @@ -528,13 +528,13 @@ end # see discussion in #18364 ... we try not to widen type of the resulting array # from cumsum or cumprod, but in some cases (+, Bool) we may not have a choice. -rcum_promote_type{T,S<:Number}(op, ::Type{T}, ::Type{S}) = promote_op(op, T, S) -rcum_promote_type{T<:Number}(op, ::Type{T}) = rcum_promote_type(op, T,T) -rcum_promote_type{T}(op, ::Type{T}) = T +rcum_promote_type(op, ::Type{T}, ::Type{S}) where {T,S<:Number} = promote_op(op, T, S) +rcum_promote_type(op, ::Type{T}) where {T<:Number} = rcum_promote_type(op, T,T) +rcum_promote_type(op, ::Type{T}) where {T} = T # handle sums of Vector{Bool} and similar. it would be nice to handle # any AbstractArray here, but it's not clear how that would be possible -rcum_promote_type{T,N}(op, ::Type{Array{T,N}}) = Array{rcum_promote_type(op,T), N} +rcum_promote_type(op, ::Type{Array{T,N}}) where {T,N} = Array{rcum_promote_type(op,T), N} # accumulate_pairwise slightly slower then accumulate, but more numerically # stable in certain situations (e.g. sums). @@ -784,7 +784,7 @@ end ### from abstractarray.jl -function fill!{T}(A::AbstractArray{T}, x) +function fill!(A::AbstractArray{T}, x) where T xT = convert(T, x) for I in eachindex(A) @inbounds A[I] = xT @@ -799,7 +799,7 @@ Copy all elements from collection `src` to array `dest`. """ copy!(dest, src) -function copy!{T,N}(dest::AbstractArray{T,N}, src::AbstractArray{T,N}) +function copy!(dest::AbstractArray{T,N}, src::AbstractArray{T,N}) where {T,N} @boundscheck checkbounds(dest, indices(src)...) for I in eachindex(IndexStyle(src,dest), src) @inbounds dest[I] = src[I] @@ -1195,7 +1195,7 @@ end ## findn -@generated function findn{N}(B::BitArray{N}) +@generated function findn(B::BitArray{N}) where N quote nnzB = countnz(B) I = ntuple(x->Vector{Int}(nnzB), Val{$N}) @@ -1255,7 +1255,7 @@ function checkdims_perm{TP,TB,N}(P::AbstractArray{TP,N}, B::AbstractArray{TB,N}, end for (V, PT, BT) in [((:N,), BitArray, BitArray), ((:T,:N), Array, StridedArray)] - @eval @generated function permutedims!{$(V...)}(P::$PT{$(V...)}, B::$BT{$(V...)}, perm) + @eval @generated function permutedims!(P::$PT{$(V...)}, B::$BT{$(V...)}, perm) where $(V...) quote checkdims_perm(P, B, perm) diff --git a/base/multimedia.jl b/base/multimedia.jl index 9314d4b5ab553..d4c1b15f7b58a 100644 --- a/base/multimedia.jl +++ b/base/multimedia.jl @@ -18,7 +18,7 @@ import Base: MIME, @MIME_str import Base: show, print, string, convert MIME(s) = MIME{Symbol(s)}() -show{mime}(io::IO, ::MIME{mime}) = print(io, "MIME type ", string(mime)) +show(io::IO, ::MIME{mime}) where {mime} = print(io, "MIME type ", string(mime)) print{mime}(io::IO, ::MIME{mime}) = print(io, mime) ########################################################################### diff --git a/base/multinverses.jl b/base/multinverses.jl index 39109d16bcac8..cf11ca296d9d8 100644 --- a/base/multinverses.jl +++ b/base/multinverses.jl @@ -134,21 +134,21 @@ struct UnsignedMultiplicativeInverse{T<:Unsigned} <: MultiplicativeInverse{T} end UnsignedMultiplicativeInverse(x::Unsigned) = UnsignedMultiplicativeInverse{typeof(x)}(x) -function div{T}(a::T, b::SignedMultiplicativeInverse{T}) +function div(a::T, b::SignedMultiplicativeInverse{T}) where T x = ((widen(a)*b.multiplier) >>> sizeof(a)*8) % T x += (a*b.addmul) % T ifelse(abs(b.divisor) == 1, a*b.divisor, (signbit(x) + (x >> b.shift)) % T) end -function div{T}(a::T, b::UnsignedMultiplicativeInverse{T}) +function div(a::T, b::UnsignedMultiplicativeInverse{T}) where T x = ((widen(a)*b.multiplier) >>> sizeof(a)*8) % T x = ifelse(b.add, convert(T, convert(T, (convert(T, a - x) >>> 1)) + x), x) ifelse(b.divisor == 1, a, x >>> b.shift) end -rem{T}(a::T, b::MultiplicativeInverse{T}) = +rem(a::T, b::MultiplicativeInverse{T}) where {T} = a - div(a, b)*b.divisor -function divrem{T}(a::T, b::MultiplicativeInverse{T}) +function divrem(a::T, b::MultiplicativeInverse{T}) where T d = div(a, b) (d, a - d*b.divisor) end diff --git a/base/nullable.jl b/base/nullable.jl index 478e41da2d058..bda2004e39111 100644 --- a/base/nullable.jl +++ b/base/nullable.jl @@ -39,7 +39,7 @@ eltype(::Type{Nullable{T}}) where {T} = T convert(::Type{Nullable{T}}, x::Nullable{T}) where {T} = x convert(::Type{Nullable }, x::Nullable ) = x -convert{T}(t::Type{Nullable{T}}, x::Any) = convert(t, convert(T, x)) +convert(t::Type{Nullable{T}}, x::Any) where {T} = convert(t, convert(T, x)) function convert(::Type{Nullable{T}}, x::Nullable) where T return isnull(x) ? Nullable{T}() : Nullable{T}(convert(T, get(x))) @@ -52,8 +52,8 @@ convert(::Type{Nullable }, x::T) where {T} = Nullable{T}(x) convert(::Type{Nullable{T}}, ::Void) where {T} = Nullable{T}() convert(::Type{Nullable }, ::Void) = Nullable{Union{}}() -promote_rule{S,T}(::Type{Nullable{S}}, ::Type{T}) = Nullable{promote_type(S, T)} -promote_rule{S,T}(::Type{Nullable{S}}, ::Type{Nullable{T}}) = Nullable{promote_type(S, T)} +promote_rule(::Type{Nullable{S}}, ::Type{T}) where {S,T} = Nullable{promote_type(S, T)} +promote_rule(::Type{Nullable{S}}, ::Type{Nullable{T}}) where {S,T} = Nullable{promote_type(S, T)} promote_op{S,T}(op::Any, ::Type{Nullable{S}}, ::Type{Nullable{T}}) = Nullable{promote_op(op, S, T)} promote_op{S,T}(op::Type, ::Type{Nullable{S}}, ::Type{Nullable{T}}) = Nullable{promote_op(op, S, T)} @@ -277,7 +277,7 @@ implementation detail, but typically the choice that maximizes performance would be used. If `x` has a value, then the return type is guaranteed to be of type `Nullable{typeof(f(x))}`. """ -function map{T}(f, x::Nullable{T}) +function map(f, x::Nullable{T}) where T S = promote_op(f, T) if isleaftype(S) && null_safe_op(f, T) Nullable(f(unsafe_get(x)), !isnull(x)) diff --git a/base/number.jl b/base/number.jl index bd5deb2bca776..b5bf38622785d 100644 --- a/base/number.jl +++ b/base/number.jl @@ -128,7 +128,7 @@ map(f, x::Number, ys::Number...) = f(x, ys...) Get the additive identity element for the type of `x` (`x` can also specify the type itself). """ zero(x::Number) = oftype(x,0) -zero{T<:Number}(::Type{T}) = convert(T,0) +zero(::Type{T}) where {T<:Number} = convert(T,0) """ one(x) @@ -160,8 +160,8 @@ julia> one(Dates.Day(1)) 1 ``` """ -one{T<:Number}(::Type{T}) = convert(T,1) -one{T<:Number}(x::T) = one(T) +one(::Type{T}) where {T<:Number} = convert(T,1) +one(x::T) where {T<:Number} = one(T) # note that convert(T, 1) should throw an error if T is dimensionful, # so this fallback definition should be okay. @@ -182,8 +182,8 @@ julia> oneunit(Dates.Day) 1 day ``` """ -oneunit{T}(x::T) = T(one(x)) -oneunit{T}(::Type{T}) = T(one(T)) +oneunit(x::T) where {T} = T(one(x)) +oneunit(::Type{T}) where {T} = T(one(T)) _default_type(::Type{Number}) = Int diff --git a/base/pair.jl b/base/pair.jl index 0236fbbe482a5..22d496f40c8ed 100644 --- a/base/pair.jl +++ b/base/pair.jl @@ -10,7 +10,7 @@ const => = Pair start(p::Pair) = 1 done(p::Pair, i) = i>2 next(p::Pair, i) = (getfield(p,i), i+1) -eltype{A,B}(p::Pair{A,B}) = Union{A,B} +eltype(p::Pair{A,B}) where {A,B} = Union{A,B} indexed_next(p::Pair, i::Int, state) = (getfield(p,i), i+1) @@ -31,9 +31,9 @@ first(p::Pair) = p.first last(p::Pair) = p.second convert(::Type{Pair{A,B}}, x::Pair{A,B}) where {A,B} = x -function convert(::Type{Pair{A,B}}, x::Pair) where A where B - Pair{A, B}(convert(A, x[1]), convert(B, x[2])) +function convert(::Type{Pair{A,B}}, x::Pair) where {A,B} + Pair{A,B}(convert(A, x[1]), convert(B, x[2])) end -promote_rule{A1, B1, A2, B2}(::Type{Pair{A1, B1}}, ::Type{Pair{A2, B2}}) = +promote_rule(::Type{Pair{A1,B1}}, ::Type{Pair{A2,B2}}) where {A1,B1,A2,B2} = Pair{promote_type(A1, A2), promote_type(B1, B2)} diff --git a/base/pointer.jl b/base/pointer.jl index 4f14eb562431b..20f3b05c40785 100644 --- a/base/pointer.jl +++ b/base/pointer.jl @@ -20,7 +20,7 @@ const C_NULL = bitcast(Ptr{Void}, 0) # TODO: deprecate these conversions. C doesn't even allow them. # pointer to integer -convert{T<:Union{Int,UInt}}(::Type{T}, x::Ptr) = bitcast(T, x) +convert(::Type{T}, x::Ptr) where {T<:Union{Int,UInt}} = bitcast(T, x) convert(::Type{T}, x::Ptr) where {T<:Integer} = convert(T, convert(UInt, x)) # integer to pointer diff --git a/base/profile.jl b/base/profile.jl index 55816bda55ce9..7ec228c19c427 100644 --- a/base/profile.jl +++ b/base/profile.jl @@ -316,7 +316,7 @@ const btskip = 0 ## Print as a flat list # Counts the number of times each line appears, at any nesting level -function count_flat{T<:Unsigned}(data::Vector{T}) +function count_flat(data::Vector{T}) where T<:Unsigned linecount = Dict{T,Int}() toskip = btskip for ip in data diff --git a/base/promotion.jl b/base/promotion.jl index 2f78d66354aec..f7918422262e8 100644 --- a/base/promotion.jl +++ b/base/promotion.jl @@ -127,9 +127,9 @@ promote_type(T) = (@_pure_meta; T) promote_type(T, S, U, V...) = (@_pure_meta; promote_type(T, promote_type(S, U, V...))) promote_type(::Type{Bottom}, ::Type{Bottom}) = (@_pure_meta; Bottom) -promote_type{T}(::Type{T}, ::Type{T}) = (@_pure_meta; T) -promote_type{T}(::Type{T}, ::Type{Bottom}) = (@_pure_meta; T) -promote_type{T}(::Type{Bottom}, ::Type{T}) = (@_pure_meta; T) +promote_type(::Type{T}, ::Type{T}) where {T} = (@_pure_meta; T) +promote_type(::Type{T}, ::Type{Bottom}) where {T} = (@_pure_meta; T) +promote_type(::Type{Bottom}, ::Type{T}) where {T} = (@_pure_meta; T) """ promote_type(type1, type2) @@ -151,7 +151,7 @@ julia> promote_type(Float32, BigInt) BigFloat ``` """ -function promote_type{T,S}(::Type{T}, ::Type{S}) +function promote_type(::Type{T}, ::Type{S}) where {T,S} @_pure_meta # Try promote_rule in both orders. Typically only one is defined, # and there is a fallback returning Bottom below, so the common case is @@ -166,11 +166,11 @@ promote_rule(T, S) = (@_pure_meta; Bottom) promote_result(t,s,T,S) = (@_pure_meta; promote_type(T,S)) # If no promote_rule is defined, both directions give Bottom. In that # case use typejoin on the original types instead. -promote_result{T,S}(::Type{T},::Type{S},::Type{Bottom},::Type{Bottom}) = (@_pure_meta; typejoin(T, S)) +promote_result(::Type{T},::Type{S},::Type{Bottom},::Type{Bottom}) where {T,S} = (@_pure_meta; typejoin(T, S)) promote() = () promote(x) = (x,) -function promote{T,S}(x::T, y::S) +function promote(x::T, y::S) where {T,S} (convert(promote_type(T,S),x), convert(promote_type(T,S),y)) end promote_typeof(x) = (@_pure_meta; typeof(x)) @@ -194,7 +194,7 @@ end # Otherwise, typejoin(T,S) is called (returning Number) so no conversion # happens, and +(promote(x,y)...) is called again, causing a stack # overflow. -function promote_result{T<:Number,S<:Number}(::Type{T},::Type{S},::Type{Bottom},::Type{Bottom}) +function promote_result(::Type{T},::Type{S},::Type{Bottom},::Type{Bottom}) where {T<:Number,S<:Number} @_pure_meta promote_to_supertype(T, S, typejoin(T,S)) end @@ -202,10 +202,10 @@ end # promote numeric types T and S to typejoin(T,S) if T<:S or S<:T # for example this makes promote_type(Integer,Real) == Real without # promoting arbitrary pairs of numeric types to Number. -promote_to_supertype{T<:Number }(::Type{T}, ::Type{T}, ::Type{T}) = (@_pure_meta; T) -promote_to_supertype{T<:Number,S<:Number}(::Type{T}, ::Type{S}, ::Type{T}) = (@_pure_meta; T) -promote_to_supertype{T<:Number,S<:Number}(::Type{T}, ::Type{S}, ::Type{S}) = (@_pure_meta; S) -promote_to_supertype{T<:Number,S<:Number}(::Type{T}, ::Type{S}, ::Type) = +promote_to_supertype(::Type{T}, ::Type{T}, ::Type{T}) where {T<:Number} = (@_pure_meta; T) +promote_to_supertype(::Type{T}, ::Type{S}, ::Type{T}) where {T<:Number,S<:Number} = (@_pure_meta; T) +promote_to_supertype(::Type{T}, ::Type{S}, ::Type{S}) where {T<:Number,S<:Number} = (@_pure_meta; S) +promote_to_supertype(::Type{T}, ::Type{S}, ::Type) where {T<:Number,S<:Number} = error("no promotion exists for ", T, " and ", S) # promotion with a check for circularity. Can be used to catch what @@ -229,9 +229,9 @@ function promote_noncircular(x, y, z, a...) end not_all_sametype(x, y) = nothing not_all_sametype(x, y, z) = nothing -not_all_sametype{S,T}(x::Tuple{S,S}, y::Tuple{T,T}) = sametype_error(x[1], y[1]) -not_all_sametype{R,S,T}(x::Tuple{R,R}, y::Tuple{S,S}, z::Tuple{T,T}) = sametype_error(x[1], y[1], z[1]) -function not_all_sametype{R,S,T}(::Tuple{R,R}, y::Tuple{S,S}, z::Tuple{T,T}, args...) +not_all_sametype(x::Tuple{S,S}, y::Tuple{T,T}) where {S,T} = sametype_error(x[1], y[1]) +not_all_sametype(x::Tuple{R,R}, y::Tuple{S,S}, z::Tuple{T,T}) where {R,S,T} = sametype_error(x[1], y[1], z[1]) +function not_all_sametype(::Tuple{R,R}, y::Tuple{S,S}, z::Tuple{T,T}, args...) where {R,S,T} @_inline_meta not_all_sametype(y, z, args...) end @@ -329,31 +329,31 @@ end ## catch-alls to prevent infinite recursion when definitions are missing ## no_op_err(name, T) = error(name," not defined for ",T) -+{T<:Number}(x::T, y::T) = no_op_err("+", T) -*{T<:Number}(x::T, y::T) = no_op_err("*", T) --{T<:Number}(x::T, y::T) = no_op_err("-", T) -/{T<:Number}(x::T, y::T) = no_op_err("/", T) -^{T<:Number}(x::T, y::T) = no_op_err("^", T) +(+)(x::T, y::T) where {T<:Number} = no_op_err("+", T) +(*)(x::T, y::T) where {T<:Number} = no_op_err("*", T) +(-)(x::T, y::T) where {T<:Number} = no_op_err("-", T) +(/)(x::T, y::T) where {T<:Number} = no_op_err("/", T) +(^)(x::T, y::T) where {T<:Number} = no_op_err("^", T) -fma{T<:Number}(x::T, y::T, z::T) = no_op_err("fma", T) +fma(x::T, y::T, z::T) where {T<:Number} = no_op_err("fma", T) fma(x::Integer, y::Integer, z::Integer) = x*y+z -muladd{T<:Number}(x::T, y::T, z::T) = x*y+z +muladd(x::T, y::T, z::T) where {T<:Number} = x*y+z -(&){T<:Integer}(x::T, y::T) = no_op_err("&", T) -(|){T<:Integer}(x::T, y::T) = no_op_err("|", T) -xor{T<:Integer}(x::T, y::T) = no_op_err("xor", T) +(&)(x::T, y::T) where {T<:Integer} = no_op_err("&", T) +(|)(x::T, y::T) where {T<:Integer} = no_op_err("|", T) +xor(x::T, y::T) where {T<:Integer} = no_op_err("xor", T) -=={T<:Number}(x::T, y::T) = x === y - <{T<:Real}(x::T, y::T) = no_op_err("<" , T) -<={T<:Real}(x::T, y::T) = no_op_err("<=", T) +(==)(x::T, y::T) where {T<:Number} = x === y +(< )(x::T, y::T) where {T<:Real} = no_op_err("<" , T) +(<=)(x::T, y::T) where {T<:Real} = no_op_err("<=", T) -rem{T<:Real}(x::T, y::T) = no_op_err("rem", T) -mod{T<:Real}(x::T, y::T) = no_op_err("mod", T) +rem(x::T, y::T) where {T<:Real} = no_op_err("rem", T) +mod(x::T, y::T) where {T<:Real} = no_op_err("mod", T) min(x::Real) = x max(x::Real) = x minmax(x::Real) = (x, x) -max{T<:Real}(x::T, y::T) = select_value(y < x, x, y) -min{T<:Real}(x::T, y::T) = select_value(y < x, y, x) -minmax{T<:Real}(x::T, y::T) = y < x ? (y, x) : (x, y) +max(x::T, y::T) where {T<:Real} = select_value(y < x, x, y) +min(x::T, y::T) where {T<:Real} = select_value(y < x, y, x) +minmax(x::T, y::T) where {T<:Real} = y < x ? (y, x) : (x, y) diff --git a/base/range.jl b/base/range.jl index f3d5cfca90c5c..393b8cd9d3dd7 100644 --- a/base/range.jl +++ b/base/range.jl @@ -2,17 +2,17 @@ colon(a::Real, b::Real) = colon(promote(a,b)...) -colon{T<:Real}(start::T, stop::T) = UnitRange{T}(start, stop) +colon(start::T, stop::T) where {T<:Real} = UnitRange{T}(start, stop) range(a::Real, len::Integer) = UnitRange{typeof(a)}(a, oftype(a, a+len-1)) -colon{T}(start::T, stop::T) = colon(start, oftype(stop-start, 1), stop) +colon(start::T, stop::T) where {T} = colon(start, oftype(stop-start, 1), stop) range(a, len::Integer) = range(a, oftype(a-a, 1), len) # first promote start and stop, leaving step alone -colon{A<:Real,C<:Real}(start::A, step, stop::C) = colon(convert(promote_type(A,C),start), step, convert(promote_type(A,C),stop)) -colon{T<:Real}(start::T, step::Real, stop::T) = colon(promote(start, step, stop)...) +colon(start::A, step, stop::C) where {A<:Real,C<:Real} = colon(convert(promote_type(A,C),start), step, convert(promote_type(A,C),stop)) +colon(start::T, step::Real, stop::T) where {T<:Real} = colon(promote(start, step, stop)...) """ colon(start, [step], stop) @@ -24,8 +24,8 @@ julia> colon(1, 2, 5) 1:2:5 ``` """ -colon{T<:AbstractFloat}(start::T, step::T, stop::T) = _colon(TypeOrder(T), TypeArithmetic(T), start, step, stop) -colon{T<:Real}(start::T, step::T, stop::T) = _colon(TypeOrder(T), TypeArithmetic(T), start, step, stop) +colon(start::T, step::T, stop::T) where {T<:AbstractFloat} = _colon(TypeOrder(T), TypeArithmetic(T), start, step, stop) +colon(start::T, step::T, stop::T) where {T<:Real} = _colon(TypeOrder(T), TypeArithmetic(T), start, step, stop) _colon{T}(::HasOrder, ::Any, start::T, step, stop::T) = StepRange(start, step, stop) # for T<:Union{Float16,Float32,Float64} see twiceprecision.jl _colon{T}(::HasOrder, ::ArithmeticRounds, start::T, step, stop::T) = StepRangeLen(start, step, floor(Int, (stop-start)/step)+1) @@ -38,8 +38,8 @@ Range operator. `a:b` constructs a range from `a` to `b` with a step size of 1, is similar but uses a step size of `s`. These syntaxes call the function `colon`. The colon is also used in indexing to select whole dimensions. """ -colon{T}(start::T, step, stop::T) = _colon(start, step, stop) -colon{T<:Real}(start::T, step, stop::T) = _colon(start, step, stop) +colon(start::T, step, stop::T) where {T} = _colon(start, step, stop) +colon(start::T, step, stop::T) where {T<:Real} = _colon(start, step, stop) # without the second method above, the first method above is ambiguous with # colon{A<:Real,C<:Real}(start::A, step, stop::C) function _colon{T}(start::T, step, stop::T) @@ -57,12 +57,12 @@ _range{T,S}(::HasOrder, ::ArithmeticOverflows, a::T, step::S, len::Integer) = St _range{T,S}(::Any, ::Any, a::T, step::S, len::Integer) = StepRangeLen{typeof(a+0*step),T,S}(a, step, len) # AbstractFloat specializations -colon{T<:AbstractFloat}(a::T, b::T) = colon(a, T(1), b) +colon(a::T, b::T) where {T<:AbstractFloat} = colon(a, T(1), b) range(a::AbstractFloat, len::Integer) = range(a, oftype(a, 1), len) -colon{T<:Real}(a::T, b::AbstractFloat, c::T) = colon(promote(a,b,c)...) -colon{T<:AbstractFloat}(a::T, b::AbstractFloat, c::T) = colon(promote(a,b,c)...) -colon{T<:AbstractFloat}(a::T, b::Real, c::T) = colon(promote(a,b,c)...) +colon(a::T, b::AbstractFloat, c::T) where {T<:Real} = colon(promote(a,b,c)...) +colon(a::T, b::AbstractFloat, c::T) where {T<:AbstractFloat} = colon(promote(a,b,c)...) +colon(a::T, b::Real, c::T) where {T<:AbstractFloat} = colon(promote(a,b,c)...) range(a::AbstractFloat, st::AbstractFloat, len::Integer) = range(promote(a, st)..., len) range(a::Real, st::AbstractFloat, len::Integer) = range(float(a), st, len) @@ -140,9 +140,9 @@ StepRange(start::T, step::S, stop::T) where {T,S} = StepRange{T,S}(start, step, struct UnitRange{T<:Real} <: AbstractUnitRange{T} start::T stop::T - UnitRange{T}(start, stop) where T<:Real = new(start, unitrange_last(start,stop)) + UnitRange{T}(start, stop) where {T<:Real} = new(start, unitrange_last(start,stop)) end -UnitRange(start::T, stop::T) where T<:Real = UnitRange{T}(start, stop) +UnitRange(start::T, stop::T) where {T<:Real} = UnitRange{T}(start, stop) unitrange_last(::Bool, stop::Bool) = stop unitrange_last{T<:Integer}(start::T, stop::T) = @@ -165,9 +165,9 @@ be 1. """ struct OneTo{T<:Integer} <: AbstractUnitRange{T} stop::T - OneTo{T}(stop) where T<:Integer = new(max(zero(T), stop)) + OneTo{T}(stop) where {T<:Integer} = new(max(zero(T), stop)) end -OneTo(stop::T) where T<:Integer = OneTo{T}(stop) +OneTo(stop::T) where {T<:Integer} = OneTo{T}(stop) ## Step ranges parametrized by length @@ -432,21 +432,21 @@ function next(r::LinSpace, i::Int) end start(r::StepRange) = oftype(r.start + r.step, r.start) -next{T}(r::StepRange{T}, i) = (convert(T,i), i+r.step) +next(r::StepRange{T}, i) where {T} = (convert(T,i), i+r.step) done(r::StepRange, i) = isempty(r) | (i < min(r.start, r.stop)) | (i > max(r.start, r.stop)) done(r::StepRange, i::Integer) = isempty(r) | (i == oftype(i, r.stop) + r.step) # see also twiceprecision.jl start(r::StepRangeLen) = (unsafe_getindex(r, 1), 1) -next{T}(r::StepRangeLen{T}, s) = s[1], (T(s[1]+r.step), s[2]+1) +next(r::StepRangeLen{T}, s) where {T} = s[1], (T(s[1]+r.step), s[2]+1) done(r::StepRangeLen, s) = s[2] > length(r) -start{T}(r::UnitRange{T}) = oftype(r.start + oneunit(T), r.start) -next{T}(r::AbstractUnitRange{T}, i) = (convert(T, i), i + oneunit(T)) -done{T}(r::AbstractUnitRange{T}, i) = i == oftype(i, r.stop) + oneunit(T) +start(r::UnitRange{T}) where {T} = oftype(r.start + oneunit(T), r.start) +next(r::AbstractUnitRange{T}, i) where {T} = (convert(T, i), i + oneunit(T)) +done(r::AbstractUnitRange{T}, i) where {T} = i == oftype(i, r.stop) + oneunit(T) -start{T}(r::OneTo{T}) = oneunit(T) +start(r::OneTo{T}) where {T} = oneunit(T) # some special cases to favor default Int type to avoid overflow let smallint = (Int === Int64 ? @@ -455,28 +455,28 @@ let smallint = (Int === Int64 ? global start global next start(r::StepRange{<:smallint}) = convert(Int, r.start) - next{T<:smallint}(r::StepRange{T}, i) = (i % T, i + r.step) + next(r::StepRange{T}, i) where {T<:smallint} = (i % T, i + r.step) start(r::UnitRange{<:smallint}) = convert(Int, r.start) - next{T<:smallint}(r::AbstractUnitRange{T}, i) = (i % T, i + 1) + next(r::AbstractUnitRange{T}, i) where {T<:smallint} = (i % T, i + 1) start(r::OneTo{<:smallint}) = 1 end ## indexing -function getindex{T}(v::UnitRange{T}, i::Integer) +function getindex(v::UnitRange{T}, i::Integer) where T @_inline_meta ret = convert(T, first(v) + i - 1) @boundscheck ((i > 0) & (ret <= v.stop) & (ret >= v.start)) || throw_boundserror(v, i) ret end -function getindex{T}(v::OneTo{T}, i::Integer) +function getindex(v::OneTo{T}, i::Integer) where T @_inline_meta @boundscheck ((i > 0) & (i <= v.stop)) || throw_boundserror(v, i) convert(T, i) end -function getindex{T}(v::Range{T}, i::Integer) +function getindex(v::Range{T}, i::Integer) where T @_inline_meta ret = convert(T, first(v) + (i - 1)*step(v)) ok = ifelse(step(v) > zero(step(v)), @@ -493,7 +493,7 @@ function getindex(r::Union{StepRangeLen,LinSpace}, i::Integer) end # This is separate to make it useful even when running with --check-bounds=yes -function unsafe_getindex{T}(r::StepRangeLen{T}, i::Integer) +function unsafe_getindex(r::StepRangeLen{T}, i::Integer) where T u = i - r.offset T(r.ref + u*r.step) end @@ -518,7 +518,7 @@ function getindex(r::AbstractUnitRange, s::AbstractUnitRange{<:Integer}) range(st, length(s)) end -function getindex{T}(r::OneTo{T}, s::OneTo) +function getindex(r::OneTo{T}, s::OneTo) where T @_inline_meta @boundscheck checkbounds(r, s) OneTo(T(s.stop)) @@ -557,13 +557,13 @@ show(io::IO, r::Range) = print(io, repr(first(r)), ':', repr(step(r)), ':', repr show(io::IO, r::UnitRange) = print(io, repr(first(r)), ':', repr(last(r))) show(io::IO, r::OneTo) = print(io, "Base.OneTo(", r.stop, ")") -=={T<:Range}(r::T, s::T) = +==(r::T, s::T) where {T<:Range} = (first(r) == first(s)) & (step(r) == step(s)) & (last(r) == last(s)) ==(r::OrdinalRange, s::OrdinalRange) = (first(r) == first(s)) & (step(r) == step(s)) & (last(r) == last(s)) -=={T<:Union{StepRangeLen,LinSpace}}(r::T, s::T) = +==(r::T, s::T) where {T<:Union{StepRangeLen,LinSpace}} = (first(r) == first(s)) & (length(r) == length(s)) & (last(r) == last(s)) -=={T}(r::Union{StepRange{T},StepRangeLen{T,T}}, s::Union{StepRange{T},StepRangeLen{T,T}}) = +==(r::Union{StepRange{T},StepRangeLen{T,T}}, s::Union{StepRange{T},StepRangeLen{T,T}}) where {T} = (first(r) == first(s)) & (last(r) == last(s)) & (step(r) == step(s)) function ==(r::Range, s::Range) @@ -745,33 +745,33 @@ end /(x::Number, r::Range) = [ x/y for y=r ] -promote_rule{T1,T2}(::Type{UnitRange{T1}},::Type{UnitRange{T2}}) = +promote_rule(::Type{UnitRange{T1}},::Type{UnitRange{T2}}) where {T1,T2} = UnitRange{promote_type(T1,T2)} convert(::Type{UnitRange{T}}, r::UnitRange{T}) where {T<:Real} = r convert(::Type{UnitRange{T}}, r::UnitRange) where {T<:Real} = UnitRange{T}(r.start, r.stop) -promote_rule{T1,T2}(::Type{OneTo{T1}},::Type{OneTo{T2}}) = +promote_rule(::Type{OneTo{T1}},::Type{OneTo{T2}}) where {T1,T2} = OneTo{promote_type(T1,T2)} convert(::Type{OneTo{T}}, r::OneTo{T}) where {T<:Real} = r convert(::Type{OneTo{T}}, r::OneTo) where {T<:Real} = OneTo{T}(r.stop) -promote_rule{T1,UR<:AbstractUnitRange}(::Type{UnitRange{T1}}, ::Type{UR}) = +promote_rule(::Type{UnitRange{T1}}, ::Type{UR}) where {T1,UR<:AbstractUnitRange} = UnitRange{promote_type(T1,eltype(UR))} convert(::Type{UnitRange{T}}, r::AbstractUnitRange) where {T<:Real} = UnitRange{T}(first(r), last(r)) convert(::Type{UnitRange}, r::AbstractUnitRange) = UnitRange(first(r), last(r)) -promote_rule{T1a,T1b,T2a,T2b}(::Type{StepRange{T1a,T1b}},::Type{StepRange{T2a,T2b}}) = +promote_rule(::Type{StepRange{T1a,T1b}},::Type{StepRange{T2a,T2b}}) where {T1a,T1b,T2a,T2b} = StepRange{promote_type(T1a,T2a),promote_type(T1b,T2b)} convert(::Type{StepRange{T1,T2}}, r::StepRange{T1,T2}) where {T1,T2} = r -promote_rule{T1a,T1b,UR<:AbstractUnitRange}(::Type{StepRange{T1a,T1b}},::Type{UR}) = +promote_rule(::Type{StepRange{T1a,T1b}},::Type{UR}) where {T1a,T1b,UR<:AbstractUnitRange} = StepRange{promote_type(T1a,eltype(UR)),promote_type(T1b,eltype(UR))} convert(::Type{StepRange{T1,T2}}, r::Range) where {T1,T2} = StepRange{T1,T2}(convert(T1, first(r)), convert(T2, step(r)), convert(T1, last(r))) convert(::Type{StepRange}, r::AbstractUnitRange{T}) where {T} = StepRange{T,T}(first(r), step(r), last(r)) -promote_rule{T1,T2,R1,R2,S1,S2}(::Type{StepRangeLen{T1,R1,S1}},::Type{StepRangeLen{T2,R2,S2}}) = +promote_rule(::Type{StepRangeLen{T1,R1,S1}},::Type{StepRangeLen{T2,R2,S2}}) where {T1,T2,R1,R2,S1,S2} = StepRangeLen{promote_type(T1,T2), promote_type(R1,R2), promote_type(S1,S2)} convert(::Type{StepRangeLen{T,R,S}}, r::StepRangeLen{T,R,S}) where {T,R,S} = r convert(::Type{StepRangeLen{T,R,S}}, r::StepRangeLen) where {T,R,S} = @@ -779,7 +779,7 @@ convert(::Type{StepRangeLen{T,R,S}}, r::StepRangeLen) where {T,R,S} = convert(::Type{StepRangeLen{T}}, r::StepRangeLen) where {T} = StepRangeLen(convert(T, r.ref), convert(T, r.step), length(r), r.offset) -promote_rule{T,R,S,OR<:Range}(::Type{StepRangeLen{T,R,S}}, ::Type{OR}) = +promote_rule(::Type{StepRangeLen{T,R,S}}, ::Type{OR}) where {T,R,S,OR<:Range} = StepRangeLen{promote_type(T,eltype(OR)),promote_type(R,eltype(OR)),promote_type(S,eltype(OR))} convert(::Type{StepRangeLen{T,R,S}}, r::Range) where {T,R,S} = StepRangeLen{T,R,S}(R(first(r)), S(step(r)), length(r)) @@ -787,7 +787,7 @@ convert(::Type{StepRangeLen{T}}, r::Range) where {T} = StepRangeLen(T(first(r)), T(step(r)), length(r)) convert(::Type{StepRangeLen}, r::Range) = convert(StepRangeLen{eltype(r)}, r) -promote_rule{T1,T2}(::Type{LinSpace{T1}},::Type{LinSpace{T2}}) = +promote_rule(::Type{LinSpace{T1}},::Type{LinSpace{T2}}) where {T1,T2} = LinSpace{promote_type(T1,T2)} convert(::Type{LinSpace{T}}, r::LinSpace{T}) where {T} = r convert(::Type{LinSpace{T}}, r::Range) where {T} = @@ -795,17 +795,17 @@ convert(::Type{LinSpace{T}}, r::Range) where {T} = convert(::Type{LinSpace}, r::Range{T}) where {T} = convert(LinSpace{T}, r) -promote_rule{T,OR<:OrdinalRange}(::Type{LinSpace{T}}, ::Type{OR}) = +promote_rule(::Type{LinSpace{T}}, ::Type{OR}) where {T,OR<:OrdinalRange} = LinSpace{promote_type(T,eltype(OR))} -promote_rule{L,T,R,S}(::Type{LinSpace{L}}, ::Type{StepRangeLen{T,R,S}}) = +promote_rule(::Type{LinSpace{L}}, ::Type{StepRangeLen{T,R,S}}) where {L,T,R,S} = StepRangeLen{promote_type(L,T),promote_type(L,R),promote_type(L,S)} # +/- of ranges is defined in operators.jl (to be able to use @eval etc.) ## concatenation ## -function vcat{T}(rs::Range{T}...) +function vcat(rs::Range{T}...) where T n::Int = 0 for ra in rs n += length(ra) @@ -889,7 +889,7 @@ end _define_range_op(:+) _define_range_op(:-) -function +{T,S}(r1::StepRangeLen{T,S}, r2::StepRangeLen{T,S}) +function +(r1::StepRangeLen{T,S}, r2::StepRangeLen{T,S}) where {T,S} len = length(r1) (len == length(r2) || throw(DimensionMismatch("argument dimensions must match"))) diff --git a/base/rational.jl b/base/rational.jl index 1760a6ab343ef..fa13a8e14e980 100644 --- a/base/rational.jl +++ b/base/rational.jl @@ -95,9 +95,9 @@ convert(::Type{Rational}, x::Float32) = convert(Rational{Int}, x) big(z::Complex{<:Rational{<:Integer}}) = Complex{Rational{BigInt}}(z) -promote_rule{T<:Integer,S<:Integer}(::Type{Rational{T}}, ::Type{S}) = Rational{promote_type(T,S)} -promote_rule{T<:Integer,S<:Integer}(::Type{Rational{T}}, ::Type{Rational{S}}) = Rational{promote_type(T,S)} -promote_rule{T<:Integer,S<:AbstractFloat}(::Type{Rational{T}}, ::Type{S}) = promote_type(T,S) +promote_rule(::Type{Rational{T}}, ::Type{S}) where {T<:Integer,S<:Integer} = Rational{promote_type(T,S)} +promote_rule(::Type{Rational{T}}, ::Type{Rational{S}}) where {T<:Integer,S<:Integer} = Rational{promote_type(T,S)} +promote_rule(::Type{Rational{T}}, ::Type{S}) where {T<:Integer,S<:AbstractFloat} = promote_type(T,S) widen{T}(::Type{Rational{T}}) = Rational{widen(T)} @@ -224,11 +224,11 @@ typemax{T<:Integer}(::Type{Rational{T}}) = one(T)//zero(T) isinteger(x::Rational) = x.den == 1 -(x::Rational) = (-x.num) // x.den -function -{T<:Signed}(x::Rational{T}) +function -(x::Rational{T}) where T<:Signed x.num == typemin(T) && throw(OverflowError()) (-x.num) // x.den end -function -{T<:Unsigned}(x::Rational{T}) +function -(x::Rational{T}) where T<:Unsigned x.num != zero(T) && throw(OverflowError()) x end @@ -416,8 +416,8 @@ function ^(x::Rational, n::Integer) end ^(x::Number, y::Rational) = x^(y.num/y.den) -^{T<:AbstractFloat}(x::T, y::Rational) = x^convert(T,y) -^{T<:AbstractFloat}(x::Complex{T}, y::Rational) = x^convert(T,y) +^(x::T, y::Rational) where {T<:AbstractFloat} = x^convert(T,y) +^(x::Complex{T}, y::Rational) where {T<:AbstractFloat} = x^convert(T,y) ^(z::Complex{<:Rational}, n::Bool) = n ? z : one(z) # to resolve ambiguity function ^(z::Complex{<:Rational}, n::Integer) diff --git a/base/reduce.jl b/base/reduce.jl index 188d9c52eff9a..7c13c8cc104ae 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -17,19 +17,19 @@ const WidenReduceResult = Union{SmallSigned, SmallUnsigned, Float16} # r_promote_type: promote T to the type of reduce(op, ::Array{T}) # (some "extra" methods are required here to avoid ambiguity warnings) -r_promote_type{T}(op, ::Type{T}) = T -r_promote_type{T<:WidenReduceResult}(op, ::Type{T}) = widen(T) -r_promote_type{T<:WidenReduceResult}(::typeof(+), ::Type{T}) = widen(T) -r_promote_type{T<:WidenReduceResult}(::typeof(*), ::Type{T}) = widen(T) -r_promote_type{T<:Number}(::typeof(+), ::Type{T}) = typeof(zero(T)+zero(T)) -r_promote_type{T<:Number}(::typeof(*), ::Type{T}) = typeof(one(T)*one(T)) -r_promote_type{T<:WidenReduceResult}(::typeof(scalarmax), ::Type{T}) = T -r_promote_type{T<:WidenReduceResult}(::typeof(scalarmin), ::Type{T}) = T -r_promote_type{T<:WidenReduceResult}(::typeof(max), ::Type{T}) = T -r_promote_type{T<:WidenReduceResult}(::typeof(min), ::Type{T}) = T +r_promote_type(op, ::Type{T}) where {T} = T +r_promote_type(op, ::Type{T}) where {T<:WidenReduceResult} = widen(T) +r_promote_type(::typeof(+), ::Type{T}) where {T<:WidenReduceResult} = widen(T) +r_promote_type(::typeof(*), ::Type{T}) where {T<:WidenReduceResult} = widen(T) +r_promote_type(::typeof(+), ::Type{T}) where {T<:Number} = typeof(zero(T)+zero(T)) +r_promote_type(::typeof(*), ::Type{T}) where {T<:Number} = typeof(one(T)*one(T)) +r_promote_type(::typeof(scalarmax), ::Type{T}) where {T<:WidenReduceResult} = T +r_promote_type(::typeof(scalarmin), ::Type{T}) where {T<:WidenReduceResult} = T +r_promote_type(::typeof(max), ::Type{T}) where {T<:WidenReduceResult} = T +r_promote_type(::typeof(min), ::Type{T}) where {T<:WidenReduceResult} = T # r_promote: promote x to the type of reduce(op, [x]) -r_promote{T}(op, x::T) = convert(r_promote_type(op, T), x) +r_promote(op, x::T) where {T} = convert(r_promote_type(op, T), x) ## foldl && mapfoldl @@ -258,7 +258,7 @@ mr_empty_iter(f, op, itr, ::EltypeUnknown) = _empty_reduce_error() _mapreduce(f, op, A::AbstractArray) = _mapreduce(f, op, IndexStyle(A), A) -function _mapreduce{T}(f, op, ::IndexLinear, A::AbstractArray{T}) +function _mapreduce(f, op, ::IndexLinear, A::AbstractArray{T}) where T inds = linearindices(A) n = length(inds) if n == 0 diff --git a/base/reducedim.jl b/base/reducedim.jl index b6592764952b1..1095fcf41f79d 100644 --- a/base/reducedim.jl +++ b/base/reducedim.jl @@ -8,7 +8,7 @@ reduced_indices(a::AbstractArray, region) = reduced_indices(indices(a), region) # for reductions that keep 0 dims as 0 reduced_indices0(a::AbstractArray, region) = reduced_indices0(indices(a), region) -function reduced_indices{N}(inds::Indices{N}, d::Int, rd::AbstractUnitRange) +function reduced_indices(inds::Indices{N}, d::Int, rd::AbstractUnitRange) where N d < 1 && throw(ArgumentError("dimension must be ≥ 1, got $d")) if d == 1 return (oftype(inds[1], rd), tail(inds)...) @@ -29,7 +29,7 @@ function reduced_indices0{N}(inds::Indices{N}, d::Int) end end -function reduced_indices{N}(inds::Indices{N}, region) +function reduced_indices(inds::Indices{N}, region) where N rinds = [inds...] for i in region isa(i, Integer) || throw(ArgumentError("reduced dimension(s) must be integers")) diff --git a/base/refpointer.jl b/base/refpointer.jl index 8671f215c595e..11ef66c0d3148 100644 --- a/base/refpointer.jl +++ b/base/refpointer.jl @@ -27,7 +27,7 @@ end ### General Methods for Ref{T} type -eltype{T}(x::Type{Ref{T}}) = T +eltype(x::Type{Ref{T}}) where {T} = T convert(::Type{Ref{T}}, x::Ref{T}) where {T} = x # create Ref objects for general object conversion @@ -48,11 +48,11 @@ Ref(x::Ref) = x Ref(x::Any) = RefValue(x) Ref{T}(x::Ptr{T}, i::Integer=1) = x + (i-1)*Core.sizeof(T) Ref(x, i::Integer) = (i != 1 && error("Object only has one element"); Ref(x)) -(::Type{Ref{T}}){T}() = RefValue{T}() # Ref{T}() -(::Type{Ref{T}}){T}(x) = RefValue{T}(x) # Ref{T}(x) +(::Type{Ref{T}})() where {T} = RefValue{T}() # Ref{T}() +(::Type{Ref{T}})(x) where {T} = RefValue{T}(x) # Ref{T}(x) convert(::Type{Ref{T}}, x) where {T} = RefValue{T}(x) -function unsafe_convert{T}(P::Type{Ptr{T}}, b::RefValue{T}) +function unsafe_convert(P::Type{Ptr{T}}, b::RefValue{T}) where T if isbits(T) return convert(P, data_pointer_from_objref(b)) else @@ -76,7 +76,7 @@ RefArray{T}(x::AbstractArray{T},i::Int=1,roots::Void=nothing) = RefArray{T,typeo convert(::Type{Ref{T}}, x::AbstractArray{T}) where {T} = RefArray(x, 1) Ref(x::AbstractArray, i::Integer=1) = RefArray(x, i) -function unsafe_convert{T}(P::Type{Ptr{T}}, b::RefArray{T}) +function unsafe_convert(P::Type{Ptr{T}}, b::RefArray{T}) where T if isbits(T) convert(P, pointer(b.x, b.i)) else @@ -108,10 +108,10 @@ function (::Type{Ref{P}}){P<:Union{Ptr,Cwstring,Cstring},T}(a::Array{T}) # Ref{P return RefArray(ptrs,1,roots) end end -cconvert{P<:Ptr}(::Type{Ptr{P}}, a::Array{<:Ptr}) = a -cconvert{P<:Ptr}(::Type{Ref{P}}, a::Array{<:Ptr}) = a -cconvert{P<:Union{Ptr,Cwstring,Cstring}}(::Type{Ptr{P}}, a::Array) = Ref{P}(a) -cconvert{P<:Union{Ptr,Cwstring,Cstring}}(::Type{Ref{P}}, a::Array) = Ref{P}(a) +cconvert(::Type{Ptr{P}}, a::Array{<:Ptr}) where {P<:Ptr} = a +cconvert(::Type{Ref{P}}, a::Array{<:Ptr}) where {P<:Ptr} = a +cconvert(::Type{Ptr{P}}, a::Array) where {P<:Union{Ptr,Cwstring,Cstring}} = Ref{P}(a) +cconvert(::Type{Ref{P}}, a::Array) where {P<:Union{Ptr,Cwstring,Cstring}} = Ref{P}(a) ### diff --git a/base/reshapedarray.jl b/base/reshapedarray.jl index 6681681471d07..3b8aff398b15a 100644 --- a/base/reshapedarray.jl +++ b/base/reshapedarray.jl @@ -18,7 +18,7 @@ struct ReshapedArrayIterator{I,M} mi::NTuple{M,SignedMultiplicativeInverse{Int}} end ReshapedArrayIterator(A::ReshapedArray) = _rs_iterator(parent(A), A.mi) -function _rs_iterator{M}(P, mi::NTuple{M}) +function _rs_iterator(P, mi::NTuple{M}) where M iter = eachindex(P) ReshapedArrayIterator{typeof(iter),M}(iter, mi) end @@ -109,20 +109,20 @@ end _throw_reshape_colon_dimmismatch(A, dims) = throw(DimensionMismatch("array size $(length(A)) must be divisible by the product of the new dimensions $dims")) -reshape{T,N}(parent::AbstractArray{T,N}, ndims::Type{Val{N}}) = parent -function reshape{N}(parent::AbstractArray, ndims::Type{Val{N}}) +reshape(parent::AbstractArray{T,N}, ndims::Type{Val{N}}) where {T,N} = parent +function reshape(parent::AbstractArray, ndims::Type{Val{N}}) where N reshape(parent, rdims((), indices(parent), Val{N})) end # Move elements from inds to out until out reaches the desired # dimensionality N, either filling with OneTo(1) or collapsing the # product of trailing dims into the last element -@pure rdims{N}(out::NTuple{N,Any}, inds::Tuple{}, ::Type{Val{N}}) = out -@pure function rdims{N}(out::NTuple{N,Any}, inds::Tuple{Any, Vararg{Any}}, ::Type{Val{N}}) +@pure rdims(out::NTuple{N,Any}, inds::Tuple{}, ::Type{Val{N}}) where {N} = out +@pure function rdims(out::NTuple{N,Any}, inds::Tuple{Any, Vararg{Any}}, ::Type{Val{N}}) where N l = length(last(out)) * prod(map(length, inds)) (front(out)..., OneTo(l)) end -@pure rdims{N}(out::Tuple, inds::Tuple{}, ::Type{Val{N}}) = rdims((out..., OneTo(1)), (), Val{N}) -@pure rdims{N}(out::Tuple, inds::Tuple{Any, Vararg{Any}}, ::Type{Val{N}}) = rdims((out..., first(inds)), tail(inds), Val{N}) +@pure rdims(out::Tuple, inds::Tuple{}, ::Type{Val{N}}) where {N} = rdims((out..., OneTo(1)), (), Val{N}) +@pure rdims(out::Tuple, inds::Tuple{Any, Vararg{Any}}, ::Type{Val{N}}) where {N} = rdims((out..., first(inds)), tail(inds), Val{N}) # _reshape on Array returns an Array _reshape(parent::Vector, dims::Dims{1}) = parent @@ -168,7 +168,7 @@ similar(A::ReshapedArray, eltype::Type, dims::Dims) = similar(parent(A), eltype, IndexStyle(::Type{<:ReshapedArrayLF}) = IndexLinear() parent(A::ReshapedArray) = A.parent parentindexes(A::ReshapedArray) = map(s->1:s, size(parent(A))) -reinterpret{T}(::Type{T}, A::ReshapedArray, dims::Dims) = reinterpret(T, parent(A), dims) +reinterpret(::Type{T}, A::ReshapedArray, dims::Dims) where {T} = reinterpret(T, parent(A), dims) @inline ind2sub_rs(::Tuple{}, i::Int) = i @inline ind2sub_rs(strds, i) = ind2sub_rs((), strds, i-1) diff --git a/base/rounding.jl b/base/rounding.jl index b56a13c482530..984848b1b14f4 100644 --- a/base/rounding.jl +++ b/base/rounding.jl @@ -142,8 +142,8 @@ See [`RoundingMode`](@ref) for available modes. setrounding_raw(::Type{<:Union{Float32,Float64}},i::Integer) = ccall(:fesetround, Int32, (Int32,), i) rounding_raw(::Type{<:Union{Float32,Float64}}) = ccall(:fegetround, Int32, ()) -setrounding{T<:Union{Float32,Float64}}(::Type{T},r::RoundingMode) = setrounding_raw(T,to_fenv(r)) -rounding{T<:Union{Float32,Float64}}(::Type{T}) = from_fenv(rounding_raw(T)) +setrounding(::Type{T},r::RoundingMode) where {T<:Union{Float32,Float64}} = setrounding_raw(T,to_fenv(r)) +rounding(::Type{T}) where {T<:Union{Float32,Float64}} = from_fenv(rounding_raw(T)) """ setrounding(f::Function, T, mode) @@ -180,7 +180,7 @@ See [`RoundingMode`](@ref) for available rounding modes. end 1.2 """ -function setrounding{T}(f::Function, ::Type{T}, rounding::RoundingMode) +function setrounding(f::Function, ::Type{T}, rounding::RoundingMode) where T old_rounding_raw = rounding_raw(T) setrounding(T,rounding) try @@ -201,16 +201,16 @@ end # To avoid ambiguous dispatch with methods in mpfr.jl: (::Type{T})(x::Real,r::RoundingMode) where {T<:AbstractFloat} = _convert_rounding(T,x,r) -_convert_rounding{T<:AbstractFloat}(::Type{T},x::Real,r::RoundingMode{:Nearest}) = convert(T,x) -function _convert_rounding{T<:AbstractFloat}(::Type{T},x::Real,r::RoundingMode{:Down}) +_convert_rounding(::Type{T},x::Real,r::RoundingMode{:Nearest}) where {T<:AbstractFloat} = convert(T,x) +function _convert_rounding(::Type{T},x::Real,r::RoundingMode{:Down}) where T<:AbstractFloat y = convert(T,x) y > x ? prevfloat(y) : y end -function _convert_rounding{T<:AbstractFloat}(::Type{T},x::Real,r::RoundingMode{:Up}) +function _convert_rounding(::Type{T},x::Real,r::RoundingMode{:Up}) where T<:AbstractFloat y = convert(T,x) y < x ? nextfloat(y) : y end -function _convert_rounding{T<:AbstractFloat}(::Type{T},x::Real,r::RoundingMode{:ToZero}) +function _convert_rounding(::Type{T},x::Real,r::RoundingMode{:ToZero}) where T<:AbstractFloat y = convert(T,x) if x > 0.0 y > x ? prevfloat(y) : y diff --git a/base/set.jl b/base/set.jl index eae1e45a53402..63cc3b83f67ae 100644 --- a/base/set.jl +++ b/base/set.jl @@ -15,7 +15,7 @@ function Set(g::Generator) end eltype(::Type{Set{T}}) where {T} = T -similar{T}(s::Set{T}) = Set{T}() +similar(s::Set{T}) where {T} = Set{T}() similar(s::Set, T::Type) = Set{T}() function show(io::IO, s::Set) diff --git a/base/sharedarray.jl b/base/sharedarray.jl index ef3d973fc8766..1e41b2e10e9ad 100644 --- a/base/sharedarray.jl +++ b/base/sharedarray.jl @@ -77,7 +77,7 @@ beginning of the file. """ SharedArray -function (::Type{SharedArray{T,N}}){T,N}(dims::Dims{N}; init=false, pids=Int[]) +function (::Type{SharedArray{T,N}})(dims::Dims{N}; init=false, pids=Int[]) where T where N isbits(T) || throw(ArgumentError("type of SharedArray elements must be bits types, got $(T)")) pids, onlocalhost = shared_pids(pids) @@ -134,21 +134,21 @@ function (::Type{SharedArray{T,N}}){T,N}(dims::Dims{N}; init=false, pids=Int[]) S end -(::Type{SharedArray{T,N}}){T,N}(I::Integer...; kwargs...) = +(::Type{SharedArray{T,N}})(I::Integer...; kwargs...) where {T,N} = SharedArray{T,N}(I; kwargs...) -(::Type{SharedArray{T}}){T}(d::NTuple; kwargs...) = +(::Type{SharedArray{T}})(d::NTuple; kwargs...) where {T} = SharedArray{T,length(d)}(d; kwargs...) -(::Type{SharedArray{T}}){T}(I::Integer...; kwargs...) = +(::Type{SharedArray{T}})(I::Integer...; kwargs...) where {T} = SharedArray{T,length(I)}(I; kwargs...) -(::Type{SharedArray{T}}){T}(m::Integer; kwargs...) = +(::Type{SharedArray{T}})(m::Integer; kwargs...) where {T} = SharedArray{T,1}(m; kwargs...) -(::Type{SharedArray{T}}){T}(m::Integer, n::Integer; kwargs...) = +(::Type{SharedArray{T}})(m::Integer, n::Integer; kwargs...) where {T} = SharedArray{T,2}(m, n; kwargs...) -(::Type{SharedArray{T}}){T}(m::Integer, n::Integer, o::Integer; kwargs...) = +(::Type{SharedArray{T}})(m::Integer, n::Integer, o::Integer; kwargs...) where {T} = SharedArray{T,3}(m, n, o; kwargs...) -function (::Type{SharedArray{T,N}}){T,N}(filename::AbstractString, dims::NTuple{N,Int}, - offset::Integer=0; mode=nothing, init=false, pids::Vector{Int}=Int[]) +function (::Type{SharedArray{T,N}})(filename::AbstractString, dims::NTuple{N,Int}, + offset::Integer=0; mode=nothing, init=false, pids::Vector{Int}=Int[]) where T where N if !isabspath(filename) throw(ArgumentError("$filename is not an absolute path; try abspath(filename)?")) end @@ -213,8 +213,8 @@ function (::Type{SharedArray{T,N}}){T,N}(filename::AbstractString, dims::NTuple{ S end -(::Type{SharedArray{T}}){T,N}(filename::AbstractString, dims::NTuple{N,Int}, offset::Integer=0; - mode=nothing, init=false, pids::Vector{Int}=Int[]) = +(::Type{SharedArray{T}})(filename::AbstractString, dims::NTuple{N,Int}, offset::Integer=0; + mode=nothing, init=false, pids::Vector{Int}=Int[]) where {T,N} = SharedArray{T,N}(filename, dims, offset; mode=mode, init=init, pids=pids) function initialize_shared_array(S, onlocalhost, init, pids) @@ -258,7 +258,7 @@ size(S::SharedArray) = S.dims ndims(S::SharedArray) = length(S.dims) IndexStyle(::Type{<:SharedArray}) = IndexLinear() -function reshape{T,N}(a::SharedArray{T}, dims::NTuple{N,Int}) +function reshape(a::SharedArray{T}, dims::NTuple{N,Int}) where T where N if length(a) != prod(dims) throw(DimensionMismatch("dimensions must be consistent with array size")) end @@ -460,7 +460,7 @@ function fill!(S::SharedArray, v) return S end -function rand!{T}(S::SharedArray{T}) +function rand!(S::SharedArray{T}) where T f = S->map!(x -> rand(T), S.loc_subarr_1d, S.loc_subarr_1d) @sync for p in procs(S) @async remotecall_wait(f, p, S) diff --git a/base/sparse/cholmod.jl b/base/sparse/cholmod.jl index 1586a0a838018..31800d3039c68 100644 --- a/base/sparse/cholmod.jl +++ b/base/sparse/cholmod.jl @@ -331,7 +331,7 @@ Factor(p::Ptr{C_Factor{Tv}}) where {Tv<:VTypes} = Factor{Tv}(p) # should be wrapped in get to make sure that SuiteSparse is not called with # a C_NULL pointer which could cause a segfault. Pointers are set to null # when serialized so this can happen when mutiple processes are in use. -function get{T<:SuiteSparseStruct}(p::Ptr{T}) +function get(p::Ptr{T}) where T<:SuiteSparseStruct if p == C_NULL throw(ArgumentError("pointer to the $T object is null. This can " * "happen if the object has been serialized.")) @@ -410,7 +410,7 @@ function ones{T<:VTypes}(m::Integer, n::Integer, ::Type{T}) end ones(m::Integer, n::Integer) = ones(m, n, Float64) -function eye{T<:VTypes}(m::Integer, n::Integer, ::Type{T}) +function eye(m::Integer, n::Integer, ::Type{T}) where T<:VTypes d = Dense(ccall((:cholmod_l_eye, :libcholmod), Ptr{C_Dense{T}}, (Csize_t, Csize_t, Cint, Ptr{UInt8}), m, n, xtyp(T), common())) @@ -571,7 +571,7 @@ function nnz{Tv<:VTypes}(A::Sparse{Tv}) get(A.p), common()) end -function speye{Tv<:VTypes}(m::Integer, n::Integer, ::Type{Tv}) +function speye(m::Integer, n::Integer, ::Type{Tv}) where Tv<:VTypes s = Sparse(ccall((@cholmod_name("speye", SuiteSparse_long), :libcholmod), Ptr{C_Sparse{Tv}}, (Csize_t, Csize_t, Cint, Ptr{UInt8}), @@ -669,7 +669,7 @@ function norm_sparse{Tv<:VTypes}(A::Sparse{Tv}, norm::Integer) get(A.p), norm, common()) end -function horzcat{Tv<:VRealTypes}(A::Sparse{Tv}, B::Sparse{Tv}, values::Bool) +function horzcat(A::Sparse{Tv}, B::Sparse{Tv}, values::Bool) where Tv<:VRealTypes s = Sparse(ccall((@cholmod_name("horzcat", SuiteSparse_long), :libcholmod), Ptr{C_Sparse{Tv}}, (Ptr{C_Sparse{Tv}}, Ptr{C_Sparse{Tv}}, Cint, Ptr{UInt8}), @@ -724,7 +724,7 @@ function sdmult!{Tv<:VTypes}(A::Sparse{Tv}, transpose::Bool, Y end -function vertcat{Tv<:VRealTypes}(A::Sparse{Tv}, B::Sparse{Tv}, values::Bool) +function vertcat(A::Sparse{Tv}, B::Sparse{Tv}, values::Bool) where Tv<:VRealTypes s = Sparse(ccall((@cholmod_name("vertcat", SuiteSparse_long), :libcholmod), Ptr{C_Sparse{Tv}}, (Ptr{C_Sparse{Tv}}, Ptr{C_Sparse{Tv}}, Cint, Ptr{UInt8}), @@ -842,7 +842,7 @@ get_perm(FC::FactorComponent) = get_perm(Factor(FC)) ######################### # Convertion/construction -function convert{T<:VTypes}(::Type{Dense{T}}, A::StridedVecOrMat) +function convert(::Type{Dense{T}}, A::StridedVecOrMat) where T<:VTypes d = allocate_dense(size(A, 1), size(A, 2), stride(A, 2), T) s = unsafe_load(d.p) for i in eachindex(A) @@ -950,7 +950,7 @@ convert(::Type{Sparse}, A::SparseMatrixCSC{Complex{Float32},<:ITypes}) = convert(Sparse, convert(SparseMatrixCSC{Complex{Float64},SuiteSparse_long}, A)) convert(::Type{Sparse}, A::Symmetric{Float64,SparseMatrixCSC{Float64,SuiteSparse_long}}) = Sparse(A.data, A.uplo == 'L' ? -1 : 1) -convert{Tv<:VTypes}(::Type{Sparse}, A::Hermitian{Tv,SparseMatrixCSC{Tv,SuiteSparse_long}}) = +convert(::Type{Sparse}, A::Hermitian{Tv,SparseMatrixCSC{Tv,SuiteSparse_long}}) where {Tv<:VTypes} = Sparse(A.data, A.uplo == 'L' ? -1 : 1) function convert{Ti<:ITypes}(::Type{Sparse}, A::Union{SparseMatrixCSC{BigFloat,Ti}, @@ -1022,7 +1022,7 @@ function (::Type{Sparse})(filename::String) end ## convertion back to base Julia types -function convert{T}(::Type{Matrix{T}}, D::Dense{T}) +function convert(::Type{Matrix{T}}, D::Dense{T}) where T s = unsafe_load(D.p) a = Matrix{T}(s.nrow, s.ncol) copy!(a, D) @@ -1050,16 +1050,16 @@ function _copy!(dest::AbstractArray, D::Dense) end dest end -convert{T}(::Type{Matrix}, D::Dense{T}) = convert(Matrix{T}, D) -function convert{T}(::Type{Vector{T}}, D::Dense{T}) +convert(::Type{Matrix}, D::Dense{T}) where {T} = convert(Matrix{T}, D) +function convert(::Type{Vector{T}}, D::Dense{T}) where T if size(D, 2) > 1 throw(DimensionMismatch("input must be a vector but had $(size(D, 2)) columns")) end copy!(Array{T}(size(D, 1)), D) end -convert{T}(::Type{Vector}, D::Dense{T}) = convert(Vector{T}, D) +convert(::Type{Vector}, D::Dense{T}) where {T} = convert(Vector{T}, D) -function convert{Tv}(::Type{SparseMatrixCSC{Tv,SuiteSparse_long}}, A::Sparse{Tv}) +function convert(::Type{SparseMatrixCSC{Tv,SuiteSparse_long}}, A::Sparse{Tv}) where Tv s = unsafe_load(A.p) if s.stype != 0 throw(ArgumentError("matrix has stype != 0. Convert to matrix " * @@ -1094,7 +1094,7 @@ function convert(::Type{Symmetric{Float64,SparseMatrixCSC{Float64,SuiteSparse_lo return B end end -function convert{Tv<:VTypes}(::Type{Hermitian{Tv,SparseMatrixCSC{Tv,SuiteSparse_long}}}, A::Sparse{Tv}) +function convert(::Type{Hermitian{Tv,SparseMatrixCSC{Tv,SuiteSparse_long}}}, A::Sparse{Tv}) where Tv<:VTypes s = unsafe_load(A.p) if !ishermitian(A) throw(ArgumentError("matrix is not Hermitian")) @@ -1173,9 +1173,9 @@ free!(A::Dense) = free_dense!(A.p) free!(A::Sparse) = free_sparse!(A.p) free!(F::Factor) = free_factor!(F.p) -eltype{T<:VTypes}(::Type{Dense{T}}) = T -eltype{T<:VTypes}(::Type{Factor{T}}) = T -eltype{T<:VTypes}(::Type{Sparse{T}}) = T +eltype(::Type{Dense{T}}) where {T<:VTypes} = T +eltype(::Type{Factor{T}}) where {T<:VTypes} = T +eltype(::Type{Sparse{T}}) where {T<:VTypes} = T nnz(F::Factor) = nnz(Sparse(F)) @@ -1247,7 +1247,7 @@ function getindex(A::Dense, i::Integer) end IndexStyle(::Sparse) = IndexCartesian() -function getindex{T}(A::Sparse{T}, i0::Integer, i1::Integer) +function getindex(A::Sparse{T}, i0::Integer, i1::Integer) where T s = unsafe_load(get(A.p)) !(1 <= i0 <= s.nrow && 1 <= i1 <= s.ncol) && throw(BoundsError()) s.stype < 0 && i0 < i1 && return conj(A[i1,i0]) @@ -1287,7 +1287,7 @@ end (*)(A::Sparse, B::Dense) = sdmult!(A, false, 1., 0., B, zeros(size(A, 1), size(B, 2))) (*)(A::Sparse, B::VecOrMat) = (*)(A, Dense(B)) -function A_mul_Bc{Tv<:VRealTypes}(A::Sparse{Tv}, B::Sparse{Tv}) +function A_mul_Bc(A::Sparse{Tv}, B::Sparse{Tv}) where Tv<:VRealTypes cm = common() if A !== B diff --git a/base/sparse/higherorderfns.jl b/base/sparse/higherorderfns.jl index abc148485a195..5f8a4f477ddec 100644 --- a/base/sparse/higherorderfns.jl +++ b/base/sparse/higherorderfns.jl @@ -65,23 +65,23 @@ end # (2) map[!] entry points -map{Tf}(f::Tf, A::SparseVector) = _noshapecheck_map(f, A) -map{Tf}(f::Tf, A::SparseMatrixCSC) = _noshapecheck_map(f, A) -map{Tf,N}(f::Tf, A::SparseMatrixCSC, Bs::Vararg{SparseMatrixCSC,N}) = +map(f::Tf, A::SparseVector) where {Tf} = _noshapecheck_map(f, A) +map(f::Tf, A::SparseMatrixCSC) where {Tf} = _noshapecheck_map(f, A) +map(f::Tf, A::SparseMatrixCSC, Bs::Vararg{SparseMatrixCSC,N}) where {Tf,N} = (_checksameshape(A, Bs...); _noshapecheck_map(f, A, Bs...)) -map{Tf,N}(f::Tf, A::SparseVecOrMat, Bs::Vararg{SparseVecOrMat,N}) = +map(f::Tf, A::SparseVecOrMat, Bs::Vararg{SparseVecOrMat,N}) where {Tf,N} = (_checksameshape(A, Bs...); _noshapecheck_map(f, A, Bs...)) -map!{Tf,N}(f::Tf, C::SparseMatrixCSC, A::SparseMatrixCSC, Bs::Vararg{SparseMatrixCSC,N}) = +map!(f::Tf, C::SparseMatrixCSC, A::SparseMatrixCSC, Bs::Vararg{SparseMatrixCSC,N}) where {Tf,N} = (_checksameshape(C, A, Bs...); _noshapecheck_map!(f, C, A, Bs...)) -map!{Tf,N}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, Bs::Vararg{SparseVecOrMat,N}) = +map!(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, Bs::Vararg{SparseVecOrMat,N}) where {Tf,N} = (_checksameshape(C, A, Bs...); _noshapecheck_map!(f, C, A, Bs...)) -function _noshapecheck_map!{Tf,N}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, Bs::Vararg{SparseVecOrMat,N}) +function _noshapecheck_map!(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, Bs::Vararg{SparseVecOrMat,N}) where {Tf,N} fofzeros = f(_zeros_eltypes(A, Bs...)...) fpreszeros = _iszero(fofzeros) return fpreszeros ? _map_zeropres!(f, C, A, Bs...) : _map_notzeropres!(f, fofzeros, C, A, Bs...) end -function _noshapecheck_map{Tf,N}(f::Tf, A::SparseVecOrMat, Bs::Vararg{SparseVecOrMat,N}) +function _noshapecheck_map(f::Tf, A::SparseVecOrMat, Bs::Vararg{SparseVecOrMat,N}) where {Tf,N} fofzeros = f(_zeros_eltypes(A, Bs...)...) fpreszeros = _iszero(fofzeros) maxnnzC = fpreszeros ? min(length(A), _sumnnzs(A, Bs...)) : length(A) @@ -92,9 +92,9 @@ function _noshapecheck_map{Tf,N}(f::Tf, A::SparseVecOrMat, Bs::Vararg{SparseVecO _map_notzeropres!(f, fofzeros, C, A, Bs...) end # (3) broadcast[!] entry points -broadcast{Tf}(f::Tf, A::SparseVector) = _noshapecheck_map(f, A) -broadcast{Tf}(f::Tf, A::SparseMatrixCSC) = _noshapecheck_map(f, A) -function broadcast!{Tf}(f::Tf, C::SparseVecOrMat) +broadcast(f::Tf, A::SparseVector) where {Tf} = _noshapecheck_map(f, A) +broadcast(f::Tf, A::SparseMatrixCSC) where {Tf} = _noshapecheck_map(f, A) +function broadcast!(f::Tf, C::SparseVecOrMat) where Tf isempty(C) && return _finishempty!(C) fofnoargs = f() if _iszero(fofnoargs) # f() is zero, so empty C @@ -107,7 +107,7 @@ function broadcast!{Tf}(f::Tf, C::SparseVecOrMat) end return C end -function broadcast!{Tf,N}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, Bs::Vararg{SparseVecOrMat,N}) +function broadcast!(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, Bs::Vararg{SparseVecOrMat,N}) where {Tf,N} _aresameshape(C, A, Bs...) && return _noshapecheck_map!(f, C, A, Bs...) Base.Broadcast.check_broadcast_indices(indices(C), A, Bs...) fofzeros = f(_zeros_eltypes(A, Bs...)...) @@ -116,13 +116,13 @@ function broadcast!{Tf,N}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, Bs::Varar _broadcast_notzeropres!(f, fofzeros, C, A, Bs...) end # the following three similar defs are necessary for type stability in the mixed vector/matrix case -broadcast{Tf,N}(f::Tf, A::SparseVector, Bs::Vararg{SparseVector,N}) = +broadcast(f::Tf, A::SparseVector, Bs::Vararg{SparseVector,N}) where {Tf,N} = _aresameshape(A, Bs...) ? _noshapecheck_map(f, A, Bs...) : _diffshape_broadcast(f, A, Bs...) -broadcast{Tf,N}(f::Tf, A::SparseMatrixCSC, Bs::Vararg{SparseMatrixCSC,N}) = +broadcast(f::Tf, A::SparseMatrixCSC, Bs::Vararg{SparseMatrixCSC,N}) where {Tf,N} = _aresameshape(A, Bs...) ? _noshapecheck_map(f, A, Bs...) : _diffshape_broadcast(f, A, Bs...) -broadcast{Tf,N}(f::Tf, A::SparseVecOrMat, Bs::Vararg{SparseVecOrMat,N}) = +broadcast(f::Tf, A::SparseVecOrMat, Bs::Vararg{SparseVecOrMat,N}) where {Tf,N} = _diffshape_broadcast(f, A, Bs...) -function _diffshape_broadcast{Tf,N}(f::Tf, A::SparseVecOrMat, Bs::Vararg{SparseVecOrMat,N}) +function _diffshape_broadcast(f::Tf, A::SparseVecOrMat, Bs::Vararg{SparseVecOrMat,N}) where {Tf,N} fofzeros = f(_zeros_eltypes(A, Bs...)...) fpreszeros = _iszero(fofzeros) indextypeC = _promote_indtype(A, Bs...) @@ -170,7 +170,7 @@ end return SparseMatrixCSC(shape..., pointers, storedinds, storedvals) end # Ambiguity killers, TODO: nix conflicting specializations -ambiguityfunnel{Tf}(f::Tf, x, y) = _aresameshape(x, y) ? _noshapecheck_map(f, x, y) : _diffshape_broadcast(f, x, y) +ambiguityfunnel(f::Tf, x, y) where {Tf} = _aresameshape(x, y) ? _noshapecheck_map(f, x, y) : _diffshape_broadcast(f, x, y) broadcast(::typeof(+), x::SparseVector, y::SparseVector) = ambiguityfunnel(+, x, y) # base/sparse/sparsevectors.jl:1266 broadcast(::typeof(-), x::SparseVector, y::SparseVector) = ambiguityfunnel(-, x, y) # base/sparse/sparsevectors.jl:1266 broadcast(::typeof(*), x::SparseVector, y::SparseVector) = ambiguityfunnel(*, x, y) # base/sparse/sparsevectors.jl:1266 @@ -178,7 +178,7 @@ broadcast(::typeof(*), x::SparseVector, y::SparseVector) = ambiguityfunnel(*, x, # (4) _map_zeropres!/_map_notzeropres! specialized for a single sparse vector/matrix "Stores only the nonzero entries of `map(f, Array(A))` in `C`." -function _map_zeropres!{Tf}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat) +function _map_zeropres!(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat) where Tf spaceC::Int = min(length(storedinds(C)), length(storedvals(C))) Ck = 1 @inbounds for j in columns(C) @@ -201,7 +201,7 @@ end Densifies `C`, storing `fillvalue` in place of each unstored entry in `A` and `f(A[i])`/`f(A[i,j])` in place of each stored entry `A[i]`/`A[i,j]` in `A`. """ -function _map_notzeropres!{Tf}(f::Tf, fillvalue, C::SparseVecOrMat, A::SparseVecOrMat) +function _map_notzeropres!(f::Tf, fillvalue, C::SparseVecOrMat, A::SparseVecOrMat) where Tf # Build dense matrix structure in C, expanding storage if necessary _densestructure!(C) # Populate values @@ -236,7 +236,7 @@ end # (5) _map_zeropres!/_map_notzeropres! specialized for a pair of sparse vectors/matrices -function _map_zeropres!{Tf}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, B::SparseVecOrMat) +function _map_zeropres!(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, B::SparseVecOrMat) where Tf spaceC::Int = min(length(storedinds(C)), length(storedvals(C))) rowsentinelA = convert(indtype(A), numrows(C) + 1) rowsentinelB = convert(indtype(B), numrows(C) + 1) @@ -278,7 +278,7 @@ function _map_zeropres!{Tf}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, B::Spar trimstorage!(C, Ck - 1) return C end -function _map_notzeropres!{Tf}(f::Tf, fillvalue, C::SparseVecOrMat, A::SparseVecOrMat, B::SparseVecOrMat) +function _map_notzeropres!(f::Tf, fillvalue, C::SparseVecOrMat, A::SparseVecOrMat, B::SparseVecOrMat) where Tf # Build dense matrix structure in C, expanding storage if necessary _densestructure!(C) # Populate values @@ -313,7 +313,7 @@ end # (6) _map_zeropres!/_map_notzeropres! for more than two sparse matrices / vectors -function _map_zeropres!{Tf,N}(f::Tf, C::SparseVecOrMat, As::Vararg{SparseVecOrMat,N}) +function _map_zeropres!(f::Tf, C::SparseVecOrMat, As::Vararg{SparseVecOrMat,N}) where {Tf,N} spaceC::Int = min(length(storedinds(C)), length(storedvals(C))) rowsentinel = numrows(C) + 1 Ck = 1 @@ -344,7 +344,7 @@ function _map_zeropres!{Tf,N}(f::Tf, C::SparseVecOrMat, As::Vararg{SparseVecOrMa trimstorage!(C, Ck - 1) return C end -function _map_notzeropres!{Tf,N}(f::Tf, fillvalue, C::SparseVecOrMat, As::Vararg{SparseVecOrMat,N}) +function _map_notzeropres!(f::Tf, fillvalue, C::SparseVecOrMat, As::Vararg{SparseVecOrMat,N}) where {Tf,N} # Build dense matrix structure in C, expanding storage if necessary _densestructure!(C) # Populate values @@ -431,7 +431,7 @@ end # (7) _broadcast_zeropres!/_broadcast_notzeropres! specialized for a single (input) sparse vector/matrix -function _broadcast_zeropres!{Tf}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat) +function _broadcast_zeropres!(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat) where Tf isempty(C) && return _finishempty!(C) spaceC::Int = min(length(storedinds(C)), length(storedvals(C))) # C and A cannot have the same shape, as we directed that case to map in broadcast's @@ -482,7 +482,7 @@ function _broadcast_zeropres!{Tf}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat) trimstorage!(C, Ck - 1) return C end -function _broadcast_notzeropres!{Tf}(f::Tf, fillvalue, C::SparseVecOrMat, A::SparseVecOrMat) +function _broadcast_notzeropres!(f::Tf, fillvalue, C::SparseVecOrMat, A::SparseVecOrMat) where Tf # For information on this code, see comments in similar code in _broadcast_zeropres! above # Build dense matrix structure in C, expanding storage if necessary _densestructure!(C) @@ -511,7 +511,7 @@ end # (8) _broadcast_zeropres!/_broadcast_notzeropres! specialized for a pair of (input) sparse vectors/matrices -function _broadcast_zeropres!{Tf}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, B::SparseVecOrMat) +function _broadcast_zeropres!(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, B::SparseVecOrMat) where Tf isempty(C) && return _finishempty!(C) spaceC::Int = min(length(storedinds(C)), length(storedvals(C))) rowsentinelA = convert(indtype(A), numrows(C) + 1) @@ -679,7 +679,7 @@ function _broadcast_zeropres!{Tf}(f::Tf, C::SparseVecOrMat, A::SparseVecOrMat, B trimstorage!(C, Ck - 1) return C end -function _broadcast_notzeropres!{Tf}(f::Tf, fillvalue, C::SparseVecOrMat, A::SparseVecOrMat, B::SparseVecOrMat) +function _broadcast_notzeropres!(f::Tf, fillvalue, C::SparseVecOrMat, A::SparseVecOrMat, B::SparseVecOrMat) where Tf # For information on this code, see comments in similar code in _broadcast_zeropres! above # Build dense matrix structure in C, expanding storage if necessary _densestructure!(C) @@ -783,7 +783,7 @@ _finishempty!(C::SparseMatrixCSC) = (fill!(C.colptr, 1); C) # (9) _broadcast_zeropres!/_broadcast_notzeropres! for more than two (input) sparse vectors/matrices -function _broadcast_zeropres!{Tf,N}(f::Tf, C::SparseVecOrMat, As::Vararg{SparseVecOrMat,N}) +function _broadcast_zeropres!(f::Tf, C::SparseVecOrMat, As::Vararg{SparseVecOrMat,N}) where {Tf,N} isempty(C) && return _finishempty!(C) spaceC::Int = min(length(storedinds(C)), length(storedvals(C))) expandsverts = _expandsvert_all(C, As) @@ -843,7 +843,7 @@ function _broadcast_zeropres!{Tf,N}(f::Tf, C::SparseVecOrMat, As::Vararg{SparseV trimstorage!(C, Ck - 1) return C end -function _broadcast_notzeropres!{Tf,N}(f::Tf, fillvalue, C::SparseVecOrMat, As::Vararg{SparseVecOrMat,N}) +function _broadcast_notzeropres!(f::Tf, fillvalue, C::SparseVecOrMat, As::Vararg{SparseVecOrMat,N}) where {Tf,N} isempty(C) && return _finishempty!(C) # Build dense matrix structure in C, expanding storage if necessary _densestructure!(C) @@ -983,11 +983,11 @@ promote_containertype(::Type{Tuple}, ::Type{AbstractSparseArray}) = Array promote_containertype(::Type{AbstractSparseArray}, ::Type{Tuple}) = Array # broadcast[!] entry points for combinations of sparse arrays and other (scalar) types -@inline function broadcast_c{N}(f, ::Type{AbstractSparseArray}, mixedargs::Vararg{Any,N}) +@inline function broadcast_c(f, ::Type{AbstractSparseArray}, mixedargs::Vararg{Any,N}) where N parevalf, passedargstup = capturescalars(f, mixedargs) return broadcast(parevalf, passedargstup...) end -@inline function broadcast_c!{N}(f, ::Type{AbstractSparseArray}, dest::SparseVecOrMat, mixedsrcargs::Vararg{Any,N}) +@inline function broadcast_c!(f, ::Type{AbstractSparseArray}, dest::SparseVecOrMat, mixedsrcargs::Vararg{Any,N}) where N parevalf, passedsrcargstup = capturescalars(f, mixedsrcargs) return broadcast!(parevalf, dest, passedsrcargstup...) end @@ -1014,8 +1014,8 @@ end @inline capturelastscalar(f, scalararg) = (passed...) -> f(passed, (scalararg,)) # NOTE: The following two method definitions work around #19096. -broadcast{Tf,T}(f::Tf, ::Type{T}, A::SparseMatrixCSC) = broadcast(y -> f(T, y), A) -broadcast{Tf,T}(f::Tf, A::SparseMatrixCSC, ::Type{T}) = broadcast(x -> f(x, T), A) +broadcast(f::Tf, ::Type{T}, A::SparseMatrixCSC) where {Tf,T} = broadcast(y -> f(T, y), A) +broadcast(f::Tf, A::SparseMatrixCSC, ::Type{T}) where {Tf,T} = broadcast(x -> f(x, T), A) # (11) broadcast[!] over combinations of scalars, sparse vectors/matrices, structured matrices, @@ -1074,7 +1074,7 @@ spcontainertype(x) = _spcontainertype(typeof(x)) spcontainertype(ct1, ct2) = promote_spcontainertype(spcontainertype(ct1), spcontainertype(ct2)) @inline spcontainertype(ct1, ct2, cts...) = promote_spcontainertype(spcontainertype(ct1), spcontainertype(ct2, cts...)) -promote_spcontainertype{T}(::Type{T}, ::Type{T}) = T +promote_spcontainertype(::Type{T}, ::Type{T}) where {T} = T # combinations involving AbstractArrays and/or Tuples divert to the generic AbstractArray broadcast code DivertToAbsArrayBC = Union{Type{AbstractArray},Type{Tuple}} promote_spcontainertype(::DivertToAbsArrayBC, ct) = AbstractArray @@ -1088,23 +1088,23 @@ promote_spcontainertype(::FunnelToSparseBC, ::FunnelToSparseBC) = PromoteToSpars # first (Broadcast containertype) dispatch layer # (broadcast_c[!], containertype, promote_containertype) -@inline broadcast_c{N}(f, ::Type{PromoteToSparse}, As::Vararg{Any,N}) = +@inline broadcast_c(f, ::Type{PromoteToSparse}, As::Vararg{Any,N}) where {N} = spbroadcast_c(f, spcontainertype(As...), As...) -@inline broadcast_c!{N}(f, ::Type{AbstractSparseArray}, ::Type{PromoteToSparse}, C, B, As::Vararg{Any,N}) = +@inline broadcast_c!(f, ::Type{AbstractSparseArray}, ::Type{PromoteToSparse}, C, B, As::Vararg{Any,N}) where {N} = spbroadcast_c!(f, AbstractSparseArray, spcontainertype(B, As...), C, B, As...) # where destination C is not an AbstractSparseArray, divert to generic AbstractArray broadcast code -@inline broadcast_c!{N}(f, CT::Type, ::Type{PromoteToSparse}, C, B, As::Vararg{Any,N}) = +@inline broadcast_c!(f, CT::Type, ::Type{PromoteToSparse}, C, B, As::Vararg{Any,N}) where {N} = broadcast_c!(f, CT, Array, C, B, As...) # second (internal sparse broadcast containertype) dispatch layer # (spbroadcast_c[!], spcontainertype, promote_spcontainertype) -@inline spbroadcast_c{N}(f, ::Type{PromoteToSparse}, As::Vararg{Any,N}) = +@inline spbroadcast_c(f, ::Type{PromoteToSparse}, As::Vararg{Any,N}) where {N} = broadcast(f, map(_sparsifystructured, As)...) -@inline spbroadcast_c{N}(f, ::Type{AbstractArray}, As::Vararg{Any,N}) = +@inline spbroadcast_c(f, ::Type{AbstractArray}, As::Vararg{Any,N}) where {N} = broadcast_c(f, Array, As...) -@inline spbroadcast_c!{N}(f, ::Type{AbstractSparseArray}, ::Type{PromoteToSparse}, C, B, As::Vararg{Any,N}) = +@inline spbroadcast_c!(f, ::Type{AbstractSparseArray}, ::Type{PromoteToSparse}, C, B, As::Vararg{Any,N}) where {N} = broadcast!(f, C, _sparsifystructured(B), map(_sparsifystructured, As)...) -@inline spbroadcast_c!{N}(f, ::Type{AbstractSparseArray}, ::Type{AbstractArray}, C, B, As::Vararg{Any,N}) = +@inline spbroadcast_c!(f, ::Type{AbstractSparseArray}, ::Type{AbstractArray}, C, B, As::Vararg{Any,N}) where {N} = broadcast_c!(f, Array, Array, C, B, As...) @inline _sparsifystructured(M::AbstractMatrix) = SparseMatrixCSC(M) @@ -1118,10 +1118,10 @@ promote_spcontainertype(::FunnelToSparseBC, ::FunnelToSparseBC) = PromoteToSpars # (12) map[!] over combinations of sparse and structured matrices StructuredMatrix = Union{Diagonal,Bidiagonal,Tridiagonal,SymTridiagonal} SparseOrStructuredMatrix = Union{SparseMatrixCSC,StructuredMatrix} -map{Tf}(f::Tf, A::StructuredMatrix) = _noshapecheck_map(f, _sparsifystructured(A)) -map{Tf,N}(f::Tf, A::SparseOrStructuredMatrix, Bs::Vararg{SparseOrStructuredMatrix,N}) = +map(f::Tf, A::StructuredMatrix) where {Tf} = _noshapecheck_map(f, _sparsifystructured(A)) +map(f::Tf, A::SparseOrStructuredMatrix, Bs::Vararg{SparseOrStructuredMatrix,N}) where {Tf,N} = (_checksameshape(A, Bs...); _noshapecheck_map(f, _sparsifystructured(A), map(_sparsifystructured, Bs)...)) -map!{Tf,N}(f::Tf, C::SparseMatrixCSC, A::SparseOrStructuredMatrix, Bs::Vararg{SparseOrStructuredMatrix,N}) = +map!(f::Tf, C::SparseMatrixCSC, A::SparseOrStructuredMatrix, Bs::Vararg{SparseOrStructuredMatrix,N}) where {Tf,N} = (_checksameshape(C, A, Bs...); _noshapecheck_map!(f, C, _sparsifystructured(A), map(_sparsifystructured, Bs)...)) end diff --git a/base/sparse/linalg.jl b/base/sparse/linalg.jl index 4ec09cc01d8eb..4b27f8fc92410 100644 --- a/base/sparse/linalg.jl +++ b/base/sparse/linalg.jl @@ -20,7 +20,7 @@ increment(A::AbstractArray{<:Integer}) = increment!(copy(A)) ## sparse matrix multiplication -function (*){TvA,TiA,TvB,TiB}(A::SparseMatrixCSC{TvA,TiA}, B::SparseMatrixCSC{TvB,TiB}) +function (*)(A::SparseMatrixCSC{TvA,TiA}, B::SparseMatrixCSC{TvB,TiB}) where {TvA,TiA,TvB,TiB} (*)(sppromote(A, B)...) end for f in (:A_mul_Bt, :A_mul_Bc, @@ -98,7 +98,7 @@ Ac_mul_B!(C::StridedVecOrMat, A::SparseMatrixCSC, B::StridedVecOrMat) = Ac_mul_B At_mul_B!(C::StridedVecOrMat, A::SparseMatrixCSC, B::StridedVecOrMat) = At_mul_B!(one(eltype(B)), A, B, zero(eltype(C)), C) -function (*){TX,TvA,TiA}(X::StridedMatrix{TX}, A::SparseMatrixCSC{TvA,TiA}) +function (*)(X::StridedMatrix{TX}, A::SparseMatrixCSC{TvA,TiA}) where {TX,TvA,TiA} mX, nX = size(X) nX == A.m || throw(DimensionMismatch()) Y = zeros(promote_type(TX,TvA), mX, A.n) @@ -122,7 +122,7 @@ end # Sparse matrix multiplication as described in [Gustavson, 1978]: # http://dl.acm.org/citation.cfm?id=355796 -(*){Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, B::SparseMatrixCSC{Tv,Ti}) = spmatmul(A,B) +(*)(A::SparseMatrixCSC{Tv,Ti}, B::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} = spmatmul(A,B) for (f, opA, opB) in ((:A_mul_Bt, :identity, :transpose), (:A_mul_Bc, :identity, :ctranspose), (:At_mul_B, :transpose, :identity), diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl index f2826d7fa88c0..34a554a854285 100644 --- a/base/sparse/sparsematrix.jl +++ b/base/sparse/sparsematrix.jl @@ -163,7 +163,7 @@ end ## Reinterpret and Reshape -function reinterpret{T,Tv}(::Type{T}, a::SparseMatrixCSC{Tv}) +function reinterpret(::Type{T}, a::SparseMatrixCSC{Tv}) where {T,Tv} if sizeof(T) != sizeof(Tv) throw(ArgumentError("SparseMatrixCSC reinterpret is only supported for element types of the same size")) end @@ -206,7 +206,7 @@ function sparse_compute_reshaped_colptr_and_rowval{Ti}(colptrS::Vector{Ti}, rowv end end -function reinterpret{T,Tv,Ti,N}(::Type{T}, a::SparseMatrixCSC{Tv,Ti}, dims::NTuple{N,Int}) +function reinterpret(::Type{T}, a::SparseMatrixCSC{Tv,Ti}, dims::NTuple{N,Int}) where {T,Tv,Ti,N} if sizeof(T) != sizeof(Tv) throw(ArgumentError("SparseMatrixCSC reinterpret is only supported for element types of the same size")) end @@ -293,7 +293,7 @@ function copy!(A::SparseMatrixCSC, B::SparseMatrixCSC) end similar(S::SparseMatrixCSC, Tv::Type=eltype(S)) = SparseMatrixCSC(S.m, S.n, copy(S.colptr), copy(S.rowval), Array{Tv}(length(S.nzval))) -function similar{Tv,Ti}(S::SparseMatrixCSC, ::Type{Tv}, ::Type{Ti}) +function similar(S::SparseMatrixCSC, ::Type{Tv}, ::Type{Ti}) where {Tv,Ti} new_colptr = copy!(similar(S.colptr, Ti), S.colptr) new_rowval = copy!(similar(S.rowval, Ti), S.rowval) new_nzval = copy!(similar(S.nzval, Tv), S.nzval) @@ -302,12 +302,12 @@ end @inline similar{Tv}(S::SparseMatrixCSC, ::Type{Tv}, d::Dims) = spzeros(Tv, d...) # convert'ing between SparseMatrixCSC types -convert{Tv}(::Type{AbstractMatrix{Tv}}, A::SparseMatrixCSC{Tv}) = A -convert{Tv}(::Type{AbstractMatrix{Tv}}, A::SparseMatrixCSC) = convert(SparseMatrixCSC{Tv}, A) -convert{Tv}(::Type{SparseMatrixCSC{Tv}}, S::SparseMatrixCSC{Tv}) = S -convert{Tv}(::Type{SparseMatrixCSC{Tv}}, S::SparseMatrixCSC) = convert(SparseMatrixCSC{Tv,eltype(S.colptr)}, S) -convert{Tv,Ti}(::Type{SparseMatrixCSC{Tv,Ti}}, S::SparseMatrixCSC{Tv,Ti}) = S -function convert{Tv,Ti}(::Type{SparseMatrixCSC{Tv,Ti}}, S::SparseMatrixCSC) +convert(::Type{AbstractMatrix{Tv}}, A::SparseMatrixCSC{Tv}) where {Tv} = A +convert(::Type{AbstractMatrix{Tv}}, A::SparseMatrixCSC) where {Tv} = convert(SparseMatrixCSC{Tv}, A) +convert(::Type{SparseMatrixCSC{Tv}}, S::SparseMatrixCSC{Tv}) where {Tv} = S +convert(::Type{SparseMatrixCSC{Tv}}, S::SparseMatrixCSC) where {Tv} = convert(SparseMatrixCSC{Tv,eltype(S.colptr)}, S) +convert(::Type{SparseMatrixCSC{Tv,Ti}}, S::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} = S +function convert(::Type{SparseMatrixCSC{Tv,Ti}}, S::SparseMatrixCSC) where {Tv,Ti} eltypeTicolptr = convert(Vector{Ti}, S.colptr) eltypeTirowval = convert(Vector{Ti}, S.rowval) eltypeTvnzval = convert(Vector{Tv}, S.nzval) @@ -315,9 +315,9 @@ function convert{Tv,Ti}(::Type{SparseMatrixCSC{Tv,Ti}}, S::SparseMatrixCSC) end # convert'ing from other matrix types to SparseMatrixCSC (also see sparse()) convert(::Type{SparseMatrixCSC}, M::Matrix) = sparse(M) -convert{Tv}(::Type{SparseMatrixCSC}, M::AbstractMatrix{Tv}) = convert(SparseMatrixCSC{Tv,Int}, M) -convert{Tv}(::Type{SparseMatrixCSC{Tv}}, M::AbstractMatrix{Tv}) = convert(SparseMatrixCSC{Tv,Int}, M) -function convert{Tv,Ti}(::Type{SparseMatrixCSC{Tv,Ti}}, M::AbstractMatrix) +convert(::Type{SparseMatrixCSC}, M::AbstractMatrix{Tv}) where {Tv} = convert(SparseMatrixCSC{Tv,Int}, M) +convert(::Type{SparseMatrixCSC{Tv}}, M::AbstractMatrix{Tv}) where {Tv} = convert(SparseMatrixCSC{Tv,Int}, M) +function convert(::Type{SparseMatrixCSC{Tv,Ti}}, M::AbstractMatrix) where {Tv,Ti} (I, J, V) = findnz(M) eltypeTiI = convert(Vector{Ti}, I) eltypeTiJ = convert(Vector{Ti}, J) @@ -325,7 +325,7 @@ function convert{Tv,Ti}(::Type{SparseMatrixCSC{Tv,Ti}}, M::AbstractMatrix) return sparse_IJ_sorted!(eltypeTiI, eltypeTiJ, eltypeTvV, size(M)...) end # convert'ing from SparseMatrixCSC to other matrix types -function convert{Tv}(::Type{Matrix}, S::SparseMatrixCSC{Tv}) +function convert(::Type{Matrix}, S::SparseMatrixCSC{Tv}) where Tv # Handle cases where zero(Tv) is not defined but the array is dense. A = length(S) == nnz(S) ? Array{Tv}(S.m, S.n) : zeros(Tv, S.m, S.n) for Sj in 1:S.n @@ -1405,7 +1405,7 @@ julia> speye(A) Note the difference from [`spones`](@ref). """ -speye{T}(S::SparseMatrixCSC{T}) = speye(T, size(S, 1), size(S, 2)) +speye(S::SparseMatrixCSC{T}) where {T} = speye(T, size(S, 1), size(S, 2)) eye(S::SparseMatrixCSC) = speye(S) """ @@ -1421,7 +1421,7 @@ multiple `α` of the identity matrix. """ speye(T::Type, m::Integer, n::Integer) = speye_scaled(T, oneunit(T), m, n) -function one{T}(S::SparseMatrixCSC{T}) +function one(S::SparseMatrixCSC{T}) where T m,n = size(S) if m != n; throw(DimensionMismatch("multiplicative identity only defined for square matrices")); end speye(T, m) @@ -1790,7 +1790,7 @@ end getindex(A::SparseMatrixCSC, I::Tuple{Integer,Integer}) = getindex(A, I[1], I[2]) -function getindex{T}(A::SparseMatrixCSC{T}, i0::Integer, i1::Integer) +function getindex(A::SparseMatrixCSC{T}, i0::Integer, i1::Integer) where T if !(1 <= i0 <= A.m && 1 <= i1 <= A.n); throw(BoundsError()); end r1 = Int(A.colptr[i1]) r2 = Int(A.colptr[i1+1]-1) @@ -1837,7 +1837,7 @@ function getindex_cols{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, J::AbstractVector) return SparseMatrixCSC(m, nJ, colptrS, rowvalS, nzvalS) end -function getindex{Tv,Ti<:Integer}(A::SparseMatrixCSC{Tv,Ti}, I::Range, J::AbstractVector) +function getindex(A::SparseMatrixCSC{Tv,Ti}, I::Range, J::AbstractVector) where {Tv,Ti<:Integer} # Ranges for indexing rows (m, n) = size(A) # whole columns: @@ -2130,7 +2130,7 @@ function getindex_general(A::SparseMatrixCSC, I::AbstractVector, J::AbstractVect end # the general case: -function getindex{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, I::AbstractVector, J::AbstractVector) +function getindex(A::SparseMatrixCSC{Tv,Ti}, I::AbstractVector, J::AbstractVector) where {Tv,Ti} (m, n) = size(A) if !isempty(J) @@ -2154,7 +2154,7 @@ function getindex{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, I::AbstractVector, J::Abstra end end -function getindex{Tv}(A::SparseMatrixCSC{Tv}, I::AbstractArray) +function getindex(A::SparseMatrixCSC{Tv}, I::AbstractArray) where Tv szA = size(A) nA = szA[1]*szA[2] colptrA = A.colptr @@ -2208,10 +2208,10 @@ getindex(A::SparseMatrixCSC, I::AbstractVector{<:Integer}, J::AbstractVector{Boo getindex(A::SparseMatrixCSC, I::AbstractVector{Bool}, J::AbstractVector{<:Integer}) = A[find(I),J] ## setindex! -function setindex!{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, v, i::Integer, j::Integer) +function setindex!(A::SparseMatrixCSC{Tv,Ti}, v, i::Integer, j::Integer) where Tv where Ti setindex!(A, convert(Tv, v), convert(Ti, i), convert(Ti, j)) end -function setindex!{Tv,Ti<:Integer}(A::SparseMatrixCSC{Tv,Ti}, v::Tv, i::Ti, j::Ti) +function setindex!(A::SparseMatrixCSC{Tv,Ti}, v::Tv, i::Ti, j::Ti) where Tv where Ti<:Integer if !((1 <= i <= A.m) & (1 <= j <= A.n)) throw(BoundsError(A, (i,j))) end @@ -2408,17 +2408,17 @@ function _spsetnz_setindex!{Tv}(A::SparseMatrixCSC{Tv}, x::Tv, return A end -setindex!{Tv,Ti,T<:Integer}(A::SparseMatrixCSC{Tv,Ti}, S::Matrix, I::AbstractVector{T}, J::AbstractVector{T}) = +setindex!(A::SparseMatrixCSC{Tv,Ti}, S::Matrix, I::AbstractVector{T}, J::AbstractVector{T}) where {Tv,Ti,T<:Integer} = setindex!(A, convert(SparseMatrixCSC{Tv,Ti}, S), I, J) setindex!(A::SparseMatrixCSC, v::AbstractVector, I::AbstractVector{<:Integer}, j::Integer) = setindex!(A, v, I, [j]) setindex!(A::SparseMatrixCSC, v::AbstractVector, i::Integer, J::AbstractVector{<:Integer}) = setindex!(A, v, [i], J) -setindex!{T<:Integer}(A::SparseMatrixCSC, v::AbstractVector, I::AbstractVector{T}, J::AbstractVector{T}) = +setindex!(A::SparseMatrixCSC, v::AbstractVector, I::AbstractVector{T}, J::AbstractVector{T}) where {T<:Integer} = setindex!(A, reshape(v, length(I), length(J)), I, J) # A[I,J] = B -function setindex!{Tv,Ti,T<:Integer}(A::SparseMatrixCSC{Tv,Ti}, B::SparseMatrixCSC{Tv,Ti}, I::AbstractVector{T}, J::AbstractVector{T}) +function setindex!(A::SparseMatrixCSC{Tv,Ti}, B::SparseMatrixCSC{Tv,Ti}, I::AbstractVector{T}, J::AbstractVector{T}) where {Tv,Ti,T<:Integer} if size(B,1) != length(I) || size(B,2) != length(J) throw(DimensionMismatch("")) end @@ -3238,7 +3238,7 @@ length(d::SpDiagIterator) = d.n start(d::SpDiagIterator) = 1 done(d::SpDiagIterator, j) = j > d.n -function next{Tv}(d::SpDiagIterator{Tv}, j) +function next(d::SpDiagIterator{Tv}, j) where Tv A = d.A r1 = Int(A.colptr[j]) r2 = Int(A.colptr[j+1]-1) diff --git a/base/sparse/sparsevector.jl b/base/sparse/sparsevector.jl index 722f064a0ec14..c6bf69aee00bc 100644 --- a/base/sparse/sparsevector.jl +++ b/base/sparse/sparsevector.jl @@ -36,10 +36,10 @@ nonzeros(x::SparseVector) = x.nzval nonzeroinds(x::SparseVector) = x.nzind similar(x::SparseVector, Tv::Type=eltype(x)) = SparseVector(x.n, copy(x.nzind), Vector{Tv}(length(x.nzval))) -function similar{Tv,Ti}(x::SparseVector, ::Type{Tv}, ::Type{Ti}) +function similar(x::SparseVector, ::Type{Tv}, ::Type{Ti}) where {Tv,Ti} return SparseVector(x.n, copy!(similar(x.nzind, Ti), x.nzind), copy!(similar(x.nzval, Tv), x.nzval)) end -similar{T}(x::SparseVector, ::Type{T}, D::Dims) = spzeros(T, D...) +similar(x::SparseVector, ::Type{T}, D::Dims) where {T} = spzeros(T, D...) ### Construct empty sparse vector @@ -225,7 +225,7 @@ end ### Element access -function setindex!{Tv,Ti<:Integer}(x::SparseVector{Tv,Ti}, v::Tv, i::Ti) +function setindex!(x::SparseVector{Tv,Ti}, v::Tv, i::Ti) where {Tv,Ti<:Integer} checkbounds(x, i) nzind = nonzeroinds(x) nzval = nonzeros(x) @@ -243,7 +243,7 @@ function setindex!{Tv,Ti<:Integer}(x::SparseVector{Tv,Ti}, v::Tv, i::Ti) x end -setindex!{Tv, Ti<:Integer}(x::SparseVector{Tv,Ti}, v, i::Integer) = +setindex!(x::SparseVector{Tv,Ti}, v, i::Integer) where {Tv,Ti<:Integer} = setindex!(x, convert(Tv, v), convert(Ti, i)) @@ -287,15 +287,15 @@ end ### Conversion # convert SparseMatrixCSC to SparseVector -function convert{Tv,Ti<:Integer}(::Type{SparseVector{Tv,Ti}}, s::SparseMatrixCSC{Tv,Ti}) +function convert(::Type{SparseVector{Tv,Ti}}, s::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti<:Integer} size(s, 2) == 1 || throw(ArgumentError("The input argument must have a single-column.")) SparseVector(s.m, s.rowval, s.nzval) end -convert{Tv,Ti}(::Type{SparseVector{Tv}}, s::SparseMatrixCSC{Tv,Ti}) = +convert(::Type{SparseVector{Tv}}, s::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} = convert(SparseVector{Tv,Ti}, s) -convert{Tv,Ti}(::Type{SparseVector}, s::SparseMatrixCSC{Tv,Ti}) = +convert(::Type{SparseVector}, s::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} = convert(SparseVector{Tv,Ti}, s) # convert Vector to SparseVector @@ -345,20 +345,20 @@ function _dense2sparsevec{Tv,Ti}(s::AbstractArray{Tv}, initcap::Ti) SparseVector(n, nzind, nzval) end -convert{Tv,Ti}(::Type{SparseVector{Tv,Ti}}, s::AbstractVector{Tv}) = +convert(::Type{SparseVector{Tv,Ti}}, s::AbstractVector{Tv}) where {Tv,Ti} = _dense2sparsevec(s, convert(Ti, max(8, div(length(s), 8)))) -convert{Tv}(::Type{SparseVector{Tv}}, s::AbstractVector{Tv}) = +convert(::Type{SparseVector{Tv}}, s::AbstractVector{Tv}) where {Tv} = convert(SparseVector{Tv,Int}, s) -convert{Tv}(::Type{SparseVector}, s::AbstractVector{Tv}) = +convert(::Type{SparseVector}, s::AbstractVector{Tv}) where {Tv} = convert(SparseVector{Tv,Int}, s) # convert between different types of SparseVector -convert{Tv}(::Type{SparseVector{Tv}}, s::SparseVector{Tv}) = s -convert{Tv,Ti}(::Type{SparseVector{Tv,Ti}}, s::SparseVector{Tv,Ti}) = s -convert{Tv,Ti}(::Type{SparseVector{Tv,Ti}}, s::SparseVector) = +convert(::Type{SparseVector{Tv}}, s::SparseVector{Tv}) where {Tv} = s +convert(::Type{SparseVector{Tv,Ti}}, s::SparseVector{Tv,Ti}) where {Tv,Ti} = s +convert(::Type{SparseVector{Tv,Ti}}, s::SparseVector) where {Tv,Ti} = SparseVector{Tv,Ti}(s.n, convert(Vector{Ti}, s.nzind), convert(Vector{Tv}, s.nzval)) convert{Tv,Ti}(::Type{SparseVector{Tv}}, s::SparseVector{<:Any,Ti}) = @@ -415,7 +415,7 @@ function copy!(A::SparseVector, B::SparseMatrixCSC) return A end -copy!{TvB, TiB}(A::SparseMatrixCSC, B::SparseVector{TvB,TiB}) = +copy!(A::SparseMatrixCSC, B::SparseVector{TvB,TiB}) where {TvB,TiB} = copy!(A, SparseMatrixCSC{TvB,TiB}(B.n, 1, TiB[1, length(B.nzind)+1], B.nzind, B.nzval)) @@ -506,7 +506,7 @@ end # Logical and linear indexing into SparseMatrices getindex(A::SparseMatrixCSC, I::AbstractVector{Bool}) = _logical_index(A, I) # Ambiguities getindex(A::SparseMatrixCSC, I::AbstractArray{Bool}) = _logical_index(A, I) -function _logical_index{Tv}(A::SparseMatrixCSC{Tv}, I::AbstractArray{Bool}) +function _logical_index(A::SparseMatrixCSC{Tv}, I::AbstractArray{Bool}) where Tv checkbounds(A, I) n = sum(I) nnzB = min(n, nnz(A)) @@ -547,7 +547,7 @@ end # TODO: further optimizations are available for ::Colon and other types of Range getindex(A::SparseMatrixCSC, ::Colon) = A[1:end] -function getindex{Tv}(A::SparseMatrixCSC{Tv}, I::UnitRange) +function getindex(A::SparseMatrixCSC{Tv}, I::UnitRange) where Tv checkbounds(A, I) szA = size(A) nA = szA[1]*szA[2] @@ -583,7 +583,7 @@ function getindex{Tv}(A::SparseMatrixCSC{Tv}, I::UnitRange) SparseVector(n, rowvalB, nzvalB) end -function getindex{Tv}(A::SparseMatrixCSC{Tv}, I::AbstractVector) +function getindex(A::SparseMatrixCSC{Tv}, I::AbstractVector) where Tv szA = size(A) nA = szA[1]*szA[2] colptrA = A.colptr @@ -620,7 +620,7 @@ function getindex{Tv}(A::SparseMatrixCSC{Tv}, I::AbstractVector) SparseVector(n, rowvalB, nzvalB) end -function find{Ti}(x::SparseVector{<:Any,Ti}) +function find(x::SparseVector{<:Any,Ti}) where Ti numnz = nnz(x) I = Vector{Ti}(numnz) @@ -643,7 +643,7 @@ function find{Ti}(x::SparseVector{<:Any,Ti}) return I end -function findnz{Tv,Ti}(x::SparseVector{Tv,Ti}) +function findnz(x::SparseVector{Tv,Ti}) where {Tv,Ti} numnz = nnz(x) I = Vector{Ti}(numnz) @@ -674,7 +674,7 @@ end ### getindex -function _spgetindex{Tv,Ti}(m::Int, nzind::AbstractVector{Ti}, nzval::AbstractVector{Tv}, i::Integer) +function _spgetindex(m::Int, nzind::AbstractVector{Ti}, nzval::AbstractVector{Tv}, i::Integer) where {Tv,Ti} ii = searchsortedfirst(nzind, convert(Ti, i)) (ii <= m && nzind[ii] == i) ? nzval[ii] : zero(Tv) end @@ -684,7 +684,7 @@ function getindex(x::AbstractSparseVector, i::Integer) _spgetindex(nnz(x), nonzeroinds(x), nonzeros(x), i) end -function getindex{Tv,Ti}(x::AbstractSparseVector{Tv,Ti}, I::UnitRange) +function getindex(x::AbstractSparseVector{Tv,Ti}, I::UnitRange) where {Tv,Ti} checkbounds(x, I) xlen = length(x) i0 = first(I) @@ -776,7 +776,7 @@ end ### Conversion to matrix -function convert{Tv,Ti}(::Type{SparseMatrixCSC{Tv,Ti}}, x::AbstractSparseVector) +function convert(::Type{SparseMatrixCSC{Tv,Ti}}, x::AbstractSparseVector) where {Tv,Ti} n = length(x) xnzind = nonzeroinds(x) xnzval = nonzeros(x) @@ -792,10 +792,10 @@ end convert{Tv,Ti}(::Type{SparseMatrixCSC{Tv}}, x::AbstractSparseVector{<:Any,Ti}) = convert(SparseMatrixCSC{Tv,Ti}, x) -convert{Tv,Ti}(::Type{SparseMatrixCSC}, x::AbstractSparseVector{Tv,Ti}) = +convert(::Type{SparseMatrixCSC}, x::AbstractSparseVector{Tv,Ti}) where {Tv,Ti} = convert(SparseMatrixCSC{Tv,Ti}, x) -function convert{Tv}(::Type{Vector}, x::AbstractSparseVector{Tv}) +function convert(::Type{Vector}, x::AbstractSparseVector{Tv}) where Tv n = length(x) n == 0 && return Vector{Tv}(0) nzind = nonzeroinds(x) @@ -817,7 +817,7 @@ vec(x::AbstractSparseVector) = x copy(x::AbstractSparseVector) = SparseVector(length(x), copy(nonzeroinds(x)), copy(nonzeros(x))) -function reinterpret{T,Tv}(::Type{T}, x::AbstractSparseVector{Tv}) +function reinterpret(::Type{T}, x::AbstractSparseVector{Tv}) where {T,Tv} sizeof(T) == sizeof(Tv) || throw(ArgumentError("reinterpret of sparse vectors only supports element types of the same size.")) SparseVector(length(x), copy(nonzeroinds(x)), reinterpret(T, nonzeros(x))) @@ -838,9 +838,9 @@ complex(x::AbstractSparseVector) = # back to the horizontal concatenation method that ensures that combinations of # sparse/special/dense matrix/vector types concatenate to SparseMatrixCSCs, instead # of _absspvec_hcat below. The <:Integer qualifications are necessary for correct dispatch. -hcat{Tv,Ti<:Integer}(X::SparseVector{Tv,Ti}...) = _absspvec_hcat(X...) -hcat{Tv,Ti<:Integer}(X::AbstractSparseVector{Tv,Ti}...) = _absspvec_hcat(X...) -function _absspvec_hcat{Tv,Ti}(X::AbstractSparseVector{Tv,Ti}...) +hcat(X::SparseVector{Tv,Ti}...) where {Tv,Ti<:Integer} = _absspvec_hcat(X...) +hcat(X::AbstractSparseVector{Tv,Ti}...) where {Tv,Ti<:Integer} = _absspvec_hcat(X...) +function _absspvec_hcat(X::AbstractSparseVector{Tv,Ti}...) where {Tv,Ti} # check sizes n = length(X) m = length(X[1]) @@ -873,9 +873,9 @@ end # back to the vertical concatenation method that ensures that combinations of # sparse/special/dense matrix/vector types concatenate to SparseMatrixCSCs, instead # of _absspvec_vcat below. The <:Integer qualifications are necessary for correct dispatch. -vcat{Tv,Ti<:Integer}(X::SparseVector{Tv,Ti}...) = _absspvec_vcat(X...) -vcat{Tv,Ti<:Integer}(X::AbstractSparseVector{Tv,Ti}...) = _absspvec_vcat(X...) -function _absspvec_vcat{Tv,Ti}(X::AbstractSparseVector{Tv,Ti}...) +vcat(X::SparseVector{Tv,Ti}...) where {Tv,Ti<:Integer} = _absspvec_vcat(X...) +vcat(X::AbstractSparseVector{Tv,Ti}...) where {Tv,Ti<:Integer} = _absspvec_vcat(X...) +function _absspvec_vcat(X::AbstractSparseVector{Tv,Ti}...) where {Tv,Ti} # check sizes n = length(X) tnnz = 0 @@ -973,10 +973,10 @@ hcat(A::Vector...) = Base.typed_hcat(promote_eltype(A...), A...) hcat(A::_DenseConcatGroup...) = Base.typed_hcat(promote_eltype(A...), A...) hvcat(rows::Tuple{Vararg{Int}}, xs::_DenseConcatGroup...) = Base.typed_hvcat(promote_eltype(xs...), rows, xs...) # For performance, specially handle the case where the matrices/vectors have homogeneous eltype -cat{T}(catdims, xs::_TypedDenseConcatGroup{T}...) = Base.cat_t(catdims, T, xs...) -vcat{T}(A::_TypedDenseConcatGroup{T}...) = Base.typed_vcat(T, A...) -hcat{T}(A::_TypedDenseConcatGroup{T}...) = Base.typed_hcat(T, A...) -hvcat{T}(rows::Tuple{Vararg{Int}}, xs::_TypedDenseConcatGroup{T}...) = Base.typed_hvcat(T, rows, xs...) +cat(catdims, xs::_TypedDenseConcatGroup{T}...) where {T} = Base.cat_t(catdims, T, xs...) +vcat(A::_TypedDenseConcatGroup{T}...) where {T} = Base.typed_vcat(T, A...) +hcat(A::_TypedDenseConcatGroup{T}...) where {T} = Base.typed_hcat(T, A...) +hvcat(rows::Tuple{Vararg{Int}}, xs::_TypedDenseConcatGroup{T}...) where {T} = Base.typed_hvcat(T, rows, xs...) ### math functions @@ -993,7 +993,7 @@ conj(x::SparseVector) = SparseVector(length(x), copy(nonzeroinds(x)), conj(nonze # macro unarymap_nz2z_z2z(op, TF) esc(quote - function $(op){Tv<:$(TF),Ti<:Integer}(x::AbstractSparseVector{Tv,Ti}) + function $(op)(x::AbstractSparseVector{Tv,Ti}) where Tv<:$(TF) where Ti<:Integer R = typeof($(op)(zero(Tv))) xnzind = nonzeroinds(x) xnzval = nonzeros(x) @@ -1039,7 +1039,7 @@ end macro unarymap_z2nz(op, TF) esc(quote - function $(op){Tv<:$(TF)}(x::AbstractSparseVector{Tv,<:Integer}) + function $(op)(x::AbstractSparseVector{Tv,<:Integer}) where Tv<:$(TF) v0 = $(op)(zero(Tv)) R = typeof(v0) xnzind = nonzeroinds(x) @@ -1500,7 +1500,7 @@ end # A_mul_B -function *{Ta,Tx}(A::StridedMatrix{Ta}, x::AbstractSparseVector{Tx}) +function *(A::StridedMatrix{Ta}, x::AbstractSparseVector{Tx}) where {Ta,Tx} m, n = size(A) length(x) == n || throw(DimensionMismatch()) Ty = promote_type(Ta, Tx) @@ -1508,7 +1508,7 @@ function *{Ta,Tx}(A::StridedMatrix{Ta}, x::AbstractSparseVector{Tx}) A_mul_B!(y, A, x) end -A_mul_B!{Tx,Ty}(y::StridedVector{Ty}, A::StridedMatrix, x::AbstractSparseVector{Tx}) = +A_mul_B!(y::StridedVector{Ty}, A::StridedMatrix, x::AbstractSparseVector{Tx}) where {Tx,Ty} = A_mul_B!(one(Tx), A, x, zero(Ty), y) function A_mul_B!(α::Number, A::StridedMatrix, x::AbstractSparseVector, β::Number, y::StridedVector) @@ -1537,7 +1537,7 @@ end # At_mul_B -function At_mul_B{Ta,Tx}(A::StridedMatrix{Ta}, x::AbstractSparseVector{Tx}) +function At_mul_B(A::StridedMatrix{Ta}, x::AbstractSparseVector{Tx}) where {Ta,Tx} m, n = size(A) length(x) == m || throw(DimensionMismatch()) Ty = promote_type(Ta, Tx) @@ -1545,7 +1545,7 @@ function At_mul_B{Ta,Tx}(A::StridedMatrix{Ta}, x::AbstractSparseVector{Tx}) At_mul_B!(y, A, x) end -At_mul_B!{Tx,Ty}(y::StridedVector{Ty}, A::StridedMatrix, x::AbstractSparseVector{Tx}) = +At_mul_B!(y::StridedVector{Ty}, A::StridedMatrix, x::AbstractSparseVector{Tx}) where {Tx,Ty} = At_mul_B!(one(Tx), A, x, zero(Ty), y) function At_mul_B!(α::Number, A::StridedMatrix, x::AbstractSparseVector, β::Number, y::StridedVector) @@ -1603,7 +1603,7 @@ end # A_mul_B -A_mul_B!{Tx,Ty}(y::StridedVector{Ty}, A::SparseMatrixCSC, x::AbstractSparseVector{Tx}) = +A_mul_B!(y::StridedVector{Ty}, A::SparseMatrixCSC, x::AbstractSparseVector{Tx}) where {Tx,Ty} = A_mul_B!(one(Tx), A, x, zero(Ty), y) function A_mul_B!(α::Number, A::SparseMatrixCSC, x::AbstractSparseVector, β::Number, y::StridedVector) @@ -1636,13 +1636,13 @@ end # At_mul_B -At_mul_B!{Tx,Ty}(y::StridedVector{Ty}, A::SparseMatrixCSC, x::AbstractSparseVector{Tx}) = +At_mul_B!(y::StridedVector{Ty}, A::SparseMatrixCSC, x::AbstractSparseVector{Tx}) where {Tx,Ty} = At_mul_B!(one(Tx), A, x, zero(Ty), y) At_mul_B!(α::Number, A::SparseMatrixCSC, x::AbstractSparseVector, β::Number, y::StridedVector) = _At_or_Ac_mul_B!(*, α, A, x, β, y) -Ac_mul_B!{Tx,Ty}(y::StridedVector{Ty}, A::SparseMatrixCSC, x::AbstractSparseVector{Tx}) = +Ac_mul_B!(y::StridedVector{Ty}, A::SparseMatrixCSC, x::AbstractSparseVector{Tx}) where {Tx,Ty} = Ac_mul_B!(one(Tx), A, x, zero(Ty), y) Ac_mul_B!(α::Number, A::SparseMatrixCSC, x::AbstractSparseVector, β::Number, y::StridedVector) = @@ -1690,7 +1690,7 @@ At_mul_B(A::SparseMatrixCSC, x::AbstractSparseVector) = Ac_mul_B(A::SparseMatrixCSC, x::AbstractSparseVector) = _At_or_Ac_mul_B(dot, A, x) -function _At_or_Ac_mul_B{TvA,TiA,TvX,TiX}(tfun::Function, A::SparseMatrixCSC{TvA,TiA}, x::AbstractSparseVector{TvX,TiX}) +function _At_or_Ac_mul_B(tfun::Function, A::SparseMatrixCSC{TvA,TiA}, x::AbstractSparseVector{TvX,TiX}) where {TvA,TiA,TvX,TiX} m, n = size(A) length(x) == m || throw(DimensionMismatch()) Tv = promote_type(TvA, TvX) @@ -1921,7 +1921,7 @@ For an in-place version and algorithmic information, see [`dropzeros!`](@ref). dropzeros(x::SparseVector, trim::Bool = true) = dropzeros!(copy(x), trim) -function _fillnonzero!{Tv,Ti}(arr::SparseMatrixCSC{Tv, Ti}, val) +function _fillnonzero!(arr::SparseMatrixCSC{Tv, Ti}, val) where {Tv,Ti} m, n = size(arr) resize!(arr.colptr, n+1) resize!(arr.rowval, m*n) @@ -1938,7 +1938,7 @@ function _fillnonzero!{Tv,Ti}(arr::SparseMatrixCSC{Tv, Ti}, val) arr end -function _fillnonzero!{Tv,Ti}(arr::SparseVector{Tv,Ti}, val) +function _fillnonzero!(arr::SparseVector{Tv,Ti}, val) where {Tv,Ti} n = arr.n resize!(arr.nzind, n) resize!(arr.nzval, n) diff --git a/base/statistics.jl b/base/statistics.jl index 12bf64921a026..073638f3a0630 100644 --- a/base/statistics.jl +++ b/base/statistics.jl @@ -41,7 +41,7 @@ function mean!(R::AbstractArray, A::AbstractArray) return R end -momenttype{T}(::Type{T}) = typeof((zero(T)*zero(T) + zero(T)*zero(T)) / 2) +momenttype(::Type{T}) where {T} = typeof((zero(T)*zero(T) + zero(T)*zero(T)) / 2) momenttype(::Type{Float32}) = Float32 momenttype(::Type{<:Union{Float64,Int32,Int64,UInt32,UInt64}}) = Float64 @@ -54,7 +54,7 @@ Compute the mean of whole array `v`, or optionally along the dimensions in `regi Julia does not ignore `NaN` values in the computation. For applications requiring the handling of missing data, the `DataArrays.jl` package is recommended. """ -mean{T}(A::AbstractArray{T}, region) = +mean(A::AbstractArray{T}, region) where {T} = mean!(reducedim_initarray(A, region, 0, momenttype(T)), A) @@ -108,7 +108,7 @@ centralize_sumabs2(A::AbstractArray, m::Number) = centralize_sumabs2(A::AbstractArray, m::Number, ifirst::Int, ilast::Int) = mapreduce_impl(centralizedabs2fun(m), +, A, ifirst, ilast) -function centralize_sumabs2!{S}(R::AbstractArray{S}, A::AbstractArray, means::AbstractArray) +function centralize_sumabs2!(R::AbstractArray{S}, A::AbstractArray, means::AbstractArray) where S # following the implementation of _mapreducedim! at base/reducedim.jl lsiz = check_reducedims(R,A) isempty(R) || fill!(R, zero(S)) @@ -147,14 +147,14 @@ function centralize_sumabs2!{S}(R::AbstractArray{S}, A::AbstractArray, means::Ab return R end -function varm{T}(A::AbstractArray{T}, m::Number; corrected::Bool=true) +function varm(A::AbstractArray{T}, m::Number; corrected::Bool=true) where T n = _length(A) n == 0 && return convert(real(momenttype(T)), NaN) n == 1 && return convert(real(momenttype(T)), abs2(A[1] - m)/(1 - Int(corrected))) return centralize_sumabs2(A, m) / (n - Int(corrected)) end -function varm!{S}(R::AbstractArray{S}, A::AbstractArray, m::AbstractArray; corrected::Bool=true) +function varm!(R::AbstractArray{S}, A::AbstractArray, m::AbstractArray; corrected::Bool=true) where S if isempty(A) fill!(R, convert(S, NaN)) else @@ -177,11 +177,11 @@ whereas the sum is scaled with `n` if `corrected` is `false` where `n = length(x applications requiring the handling of missing data, the `DataArrays.jl` package is recommended. """ -varm{T}(A::AbstractArray{T}, m::AbstractArray, region; corrected::Bool=true) = +varm(A::AbstractArray{T}, m::AbstractArray, region; corrected::Bool=true) where {T} = varm!(reducedim_initarray(A, region, 0, real(momenttype(T))), A, m; corrected=corrected) -var{T}(A::AbstractArray{T}; corrected::Bool=true, mean=nothing) = +var(A::AbstractArray{T}; corrected::Bool=true, mean=nothing) where {T} = convert(real(momenttype(T)), varm(A, mean === nothing ? Base.mean(A) : mean; corrected=corrected)) @@ -399,7 +399,7 @@ clampcor(x) = x # cov2cor! -function cov2cor!{T}(C::AbstractMatrix{T}, xsd::AbstractArray) +function cov2cor!(C::AbstractMatrix{T}, xsd::AbstractArray) where T nx = length(xsd) size(C) == (nx, nx) || throw(DimensionMismatch("inconsistent dimensions")) for j = 1:nx @@ -447,7 +447,7 @@ end # corzm (non-exported, with centered data) -corzm{T}(x::AbstractVector{T}) = one(real(T)) +corzm(x::AbstractVector{T}) where {T} = one(real(T)) function corzm(x::AbstractMatrix, vardim::Int=1) c = unscaled_covzm(x, vardim) return cov2cor!(c, sqrt!(diag(c))) @@ -461,7 +461,7 @@ corzm(x::AbstractMatrix, y::AbstractMatrix, vardim::Int=1) = # corm -corm{T}(x::AbstractVector{T}, xmean) = one(real(T)) +corm(x::AbstractVector{T}, xmean) where {T} = one(real(T)) corm(x::AbstractMatrix, xmean, vardim::Int=1) = corzm(x .- xmean, vardim) function corm(x::AbstractVector, mx::Number, y::AbstractVector, my::Number) n = length(x) diff --git a/base/strings/basic.jl b/base/strings/basic.jl index c4cfcf280e27d..4a6c4fa17c73b 100644 --- a/base/strings/basic.jl +++ b/base/strings/basic.jl @@ -69,7 +69,7 @@ julia> "Hello " * "world" """ (*)(s1::AbstractString, ss::AbstractString...) = string(s1, ss...) -one{T<:AbstractString}(::Union{T,Type{T}}) = convert(T, "") +one(::Union{T,Type{T}}) where {T<:AbstractString} = convert(T, "") length(s::DirectIndexString) = endof(s) diff --git a/base/strings/types.jl b/base/strings/types.jl index 6b51d60176527..a57345e8600b6 100644 --- a/base/strings/types.jl +++ b/base/strings/types.jl @@ -73,7 +73,7 @@ chr2ind(s::SubString{<:DirectIndexString}, i::Integer) = begin checkbounds(s,i); nextind(s::SubString, i::Integer) = nextind(s.string, i+s.offset)-s.offset prevind(s::SubString, i::Integer) = prevind(s.string, i+s.offset)-s.offset -convert{T<:AbstractString}(::Type{SubString{T}}, s::T) = SubString(s, 1, endof(s)) +convert(::Type{SubString{T}}, s::T) where {T<:AbstractString} = SubString(s, 1, endof(s)) String(p::SubString{String}) = unsafe_string(pointer(p.string, p.offset+1), nextind(p, p.endof)-1) @@ -94,7 +94,7 @@ end # don't make unnecessary copies when passing substrings to C functions cconvert(::Type{Ptr{UInt8}}, s::SubString{String}) = s cconvert(::Type{Ptr{Int8}}, s::SubString{String}) = s -function unsafe_convert{R<:Union{Int8, UInt8}}(::Type{Ptr{R}}, s::SubString{String}) +function unsafe_convert(::Type{Ptr{R}}, s::SubString{String}) where R<:Union{Int8, UInt8} convert(Ptr{R}, pointer(s.string)) + s.offset end diff --git a/base/strings/utf8proc.jl b/base/strings/utf8proc.jl index 591d0b5793dd8..078ab703e2939 100644 --- a/base/strings/utf8proc.jl +++ b/base/strings/utf8proc.jl @@ -352,7 +352,7 @@ letter combined with an accent mark is a single grapheme.) """ graphemes(s::AbstractString) = GraphemeIterator{typeof(s)}(s) -eltype{S}(::Type{GraphemeIterator{S}}) = SubString{S} +eltype(::Type{GraphemeIterator{S}}) where {S} = SubString{S} function length(g::GraphemeIterator) c0 = Char(0x00ad) # soft hyphen (grapheme break always allowed after this) @@ -387,9 +387,9 @@ end hash(g::GraphemeIterator, h::UInt) = hash(g.s, h) isless(g1::GraphemeIterator, g2::GraphemeIterator) = isless(g1.s, g2.s) -convert{S<:AbstractString}(::Type{S}, g::GraphemeIterator) = convert(S, g.s) +convert(::Type{S}, g::GraphemeIterator) where {S<:AbstractString} = convert(S, g.s) -show{S}(io::IO, g::GraphemeIterator{S}) = print(io, "length-$(length(g)) GraphemeIterator{$S} for \"$(g.s)\"") +show(io::IO, g::GraphemeIterator{S}) where {S} = print(io, "length-$(length(g)) GraphemeIterator{$S} for \"$(g.s)\"") ############################################################################ diff --git a/base/subarray.jl b/base/subarray.jl index 536c569f11920..5c1d6b9e7263c 100644 --- a/base/subarray.jl +++ b/base/subarray.jl @@ -179,7 +179,7 @@ end # In general, we simply re-index the parent indices by the provided ones SlowSubArray{T,N,P,I} = SubArray{T,N,P,I,false} -function getindex{T,N}(V::SlowSubArray{T,N}, I::Vararg{Int,N}) +function getindex(V::SlowSubArray{T,N}, I::Vararg{Int,N}) where {T,N} @_inline_meta @boundscheck checkbounds(V, I...) @inbounds r = V.parent[reindex(V, V.indexes, I)...] @@ -202,7 +202,7 @@ function getindex(V::FastContiguousSubArray, i::Int) r end -function setindex!{T,N}(V::SlowSubArray{T,N}, x, I::Vararg{Int,N}) +function setindex!(V::SlowSubArray{T,N}, x, I::Vararg{Int,N}) where {T,N} @_inline_meta @boundscheck checkbounds(V, I...) @inbounds V.parent[reindex(V, V.indexes, I)...] = x @@ -270,7 +270,7 @@ compute_offset1(parent, stride1::Integer, dims::Tuple{Int}, inds::Tuple{Slice}, compute_offset1(parent, stride1::Integer, dims, inds, I::Tuple) = (@_inline_meta; compute_linindex(parent, I) - stride1) # linear indexing starts with 1 -function compute_linindex{N}(parent, I::NTuple{N,Any}) +function compute_linindex(parent, I::NTuple{N,Any}) where N @_inline_meta IP = fill_to_length(indices(parent), OneTo(1), Val{N}) compute_linindex(1, 1, IP, I) diff --git a/base/test.jl b/base/test.jl index fa639f97b3863..6fdaa48057bd5 100644 --- a/base/test.jl +++ b/base/test.jl @@ -1105,10 +1105,8 @@ end # # Raises an error if any columnwise vector norm exceeds err. Otherwise, returns # nothing. -function test_approx_eq_modphase{S<:Real,T<:Real}( - a::StridedVecOrMat{S}, b::StridedVecOrMat{T}, - err = length(indices(a,1))^3*(eps(S)+eps(T)) - ) +function test_approx_eq_modphase(a::StridedVecOrMat{S}, b::StridedVecOrMat{T}, + err = length(indices(a,1))^3*(eps(S)+eps(T))) where {S<:Real,T<:Real} @test indices(a,1) == indices(b,1) && indices(a,2) == indices(b,2) for i in indices(a,2) v1, v2 = a[:, i], b[:, i] @@ -1129,11 +1127,10 @@ elsewhere. want to set this to `false`. See [`Base.isambiguous`](@ref). """ function detect_ambiguities(mods...; - imported::Bool = false, - ambiguous_bottom::Bool = false, - allow_bottom::Union{Bool,Void} = nothing - ) - if allow_bottom != nothing + imported::Bool = false, + ambiguous_bottom::Bool = false, + allow_bottom::Union{Bool,Void} = nothing) + if allow_bottom !== nothing Base.depwarn("the `allow_bottom` keyword to detect_ambiguities has been renamed to `ambiguous_bottom`", :detect_ambiguities) ambiguous_bottom = allow_bottom end diff --git a/base/twiceprecision.jl b/base/twiceprecision.jl index 74f0829a49261..beb5383301d59 100644 --- a/base/twiceprecision.jl +++ b/base/twiceprecision.jl @@ -62,9 +62,9 @@ nbitslen(len, offset) = len < 2 ? 0 : ceil(Int, log2(max(offset-1, len-offset))) eltype(::Type{TwicePrecision{T}}) where {T} = T -promote_rule{R,S}(::Type{TwicePrecision{R}}, ::Type{TwicePrecision{S}}) = +promote_rule(::Type{TwicePrecision{R}}, ::Type{TwicePrecision{S}}) where {R,S} = TwicePrecision{promote_type(R,S)} -promote_rule{R,S}(::Type{TwicePrecision{R}}, ::Type{S}) = +promote_rule(::Type{TwicePrecision{R}}, ::Type{S}) where {R,S} = TwicePrecision{promote_type(R,S)} convert(::Type{TwicePrecision{T}}, x::TwicePrecision{T}) where {T} = x @@ -81,7 +81,7 @@ big(x::TwicePrecision) = big(x.hi) + big(x.lo) -(x::TwicePrecision) = TwicePrecision(-x.hi, -x.lo) -zero{T}(::Type{TwicePrecision{T}}) = TwicePrecision{T}(0, 0) +zero(::Type{TwicePrecision{T}}) where {T} = TwicePrecision{T}(0, 0) ## StepRangeLen @@ -120,7 +120,7 @@ function floatrange(a::AbstractFloat, st::AbstractFloat, len::Real, divisor::Abs TwicePrecision{T}((st,divisor), nbitslen(T, len, 1)), Int(len), 1) end -function colon{T<:Union{Float16,Float32,Float64}}(start::T, step::T, stop::T) +function colon(start::T, step::T, stop::T) where T<:Union{Float16,Float32,Float64} step == 0 && throw(ArgumentError("range step cannot be zero")) # see if the inputs have exact rational approximations (and if so, # perform all computations in terms of the rationals) @@ -234,10 +234,10 @@ convert(::Type{StepRangeLen{T,R,S}}, r::StepRangeLen{T,R,S}) where {T<:AbstractF convert(::Type{StepRangeLen{T,R,S}}, r::StepRangeLen) where {T<:AbstractFloat,R<:TwicePrecision,S<:TwicePrecision} = _convertSRL(StepRangeLen{T,R,S}, r) -convert{T<:Union{Float16,Float32,Float64}}(::Type{StepRangeLen{T}}, r::StepRangeLen) = +convert(::Type{StepRangeLen{T}}, r::StepRangeLen) where {T<:Union{Float16,Float32,Float64}} = _convertSRL(StepRangeLen{T,TwicePrecision{T},TwicePrecision{T}}, r) -convert{T<:Union{Float16,Float32,Float64}}(::Type{StepRangeLen{T}}, r::Range) = +convert(::Type{StepRangeLen{T}}, r::Range) where {T<:Union{Float16,Float32,Float64}} = _convertSRL(StepRangeLen{T,TwicePrecision{T},TwicePrecision{T}}, r) function _convertSRL{T,R,S}(::Type{StepRangeLen{T,R,S}}, r::StepRangeLen{<:Integer}) @@ -296,7 +296,7 @@ end # sum(1:n) as a product of two integers sumpair(n::Integer) = iseven(n) ? (n+1, n>>1) : (n, (n+1)>>1) -function +{T,R<:TwicePrecision}(r1::StepRangeLen{T,R}, r2::StepRangeLen{T,R}) +function +(r1::StepRangeLen{T,R}, r2::StepRangeLen{T,R}) where T where R<:TwicePrecision len = length(r1) (len == length(r2) || throw(DimensionMismatch("argument dimensions must match"))) @@ -456,7 +456,7 @@ function +(x::TwicePrecision, y::Number) end +(x::Number, y::TwicePrecision) = y+x -function +{T}(x::TwicePrecision{T}, y::TwicePrecision{T}) +function +(x::TwicePrecision{T}, y::TwicePrecision{T}) where T r = x.hi + y.hi s = abs(x.hi) > abs(y.hi) ? (((x.hi - r) + y.hi) + y.lo) + x.lo : (((y.hi - r) + x.hi) + x.lo) + y.lo TwicePrecision(r, s) @@ -483,7 +483,7 @@ end _mul2(x::TwicePrecision, v::Number) = TwicePrecision(x.hi*v, x.lo*v) -function *{R,S<:Number}(x::TwicePrecision{R}, v::S) +function *(x::TwicePrecision{R}, v::S) where R where S<:Number T = promote_type(R, S) _mul2(convert(TwicePrecision{T}, x), convert(T, v)) end diff --git a/base/util.jl b/base/util.jl index 57b6b5fc9f363..116ee5704b635 100644 --- a/base/util.jl +++ b/base/util.jl @@ -844,10 +844,10 @@ The default value for a type for use with the `@kwdef` macro. Returns: """ function kwdef_val end -kwdef_val{T}(::Type{Ptr{T}}) = Ptr{T}(C_NULL) +kwdef_val(::Type{Ptr{T}}) where {T} = Ptr{T}(C_NULL) kwdef_val(::Type{Cstring}) = Cstring(C_NULL) kwdef_val(::Type{Cwstring}) = Cwstring(C_NULL) -kwdef_val{T<:Integer}(::Type{T}) = zero(T) +kwdef_val(::Type{T}) where {T<:Integer} = zero(T) -kwdef_val{T}(::Type{T}) = T() +kwdef_val(::Type{T}) where {T} = T() diff --git a/base/weakkeydict.jl b/base/weakkeydict.jl index bffa5737f115f..232c4d88ac7fd 100644 --- a/base/weakkeydict.jl +++ b/base/weakkeydict.jl @@ -65,8 +65,8 @@ function WeakKeyDict(kv) end end -similar{K,V}(d::WeakKeyDict{K,V}) = WeakKeyDict{K,V}() -similar{K,V}(d::WeakKeyDict, ::Type{Pair{K,V}}) = WeakKeyDict{K,V}() +similar(d::WeakKeyDict{K,V}) where {K,V} = WeakKeyDict{K,V}() +similar(d::WeakKeyDict, ::Type{Pair{K,V}}) where {K,V} = WeakKeyDict{K,V}() # conversion between Dict types function convert(::Type{WeakKeyDict{K,V}},d::Associative) where V where K @@ -87,7 +87,7 @@ islocked(wkh::WeakKeyDict) = islocked(wkh.lock) lock(f, wkh::WeakKeyDict) = lock(f, wkh.lock) trylock(f, wkh::WeakKeyDict) = trylock(f, wkh.lock) -function setindex!{K}(wkh::WeakKeyDict{K}, v, key) +function setindex!(wkh::WeakKeyDict{K}, v, key) where K k = convert(K, key) finalizer(k, wkh.finalizer) lock(wkh) do @@ -96,7 +96,7 @@ function setindex!{K}(wkh::WeakKeyDict{K}, v, key) return wkh end -function getkey{K}(wkh::WeakKeyDict{K}, kk, default) +function getkey(wkh::WeakKeyDict{K}, kk, default) where K return lock(wkh) do k = getkey(wkh.ht, kk, secret_table_token) k === secret_table_token && return default @@ -104,20 +104,20 @@ function getkey{K}(wkh::WeakKeyDict{K}, kk, default) end end -get{K}(wkh::WeakKeyDict{K}, key, default) = lock(() -> get(wkh.ht, key, default), wkh) -get{K}(default::Callable, wkh::WeakKeyDict{K}, key) = lock(() -> get(default, wkh.ht, key), wkh) -get!{K}(wkh::WeakKeyDict{K}, key, default) = lock(() -> get!(wkh.ht, key, default), wkh) -get!{K}(default::Callable, wkh::WeakKeyDict{K}, key) = lock(() -> get!(default, wkh.ht, key), wkh) -pop!{K}(wkh::WeakKeyDict{K}, key) = lock(() -> pop!(wkh.ht, key), wkh) -pop!{K}(wkh::WeakKeyDict{K}, key, default) = lock(() -> pop!(wkh.ht, key, default), wkh) +get(wkh::WeakKeyDict{K}, key, default) where {K} = lock(() -> get(wkh.ht, key, default), wkh) +get(default::Callable, wkh::WeakKeyDict{K}, key) where {K} = lock(() -> get(default, wkh.ht, key), wkh) +get!(wkh::WeakKeyDict{K}, key, default) where {K} = lock(() -> get!(wkh.ht, key, default), wkh) +get!(default::Callable, wkh::WeakKeyDict{K}, key) where {K} = lock(() -> get!(default, wkh.ht, key), wkh) +pop!(wkh::WeakKeyDict{K}, key) where {K} = lock(() -> pop!(wkh.ht, key), wkh) +pop!(wkh::WeakKeyDict{K}, key, default) where {K} = lock(() -> pop!(wkh.ht, key, default), wkh) delete!{K}(wkh::WeakKeyDict{K}, key) = lock(() -> delete!(wkh.ht, key), wkh) empty!(wkh::WeakKeyDict) = (lock(() -> empty!(wkh.ht), wkh); wkh) -haskey{K}(wkh::WeakKeyDict{K}, key) = lock(() -> haskey(wkh.ht, key), wkh) -getindex{K}(wkh::WeakKeyDict{K}, key) = lock(() -> getindex(wkh.ht, key), wkh) +haskey(wkh::WeakKeyDict{K}, key) where {K} = lock(() -> haskey(wkh.ht, key), wkh) +getindex(wkh::WeakKeyDict{K}, key) where {K} = lock(() -> getindex(wkh.ht, key), wkh) isempty(wkh::WeakKeyDict) = isempty(wkh.ht) length(t::WeakKeyDict) = length(t.ht) -function start{K,V}(t::WeakKeyDict{K,V}) +function start(t::WeakKeyDict{K,V}) where V where K gc_token = Ref{Bool}(false) # no keys will be deleted via finalizers until this token is gc'd finalizer(gc_token, function(r) if r[] @@ -130,7 +130,7 @@ function start{K,V}(t::WeakKeyDict{K,V}) return (start(t.ht), gc_token) end done(t::WeakKeyDict, i) = done(t.ht, i[1]) -function next{K,V}(t::WeakKeyDict{K,V}, i) +function next(t::WeakKeyDict{K,V}, i) where V where K gc_token = i[2] wkv, i = next(t.ht, i[1]) kv = Pair{K,V}(wkv[1].value::K, wkv[2]) From 5444473732c5a147cec23ace64391de569a3a294 Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Fri, 21 Apr 2017 14:32:28 -0700 Subject: [PATCH 0490/1534] More stylistic updates to the manual for consistency (#21463) --- doc/src/manual/arrays.md | 4 +- doc/src/manual/dates.md | 4 +- doc/src/manual/documentation.md | 2 +- doc/src/manual/embedding.md | 52 ++++++++++++------------ doc/src/manual/faq.md | 10 ++--- doc/src/manual/interacting-with-julia.md | 10 ++--- doc/src/manual/interfaces.md | 6 +-- doc/src/manual/metaprogramming.md | 14 +++---- doc/src/manual/modules.md | 2 +- doc/src/manual/networking-and-streams.md | 26 ++++++------ doc/src/manual/parallel-computing.md | 2 +- doc/src/manual/performance-tips.md | 32 +++++++-------- doc/src/manual/style-guide.md | 2 +- 13 files changed, 83 insertions(+), 83 deletions(-) diff --git a/doc/src/manual/arrays.md b/doc/src/manual/arrays.md index d2dd09906b16f..2ac46480a4369 100644 --- a/doc/src/manual/arrays.md +++ b/doc/src/manual/arrays.md @@ -513,7 +513,7 @@ iterate over any array type. If you write a custom `AbstractArray` type, you can specify that it has fast linear indexing using ```julia -Base.IndexStyle{T<:MyArray}(::Type{T}) = IndexLinear() +Base.IndexStyle(::Type{<:MyArray}) = IndexLinear() ``` This setting will cause `eachindex` iteration over a `MyArray` to use integers. If you don't @@ -716,7 +716,7 @@ Julia sparse matrices have the type `SparseMatrixCSC{Tv,Ti}`, where `Tv` is the values, and `Ti` is the integer type for storing column pointers and row indices.: ```julia -type SparseMatrixCSC{Tv,Ti<:Integer} <: AbstractSparseMatrix{Tv,Ti} +struct SparseMatrixCSC{Tv,Ti<:Integer} <: AbstractSparseMatrix{Tv,Ti} m::Int # Number of rows n::Int # Number of columns colptr::Vector{Ti} # Column i is in colptr[i]:(colptr[i+1]-1) diff --git a/doc/src/manual/dates.md b/doc/src/manual/dates.md index 6c4e4a84a40a8..4fbd3b953f97a 100644 --- a/doc/src/manual/dates.md +++ b/doc/src/manual/dates.md @@ -119,8 +119,8 @@ julia> dt2 = Date("2015-01-02",df) You can also use the `dateformat""` string macro. This macro creates the `DateFormat` object once when the macro is expanded and uses the same `DateFormat` object even if a code snippet is run multiple times. ```jldoctest -julia> for i=1:10^5 - Date("2015-01-01",dateformat"y-m-d") +julia> for i = 1:10^5 + Date("2015-01-01", dateformat"y-m-d") end ``` diff --git a/doc/src/manual/documentation.md b/doc/src/manual/documentation.md index 754bca4ca9699..85b4fef5a0e41 100644 --- a/doc/src/manual/documentation.md +++ b/doc/src/manual/documentation.md @@ -267,7 +267,7 @@ instance, rather than just on the type itself. In these cases, you can add a met for your custom type that returns the documentation on a per-instance basis. For instance, ```julia -type MyType +struct MyType value::String end diff --git a/doc/src/manual/embedding.md b/doc/src/manual/embedding.md index 14e8d65e79a2f..64aeee8442202 100644 --- a/doc/src/manual/embedding.md +++ b/doc/src/manual/embedding.md @@ -11,7 +11,7 @@ further language bridges (e.g. calling Julia from Python or C#). We start with a simple C program that initializes Julia and calls some Julia code: -``` +```c #include int main(int argc, char *argv[]) @@ -83,15 +83,15 @@ shared data directory. #### Example -``` +```c #include int main(int argc, char *argv[]) { - jl_init(); - (void)jl_eval_string("println(sqrt(2.0))"); - jl_atexit_hook(0); - return 0; + jl_init(); + (void)jl_eval_string("println(sqrt(2.0))"); + jl_atexit_hook(0); + return 0; } ``` @@ -143,7 +143,7 @@ Julia object. Storing simple data types like `Float64` in this way is called `bo the stored primitive data is called `unboxing`. Our improved sample program that calculates the square root of 2 in Julia and reads back the result in C looks as follows: -``` +```c jl_value_t *ret = jl_eval_string("sqrt(2.0)"); if (jl_typeis(ret, jl_float64_type)) { @@ -163,7 +163,7 @@ is used in the above code snippet. Corresponding `jl_box_...` functions are used to convert the other way: -```julia +```c jl_value_t *a = jl_box_float64(3.0); jl_value_t *b = jl_box_float32(3.0f); jl_value_t *c = jl_box_int32(3); @@ -177,7 +177,7 @@ While `jl_eval_string` allows C to obtain the result of a Julia expression, it d passing arguments computed in C to Julia. For this you will need to invoke Julia functions directly, using `jl_call`: -```julia +```c jl_function_t *func = jl_get_function(jl_base_module, "sqrt"); jl_value_t *argument = jl_box_float64(2.0); jl_value_t *ret = jl_call1(func, argument); @@ -211,7 +211,7 @@ safe to use pointers in between `jl_...` calls. But in order to make sure that v `jl_...` calls, we have to tell Julia that we hold a reference to a Julia value. This can be done using the `JL_GC_PUSH` macros: -``` +```c jl_value_t *ret = jl_eval_string("sqrt(2.0)"); JL_GC_PUSH1(&ret); // Do something with ret @@ -226,7 +226,7 @@ Several Julia values can be pushed at once using the `JL_GC_PUSH2` , `JL_GC_PUSH macros. To push an array of Julia values one can use the `JL_GC_PUSHARGS` macro, which can be used as follows: -``` +```c jl_value_t **args; JL_GC_PUSHARGS(args, 2); // args can now hold 2 `jl_value_t*` objects args[0] = some_value; @@ -239,7 +239,7 @@ The garbage collector also operates under the assumption that it is aware of eve object pointing to a young-generation one. Any time a pointer is updated breaking that assumption, it must be signaled to the collector with the `jl_gc_wb` (write barrier) function like so: -``` +```c jl_value_t *parent = some_old_value, *child = some_young_value; ((some_specific_type*)parent)->field = child; jl_gc_wb(parent, child); @@ -253,7 +253,7 @@ can sometimes invoke garbage collection. The write barrier is also necessary for arrays of pointers when updating their data directly. For example: -``` +```c jl_array_t *some_array = ...; // e.g. a Vector{Any} void **data = (void**)jl_array_data(some_array); jl_value_t *some_value = ...; @@ -286,7 +286,7 @@ struct that contains: To keep things simple, we start with a 1D array. Creating an array containing Float64 elements of length 10 is done by: -```julia +```c jl_value_t* array_type = jl_apply_array_type(jl_float64_type, 1); jl_array_t* x = jl_alloc_array_1d(array_type, 10); ``` @@ -294,7 +294,7 @@ jl_array_t* x = jl_alloc_array_1d(array_type, 10); Alternatively, if you have already allocated the array you can generate a thin wrapper around its data: -``` +```c double *existingArray = (double*)malloc(sizeof(double)*10); jl_array_t *x = jl_ptr_to_array_1d(array_type, existingArray, 10, 0); ``` @@ -305,21 +305,21 @@ referenced. In order to access the data of x, we can use `jl_array_data`: -``` +```c double *xData = (double*)jl_array_data(x); ``` Now we can fill the array: -``` +```c for(size_t i=0; i (s,o...)->(LineEdit.edit_move_up(s) || LineEdit.history_prev(s, LineEdit.mode(s).hist)), - # Down Arrow - "\e[B" => (s,o...)->(LineEdit.edit_move_up(s) || LineEdit.history_next(s, LineEdit.mode(s).hist)) + # Up Arrow + "\e[A" => (s,o...)->(LineEdit.edit_move_up(s) || LineEdit.history_prev(s, LineEdit.mode(s).hist)), + # Down Arrow + "\e[B" => (s,o...)->(LineEdit.edit_move_up(s) || LineEdit.history_next(s, LineEdit.mode(s).hist)) ) function customize_keys(repl) - repl.interface = REPL.setup_interface(repl; extra_repl_keymap = mykeys) + repl.interface = REPL.setup_interface(repl; extra_repl_keymap = mykeys) end atreplinit(customize_keys) diff --git a/doc/src/manual/interfaces.md b/doc/src/manual/interfaces.md index f6ae319302b26..fd7b5cba85501 100644 --- a/doc/src/manual/interfaces.md +++ b/doc/src/manual/interfaces.md @@ -294,11 +294,11 @@ julia> SparseArray{T,N}(::Type{T}, dims::NTuple{N,Int}) = SparseArray{T,N}(Dict{ julia> Base.size(A::SparseArray) = A.dims -julia> Base.similar{T}(A::SparseArray, ::Type{T}, dims::Dims) = SparseArray(T, dims) +julia> Base.similar(A::SparseArray, ::Type{T}, dims::Dims) where {T} = SparseArray(T, dims) -julia> Base.getindex{T,N}(A::SparseArray{T,N}, I::Vararg{Int,N}) = get(A.data, I, zero(T)) +julia> Base.getindex(A::SparseArray{T,N}, I::Vararg{Int,N}) where {T,N} = get(A.data, I, zero(T)) -julia> Base.setindex!{T,N}(A::SparseArray{T,N}, v, I::Vararg{Int,N}) = (A.data[I] = v) +julia> Base.setindex!(A::SparseArray{T,N}, v, I::Vararg{Int,N}) where {T,N} = (A.data[I] = v) ``` Notice that this is an `IndexCartesian` array, so we must manually define [`getindex()`](@ref) and [`setindex!()`](@ref) diff --git a/doc/src/manual/metaprogramming.md b/doc/src/manual/metaprogramming.md index 7f9fc660e592d..f3820d04ba602 100644 --- a/doc/src/manual/metaprogramming.md +++ b/doc/src/manual/metaprogramming.md @@ -474,7 +474,7 @@ I execute at runtime. The argument is: (1, 2, 3) Macros are invoked with the following general syntax: -``` +```julia @name expr1 expr2 ... @name(expr1, expr2, ...) ``` @@ -484,7 +484,7 @@ expressions in the first form, and the lack of whitespace after `@name` in the s two styles should not be mixed. For example, the following syntax is different from the examples above; it passes the tuple `(expr1, expr2, ...)` as one argument to the macro: -``` +```julia @name (expr1, expr2, ...) ``` @@ -661,7 +661,7 @@ with any user variables, and `time` and `println` will refer to the standard lib One problem remains however. Consider the following use of this macro: -``` +```julia module MyModule import Base.@time @@ -675,7 +675,7 @@ Here the user expression `ex` is a call to `time`, but not the same `time` funct uses. It clearly refers to `MyModule.time`. Therefore we must arrange for the code in `ex` to be resolved in the macro call environment. This is done by "escaping" the expression with [`esc()`](@ref): -``` +```julia macro time(ex) ... local val = $(esc(ex)) @@ -1075,7 +1075,7 @@ can be used to index into an array `A` using `A[i]`, instead of `A[x,y,z,...]`. is the following: ```jldoctest sub2ind -julia> function sub2ind_loop{N}(dims::NTuple{N}, I::Integer...) +julia> function sub2ind_loop(dims::NTuple{N}, I::Integer...) where N ind = I[N] - 1 for i = N-1:-1:1 ind = I[i]-1 + dims[i]*ind @@ -1114,7 +1114,7 @@ we use generated functions to manually unroll the loop. The body becomes almost instead of calculating the linear index, we build up an *expression* that calculates the index: ```jldoctest sub2ind_gen -julia> @generated function sub2ind_gen{N}(dims::NTuple{N}, I::Integer...) +julia> @generated function sub2ind_gen(dims::NTuple{N}, I::Integer...) where N ex = :(I[$N] - 1) for i = (N - 1):-1:1 ex = :(I[$i] - 1 + dims[$i] * $ex) @@ -1132,7 +1132,7 @@ julia> sub2ind_gen((3, 5), 1, 2) An easy way to find out is to extract the body into another (regular) function: ```jldoctest sub2ind_gen2 -julia> @generated function sub2ind_gen{N}(dims::NTuple{N}, I::Integer...) +julia> @generated function sub2ind_gen(dims::NTuple{N}, I::Integer...) where N return sub2ind_gen_impl(dims, I...) end sub2ind_gen (generic function with 1 method) diff --git a/doc/src/manual/modules.md b/doc/src/manual/modules.md index 870e3029ea12a..cc8cfe7463447 100644 --- a/doc/src/manual/modules.md +++ b/doc/src/manual/modules.md @@ -321,7 +321,7 @@ Other known potential failure scenarios include: code snippet: ```julia - type UniquedById + mutable struct UniquedById myid::Int let counter = 0 UniquedById() = new(counter += 1) diff --git a/doc/src/manual/networking-and-streams.md b/doc/src/manual/networking-and-streams.md index db4d77564521c..8919f55b60e4f 100644 --- a/doc/src/manual/networking-and-streams.md +++ b/doc/src/manual/networking-and-streams.md @@ -175,7 +175,7 @@ anonymous function on the fly: ```julia julia> open("hello.txt") do f - uppercase(readstring(f)) + uppercase(readstring(f)) end "HELLO AGAIN." ``` @@ -186,11 +186,11 @@ Let's jump right in with a simple example involving TCP sockets. Let's first cre ```julia julia> @async begin - server = listen(2000) - while true - sock = accept(server) - println("Hello World\n") - end + server = listen(2000) + while true + sock = accept(server) + println("Hello World\n") + end end Task (runnable) @0x00007fd31dc11ae0 ``` @@ -252,13 +252,13 @@ To see this, consider the following simple echo server: ```julia julia> @async begin - server = listen(2001) - while true - sock = accept(server) - @async while isopen(sock) - write(sock,readline(sock)) + server = listen(2001) + while true + sock = accept(server) + @async while isopen(sock) + write(sock,readline(sock)) + end end - end end Task (runnable) @0x00007fd31dc12e60 @@ -266,7 +266,7 @@ julia> clientside = connect(2001) TCPSocket(RawFD(28) open, 0 bytes waiting) julia> @async while true - write(STDOUT,readline(clientside)) + write(STDOUT,readline(clientside)) end Task (runnable) @0x00007fd31dc11870 diff --git a/doc/src/manual/parallel-computing.md b/doc/src/manual/parallel-computing.md index ed465297c25c6..d3d84f6a652dd 100644 --- a/doc/src/manual/parallel-computing.md +++ b/doc/src/manual/parallel-computing.md @@ -520,7 +520,7 @@ A channel can be visualized as a pipe, i.e., it has a write end and read end. * Multiple readers in different tasks can read data concurrently via [`take!()`](@ref) calls. * As an example: - ``` + ```julia # Given Channels c1 and c2, c1 = Channel(32) c2 = Channel(32) diff --git a/doc/src/manual/performance-tips.md b/doc/src/manual/performance-tips.md index a0c9ed220dbe0..00f2a313ea640 100644 --- a/doc/src/manual/performance-tips.md +++ b/doc/src/manual/performance-tips.md @@ -359,10 +359,10 @@ However, there are cases where you may need to declare different versions of the for different element types of `a`. You could do it like this: ``` -function myfun{T<:AbstractFloat}(c::MySimpleContainer{Vector{T}}) +function myfun(c::MySimpleContainer{Vector{T}}) where T<:AbstractFloat ... end -function myfun{T<:Integer}(c::MySimpleContainer{Vector{T}}) +function myfun(c::MySimpleContainer{Vector{T}}) where T<:Integer ... end ``` @@ -389,17 +389,17 @@ Note the somewhat surprising fact that `T` doesn't appear in the declaration of that we'll return to in a moment. With this approach, one can write functions such as: ```jldoctest containers2 -julia> function myfunc{T<:Integer, A<:AbstractArray}(c::MyContainer{T,A}) +julia> function myfunc(c::MyContainer{<:Integer, <:AbstractArray}) return c.a[1]+1 end myfunc (generic function with 1 method) -julia> function myfunc{T<:AbstractFloat}(c::MyContainer{T}) +julia> function myfunc(c::MyContainer{<:AbstractFloat}) return c.a[1]+2 end myfunc (generic function with 2 methods) -julia> function myfunc{T<:Integer}(c::MyContainer{T,Vector{T}}) +julia> function myfunc(c::MyContainer{T,Vector{T}}) where T<:Integer return c.a[1]+3 end myfunc (generic function with 3 methods) @@ -509,7 +509,7 @@ function norm(A) if isa(A, Vector) return sqrt(real(dot(A,A))) elseif isa(A, Matrix) - return max(svd(A)[2]) + return maximum(svd(A)[2]) else error("norm: invalid argument") end @@ -520,7 +520,7 @@ This can be written more concisely and efficiently as: ```julia norm(x::Vector) = sqrt(real(dot(x,x))) -norm(A::Matrix) = max(svd(A)[2]) +norm(A::Matrix) = maximum(svd(A)[2]) ``` ## Write "type-stable" functions @@ -681,7 +681,7 @@ one approach is to pass the dimensionality as a parameter, for example through ` ["Value types"](@ref)): ```jldoctest -julia> function array3{N}(fillval, ::Type{Val{N}}) +julia> function array3(fillval, ::Type{Val{N}}) where N fill(fillval, ntuple(d->3, Val{N})) end array3 (generic function with 1 method) @@ -715,7 +715,7 @@ code like the above be used.) An example of correct usage of `Val` would be: ```julia -function filter3{T,N}(A::AbstractArray{T,N}) +function filter3(A::AbstractArray{T,N}) where {T,N} kernel = array3(1, Val{N}) filter(A, kernel) end @@ -804,7 +804,7 @@ copies (perhaps the rest of the code can be easily adapted accordingly). We coul do this in at least four ways (in addition to the recommended call to the built-in [`repmat()`](@ref)): ```julia -function copy_cols{T}(x::Vector{T}) +function copy_cols(x::Vector{T}) where T n = size(x, 1) out = Array{T}(n, n) for i = 1:n @@ -813,7 +813,7 @@ function copy_cols{T}(x::Vector{T}) out end -function copy_rows{T}(x::Vector{T}) +function copy_rows(x::Vector{T}) where T n = size(x, 1) out = Array{T}(n, n) for i = 1:n @@ -822,7 +822,7 @@ function copy_rows{T}(x::Vector{T}) out end -function copy_col_row{T}(x::Vector{T}) +function copy_col_row(x::Vector{T}) where T n = size(x, 1) out = Array{T}(n, n) for col = 1:n, row = 1:n @@ -831,7 +831,7 @@ function copy_col_row{T}(x::Vector{T}) out end -function copy_row_col{T}(x::Vector{T}) +function copy_row_col(x::Vector{T}) where T n = size(x, 1) out = Array{T}(n, n) for row = 1:n, col = 1:n @@ -886,7 +886,7 @@ end with ```julia -function xinc!{T}(ret::AbstractVector{T}, x::T) +function xinc!(ret::AbstractVector{T}, x::T) where T ret[1] = x ret[2] = x+1 ret[3] = x+2 @@ -1261,7 +1261,7 @@ strict IEEE behavior for subnormal numbers. Below is an example where subnormals noticeably impact performance on some hardware: ```julia -function timestep{T}( b::Vector{T}, a::Vector{T}, Δt::T ) +function timestep(b::Vector{T}, a::Vector{T}, Δt::T) where T @assert length(a)==length(b) n = length(b) b[1] = 1 # Boundary condition @@ -1271,7 +1271,7 @@ function timestep{T}( b::Vector{T}, a::Vector{T}, Δt::T ) b[n] = 0 # Boundary condition end -function heatflow{T}( a::Vector{T}, nstep::Integer ) +function heatflow(a::Vector{T}, nstep::Integer) where T b = similar(a) for t=1:div(nstep,2) # Assume nstep is even timestep(b,a,T(0.1)) diff --git a/doc/src/manual/style-guide.md b/doc/src/manual/style-guide.md index 86181bcdc8d82..c4ac88ffc20a6 100644 --- a/doc/src/manual/style-guide.md +++ b/doc/src/manual/style-guide.md @@ -123,7 +123,7 @@ Types such as `Union{Function,AbstractString}` are often a sign that some design When creating a type such as: ```julia -struct MyType +mutable struct MyType ... x::Union{Void,T} end From ba7a2651f7382935f8be2caee994c75a23e560fa Mon Sep 17 00:00:00 2001 From: Rory-Finnegan Date: Thu, 13 Apr 2017 18:47:56 -0500 Subject: [PATCH 0491/1534] Updated `filter!` to take an `AbstractVector` vs a `Vector`. --- base/array.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/array.jl b/base/array.jl index a6961462f0ef2..cffb5514274ab 100644 --- a/base/array.jl +++ b/base/array.jl @@ -1806,7 +1806,7 @@ julia> filter(isodd, a) """ filter(f, As::AbstractArray) = As[map(f, As)::AbstractArray{Bool}] -function filter!(f, a::Vector) +function filter!(f, a::AbstractVector) insrt = 1 for acurr in a if f(acurr) From 950db948ef0f6839d33143a5f3863dfe4c831c55 Mon Sep 17 00:00:00 2001 From: Rory-Finnegan Date: Tue, 18 Apr 2017 21:19:40 -0500 Subject: [PATCH 0492/1534] `filter!(f, a::AbstractVector)` now uses arbitrary indices --- base/array.jl | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/base/array.jl b/base/array.jl index cffb5514274ab..6be459cf142a7 100644 --- a/base/array.jl +++ b/base/array.jl @@ -1807,14 +1807,18 @@ julia> filter(isodd, a) filter(f, As::AbstractArray) = As[map(f, As)::AbstractArray{Bool}] function filter!(f, a::AbstractVector) - insrt = 1 + idx = eachindex(a) + state = start(idx) + (i, state) = next(idx, state) + for acurr in a if f(acurr) - a[insrt] = acurr - insrt += 1 + a[i] = acurr + (i, state) = next(idx, state) end end - deleteat!(a, insrt:length(a)) + + deleteat!(a, i:last(idx)) return a end From d3f22fd7d8120eaa6154ff74db9573c9f99e1a42 Mon Sep 17 00:00:00 2001 From: Rory-Finnegan Date: Tue, 18 Apr 2017 22:02:44 -0500 Subject: [PATCH 0493/1534] Added some tests for `filter!(f, a::AbstractVector)` --- test/arrayops.jl | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/arrayops.jl b/test/arrayops.jl index ca9bc0636ad2b..e4ba79c464d6f 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -1081,6 +1081,24 @@ end end end +@testset "filter!" begin + # base case w/ Vector + a = collect(1:10) + filter!(x -> x > 5, a) + + # different subtype of AbstractVector + @test a == collect(6:10) + ba = rand(10) .> 0.5 + filter!(x -> x, ba) + @test all(ba) + + # empty array + ea = [] + filter!(x -> x > 5, ea) + @test isempty(ea) +end + + @testset "deleteat!" begin for idx in Any[1, 2, 5, 9, 10, 1:0, 2:1, 1:1, 2:2, 1:2, 2:4, 9:8, 10:9, 9:9, 10:10, 8:9, 9:10, 6:9, 7:10] From 4c8d066c067fd3b42f9b0ddfd8e0cbc4ecc47ed9 Mon Sep 17 00:00:00 2001 From: Rory Finnegan Date: Wed, 19 Apr 2017 09:57:33 -0500 Subject: [PATCH 0494/1534] Fixed misplaced comment in filter! tests --- test/arrayops.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/arrayops.jl b/test/arrayops.jl index e4ba79c464d6f..1fe75ae1b1622 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -1085,10 +1085,11 @@ end # base case w/ Vector a = collect(1:10) filter!(x -> x > 5, a) + @test a == collect(6:10) # different subtype of AbstractVector - @test a == collect(6:10) ba = rand(10) .> 0.5 + @test isa(ba, BitArray) filter!(x -> x, ba) @test all(ba) From ac07ec536bd175d8db0d2bff26750534ed0470fa Mon Sep 17 00:00:00 2001 From: Rory-Finnegan Date: Fri, 21 Apr 2017 16:47:24 -0500 Subject: [PATCH 0495/1534] Added isempty check to `filter!(f, a::AbstractVector)` and added some `OffsetArray` tests. --- base/array.jl | 21 ++++++++++++--------- test/TestHelpers.jl | 18 ++++++++++++++++++ test/arrayops.jl | 15 ++++++++++++--- 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/base/array.jl b/base/array.jl index 6be459cf142a7..d88a9ab44cc97 100644 --- a/base/array.jl +++ b/base/array.jl @@ -1807,18 +1807,21 @@ julia> filter(isodd, a) filter(f, As::AbstractArray) = As[map(f, As)::AbstractArray{Bool}] function filter!(f, a::AbstractVector) - idx = eachindex(a) - state = start(idx) - (i, state) = next(idx, state) - - for acurr in a - if f(acurr) - a[i] = acurr - (i, state) = next(idx, state) + if !isempty(a) + idx = eachindex(a) + state = start(idx) + i, state = next(idx, state) + + for acurr in a + if f(acurr) + a[i] = acurr + i, state = next(idx, state) + end end + + deleteat!(a, i:last(idx)) end - deleteat!(a, i:last(idx)) return a end diff --git a/test/TestHelpers.jl b/test/TestHelpers.jl index 422cd085410ff..59eb7328a1d68 100644 --- a/test/TestHelpers.jl +++ b/test/TestHelpers.jl @@ -198,6 +198,24 @@ end val end +@inline function Base.deleteat!(A::OffsetArray, i::Int) + checkbounds(A, i) + @inbounds deleteat!(parent(A), offset(A.offsets, (i,))[1]) +end + +@inline function Base.deleteat!{T,N}(A::OffsetArray{T,N}, I::Vararg{Int, N}) + checkbounds(A, I...) + @inbounds deleteat!(parent(A), offset(A.offsets, I)...) +end + +@inline function Base.deleteat!(A::OffsetArray, i::UnitRange{Int}) + checkbounds(A, first(i)) + checkbounds(A, last(i)) + first_idx = offset(A.offsets, (first(i),))[1] + last_idx = offset(A.offsets, (last(i),))[1] + @inbounds deleteat!(parent(A), first_idx:last_idx) +end + # Computing a shifted index (subtracting the offset) offset{N}(offsets::NTuple{N,Int}, inds::NTuple{N,Int}) = _offset((), offsets, inds) _offset(out, ::Tuple{}, ::Tuple{}) = out diff --git a/test/arrayops.jl b/test/arrayops.jl index 1fe75ae1b1622..b27f348f30694 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -1,6 +1,8 @@ # This file is a part of Julia. License is MIT: http://julialang.org/license # Array test +isdefined(Main, :TestHelpers) || @eval Main include("TestHelpers.jl") +using TestHelpers.OAs @testset "basics" begin @test length([1, 2, 3]) == 3 @@ -1097,6 +1099,16 @@ end ea = [] filter!(x -> x > 5, ea) @test isempty(ea) + + # non-1-indexed array + oa = OffsetArray(collect(1:10), -5) + filter!(x -> x > 5, oa) + @test oa == OffsetArray(collect(6:10), -5) + + # empty non-1-indexed array + eoa = OffsetArray([], -5) + filter!(x -> x > 5, eoa) + @test isempty(eoa) end @@ -1211,9 +1223,6 @@ A = [[i i; i i] for i=1:2] @test cumsum(A) == Any[[1 1; 1 1], [3 3; 3 3]] @test cumprod(A) == Any[[1 1; 1 1], [4 4; 4 4]] -isdefined(Main, :TestHelpers) || @eval Main include("TestHelpers.jl") -using TestHelpers.OAs - @testset "prepend/append" begin # PR #4627 A = [1,2] From 9d7fdc9651627e6fcfb6c7cd531d3889d7dac195 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 21 Apr 2017 18:59:03 -0400 Subject: [PATCH 0496/1534] isolate `known_object_data` when deserializing from multiple streams --- base/distributed/clusterserialize.jl | 26 ++++++++++++++----- base/serialize.jl | 39 +++++++++++++++++----------- test/serialize.jl | 5 ++-- 3 files changed, 47 insertions(+), 23 deletions(-) diff --git a/base/distributed/clusterserialize.jl b/base/distributed/clusterserialize.jl index 043ca57abf576..fd865a05e3771 100644 --- a/base/distributed/clusterserialize.jl +++ b/base/distributed/clusterserialize.jl @@ -1,9 +1,11 @@ # This file is a part of Julia. License is MIT: http://julialang.org/license -using Base.Serializer: known_object_data, object_number, serialize_cycle, deserialize_cycle, writetag, +using Base.Serializer: object_number, serialize_cycle, deserialize_cycle, writetag, __deserialized_types__, serialize_typename, deserialize_typename, TYPENAME_TAG, object_numbers, reset_state, serialize_type +import Base.Serializer: lookup_object_number, remember_object + mutable struct ClusterSerializer{I<:IO} <: AbstractSerializer io::I counter::Int @@ -23,15 +25,27 @@ mutable struct ClusterSerializer{I<:IO} <: AbstractSerializer end ClusterSerializer(io::IO) = ClusterSerializer{typeof(io)}(io) +const known_object_data = Dict{UInt64,Any}() + +function lookup_object_number(s::ClusterSerializer, n::UInt64) + return get(known_object_data, n, nothing) +end + +function remember_object(s::ClusterSerializer, o::ANY, n::UInt64) + known_object_data[n] = o + if isa(o, TypeName) && !haskey(object_numbers, o) + # set up reverse mapping for serialize + object_numbers[o] = n + end + return nothing +end + function deserialize(s::ClusterSerializer, ::Type{TypeName}) full_body_sent = deserialize(s) number = read(s.io, UInt64) if !full_body_sent - tn = get(known_object_data, number, nothing)::TypeName - if !haskey(object_numbers, tn) - # set up reverse mapping for serialize - object_numbers[tn] = number - end + tn = lookup_object_number(s, number)::TypeName + remember_object(s, tn, number) deserialize_cycle(s, tn) else tn = deserialize_typename(s, number) diff --git a/base/serialize.jl b/base/serialize.jl index df85a9659874b..606b0908f867c 100644 --- a/base/serialize.jl +++ b/base/serialize.jl @@ -12,7 +12,8 @@ mutable struct SerializationState{I<:IO} <: AbstractSerializer io::I counter::Int table::ObjectIdDict - SerializationState{I}(io::I) where I<:IO = new(io, 0, ObjectIdDict()) + known_object_data::Dict{UInt64,Any} + SerializationState{I}(io::I) where I<:IO = new(io, 0, ObjectIdDict(), Dict{UInt64,Any}()) end SerializationState(io::IO) = SerializationState{typeof(io)}(io) @@ -326,7 +327,7 @@ end # TODO: make this bidirectional, so objects can be sent back via the same key const object_numbers = WeakKeyDict() -obj_number_salt = 0 +const obj_number_salt = Ref(0) function object_number(l::ANY) global obj_number_salt, object_numbers if haskey(object_numbers, l) @@ -334,12 +335,25 @@ function object_number(l::ANY) end # a hash function that always gives the same number to the same # object on the same machine, and is unique over all machines. - ln = obj_number_salt+(UInt64(myid())<<44) - obj_number_salt += 1 + ln = obj_number_salt[]+(UInt64(myid())<<44) + obj_number_salt[] += 1 object_numbers[l] = ln return ln::UInt64 end +lookup_object_number(s::AbstractSerializer, n::UInt64) = nothing + +remember_object(s::AbstractSerializer, o::ANY, n::UInt64) = nothing + +function lookup_object_number(s::SerializationState, n::UInt64) + return get(s.known_object_data, n, nothing) +end + +function remember_object(s::SerializationState, o::ANY, n::UInt64) + s.known_object_data[n] = o + return nothing +end + function serialize(s::AbstractSerializer, meth::Method) serialize_cycle(s, meth) && return writetag(s.io, METHOD_TAG) @@ -636,12 +650,11 @@ function deserialize(s::AbstractSerializer, ::Type{Module}) m end -const known_object_data = Dict() - function deserialize(s::AbstractSerializer, ::Type{Method}) lnumber = read(s.io, UInt64) - if haskey(known_object_data, lnumber) - meth = known_object_data[lnumber]::Method + meth = lookup_object_number(s, lnumber) + if meth !== nothing + meth = meth::Method makenew = false else meth = ccall(:jl_new_method_uninit, Ref{Method}, ()) @@ -683,7 +696,7 @@ function deserialize(s::AbstractSerializer, ::Type{Method}) if isdefined(ftype.name, :mt) && nothing === ccall(:jl_methtable_lookup, Any, (Any, Any, UInt), ftype.name.mt, sig, typemax(UInt)) ccall(:jl_method_table_insert, Void, (Any, Any, Ptr{Void}), ftype.name.mt, meth, C_NULL) end - known_object_data[lnumber] = meth + remember_object(s, meth, lnumber) end return meth end @@ -781,7 +794,7 @@ end function deserialize_typename(s::AbstractSerializer, number) name = deserialize(s)::Symbol - tn = get(known_object_data, number, nothing) + tn = lookup_object_number(s, number) if tn !== nothing makenew = false else @@ -790,12 +803,8 @@ function deserialize_typename(s::AbstractSerializer, number) tn = ccall(:jl_new_typename_in, Ref{TypeName}, (Any, Any), tn_name, __deserialized_types__) makenew = true - known_object_data[number] = tn - end - if !haskey(object_numbers, tn) - # set up reverse mapping for serialize - object_numbers[tn] = number end + remember_object(s, tn, number) deserialize_cycle(s, tn) names = deserialize(s)::SimpleVector diff --git a/test/serialize.jl b/test/serialize.jl index 63aac82a3f55e..02efc45685b3a 100644 --- a/test/serialize.jl +++ b/test/serialize.jl @@ -294,11 +294,12 @@ main_ex = quote serialize(s, g) seekstart(s) - local g2 = deserialize(s) + ds = SerializationState(s) + local g2 = deserialize(ds) $Test.@test g2 !== g $Test.@test g2() == :magic_token_anon_fun_test $Test.@test g2() == :magic_token_anon_fun_test - $Test.@test deserialize(s) === g2 + $Test.@test deserialize(ds) === g2 end end # This needs to be run on `Main` since the serializer treats it differently. From 2096f6888e05a868c82fca8707077de7e2d33dc4 Mon Sep 17 00:00:00 2001 From: Mus M Date: Fri, 21 Apr 2017 20:02:43 -0400 Subject: [PATCH 0497/1534] Update misc methods to where syntax and use Vector instead of Array where it makes sense (#21457) * Update misc methods to where syntax * More changes * Explicitly pass size and type in unsafe_wrap --- base/linalg/blas.jl | 17 ++-- base/linalg/dense.jl | 8 +- base/linalg/givens.jl | 2 +- base/linalg/lq.jl | 2 +- base/linalg/matmul.jl | 8 +- base/linalg/symmetric.jl | 4 +- base/permuteddimsarray.jl | 4 +- base/reducedim.jl | 6 +- base/sparse/cholmod.jl | 162 +++++++++++++++---------------- base/sparse/sparsematrix.jl | 189 ++++++++++++++++++------------------ base/sparse/sparsevector.jl | 100 +++++++++---------- base/sparse/spqr.jl | 2 +- 12 files changed, 251 insertions(+), 253 deletions(-) diff --git a/base/linalg/blas.jl b/base/linalg/blas.jl index 09e7f81ad3790..f7e0667b53db4 100644 --- a/base/linalg/blas.jl +++ b/base/linalg/blas.jl @@ -305,21 +305,21 @@ for (fname, elty) in ((:cblas_zdotu_sub,:Complex128), end end end -function dot{T<:BlasReal}(DX::Union{DenseArray{T},StridedVector{T}}, DY::Union{DenseArray{T},StridedVector{T}}) +function dot(DX::Union{DenseArray{T},StridedVector{T}}, DY::Union{DenseArray{T},StridedVector{T}}) where T<:BlasReal n = length(DX) if n != length(DY) throw(DimensionMismatch("dot product arguments have lengths $(length(DX)) and $(length(DY))")) end dot(n, pointer(DX), stride(DX, 1), pointer(DY), stride(DY, 1)) end -function dotc{T<:BlasComplex}(DX::Union{DenseArray{T},StridedVector{T}}, DY::Union{DenseArray{T},StridedVector{T}}) +function dotc(DX::Union{DenseArray{T},StridedVector{T}}, DY::Union{DenseArray{T},StridedVector{T}}) where T<:BlasComplex n = length(DX) if n != length(DY) throw(DimensionMismatch("dot product arguments have lengths $(length(DX)) and $(length(DY))")) end dotc(n, pointer(DX), stride(DX, 1), pointer(DY), stride(DY, 1)) end -function dotu{T<:BlasComplex}(DX::Union{DenseArray{T},StridedVector{T}}, DY::Union{DenseArray{T},StridedVector{T}}) +function dotu(DX::Union{DenseArray{T},StridedVector{T}}, DY::Union{DenseArray{T},StridedVector{T}}) where T<:BlasComplex n = length(DX) if n != length(DY) throw(DimensionMismatch("dot product arguments have lengths $(length(DX)) and $(length(DY))")) @@ -437,7 +437,7 @@ for (fname, elty) in ((:daxpy_,:Float64), end end end -function axpy!{T<:BlasFloat}(alpha::Number, x::Union{DenseArray{T},StridedVector{T}}, y::Union{DenseArray{T},StridedVector{T}}) +function axpy!(alpha::Number, x::Union{DenseArray{T},StridedVector{T}}, y::Union{DenseArray{T},StridedVector{T}}) where T<:BlasFloat if length(x) != length(y) throw(DimensionMismatch("x has length $(length(x)), but y has length $(length(y))")) end @@ -445,9 +445,8 @@ function axpy!{T<:BlasFloat}(alpha::Number, x::Union{DenseArray{T},StridedVector y end -function axpy!{T<:BlasFloat,Ti<:Integer}(alpha::Number, x::Array{T}, rx::Union{UnitRange{Ti},Range{Ti}}, - y::Array{T}, ry::Union{UnitRange{Ti},Range{Ti}}) - +function axpy!(alpha::Number, x::Array{T}, rx::Union{UnitRange{Ti},Range{Ti}}, + y::Array{T}, ry::Union{UnitRange{Ti},Range{Ti}}) where {T<:BlasFloat,Ti<:Integer} if length(rx) != length(ry) throw(DimensionMismatch("ranges of differing lengths")) end @@ -1464,8 +1463,8 @@ end end # module -function copy!{T<:BlasFloat,Ti<:Integer}(dest::Array{T}, rdest::Union{UnitRange{Ti},Range{Ti}}, - src::Array{T}, rsrc::Union{UnitRange{Ti},Range{Ti}}) +function copy!(dest::Array{T}, rdest::Union{UnitRange{Ti},Range{Ti}}, + src::Array{T}, rsrc::Union{UnitRange{Ti},Range{Ti}}) where {T<:BlasFloat,Ti<:Integer} if minimum(rdest) < 1 || maximum(rdest) > length(dest) throw(ArgumentError("range out of bounds for dest, of length $(length(dest))")) end diff --git a/base/linalg/dense.jl b/base/linalg/dense.jl index e2516fee049da..6b37b15a212b6 100644 --- a/base/linalg/dense.jl +++ b/base/linalg/dense.jl @@ -9,7 +9,7 @@ const DOT_CUTOFF = 128 const ASUM_CUTOFF = 32 const NRM2_CUTOFF = 32 -function scale!{T<:BlasFloat}(X::Array{T}, s::T) +function scale!(X::Array{T}, s::T) where T<:BlasFloat s == 0 && return fill!(X, zero(T)) s == 1 && return X if length(X) < SCAL_CUTOFF @@ -20,10 +20,10 @@ function scale!{T<:BlasFloat}(X::Array{T}, s::T) X end -scale!{T<:BlasFloat}(s::T, X::Array{T}) = scale!(X, s) +scale!(s::T, X::Array{T}) where {T<:BlasFloat} = scale!(X, s) -scale!{T<:BlasFloat}(X::Array{T}, s::Number) = scale!(X, convert(T, s)) -function scale!{T<:BlasComplex}(X::Array{T}, s::Real) +scale!(X::Array{T}, s::Number) where {T<:BlasFloat} = scale!(X, convert(T, s)) +function scale!(X::Array{T}, s::Real) where T<:BlasComplex R = typeof(real(zero(T))) BLAS.scal!(2*length(X), convert(R,s), convert(Ptr{R},pointer(X)), 1) X diff --git a/base/linalg/givens.jl b/base/linalg/givens.jl index f372710dc9787..4a9766f19fb56 100644 --- a/base/linalg/givens.jl +++ b/base/linalg/givens.jl @@ -42,7 +42,7 @@ convert(::Type{AbstractRotation{T}}, G::Givens) where {T} = convert(Givens{T}, G convert(::Type{AbstractRotation{T}}, R::Rotation) where {T} = convert(Rotation{T}, R) ctranspose(G::Givens) = Givens(G.i1, G.i2, conj(G.c), -G.s) -ctranspose{T}(R::Rotation{T}) = Rotation{T}(reverse!([ctranspose(r) for r in R.rotations])) +ctranspose(R::Rotation{T}) where {T} = Rotation{T}(reverse!([ctranspose(r) for r in R.rotations])) realmin2(::Type{Float32}) = reinterpret(Float32, 0x26000000) realmin2(::Type{Float64}) = reinterpret(Float64, 0x21a0000000000000) diff --git a/base/linalg/lq.jl b/base/linalg/lq.jl index 42844b41294f7..18c3845b2dc32 100644 --- a/base/linalg/lq.jl +++ b/base/linalg/lq.jl @@ -56,7 +56,7 @@ convert(::Type{Matrix}, A::LQ) = convert(Array, convert(AbstractArray, A)) convert(::Type{Array}, A::LQ) = convert(Matrix, A) full(A::LQ) = convert(AbstractArray, A) -ctranspose{T}(A::LQ{T}) = QR{T,typeof(A.factors)}(A.factors', A.τ) +ctranspose(A::LQ{T}) where {T} = QR{T,typeof(A.factors)}(A.factors', A.τ) function getindex(A::LQ, d::Symbol) m, n = size(A) diff --git a/base/linalg/matmul.jl b/base/linalg/matmul.jl index f7dd618f0178e..5bbcb6f63fca8 100644 --- a/base/linalg/matmul.jl +++ b/base/linalg/matmul.jl @@ -467,9 +467,9 @@ function generic_matmatmul(tA, tB, A::AbstractVecOrMat{T}, B::AbstractMatrix{S}) end const tilebufsize = 10800 # Approximately 32k/3 -const Abuf = Array{UInt8}(tilebufsize) -const Bbuf = Array{UInt8}(tilebufsize) -const Cbuf = Array{UInt8}(tilebufsize) +const Abuf = Vector{UInt8}(tilebufsize) +const Bbuf = Vector{UInt8}(tilebufsize) +const Cbuf = Vector{UInt8}(tilebufsize) function generic_matmatmul!(C::AbstractMatrix, tA, tB, A::AbstractMatrix, B::AbstractMatrix) mA, nA = lapack_size(tA, A) @@ -502,7 +502,7 @@ function _generic_matmatmul!(C::AbstractVecOrMat{R}, tA, tB, A::AbstractVecOrMat tile_size = 0 if isbits(R) && isbits(T) && isbits(S) && (tA == 'N' || tB != 'N') - tile_size = floor(Int,sqrt(tilebufsize/max(sizeof(R),sizeof(S),sizeof(T)))) + tile_size = floor(Int, sqrt(tilebufsize / max(sizeof(R), sizeof(S), sizeof(T)))) end @inbounds begin if tile_size > 0 diff --git a/base/linalg/symmetric.jl b/base/linalg/symmetric.jl index 10e2dd5a5fc6a..2278afa943cd7 100644 --- a/base/linalg/symmetric.jl +++ b/base/linalg/symmetric.jl @@ -138,8 +138,8 @@ convert(::Type{Hermitian{T,S}},A::Hermitian{T,S}) where {T,S<:AbstractMatrix} = convert(::Type{Hermitian{T,S}},A::Hermitian) where {T,S<:AbstractMatrix} = Hermitian{T,S}(convert(S,A.data),A.uplo) convert(::Type{AbstractMatrix{T}}, A::Hermitian) where {T} = Hermitian(convert(AbstractMatrix{T}, A.data), Symbol(A.uplo)) -copy{T,S}(A::Symmetric{T,S}) = (B = copy(A.data); Symmetric{T,typeof(B)}(B,A.uplo)) -copy{T,S}(A::Hermitian{T,S}) = (B = copy(A.data); Hermitian{T,typeof(B)}(B,A.uplo)) +copy(A::Symmetric{T,S}) where {T,S} = (B = copy(A.data); Symmetric{T,typeof(B)}(B,A.uplo)) +copy(A::Hermitian{T,S}) where {T,S} = (B = copy(A.data); Hermitian{T,typeof(B)}(B,A.uplo)) function copy!(dest::Symmetric, src::Symmetric) if src.uplo == dest.uplo diff --git a/base/permuteddimsarray.jl b/base/permuteddimsarray.jl index 506b4c4a43b6b..e93cbfe67c949 100644 --- a/base/permuteddimsarray.jl +++ b/base/permuteddimsarray.jl @@ -132,13 +132,13 @@ function Base.permutedims!(dest, src::AbstractArray, perm) return dest end -function Base.copy!{T,N}(dest::PermutedDimsArray{T,N}, src::AbstractArray{T,N}) +function Base.copy!(dest::PermutedDimsArray{T,N}, src::AbstractArray{T,N}) where {T,N} checkbounds(dest, indices(src)...) _copy!(dest, src) end Base.copy!(dest::PermutedDimsArray, src::AbstractArray) = _copy!(dest, src) -function _copy!{T,N,perm}(P::PermutedDimsArray{T,N,perm}, src) +function _copy!(P::PermutedDimsArray{T,N,perm}, src) where {T,N,perm} # If dest/src are "close to dense," then it pays to be cache-friendly. # Determine the first permuted dimension d = 0 # d+1 will hold the first permuted dimension of src diff --git a/base/reducedim.jl b/base/reducedim.jl index 1095fcf41f79d..837fa564c248c 100644 --- a/base/reducedim.jl +++ b/base/reducedim.jl @@ -576,7 +576,7 @@ end ##### findmin & findmax ##### -function findminmax!{T,N}(f, Rval, Rind, A::AbstractArray{T,N}) +function findminmax!(f, Rval, Rind, A::AbstractArray{T,N}) where {T,N} (isempty(Rval) || isempty(A)) && return Rval, Rind lsiz = check_reducedims(Rval, A) for i = 1:N @@ -650,7 +650,7 @@ julia> findmin(A, 2) ([1; 3], [1; 2]) ``` """ -function findmin{T}(A::AbstractArray{T}, region) +function findmin(A::AbstractArray{T}, region) where T if isempty(A) return (similar(A, reduced_indices0(A, region)), similar(dims->zeros(Int, dims), reduced_indices0(A, region))) @@ -688,7 +688,7 @@ julia> findmax(A,2) ([2; 4], [3; 4]) ``` """ -function findmax{T}(A::AbstractArray{T}, region) +function findmax(A::AbstractArray{T}, region) where T if isempty(A) return (similar(A, reduced_indices0(A,region)), similar(dims->zeros(Int, dims), reduced_indices0(A,region))) diff --git a/base/sparse/cholmod.jl b/base/sparse/cholmod.jl index 31800d3039c68..92aaaee905941 100644 --- a/base/sparse/cholmod.jl +++ b/base/sparse/cholmod.jl @@ -389,7 +389,7 @@ function allocate_dense(nrow::Integer, ncol::Integer, d::Integer, ::Type{Complex d end -free_dense!{T}(p::Ptr{C_Dense{T}}) = ccall((:cholmod_l_free_dense, :libcholmod), +free_dense!(p::Ptr{C_Dense{T}}) where {T} = ccall((:cholmod_l_free_dense, :libcholmod), Cint, (Ref{Ptr{C_Dense{T}}}, Ptr{Void}), p, common()) function zeros{T<:VTypes}(m::Integer, n::Integer, ::Type{T}) @@ -420,7 +420,7 @@ end eye(m::Integer, n::Integer) = eye(m, n, Float64) eye(n::Integer) = eye(n, n, Float64) -function copy_dense{Tv<:VTypes}(A::Dense{Tv}) +function copy_dense(A::Dense{Tv}) where Tv<:VTypes d = Dense(ccall((:cholmod_l_copy_dense, :libcholmod), Ptr{C_Dense{Tv}}, (Ptr{C_Dense{Tv}}, Ptr{UInt8}), get(A.p), common())) @@ -428,7 +428,7 @@ function copy_dense{Tv<:VTypes}(A::Dense{Tv}) d end -function sort!{Tv<:VTypes}(S::Sparse{Tv}) +function sort!(S::Sparse{Tv}) where Tv<:VTypes @isok ccall((:cholmod_l_sort, :libcholmod), SuiteSparse_long, (Ptr{C_Sparse{Tv}}, Ptr{UInt8}), get(S.p), common()) @@ -436,7 +436,7 @@ function sort!{Tv<:VTypes}(S::Sparse{Tv}) end ### cholmod_matrixops.h ### -function norm_dense{Tv<:VTypes}(D::Dense{Tv}, p::Integer) +function norm_dense(D::Dense{Tv}, p::Integer) where Tv<:VTypes s = unsafe_load(get(D.p)) if p == 2 if s.ncol > 1 @@ -451,7 +451,7 @@ function norm_dense{Tv<:VTypes}(D::Dense{Tv}, p::Integer) end ### cholmod_check.h ### -function check_dense{T<:VTypes}(A::Dense{T}) +function check_dense(A::Dense{T}) where T<:VTypes ccall((:cholmod_l_check_dense, :libcholmod), Cint, (Ptr{C_Dense{T}}, Ptr{UInt8}), A.p, common())!=0 @@ -481,7 +481,7 @@ function allocate_sparse(nrow::Integer, ncol::Integer, nzmax::Integer, finalizer(s, free!) s end -function free_sparse!{Tv<:VTypes}(ptr::Ptr{C_Sparse{Tv}}) +function free_sparse!(ptr::Ptr{C_Sparse{Tv}}) where Tv<:VTypes @isok ccall((@cholmod_name("free_sparse", SuiteSparse_long), :libcholmod), Cint, (Ptr{Ptr{C_Sparse{Tv}}}, Ptr{UInt8}), &ptr, common()) @@ -493,14 +493,14 @@ function free_sparse!(ptr::Ptr{C_SparseVoid}) &ptr, common()) end -function free_factor!{Tv<:VTypes}(ptr::Ptr{C_Factor{Tv}}) +function free_factor!(ptr::Ptr{C_Factor{Tv}}) where Tv<:VTypes # Warning! Important that finalizer doesn't modify the global Common struct. @isok ccall((@cholmod_name("free_factor", SuiteSparse_long), :libcholmod), Cint, (Ptr{Ptr{C_Factor{Tv}}}, Ptr{Void}), &ptr, common()) end -function aat{Tv<:VRealTypes}(A::Sparse{Tv}, fset::Vector{SuiteSparse_long}, mode::Integer) +function aat(A::Sparse{Tv}, fset::Vector{SuiteSparse_long}, mode::Integer) where Tv<:VRealTypes s = Sparse(ccall((@cholmod_name("aat", SuiteSparse_long), :libcholmod), Ptr{C_Sparse{Tv}}, (Ptr{C_Sparse{Tv}}, Ptr{SuiteSparse_long}, Csize_t, Cint, Ptr{UInt8}), @@ -509,7 +509,7 @@ function aat{Tv<:VRealTypes}(A::Sparse{Tv}, fset::Vector{SuiteSparse_long}, mode s end -function sparse_to_dense{Tv<:VTypes}(A::Sparse{Tv}) +function sparse_to_dense(A::Sparse{Tv}) where Tv<:VTypes d = Dense(ccall((@cholmod_name("sparse_to_dense", SuiteSparse_long),:libcholmod), Ptr{C_Dense{Tv}}, (Ptr{C_Sparse{Tv}}, Ptr{UInt8}), @@ -517,7 +517,7 @@ function sparse_to_dense{Tv<:VTypes}(A::Sparse{Tv}) finalizer(d, free!) d end -function dense_to_sparse{Tv<:VTypes}(D::Dense{Tv}, ::Type{SuiteSparse_long}) +function dense_to_sparse(D::Dense{Tv}, ::Type{SuiteSparse_long}) where Tv<:VTypes s = Sparse(ccall((@cholmod_name("dense_to_sparse", SuiteSparse_long),:libcholmod), Ptr{C_Sparse{Tv}}, (Ptr{C_Dense{Tv}}, Cint, Ptr{UInt8}), @@ -526,7 +526,7 @@ function dense_to_sparse{Tv<:VTypes}(D::Dense{Tv}, ::Type{SuiteSparse_long}) s end -function factor_to_sparse!{Tv<:VTypes}(F::Factor{Tv}) +function factor_to_sparse!(F::Factor{Tv}) where Tv<:VTypes ss = unsafe_load(F.p) ss.xtype > PATTERN || throw(CHOLMODException("only numeric factors are supported")) s = Sparse(ccall((@cholmod_name("factor_to_sparse", SuiteSparse_long),:libcholmod), @@ -537,29 +537,29 @@ function factor_to_sparse!{Tv<:VTypes}(F::Factor{Tv}) s end -function change_factor!{Tv<:VTypes}(::Type{Float64}, to_ll::Bool, - to_super::Bool, to_packed::Bool, to_monotonic::Bool, F::Factor{Tv}) +function change_factor!(::Type{Float64}, to_ll::Bool, + to_super::Bool, to_packed::Bool, to_monotonic::Bool, F::Factor{Tv}) where Tv<:VTypes @isok ccall((@cholmod_name("change_factor", SuiteSparse_long),:libcholmod), Cint, (Cint, Cint, Cint, Cint, Cint, Ptr{C_Factor{Tv}}, Ptr{UInt8}), REAL, to_ll, to_super, to_packed, to_monotonic, get(F.p), common()) Factor{Float64}(F.p) end -function change_factor!{Tv<:VTypes}(::Type{Complex{Float64}}, to_ll::Bool, - to_super::Bool, to_packed::Bool, to_monotonic::Bool, F::Factor{Tv}) +function change_factor!(::Type{Complex{Float64}}, to_ll::Bool, + to_super::Bool, to_packed::Bool, to_monotonic::Bool, F::Factor{Tv}) where Tv<:VTypes @isok ccall((@cholmod_name("change_factor", SuiteSparse_long),:libcholmod), Cint, (Cint, Cint, Cint, Cint, Cint, Ptr{C_Factor{Tv}}, Ptr{UInt8}), COMPLEX, to_ll, to_super, to_packed, to_monotonic, get(F.p), common()) Factor{Complex{Float64}}(F.p) end -function check_sparse{Tv<:VTypes}(A::Sparse{Tv}) +function check_sparse(A::Sparse{Tv}) where Tv<:VTypes ccall((@cholmod_name("check_sparse", SuiteSparse_long),:libcholmod), Cint, (Ptr{C_Sparse{Tv}}, Ptr{UInt8}), get(A.p), common())!=0 end -function check_factor{Tv<:VTypes}(F::Factor{Tv}) +function check_factor(F::Factor{Tv}) where Tv<:VTypes ccall((@cholmod_name("check_factor", SuiteSparse_long),:libcholmod), Cint, (Ptr{C_Factor{Tv}}, Ptr{UInt8}), get(F.p), common())!=0 @@ -580,7 +580,7 @@ function speye(m::Integer, n::Integer, ::Type{Tv}) where Tv<:VTypes s end -function spzeros{Tv<:VTypes}(m::Integer, n::Integer, nzmax::Integer, ::Type{Tv}) +function spzeros(m::Integer, n::Integer, nzmax::Integer, ::Type{Tv}) where Tv<:VTypes s = Sparse(ccall((@cholmod_name("spzeros", SuiteSparse_long), :libcholmod), Ptr{C_Sparse{Tv}}, (Csize_t, Csize_t, Csize_t, Cint, Ptr{UInt8}), @@ -589,7 +589,7 @@ function spzeros{Tv<:VTypes}(m::Integer, n::Integer, nzmax::Integer, ::Type{Tv}) s end -function transpose_{Tv<:VTypes}(A::Sparse{Tv}, values::Integer) +function transpose_(A::Sparse{Tv}, values::Integer) where Tv<:VTypes s = Sparse(ccall((@cholmod_name("transpose", SuiteSparse_long),:libcholmod), Ptr{C_Sparse{Tv}}, (Ptr{C_Sparse{Tv}}, Cint, Ptr{UInt8}), @@ -598,7 +598,7 @@ function transpose_{Tv<:VTypes}(A::Sparse{Tv}, values::Integer) s end -function copy_factor{Tv<:VTypes}(F::Factor{Tv}) +function copy_factor(F::Factor{Tv}) where Tv<:VTypes f = Factor(ccall((@cholmod_name("copy_factor", SuiteSparse_long),:libcholmod), Ptr{C_Factor{Tv}}, (Ptr{C_Factor{Tv}}, Ptr{UInt8}), @@ -606,7 +606,7 @@ function copy_factor{Tv<:VTypes}(F::Factor{Tv}) finalizer(f, free!) f end -function copy_sparse{Tv<:VTypes}(A::Sparse{Tv}) +function copy_sparse(A::Sparse{Tv}) where Tv<:VTypes s = Sparse(ccall((@cholmod_name("copy_sparse", SuiteSparse_long),:libcholmod), Ptr{C_Sparse{Tv}}, (Ptr{C_Sparse{Tv}}, Ptr{UInt8}), @@ -614,7 +614,7 @@ function copy_sparse{Tv<:VTypes}(A::Sparse{Tv}) finalizer(s, free!) s end -function copy{Tv<:VRealTypes}(A::Sparse{Tv}, stype::Integer, mode::Integer) +function copy(A::Sparse{Tv}, stype::Integer, mode::Integer) where Tv<:VRealTypes s = Sparse(ccall((@cholmod_name("copy", SuiteSparse_long),:libcholmod), Ptr{C_Sparse{Tv}}, (Ptr{C_Sparse{Tv}}, Cint, Cint, Ptr{UInt8}), @@ -624,7 +624,7 @@ function copy{Tv<:VRealTypes}(A::Sparse{Tv}, stype::Integer, mode::Integer) end ### cholmod_check.h ### -function print_sparse{Tv<:VTypes}(A::Sparse{Tv}, name::String) +function print_sparse(A::Sparse{Tv}, name::String) where Tv<:VTypes isascii(name) || error("non-ASCII name: $name") cm = common() set_print_level(cm, 3) @@ -633,7 +633,7 @@ function print_sparse{Tv<:VTypes}(A::Sparse{Tv}, name::String) get(A.p), name, cm) nothing end -function print_factor{Tv<:VTypes}(F::Factor{Tv}, name::String) +function print_factor(F::Factor{Tv}, name::String) where Tv<:VTypes cm = common() set_print_level(cm, 3) @isok ccall((@cholmod_name("print_factor", SuiteSparse_long),:libcholmod), Cint, @@ -643,8 +643,8 @@ function print_factor{Tv<:VTypes}(F::Factor{Tv}, name::String) end ### cholmod_matrixops.h ### -function ssmult{Tv<:VRealTypes}(A::Sparse{Tv}, B::Sparse{Tv}, stype::Integer, - values::Bool, sorted::Bool) +function ssmult(A::Sparse{Tv}, B::Sparse{Tv}, stype::Integer, + values::Bool, sorted::Bool) where Tv<:VRealTypes lA = unsafe_load(get(A.p)) lB = unsafe_load(get(B.p)) if lA.ncol != lB.nrow @@ -660,7 +660,7 @@ function ssmult{Tv<:VRealTypes}(A::Sparse{Tv}, B::Sparse{Tv}, stype::Integer, s end -function norm_sparse{Tv<:VTypes}(A::Sparse{Tv}, norm::Integer) +function norm_sparse(A::Sparse{Tv}, norm::Integer) where Tv<:VTypes if norm != 0 && norm != 1 throw(ArgumentError("norm argument must be either 0 or 1")) end @@ -678,7 +678,7 @@ function horzcat(A::Sparse{Tv}, B::Sparse{Tv}, values::Bool) where Tv<:VRealType s end -function scale!{Tv<:VRealTypes}(S::Dense{Tv}, scale::Integer, A::Sparse{Tv}) +function scale!(S::Dense{Tv}, scale::Integer, A::Sparse{Tv}) where Tv<:VRealTypes sS = unsafe_load(get(S.p)) sA = unsafe_load(get(A.p)) if sS.ncol != 1 && sS.nrow != 1 @@ -708,8 +708,8 @@ function scale!{Tv<:VRealTypes}(S::Dense{Tv}, scale::Integer, A::Sparse{Tv}) A end -function sdmult!{Tv<:VTypes}(A::Sparse{Tv}, transpose::Bool, - α::Number, β::Number, X::Dense{Tv}, Y::Dense{Tv}) +function sdmult!(A::Sparse{Tv}, transpose::Bool, + α::Number, β::Number, X::Dense{Tv}, Y::Dense{Tv}) where Tv<:VTypes m, n = size(A) nc = transpose ? m : n nr = transpose ? n : m @@ -733,7 +733,7 @@ function vertcat(A::Sparse{Tv}, B::Sparse{Tv}, values::Bool) where Tv<:VRealType s end -function symmetry{Tv<:VTypes}(A::Sparse{Tv}, option::Integer) +function symmetry(A::Sparse{Tv}, option::Integer) where Tv<:VTypes xmatched = Ref{SuiteSparse_long}() pmatched = Ref{SuiteSparse_long}() nzoffdiag = Ref{SuiteSparse_long}() @@ -768,13 +768,13 @@ function analyze_p{Tv<:VTypes}(A::Sparse{Tv}, perm::Vector{SuiteSparse_long}, finalizer(f, free!) f end -function factorize!{Tv<:VTypes}(A::Sparse{Tv}, F::Factor{Tv}, cmmn::Vector{UInt8}) +function factorize!(A::Sparse{Tv}, F::Factor{Tv}, cmmn::Vector{UInt8}) where Tv<:VTypes @isok ccall((@cholmod_name("factorize", SuiteSparse_long),:libcholmod), Cint, (Ptr{C_Sparse{Tv}}, Ptr{C_Factor{Tv}}, Ptr{UInt8}), get(A.p), get(F.p), cmmn) F end -function factorize_p!{Tv<:VTypes}(A::Sparse{Tv}, β::Real, F::Factor{Tv}, cmmn::Vector{UInt8}) +function factorize_p!(A::Sparse{Tv}, β::Real, F::Factor{Tv}, cmmn::Vector{UInt8}) where Tv<:VTypes # note that β is passed as a complex number (double beta[2]), # but the CHOLMOD manual says that only beta[0] (real part) is used @isok ccall((@cholmod_name("factorize_p", SuiteSparse_long),:libcholmod), Cint, @@ -784,7 +784,7 @@ function factorize_p!{Tv<:VTypes}(A::Sparse{Tv}, β::Real, F::Factor{Tv}, cmmn:: F end -function solve{Tv<:VTypes}(sys::Integer, F::Factor{Tv}, B::Dense{Tv}) +function solve(sys::Integer, F::Factor{Tv}, B::Dense{Tv}) where Tv<:VTypes if size(F,1) != size(B,1) throw(DimensionMismatch("LHS and RHS should have the same number of rows. " * "LHS has $(size(F,1)) rows, but RHS has $(size(B,1)) rows.")) @@ -796,7 +796,7 @@ function solve{Tv<:VTypes}(sys::Integer, F::Factor{Tv}, B::Dense{Tv}) d end -function spsolve{Tv<:VTypes}(sys::Integer, F::Factor{Tv}, B::Sparse{Tv}) +function spsolve(sys::Integer, F::Factor{Tv}, B::Sparse{Tv}) where Tv<:VTypes if size(F,1) != size(B,1) throw(DimensionMismatch("LHS and RHS should have the same number of rows. " * "LHS has $(size(F,1)) rows, but RHS has $(size(B,1)) rows.")) @@ -959,11 +959,11 @@ function convert{Ti<:ITypes}(::Type{Sparse}, args...) throw(MethodError(convert, (Sparse, A))) end -function convert{T,Ti<:ITypes}(::Type{Sparse}, +function convert(::Type{Sparse}, A::Union{SparseMatrixCSC{T,Ti}, Symmetric{T,SparseMatrixCSC{T,Ti}}, Hermitian{T,SparseMatrixCSC{T,Ti}}}, - args...) + args...) where T where Ti<:ITypes return Sparse(convert(AbstractMatrix{promote_type(Float64, T)}, A), args...) end @@ -1029,9 +1029,9 @@ function convert(::Type{Matrix{T}}, D::Dense{T}) where T end Base.copy!(dest::Base.PermutedDimsArrays.PermutedDimsArray, src::Dense) = _copy!(dest, src) # ambig -Base.copy!{T<:VTypes}(dest::Dense{T}, D::Dense{T}) = _copy!(dest, D) -Base.copy!{T<:VTypes}(dest::AbstractArray{T}, D::Dense{T}) = _copy!(dest, D) -Base.copy!{T<:VTypes}(dest::AbstractArray{T,2}, D::Dense{T}) = _copy!(dest, D) +Base.copy!(dest::Dense{T}, D::Dense{T}) where {T<:VTypes} = _copy!(dest, D) +Base.copy!(dest::AbstractArray{T}, D::Dense{T}) where {T<:VTypes} = _copy!(dest, D) +Base.copy!(dest::AbstractArray{T,2}, D::Dense{T}) where {T<:VTypes} = _copy!(dest, D) Base.copy!(dest::AbstractArray, D::Dense) = _copy!(dest, D) function _copy!(dest::AbstractArray, D::Dense) @@ -1138,7 +1138,7 @@ function sparse(F::Factor) SparseArrays.sortSparseMatrixCSC!(A) p = get_perm(F) if p != [1:s.n;] - pinv = Array{Int}(length(p)) + pinv = Vector{Int}(length(p)) for k = 1:length(p) pinv[p[k]] = k end @@ -1149,7 +1149,7 @@ end sparse(D::Dense) = sparse(Sparse(D)) -function sparse{Tv}(FC::FactorComponent{Tv,:L}) +function sparse(FC::FactorComponent{Tv,:L}) where Tv F = Factor(FC) s = unsafe_load(F.p) if s.is_ll == 0 @@ -1157,7 +1157,7 @@ function sparse{Tv}(FC::FactorComponent{Tv,:L}) end sparse(Sparse(F)) end -sparse{Tv}(FC::FactorComponent{Tv,:LD}) = sparse(Sparse(Factor(FC))) +sparse(FC::FactorComponent{Tv,:LD}) where {Tv} = sparse(Sparse(Factor(FC))) # Calculate the offset into the stype field of the cholmod_sparse_struct and # change the value @@ -1230,15 +1230,15 @@ IndexStyle(::Dense) = IndexLinear() size(FC::FactorComponent, i::Integer) = size(FC.F, i) size(FC::FactorComponent) = size(FC.F) -ctranspose{Tv}(FC::FactorComponent{Tv,:L}) = FactorComponent{Tv,:U}(FC.F) -ctranspose{Tv}(FC::FactorComponent{Tv,:U}) = FactorComponent{Tv,:L}(FC.F) -ctranspose{Tv}(FC::FactorComponent{Tv,:PtL}) = FactorComponent{Tv,:UP}(FC.F) -ctranspose{Tv}(FC::FactorComponent{Tv,:UP}) = FactorComponent{Tv,:PtL}(FC.F) -ctranspose{Tv}(FC::FactorComponent{Tv,:D}) = FC -ctranspose{Tv}(FC::FactorComponent{Tv,:LD}) = FactorComponent{Tv,:DU}(FC.F) -ctranspose{Tv}(FC::FactorComponent{Tv,:DU}) = FactorComponent{Tv,:LD}(FC.F) -ctranspose{Tv}(FC::FactorComponent{Tv,:PtLD}) = FactorComponent{Tv,:DUP}(FC.F) -ctranspose{Tv}(FC::FactorComponent{Tv,:DUP}) = FactorComponent{Tv,:PtLD}(FC.F) +ctranspose(FC::FactorComponent{Tv,:L}) where {Tv} = FactorComponent{Tv,:U}(FC.F) +ctranspose(FC::FactorComponent{Tv,:U}) where {Tv} = FactorComponent{Tv,:L}(FC.F) +ctranspose(FC::FactorComponent{Tv,:PtL}) where {Tv} = FactorComponent{Tv,:UP}(FC.F) +ctranspose(FC::FactorComponent{Tv,:UP}) where {Tv} = FactorComponent{Tv,:PtL}(FC.F) +ctranspose(FC::FactorComponent{Tv,:D}) where {Tv} = FC +ctranspose(FC::FactorComponent{Tv,:LD}) where {Tv} = FactorComponent{Tv,:DU}(FC.F) +ctranspose(FC::FactorComponent{Tv,:DU}) where {Tv} = FactorComponent{Tv,:LD}(FC.F) +ctranspose(FC::FactorComponent{Tv,:PtLD}) where {Tv} = FactorComponent{Tv,:DUP}(FC.F) +ctranspose(FC::FactorComponent{Tv,:DUP}) where {Tv} = FactorComponent{Tv,:PtLD}(FC.F) function getindex(A::Dense, i::Integer) s = unsafe_load(get(A.p)) @@ -1267,7 +1267,7 @@ function getindex(F::Factor, sym::Symbol) end function getLd!(S::SparseMatrixCSC) - d = Array{eltype(S)}(size(S, 1)) + d = Vector{eltype(S)}(size(S, 1)) fill!(d, 0) col = 1 for k = 1:nnz(S) @@ -1347,7 +1347,7 @@ function fact_(A::Sparse{<:VTypes}, cm::Array{UInt8}; return F end -function cholfact!{Tv}(F::Factor{Tv}, A::Sparse{Tv}; shift::Real=0.0) +function cholfact!(F::Factor{Tv}, A::Sparse{Tv}; shift::Real=0.0) where Tv cm = common() # Makes it an LLt @@ -1377,12 +1377,12 @@ See also [`cholfact`](@ref). be converted to `SparseMatrixCSC{Float64}` or `SparseMatrixCSC{Complex128}` as appropriate. """ -cholfact!{T<:Real}(F::Factor, A::Union{SparseMatrixCSC{T}, +cholfact!(F::Factor, A::Union{SparseMatrixCSC{T}, SparseMatrixCSC{Complex{T}}, Symmetric{T,SparseMatrixCSC{T,SuiteSparse_long}}, Hermitian{Complex{T},SparseMatrixCSC{Complex{T},SuiteSparse_long}}, Hermitian{T,SparseMatrixCSC{T,SuiteSparse_long}}}; - shift = 0.0) = + shift = 0.0) where {T<:Real} = cholfact!(F, Sparse(A); shift = shift) function cholfact(A::Sparse; shift::Real=0.0, @@ -1435,14 +1435,14 @@ it should be a permutation of `1:size(A,1)` giving the ordering to use Many other functions from CHOLMOD are wrapped but not exported from the `Base.SparseArrays.CHOLMOD` module. """ -cholfact{T<:Real}(A::Union{SparseMatrixCSC{T}, SparseMatrixCSC{Complex{T}}, +cholfact(A::Union{SparseMatrixCSC{T}, SparseMatrixCSC{Complex{T}}, Symmetric{T,SparseMatrixCSC{T,SuiteSparse_long}}, Hermitian{Complex{T},SparseMatrixCSC{Complex{T},SuiteSparse_long}}, Hermitian{T,SparseMatrixCSC{T,SuiteSparse_long}}}; - kws...) = cholfact(Sparse(A); kws...) + kws...) where {T<:Real} = cholfact(Sparse(A); kws...) -function ldltfact!{Tv}(F::Factor{Tv}, A::Sparse{Tv}; shift::Real=0.0) +function ldltfact!(F::Factor{Tv}, A::Sparse{Tv}; shift::Real=0.0) where Tv cm = common() # Compute the numerical factorization @@ -1469,12 +1469,12 @@ See also [`ldltfact`](@ref). be converted to `SparseMatrixCSC{Float64}` or `SparseMatrixCSC{Complex128}` as appropriate. """ -ldltfact!{T<:Real}(F::Factor, A::Union{SparseMatrixCSC{T}, +ldltfact!(F::Factor, A::Union{SparseMatrixCSC{T}, SparseMatrixCSC{Complex{T}}, Symmetric{T,SparseMatrixCSC{T,SuiteSparse_long}}, Hermitian{Complex{T},SparseMatrixCSC{Complex{T},SuiteSparse_long}}, Hermitian{T,SparseMatrixCSC{T,SuiteSparse_long}}}; - shift = 0.0) = + shift = 0.0) where {T<:Real} = ldltfact!(F, Sparse(A), shift = shift) function ldltfact(A::Sparse; shift::Real=0.0, @@ -1535,11 +1535,11 @@ it should be a permutation of `1:size(A,1)` giving the ordering to use Many other functions from CHOLMOD are wrapped but not exported from the `Base.SparseArrays.CHOLMOD` module. """ -ldltfact{T<:Real}(A::Union{SparseMatrixCSC{T},SparseMatrixCSC{Complex{T}}, +ldltfact(A::Union{SparseMatrixCSC{T},SparseMatrixCSC{Complex{T}}, Symmetric{T,SparseMatrixCSC{T,SuiteSparse_long}}, Hermitian{Complex{T},SparseMatrixCSC{Complex{T},SuiteSparse_long}}, Hermitian{T,SparseMatrixCSC{T,SuiteSparse_long}}}; - kws...) = ldltfact(Sparse(A); kws...) + kws...) where {T<:Real} = ldltfact(Sparse(A); kws...) ## Solvers @@ -1600,10 +1600,10 @@ Ac_ldiv_B(L::FactorComponent, B::RowVector) = ctranspose(L)\B # ambiguity (\){T<:VTypes}(L::Factor{T}, B::Dense{T}) = solve(CHOLMOD_A, L, B) # Explicit typevars are necessary to avoid ambiguities with defs in linalg/factorizations.jl # Likewise the two following explicit Vector and Matrix defs (rather than a single VecOrMat) -(\){T<:Float64}(L::Factor{T}, B::Vector{Complex{T}}) = complex.(L\real(B), L\imag(B)) -(\){T<:Float64}(L::Factor{T}, B::Matrix{Complex{T}}) = complex.(L\real(B), L\imag(B)) -(\){T<:VTypes}(L::Factor{T}, b::StridedVector) = Vector(L\convert(Dense{T}, b)) -(\){T<:VTypes}(L::Factor{T}, B::StridedMatrix) = Matrix(L\convert(Dense{T}, B)) +(\)(L::Factor{T}, B::Vector{Complex{T}}) where {T<:Float64} = complex.(L\real(B), L\imag(B)) +(\)(L::Factor{T}, B::Matrix{Complex{T}}) where {T<:Float64} = complex.(L\real(B), L\imag(B)) +(\)(L::Factor{T}, b::StridedVector) where {T<:VTypes} = Vector(L\convert(Dense{T}, b)) +(\)(L::Factor{T}, B::StridedMatrix) where {T<:VTypes} = Matrix(L\convert(Dense{T}, B)) (\)(L::Factor, B::Sparse) = spsolve(CHOLMOD_A, L, B) # When right hand side is sparse, we have to ensure that the rhs is not marked as symmetric. (\)(L::Factor, B::SparseVecOrMat) = sparse(spsolve(CHOLMOD_A, L, Sparse(B, 0))) @@ -1627,7 +1627,7 @@ for f in (:\, :Ac_ldiv_B) end ## Other convenience methods -function diag{Tv}(F::Factor{Tv}) +function diag(F::Factor{Tv}) where Tv f = unsafe_load(get(F.p)) fsuper = f.super fpi = f.pi @@ -1659,7 +1659,7 @@ function diag{Tv}(F::Factor{Tv}) res end -function logdet{Tv<:VTypes}(F::Factor{Tv}) +function logdet(F::Factor{Tv}) where Tv<:VTypes f = unsafe_load(get(F.p)) res = zero(Tv) for d in diag(F); res += log(abs(d)) end @@ -1708,18 +1708,18 @@ function ishermitian(A::Sparse{Complex{Float64}}) end end -(*){Ti}(A::Symmetric{Float64,SparseMatrixCSC{Float64,Ti}}, - B::SparseVecOrMat{Float64,Ti}) = sparse(Sparse(A)*Sparse(B)) -(*){Ti}(A::Hermitian{Complex{Float64},SparseMatrixCSC{Complex{Float64},Ti}}, - B::SparseVecOrMat{Complex{Float64},Ti}) = sparse(Sparse(A)*Sparse(B)) -(*){Ti}(A::Hermitian{Float64,SparseMatrixCSC{Float64,Ti}}, - B::SparseVecOrMat{Float64,Ti}) = sparse(Sparse(A)*Sparse(B)) +(*)(A::Symmetric{Float64,SparseMatrixCSC{Float64,Ti}}, + B::SparseVecOrMat{Float64,Ti}) where {Ti} = sparse(Sparse(A)*Sparse(B)) +(*)(A::Hermitian{Complex{Float64},SparseMatrixCSC{Complex{Float64},Ti}}, + B::SparseVecOrMat{Complex{Float64},Ti}) where {Ti} = sparse(Sparse(A)*Sparse(B)) +(*)(A::Hermitian{Float64,SparseMatrixCSC{Float64,Ti}}, + B::SparseVecOrMat{Float64,Ti}) where {Ti} = sparse(Sparse(A)*Sparse(B)) -(*){Ti}(A::SparseVecOrMat{Float64,Ti}, - B::Symmetric{Float64,SparseMatrixCSC{Float64,Ti}}) = sparse(Sparse(A)*Sparse(B)) -(*){Ti}(A::SparseVecOrMat{Complex{Float64},Ti}, - B::Hermitian{Complex{Float64},SparseMatrixCSC{Complex{Float64},Ti}}) = sparse(Sparse(A)*Sparse(B)) -(*){Ti}(A::SparseVecOrMat{Float64,Ti}, - B::Hermitian{Float64,SparseMatrixCSC{Float64,Ti}}) = sparse(Sparse(A)*Sparse(B)) +(*)(A::SparseVecOrMat{Float64,Ti}, + B::Symmetric{Float64,SparseMatrixCSC{Float64,Ti}}) where {Ti} = sparse(Sparse(A)*Sparse(B)) +(*)(A::SparseVecOrMat{Complex{Float64},Ti}, + B::Hermitian{Complex{Float64},SparseMatrixCSC{Complex{Float64},Ti}}) where {Ti} = sparse(Sparse(A)*Sparse(B)) +(*)(A::SparseVecOrMat{Float64,Ti}, + B::Hermitian{Float64,SparseMatrixCSC{Float64,Ti}}) where {Ti} = sparse(Sparse(A)*Sparse(B)) end #module diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl index 34a554a854285..bb75c38414ee5 100644 --- a/base/sparse/sparsematrix.jl +++ b/base/sparse/sparsematrix.jl @@ -216,7 +216,7 @@ function reinterpret(::Type{T}, a::SparseMatrixCSC{Tv,Ti}, dims::NTuple{N,Int}) mS,nS = dims mA,nA = size(a) numnz = nnz(a) - colptr = Array{Ti}(nS+1) + colptr = Vector{Ti}(nS+1) rowval = similar(a.rowval) nzval = reinterpret(T, a.nzval) @@ -299,7 +299,7 @@ function similar(S::SparseMatrixCSC, ::Type{Tv}, ::Type{Ti}) where {Tv,Ti} new_nzval = copy!(similar(S.nzval, Tv), S.nzval) SparseMatrixCSC(S.m, S.n, new_colptr, new_rowval, new_nzval) end -@inline similar{Tv}(S::SparseMatrixCSC, ::Type{Tv}, d::Dims) = spzeros(Tv, d...) +@inline similar(S::SparseMatrixCSC, ::Type{Tv}, d::Dims) where {Tv} = spzeros(Tv, d...) # convert'ing between SparseMatrixCSC types convert(::Type{AbstractMatrix{Tv}}, A::SparseMatrixCSC{Tv}) where {Tv} = A @@ -389,7 +389,7 @@ julia> sparse(A) [3, 3] = 1.0 ``` """ -sparse{Tv}(A::AbstractMatrix{Tv}) = convert(SparseMatrixCSC{Tv,Int}, A) +sparse(A::AbstractMatrix{Tv}) where {Tv} = convert(SparseMatrixCSC{Tv,Int}, A) sparse(S::SparseMatrixCSC) = copy(S) @@ -397,10 +397,9 @@ sparse_IJ_sorted!(I,J,V,m,n) = sparse_IJ_sorted!(I,J,V,m,n,+) sparse_IJ_sorted!(I,J,V::AbstractVector{Bool},m,n) = sparse_IJ_sorted!(I,J,V,m,n,|) -function sparse_IJ_sorted!{Ti<:Integer}(I::AbstractVector{Ti}, J::AbstractVector{Ti}, - V::AbstractVector, - m::Integer, n::Integer, combine::Function) - +function sparse_IJ_sorted!(I::AbstractVector{Ti}, J::AbstractVector{Ti}, + V::AbstractVector, + m::Integer, n::Integer, combine::Function) where Ti<:Integer m = m < 0 ? 0 : m n = n < 0 ? 0 : n if isempty(V); return spzeros(eltype(V),Ti,m,n); end @@ -470,7 +469,7 @@ julia> sparse(Is, Js, Vs) [3, 3] = 3 ``` """ -function sparse{Tv,Ti<:Integer}(I::AbstractVector{Ti}, J::AbstractVector{Ti}, V::AbstractVector{Tv}, m::Integer, n::Integer, combine) +function sparse(I::AbstractVector{Ti}, J::AbstractVector{Ti}, V::AbstractVector{Tv}, m::Integer, n::Integer, combine) where {Tv,Ti<:Integer} coolen = length(I) if length(J) != coolen || length(V) != coolen throw(ArgumentError(string("the first three arguments' lengths must match, ", @@ -504,7 +503,7 @@ function sparse{Tv,Ti<:Integer}(I::AbstractVector{Ti}, J::AbstractVector{Ti}, V: sparse!(I, J, V, m, n, combine, klasttouch, csrrowptr, csrcolval, csrnzval, - csccolptr, cscrowval, cscnzval ) + csccolptr, cscrowval, cscnzval) end end @@ -560,10 +559,10 @@ F. Gustavson, "Two fast algorithms for sparse matrices: multiplication and permu transposition," ACM TOMS 4(3), 250-269 (1978) inspired this method's use of a pair of counting sorts. """ -function sparse!{Tv,Ti<:Integer}(I::AbstractVector{Ti}, J::AbstractVector{Ti}, +function sparse!(I::AbstractVector{Ti}, J::AbstractVector{Ti}, V::AbstractVector{Tv}, m::Integer, n::Integer, combine, klasttouch::Vector{Ti}, csrrowptr::Vector{Ti}, csrcolval::Vector{Ti}, csrnzval::Vector{Tv}, - csccolptr::Vector{Ti}, cscrowval::Vector{Ti}, cscnzval::Vector{Tv} ) + csccolptr::Vector{Ti}, cscrowval::Vector{Ti}, cscnzval::Vector{Tv}) where {Tv,Ti<:Integer} # Compute the CSR form's row counts and store them shifted forward by one in csrrowptr fill!(csrrowptr, 0) @@ -662,20 +661,20 @@ function sparse!{Tv,Ti<:Integer}(I::AbstractVector{Ti}, J::AbstractVector{Ti}, SparseMatrixCSC(m, n, csccolptr, cscrowval, cscnzval) end -function sparse!{Tv,Ti<:Integer}(I::AbstractVector{Ti}, J::AbstractVector{Ti}, +function sparse!(I::AbstractVector{Ti}, J::AbstractVector{Ti}, V::AbstractVector{Tv}, m::Integer, n::Integer, combine, klasttouch::Vector{Ti}, csrrowptr::Vector{Ti}, csrcolval::Vector{Ti}, csrnzval::Vector{Tv}, - csccolptr::Vector{Ti} ) + csccolptr::Vector{Ti}) where {Tv,Ti<:Integer} sparse!(I, J, V, m, n, combine, klasttouch, csrrowptr, csrcolval, csrnzval, - csccolptr, Vector{Ti}(), Vector{Tv}() ) + csccolptr, Vector{Ti}(), Vector{Tv}()) end -function sparse!{Tv,Ti<:Integer}(I::AbstractVector{Ti}, J::AbstractVector{Ti}, +function sparse!(I::AbstractVector{Ti}, J::AbstractVector{Ti}, V::AbstractVector{Tv}, m::Integer, n::Integer, combine, klasttouch::Vector{Ti}, - csrrowptr::Vector{Ti}, csrcolval::Vector{Ti}, csrnzval::Vector{Tv} ) + csrrowptr::Vector{Ti}, csrcolval::Vector{Ti}, csrnzval::Vector{Tv}) where {Tv,Ti<:Integer} sparse!(I, J, V, m, n, combine, klasttouch, csrrowptr, csrcolval, csrnzval, - Vector{Ti}(n+1), Vector{Ti}(), Vector{Tv}() ) + Vector{Ti}(n+1), Vector{Ti}(), Vector{Tv}()) end dimlub(I) = isempty(I) ? 0 : Int(maximum(I)) #least upper bound on required sparse matrix dimension @@ -731,8 +730,8 @@ algorithms for sparse matrices: multiplication and permuted transposition," ACM 250-269 (1978). The algorithm runs in `O(A.m, A.n, nnz(A))` time and requires no space beyond that passed in. """ -function halfperm!{Tv,Ti}(X::SparseMatrixCSC{Tv,Ti}, A::SparseMatrixCSC{Tv,Ti}, - q::AbstractVector{<:Integer}, f::Function = identity) +function halfperm!(X::SparseMatrixCSC{Tv,Ti}, A::SparseMatrixCSC{Tv,Ti}, + q::AbstractVector{<:Integer}, f::Function = identity) where {Tv,Ti} _computecolptrs_halfperm!(X, A) _distributevals_halfperm!(X, A, q, f) return X @@ -741,7 +740,7 @@ end Helper method for `halfperm!`. Computes `transpose(A[:,q])`'s column pointers, storing them shifted one position forward in `X.colptr`; `_distributevals_halfperm!` fixes this shift. """ -function _computecolptrs_halfperm!{Tv,Ti}(X::SparseMatrixCSC{Tv,Ti}, A::SparseMatrixCSC{Tv,Ti}) +function _computecolptrs_halfperm!(X::SparseMatrixCSC{Tv,Ti}, A::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} # Compute `transpose(A[:,q])`'s column counts. Store shifted forward one position in X.colptr. fill!(X.colptr, 0) @inbounds for k in 1:nnz(A) @@ -762,8 +761,8 @@ position forward in `X.colptr`, computes `map(f, transpose(A[:,q]))` by appropri distributing `A.rowval` and `f`-transformed `A.nzval` into `X.rowval` and `X.nzval` respectively. Simultaneously fixes the one-position-forward shift in `X.colptr`. """ -function _distributevals_halfperm!{Tv,Ti}(X::SparseMatrixCSC{Tv,Ti}, - A::SparseMatrixCSC{Tv,Ti}, q::AbstractVector{<:Integer}, f::Function) +function _distributevals_halfperm!(X::SparseMatrixCSC{Tv,Ti}, + A::SparseMatrixCSC{Tv,Ti}, q::AbstractVector{<:Integer}, f::Function) where {Tv,Ti} @inbounds for Xi in 1:A.n Aj = q[Xi] for Ak in nzrange(A, Aj) @@ -777,7 +776,7 @@ function _distributevals_halfperm!{Tv,Ti}(X::SparseMatrixCSC{Tv,Ti}, return # kill potential type instability end -function ftranspose!{Tv,Ti}(X::SparseMatrixCSC{Tv,Ti}, A::SparseMatrixCSC{Tv,Ti}, f::Function) +function ftranspose!(X::SparseMatrixCSC{Tv,Ti}, A::SparseMatrixCSC{Tv,Ti}, f::Function) where {Tv,Ti} # Check compatibility of source argument A and destination argument X if X.n != A.m throw(DimensionMismatch(string("destination argument `X`'s column count, ", @@ -796,10 +795,10 @@ function ftranspose!{Tv,Ti}(X::SparseMatrixCSC{Tv,Ti}, A::SparseMatrixCSC{Tv,Ti} end halfperm!(X, A, 1:A.n, f) end -transpose!{Tv,Ti}(X::SparseMatrixCSC{Tv,Ti}, A::SparseMatrixCSC{Tv,Ti}) = ftranspose!(X, A, identity) -ctranspose!{Tv,Ti}(X::SparseMatrixCSC{Tv,Ti}, A::SparseMatrixCSC{Tv,Ti}) = ftranspose!(X, A, conj) +transpose!(X::SparseMatrixCSC{Tv,Ti}, A::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} = ftranspose!(X, A, identity) +ctranspose!(X::SparseMatrixCSC{Tv,Ti}, A::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} = ftranspose!(X, A, conj) -function ftranspose{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, f::Function) +function ftranspose(A::SparseMatrixCSC{Tv,Ti}, f::Function) where {Tv,Ti} X = SparseMatrixCSC(A.n, A.m, Vector{Ti}(A.m+1), Vector{Ti}(nnz(A)), Vector{Tv}(nnz(A))) halfperm!(X, A, 1:A.n, f) end @@ -921,8 +920,8 @@ end Helper method for `permute` and `permute!` methods operating on `SparseMatrixCSC`s. Checks compatibility of source argument `A` and destination argument `X`. """ -function _checkargs_sourcecompatdest_permute!{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, - X::SparseMatrixCSC{Tv,Ti}) +function _checkargs_sourcecompatdest_permute!(A::SparseMatrixCSC{Tv,Ti}, + X::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} if X.m != A.m throw(DimensionMismatch(string("destination argument `X`'s row count, ", "`X.m (= $(X.m))`, must match source argument `A`'s row count, `A.m (= $(A.m))`"))) @@ -943,8 +942,8 @@ end Helper method for `permute` and `permute!` methods operating on `SparseMatrixCSC`s. Checks compatibility of source argument `A` and intermediate result argument `C`. """ -function _checkargs_sourcecompatworkmat_permute!{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, - C::SparseMatrixCSC{Tv,Ti}) +function _checkargs_sourcecompatworkmat_permute!(A::SparseMatrixCSC{Tv,Ti}, + C::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} if C.n != A.m throw(DimensionMismatch(string("intermediate result argument `C`'s column count, ", "`C.n (= $(C.n))`, must match source argument `A`'s row count, `A.m (= $(A.m))`"))) @@ -965,8 +964,8 @@ end Helper method for `permute` and `permute!` methods operating on `SparseMatrixCSC`s. Checks compatibility of source argument `A` and workspace argument `workcolptr`. """ -function _checkargs_sourcecompatworkcolptr_permute!{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, - workcolptr::Vector{Ti}) +function _checkargs_sourcecompatworkcolptr_permute!(A::SparseMatrixCSC{Tv,Ti}, + workcolptr::Vector{Ti}) where {Tv,Ti} if length(workcolptr) <= A.n throw(DimensionMismatch(string("argument `workcolptr`'s length, ", "`length(workcolptr) (= $(length(workcolptr)))`, must exceed source argument ", @@ -1165,8 +1164,8 @@ end function findn{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}) numnz = nnz(S) - I = Array{Ti}(numnz) - J = Array{Ti}(numnz) + I = Vector{Ti}(numnz) + J = Vector{Ti}(numnz) count = 1 @inbounds for col = 1 : S.n, k = S.colptr[col] : (S.colptr[col+1]-1) @@ -1188,9 +1187,9 @@ end function findnz{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}) numnz = nnz(S) - I = Array{Ti}(numnz) - J = Array{Ti}(numnz) - V = Array{Tv}(numnz) + I = Vector{Ti}(numnz) + J = Vector{Ti}(numnz) + V = Vector{Tv}(numnz) count = 1 @inbounds for col = 1 : S.n, k = S.colptr[col] : (S.colptr[col+1]-1) @@ -1299,9 +1298,9 @@ truebools(r::AbstractRNG, n::Integer) = ones(Bool, n) sprand(m::Integer, n::Integer, density::AbstractFloat) = sprand(GLOBAL_RNG,m,n,density) sprand(r::AbstractRNG, m::Integer, n::Integer, density::AbstractFloat) = sprand(r,m,n,density,rand,Float64) -sprand{T}(r::AbstractRNG, ::Type{T}, m::Integer, n::Integer, density::AbstractFloat) = sprand(r,m,n,density,(r, i) -> rand(r, T, i), T) +sprand(r::AbstractRNG, ::Type{T}, m::Integer, n::Integer, density::AbstractFloat) where {T} = sprand(r,m,n,density,(r, i) -> rand(r, T, i), T) sprand(r::AbstractRNG, ::Type{Bool}, m::Integer, n::Integer, density::AbstractFloat) = sprand(r,m,n,density, truebools, Bool) -sprand{T}(::Type{T}, m::Integer, n::Integer, density::AbstractFloat) = sprand(GLOBAL_RNG, T, m, n, density) +sprand(::Type{T}, m::Integer, n::Integer, density::AbstractFloat) where {T} = sprand(GLOBAL_RNG, T, m, n, density) """ @@ -1350,7 +1349,7 @@ julia> spones(A) Note the difference from [`speye`](@ref). """ -spones{T}(S::SparseMatrixCSC{T}) = +spones(S::SparseMatrixCSC{T}) where {T} = SparseMatrixCSC(S.m, S.n, copy(S.colptr), copy(S.rowval), ones(T, S.colptr[end]-1)) """ @@ -1432,7 +1431,7 @@ speye_scaled(diag, m::Integer, n::Integer) = speye_scaled(typeof(diag), diag, m, function speye_scaled(T, diag, m::Integer, n::Integer) ((m < 0) || (n < 0)) && throw(ArgumentError("invalid array dimensions")) nnz = min(m,n) - colptr = Array{Int,1}(1+n) + colptr = Vector{Int}(1+n) colptr[1:nnz+1] = 1:nnz+1 colptr[nnz+2:end] = nnz+1 SparseMatrixCSC(Int(m), Int(n), colptr, Vector{Int}(1:nnz), fill!(Vector{T}(nnz), diag)) @@ -1450,10 +1449,10 @@ conj!(A::SparseMatrixCSC) = (@inbounds broadcast!(conj, A.nzval, A.nzval); A) (+)(A::SparseMatrixCSC, B::SparseMatrixCSC) = map(+, A, B) (-)(A::SparseMatrixCSC, B::SparseMatrixCSC) = map(-, A, B) -( +)(A::SparseMatrixCSC, B::Array ) = Array(A) + B -( +)(A::Array , B::SparseMatrixCSC) = A + Array(B) -( -)(A::SparseMatrixCSC, B::Array ) = Array(A) - B -( -)(A::Array , B::SparseMatrixCSC) = A - Array(B) +(+)(A::SparseMatrixCSC, B::Array) = Array(A) + B +(+)(A::Array, B::SparseMatrixCSC) = A + Array(B) +(-)(A::SparseMatrixCSC, B::Array) = Array(A) - B +(-)(A::Array, B::SparseMatrixCSC) = A - Array(B) ## full equality function ==(A1::SparseMatrixCSC, A2::SparseMatrixCSC) @@ -1716,7 +1715,7 @@ macro _findr(op, A, region, Tv, Ti) if $region == 1 || $region == (1,) (N == 0) && (return (fill(zval,1,n), fill(convert($Ti,1),1,n))) - S = Array{$Tv}(n); I = Array{$Ti}(n) + S = Vector{$Tv}(n); I = Vector{$Ti}(n) @inbounds for i = 1 : n Sc = zval; Ic = _findz($A, 1:m, i:i) if Ic == 0 @@ -1735,7 +1734,7 @@ macro _findr(op, A, region, Tv, Ti) return(reshape(S,1,n), reshape(I,1,n)) elseif $region == 2 || $region == (2,) (N == 0) && (return (fill(zval,m,1), fill(convert($Ti,1),m,1))) - S = Array{$Tv}(m); I = Array{$Ti}(m) + S = Vector{$Tv}(m); I = Vector{$Ti}(m) @inbounds for row in 1:m S[row] = zval; I[row] = _findz($A, row:row, 1:n) if I[row] == 0 @@ -1770,7 +1769,7 @@ macro _findr(op, A, region, Tv, Ti) end findmin{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, region) = @_findr(<, A, region, Tv, Ti) -findmax{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, region) = @_findr(>, A, region, Tv, Ti) +findmax(A::SparseMatrixCSC{Tv,Ti}, region) where {Tv,Ti} = @_findr(>, A, region, Tv, Ti) findmin(A::SparseMatrixCSC) = (r=findmin(A,(1,2)); (r[1][1], r[2][1])) findmax(A::SparseMatrixCSC) = (r=findmax(A,(1,2)); (r[1][1], r[2][1])) @@ -1811,7 +1810,7 @@ function getindex_cols{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, J::AbstractVector) colptrA = A.colptr; rowvalA = A.rowval; nzvalA = A.nzval - colptrS = Array{Ti}(nJ+1) + colptrS = Vector{Ti}(nJ+1) colptrS[1] = 1 nnzS = 0 @@ -1822,8 +1821,8 @@ function getindex_cols{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, J::AbstractVector) colptrS[j+1] = nnzS + 1 end - rowvalS = Array{Ti}(nnzS) - nzvalS = Array{Tv}(nnzS) + rowvalS = Vector{Ti}(nnzS) + nzvalS = Vector{Tv}(nnzS) ptrS = 0 @inbounds for j = 1:nJ @@ -1849,7 +1848,7 @@ function getindex(A::SparseMatrixCSC{Tv,Ti}, I::Range, J::AbstractVector) where nI == 0 || (minimum(I) >= 1 && maximum(I) <= m) || throw(BoundsError()) nJ = length(J) colptrA = A.colptr; rowvalA = A.rowval; nzvalA = A.nzval - colptrS = Array{Ti}(nJ+1) + colptrS = Vector{Ti}(nJ+1) colptrS[1] = 1 nnzS = 0 @@ -1864,8 +1863,8 @@ function getindex(A::SparseMatrixCSC{Tv,Ti}, I::Range, J::AbstractVector) where end # Populate the values in the result - rowvalS = Array{Ti}(nnzS) - nzvalS = Array{Tv}(nnzS) + rowvalS = Vector{Ti}(nnzS) + nzvalS = Vector{Tv}(nnzS) ptrS = 1 @inbounds for j = 1:nJ @@ -1909,7 +1908,7 @@ function getindex_I_sorted_bsearch_A{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, I::Abstra const nJ = length(J) colptrA = A.colptr; rowvalA = A.rowval; nzvalA = A.nzval - colptrS = Array{Ti}(nJ+1) + colptrS = Vector{Ti}(nJ+1) colptrS[1] = 1 ptrS = 1 @@ -1934,8 +1933,8 @@ function getindex_I_sorted_bsearch_A{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, I::Abstra colptrS[j+1] = ptrS end - rowvalS = Array{Ti}(ptrS-1) - nzvalS = Array{Tv}(ptrS-1) + rowvalS = Vector{Ti}(ptrS-1) + nzvalS = Vector{Tv}(ptrS-1) # fill the values ptrS = 1 @@ -1963,12 +1962,12 @@ function getindex_I_sorted_bsearch_A{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, I::Abstra return SparseMatrixCSC(nI, nJ, colptrS, rowvalS, nzvalS) end -function getindex_I_sorted_linear{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, I::AbstractVector, J::AbstractVector) +function getindex_I_sorted_linear(A::SparseMatrixCSC{Tv,Ti}, I::AbstractVector, J::AbstractVector) where {Tv,Ti} const nI = length(I) const nJ = length(J) colptrA = A.colptr; rowvalA = A.rowval; nzvalA = A.nzval - colptrS = Array{Ti}(nJ+1) + colptrS = Vector{Ti}(nJ+1) colptrS[1] = 1 cacheI = zeros(Int, A.m) @@ -1996,8 +1995,8 @@ function getindex_I_sorted_linear{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, I::AbstractV colptrS[j+1] = ptrS end - rowvalS = Array{Ti}(ptrS-1) - nzvalS = Array{Tv}(ptrS-1) + rowvalS = Vector{Ti}(ptrS-1) + nzvalS = Vector{Tv}(ptrS-1) # fill the values ptrS = 1 @@ -2022,12 +2021,12 @@ function getindex_I_sorted_linear{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, I::AbstractV return SparseMatrixCSC(nI, nJ, colptrS, rowvalS, nzvalS) end -function getindex_I_sorted_bsearch_I{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, I::AbstractVector, J::AbstractVector) +function getindex_I_sorted_bsearch_I(A::SparseMatrixCSC{Tv,Ti}, I::AbstractVector, J::AbstractVector) where {Tv,Ti} const nI = length(I) const nJ = length(J) colptrA = A.colptr; rowvalA = A.rowval; nzvalA = A.nzval - colptrS = Array{Ti}(nJ+1) + colptrS = Vector{Ti}(nJ+1) colptrS[1] = 1 m = A.m @@ -2061,8 +2060,8 @@ function getindex_I_sorted_bsearch_I{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, I::Abstra break end end - rowvalS = Array{Ti}(ptrS) - nzvalS = Array{Tv}(ptrS) + rowvalS = Vector{Ti}(ptrS) + nzvalS = Vector{Tv}(ptrS) colptrS[nJ+1] = ptrS+1 # fill the values @@ -2091,14 +2090,14 @@ function getindex_I_sorted_bsearch_I{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, I::Abstra return SparseMatrixCSC(nI, nJ, colptrS, rowvalS, nzvalS) end -function permute_rows!{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}, pI::Vector{Int}) +function permute_rows!(S::SparseMatrixCSC{Tv,Ti}, pI::Vector{Int}) where {Tv,Ti} (m, n) = size(S) colptrS = S.colptr; rowvalS = S.rowval; nzvalS = S.nzval # preallocate temporary sort space nr = min(nnz(S), m) - rowperm = Array{Int}(nr) - rowvalTemp = Array{Ti}(nr) - nzvalTemp = Array{Tv}(nr) + rowperm = Vector{Int}(nr) + rowvalTemp = Vector{Ti}(nr) + nzvalTemp = Vector{Tv}(nr) @inbounds for j in 1:n rowrange = colptrS[j]:(colptrS[j+1]-1) @@ -2111,7 +2110,7 @@ function permute_rows!{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}, pI::Vector{Int}) nzvalTemp[k] = nzvalS[i] k += 1 end - sortperm!(unsafe_wrap(Array, pointer(rowperm), nr), unsafe_wrap(Array, pointer(rowvalTemp), nr)) + sortperm!(unsafe_wrap(Vector{Int}, pointer(rowperm), nr), unsafe_wrap(Vector{Ti}, pointer(rowvalTemp), nr)) k = 1 for i in rowrange kperm = rowperm[k] @@ -2166,8 +2165,8 @@ function getindex(A::SparseMatrixCSC{Tv}, I::AbstractArray) where Tv outn = size(I,2) szB = (outm, outn) colptrB = zeros(Int, outn+1) - rowvalB = Array{Int}(n) - nzvalB = Array{Tv}(n) + rowvalB = Vector{Int}(n) + nzvalB = Vector{Tv}(n) colB = 1 rowB = 1 @@ -2302,8 +2301,8 @@ Helper method for immediately preceding setindex! method. For all (i,j) such tha and j in J, assigns x to A[i,j] if A[i,j] is a presently-stored entry, and allocates and assigns x to A[i,j] if A[i,j] is not presently stored. """ -function _spsetnz_setindex!{Tv}(A::SparseMatrixCSC{Tv}, x::Tv, - I::AbstractVector{<:Integer}, J::AbstractVector{<:Integer}) +function _spsetnz_setindex!(A::SparseMatrixCSC{Tv}, x::Tv, + I::AbstractVector{<:Integer}, J::AbstractVector{<:Integer}) where Tv m, n = size(A) lenI = length(I) @@ -2901,9 +2900,9 @@ function vcat(X::SparseMatrixCSC...) nnzX = Int[ nnz(x) for x in X ] nnz_res = sum(nnzX) - colptr = Array{Ti}(n + 1) - rowval = Array{Ti}(nnz_res) - nzval = Array{Tv}(nnz_res) + colptr = Vector{Ti}(n+1) + rowval = Vector{Ti}(nnz_res) + nzval = Vector{Tv}(nnz_res) colptr[1] = 1 for c = 1:n @@ -2952,11 +2951,11 @@ function hcat(X::SparseMatrixCSC...) Tv = promote_eltype(X...) Ti = promote_eltype(map(x->x.rowval, X)...) - colptr = Array{Ti}(n + 1) + colptr = Vector{Ti}(n+1) nnzX = Int[ nnz(x) for x in X ] nnz_res = sum(nnzX) - rowval = Array{Ti}(nnz_res) - nzval = Array{Tv}(nnz_res) + rowval = Vector{Ti}(nnz_res) + nzval = Vector{Tv}(nnz_res) nnz_sofar = 0 nX_sofar = 0 @@ -3003,11 +3002,11 @@ function blkdiag(X::SparseMatrixCSC...) Tv = promote_type(map(x->eltype(x.nzval), X)...) Ti = promote_type(map(x->eltype(x.rowval), X)...) - colptr = Array{Ti}(n + 1) + colptr = Vector{Ti}(n+1) nnzX = Int[ nnz(x) for x in X ] nnz_res = sum(nnzX) - rowval = Array{Ti}(nnz_res) - nzval = Array{Tv}(nnz_res) + rowval = Vector{Ti}(nnz_res) + nzval = Vector{Tv}(nnz_res) nnz_sofar = 0 nX_sofar = 0 @@ -3153,9 +3152,9 @@ function spdiagm_internal(B, d) for vec in B ncoeffs += length(vec) end - I = Array{Int}(ncoeffs) - J = Array{Int}(ncoeffs) - V = Array{promote_type(map(eltype, B)...)}(ncoeffs) + I = Vector{Int}(ncoeffs) + J = Vector{Int}(ncoeffs) + V = Vector{promote_type(map(eltype, B)...)}(ncoeffs) id = 0 i = 0 for vec in B @@ -3267,9 +3266,9 @@ function diagm{Tv,Ti}(v::SparseMatrixCSC{Tv,Ti}) n = length(v) numnz = nnz(v) - colptr = Array{Ti}(n+1) - rowval = Array{Ti}(numnz) - nzval = Array{Tv}(numnz) + colptr = Vector{Ti}(n+1) + rowval = Vector{Ti}(numnz) + nzval = Vector{Tv}(numnz) if size(v,1) == 1 copy!(colptr, 1, v.colptr, 1, n+1) @@ -3307,10 +3306,10 @@ end # Sort all the indices in each column of a CSC sparse matrix # sortSparseMatrixCSC!(A, sortindices = :sortcols) # Sort each column with sort() # sortSparseMatrixCSC!(A, sortindices = :doubletranspose) # Sort with a double transpose -function sortSparseMatrixCSC!{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}; sortindices::Symbol = :sortcols) +function sortSparseMatrixCSC!(A::SparseMatrixCSC{Tv,Ti}; sortindices::Symbol = :sortcols) where {Tv,Ti} if sortindices == :doubletranspose nB, mB = size(A) - B = SparseMatrixCSC(mB, nB, Array{Ti}(nB+1), similar(A.rowval), similar(A.nzval)) + B = SparseMatrixCSC(mB, nB, Vector{Ti}(nB+1), similar(A.rowval), similar(A.nzval)) transpose!(B, A) transpose!(A, B) return A @@ -3347,8 +3346,8 @@ function sortSparseMatrixCSC!{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}; sortindices::Sym jj += 1 end - sortperm!(unsafe_wrap(Array, pointer(index), numrows), - unsafe_wrap(Array, pointer(row), numrows)) + sortperm!(unsafe_wrap(Vector{Ti}, pointer(index), numrows), + unsafe_wrap(Vector{Ti}, pointer(row), numrows)) jj = 1 @simd for j = col_start:col_end @@ -3406,7 +3405,7 @@ end hash(val, h) end -function hash{T}(A::SparseMatrixCSC{T}, h::UInt) +function hash(A::SparseMatrixCSC{T}, h::UInt) where T h += Base.hashaa_seed sz = size(A) h += hash(sz) @@ -3441,7 +3440,7 @@ end ## Statistics # This is the function that does the reduction underlying var/std -function Base.centralize_sumabs2!{S,Tv,Ti}(R::AbstractArray{S}, A::SparseMatrixCSC{Tv,Ti}, means::AbstractArray) +function Base.centralize_sumabs2!(R::AbstractArray{S}, A::SparseMatrixCSC{Tv,Ti}, means::AbstractArray) where {S,Tv,Ti} lsiz = Base.check_reducedims(R,A) size(means) == size(R) || error("size of means must match size of R") isempty(R) || fill!(R, zero(S)) diff --git a/base/sparse/sparsevector.jl b/base/sparse/sparsevector.jl index c6bf69aee00bc..fa351eb199582 100644 --- a/base/sparse/sparsevector.jl +++ b/base/sparse/sparsevector.jl @@ -44,11 +44,11 @@ similar(x::SparseVector, ::Type{T}, D::Dims) where {T} = spzeros(T, D...) ### Construct empty sparse vector spzeros(len::Integer) = spzeros(Float64, len) -spzeros{T}(::Type{T}, len::Integer) = SparseVector(len, Int[], T[]) -spzeros{Tv, Ti <: Integer}(::Type{Tv}, ::Type{Ti}, len::Integer) = SparseVector(len, Ti[], Tv[]) +spzeros(::Type{T}, len::Integer) where {T} = SparseVector(len, Int[], T[]) +spzeros(::Type{Tv}, ::Type{Ti}, len::Integer) where {Tv,Ti<:Integer} = SparseVector(len, Ti[], Tv[]) # Construction of same structure, but with all ones -spones{T}(x::SparseVector{T}) = SparseVector(x.n, copy(x.nzind), ones(T, length(x.nzval))) +spones(x::SparseVector{T}) where {T} = SparseVector(x.n, copy(x.nzind), ones(T, length(x.nzval))) ### Construction from lists of indices and values @@ -183,7 +183,7 @@ julia> sparsevec(Dict(1 => 3, 2 => 2)) [2] = 2 ``` """ -function sparsevec{Tv,Ti<:Integer}(dict::Associative{Ti,Tv}) +function sparsevec(dict::Associative{Ti,Tv}) where {Tv,Ti<:Integer} m = length(dict) nzind = Vector{Ti}(m) nzval = Vector{Tv}(m) @@ -204,7 +204,7 @@ function sparsevec{Tv,Ti<:Integer}(dict::Associative{Ti,Tv}) _sparsevector!(nzind, nzval, len) end -function sparsevec{Tv,Ti<:Integer}(dict::Associative{Ti,Tv}, len::Integer) +function sparsevec(dict::Associative{Ti,Tv}, len::Integer) where {Tv,Ti<:Integer} m = length(dict) nzind = Vector{Ti}(m) nzval = Vector{Tv}(m) @@ -313,12 +313,12 @@ julia> sparsevec([1.0, 2.0, 0.0, 0.0, 3.0, 0.0]) [5] = 3.0 ``` """ -sparsevec{T}(a::AbstractVector{T}) = convert(SparseVector{T, Int}, a) +sparsevec(a::AbstractVector{T}) where {T} = convert(SparseVector{T, Int}, a) sparsevec(a::AbstractArray) = sparsevec(vec(a)) sparsevec(a::AbstractSparseArray) = vec(a) sparse(a::AbstractVector) = sparsevec(a) -function _dense2sparsevec{Tv,Ti}(s::AbstractArray{Tv}, initcap::Ti) +function _dense2sparsevec(s::AbstractArray{Tv}, initcap::Ti) where {Tv,Ti} # pre-condition: initcap > 0; the initcap determines the index type n = length(s) cap = initcap @@ -361,7 +361,7 @@ convert(::Type{SparseVector{Tv,Ti}}, s::SparseVector{Tv,Ti}) where {Tv,Ti} = s convert(::Type{SparseVector{Tv,Ti}}, s::SparseVector) where {Tv,Ti} = SparseVector{Tv,Ti}(s.n, convert(Vector{Ti}, s.nzind), convert(Vector{Tv}, s.nzval)) -convert{Tv,Ti}(::Type{SparseVector{Tv}}, s::SparseVector{<:Any,Ti}) = +convert(::Type{SparseVector{Tv}}, s::SparseVector{<:Any,Ti}) where {Tv,Ti} = SparseVector{Tv,Ti}(s.n, s.nzind, convert(Vector{Tv}, s.nzval)) @@ -420,8 +420,8 @@ copy!(A::SparseMatrixCSC, B::SparseVector{TvB,TiB}) where {TvB,TiB} = ### Rand Construction -sprand{T}(n::Integer, p::AbstractFloat, rfn::Function, ::Type{T}) = sprand(GLOBAL_RNG, n, p, rfn, T) -function sprand{T}(r::AbstractRNG, n::Integer, p::AbstractFloat, rfn::Function, ::Type{T}) +sprand(n::Integer, p::AbstractFloat, rfn::Function, ::Type{T}) where {T} = sprand(GLOBAL_RNG, n, p, rfn, T) +function sprand(r::AbstractRNG, n::Integer, p::AbstractFloat, rfn::Function, ::Type{T}) where T I = randsubseq(r, 1:convert(Int, n), p) V = rfn(r, T, length(I)) SparseVector(n, I, V) @@ -437,9 +437,9 @@ end sprand(n::Integer, p::AbstractFloat) = sprand(GLOBAL_RNG, n, p, rand) sprand(r::AbstractRNG, n::Integer, p::AbstractFloat) = sprand(r, n, p, rand) -sprand{T}(r::AbstractRNG, ::Type{T}, n::Integer, p::AbstractFloat) = sprand(r, n, p, (r, i) -> rand(r, T, i)) +sprand(r::AbstractRNG, ::Type{T}, n::Integer, p::AbstractFloat) where {T} = sprand(r, n, p, (r, i) -> rand(r, T, i)) sprand(r::AbstractRNG, ::Type{Bool}, n::Integer, p::AbstractFloat) = sprand(r, n, p, truebools) -sprand{T}(::Type{T}, n::Integer, p::AbstractFloat) = sprand(GLOBAL_RNG, T, n, p) +sprand(::Type{T}, n::Integer, p::AbstractFloat) where {T} = sprand(GLOBAL_RNG, T, n, p) sprandn(n::Integer, p::AbstractFloat) = sprand(GLOBAL_RNG, n, p, randn) sprandn(r::AbstractRNG, n::Integer, p::AbstractFloat) = sprand(r, n, p, randn) @@ -473,7 +473,7 @@ end # Row slices getindex(A::SparseMatrixCSC, i::Integer, ::Colon) = A[i, 1:end] -function Base.getindex{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, i::Integer, J::AbstractVector) +function Base.getindex(A::SparseMatrixCSC{Tv,Ti}, i::Integer, J::AbstractVector) where {Tv,Ti} checkbounds(A, i, J) nJ = length(J) colptrA = A.colptr; rowvalA = A.rowval; nzvalA = A.nzval @@ -1021,7 +1021,7 @@ end real(x::AbstractSparseVector{<:Real}) = x @unarymap_nz2z_z2z real Complex -imag{Tv<:Real,Ti<:Integer}(x::AbstractSparseVector{Tv,Ti}) = SparseVector(length(x), Ti[], Tv[]) +imag(x::AbstractSparseVector{Tv,Ti}) where {Tv<:Real,Ti<:Integer} = SparseVector(length(x), Ti[], Tv[]) @unarymap_nz2z_z2z imag Complex for op in [:floor, :ceil, :trunc, :round] @@ -1072,10 +1072,10 @@ end # 1: f(nz, nz) -> z/nz, f(z, nz) -> nz, f(nz, z) -> nz # 2: f(nz, nz) -> z/nz, f(z, nz) -> z/nz, f(nz, z) -> z/nz -function _binarymap{Tx,Ty}(f::Function, - x::AbstractSparseVector{Tx}, - y::AbstractSparseVector{Ty}, - mode::Int) +function _binarymap(f::Function, + x::AbstractSparseVector{Tx}, + y::AbstractSparseVector{Ty}, + mode::Int) where {Tx,Ty} 0 <= mode <= 2 || throw(ArgumentError("Incorrect mode $mode.")) R = typeof(f(zero(Tx), zero(Ty))) n = length(x) @@ -1129,10 +1129,10 @@ function _binarymap_mode_0!(f::Function, mx::Int, my::Int, return ir end -function _binarymap_mode_1!{Tx,Ty}(f::Function, mx::Int, my::Int, - xnzind, xnzval::AbstractVector{Tx}, - ynzind, ynzval::AbstractVector{Ty}, - rind, rval) +function _binarymap_mode_1!(f::Function, mx::Int, my::Int, + xnzind, xnzval::AbstractVector{Tx}, + ynzind, ynzval::AbstractVector{Ty}, + rind, rval) where {Tx,Ty} # f(nz, nz) -> z/nz, f(z, nz) -> nz, f(nz, z) -> nz ir = 0; ix = 1; iy = 1 @inbounds while ix <= mx && iy <= my @@ -1167,10 +1167,10 @@ function _binarymap_mode_1!{Tx,Ty}(f::Function, mx::Int, my::Int, return ir end -function _binarymap_mode_2!{Tx,Ty}(f::Function, mx::Int, my::Int, - xnzind, xnzval::AbstractVector{Tx}, - ynzind, ynzval::AbstractVector{Ty}, - rind, rval) +function _binarymap_mode_2!(f::Function, mx::Int, my::Int, + xnzind, xnzval::AbstractVector{Tx}, + ynzind, ynzval::AbstractVector{Ty}, + rind, rval) where {Tx,Ty} # f(nz, nz) -> z/nz, f(z, nz) -> z/nz, f(nz, z) -> z/nz ir = 0; ix = 1; iy = 1 @inbounds while ix <= mx && iy <= my @@ -1213,10 +1213,10 @@ function _binarymap_mode_2!{Tx,Ty}(f::Function, mx::Int, my::Int, return ir end -function _binarymap{Tx,Ty}(f::Function, - x::AbstractVector{Tx}, - y::AbstractSparseVector{Ty}, - mode::Int) +function _binarymap(f::Function, + x::AbstractVector{Tx}, + y::AbstractSparseVector{Ty}, + mode::Int) where {Tx,Ty} 0 <= mode <= 2 || throw(ArgumentError("Incorrect mode $mode.")) R = typeof(f(zero(Tx), zero(Ty))) n = length(x) @@ -1255,10 +1255,10 @@ function _binarymap{Tx,Ty}(f::Function, return dst end -function _binarymap{Tx,Ty}(f::Function, - x::AbstractSparseVector{Tx}, - y::AbstractVector{Ty}, - mode::Int) +function _binarymap(f::Function, + x::AbstractSparseVector{Tx}, + y::AbstractVector{Ty}, + mode::Int) where {Tx,Ty} 0 <= mode <= 2 || throw(ArgumentError("Incorrect mode $mode.")) R = typeof(f(zero(Tx), zero(Ty))) n = length(x) @@ -1349,7 +1349,7 @@ complex(x::AbstractSparseVector{<:Real}, y::StridedVector{<:Real}) = _binarymap( sum(x::AbstractSparseVector) = sum(nonzeros(x)) -function maximum{T<:Real}(x::AbstractSparseVector{T}) +function maximum(x::AbstractSparseVector{T}) where T<:Real n = length(x) n > 0 || throw(ArgumentError("maximum over empty array is not allowed.")) m = nnz(x) @@ -1358,7 +1358,7 @@ function maximum{T<:Real}(x::AbstractSparseVector{T}) max(zero(T), maximum(nonzeros(x))))::T end -function minimum{T<:Real}(x::AbstractSparseVector{T}) +function minimum(x::AbstractSparseVector{T}) where T<:Real n = length(x) n > 0 || throw(ArgumentError("minimum over empty array is not allowed.")) m = nnz(x) @@ -1370,7 +1370,7 @@ end for f in [:sum, :maximum, :minimum], op in [:abs, :abs2] SV = :AbstractSparseVector if f == :minimum - @eval ($f){T<:Number}(::typeof($op), x::$SV{T}) = nnz(x) < length(x) ? ($op)(zero(T)) : ($f)($op, nonzeros(x)) + @eval ($f)(::typeof($op), x::$SV{T}) where {T<:Number} = nnz(x) < length(x) ? ($op)(zero(T)) : ($f)($op, nonzeros(x)) else @eval ($f)(::typeof($op), x::$SV) = ($f)($op, nonzeros(x)) end @@ -1426,16 +1426,16 @@ scale!(a::Real, x::AbstractSparseVector) = (scale!(nonzeros(x), a); x) scale!(a::Complex, x::AbstractSparseVector) = (scale!(nonzeros(x), a); x) -*(x::AbstractSparseVector, a::Number) = SparseVector(length(x), copy(nonzeroinds(x)), nonzeros(x) * a) -*(a::Number, x::AbstractSparseVector) = SparseVector(length(x), copy(nonzeroinds(x)), a * nonzeros(x)) -/(x::AbstractSparseVector, a::Number) = SparseVector(length(x), copy(nonzeroinds(x)), nonzeros(x) / a) +(*)(x::AbstractSparseVector, a::Number) = SparseVector(length(x), copy(nonzeroinds(x)), nonzeros(x) * a) +(*)(a::Number, x::AbstractSparseVector) = SparseVector(length(x), copy(nonzeroinds(x)), a * nonzeros(x)) +(/)(x::AbstractSparseVector, a::Number) = SparseVector(length(x), copy(nonzeroinds(x)), nonzeros(x) / a) broadcast(::typeof(*), x::AbstractSparseVector, a::Number) = x * a broadcast(::typeof(*), a::Number, x::AbstractSparseVector) = a * x broadcast(::typeof(/), x::AbstractSparseVector, a::Number) = x / a # dot -function dot{Tx<:Number,Ty<:Number}(x::StridedVector{Tx}, y::AbstractSparseVector{Ty}) +function dot(x::StridedVector{Tx}, y::AbstractSparseVector{Ty}) where {Tx<:Number,Ty<:Number} n = length(x) length(y) == n || throw(DimensionMismatch()) nzind = nonzeroinds(y) @@ -1447,7 +1447,7 @@ function dot{Tx<:Number,Ty<:Number}(x::StridedVector{Tx}, y::AbstractSparseVecto return s end -function dot{Tx<:Number,Ty<:Number}(x::AbstractSparseVector{Tx}, y::AbstractVector{Ty}) +function dot(x::AbstractSparseVector{Tx}, y::AbstractVector{Ty}) where {Tx<:Number,Ty<:Number} n = length(y) length(x) == n || throw(DimensionMismatch()) nzind = nonzeroinds(x) @@ -1500,11 +1500,11 @@ end # A_mul_B -function *(A::StridedMatrix{Ta}, x::AbstractSparseVector{Tx}) where {Ta,Tx} +function (*)(A::StridedMatrix{Ta}, x::AbstractSparseVector{Tx}) where {Ta,Tx} m, n = size(A) length(x) == n || throw(DimensionMismatch()) Ty = promote_type(Ta, Tx) - y = Array{Ty}(m) + y = Vector{Ty}(m) A_mul_B!(y, A, x) end @@ -1541,7 +1541,7 @@ function At_mul_B(A::StridedMatrix{Ta}, x::AbstractSparseVector{Tx}) where {Ta,T m, n = size(A) length(x) == m || throw(DimensionMismatch()) Ty = promote_type(Ta, Tx) - y = Array{Ty}(n) + y = Vector{Ty}(n) At_mul_B!(y, A, x) end @@ -1588,7 +1588,7 @@ function densemv(A::SparseMatrixCSC, x::AbstractSparseVector; trans::Char='N') end xlen == length(x) || throw(DimensionMismatch()) T = promote_type(eltype(A), eltype(x)) - y = Array{T}(ylen) + y = Vector{T}(ylen) if trans == 'N' || trans == 'N' A_mul_B!(y, A, x) elseif trans == 'T' || trans == 't' @@ -1703,8 +1703,8 @@ function _At_or_Ac_mul_B(tfun::Function, A::SparseMatrixCSC{TvA,TiA}, x::Abstrac Anzval = A.nzval mx = length(xnzind) - ynzind = Array{Ti}(n) - ynzval = Array{Tv}(n) + ynzind = Vector{Ti}(n) + ynzval = Vector{Tv}(n) jr = 0 for j = 1:n @@ -1740,7 +1740,7 @@ for isunittri in (true, false), islowertri in (true, false) (true, :(Ac_ldiv_B), :(Ac_ldiv_B!)) ) # broad method where elements are Numbers - @eval function ($func){TA<:Number,Tb<:Number}(A::$tritype{TA,<:AbstractMatrix}, b::SparseVector{Tb}) + @eval function ($func)(A::$tritype{TA,<:AbstractMatrix}, b::SparseVector{Tb}) where {TA<:Number,Tb<:Number} TAb = $(isunittri ? :(typeof(zero(TA)*zero(Tb) + zero(TA)*zero(Tb))) : :(typeof((zero(TA)*zero(Tb) + zero(TA)*zero(Tb))/one(TA))) ) @@ -1749,7 +1749,7 @@ for isunittri in (true, false), islowertri in (true, false) # faster method requiring good view support of the # triangular matrix type. hence the StridedMatrix restriction. - @eval function ($func){TA<:Number,Tb<:Number}(A::$tritype{TA,<:StridedMatrix}, b::SparseVector{Tb}) + @eval function ($func)(A::$tritype{TA,<:StridedMatrix}, b::SparseVector{Tb}) where {TA<:Number,Tb<:Number} TAb = $(isunittri ? :(typeof(zero(TA)*zero(Tb) + zero(TA)*zero(Tb))) : :(typeof((zero(TA)*zero(Tb) + zero(TA)*zero(Tb))/one(TA))) ) diff --git a/base/sparse/spqr.jl b/base/sparse/spqr.jl index 66deb05e5d320..0f4bb9a65b772 100644 --- a/base/sparse/spqr.jl +++ b/base/sparse/spqr.jl @@ -106,7 +106,7 @@ function factorize{Tv<:VTypes}(ordering::Integer, tol::Real, A::Sparse{Tv}) f end -function solve{Tv<:VTypes}(system::Integer, QR::Factorization{Tv}, B::Dense{Tv}) +function solve(system::Integer, QR::Factorization{Tv}, B::Dense{Tv}) where Tv<:VTypes m, n = size(QR) mB = size(B, 1) if (system == RX_EQUALS_B || system == RETX_EQUALS_B) && m != mB From dc5a62f6137e51e48b50e9f816dd6c9702f25b10 Mon Sep 17 00:00:00 2001 From: Mus M Date: Fri, 21 Apr 2017 20:05:28 -0400 Subject: [PATCH 0498/1534] Minor style and code tweaks and use where syntax for misc methods (#21468) --- base/broadcast.jl | 2 +- base/linalg/bidiag.jl | 36 ++++++++++++++++++------------------ base/linalg/tridiag.jl | 16 ++++++++-------- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/base/broadcast.jl b/base/broadcast.jl index 436bed3068d59..c6dfb006e8f8e 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -15,7 +15,7 @@ const ScalarType = Union{Type{Any}, Type{Nullable}} # fallbacks for some special cases @inline broadcast(f, x::Number...) = f(x...) @inline broadcast(f, t::NTuple{N,Any}, ts::Vararg{NTuple{N,Any}}) where {N} = map(f, t, ts...) -broadcast!{T,S,N}(::typeof(identity), x::Array{T,N}, y::Array{S,N}) = +broadcast!(::typeof(identity), x::Array{T,N}, y::Array{S,N}) where {T,S,N} = size(x) == size(y) ? copy!(x, y) : broadcast_c!(identity, Array, Array, x, y) # special cases for "X .= ..." (broadcast!) assignments diff --git a/base/linalg/bidiag.jl b/base/linalg/bidiag.jl index 9448bec2dee09..9d70bea5ba578 100644 --- a/base/linalg/bidiag.jl +++ b/base/linalg/bidiag.jl @@ -96,7 +96,7 @@ julia> Bl = Bidiagonal(dv, ev, 'L') #e is on the first subdiagonal ``` """ #Convert from BLAS uplo flag to boolean internal -Bidiagonal(dv::AbstractVector, ev::AbstractVector, uplo::Char) = begin +function Bidiagonal(dv::AbstractVector, ev::AbstractVector, uplo::Char) if uplo === 'U' isupper = true elseif uplo === 'L' @@ -265,10 +265,10 @@ broadcast(::typeof(ceil), M::Bidiagonal) = Bidiagonal(ceil.(M.dv), ceil.(M.ev), for func in (:conj, :copy, :real, :imag) @eval ($func)(M::Bidiagonal) = Bidiagonal(($func)(M.dv), ($func)(M.ev), M.isupper) end -broadcast{T<:Integer}(::typeof(round), ::Type{T}, M::Bidiagonal) = Bidiagonal(round.(T, M.dv), round.(T, M.ev), M.isupper) -broadcast{T<:Integer}(::typeof(trunc), ::Type{T}, M::Bidiagonal) = Bidiagonal(trunc.(T, M.dv), trunc.(T, M.ev), M.isupper) -broadcast{T<:Integer}(::typeof(floor), ::Type{T}, M::Bidiagonal) = Bidiagonal(floor.(T, M.dv), floor.(T, M.ev), M.isupper) -broadcast{T<:Integer}(::typeof(ceil), ::Type{T}, M::Bidiagonal) = Bidiagonal(ceil.(T, M.dv), ceil.(T, M.ev), M.isupper) +broadcast(::typeof(round), ::Type{T}, M::Bidiagonal) where {T<:Integer} = Bidiagonal(round.(T, M.dv), round.(T, M.ev), M.isupper) +broadcast(::typeof(trunc), ::Type{T}, M::Bidiagonal) where {T<:Integer} = Bidiagonal(trunc.(T, M.dv), trunc.(T, M.ev), M.isupper) +broadcast(::typeof(floor), ::Type{T}, M::Bidiagonal) where {T<:Integer} = Bidiagonal(floor.(T, M.dv), floor.(T, M.ev), M.isupper) +broadcast(::typeof(ceil), ::Type{T}, M::Bidiagonal) where {T<:Integer} = Bidiagonal(ceil.(T, M.dv), ceil.(T, M.ev), M.isupper) transpose(M::Bidiagonal) = Bidiagonal(M.dv, M.ev, !M.isupper) ctranspose(M::Bidiagonal) = Bidiagonal(conj(M.dv), conj(M.ev), !M.isupper) @@ -312,7 +312,7 @@ function triu!(M::Bidiagonal, k::Integer=0) return M end -function diag{T}(M::Bidiagonal{T}, n::Integer=0) +function diag(M::Bidiagonal{T}, n::Integer=0) where T if n == 0 return M.dv elseif n == 1 @@ -348,8 +348,8 @@ end /(A::Bidiagonal, B::Number) = Bidiagonal(A.dv/B, A.ev/B, A.isupper) ==(A::Bidiagonal, B::Bidiagonal) = (A.dv==B.dv) && (A.ev==B.ev) && (A.isupper==B.isupper) -BiTriSym = Union{Bidiagonal, Tridiagonal, SymTridiagonal} -BiTri = Union{Bidiagonal, Tridiagonal} +const BiTriSym = Union{Bidiagonal,Tridiagonal,SymTridiagonal} +const BiTri = Union{Bidiagonal,Tridiagonal} A_mul_B!(C::AbstractMatrix, A::SymTridiagonal, B::BiTriSym) = A_mul_B_td!(C, A, B) A_mul_B!(C::AbstractMatrix, A::BiTri, B::BiTriSym) = A_mul_B_td!(C, A, B) A_mul_B!(C::AbstractMatrix, A::BiTriSym, B::BiTriSym) = A_mul_B_td!(C, A, B) @@ -493,21 +493,21 @@ function A_mul_B_td!(C::AbstractMatrix, A::AbstractMatrix, B::BiTriSym) C end -SpecialMatrix = Union{Bidiagonal, SymTridiagonal, Tridiagonal} +const SpecialMatrix = Union{Bidiagonal,SymTridiagonal,Tridiagonal} # to avoid ambiguity warning, but shouldn't be necessary *(A::AbstractTriangular, B::SpecialMatrix) = Array(A) * Array(B) *(A::SpecialMatrix, B::SpecialMatrix) = Array(A) * Array(B) #Generic multiplication for func in (:*, :Ac_mul_B, :A_mul_Bc, :/, :A_rdiv_Bc) - @eval ($func){T}(A::Bidiagonal{T}, B::AbstractVector{T}) = ($func)(Array(A), B) + @eval ($func)(A::Bidiagonal{T}, B::AbstractVector{T}) where {T} = ($func)(Array(A), B) end #Linear solvers A_ldiv_B!(A::Union{Bidiagonal, AbstractTriangular}, b::AbstractVector) = naivesub!(A, b) At_ldiv_B!(A::Bidiagonal, b::AbstractVector) = A_ldiv_B!(transpose(A), b) Ac_ldiv_B!(A::Bidiagonal, b::AbstractVector) = A_ldiv_B!(ctranspose(A), b) -function A_ldiv_B!(A::Union{Bidiagonal, AbstractTriangular}, B::AbstractMatrix) +function A_ldiv_B!(A::Union{Bidiagonal,AbstractTriangular}, B::AbstractMatrix) nA,mA = size(A) tmp = similar(B,size(B,1)) n = size(B, 1) @@ -538,7 +538,7 @@ for func in (:Ac_ldiv_B!, :At_ldiv_B!) end end #Generic solver using naive substitution -function naivesub!{T}(A::Bidiagonal{T}, b::AbstractVector, x::AbstractVector = b) +function naivesub!(A::Bidiagonal{T}, b::AbstractVector, x::AbstractVector = b) where T N = size(A, 2) if N != length(b) || N != length(x) throw(DimensionMismatch("second dimension of A, $N, does not match one of the lengths of x, $(length(x)), or b, $(length(b))")) @@ -562,7 +562,7 @@ end ### Generic promotion methods and fallbacks for (f,g) in ((:\, :A_ldiv_B!), (:At_ldiv_B, :At_ldiv_B!), (:Ac_ldiv_B, :Ac_ldiv_B!)) @eval begin - function ($f){TA<:Number,TB<:Number}(A::Bidiagonal{TA}, B::AbstractVecOrMat{TB}) + function ($f)(A::Bidiagonal{TA}, B::AbstractVecOrMat{TB}) where {TA<:Number,TB<:Number} TAB = typeof((zero(TA)*zero(TB) + zero(TA)*zero(TB))/one(TA)) ($g)(convert(AbstractArray{TAB}, A), copy_oftype(B, TAB)) end @@ -574,9 +574,9 @@ factorize(A::Bidiagonal) = A # Eigensystems eigvals(M::Bidiagonal) = M.dv -function eigvecs{T}(M::Bidiagonal{T}) +function eigvecs(M::Bidiagonal{T}) where T n = length(M.dv) - Q = Array{T}(n, n) + Q = Matrix{T}(n,n) blks = [0; find(x -> x == 0, M.ev); n] v = zeros(T, n) if M.isupper @@ -630,14 +630,14 @@ SpecialArrays = Union{Diagonal, end # for historical reasons: -fill!(a::AbstractTriangular, x) = fillslots!(a, x); -fill!(D::Diagonal, x) = fillslots!(D, x); +fill!(a::AbstractTriangular, x) = fillslots!(a, x) +fill!(D::Diagonal, x) = fillslots!(D, x) _small_enough(A::Bidiagonal) = size(A, 1) <= 1 _small_enough(A::Tridiagonal) = size(A, 1) <= 2 _small_enough(A::SymTridiagonal) = size(A, 1) <= 2 -function fill!(A::Union{Bidiagonal, Tridiagonal, SymTridiagonal} ,x) +function fill!(A::Union{Bidiagonal, Tridiagonal, SymTridiagonal}, x) xT = convert(eltype(A), x) (xT == zero(eltype(A)) || _small_enough(A)) && return fillslots!(A, xT) throw(ArgumentError("array A of type $(typeof(A)) and size $(size(A)) can diff --git a/base/linalg/tridiag.jl b/base/linalg/tridiag.jl index faa5d53624706..0efaf34f43a6b 100644 --- a/base/linalg/tridiag.jl +++ b/base/linalg/tridiag.jl @@ -104,10 +104,10 @@ broadcast(::typeof(ceil), M::SymTridiagonal) = SymTridiagonal(ceil.(M.dv), ceil. for func in (:conj, :copy, :real, :imag) @eval ($func)(M::SymTridiagonal) = SymTridiagonal(($func)(M.dv), ($func)(M.ev)) end -broadcast{T<:Integer}(::typeof(round), ::Type{T}, M::SymTridiagonal) = SymTridiagonal(round.(T, M.dv), round.(T, M.ev)) -broadcast{T<:Integer}(::typeof(trunc), ::Type{T}, M::SymTridiagonal) = SymTridiagonal(trunc.(T, M.dv), trunc.(T, M.ev)) -broadcast{T<:Integer}(::typeof(floor), ::Type{T}, M::SymTridiagonal) = SymTridiagonal(floor.(T, M.dv), floor.(T, M.ev)) -broadcast{T<:Integer}(::typeof(ceil), ::Type{T}, M::SymTridiagonal) = SymTridiagonal(ceil.(T, M.dv), ceil.(T, M.ev)) +broadcast(::typeof(round), ::Type{T}, M::SymTridiagonal) where {T<:Integer} = SymTridiagonal(round.(T, M.dv), round.(T, M.ev)) +broadcast(::typeof(trunc), ::Type{T}, M::SymTridiagonal) where {T<:Integer} = SymTridiagonal(trunc.(T, M.dv), trunc.(T, M.ev)) +broadcast(::typeof(floor), ::Type{T}, M::SymTridiagonal) where {T<:Integer} = SymTridiagonal(floor.(T, M.dv), floor.(T, M.ev)) +broadcast(::typeof(ceil), ::Type{T}, M::SymTridiagonal) where {T<:Integer} = SymTridiagonal(ceil.(T, M.dv), ceil.(T, M.ev)) transpose(M::SymTridiagonal) = M #Identity operation ctranspose(M::SymTridiagonal) = conj(M) @@ -517,13 +517,13 @@ for func in (:conj, :copy, :real, :imag) Tridiagonal(($func)(M.dl), ($func)(M.d), ($func)(M.du), ($func)(M.du2)) end end -broadcast{T<:Integer}(::typeof(round), ::Type{T}, M::Tridiagonal) = +broadcast(::typeof(round), ::Type{T}, M::Tridiagonal) where {T<:Integer} = Tridiagonal(round.(T, M.dl), round.(T, M.d), round.(T, M.du), round.(T, M.du2)) -broadcast{T<:Integer}(::typeof(trunc), ::Type{T}, M::Tridiagonal) = +broadcast(::typeof(trunc), ::Type{T}, M::Tridiagonal) where {T<:Integer} = Tridiagonal(trunc.(T, M.dl), trunc.(T, M.d), trunc.(T, M.du), trunc.(T, M.du2)) -broadcast{T<:Integer}(::typeof(floor), ::Type{T}, M::Tridiagonal) = +broadcast(::typeof(floor), ::Type{T}, M::Tridiagonal) where {T<:Integer} = Tridiagonal(floor.(T, M.dl), floor.(T, M.d), floor.(T, M.du), floor.(T, M.du2)) -broadcast{T<:Integer}(::typeof(ceil), ::Type{T}, M::Tridiagonal) = +broadcast(::typeof(ceil), ::Type{T}, M::Tridiagonal) where {T<:Integer} = Tridiagonal(ceil.(T, M.dl), ceil.(T, M.d), ceil.(T, M.du), ceil.(T, M.du2)) transpose(M::Tridiagonal) = Tridiagonal(M.du, M.d, M.dl) From 51202adfd24814a25d83fb16d928dab16f6f69ca Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Fri, 21 Apr 2017 11:33:45 -0400 Subject: [PATCH 0499/1534] Optimize pause and wake functions in julia code --- src/ccall.cpp | 37 ++++++++++++++++++++++++++++++++++++- src/codegen.cpp | 4 +++- src/julia_threads.h | 1 + 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/ccall.cpp b/src/ccall.cpp index 60ddb2c9f6474..7623aefeaad78 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -1647,12 +1647,47 @@ static jl_cgval_t emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) return mark_or_box_ccall_result(emit_bitcast(ary, lrt), retboxed, rt, unionall, static_rt, ctx); } - else if (JL_CPU_WAKE_NOOP && is_libjulia_func(jl_cpu_wake)) { + else if (is_libjulia_func(jl_cpu_pause)) { + // Keep in sync with the julia_threads.h version assert(lrt == T_void); assert(!isVa && !llvmcall); assert(nargt == 0); +#ifdef __MIC__ + // TODO +#elif defined(_CPU_X86_64_) || defined(_CPU_X86_) /* !__MIC__ */ +#if JL_LLVM_VERSION >= 30700 + static auto pauseinst = InlineAsm::get(FunctionType::get(T_void, false), "pause", + "~{memory}", true); + builder.CreateCall(pauseinst); JL_GC_POP(); return ghostValue(jl_void_type); +#endif +#elif defined(_CPU_AARCH64_) || (defined(_CPU_ARM_) && __ARM_ARCH >= 7) + static auto wfeinst = InlineAsm::get(FunctionType::get(T_void, false), "wfe", + "~{memory}", true); + builder.CreateCall(wfeinst); + JL_GC_POP(); + return ghostValue(jl_void_type); +#else + JL_GC_POP(); + return ghostValue(jl_void_type); +#endif + } + else if (is_libjulia_func(jl_cpu_wake)) { + // Keep in sync with the julia_threads.h version + assert(lrt == T_void); + assert(!isVa && !llvmcall); + assert(nargt == 0); +#if JL_CPU_WAKE_NOOP == 1 + JL_GC_POP(); + return ghostValue(jl_void_type); +#elif defined(_CPU_AARCH64_) || (defined(_CPU_ARM_) && __ARM_ARCH >= 7) + static auto sevinst = InlineAsm::get(FunctionType::get(T_void, false), "sev", + "~{memory}", true); + builder.CreateCall(sevinst); + JL_GC_POP(); + return ghostValue(jl_void_type); +#endif } else if (is_libjulia_func(jl_gc_safepoint)) { assert(lrt == T_void); diff --git a/src/codegen.cpp b/src/codegen.cpp index 5de00ef196c3f..a9ea6ffed4584 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -96,8 +96,10 @@ #include #include -#if defined(_CPU_ARM_) || defined(_CPU_AARCH64_) +#if JL_LLVM_VERSION >= 30700 # include +#endif +#if defined(_CPU_ARM_) || defined(_CPU_AARCH64_) # include #endif #if defined(USE_POLLY) diff --git a/src/julia_threads.h b/src/julia_threads.h index b8c9087076efb..8fd701f03ae7f 100644 --- a/src/julia_threads.h +++ b/src/julia_threads.h @@ -140,6 +140,7 @@ typedef struct _jl_tls_states_t { } jl_tls_states_t; typedef jl_tls_states_t *jl_ptls_t; +// Update codegen version in `ccall.cpp` after changing either `pause` or `wake` #ifdef __MIC__ # define jl_cpu_pause() _mm_delay_64(100) # define jl_cpu_wake() ((void)0) From 5b32e44fbbf9e30df4eda42eefa70837f0467ee5 Mon Sep 17 00:00:00 2001 From: Carlo Baldassi Date: Sat, 22 Apr 2017 02:51:49 +0200 Subject: [PATCH 0500/1534] Improve Pkg.resolve accuracy Reset the messages after each decimation. This helps avoiding some of the problems that were reported lately, in particular those at: https://discourse.julialang.org/t/differentialequations-pkg-wont-be-added --- base/pkg/resolve/fieldvalue.jl | 9 +++++++++ base/pkg/resolve/maxsum.jl | 27 +++++++++++++++++++++++---- base/pkg/resolve/versionweight.jl | 20 ++++++++++++++++++++ 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/base/pkg/resolve/fieldvalue.jl b/base/pkg/resolve/fieldvalue.jl index ca64085644101..76077d7f78675 100644 --- a/base/pkg/resolve/fieldvalue.jl +++ b/base/pkg/resolve/fieldvalue.jl @@ -65,6 +65,15 @@ Base.:(==)(a::FieldValue, b::FieldValue) = Base.abs(a::FieldValue) = FieldValue(abs(a.l0), abs(a.l1), abs(a.l2), abs(a.l3), abs(a.l4), abs(a.l5)) +Base.copy(a::FieldValue) = FieldValue(a.l0, copy(a.l1), copy(a.l2), a.l3, a.l4, a.l5) + +function Base.unsafe_copy!(dest::Field, doffs, src::Field, soffs, n) + for i = 1:n + dest[doffs+i-1] = copy(src[soffs+i-1]) + end + return dest +end + # if the maximum field has l0 < 0, it means that # some hard constraint is being violated validmax(a::FieldValue) = a.l0 >= 0 diff --git a/base/pkg/resolve/maxsum.jl b/base/pkg/resolve/maxsum.jl index 55c02a2925a9c..706b1df8dba50 100644 --- a/base/pkg/resolve/maxsum.jl +++ b/base/pkg/resolve/maxsum.jl @@ -170,6 +170,9 @@ mutable struct Messages # fields are not normalized fld::Vector{Field} + # backup of the initial value of fld, to be used when resetting + initial_fld::Vector{Field} + # keep track of which variables have been decimated decimated::BitVector num_nondecimated::Int @@ -221,11 +224,13 @@ mutable struct Messages end end + initial_fld = deepcopy(fld) + # initialize cavity messages to 0 gadj = graph.gadj msg = [[zeros(FieldValue, spp[p0]) for p1 = 1:length(gadj[p0])] for p0 = 1:np] - return new(msg, fld, falses(np), np) + return new(msg, fld, initial_fld, falses(np), np) end end @@ -380,14 +385,27 @@ function decimate1(p0::Int, graph::Graph, msgs::Messages) #println("DECIMATING $p0 ($(packages()[p0]) s0=$s0)") for v0 = 1:length(fld0) if v0 != s0 - fld0[v0] -= FieldValue(1) + fld0[v0] = FieldValue(-1) end end - update(p0, graph, msgs) msgs.decimated[p0] = true msgs.num_nondecimated -= 1 end +function reset_messages!(msgs::Messages) + msg = msgs.msg + fld = msgs.fld + initial_fld = msgs.initial_fld + decimated = msgs.decimated + np = length(fld) + for p0 = 1:np + map(m->fill!(m, zero(FieldValue)), msg[p0]) + decimated[p0] && continue + fld[p0] = copy(initial_fld[p0]) + end + return msgs +end + # If normal convergence fails (or is too slow) fix the most # polarized packages by adding extra infinite fields on every state # but the maximum @@ -403,6 +421,7 @@ function decimate(n::Int, graph::Graph, msgs::Messages) n == 0 && break end @assert n == 0 + reset_messages!(msgs) return end @@ -449,7 +468,7 @@ function maxsum(graph::Graph, msgs::Messages) end if it >= params.nondec_iterations && (it - params.nondec_iterations) % params.dec_interval == 0 - numdec = clamp(floor(Int, params.dec_fraction * graph.np), 1, msgs.num_nondecimated) + numdec = clamp(floor(Int, params.dec_fraction * graph.np), 1, msgs.num_nondecimated) decimate(numdec, graph, msgs) msgs.num_nondecimated == 0 && break end diff --git a/base/pkg/resolve/versionweight.jl b/base/pkg/resolve/versionweight.jl index 4b93f257f94cd..db7ad88a7e5af 100644 --- a/base/pkg/resolve/versionweight.jl +++ b/base/pkg/resolve/versionweight.jl @@ -68,6 +68,8 @@ Base.:(==){T}(a::HierarchicalValue{T}, b::HierarchicalValue{T}) = cmp(a,b) == 0 Base.abs{T}(a::HierarchicalValue{T}) = HierarchicalValue(T[abs(x) for x in a.v], abs(a.rest)) +Base.copy{T}(a::HierarchicalValue{T}) = HierarchicalValue(T[copy(x) for x in a.v], copy(a.rest)) + struct VWPreBuildItem nonempty::Int s::HierarchicalValue{Int} @@ -96,6 +98,8 @@ Base.:(==)(a::VWPreBuildItem, b::VWPreBuildItem) = cmp(a,b) == 0 Base.abs(a::VWPreBuildItem) = VWPreBuildItem(abs(a.nonempty), abs(a.s), abs(a.i)) +Base.copy(a::VWPreBuildItem) = VWPreBuildItem(a.nonempty, copy(a.s), a.i) + struct VWPreBuild nonempty::Int w::HierarchicalValue{VWPreBuildItem} @@ -151,6 +155,18 @@ function Base.abs(a::VWPreBuild) VWPreBuild(abs(a.nonempty), abs(a.w)) end +function Base.copy(a::VWPreBuild) + a === _vwprebuild_zero && return a + VWPreBuild(a.nonempty, copy(a.w)) +end + +function Base.deepcopy_internal(a::VWPreBuild, dict::ObjectIdDict) + haskey(dict, a) && return dict[a] + b = (a === _vwprebuild_zero) ? _vwprebuild_zero : VWPreBuild(a.nonempty, Base.deepcopy_internal(a.w, dict)) + dict[a] = b + return b +end + # The numeric type used to determine how the different # versions of a package should be weighed struct VersionWeight @@ -200,4 +216,8 @@ Base.abs(a::VersionWeight) = VersionWeight(abs(a.major), abs(a.minor), abs(a.patch), abs(a.prerelease), abs(a.build)) +Base.copy(a::VersionWeight) = + VersionWeight(a.major, a.minor, a.patch, + copy(a.prerelease), copy(a.build)) + end From d31f1967aef2fbcae17e321e9111a87a60519791 Mon Sep 17 00:00:00 2001 From: Isaiah Date: Fri, 21 Apr 2017 21:52:55 -0400 Subject: [PATCH 0501/1534] Export jl_repl_raise_sigtstp so that Ctrl^Z works (#21483) re-fixes #6390 --- ui/repl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/repl.c b/ui/repl.c index 5f8f066cccb46..769f2281cce3e 100644 --- a/ui/repl.c +++ b/ui/repl.c @@ -87,7 +87,7 @@ static int exec_program(char *program) void jl_lisp_prompt(); #ifndef _WIN32 -int jl_repl_raise_sigtstp(void) +JL_DLLEXPORT int jl_repl_raise_sigtstp(void) { return raise(SIGTSTP); } From bd85ce032f55b57b273897333df0e2eba9b853d6 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Fri, 21 Apr 2017 21:48:57 -0400 Subject: [PATCH 0502/1534] Use jl_assume to hint for fast path instead of page_metadata_ext. --- src/gc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/gc.c b/src/gc.c index 18408c6b50b6f..5c16c3ce85602 100644 --- a/src/gc.c +++ b/src/gc.c @@ -602,7 +602,7 @@ STATIC_INLINE void gc_setmark_pool_(jl_ptls_t ptls, jl_taggedvalue_t *o, STATIC_INLINE void gc_setmark_pool(jl_ptls_t ptls, jl_taggedvalue_t *o, uint8_t mark_mode) { - gc_setmark_pool_(ptls, o, mark_mode, page_metadata_ext(o).meta); + gc_setmark_pool_(ptls, o, mark_mode, jl_assume(page_metadata(o))); } STATIC_INLINE void gc_setmark(jl_ptls_t ptls, jl_taggedvalue_t *o, @@ -930,7 +930,7 @@ JL_DLLEXPORT jl_value_t *jl_gc_pool_alloc(jl_ptls_t ptls, int pool_offset, if (__unlikely(gc_page_data(v) != gc_page_data(next))) { // we only update pg's fields when the freelist changes page // since pg's metadata is likely not in cache - jl_gc_pagemeta_t *pg = page_metadata_ext(v).meta; + jl_gc_pagemeta_t *pg = jl_assume(page_metadata(v)); assert(pg->osize == p->osize); pg->nfree = 0; pg->has_young = 1; @@ -947,7 +947,7 @@ JL_DLLEXPORT jl_value_t *jl_gc_pool_alloc(jl_ptls_t ptls, int pool_offset, if (v) { // like the freelist case, // but only update the page metadata when it is full - jl_gc_pagemeta_t *pg = page_metadata_ext((char*)v - 1).meta; + jl_gc_pagemeta_t *pg = jl_assume(page_metadata((char*)v - 1)); assert(pg->osize == p->osize); pg->nfree = 0; pg->has_young = 1; @@ -1220,7 +1220,7 @@ static void gc_sweep_pool(int sweep_full) jl_gc_pool_t *p = &ptls2->heap.norm_pools[i]; jl_taggedvalue_t *last = p->freelist; if (last) { - jl_gc_pagemeta_t *pg = page_metadata_ext(last).meta; + jl_gc_pagemeta_t *pg = jl_assume(page_metadata(last)); gc_pool_sync_nfree(pg, last); pg->has_young = 1; } @@ -1230,7 +1230,7 @@ static void gc_sweep_pool(int sweep_full) last = p->newpages; if (last) { char *last_p = (char*)last; - jl_gc_pagemeta_t *pg = page_metadata_ext(last_p - 1).meta; + jl_gc_pagemeta_t *pg = jl_assume(page_metadata(last_p - 1)); assert(last_p - gc_page_data(last_p - 1) >= GC_PAGE_OFFSET); pg->nfree = (GC_PAGE_SZ - (last_p - gc_page_data(last_p - 1))) / p->osize; pg->has_young = 1; From 89983b4101b8478b54efb3aa4dd7a47d93bf8f0e Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Fri, 21 Apr 2017 21:59:44 -0400 Subject: [PATCH 0503/1534] Fix gc verifier --- src/gc-debug.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/gc-debug.c b/src/gc-debug.c index ef90d9384bd12..93343af3985bb 100644 --- a/src/gc-debug.c +++ b/src/gc-debug.c @@ -97,11 +97,11 @@ void add_lostval_parent(jl_value_t *parent) // the error is caught at the first long collection static arraylist_t bits_save[4]; -static void gc_clear_mark_page(jl_gc_pagemeta_t *pg) +static void gc_clear_mark_page(jl_gc_pagemeta_t *pg, int bits) { jl_ptls_t ptls2 = jl_all_tls_states[pg->thread_n]; jl_gc_pool_t *pool = &ptls2->heap.norm_pools[pg->pool_n]; - pv = (jl_taggedvalue_t*)(pg->data + GC_PAGE_OFFSET); + jl_taggedvalue_t *pv = (jl_taggedvalue_t*)(pg->data + GC_PAGE_OFFSET); char *lim = (char*)pv + GC_PAGE_SZ - GC_PAGE_OFFSET - pool->osize; while ((char*)pv <= lim) { if (!gc_verifying) @@ -111,42 +111,42 @@ static void gc_clear_mark_page(jl_gc_pagemeta_t *pg) } } -static void gc_clear_mark_pagetable0(pagetable0_t *pagetable0) +static void gc_clear_mark_pagetable0(pagetable0_t *pagetable0, int bits) { for (int pg_i = 0; pg_i < REGION0_PG_COUNT / 32; pg_i++) { uint32_t line = pagetable0->allocmap[pg_i]; if (line) { for (int j = 0; j < 32; j++) { if ((line >> j) & 1) { - gc_clear_mark_page(pagetable0->meta[pg_i * 32 + j]); + gc_clear_mark_page(pagetable0->meta[pg_i * 32 + j], bits); } } } } } -static void gc_clear_mark_pagetable1(pagetable1_t *pagetable1) +static void gc_clear_mark_pagetable1(pagetable1_t *pagetable1, int bits) { for (int pg_i = 0; pg_i < REGION1_PG_COUNT / 32; pg_i++) { uint32_t line = pagetable1->allocmap0[pg_i]; if (line) { for (int j = 0; j < 32; j++) { if ((line >> j) & 1) { - gc_clear_mark_pagetable0(pagetable1->meta0[pg_i * 32 + j]); + gc_clear_mark_pagetable0(pagetable1->meta0[pg_i * 32 + j], bits); } } } } } -static void gc_clear_mark_pagetable(void) +static void gc_clear_mark_pagetable(int bits) { for (int pg_i = 0; pg_i < (REGION2_PG_COUNT + 31) / 32; pg_i++) { uint32_t line = memory_map.allocmap1[pg_i]; if (line) { for (int j = 0; j < 32; j++) { if ((line >> j) & 1) { - gc_clear_mark_pagetable1(memory_map.meta1[pg_i * 32 + j]); + gc_clear_mark_pagetable1(memory_map.meta1[pg_i * 32 + j], bits); } } } @@ -184,7 +184,7 @@ static void clear_mark(int bits) v = v->next; } - gc_clear_mark_pagetable(); + gc_clear_mark_pagetable(bits); } static void restore(void) From 81bdedad440623941273b6b492e48e2839c59ccd Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Fri, 21 Apr 2017 22:13:56 -0400 Subject: [PATCH 0504/1534] Use the permgen allocator to allocate page metadata. --- src/datatype.c | 2 +- src/dump.c | 2 +- src/gc-pages.c | 20 +++++++++++--------- src/gc.c | 10 +++++----- src/julia_internal.h | 4 ++-- src/symbol.c | 2 +- 6 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/datatype.c b/src/datatype.c index 69c571aa04c04..a8f1f678c4f71 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -135,7 +135,7 @@ static jl_datatype_layout_t *jl_get_layout(uint32_t nfields, jl_datatype_layout_t *flddesc = (jl_datatype_layout_t*)jl_gc_perm_alloc(sizeof(jl_datatype_layout_t) + nfields * fielddesc_size + - (has_padding ? sizeof(uint32_t) : 0)); + (has_padding ? sizeof(uint32_t) : 0), 0); if (has_padding) { if (first_ptr > UINT16_MAX) first_ptr = UINT16_MAX; diff --git a/src/dump.c b/src/dump.c index 1874926fddec0..1293667f5a37b 100644 --- a/src/dump.c +++ b/src/dump.c @@ -1502,7 +1502,7 @@ static jl_value_t *jl_deserialize_datatype(jl_serializer_state *s, int pos, jl_v size_t fielddesc_size = nf > 0 ? jl_fielddesc_size(fielddesc_type) : 0; jl_datatype_layout_t *layout = (jl_datatype_layout_t*)jl_gc_perm_alloc( sizeof(jl_datatype_layout_t) + nf * fielddesc_size + - (has_padding ? sizeof(uint32_t) : 0)); + (has_padding ? sizeof(uint32_t) : 0), 0); if (has_padding) { layout = (jl_datatype_layout_t*)(((char*)layout) + sizeof(uint32_t)); jl_datatype_layout_n_nonptr(layout) = read_int32(s->s); diff --git a/src/gc-pages.c b/src/gc-pages.c index aecf418e1ba29..7c6cda248e453 100644 --- a/src/gc-pages.c +++ b/src/gc-pages.c @@ -19,7 +19,6 @@ extern "C" { #define MIN_BLOCK_PG_ALLOC (1) // 16 KB static int block_pg_cnt = DEFAULT_BLOCK_PG_ALLOC; -static jl_mutex_t pagealloc_lock; static size_t current_pg_count = 0; void jl_gc_init_page(void) @@ -62,7 +61,7 @@ static char *jl_gc_try_alloc_pages(int pg_cnt) // more chunks (or other allocations). The final page count is recorded // and will be used as the starting count next time. If the page count is // smaller `MIN_BLOCK_PG_ALLOC` a `jl_memory_exception` is thrown. -// Assumes `pagealloc_lock` is acquired, the lock is released before the +// Assumes `gc_perm_lock` is acquired, the lock is released before the // exception is thrown. static jl_gc_pagemeta_t *jl_gc_alloc_new_page(void) { @@ -83,7 +82,7 @@ static jl_gc_pagemeta_t *jl_gc_alloc_new_page(void) block_pg_cnt = pg_cnt = min_block_pg_alloc; } else { - JL_UNLOCK_NOGC(&pagealloc_lock); + JL_UNLOCK_NOGC(&gc_perm_lock); jl_throw(jl_memory_exception); } } @@ -91,7 +90,8 @@ static jl_gc_pagemeta_t *jl_gc_alloc_new_page(void) // now need to insert these pages into the pagetable metadata // if any allocation fails, this just stops recording more pages from that point // and will free (munmap) the remainder - jl_gc_pagemeta_t *page_meta = (jl_gc_pagemeta_t*)calloc(pg_cnt, sizeof(jl_gc_pagemeta_t)); + jl_gc_pagemeta_t *page_meta = + (jl_gc_pagemeta_t*)jl_gc_perm_alloc_nolock(pg_cnt * sizeof(jl_gc_pagemeta_t), 1); pg = 0; if (page_meta) { for (; pg < pg_cnt; pg++) { @@ -114,7 +114,8 @@ static jl_gc_pagemeta_t *jl_gc_alloc_new_page(void) memory_map.freemap1[info.pagetable_i32] |= msk; // has free info.pagetable1 = *(ppagetable1 = &memory_map.meta1[i]); if (!info.pagetable1) { - info.pagetable1 = (*ppagetable1 = (pagetable1_t*)calloc(1, sizeof(pagetable1_t))); + info.pagetable1 = (pagetable1_t*)jl_gc_perm_alloc_nolock(sizeof(pagetable1_t), 1); + *ppagetable1 = info.pagetable1; if (!info.pagetable1) break; } @@ -128,7 +129,8 @@ static jl_gc_pagemeta_t *jl_gc_alloc_new_page(void) info.pagetable1->freemap0[info.pagetable1_i32] |= msk; // has free info.pagetable0 = *(ppagetable0 = &info.pagetable1->meta0[i]); if (!info.pagetable0) { - info.pagetable0 = (*ppagetable0 = (pagetable0_t*)calloc(1, sizeof(pagetable0_t))); + info.pagetable0 = (pagetable0_t*)jl_gc_perm_alloc_nolock(sizeof(pagetable0_t), 1); + *ppagetable0 = info.pagetable0; if (!info.pagetable0) break; } @@ -154,7 +156,7 @@ static jl_gc_pagemeta_t *jl_gc_alloc_new_page(void) GC_PAGE_SZ * pg_cnt - LLT_ALIGN(GC_PAGE_SZ * pg, jl_page_size)); #endif if (pg == 0) { - JL_UNLOCK_NOGC(&pagealloc_lock); + JL_UNLOCK_NOGC(&gc_perm_lock); jl_throw(jl_memory_exception); } } @@ -166,7 +168,7 @@ static jl_gc_pagemeta_t *jl_gc_alloc_new_page(void) NOINLINE jl_gc_pagemeta_t *jl_gc_alloc_page(void) { struct jl_gc_metadata_ext info; - JL_LOCK_NOGC(&pagealloc_lock); + JL_LOCK_NOGC(&gc_perm_lock); // scan over memory_map page-table for existing allocated but unused pages for (info.pagetable_i32 = memory_map.lb; info.pagetable_i32 < (REGION2_PG_COUNT + 31) / 32; info.pagetable_i32++) { @@ -242,7 +244,7 @@ NOINLINE jl_gc_pagemeta_t *jl_gc_alloc_page(void) #endif current_pg_count++; gc_final_count_page(current_pg_count); - JL_UNLOCK_NOGC(&pagealloc_lock); + JL_UNLOCK_NOGC(&gc_perm_lock); return info.meta; } diff --git a/src/gc.c b/src/gc.c index 5c16c3ce85602..9adea74dfa25c 100644 --- a/src/gc.c +++ b/src/gc.c @@ -2366,13 +2366,13 @@ static char *gc_perm_pool = NULL; static size_t gc_perm_size = 0; // **NOT** a safepoint -void *jl_gc_perm_alloc_nolock(size_t sz) +void *jl_gc_perm_alloc_nolock(size_t sz, int zero) { // The caller should have acquired `gc_perm_lock` #ifndef MEMDEBUG if (__unlikely(sz > GC_PERM_POOL_LIMIT)) #endif - return malloc(sz); + return zero ? calloc(1, sz) : malloc(sz); sz = LLT_ALIGN(sz, JL_SMALL_BYTE_ALIGNMENT); if (__unlikely(sz > gc_perm_size)) { #ifdef _OS_WINDOWS_ @@ -2399,14 +2399,14 @@ void *jl_gc_perm_alloc_nolock(size_t sz) } // **NOT** a safepoint -void *jl_gc_perm_alloc(size_t sz) +void *jl_gc_perm_alloc(size_t sz, int zero) { #ifndef MEMDEBUG if (__unlikely(sz > GC_PERM_POOL_LIMIT)) #endif - return malloc(sz); + return zero ? calloc(1, sz) : malloc(sz); JL_LOCK_NOGC(&gc_perm_lock); - void *p = jl_gc_perm_alloc_nolock(sz); + void *p = jl_gc_perm_alloc_nolock(sz, zero); JL_UNLOCK_NOGC(&gc_perm_lock); return p; } diff --git a/src/julia_internal.h b/src/julia_internal.h index fd931962af465..d9305cacedd93 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -127,8 +127,8 @@ JL_DLLEXPORT jl_value_t *jl_gc_pool_alloc(jl_ptls_t ptls, int pool_offset, JL_DLLEXPORT jl_value_t *jl_gc_big_alloc(jl_ptls_t ptls, size_t allocsz); int jl_gc_classify_pools(size_t sz, int *osize); extern jl_mutex_t gc_perm_lock; -void *jl_gc_perm_alloc_nolock(size_t sz); -void *jl_gc_perm_alloc(size_t sz); +void *jl_gc_perm_alloc_nolock(size_t sz, int zero); +void *jl_gc_perm_alloc(size_t sz, int zero); // pools are 16376 bytes large (GC_POOL_SZ - GC_PAGE_OFFSET) static const int jl_gc_sizeclasses[JL_GC_N_POOLS] = { diff --git a/src/symbol.c b/src/symbol.c index 4950b1163a1a6..7b9f5116230cd 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -32,7 +32,7 @@ static jl_sym_t *mk_symbol(const char *str, size_t len) jl_sym_t *sym; size_t nb = symbol_nbytes(len); - jl_taggedvalue_t *tag = (jl_taggedvalue_t*)jl_gc_perm_alloc_nolock(nb); + jl_taggedvalue_t *tag = (jl_taggedvalue_t*)jl_gc_perm_alloc_nolock(nb, 0); sym = (jl_sym_t*)jl_valueof(tag); // set to old marked since we don't need write barrier on it. tag->header = ((uintptr_t)jl_sym_type) | GC_OLD_MARKED; From b26d120befde47ff0da6dbd1eb0e6f254c8c9f32 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Sat, 22 Apr 2017 00:13:15 -0400 Subject: [PATCH 0505/1534] fix off-by-one in gc_page_free fix #21470 --- src/gc-pages.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/gc-pages.c b/src/gc-pages.c index aecf418e1ba29..6ad48a9764be5 100644 --- a/src/gc-pages.c +++ b/src/gc-pages.c @@ -277,13 +277,14 @@ void jl_gc_free_page(void *p) // ensure so we don't release more memory than intended size_t n_pages = jl_page_size / GC_PAGE_SZ; // exact division decommit_size = jl_page_size; - p = (void*)((uintptr_t)p & ~(jl_page_size - 1)); // round down to the nearest physical page + void *otherp = (void*)((uintptr_t)p & ~(jl_page_size - 1)); // round down to the nearest physical page + p = otherp; while (n_pages--) { - struct jl_gc_metadata_ext info = page_metadata_ext(p); + struct jl_gc_metadata_ext info = page_metadata_ext(otherp); msk = (uint32_t)(1 << info.pagetable0_i); if (info.pagetable0->allocmap[info.pagetable0_i32] & msk) goto no_decommit; - p = (void*)((char*)p + GC_PAGE_SZ); + otherp = (void*)((char*)otherp + GC_PAGE_SZ); } } #ifdef _OS_WINDOWS_ From 4c7b4f180c8b3e5d332cd4dba43ea2897f9d77ff Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 21 Apr 2017 15:43:55 -0400 Subject: [PATCH 0506/1534] remove manual memory-management from Timer and AsyncConditional fixes a potential resource leak with a repeating timer and is just generally less finicky --- base/event.jl | 82 ++++++++++++++++++++++++-------------------------- base/libuv.jl | 1 - test/pollfd.jl | 20 +++++++++++- 3 files changed, 59 insertions(+), 44 deletions(-) diff --git a/base/event.jl b/base/event.jl index 940340ec162c4..8a5167d047f5f 100644 --- a/base/event.jl +++ b/base/event.jl @@ -238,41 +238,24 @@ Use [`isopen`](@ref) to check whether it is still active. mutable struct AsyncCondition handle::Ptr{Void} cond::Condition + isopen::Bool function AsyncCondition() - this = new(Libc.malloc(_sizeof_uv_async), Condition()) + this = new(Libc.malloc(_sizeof_uv_async), Condition(), true) associate_julia_struct(this.handle, this) - preserve_handle_new(this) + finalizer(this, uvfinalize) err = ccall(:uv_async_init, Cint, (Ptr{Void}, Ptr{Void}, Ptr{Void}), eventloop(), this, uv_jl_asynccb::Ptr{Void}) - this + if err != 0 + #TODO: this codepath is currently not tested + Libc.free(this.handle) + this.handle = C_NULL + throw(UVError("uv_async_init", err)) + end + return this end end -unsafe_convert(::Type{Ptr{Void}}, async::AsyncCondition) = async.handle - -function wait(async::AsyncCondition) - isopen(async) || throw(EOFError()) - wait(async.cond) -end - -isopen(t::AsyncCondition) = (t.handle != C_NULL) - -close(t::AsyncCondition) = ccall(:jl_close_uv, Void, (Ptr{Void},), t) - -function _uv_hook_close(async::AsyncCondition) - async.handle = C_NULL - unpreserve_handle(async) - notify_error(async.cond, EOFError()) - nothing -end - -function uv_asynccb(handle::Ptr{Void}) - async = @handle_as handle AsyncCondition - notify(async.cond) - nothing -end - """ AsyncCondition(callback::Function) @@ -286,8 +269,8 @@ function AsyncCondition(cb::Function) success = try wait(async) true - catch # ignore possible exception on close() - false + catch exc # ignore possible exception on close() + isa(exc, EOFError) || rethrow(exc) end success && cb(async) end @@ -323,11 +306,11 @@ mutable struct Timer #TODO: this codepath is currently not tested Libc.free(this.handle) this.handle = C_NULL - throw(UVError("uv_make_timer",err)) + throw(UVError("uv_timer_init", err)) end associate_julia_struct(this.handle, this) - preserve_handle_new(this) + finalizer(this, uvfinalize) ccall(:uv_update_time, Void, (Ptr{Void},), eventloop()) ccall(:uv_timer_start, Cint, (Ptr{Void}, Ptr{Void}, UInt64, UInt64), @@ -338,32 +321,46 @@ mutable struct Timer end unsafe_convert(::Type{Ptr{Void}}, t::Timer) = t.handle +unsafe_convert(::Type{Ptr{Void}}, async::AsyncCondition) = async.handle -function wait(t::Timer) +function wait(t::Union{Timer, AsyncCondition}) isopen(t) || throw(EOFError()) - wait(t.cond) + stream_wait(t, t.cond) end -isopen(t::Timer) = t.isopen +isopen(t::Union{Timer, AsyncCondition}) = t.isopen -function close(t::Timer) - if t.handle != C_NULL +function close(t::Union{Timer, AsyncCondition}) + if t.handle != C_NULL && isopen(t) t.isopen = false - ccall(:uv_timer_stop, Cint, (Ptr{Void},), t) + isa(t, Timer) && ccall(:uv_timer_stop, Cint, (Ptr{Void},), t) ccall(:jl_close_uv, Void, (Ptr{Void},), t) end nothing end -function _uv_hook_close(t::Timer) - unpreserve_handle(t) - disassociate_julia_struct(t) - t.handle = C_NULL +function uvfinalize(t::Union{Timer, AsyncCondition}) + if t.handle != C_NULL + disassociate_julia_struct(t.handle) # not going to call the usual close hooks + close(t) + t.handle = C_NULL + end t.isopen = false + nothing +end + +function _uv_hook_close(t::Union{Timer, AsyncCondition}) + uvfinalize(t) notify_error(t.cond, EOFError()) nothing end +function uv_asynccb(handle::Ptr{Void}) + async = @handle_as handle AsyncCondition + notify(async.cond) + nothing +end + function uv_timercb(handle::Ptr{Void}) t = @handle_as handle Timer if ccall(:uv_timer_get_repeat, UInt64, (Ptr{Void},), t) == 0 @@ -403,7 +400,8 @@ function Timer(cb::Function, timeout::Real, repeat::Real=0.0) success = try wait(t) true - catch # ignore possible exception on close() + catch exc # ignore possible exception on close() + isa(exc, EOFError) || rethrow(exc) false end success && cb(t) diff --git a/base/libuv.jl b/base/libuv.jl index 1037e7ce03d9c..35677c54d89dc 100644 --- a/base/libuv.jl +++ b/base/libuv.jl @@ -49,7 +49,6 @@ disassociate_julia_struct(handle::Ptr{Void}) = # and should thus not be garbage collected const uvhandles = ObjectIdDict() preserve_handle(x) = uvhandles[x] = get(uvhandles,x,0)::Int+1 -preserve_handle_new(x) = uvhandles[x] = 1 unpreserve_handle(x) = (v = uvhandles[x]::Int; v == 1 ? pop!(uvhandles,x) : (uvhandles[x] = v-1); nothing) ## Libuv error handling ## diff --git a/test/pollfd.jl b/test/pollfd.jl index 7051c2fc1739d..7c7fe9359d784 100644 --- a/test/pollfd.jl +++ b/test/pollfd.jl @@ -123,7 +123,25 @@ end # issue #12473 # make sure 1-shot timers work let a = [] - Timer(t->push!(a, 1), 0.01, 0) + Timer(t -> push!(a, 1), 0.01, 0) sleep(0.2) @test a == [1] end + +# make sure repeating timers work +@noinline function make_unrooted_timer(a) + t = Timer(0.0, 0.1) + finalizer(t, t -> a[] += 1) + wait(t) + e = @elapsed for i = 1:5 + wait(t) + end + @test 1.5 > e > 0.5 + @test a[] == 0 + nothing +end +let a = Ref(0) + make_unrooted_timer(a) + gc() + @test a[] == 1 +end From 3d207665461f4a18916253c827fca37638d01722 Mon Sep 17 00:00:00 2001 From: Kiaran B Dave Date: Fri, 20 Jan 2017 14:45:28 -0500 Subject: [PATCH 0507/1534] documentation for environment variables small typo forgot about make.jl Line width to 80 characters; strip trailing spaces; line breaks after h3 added threading/debugging entries and cross-references. Increase text width to 92 columns, cull spurious line breaks, switch to admonition syntax, simplify cross-references, fix title. Trailing whitespace Admonition line breaks; editor envvar heading. clarify integer types, remove outdated notes, whitespace change whitespace No windows shell, English fixes, delete reference to base, clarify 'r', julia-debug. --- doc/make.jl | 1 + doc/src/index.md | 1 + doc/src/manual/environment-variables.md | 313 ++++++++++++++++++++++++ doc/src/manual/index.md | 1 + 4 files changed, 316 insertions(+) create mode 100644 doc/src/manual/environment-variables.md diff --git a/doc/make.jl b/doc/make.jl index 4ef4222db9e8f..92a98912d4dc7 100644 --- a/doc/make.jl +++ b/doc/make.jl @@ -46,6 +46,7 @@ const PAGES = [ "manual/running-external-programs.md", "manual/calling-c-and-fortran-code.md", "manual/handling-operating-system-variation.md", + "manual/environment-variables.md", "manual/interacting-with-julia.md", "manual/embedding.md", "manual/packages.md", diff --git a/doc/src/index.md b/doc/src/index.md index bdfb34252e42d..deca430af0046 100644 --- a/doc/src/index.md +++ b/doc/src/index.md @@ -28,6 +28,7 @@ * [Running External Programs](@ref) * [Calling C and Fortran Code](@ref) * [Handling Operating System Variation](@ref) + * [Environment Variables](@ref) * [Interacting With Julia](@ref) * [Embedding Julia](@ref) * [Packages](@ref) diff --git a/doc/src/manual/environment-variables.md b/doc/src/manual/environment-variables.md new file mode 100644 index 0000000000000..c2b00b5789e97 --- /dev/null +++ b/doc/src/manual/environment-variables.md @@ -0,0 +1,313 @@ +# Environment Variables + +The environment variables that Julia uses generally start with `JULIA`. If +[`Base.versioninfo`](@ref) is called with `verbose` equal to `true`, then the output will +list all environment variables for which `JULIA` appears in the name. + +## File locations + +### `JULIA_HOME` + +The absolute path of the directory containing the Julia executable, which sets the global +variable [`Base.JULIA_HOME`](@ref). If `$JULIA_HOME` is not set, then `Base.JULIA_HOME` +defaults to its compile-time value. + +The executable itself is one of + +``` +$JULIA_HOME/julia +$JULIA_HOME/julia-debug +``` + +by default. + +The global variable `Base.DATAROOTDIR` determines a relative path from `Base.JULIA_HOME` to +the data directory associated with Julia. Then the path + +``` +$JULIA_HOME/$DATAROOTDIR/julia/base +``` + +determines the directory in which Julia initially searches for source files (via +`Base.find_source_file()`). + +Likewise, the global variable `Base.SYSCONFDIR` determines a relative path to the +configuration file directory. Then Julia searches for a `juliarc.jl` file at + +``` +$JULIA_HOME/$SYSCONFDIR/julia/juliarc.jl +$JULIA_HOME/../etc/julia/juliarc.jl +``` + +by default (via `Base.load_juliarc()`). + +For example, a Linux installation with a Julia executable located at `/bin/julia`, +a `DATAROOTDIR` of `../share`, and a `SYSCONFDIR` of `../etc` will have `JULIA_HOME` set to +`/bin`, a source-file search path of + +``` +/share/julia/base +``` + +and a global configuration search path of + +``` +/etc/julia/juliarc.jl +``` + +### `JULIA_LOAD_PATH` + +A separated list of absolute paths that are to be appended to the variable +[`Base.LOAD_PATH`](@ref). (In Unix-like systems, the path separator is `:`; in Windows +systems, the path separator is `;`.) The `Base.LOAD_PATH` variable is where +[`Base.require`](@ref) and `Base.load_in_path()` look for code; it defaults to the absolute +paths + +``` +$JULIA_HOME/../local/share/julia/site/v$(Base.VERSION.major).$(Base.VERSION.minor) +$JULIA_HOME/../share/julia/site/v$(Base.VERSION.major).$(Base.VERSION.minor) +``` + +so that, e.g., version 0.5 of Julia on a Linux system with a Julia executable at +`/bin/julia` will have a default `Base.LOAD_PATH` of + +``` +/local/share/julia/site/v0.5 +/share/julia/site/v0.5 +``` + +### `JULIA_PKGDIR` + +The path of the parent directory `Dir._pkgroot()` for the version-specific Julia package +repositories. If the path is relative, then it is taken with respect to the working +directory. If `$JULIA_PKGDIR` is not set, then `_pkgroot()` defaults to + +``` +$HOME/.julia +``` + +Then the repository location [`Base.Pkg.dir`](@ref) for a given Julia version is + +``` +$JULIA_PKGDIR/v$(Base.VERSION.major).$(Base.VERSION.minor) +``` + +For example, for a Linux user whose home directory is `/home/alice`, the directory +containing the package repositories would by default be + +``` +/home/alice/.julia +``` + +and the package repository for version 0.5 of Julia would be + +``` +/home/alice/.julia/v0.5 +``` + +### `JULIA_HISTORY` + +The absolute path `Base.find_hist_file()` of the REPL's history file. If `$JULIA_HISTORY` is +not set, then `Base.find_hist_file()` defaults to + +``` +$HOME/.julia_history +``` + +### `JULIA_PKGRESOLVE_ACCURACY` + +A positive `Int` that determines how much time the max-sum subroutine `MaxSum.maxsum()` of +the package dependency resolver [`Base.Pkg.resolve`](@ref) will devote to attempting +satisfying constraints before giving up: this value is by default `1`, and larger values +correspond to larger amounts of time. + +Suppose the value of `$JULIA_PKGRESOLVE_ACCURACY` is `n`. Then + +* the number of pre-decimation iterations is `20*n`, +* the number of iterations between decimation steps is `10*n`, and +* at decimation steps, at most one in every `20*n` packages is decimated. + +## External applications + +### `JULIA_SHELL` + +The absolute path of the shell with which Julia should execute external commands (via +`Base.repl_cmd()`). Defaults to the environment variable `$SHELL`, and falls back to +`/bin/sh` if `$SHELL` is unset. + +!!! note + + On Windows, this environment variable is ignored, and external commands are executed + directly. + +### `JULIA_EDITOR` + +The editor returned by `Base.editor()` and used in, e.g., [`Base.edit`](@ref). + +`$JULIA_EDITOR` takes precedence over `$VISUAL`, which in turn takes precedence over +`$EDITOR`. If none of these environment variables is set, then the editor is taken to be +`open` on Windows and OS X, or `/etc/alternatives/editor` if it exists, or `emacs` +otherwise. + +!!! note + + `$JULIA_EDITOR` is *not* used in the determination of the editor for + [`Base.Pkg.edit`](@ref): this function checks `$VISUAL` and `$EDITOR` alone. + +## Parallelization + +### `JULIA_CPU_CORES` + +Overrides the global variable [`Base.Sys.CPU_CORES`](@ref), the number of logical CPU cores +available. + +### `JULIA_WORKER_TIMEOUT` + +A `Float64` that sets the value of `Base.worker_timeout()` (default: `60.0`). This function +gives the number of seconds a worker process will wait for a master process to establish +a connection before dying. + +### `JULIA_NUM_THREADS` + +An unsigned 64-bit integer (`uint64_t`) that sets the maximum number of threads available to +Julia. If `$JULIA_NUM_THREADS` exceeds the number of available physical CPU cores, then the +number of threads is set to the number of cores. If `$JULIA_NUM_THREADS` is not positive or +is not set, or if the number of CPU cores cannot be determined through system calls, then +the number of threads is set to `1`. + +### `JULIA_THREAD_SLEEP_THRESHOLD` + +If set to a string that starts with the case-insensitive substring `"infinite"`, then +spinning threads never sleep. Otherwise, `$JULIA_THREAD_SLEEP_THRESHOLD` is interpreted as +an unsigned 64-bit integer (`uint64_t`) and gives, in nanoseconds, the amount of time after +which spinning threads should sleep. + +### `JULIA_EXCLUSIVE` + +If set to anything besides `0`, then Julia's thread policy is consistent with running on +a dedicated machine: the master thread is on proc 0, and threads are affinitized. Otherwise, +Julia lets the operating system handle thread policy. + +## REPL formatting + +Environment variables that determine how REPL output should be formatted at the terminal. +Generally, these variables should be set to [ANSI terminal escape +sequences](http://ascii-table.com/ansi-escape-sequences.php). Julia provides a high-level +interface with much of the same functionality: see the section on [Interacting With +Julia](@ref). + +### `JULIA_ERROR_COLOR` + +The formatting `Base.error_color()` (default: light red, `"\033[91m"`) that errors should +have at the terminal. + +### `JULIA_WARN_COLOR` + +The formatting `Base.warn_color()` (default: yellow, `"\033[93m"`) that warnings should have +at the terminal. + +### `JULIA_INFO_COLOR` + +The formatting `Base.info_color()` (default: cyan, `"\033[36m"`) that info should have at +the terminal. + +### `JULIA_INPUT_COLOR` + +The formatting `Base.input_color()` (default: normal, `"\033[0m"`) that input should have at +the terminal. + +### `JULIA_ANSWER_COLOR` + +The formatting `Base.answer_color()` (default: normal, `"\033[0m"`) that output should have +at the terminal. + +### `JULIA_STACKFRAME_LINEINFO_COLOR` + +The formatting `Base.stackframe_lineinfo_color()` (default: bold, `"\033[1m"`) that line +info should have during a stack trace at the terminal. + +### `JULIA_STACKFRAME_FUNCTION_COLOR` + +The formatting `Base.stackframe_function_color()` (default: bold, `"\033[1m"`) that function +calls should have during a stack trace at the terminal. + +## Debugging and profiling + +### `JULIA_GC_ALLOC_POOL`, `JULIA_GC_ALLOC_OTHER`, `JULIA_GC_ALLOC_PRINT` + +If set, these environment variables take strings that optionally start with the character +`'r'`, followed by a string interpolation of a colon-separated list of three signed 64-bit +integers (`int64_t`). This triple of integers `a:b:c` represents the arithmetic sequence +`a`, `a + b`, `a + 2*b`, ... `c`. + +* If it's the `n`th time that `jl_gc_pool_alloc()` has been called, and `n` belongs to the + arithmetic sequence represented by `$JULIA_GC_ALLOC_POOL`, then garbage collection is + forced. +* If it's the `n`th time that `maybe_collect()` has been called, and `n` belongs to the + arithmetic sequence represented by `$JULIA_GC_ALLOC_OTHER`, then garbage collection is + forced. +* If it's the `n`th time that `jl_gc_collect()` has been called, and `n` belongs to the + arithmetic sequence represented by `$JULIA_GC_ALLOC_PRINT`, then counts for the number + of calls to `jl_gc_pool_alloc()` and `maybe_collect()` are printed. + +If the value of the environment variable begins with the character `'r'`, then the interval +between garbage collection events is randomized. + +!!! note + + These environment variables only have an effect if Julia was compiled with + garbage-collection debugging (that is, if `WITH_GC_DEBUG_ENV` is set to `1` in the build + configuration). + +### `JULIA_GC_NO_GENERATIONAL` + +If set to anything besides `0`, then the Julia garbage collector never performs "quick +sweeps" of memory. + +!!! note + + This environment variable only has an effect if Julia was compiled with + garbage-collection debugging (that is, if `WITH_GC_DEBUG_ENV` is set to `1` in the build + configuration). + +### `JULIA_GC_WAIT_FOR_DEBUGGER` + +If set to anything besides `0`, then the Julia garbage collector will wait for the debugger +to attach instead of aborting whenever there's a critical error. + +!!! note + + This environment variable only has an effect if Julia was compiled with + garbage-collection debugging (that is, if `WITH_GC_DEBUG_ENV` is set to `1` in the build + configuration). + +### `ENABLE_JITPROFILING` + +If set to anything besides `0`, then the compiler will create and register an event listener +for just-in-time (JIT) profiling. + +!!! note + + This environment variable only has an effect if Julia was compiled with JIT profiling + support, using either + +* Intel's [VTune™ Amplifier](https://software.intel.com/en-us/intel-vtune-amplifier-xe) + (`USE_INTEL_JITEVENTS` set to `1` in the build configuration), or +* [OProfile](http://oprofile.sourceforge.net/news/) (`USE_OPROFILE_JITEVENTS` set to `1` + in the build configuration). + +### `JULIA_LLVM_ARGS` + +Arguments to be passed to the LLVM backend. + +!!! note + + This environment variable has an effect only if Julia was compiled with `JL_DEBUG_BUILD` + set—in particular, the `julia-debug` executable is always compiled with this build + variable. + +### `JULIA_DEBUG_LOADING` + +If set, then Julia prints detailed information about the cache in the loading process of +[`Base.require`](@ref). + diff --git a/doc/src/manual/index.md b/doc/src/manual/index.md index c516ad473e0e8..37a8b0b67862e 100644 --- a/doc/src/manual/index.md +++ b/doc/src/manual/index.md @@ -26,6 +26,7 @@ * [Running External Programs](@ref) * [Calling C and Fortran Code](@ref) * [Handling Operating System Variation](@ref) + * [Environment Variables](@ref) * [Interacting With Julia](@ref) * [Embedding Julia](@ref) * [Packages](@ref) From a8de1ac42f061355939258aa918122800d25d9b7 Mon Sep 17 00:00:00 2001 From: m-j-w Date: Fri, 21 Apr 2017 23:16:16 +0200 Subject: [PATCH 0508/1534] Made remaining changes of kbdave314's PR. Please take into account that this file was originally authored by kbdave314. - Explain how to set environment variables (fredrikekre) - Corrected `Base.REPL.find_history_file()` (GregPlowman) - Mentioned editor is a command with vim as example (yuyichao) Also made it stick to 80 character text width. Implemented review comments of tkelman - JULIA_HOME determined at run-time. - added `Pkg` to `Dir...` - removed `Base` from `Base.Pkg....`, `Base.VERSION....` and `Base.LOAD_PATH`. - "a debugger" - whitespace " - " Made 'make docs' work again...by removing the faulty reference to JULIA_HOME introduced by myself. - clarified output of environment variables. - removed a blank Bumped mentioned versions to 0.6 - its a 0.6 documentation after all. Squashed commits to one for each author. --- doc/src/manual/environment-variables.md | 240 +++++++++++++----------- 1 file changed, 127 insertions(+), 113 deletions(-) diff --git a/doc/src/manual/environment-variables.md b/doc/src/manual/environment-variables.md index c2b00b5789e97..bbb2c41e27a91 100644 --- a/doc/src/manual/environment-variables.md +++ b/doc/src/manual/environment-variables.md @@ -1,16 +1,26 @@ # Environment Variables +Julia may be configured with a number of environment variables, either in the +usual way of the operating system, or in a portable way from within Julia. +Suppose you want to set the environment variable `JULIA_EDITOR` to +`vim`, then either type `ENV["JULIA_EDITOR"] = "vim"` for instance in the REPL +to make this change on a case by case basis, or add the same to the user +configuration file `.juliarc.jl` in the user's home directory to have +a permanent effect. The current value of the same environment variable is +determined by evaluating `ENV["JULIA_EDITOR"]`. + The environment variables that Julia uses generally start with `JULIA`. If -[`Base.versioninfo`](@ref) is called with `verbose` equal to `true`, then the output will -list all environment variables for which `JULIA` appears in the name. +[`Base.versioninfo`](@ref) is called with `verbose` equal to `true`, then the +output will list defined environment variables relevant for Julia, including +those for which `JULIA` appears in the name. ## File locations ### `JULIA_HOME` -The absolute path of the directory containing the Julia executable, which sets the global -variable [`Base.JULIA_HOME`](@ref). If `$JULIA_HOME` is not set, then `Base.JULIA_HOME` -defaults to its compile-time value. +The absolute path of the directory containing the Julia executable, which sets +the global variable [`Base.JULIA_HOME`](@ref). If `$JULIA_HOME` is not set, then +Julia determines the value `Base.JULIA_HOME` at run-time. The executable itself is one of @@ -21,8 +31,8 @@ $JULIA_HOME/julia-debug by default. -The global variable `Base.DATAROOTDIR` determines a relative path from `Base.JULIA_HOME` to -the data directory associated with Julia. Then the path +The global variable `Base.DATAROOTDIR` determines a relative path from +`Base.JULIA_HOME` to the data directory associated with Julia. Then the path ``` $JULIA_HOME/$DATAROOTDIR/julia/base @@ -41,9 +51,9 @@ $JULIA_HOME/../etc/julia/juliarc.jl by default (via `Base.load_juliarc()`). -For example, a Linux installation with a Julia executable located at `/bin/julia`, -a `DATAROOTDIR` of `../share`, and a `SYSCONFDIR` of `../etc` will have `JULIA_HOME` set to -`/bin`, a source-file search path of +For example, a Linux installation with a Julia executable located at +`/bin/julia`, a `DATAROOTDIR` of `../share`, and a `SYSCONFDIR` of `../etc` will +have `JULIA_HOME` set to `/bin`, a source-file search path of ``` /share/julia/base @@ -58,38 +68,39 @@ and a global configuration search path of ### `JULIA_LOAD_PATH` A separated list of absolute paths that are to be appended to the variable -[`Base.LOAD_PATH`](@ref). (In Unix-like systems, the path separator is `:`; in Windows -systems, the path separator is `;`.) The `Base.LOAD_PATH` variable is where +[`LOAD_PATH`](@ref). (In Unix-like systems, the path separator is `:`; in Windows +systems, the path separator is `;`.) The `LOAD_PATH` variable is where [`Base.require`](@ref) and `Base.load_in_path()` look for code; it defaults to the absolute paths ``` -$JULIA_HOME/../local/share/julia/site/v$(Base.VERSION.major).$(Base.VERSION.minor) -$JULIA_HOME/../share/julia/site/v$(Base.VERSION.major).$(Base.VERSION.minor) +$JULIA_HOME/../local/share/julia/site/v$(VERSION.major).$(VERSION.minor) +$JULIA_HOME/../share/julia/site/v$(VERSION.major).$(VERSION.minor) ``` -so that, e.g., version 0.5 of Julia on a Linux system with a Julia executable at -`/bin/julia` will have a default `Base.LOAD_PATH` of +so that, e.g., version 0.6 of Julia on a Linux system with a Julia executable at +`/bin/julia` will have a default `LOAD_PATH` of ``` -/local/share/julia/site/v0.5 -/share/julia/site/v0.5 +/local/share/julia/site/v0.6 +/share/julia/site/v0.6 ``` ### `JULIA_PKGDIR` -The path of the parent directory `Dir._pkgroot()` for the version-specific Julia package -repositories. If the path is relative, then it is taken with respect to the working -directory. If `$JULIA_PKGDIR` is not set, then `_pkgroot()` defaults to +The path of the parent directory `Pkg.Dir._pkgroot()` for the version-specific +Julia package repositories. If the path is relative, then it is taken with +respect to the working directory. If `$JULIA_PKGDIR` is not set, then +`Pkg.Dir._pkgroot()` defaults to ``` $HOME/.julia ``` -Then the repository location [`Base.Pkg.dir`](@ref) for a given Julia version is +Then the repository location [`Pkg.dir`](@ref) for a given Julia version is ``` -$JULIA_PKGDIR/v$(Base.VERSION.major).$(Base.VERSION.minor) +$JULIA_PKGDIR/v$(VERSION.major).$(VERSION.minor) ``` For example, for a Linux user whose home directory is `/home/alice`, the directory @@ -99,16 +110,16 @@ containing the package repositories would by default be /home/alice/.julia ``` -and the package repository for version 0.5 of Julia would be +and the package repository for version 0.6 of Julia would be ``` -/home/alice/.julia/v0.5 +/home/alice/.julia/v0.6 ``` ### `JULIA_HISTORY` -The absolute path `Base.find_hist_file()` of the REPL's history file. If `$JULIA_HISTORY` is -not set, then `Base.find_hist_file()` defaults to +The absolute path `Base.REPL.find_hist_file()` of the REPL's history file. If +`$JULIA_HISTORY` is not set, then `Base.REPL.find_hist_file()` defaults to ``` $HOME/.julia_history @@ -116,10 +127,10 @@ $HOME/.julia_history ### `JULIA_PKGRESOLVE_ACCURACY` -A positive `Int` that determines how much time the max-sum subroutine `MaxSum.maxsum()` of -the package dependency resolver [`Base.Pkg.resolve`](@ref) will devote to attempting -satisfying constraints before giving up: this value is by default `1`, and larger values -correspond to larger amounts of time. +A positive `Int` that determines how much time the max-sum subroutine +`MaxSum.maxsum()` of the package dependency resolver [`Base.Pkg.resolve`](@ref) +will devote to attempting satisfying constraints before giving up: this value is +by default `1`, and larger values correspond to larger amounts of time. Suppose the value of `$JULIA_PKGRESOLVE_ACCURACY` is `n`. Then @@ -131,23 +142,24 @@ Suppose the value of `$JULIA_PKGRESOLVE_ACCURACY` is `n`. Then ### `JULIA_SHELL` -The absolute path of the shell with which Julia should execute external commands (via -`Base.repl_cmd()`). Defaults to the environment variable `$SHELL`, and falls back to -`/bin/sh` if `$SHELL` is unset. +The absolute path of the shell with which Julia should execute external commands +(via `Base.repl_cmd()`). Defaults to the environment variable `$SHELL`, and +falls back to `/bin/sh` if `$SHELL` is unset. !!! note - On Windows, this environment variable is ignored, and external commands are executed - directly. + On Windows, this environment variable is ignored, and external commands are + executed directly. ### `JULIA_EDITOR` -The editor returned by `Base.editor()` and used in, e.g., [`Base.edit`](@ref). +The editor returned by `Base.editor()` and used in, e.g., [`Base.edit`](@ref), +referring to the command of the preferred editor, for instance `vim`. -`$JULIA_EDITOR` takes precedence over `$VISUAL`, which in turn takes precedence over -`$EDITOR`. If none of these environment variables is set, then the editor is taken to be -`open` on Windows and OS X, or `/etc/alternatives/editor` if it exists, or `emacs` -otherwise. +`$JULIA_EDITOR` takes precedence over `$VISUAL`, which in turn takes precedence +over `$EDITOR`. If none of these environment variables is set, then the editor +is taken to be `open` on Windows and OS X, or `/etc/alternatives/editor` if it +exists, or `emacs` otherwise. !!! note @@ -158,138 +170,140 @@ otherwise. ### `JULIA_CPU_CORES` -Overrides the global variable [`Base.Sys.CPU_CORES`](@ref), the number of logical CPU cores -available. +Overrides the global variable [`Base.Sys.CPU_CORES`](@ref), the number of +logical CPU cores available. ### `JULIA_WORKER_TIMEOUT` -A `Float64` that sets the value of `Base.worker_timeout()` (default: `60.0`). This function -gives the number of seconds a worker process will wait for a master process to establish -a connection before dying. +A `Float64` that sets the value of `Base.worker_timeout()` (default: `60.0`). +This function gives the number of seconds a worker process will wait for +a master process to establish a connection before dying. ### `JULIA_NUM_THREADS` -An unsigned 64-bit integer (`uint64_t`) that sets the maximum number of threads available to -Julia. If `$JULIA_NUM_THREADS` exceeds the number of available physical CPU cores, then the -number of threads is set to the number of cores. If `$JULIA_NUM_THREADS` is not positive or -is not set, or if the number of CPU cores cannot be determined through system calls, then -the number of threads is set to `1`. +An unsigned 64-bit integer (`uint64_t`) that sets the maximum number of threads +available to Julia. If `$JULIA_NUM_THREADS` exceeds the number of available +physical CPU cores, then the number of threads is set to the number of cores. If +`$JULIA_NUM_THREADS` is not positive or is not set, or if the number of CPU +cores cannot be determined through system calls, then the number of threads is +set to `1`. ### `JULIA_THREAD_SLEEP_THRESHOLD` -If set to a string that starts with the case-insensitive substring `"infinite"`, then -spinning threads never sleep. Otherwise, `$JULIA_THREAD_SLEEP_THRESHOLD` is interpreted as -an unsigned 64-bit integer (`uint64_t`) and gives, in nanoseconds, the amount of time after -which spinning threads should sleep. +If set to a string that starts with the case-insensitive substring `"infinite"`, +then spinning threads never sleep. Otherwise, `$JULIA_THREAD_SLEEP_THRESHOLD` is +interpreted as an unsigned 64-bit integer (`uint64_t`) and gives, in +nanoseconds, the amount of time after which spinning threads should sleep. ### `JULIA_EXCLUSIVE` -If set to anything besides `0`, then Julia's thread policy is consistent with running on -a dedicated machine: the master thread is on proc 0, and threads are affinitized. Otherwise, -Julia lets the operating system handle thread policy. +If set to anything besides `0`, then Julia's thread policy is consistent with +running on a dedicated machine: the master thread is on proc 0, and threads are +affinitized. Otherwise, Julia lets the operating system handle thread policy. ## REPL formatting -Environment variables that determine how REPL output should be formatted at the terminal. -Generally, these variables should be set to [ANSI terminal escape -sequences](http://ascii-table.com/ansi-escape-sequences.php). Julia provides a high-level -interface with much of the same functionality: see the section on [Interacting With -Julia](@ref). +Environment variables that determine how REPL output should be formatted at the +terminal. Generally, these variables should be set to [ANSI terminal escape +sequences](http://ascii-table.com/ansi-escape-sequences.php). Julia provides +a high-level interface with much of the same functionality: see the section on +[Interacting With Julia](@ref). ### `JULIA_ERROR_COLOR` -The formatting `Base.error_color()` (default: light red, `"\033[91m"`) that errors should -have at the terminal. +The formatting `Base.error_color()` (default: light red, `"\033[91m"`) that +errors should have at the terminal. ### `JULIA_WARN_COLOR` -The formatting `Base.warn_color()` (default: yellow, `"\033[93m"`) that warnings should have -at the terminal. +The formatting `Base.warn_color()` (default: yellow, `"\033[93m"`) that warnings +should have at the terminal. ### `JULIA_INFO_COLOR` -The formatting `Base.info_color()` (default: cyan, `"\033[36m"`) that info should have at -the terminal. +The formatting `Base.info_color()` (default: cyan, `"\033[36m"`) that info +should have at the terminal. ### `JULIA_INPUT_COLOR` -The formatting `Base.input_color()` (default: normal, `"\033[0m"`) that input should have at -the terminal. +The formatting `Base.input_color()` (default: normal, `"\033[0m"`) that input +should have at the terminal. ### `JULIA_ANSWER_COLOR` -The formatting `Base.answer_color()` (default: normal, `"\033[0m"`) that output should have -at the terminal. +The formatting `Base.answer_color()` (default: normal, `"\033[0m"`) that output +should have at the terminal. ### `JULIA_STACKFRAME_LINEINFO_COLOR` -The formatting `Base.stackframe_lineinfo_color()` (default: bold, `"\033[1m"`) that line -info should have during a stack trace at the terminal. +The formatting `Base.stackframe_lineinfo_color()` (default: bold, `"\033[1m"`) +that line info should have during a stack trace at the terminal. ### `JULIA_STACKFRAME_FUNCTION_COLOR` -The formatting `Base.stackframe_function_color()` (default: bold, `"\033[1m"`) that function -calls should have during a stack trace at the terminal. +The formatting `Base.stackframe_function_color()` (default: bold, `"\033[1m"`) +that function calls should have during a stack trace at the terminal. ## Debugging and profiling ### `JULIA_GC_ALLOC_POOL`, `JULIA_GC_ALLOC_OTHER`, `JULIA_GC_ALLOC_PRINT` -If set, these environment variables take strings that optionally start with the character -`'r'`, followed by a string interpolation of a colon-separated list of three signed 64-bit -integers (`int64_t`). This triple of integers `a:b:c` represents the arithmetic sequence -`a`, `a + b`, `a + 2*b`, ... `c`. - -* If it's the `n`th time that `jl_gc_pool_alloc()` has been called, and `n` belongs to the - arithmetic sequence represented by `$JULIA_GC_ALLOC_POOL`, then garbage collection is - forced. -* If it's the `n`th time that `maybe_collect()` has been called, and `n` belongs to the - arithmetic sequence represented by `$JULIA_GC_ALLOC_OTHER`, then garbage collection is - forced. -* If it's the `n`th time that `jl_gc_collect()` has been called, and `n` belongs to the - arithmetic sequence represented by `$JULIA_GC_ALLOC_PRINT`, then counts for the number - of calls to `jl_gc_pool_alloc()` and `maybe_collect()` are printed. - -If the value of the environment variable begins with the character `'r'`, then the interval -between garbage collection events is randomized. +If set, these environment variables take strings that optionally start with the +character `'r'`, followed by a string interpolation of a colon-separated list of +three signed 64-bit integers (`int64_t`). This triple of integers `a:b:c` +represents the arithmetic sequence `a`, `a + b`, `a + 2*b`, ... `c`. + +* If it's the `n`th time that `jl_gc_pool_alloc()` has been called, and `n` + belongs to the arithmetic sequence represented by `$JULIA_GC_ALLOC_POOL`, + then garbage collection is forced. +* If it's the `n`th time that `maybe_collect()` has been called, and `n` belongs + to the arithmetic sequence represented by `$JULIA_GC_ALLOC_OTHER`, then garbage + collection is forced. +* If it's the `n`th time that `jl_gc_collect()` has been called, and `n` belongs + to the arithmetic sequence represented by `$JULIA_GC_ALLOC_PRINT`, then counts + for the number of calls to `jl_gc_pool_alloc()` and `maybe_collect()` are + printed. + +If the value of the environment variable begins with the character `'r'`, then +the interval between garbage collection events is randomized. !!! note These environment variables only have an effect if Julia was compiled with - garbage-collection debugging (that is, if `WITH_GC_DEBUG_ENV` is set to `1` in the build - configuration). + garbage-collection debugging (that is, if `WITH_GC_DEBUG_ENV` is set to `1` + in the build configuration). ### `JULIA_GC_NO_GENERATIONAL` -If set to anything besides `0`, then the Julia garbage collector never performs "quick -sweeps" of memory. +If set to anything besides `0`, then the Julia garbage collector never performs +"quick sweeps" of memory. !!! note This environment variable only has an effect if Julia was compiled with - garbage-collection debugging (that is, if `WITH_GC_DEBUG_ENV` is set to `1` in the build - configuration). + garbage-collection debugging (that is, if `WITH_GC_DEBUG_ENV` is set to `1` + in the build configuration). ### `JULIA_GC_WAIT_FOR_DEBUGGER` -If set to anything besides `0`, then the Julia garbage collector will wait for the debugger -to attach instead of aborting whenever there's a critical error. +If set to anything besides `0`, then the Julia garbage collector will wait for +a debugger to attach instead of aborting whenever there's a critical error. !!! note This environment variable only has an effect if Julia was compiled with - garbage-collection debugging (that is, if `WITH_GC_DEBUG_ENV` is set to `1` in the build - configuration). + garbage-collection debugging (that is, if `WITH_GC_DEBUG_ENV` is set to `1` + in the build configuration). ### `ENABLE_JITPROFILING` -If set to anything besides `0`, then the compiler will create and register an event listener -for just-in-time (JIT) profiling. +If set to anything besides `0`, then the compiler will create and register an +event listener for just-in-time (JIT) profiling. !!! note - This environment variable only has an effect if Julia was compiled with JIT profiling - support, using either + This environment variable only has an effect if Julia was compiled with JIT + profiling support, using either * Intel's [VTune™ Amplifier](https://software.intel.com/en-us/intel-vtune-amplifier-xe) (`USE_INTEL_JITEVENTS` set to `1` in the build configuration), or @@ -302,12 +316,12 @@ Arguments to be passed to the LLVM backend. !!! note - This environment variable has an effect only if Julia was compiled with `JL_DEBUG_BUILD` - set—in particular, the `julia-debug` executable is always compiled with this build - variable. + This environment variable has an effect only if Julia was compiled with + `JL_DEBUG_BUILD` set — in particular, the `julia-debug` executable is always + compiled with this build variable. ### `JULIA_DEBUG_LOADING` -If set, then Julia prints detailed information about the cache in the loading process of -[`Base.require`](@ref). +If set, then Julia prints detailed information about the cache in the loading +process of [`Base.require`](@ref). From d63c57d3d3b866604f19169bc221fcdf2541d944 Mon Sep 17 00:00:00 2001 From: Mus M Date: Fri, 21 Apr 2017 22:46:57 -0400 Subject: [PATCH 0509/1534] Chnage back to Array for TOL in arpack.jl --- base/linalg/arpack.jl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/base/linalg/arpack.jl b/base/linalg/arpack.jl index 4b5d1d147e4e4..f798937fa4422 100644 --- a/base/linalg/arpack.jl +++ b/base/linalg/arpack.jl @@ -12,8 +12,8 @@ function aupd_wrapper(T, matvecA!::Function, matvecB::Function, solveSI::Functio tol::Real, maxiter::Integer, mode::Integer, v0::Vector) lworkl = cmplx ? ncv * (3*ncv + 5) : (sym ? ncv * (ncv + 8) : ncv * (3*ncv + 6) ) TR = cmplx ? T.types[1] : T - TOL = Ref{TR}() - TOL[] = tol + TOL = Vector{TR}(1) + TOL[1] = tol v = Matrix{T}(n, ncv) workd = Vector{T}(3*n) @@ -106,7 +106,7 @@ end function eupd_wrapper(T, n::Integer, sym::Bool, cmplx::Bool, bmat::String, nev::Integer, which::String, ritzvec::Bool, - TOL::Ref, resid, ncv::Integer, v, ldv, sigma, iparam, ipntr, + TOL::Array, resid, ncv::Integer, v, ldv, sigma, iparam, ipntr, workd, workl, lworkl, rwork) howmny = "A" select = Array{BlasInt}(ncv) @@ -203,7 +203,7 @@ for (T, saupd_name, seupd_name, naupd_name, neupd_name) in ((:Float64, :dsaupd_, :dseupd_, :dnaupd_, :dneupd_), (:Float32, :ssaupd_, :sseupd_, :snaupd_, :sneupd_)) @eval begin - function naupd(ido, bmat, n, evtype, nev, TOL::Ref{$T}, resid::Array{$T}, ncv, v::Array{$T}, ldv, + function naupd(ido, bmat, n, evtype, nev, TOL::Array{$T}, resid::Array{$T}, ncv, v::Array{$T}, ldv, iparam, ipntr, workd::Array{$T}, workl::Array{$T}, lworkl, info) ccall(($(string(naupd_name)), :libarpack), Void, (Ptr{BlasInt}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{UInt8}, Ptr{BlasInt}, @@ -214,7 +214,7 @@ for (T, saupd_name, seupd_name, naupd_name, neupd_name) in end function neupd(rvec, howmny, select, dr, di, z, ldz, sigmar, sigmai, - workev::Array{$T}, bmat, n, evtype, nev, TOL::Ref{$T}, resid::Array{$T}, ncv, v, ldv, + workev::Array{$T}, bmat, n, evtype, nev, TOL::Array{$T}, resid::Array{$T}, ncv, v, ldv, iparam, ipntr, workd::Array{$T}, workl::Array{$T}, lworkl, info) ccall(($(string(neupd_name)), :libarpack), Void, (Ptr{BlasInt}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{$T}, Ptr{$T}, Ptr{$T}, @@ -228,7 +228,7 @@ for (T, saupd_name, seupd_name, naupd_name, neupd_name) in sizeof(howmny), sizeof(bmat), sizeof(evtype)) end - function saupd(ido, bmat, n, which, nev, TOL::Ref{$T}, resid::Array{$T}, ncv, v::Array{$T}, ldv, + function saupd(ido, bmat, n, which, nev, TOL::Array{$T}, resid::Array{$T}, ncv, v::Array{$T}, ldv, iparam, ipntr, workd::Array{$T}, workl::Array{$T}, lworkl, info) ccall(($(string(saupd_name)), :libarpack), Void, (Ptr{BlasInt}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{UInt8}, Ptr{BlasInt}, @@ -239,7 +239,7 @@ for (T, saupd_name, seupd_name, naupd_name, neupd_name) in end function seupd(rvec, howmny, select, d, z, ldz, sigma, - bmat, n, evtype, nev, TOL::Ref{$T}, resid::Array{$T}, ncv, v::Array{$T}, ldv, + bmat, n, evtype, nev, TOL::Array{$T}, resid::Array{$T}, ncv, v::Array{$T}, ldv, iparam, ipntr, workd::Array{$T}, workl::Array{$T}, lworkl, info) ccall(($(string(seupd_name)), :libarpack), Void, (Ptr{BlasInt}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{$T}, Ptr{$T}, Ptr{BlasInt}, Ptr{$T}, @@ -257,7 +257,7 @@ for (T, TR, naupd_name, neupd_name) in ((:Complex128, :Float64, :znaupd_, :zneupd_), (:Complex64, :Float32, :cnaupd_, :cneupd_)) @eval begin - function naupd(ido, bmat, n, evtype, nev, TOL::Ref{$TR}, resid::Array{$T}, ncv, v::Array{$T}, ldv, + function naupd(ido, bmat, n, evtype, nev, TOL::Array{$TR}, resid::Array{$T}, ncv, v::Array{$T}, ldv, iparam, ipntr, workd::Array{$T}, workl::Array{$T}, lworkl, rwork::Array{$TR}, info) ccall(($(string(naupd_name)), :libarpack), Void, @@ -270,7 +270,7 @@ for (T, TR, naupd_name, neupd_name) in end function neupd(rvec, howmny, select, d, z, ldz, sigma, workev::Array{$T}, - bmat, n, evtype, nev, TOL::Ref{$TR}, resid::Array{$T}, ncv, v::Array{$T}, ldv, + bmat, n, evtype, nev, TOL::Array{$TR}, resid::Array{$T}, ncv, v::Array{$T}, ldv, iparam, ipntr, workd::Array{$T}, workl::Array{$T}, lworkl, rwork::Array{$TR}, info) ccall(($(string(neupd_name)), :libarpack), Void, From 3eb7115464c68b05a53d139b3aa9d9683039079e Mon Sep 17 00:00:00 2001 From: Carlo Baldassi Date: Sat, 22 Apr 2017 17:02:33 +0200 Subject: [PATCH 0510/1534] Slight refactoring in test/resolve.jl This is in order to catch resolver failures inside `@test` calls --- test/resolve.jl | 123 ++++++++++++++++++++++++------------------------ 1 file changed, 62 insertions(+), 61 deletions(-) diff --git a/test/resolve.jl b/test/resolve.jl index 059e23a90cecb..f513a884dd4a8 100644 --- a/test/resolve.jl +++ b/test/resolve.jl @@ -100,7 +100,7 @@ function sanity_tst(deps_data, expected_result; pkgs=[]) end sanity_tst(deps_data; kw...) = sanity_tst(deps_data, []; kw...) -function resolve_tst(deps_data, reqs_data) +function resolve_tst(deps_data, reqs_data, want_data = nothing) deps = deps_from_data(deps_data) reqs = reqs_from_data(reqs_data) @@ -109,6 +109,7 @@ function resolve_tst(deps_data, reqs_data) #println("reqs=$reqs") deps = Query.prune_dependencies(reqs, deps) want = resolve(reqs, deps) + return want == want_data end ## DEPENDENCY SCHEME 1: TWO PACKAGES, DAG @@ -129,15 +130,15 @@ reqs_data = Any[ ["B"] ] -want = resolve_tst(deps_data, reqs_data) -@test want == Dict("B"=>v"2") +want_data = Dict("B"=>v"2") +@test resolve_tst(deps_data, reqs_data, want_data) # require just A: must bring in B reqs_data = Any[ ["A"] ] -want = resolve_tst(deps_data, reqs_data) -@test want == Dict("A"=>v"2", "B"=>v"2") +want_data = Dict("A"=>v"2", "B"=>v"2") +@test resolve_tst(deps_data, reqs_data, want_data) ## DEPENDENCY SCHEME 2: TWO PACKAGES, CYCLIC @@ -154,22 +155,22 @@ deps_data = Any[ reqs_data = Any[ ["A"] ] -want = resolve_tst(deps_data, reqs_data) -@test want == Dict("A"=>v"2", "B"=>v"2") +want_data = Dict("A"=>v"2", "B"=>v"2") +@test resolve_tst(deps_data, reqs_data, want_data) # require just B, force lower version reqs_data = Any[ ["B", v"1", v"2"] ] -want = resolve_tst(deps_data, reqs_data) -@test want == Dict("A"=>v"2", "B"=>v"1") +want_data = Dict("A"=>v"2", "B"=>v"1") +@test resolve_tst(deps_data, reqs_data, want_data) # require just A, force lower version reqs_data = Any[ ["A", v"1", v"2"] ] -want = resolve_tst(deps_data, reqs_data) -@test want == Dict("A"=>v"1", "B"=>v"2") +want_data = Dict("A"=>v"1", "B"=>v"2") +@test resolve_tst(deps_data, reqs_data, want_data) ## DEPENDENCY SCHEME 3: THREE PACKAGES, CYCLIC, TWO MUTUALLY EXCLUSIVE SOLUTIONS @@ -188,22 +189,22 @@ deps_data = Any[ reqs_data = Any[ ["A"] ] -want = resolve_tst(deps_data, reqs_data) -@test want == Dict("A"=>v"2", "B"=>v"1", "C"=>v"2") +want_data = Dict("A"=>v"2", "B"=>v"1", "C"=>v"2") +@test resolve_tst(deps_data, reqs_data, want_data) # require just B (must choose solution which has the highest version for B) reqs_data = Any[ ["B"] ] -want = resolve_tst(deps_data, reqs_data) -@test want == Dict("A"=>v"1", "B"=>v"2", "C"=>v"1") +want_data = Dict("A"=>v"1", "B"=>v"2", "C"=>v"1") +@test resolve_tst(deps_data, reqs_data, want_data) # require just A, force lower version reqs_data = Any[ ["A", v"1", v"2"] ] -want = resolve_tst(deps_data, reqs_data) -@test want == Dict("A"=>v"1", "B"=>v"2", "C"=>v"1") +want_data = Dict("A"=>v"1", "B"=>v"2", "C"=>v"1") +@test resolve_tst(deps_data, reqs_data, want_data) # require A and C, incompatible versions reqs_data = Any[ @@ -226,8 +227,8 @@ deps_data = Any[ reqs_data = Any[ ["B"] ] -want = resolve_tst(deps_data, reqs_data) -@test want == Dict("B"=>v"1") +want_data = Dict("B"=>v"1") +@test resolve_tst(deps_data, reqs_data, want_data) ## DEPENDENCY SCHEME 5: THREE PACKAGES, DAG, WITH IMPLICIT INCONSISTENCY @@ -250,8 +251,8 @@ deps_data = Any[ reqs_data = Any[ ["A"] ] -want = resolve_tst(deps_data, reqs_data) -@test want == Dict("A"=>v"1", "B"=>v"2", "C"=>v"2") +want_data = Dict("A"=>v"1", "B"=>v"2", "C"=>v"2") +@test resolve_tst(deps_data, reqs_data, want_data) # require A, force highest version (impossible) reqs_data = Any[ @@ -301,15 +302,15 @@ deps_data = Any[ reqs_data = Any[ ["A"] ] -want = resolve_tst(deps_data, reqs_data) -@test want == Dict("A"=>v"2", "B"=>v"2", "C"=>v"2") +want_data = Dict("A"=>v"2", "B"=>v"2", "C"=>v"2") +@test resolve_tst(deps_data, reqs_data, want_data) # require C reqs_data = Any[ ["C"] ] -want = resolve_tst(deps_data, reqs_data) -@test want == Dict("A"=>v"2", "B"=>v"2", "C"=>v"2") +want_data = Dict("A"=>v"2", "B"=>v"2", "C"=>v"2") +@test resolve_tst(deps_data, reqs_data, want_data) # require C, lowest version (impossible) reqs_data = Any[ @@ -374,44 +375,44 @@ deps_data = Any[ reqs_data = Any[ ["F"] ] -want = resolve_tst(deps_data, reqs_data) -@test want == Dict("A"=>v"3", "B"=>v"2", "C"=>v"2", - "D"=>v"2", "E"=>v"1", "F"=>v"2") +want_data = Dict("A"=>v"3", "B"=>v"2", "C"=>v"2", + "D"=>v"2", "E"=>v"1", "F"=>v"2") +@test resolve_tst(deps_data, reqs_data, want_data) # require just F, lower version reqs_data = Any[ ["F", v"1", v"2"] ] -want = resolve_tst(deps_data, reqs_data) -@test want == Dict("A"=>v"2", "B"=>v"2", "D"=>v"2", - "E"=>v"1", "F"=>v"1") +want_data = Dict("A"=>v"2", "B"=>v"2", "D"=>v"2", + "E"=>v"1", "F"=>v"1") +@test resolve_tst(deps_data, reqs_data, want_data) # require F and B; force lower B version -> must bring down F, A, and D versions too reqs_data = Any[ ["F"], ["B", v"1", v"2"] ] -want = resolve_tst(deps_data, reqs_data) -@test want == Dict("A"=>v"1", "B"=>v"1", "D"=>v"1", - "E"=>v"1", "F"=>v"1") +want_data = Dict("A"=>v"1", "B"=>v"1", "D"=>v"1", + "E"=>v"1", "F"=>v"1") +@test resolve_tst(deps_data, reqs_data, want_data) # require F and D; force lower D version -> must not bring down F version reqs_data = Any[ ["F"], ["D", v"1", v"2"] ] -want = resolve_tst(deps_data, reqs_data) -@test want == Dict("A"=>v"3", "B"=>v"2", "C"=>v"2", - "D"=>v"1", "E"=>v"1", "F"=>v"2") +want_data = Dict("A"=>v"3", "B"=>v"2", "C"=>v"2", + "D"=>v"1", "E"=>v"1", "F"=>v"2") +@test resolve_tst(deps_data, reqs_data, want_data) # require F and C; force lower C version -> must bring down F and A versions reqs_data = Any[ ["F"], ["C", v"1", v"2"] ] -want = resolve_tst(deps_data, reqs_data) -@test want == Dict("A"=>v"2", "B"=>v"2", "C"=>v"1", - "D"=>v"2", "E"=>v"1", "F"=>v"1") +want_data = Dict("A"=>v"2", "B"=>v"2", "C"=>v"1", + "D"=>v"2", "E"=>v"1", "F"=>v"1") +@test resolve_tst(deps_data, reqs_data, want_data) ## DEPENDENCY SCHEME 10: SIX PACKAGES, DAG, WITH PRERELEASE/BUILD VERSIONS deps_data = Any[ @@ -448,44 +449,44 @@ deps_data = Any[ reqs_data = Any[ ["F"] ] -want = resolve_tst(deps_data, reqs_data) -@test want == Dict("A"=>v"2.1", "B"=>v"1.0.1", "C"=>v"2", - "D"=>v"2", "E"=>v"1", "F"=>v"2") +want_data = Dict("A"=>v"2.1", "B"=>v"1.0.1", "C"=>v"2", + "D"=>v"2", "E"=>v"1", "F"=>v"2") +@test resolve_tst(deps_data, reqs_data, want_data) # require just F, lower version reqs_data = Any[ ["F", v"1", v"2-"] ] -want = resolve_tst(deps_data, reqs_data) -@test want == Dict("A"=>v"2", "B"=>v"1.0.1", "D"=>v"2", - "E"=>v"1", "F"=>v"1.1") +want_data = Dict("A"=>v"2", "B"=>v"1.0.1", "D"=>v"2", + "E"=>v"1", "F"=>v"1.1") +@test resolve_tst(deps_data, reqs_data, want_data) # require F and B; force lower B version -> must bring down F, A, and D versions too reqs_data = Any[ ["F"], ["B", v"1", v"1.0.1-"] ] -want = resolve_tst(deps_data, reqs_data) -@test want == Dict("A"=>v"1", "B"=>v"1", "D"=>v"1", - "E"=>v"1", "F"=>v"1.1") +want_data = Dict("A"=>v"1", "B"=>v"1", "D"=>v"1", + "E"=>v"1", "F"=>v"1.1") +@test resolve_tst(deps_data, reqs_data, want_data) # require F and D; force lower D version -> must not bring down F version reqs_data = Any[ ["F"], ["D", v"1", v"2"] ] -want = resolve_tst(deps_data, reqs_data) -@test want == Dict("A"=>v"2.1", "B"=>v"1.0.1", "C"=>v"2", - "D"=>v"1", "E"=>v"1", "F"=>v"2") +want_data = Dict("A"=>v"2.1", "B"=>v"1.0.1", "C"=>v"2", + "D"=>v"1", "E"=>v"1", "F"=>v"2") +@test resolve_tst(deps_data, reqs_data, want_data) # require F and C; force lower C version -> must bring down F and A versions reqs_data = Any[ ["F"], ["C", v"1", v"2"] ] -want = resolve_tst(deps_data, reqs_data) -@test want == Dict("A"=>v"2", "B"=>v"1.0.1", "C"=>v"1+BLD", - "D"=>v"2", "E"=>v"1", "F"=>v"2-rc.1") +want_data = Dict("A"=>v"2", "B"=>v"1.0.1", "C"=>v"1+BLD", + "D"=>v"2", "E"=>v"1", "F"=>v"2-rc.1") +@test resolve_tst(deps_data, reqs_data, want_data) ## DEPENDENCY SCHEME 11: FIVE PACKAGES, SAME AS SCHEMES 5 + 1, UNCONNECTED deps_data = Any[ @@ -513,15 +514,15 @@ deps_data = Any[ reqs_data = Any[ ["A"] ] -want = resolve_tst(deps_data, reqs_data) -@test want == Dict("A"=>v"1", "B"=>v"2", "C"=>v"2") +want_data = Dict("A"=>v"1", "B"=>v"2", "C"=>v"2") +@test resolve_tst(deps_data, reqs_data, want_data) # require just D: must bring in E reqs_data = Any[ ["D"] ] -want = resolve_tst(deps_data, reqs_data) -@test want == Dict("D"=>v"2", "E"=>v"2") +want_data = Dict("D"=>v"2", "E"=>v"2") +@test resolve_tst(deps_data, reqs_data, want_data) # require A and D, must be the merge of the previous two cases @@ -529,5 +530,5 @@ reqs_data = Any[ ["A"], ["D"] ] -want = resolve_tst(deps_data, reqs_data) -@test want == Dict("A"=>v"1", "B"=>v"2", "C"=>v"2", "D"=>v"2", "E"=>v"2") +want_data = Dict("A"=>v"1", "B"=>v"2", "C"=>v"2", "D"=>v"2", "E"=>v"2") +@test resolve_tst(deps_data, reqs_data, want_data) From 252552253d2da2e594383b440154f348a9fd0a7c Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Sat, 22 Apr 2017 17:02:57 +0200 Subject: [PATCH 0511/1534] fix typos in testset docs --- base/test.jl | 2 +- doc/src/stdlib/test.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/base/test.jl b/base/test.jl index 6fdaa48057bd5..d8ad274f4c576 100644 --- a/base/test.jl +++ b/base/test.jl @@ -793,7 +793,7 @@ end Starts a new test set, or multiple test sets if a `for` loop is provided. If no custom testset type is given it defaults to creating a `DefaultTestSet`. -`DefaultTestSet` records all the results and, and if there are any `Fail`s or +`DefaultTestSet` records all the results and, if there are any `Fail`s or `Error`s, throws an exception at the end of the top-level (non-nested) test set, along with a summary of the test results. diff --git a/doc/src/stdlib/test.md b/doc/src/stdlib/test.md index f4e2999fbf06e..cf8503f851bc4 100644 --- a/doc/src/stdlib/test.md +++ b/doc/src/stdlib/test.md @@ -89,7 +89,7 @@ Test Passed ## Working with Test Sets -Typically a large of number of tests are used to make sure functions work correctly over a range +Typically a large number of tests are used to make sure functions work correctly over a range of inputs. In the event a test fails, the default behavior is to throw an exception immediately. However, it is normally preferable to run the rest of the tests first to get a better picture of how many errors there are in the code being tested. From bc9efecc52e7942da355962440bb8bd1cb72275e Mon Sep 17 00:00:00 2001 From: Carlo Baldassi Date: Sat, 22 Apr 2017 17:04:18 +0200 Subject: [PATCH 0512/1534] Add a realistic test in test/resolve.jl This is to catch a particularly hard case for the resolver that was reported in https://discourse.julialang.org/t/differentialequations-pkg-wont-be-added --- test/resolve.jl | 8 + test/resolvedata1.jl | 2851 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 2859 insertions(+) create mode 100644 test/resolvedata1.jl diff --git a/test/resolve.jl b/test/resolve.jl index f513a884dd4a8..efb07c22a4483 100644 --- a/test/resolve.jl +++ b/test/resolve.jl @@ -532,3 +532,11 @@ reqs_data = Any[ ] want_data = Dict("A"=>v"1", "B"=>v"2", "C"=>v"2", "D"=>v"2", "E"=>v"2") @test resolve_tst(deps_data, reqs_data, want_data) + +## DEPENDENCY SCHEME 12: A REALISTIC EXAMPLE +## ref issue #21485 + +include("resolvedata1.jl") + +@test sanity_tst(deps_data, problematic_data) +@test resolve_tst(deps_data, reqs_data, want_data) diff --git a/test/resolvedata1.jl b/test/resolvedata1.jl new file mode 100644 index 0000000000000..19346bc08200a --- /dev/null +++ b/test/resolvedata1.jl @@ -0,0 +1,2851 @@ +deps_data = Any[ + ["ASTInterpreter", v"0.0.1", "AbstractTrees", v"0.0.1", v"0.1.0"], + ["ASTInterpreter", v"0.0.1", "JuliaParser", v"0.7.1"], + ["ASTInterpreter", v"0.0.3", "AbstractTrees", v"0.0.2", v"0.1.0"], + ["ASTInterpreter", v"0.0.3", "JuliaParser", v"0.7.2"], + ["ASTInterpreter", v"0.0.4", "AbstractTrees", v"0.0.4", v"0.1.0"], + ["ASTInterpreter", v"0.0.4", "JuliaParser", v"0.7.2"], + ["AbstractTrees", v"0.0.1"], + ["AbstractTrees", v"0.0.3"], + ["AbstractTrees", v"0.0.4"], + ["AbstractTrees", v"0.1.0", "Compat", v"0.17.0"], + ["AlgebraicDiffEq", v"0.0.1", "DiffEqBase"], + ["AlgebraicDiffEq", v"0.0.1", "Parameters", v"0.5.0"], + ["AlgebraicDiffEq", v"0.0.1", "Sundials", v"0.3.0"], + ["AlgebraicDiffEq", v"0.0.2", "DiffEqBase"], + ["AlgebraicDiffEq", v"0.0.2", "Parameters", v"0.5.0"], + ["AlgebraicDiffEq", v"0.0.2", "Sundials", v"0.3.0"], + ["AlgebraicDiffEq", v"0.1.0", "DiffEqBase", v"0.2.0"], + ["AlgebraicDiffEq", v"0.1.0", "Parameters", v"0.5.0"], + ["AnsiColor", v"0.0.2"], + ["ArgParse", v"0.2.9", "Options"], + ["ArgParse", v"0.2.9", "TextWrap", v"0.1.0-"], + ["ArgParse", v"0.2.10", "Compat"], + ["ArgParse", v"0.2.10", "Options"], + ["ArgParse", v"0.2.10", "TextWrap", v"0.1.0-"], + ["ArgParse", v"0.2.12", "Options"], + ["ArgParse", v"0.2.12", "Compat", v"0.2.9"], + ["ArgParse", v"0.2.12", "TextWrap", v"0.1.0-"], + ["ArgParse", v"0.2.13", "Options"], + ["ArgParse", v"0.2.13", "Compat", v"0.7.3"], + ["ArgParse", v"0.2.13", "TextWrap", v"0.1.4"], + ["ArgParse", v"0.3.0", "Compat", v"0.7.3"], + ["ArgParse", v"0.3.0", "TextWrap", v"0.1.4"], + ["ArgParse", v"0.4.0", "Compat", v"0.8.0"], + ["ArgParse", v"0.4.0", "TextWrap", v"0.1.4"], + ["ArrayViews", v"0.1.1"], + ["ArrayViews", v"0.3.0"], + ["ArrayViews", v"0.4.5"], + ["ArrayViews", v"0.4.7"], + ["ArrayViews", v"0.4.8"], + ["ArrayViews", v"0.4.9"], + ["ArrayViews", v"0.4.11"], + ["ArrayViews", v"0.6.3"], + ["ArrayViews", v"0.6.4", "Compat"], + ["Atom", v"0.2.1", "CodeTools"], + ["Atom", v"0.2.1", "Hiccup"], + ["Atom", v"0.2.1", "JSON"], + ["Atom", v"0.2.1", "LNR"], + ["Atom", v"0.2.1", "Lazy"], + ["Atom", v"0.2.1", "Media"], + ["Atom", v"0.4.0", "Blink"], + ["Atom", v"0.4.0", "CodeTools"], + ["Atom", v"0.4.0", "Hiccup"], + ["Atom", v"0.4.0", "JSON"], + ["Atom", v"0.4.0", "LNR"], + ["Atom", v"0.4.0", "Lazy"], + ["Atom", v"0.4.0", "Media"], + ["Atom", v"0.4.0", "Reexport"], + ["Atom", v"0.4.6", "Blink"], + ["Atom", v"0.4.6", "CodeTools"], + ["Atom", v"0.4.6", "Hiccup"], + ["Atom", v"0.4.6", "JSON"], + ["Atom", v"0.4.6", "LNR"], + ["Atom", v"0.4.6", "Lazy"], + ["Atom", v"0.4.6", "MacroTools"], + ["Atom", v"0.4.6", "Media"], + ["Atom", v"0.4.6", "Reexport"], + ["Atom", v"0.4.6", "Requires"], + ["Atom", v"0.5.0", "ASTInterpreter"], + ["Atom", v"0.5.0", "Blink"], + ["Atom", v"0.5.0", "CodeTools"], + ["Atom", v"0.5.0", "Gallium"], + ["Atom", v"0.5.0", "Hiccup"], + ["Atom", v"0.5.0", "JSON"], + ["Atom", v"0.5.0", "LNR"], + ["Atom", v"0.5.0", "Lazy"], + ["Atom", v"0.5.0", "MacroTools"], + ["Atom", v"0.5.0", "Media"], + ["Atom", v"0.5.0", "Reexport"], + ["Atom", v"0.5.0", "Requires"], + ["Atom", v"0.5.2", "ASTInterpreter"], + ["Atom", v"0.5.2", "Blink"], + ["Atom", v"0.5.2", "CodeTools"], + ["Atom", v"0.5.2", "Gallium"], + ["Atom", v"0.5.2", "Hiccup"], + ["Atom", v"0.5.2", "JSON"], + ["Atom", v"0.5.2", "Juno"], + ["Atom", v"0.5.2", "LNR"], + ["Atom", v"0.5.2", "Lazy"], + ["Atom", v"0.5.2", "MacroTools"], + ["Atom", v"0.5.2", "Media"], + ["Atom", v"0.5.2", "Reexport"], + ["Atom", v"0.5.2", "Requires"], + ["Atom", v"0.5.8", "ASTInterpreter"], + ["Atom", v"0.5.8", "Blink"], + ["Atom", v"0.5.8", "CodeTools"], + ["Atom", v"0.5.8", "Gallium"], + ["Atom", v"0.5.8", "Hiccup"], + ["Atom", v"0.5.8", "JSON"], + ["Atom", v"0.5.8", "Juno"], + ["Atom", v"0.5.8", "LNR"], + ["Atom", v"0.5.8", "MacroTools"], + ["Atom", v"0.5.8", "Media"], + ["Atom", v"0.5.8", "Reexport"], + ["Atom", v"0.5.8", "Lazy", v"0.11.3"], + ["Atom", v"0.5.10", "ASTInterpreter"], + ["Atom", v"0.5.10", "Blink"], + ["Atom", v"0.5.10", "CodeTools"], + ["Atom", v"0.5.10", "Gallium"], + ["Atom", v"0.5.10", "Hiccup"], + ["Atom", v"0.5.10", "JSON"], + ["Atom", v"0.5.10", "LNR"], + ["Atom", v"0.5.10", "MacroTools"], + ["Atom", v"0.5.10", "Media"], + ["Atom", v"0.5.10", "Reexport"], + ["Atom", v"0.5.10", "Juno", v"0.2.6"], + ["Atom", v"0.5.10", "Lazy", v"0.11.3"], + ["AxisAlgorithms", v"0.1.6", "WoodburyMatrices"], + ["AxisAlgorithms", v"0.1.6", "Compat", v"0.8.0"], + ["AxisArrays", v"0.0.3", "IntervalSets"], + ["AxisArrays", v"0.0.3", "Iterators"], + ["AxisArrays", v"0.0.3", "RangeArrays"], + ["AxisArrays", v"0.1.2", "Compat", v"0.19.0"], + ["AxisArrays", v"0.1.2", "IntervalSets"], + ["AxisArrays", v"0.1.2", "Iterators"], + ["AxisArrays", v"0.1.2", "RangeArrays"], + ["BinDeps", v"0.2.0"], + ["BinDeps", v"0.2.4", "URIParser"], + ["BinDeps", v"0.2.14", "URIParser"], + ["BinDeps", v"0.3.4", "URIParser"], + ["BinDeps", v"0.3.4", "SHA", v"0.0.0", v"0.0.3"], + ["BinDeps", v"0.3.5", "URIParser"], + ["BinDeps", v"0.3.5", "SHA", v"0.0.3"], + ["BinDeps", v"0.3.8", "SHA"], + ["BinDeps", v"0.3.8", "URIParser"], + ["BinDeps", v"0.3.10", "Compat", v"0.3.6"], + ["BinDeps", v"0.3.10", "SHA"], + ["BinDeps", v"0.3.10", "URIParser"], + ["BinDeps", v"0.3.15", "Compat", v"0.4.0"], + ["BinDeps", v"0.3.15", "SHA"], + ["BinDeps", v"0.3.15", "URIParser"], + ["BinDeps", v"0.3.21", "Compat", v"0.7.1"], + ["BinDeps", v"0.3.21", "SHA"], + ["BinDeps", v"0.3.21", "URIParser"], + ["BinDeps", v"0.3.23", "URIParser"], + ["BinDeps", v"0.3.23", "Compat", v"0.8.4"], + ["BinDeps", v"0.3.23", "SHA"], + ["BinDeps", v"0.4.2", "Compat", v"0.8.4"], + ["BinDeps", v"0.4.2", "SHA"], + ["BinDeps", v"0.4.2", "URIParser"], + ["BinDeps", v"0.4.5", "Compat", v"0.8.4"], + ["BinDeps", v"0.4.5", "SHA"], + ["BinDeps", v"0.4.5", "URIParser"], + ["BinDeps", v"0.4.7", "Compat", v"0.17.0"], + ["BinDeps", v"0.4.7", "SHA"], + ["BinDeps", v"0.4.7", "URIParser"], + ["Blink", v"0.1.4", "JSON"], + ["Blink", v"0.1.4", "Lazy"], + ["Blink", v"0.1.4", "Requires"], + ["Blink", v"0.1.5", "JSON"], + ["Blink", v"0.1.5", "Lazy"], + ["Blink", v"0.1.5", "MacroTools"], + ["Blink", v"0.1.5", "Requires"], + ["Blink", v"0.2.0", "HttpServer"], + ["Blink", v"0.2.0", "JSON"], + ["Blink", v"0.2.0", "Lazy"], + ["Blink", v"0.2.0", "MacroTools"], + ["Blink", v"0.2.0", "Mustache"], + ["Blink", v"0.2.0", "Reexport"], + ["Blink", v"0.2.0", "Requires"], + ["Blink", v"0.2.0", "WebSockets"], + ["Blink", v"0.2.1", "HttpServer"], + ["Blink", v"0.2.1", "JSON"], + ["Blink", v"0.2.1", "Lazy"], + ["Blink", v"0.2.1", "MacroTools"], + ["Blink", v"0.2.1", "Mustache"], + ["Blink", v"0.2.1", "Mux"], + ["Blink", v"0.2.1", "Reexport"], + ["Blink", v"0.2.1", "Requires"], + ["Blink", v"0.2.1", "WebSockets"], + ["Blink", v"0.3.4", "BinDeps"], + ["Blink", v"0.3.4", "HttpServer"], + ["Blink", v"0.3.4", "JSON"], + ["Blink", v"0.3.4", "Lazy"], + ["Blink", v"0.3.4", "MacroTools"], + ["Blink", v"0.3.4", "Mustache"], + ["Blink", v"0.3.4", "Mux"], + ["Blink", v"0.3.4", "Reexport"], + ["Blink", v"0.3.4", "Requires"], + ["Blink", v"0.3.4", "WebSockets"], + ["Blink", v"0.4.1", "BinDeps"], + ["Blink", v"0.4.1", "HttpServer"], + ["Blink", v"0.4.1", "Mustache"], + ["Blink", v"0.4.1", "Reexport"], + ["Blink", v"0.4.1", "Requires"], + ["Blink", v"0.4.1", "Compat", v"0.8.6"], + ["Blink", v"0.4.1", "JSON"], + ["Blink", v"0.4.1", "Lazy"], + ["Blink", v"0.4.1", "MacroTools"], + ["Blink", v"0.4.1", "Mux"], + ["Blink", v"0.4.1", "WebSockets"], + ["Blink", v"0.5.1", "BinDeps"], + ["Blink", v"0.5.1", "HttpServer"], + ["Blink", v"0.5.1", "Compat", v"0.8.6"], + ["Blink", v"0.5.1", "JSON"], + ["Blink", v"0.5.1", "MacroTools"], + ["Blink", v"0.5.1", "Mustache"], + ["Blink", v"0.5.1", "Lazy", v"0.11.3"], + ["Blink", v"0.5.1", "Mux"], + ["Blink", v"0.5.1", "Reexport"], + ["Blink", v"0.5.1", "WebSockets"], + ["Blocks", v"0.0.4"], + ["Blocks", v"0.1.0", "Compat"], + ["Blosc", v"0.1.1", "BinDeps"], + ["Blosc", v"0.1.5", "BinDeps"], + ["Blosc", v"0.1.5", "Compat"], + ["Blosc", v"0.2.0", "BinDeps"], + ["Blosc", v"0.2.0", "Compat", v"0.8.0"], + ["COFF", v"0.0.2", "DWARF"], + ["COFF", v"0.0.2", "ObjFileBase"], + ["COFF", v"0.0.2", "StructIO"], + ["CRC", v"0.1.0", "ArgParse"], + ["CRC", v"0.1.0", "Zlib"], + ["CRC", v"1.1.1", "ArgParse"], + ["CRC", v"1.1.1", "Compat"], + ["CRC", v"1.2.0", "ArgParse"], + ["Calculus", v"0.1.5"], + ["Calculus", v"0.1.6", "Compat"], + ["Calculus", v"0.1.14", "Compat", v"0.4.0"], + ["Calculus", v"0.1.15", "Compat", v"0.4.0"], + ["Calculus", v"0.2.0", "Compat", v"0.4.0"], + ["Calculus", v"0.2.2", "Compat", v"0.17.0"], + ["Calendar", v"0.4.3", "ICU"], + ["CatIndices", v"0.0.2", "CustomUnitRanges"], + ["CatIndices", v"0.0.2", "OffsetArrays"], + ["ChunkedArrays", v"0.0.1", "Compat"], + ["ChunkedArrays", v"0.0.1", "EllipsisNotation"], + ["ChunkedArrays", v"0.0.2", "Compat"], + ["ChunkedArrays", v"0.0.2", "EllipsisNotation"], + ["ChunkedArrays", v"0.1.0", "Compat"], + ["ChunkedArrays", v"0.1.0", "EllipsisNotation"], + ["ChunkedArrays", v"0.1.1", "EllipsisNotation", v"0.0.2"], + ["CodeTools", v"0.1.0", "JuliaParser"], + ["CodeTools", v"0.1.0", "LNR"], + ["CodeTools", v"0.1.0", "Lazy"], + ["CodeTools", v"0.1.0", "MacroTools"], + ["CodeTools", v"0.2.0", "Compat"], + ["CodeTools", v"0.2.0", "JuliaParser"], + ["CodeTools", v"0.2.0", "LNR"], + ["CodeTools", v"0.2.0", "Lazy"], + ["CodeTools", v"0.2.0", "MacroTools"], + ["CodeTools", v"0.4.1", "Compat"], + ["CodeTools", v"0.4.1", "JuliaParser"], + ["CodeTools", v"0.4.1", "LNR"], + ["CodeTools", v"0.4.1", "Lazy"], + ["CodeTools", v"0.4.1", "MacroTools"], + ["CodeTools", v"0.4.1", "Requires"], + ["CodeTools", v"0.4.3", "LNR"], + ["CodeTools", v"0.4.3", "Lazy"], + ["CodeTools", v"0.4.3", "MacroTools"], + ["Codecs", v"0.1.0", "Iterators"], + ["Codecs", v"0.1.3"], + ["Codecs", v"0.1.5", "Compat"], + ["Codecs", v"0.2.0", "Compat", v"0.7.20"], + ["Codecs", v"0.3.0", "Compat", v"0.17.0"], + ["ColorTypes", v"0.0.1", "FixedPointNumbers", v"0.0.0-", v"0.3.0"], + ["ColorTypes", v"0.0.1", "FixedSizeArrays"], + ["ColorTypes", v"0.1.7", "Compat"], + ["ColorTypes", v"0.1.7", "Docile"], + ["ColorTypes", v"0.1.7", "FixedPointNumbers", v"0.0.0-", v"0.3.0"], + ["ColorTypes", v"0.2.6", "FixedPointNumbers", v"0.1.0", v"0.3.0"], + ["ColorTypes", v"0.2.8", "FixedPointNumbers", v"0.1.0", v"0.3.0"], + ["ColorTypes", v"0.2.12", "FixedPointNumbers", v"0.1.0", v"0.3.0"], + ["ColorTypes", v"0.3.0", "FixedPointNumbers", v"0.3.0"], + ["ColorTypes", v"0.3.2", "Compat", v"0.16.0"], + ["ColorTypes", v"0.3.2", "FixedPointNumbers", v"0.3.0"], + ["ColorTypes", v"0.3.3", "Compat", v"0.17.0"], + ["ColorTypes", v"0.3.3", "FixedPointNumbers", v"0.3.0"], + ["ColorTypes", v"0.3.5", "Compat", v"0.18.0"], + ["ColorTypes", v"0.3.5", "FixedPointNumbers", v"0.3.0"], + ["ColorTypes", v"0.4.1", "Compat", v"0.18.0"], + ["ColorTypes", v"0.4.1", "FixedPointNumbers", v"0.3.0"], + ["ColorVectorSpace", v"0.0.5", "ColorTypes"], + ["ColorVectorSpace", v"0.0.5", "Compat"], + ["ColorVectorSpace", v"0.0.5", "FixedPointNumbers", v"0.0.0-", v"0.3.0"], + ["ColorVectorSpace", v"0.1.7", "ColorTypes", v"0.2.0"], + ["ColorVectorSpace", v"0.1.7", "FixedPointNumbers", v"0.1.0", v"0.3.0"], + ["ColorVectorSpace", v"0.1.8", "ColorTypes", v"0.2.0"], + ["ColorVectorSpace", v"0.1.8", "Compat", v"0.9.1"], + ["ColorVectorSpace", v"0.1.8", "FixedPointNumbers", v"0.1.0", v"0.3.0"], + ["ColorVectorSpace", v"0.1.10", "ColorTypes", v"0.2.7"], + ["ColorVectorSpace", v"0.1.10", "Compat", v"0.9.1"], + ["ColorVectorSpace", v"0.1.10", "FixedPointNumbers", v"0.1.8", v"0.3.0"], + ["ColorVectorSpace", v"0.1.12", "ColorTypes", v"0.2.7"], + ["ColorVectorSpace", v"0.1.12", "Compat", v"0.9.1"], + ["ColorVectorSpace", v"0.1.12", "FixedPointNumbers", v"0.1.8", v"0.3.0"], + ["ColorVectorSpace", v"0.2.0", "ColorTypes", v"0.3.0"], + ["ColorVectorSpace", v"0.2.0", "Compat", v"0.9.1"], + ["ColorVectorSpace", v"0.2.0", "FixedPointNumbers", v"0.3.0"], + ["ColorVectorSpace", v"0.3.0", "ColorTypes", v"0.3.3"], + ["ColorVectorSpace", v"0.3.0", "Colors", v"0.7.1"], + ["ColorVectorSpace", v"0.3.0", "Compat", v"0.9.1"], + ["ColorVectorSpace", v"0.3.0", "FixedPointNumbers", v"0.3.0"], + ["ColorVectorSpace", v"0.3.0", "StatsBase", v"0.8.2"], + ["ColorVectorSpace", v"0.4.0", "ColorTypes", v"0.3.3"], + ["ColorVectorSpace", v"0.4.0", "Colors", v"0.7.1"], + ["ColorVectorSpace", v"0.4.0", "Compat", v"0.18.0"], + ["ColorVectorSpace", v"0.4.0", "FixedPointNumbers", v"0.3.0"], + ["ColorVectorSpace", v"0.4.0", "StatsBase", v"0.8.2"], + ["ColorVectorSpace", v"0.4.2", "ColorTypes", v"0.4.0"], + ["ColorVectorSpace", v"0.4.2", "Colors", v"0.7.1"], + ["ColorVectorSpace", v"0.4.2", "Compat", v"0.18.0"], + ["ColorVectorSpace", v"0.4.2", "FixedPointNumbers", v"0.3.0"], + ["ColorVectorSpace", v"0.4.2", "StatsBase", v"0.8.2"], + ["Colors", v"0.4.7", "Compat", v"0.2.0"], + ["Colors", v"0.4.7", "Graphics", v"0.1.0"], + ["Colors", v"0.4.7", "FixedPointNumbers", v"0.0.0-", v"0.3.0"], + ["Colors", v"0.5.0", "ColorTypes"], + ["Colors", v"0.5.0", "Reexport"], + ["Colors", v"0.5.0", "Compat", v"0.2.0"], + ["Colors", v"0.5.0", "Graphics", v"0.1.0"], + ["Colors", v"0.5.0", "FixedPointNumbers", v"0.0.0-", v"0.3.0"], + ["Colors", v"0.5.4", "ColorTypes"], + ["Colors", v"0.5.4", "Reexport"], + ["Colors", v"0.5.4", "Compat", v"0.2.0"], + ["Colors", v"0.5.4", "FixedPointNumbers", v"0.0.0-", v"0.3.0"], + ["Colors", v"0.6.2", "Reexport"], + ["Colors", v"0.6.2", "ColorTypes", v"0.2.0"], + ["Colors", v"0.6.2", "FixedPointNumbers", v"0.1.0", v"0.3.0"], + ["Colors", v"0.6.4", "Compat"], + ["Colors", v"0.6.4", "Reexport"], + ["Colors", v"0.6.4", "ColorTypes", v"0.2.0"], + ["Colors", v"0.6.4", "FixedPointNumbers", v"0.1.0", v"0.3.0"], + ["Colors", v"0.6.6", "Reexport"], + ["Colors", v"0.6.6", "ColorTypes", v"0.2.0"], + ["Colors", v"0.6.6", "Compat", v"0.8.0"], + ["Colors", v"0.6.6", "FixedPointNumbers", v"0.1.0", v"0.3.0"], + ["Colors", v"0.6.7", "Reexport"], + ["Colors", v"0.6.7", "ColorTypes", v"0.2.0"], + ["Colors", v"0.6.7", "Compat", v"0.9.1"], + ["Colors", v"0.6.7", "FixedPointNumbers", v"0.1.0", v"0.3.0"], + ["Colors", v"0.6.8", "Reexport"], + ["Colors", v"0.6.8", "ColorTypes", v"0.2.7"], + ["Colors", v"0.6.8", "Compat", v"0.9.1"], + ["Colors", v"0.6.8", "FixedPointNumbers", v"0.1.8", v"0.3.0"], + ["Colors", v"0.6.9", "Reexport"], + ["Colors", v"0.6.9", "ColorTypes", v"0.2.9"], + ["Colors", v"0.6.9", "Compat", v"0.9.1"], + ["Colors", v"0.6.9", "FixedPointNumbers", v"0.1.8", v"0.3.0"], + ["Colors", v"0.7.0", "Reexport"], + ["Colors", v"0.7.0", "ColorTypes", v"0.3.0"], + ["Colors", v"0.7.0", "Compat", v"0.9.1"], + ["Colors", v"0.7.0", "FixedPointNumbers", v"0.3.0"], + ["Colors", v"0.7.1", "Reexport"], + ["Colors", v"0.7.1", "ColorTypes", v"0.3.0"], + ["Colors", v"0.7.1", "Compat", v"0.9.1"], + ["Colors", v"0.7.1", "FixedPointNumbers", v"0.3.0"], + ["Colors", v"0.7.2", "Reexport"], + ["Colors", v"0.7.2", "ColorTypes", v"0.3.0"], + ["Colors", v"0.7.2", "Compat", v"0.17.0"], + ["Colors", v"0.7.2", "FixedPointNumbers", v"0.3.0"], + ["Colors", v"0.7.3", "ColorTypes", v"0.3.0"], + ["Colors", v"0.7.3", "Compat", v"0.18.0"], + ["Colors", v"0.7.3", "FixedPointNumbers", v"0.3.0"], + ["Colors", v"0.7.3", "Reexport"], + ["Combinatorics", v"0.2.0", "Compat"], + ["Combinatorics", v"0.2.0", "Iterators"], + ["Combinatorics", v"0.2.0", "Polynomials"], + ["Combinatorics", v"0.3.2", "Iterators"], + ["Combinatorics", v"0.3.2", "Polynomials"], + ["Combinatorics", v"0.4.0", "Compat", v"0.18.0"], + ["Combinatorics", v"0.4.0", "Iterators"], + ["Combinatorics", v"0.4.0", "Polynomials"], + ["Compat", v"0.8.1"], + ["Compat", v"0.8.3"], + ["Compat", v"0.8.4"], + ["Compat", v"0.8.5"], + ["Compat", v"0.8.6"], + ["Compat", v"0.8.7"], + ["Compat", v"0.8.8"], + ["Compat", v"0.9.0"], + ["Compat", v"0.9.1"], + ["Compat", v"0.9.3"], + ["Compat", v"0.9.4"], + ["Compat", v"0.10.0"], + ["Compat", v"0.11.0"], + ["Compat", v"0.12.0"], + ["Compat", v"0.13.0"], + ["Compat", v"0.15.0"], + ["Compat", v"0.16.2"], + ["Compat", v"0.17.0"], + ["Compat", v"0.18.0"], + ["Compat", v"0.23.0"], + ["Compat", v"0.24.0"], + ["ComputationalResources", v"0.0.1"], + ["ComputationalResources", v"0.0.2", "Compat", v"0.17.0"], + ["Conda", v"0.1.5", "BinDeps"], + ["Conda", v"0.1.5", "Compat"], + ["Conda", v"0.1.5", "JSON"], + ["Conda", v"0.1.9", "BinDeps"], + ["Conda", v"0.1.9", "Compat"], + ["Conda", v"0.1.9", "JSON"], + ["Conda", v"0.2.2", "BinDeps"], + ["Conda", v"0.2.2", "Compat", v"0.7.15"], + ["Conda", v"0.2.2", "JSON"], + ["Conda", v"0.2.4", "BinDeps"], + ["Conda", v"0.2.4", "Compat", v"0.8.0"], + ["Conda", v"0.2.4", "JSON"], + ["Conda", v"0.2.5", "BinDeps"], + ["Conda", v"0.2.5", "Compat", v"0.7.20"], + ["Conda", v"0.2.5", "JSON"], + ["Conda", v"0.3.2", "BinDeps"], + ["Conda", v"0.3.2", "Compat", v"0.8.0"], + ["Conda", v"0.3.2", "JSON"], + ["Conda", v"0.5.3", "BinDeps"], + ["Conda", v"0.5.3", "Compat", v"0.8.0"], + ["Conda", v"0.5.3", "JSON"], + ["CoordinateTransformations", v"0.1.0", "FixedSizeArrays"], + ["CoordinateTransformations", v"0.1.0", "Rotations"], + ["CoordinateTransformations", v"0.2.0", "Compat", v"0.8.0", v"0.11.0"], + ["CoordinateTransformations", v"0.2.0", "FixedSizeArrays", v"0.2.2"], + ["CoordinateTransformations", v"0.2.0", "Rotations", v"0.1.0", v"0.2.0+"], + ["CoordinateTransformations", v"0.3.2", "Rotations", v"0.3.0"], + ["CoordinateTransformations", v"0.3.2", "StaticArrays"], + ["CoordinateTransformations", v"0.4.0", "Rotations", v"0.3.0"], + ["CoordinateTransformations", v"0.4.0", "StaticArrays"], + ["CoordinateTransformations", v"0.4.1", "Compat", v"0.17.0"], + ["CoordinateTransformations", v"0.4.1", "Rotations", v"0.3.0"], + ["CoordinateTransformations", v"0.4.1", "StaticArrays"], + ["CustomUnitRanges", v"0.0.4"], + ["DWARF", v"0.0.0", "ELF"], + ["DWARF", v"0.0.0", "StrPack"], + ["DWARF", v"0.1.0", "AbstractTrees"], + ["DWARF", v"0.1.0", "ObjFileBase"], + ["DWARF", v"0.1.0", "StructIO"], + ["DataArrays", v"0.4.0", "Reexport"], + ["DataArrays", v"0.4.0", "SpecialFunctions"], + ["DataArrays", v"0.4.0", "Compat", v"0.8.6"], + ["DataArrays", v"0.4.0", "StatsBase", v"0.3.0"], + ["DataFrames", v"0.0.0", "Options"], + ["DataFrames", v"0.0.0", "StatsBase", v"0.0.0", v"0.8.3"], + ["DataFrames", v"0.2.2", "GZip"], + ["DataFrames", v"0.2.2", "Options"], + ["DataFrames", v"0.2.2", "StatsBase", v"0.0.0", v"0.8.3"], + ["DataFrames", v"0.3.10", "GZip"], + ["DataFrames", v"0.3.10", "StatsBase", v"0.0.0", v"0.8.3"], + ["DataFrames", v"0.3.11", "Blocks"], + ["DataFrames", v"0.3.11", "GZip"], + ["DataFrames", v"0.3.11", "StatsBase", v"0.0.0", v"0.8.3"], + ["DataFrames", v"0.3.16", "Blocks"], + ["DataFrames", v"0.3.16", "GZip"], + ["DataFrames", v"0.3.16", "SortingAlgorithms"], + ["DataFrames", v"0.3.16", "StatsBase", v"0.0.0", v"0.8.3"], + ["DataFrames", v"0.4.2", "Blocks"], + ["DataFrames", v"0.4.2", "DataArrays"], + ["DataFrames", v"0.4.2", "GZip"], + ["DataFrames", v"0.4.2", "SortingAlgorithms"], + ["DataFrames", v"0.4.2", "Stats"], + ["DataFrames", v"0.5.0", "Blocks"], + ["DataFrames", v"0.5.0", "GZip"], + ["DataFrames", v"0.5.0", "SortingAlgorithms"], + ["DataFrames", v"0.5.0", "DataArrays", v"0.1.0-"], + ["DataFrames", v"0.5.0", "StatsBase", v"0.3.0-", v"0.8.3"], + ["DataFrames", v"0.5.3", "Blocks"], + ["DataFrames", v"0.5.3", "DataArrays"], + ["DataFrames", v"0.5.3", "GZip"], + ["DataFrames", v"0.5.3", "SortingAlgorithms"], + ["DataFrames", v"0.5.3", "StatsBase", v"0.0.0", v"0.8.3"], + ["DataFrames", v"0.5.4", "Blocks"], + ["DataFrames", v"0.5.4", "DataArrays"], + ["DataFrames", v"0.5.4", "GZip"], + ["DataFrames", v"0.5.4", "Reexport"], + ["DataFrames", v"0.5.4", "SortingAlgorithms"], + ["DataFrames", v"0.5.4", "StatsBase", v"0.3.9+", v"0.8.3"], + ["DataFrames", v"0.5.11", "DataArrays"], + ["DataFrames", v"0.5.11", "GZip"], + ["DataFrames", v"0.5.11", "Reexport"], + ["DataFrames", v"0.5.11", "SortingAlgorithms"], + ["DataFrames", v"0.5.11", "StatsBase", v"0.3.9+", v"0.8.3"], + ["DataFrames", v"0.6.1", "Compat"], + ["DataFrames", v"0.6.1", "DataArrays"], + ["DataFrames", v"0.6.1", "GZip"], + ["DataFrames", v"0.6.1", "Reexport"], + ["DataFrames", v"0.6.1", "SortingAlgorithms"], + ["DataFrames", v"0.6.1", "StatsBase", v"0.3.9+", v"0.8.3"], + ["DataFrames", v"0.6.5", "Compat"], + ["DataFrames", v"0.6.5", "DataArrays"], + ["DataFrames", v"0.6.5", "Docile"], + ["DataFrames", v"0.6.5", "GZip"], + ["DataFrames", v"0.6.5", "Reexport"], + ["DataFrames", v"0.6.5", "SortingAlgorithms"], + ["DataFrames", v"0.6.5", "StatsBase", v"0.3.9+", v"0.8.3"], + ["DataFrames", v"0.6.10", "Compat"], + ["DataFrames", v"0.6.10", "Docile"], + ["DataFrames", v"0.6.10", "GZip"], + ["DataFrames", v"0.6.10", "Reexport"], + ["DataFrames", v"0.6.10", "SortingAlgorithms"], + ["DataFrames", v"0.6.10", "DataArrays", v"0.2.15"], + ["DataFrames", v"0.6.10", "StatsBase", v"0.3.9+", v"0.8.3"], + ["DataFrames", v"0.7.0", "Docile"], + ["DataFrames", v"0.7.0", "GZip"], + ["DataFrames", v"0.7.0", "Reexport"], + ["DataFrames", v"0.7.0", "SortingAlgorithms"], + ["DataFrames", v"0.7.0", "Compat", v"0.7.12"], + ["DataFrames", v"0.7.0", "DataArrays", v"0.2.15"], + ["DataFrames", v"0.7.0", "StatsBase", v"0.8.0", v"0.8.3"], + ["DataFrames", v"0.7.2", "Docile"], + ["DataFrames", v"0.7.2", "GZip"], + ["DataFrames", v"0.7.2", "Reexport"], + ["DataFrames", v"0.7.2", "SortingAlgorithms"], + ["DataFrames", v"0.7.2", "Compat", v"0.7.17"], + ["DataFrames", v"0.7.2", "DataArrays", v"0.2.15"], + ["DataFrames", v"0.7.2", "StatsBase", v"0.8.0", v"0.8.3"], + ["DataFrames", v"0.7.3", "Docile"], + ["DataFrames", v"0.7.3", "GZip"], + ["DataFrames", v"0.7.3", "Reexport"], + ["DataFrames", v"0.7.3", "SortingAlgorithms"], + ["DataFrames", v"0.7.3", "Compat", v"0.7.19"], + ["DataFrames", v"0.7.3", "DataArrays", v"0.2.15"], + ["DataFrames", v"0.7.3", "StatsBase", v"0.8.0", v"0.8.3"], + ["DataFrames", v"0.7.4", "Docile"], + ["DataFrames", v"0.7.4", "GZip"], + ["DataFrames", v"0.7.4", "Reexport"], + ["DataFrames", v"0.7.4", "SortingAlgorithms"], + ["DataFrames", v"0.7.4", "Compat", v"0.7.19"], + ["DataFrames", v"0.7.4", "DataArrays", v"0.3.4"], + ["DataFrames", v"0.7.4", "StatsBase", v"0.8.0", v"0.8.3"], + ["DataFrames", v"0.7.6", "Docile"], + ["DataFrames", v"0.7.6", "GZip"], + ["DataFrames", v"0.7.6", "Reexport"], + ["DataFrames", v"0.7.6", "SortingAlgorithms"], + ["DataFrames", v"0.7.6", "Compat", v"0.7.19"], + ["DataFrames", v"0.7.6", "DataArrays", v"0.3.4"], + ["DataFrames", v"0.7.6", "StatsBase", v"0.8.3"], + ["DataFrames", v"0.7.8", "GZip"], + ["DataFrames", v"0.7.8", "Reexport"], + ["DataFrames", v"0.7.8", "SortingAlgorithms"], + ["DataFrames", v"0.7.8", "Compat", v"0.8.0"], + ["DataFrames", v"0.7.8", "DataArrays", v"0.3.4"], + ["DataFrames", v"0.7.8", "StatsBase", v"0.8.3"], + ["DataFrames", v"0.8.0", "GZip"], + ["DataFrames", v"0.8.0", "Reexport"], + ["DataFrames", v"0.8.0", "SortingAlgorithms"], + ["DataFrames", v"0.8.0", "Compat", v"0.8.4"], + ["DataFrames", v"0.8.0", "DataArrays", v"0.3.4"], + ["DataFrames", v"0.8.0", "StatsBase", v"0.8.3"], + ["DataFrames", v"0.8.3", "GZip"], + ["DataFrames", v"0.8.3", "Reexport"], + ["DataFrames", v"0.8.3", "SortingAlgorithms"], + ["DataFrames", v"0.8.3", "Compat", v"0.8.4"], + ["DataFrames", v"0.8.3", "DataArrays", v"0.3.4"], + ["DataFrames", v"0.8.3", "FileIO", v"0.1.2"], + ["DataFrames", v"0.8.3", "StatsBase", v"0.8.3"], + ["DataFrames", v"0.8.4", "GZip"], + ["DataFrames", v"0.8.4", "Reexport"], + ["DataFrames", v"0.8.4", "SortingAlgorithms"], + ["DataFrames", v"0.8.4", "Compat", v"0.8.4"], + ["DataFrames", v"0.8.4", "DataArrays", v"0.3.4"], + ["DataFrames", v"0.8.4", "FileIO", v"0.1.2"], + ["DataFrames", v"0.8.4", "StatsBase", v"0.11.0"], + ["DataFrames", v"0.8.5", "GZip"], + ["DataFrames", v"0.8.5", "Reexport"], + ["DataFrames", v"0.8.5", "SortingAlgorithms"], + ["DataFrames", v"0.8.5", "Compat", v"0.8.4"], + ["DataFrames", v"0.8.5", "DataArrays", v"0.3.4"], + ["DataFrames", v"0.8.5", "FileIO", v"0.1.2"], + ["DataFrames", v"0.8.5", "Juno", v"0.2.4"], + ["DataFrames", v"0.8.5", "StatsBase", v"0.11.0"], + ["DataFrames", v"0.9.1", "GZip"], + ["DataFrames", v"0.9.1", "Reexport"], + ["DataFrames", v"0.9.1", "SortingAlgorithms"], + ["DataFrames", v"0.9.1", "Compat", v"0.18.0"], + ["DataFrames", v"0.9.1", "DataArrays", v"0.3.4"], + ["DataFrames", v"0.9.1", "FileIO", v"0.1.2"], + ["DataFrames", v"0.9.1", "StatsBase", v"0.11.0"], + ["DataStructures", v"0.4.5"], + ["DataStructures", v"0.4.6", "Compat", v"0.8.5"], + ["DataStructures", v"0.5.1", "Compat", v"0.9.4"], + ["DataStructures", v"0.5.2", "Compat", v"0.9.4"], + ["DataStructures", v"0.5.3", "Compat", v"0.17.0"], + ["Dates", v"0.4.4"], + ["DelayDiffEq", v"0.0.1", "Combinatorics"], + ["DelayDiffEq", v"0.0.1", "DataStructures", v"0.4.6"], + ["DelayDiffEq", v"0.0.1", "DiffEqBase", v"0.5.0", v"0.7.0"], + ["DelayDiffEq", v"0.0.1", "RecursiveArrayTools", v"0.1.2"], + ["DelayDiffEq", v"0.0.1", "OrdinaryDiffEq", v"1.0.0", v"1.2.0"], + ["DelayDiffEq", v"0.1.0", "Combinatorics"], + ["DelayDiffEq", v"0.1.0", "DataStructures", v"0.4.6"], + ["DelayDiffEq", v"0.1.0", "DiffEqBase", v"0.8.0", v"0.15.0"], + ["DelayDiffEq", v"0.1.0", "OrdinaryDiffEq", v"1.2.0"], + ["DelayDiffEq", v"0.1.0", "RecursiveArrayTools", v"0.2.0"], + ["DelayDiffEq", v"0.2.0", "Combinatorics"], + ["DelayDiffEq", v"0.2.0", "DataStructures", v"0.4.6"], + ["DelayDiffEq", v"0.2.0", "DiffEqBase", v"0.8.0", v"0.15.0"], + ["DelayDiffEq", v"0.2.0", "OrdinaryDiffEq", v"1.6.0"], + ["DelayDiffEq", v"0.2.0", "RecursiveArrayTools", v"0.2.0"], + ["DelayDiffEq", v"0.3.0", "Combinatorics"], + ["DelayDiffEq", v"0.3.0", "DataStructures", v"0.4.6"], + ["DelayDiffEq", v"0.3.0", "DiffEqBase", v"0.15.0"], + ["DelayDiffEq", v"0.3.0", "OrdinaryDiffEq", v"1.6.0"], + ["DelayDiffEq", v"0.3.0", "RecursiveArrayTools", v"0.2.0"], + ["DiffBase", v"0.0.2", "Compat", v"0.7.15"], + ["DiffBase", v"0.1.0", "Compat", v"0.7.15"], + ["DiffEqBase", v"0.0.1", "RecipesBase", v"0.1.0"], + ["DiffEqBase", v"0.0.4", "Ranges", v"0.0.1"], + ["DiffEqBase", v"0.0.4", "RecipesBase", v"0.1.0"], + ["DiffEqBase", v"0.1.0", "Parameters"], + ["DiffEqBase", v"0.1.0", "Ranges", v"0.0.1"], + ["DiffEqBase", v"0.1.0", "RecursiveArrayTools"], + ["DiffEqBase", v"0.1.0", "RecipesBase", v"0.1.0"], + ["DiffEqBase", v"0.1.1", "Parameters"], + ["DiffEqBase", v"0.1.1", "Ranges", v"0.0.1"], + ["DiffEqBase", v"0.1.1", "RecursiveArrayTools"], + ["DiffEqBase", v"0.1.1", "RecipesBase", v"0.1.0"], + ["DiffEqBase", v"0.1.2", "Parameters", v"0.5.0"], + ["DiffEqBase", v"0.1.2", "Ranges", v"0.0.1"], + ["DiffEqBase", v"0.1.2", "RecipesBase", v"0.1.0"], + ["DiffEqBase", v"0.1.2", "RecursiveArrayTools", v"0.0.2"], + ["DiffEqBase", v"0.1.3", "Parameters", v"0.5.0"], + ["DiffEqBase", v"0.1.3", "Ranges", v"0.0.1"], + ["DiffEqBase", v"0.1.3", "RecipesBase", v"0.1.0"], + ["DiffEqBase", v"0.1.3", "RecursiveArrayTools", v"0.0.2"], + ["DiffEqBase", v"0.2.0", "Parameters", v"0.5.0"], + ["DiffEqBase", v"0.2.0", "Ranges", v"0.0.1"], + ["DiffEqBase", v"0.2.0", "RecipesBase", v"0.1.0"], + ["DiffEqBase", v"0.2.0", "RecursiveArrayTools", v"0.0.2"], + ["DiffEqBase", v"0.3.2", "Parameters", v"0.5.0"], + ["DiffEqBase", v"0.3.2", "Ranges", v"0.0.1"], + ["DiffEqBase", v"0.3.2", "RecipesBase", v"0.1.0"], + ["DiffEqBase", v"0.3.2", "RecursiveArrayTools", v"0.0.2"], + ["DiffEqBase", v"0.3.2", "SimpleTraits", v"0.1.1"], + ["DiffEqBase", v"0.4.0", "Parameters", v"0.5.0"], + ["DiffEqBase", v"0.4.0", "Ranges", v"0.0.1"], + ["DiffEqBase", v"0.4.0", "RecipesBase", v"0.1.0"], + ["DiffEqBase", v"0.4.0", "RecursiveArrayTools", v"0.0.2"], + ["DiffEqBase", v"0.4.0", "SimpleTraits", v"0.1.1"], + ["DiffEqBase", v"0.4.1", "Parameters", v"0.5.0"], + ["DiffEqBase", v"0.4.1", "Ranges", v"0.0.1"], + ["DiffEqBase", v"0.4.1", "RecipesBase", v"0.1.0"], + ["DiffEqBase", v"0.4.1", "RecursiveArrayTools", v"0.0.2"], + ["DiffEqBase", v"0.4.1", "SimpleTraits", v"0.1.1"], + ["DiffEqBase", v"0.5.0", "Parameters", v"0.5.0"], + ["DiffEqBase", v"0.5.0", "Ranges", v"0.0.1"], + ["DiffEqBase", v"0.5.0", "RecipesBase", v"0.1.0"], + ["DiffEqBase", v"0.5.0", "RecursiveArrayTools", v"0.0.2"], + ["DiffEqBase", v"0.5.0", "SimpleTraits", v"0.1.1"], + ["DiffEqBase", v"0.6.0", "Parameters", v"0.5.0"], + ["DiffEqBase", v"0.6.0", "Ranges", v"0.0.1"], + ["DiffEqBase", v"0.6.0", "RecipesBase", v"0.1.0"], + ["DiffEqBase", v"0.6.0", "RecursiveArrayTools", v"0.0.2"], + ["DiffEqBase", v"0.6.0", "SimpleTraits", v"0.1.1"], + ["DiffEqBase", v"0.7.0", "Parameters", v"0.5.0"], + ["DiffEqBase", v"0.7.0", "Ranges", v"0.0.1"], + ["DiffEqBase", v"0.7.0", "RecipesBase", v"0.1.0"], + ["DiffEqBase", v"0.7.0", "RecursiveArrayTools", v"0.0.2"], + ["DiffEqBase", v"0.7.0", "SimpleTraits", v"0.1.1"], + ["DiffEqBase", v"0.10.0", "Parameters", v"0.5.0"], + ["DiffEqBase", v"0.10.0", "Ranges", v"0.0.1"], + ["DiffEqBase", v"0.10.0", "RecipesBase", v"0.1.0"], + ["DiffEqBase", v"0.10.0", "RecursiveArrayTools", v"0.2.0"], + ["DiffEqBase", v"0.10.0", "SimpleTraits", v"0.1.1"], + ["DiffEqBase", v"0.11.0", "Parameters", v"0.5.0"], + ["DiffEqBase", v"0.11.0", "Ranges", v"0.0.1"], + ["DiffEqBase", v"0.11.0", "RecipesBase", v"0.1.0"], + ["DiffEqBase", v"0.11.0", "RecursiveArrayTools", v"0.2.0"], + ["DiffEqBase", v"0.11.0", "SimpleTraits", v"0.1.1"], + ["DiffEqBase", v"0.12.1", "Compat", v"0.19.0"], + ["DiffEqBase", v"0.12.1", "Parameters", v"0.5.0"], + ["DiffEqBase", v"0.12.1", "Ranges", v"0.0.1"], + ["DiffEqBase", v"0.12.1", "RecipesBase", v"0.1.0"], + ["DiffEqBase", v"0.12.1", "RecursiveArrayTools", v"0.2.0"], + ["DiffEqBase", v"0.12.1", "SimpleTraits", v"0.1.1"], + ["DiffEqBase", v"0.13.0", "Compat", v"0.19.0"], + ["DiffEqBase", v"0.13.0", "Parameters", v"0.5.0"], + ["DiffEqBase", v"0.13.0", "Ranges", v"0.0.1"], + ["DiffEqBase", v"0.13.0", "RecipesBase", v"0.1.0"], + ["DiffEqBase", v"0.13.0", "RecursiveArrayTools", v"0.2.0"], + ["DiffEqBase", v"0.13.0", "SimpleTraits", v"0.1.1"], + ["DiffEqBase", v"0.14.0", "Compat", v"0.19.0"], + ["DiffEqBase", v"0.14.0", "Parameters", v"0.5.0"], + ["DiffEqBase", v"0.14.0", "Ranges", v"0.0.1"], + ["DiffEqBase", v"0.14.0", "RecipesBase", v"0.1.0"], + ["DiffEqBase", v"0.14.0", "RecursiveArrayTools", v"0.2.0"], + ["DiffEqBase", v"0.14.0", "SimpleTraits", v"0.1.1"], + ["DiffEqBase", v"0.15.0", "Compat", v"0.19.0"], + ["DiffEqBase", v"0.15.0", "Parameters", v"0.5.0"], + ["DiffEqBase", v"0.15.0", "Ranges", v"0.0.1"], + ["DiffEqBase", v"0.15.0", "RecipesBase", v"0.1.0"], + ["DiffEqBase", v"0.15.0", "RecursiveArrayTools", v"0.2.0"], + ["DiffEqBase", v"0.15.0", "SimpleTraits", v"0.1.1"], + ["DiffEqBiological", v"0.0.1", "DiffEqBase"], + ["DiffEqBiological", v"0.0.1", "DiffEqJump"], + ["DiffEqCallbacks", v"0.0.2", "DiffEqBase", v"0.6.0"], + ["DiffEqDevTools", v"0.0.1", "DiffEqBase", v"0.0.0", v"0.5.0"], + ["DiffEqDevTools", v"0.0.1", "FiniteElementDiffEq"], + ["DiffEqDevTools", v"0.0.1", "OrdinaryDiffEq"], + ["DiffEqDevTools", v"0.0.1", "StochasticDiffEq"], + ["DiffEqDevTools", v"0.0.1", "RecipesBase", v"0.1.0"], + ["DiffEqDevTools", v"0.1.0", "DiffEqBase", v"0.0.0", v"0.5.0"], + ["DiffEqDevTools", v"0.1.0", "FiniteElementDiffEq"], + ["DiffEqDevTools", v"0.1.0", "OrdinaryDiffEq"], + ["DiffEqDevTools", v"0.1.0", "RecursiveArrayTools"], + ["DiffEqDevTools", v"0.1.0", "StochasticDiffEq"], + ["DiffEqDevTools", v"0.1.0", "RecipesBase", v"0.1.0"], + ["DiffEqDevTools", v"0.1.1", "DiffEqBase", v"0.1.3", v"0.5.0"], + ["DiffEqDevTools", v"0.1.1", "FiniteElementDiffEq", v"0.0.5"], + ["DiffEqDevTools", v"0.1.1", "OrdinaryDiffEq", v"0.1.1"], + ["DiffEqDevTools", v"0.1.1", "RecipesBase", v"0.1.0"], + ["DiffEqDevTools", v"0.1.1", "RecursiveArrayTools", v"0.0.2"], + ["DiffEqDevTools", v"0.1.1", "StochasticDiffEq", v"0.0.5"], + ["DiffEqDevTools", v"0.2.0", "DiffEqBase", v"0.2.0", v"0.5.0"], + ["DiffEqDevTools", v"0.2.0", "FiniteElementDiffEq", v"0.0.5"], + ["DiffEqDevTools", v"0.2.0", "RecipesBase", v"0.1.0"], + ["DiffEqDevTools", v"0.2.0", "RecursiveArrayTools", v"0.0.2"], + ["DiffEqDevTools", v"0.3.0", "DiffEqBase", v"0.3.0", v"0.5.0"], + ["DiffEqDevTools", v"0.3.0", "RecipesBase", v"0.1.0"], + ["DiffEqDevTools", v"0.3.0", "RecursiveArrayTools", v"0.0.2"], + ["DiffEqDevTools", v"0.4.0", "DiffEqBase", v"0.4.0", v"0.5.0"], + ["DiffEqDevTools", v"0.4.0", "RecipesBase", v"0.1.0"], + ["DiffEqDevTools", v"0.4.0", "RecursiveArrayTools", v"0.1.2"], + ["DiffEqDevTools", v"0.5.0", "DiffEqBase", v"0.4.0", v"0.5.0"], + ["DiffEqDevTools", v"0.5.0", "DiffEqPDEBase"], + ["DiffEqDevTools", v"0.5.0", "RecipesBase", v"0.1.0"], + ["DiffEqDevTools", v"0.5.0", "RecursiveArrayTools", v"0.1.2"], + ["DiffEqDevTools", v"0.6.0", "DiffEqBase", v"0.5.0", v"0.15.0"], + ["DiffEqDevTools", v"0.6.0", "DiffEqPDEBase"], + ["DiffEqDevTools", v"0.6.0", "RecipesBase", v"0.1.0"], + ["DiffEqDevTools", v"0.6.0", "RecursiveArrayTools", v"0.1.2"], + ["DiffEqDevTools", v"0.7.0", "DiffEqBase", v"0.15.0"], + ["DiffEqDevTools", v"0.7.0", "DiffEqPDEBase"], + ["DiffEqDevTools", v"0.7.0", "RecipesBase", v"0.1.0"], + ["DiffEqDevTools", v"0.7.0", "RecursiveArrayTools", v"0.1.2"], + ["DiffEqFinancial", v"0.0.1", "DiffEqBase", v"0.0.0", v"0.15.0"], + ["DiffEqFinancial", v"0.0.1", "StochasticDiffEq"], + ["DiffEqFinancial", v"0.1.0", "DiffEqBase", v"0.15.0"], + ["DiffEqFinancial", v"0.1.0", "StochasticDiffEq"], + ["DiffEqJump", v"0.0.1", "DiffEqBase"], + ["DiffEqJump", v"0.2.0", "DiffEqBase"], + ["DiffEqJump", v"0.2.0", "RecursiveArrayTools"], + ["DiffEqJump", v"0.3.0", "DiffEqBase", v"0.13.0"], + ["DiffEqJump", v"0.3.0", "RecursiveArrayTools"], + ["DiffEqMonteCarlo", v"0.1.0", "DiffEqBase", v"0.6.0", v"0.14.0"], + ["DiffEqMonteCarlo", v"0.1.0", "RecipesBase", v"0.1.0"], + ["DiffEqMonteCarlo", v"0.2.0", "DiffEqBase", v"0.14.0"], + ["DiffEqPDEBase", v"0.0.1", "ChunkedArrays"], + ["DiffEqPDEBase", v"0.0.1", "DiffEqBase", v"0.0.0", v"0.15.0"], + ["DiffEqPDEBase", v"0.0.1", "RecipesBase"], + ["DiffEqPDEBase", v"0.0.1", "VectorizedRoutines"], + ["DiffEqPDEBase", v"0.0.3", "ChunkedArrays"], + ["DiffEqPDEBase", v"0.0.3", "DiffEqBase", v"0.4.1", v"0.15.0"], + ["DiffEqPDEBase", v"0.0.3", "RecipesBase"], + ["DiffEqPDEBase", v"0.0.3", "VectorizedRoutines"], + ["DiffEqPDEBase", v"0.1.0", "ChunkedArrays"], + ["DiffEqPDEBase", v"0.1.0", "Compat", v"0.17.0"], + ["DiffEqPDEBase", v"0.1.0", "DiffEqBase", v"0.4.1", v"0.15.0"], + ["DiffEqPDEBase", v"0.1.0", "RecipesBase"], + ["DiffEqPDEBase", v"0.1.0", "VectorizedRoutines"], + ["DiffEqPDEBase", v"0.2.0", "ChunkedArrays"], + ["DiffEqPDEBase", v"0.2.0", "Compat", v"0.17.0"], + ["DiffEqPDEBase", v"0.2.0", "DiffEqBase", v"0.15.0"], + ["DiffEqPDEBase", v"0.2.0", "RecipesBase"], + ["DiffEqPDEBase", v"0.2.0", "VectorizedRoutines"], + ["DiffEqParamEstim", v"0.0.1", "DiffEqBase", v"0.0.0", v"0.14.0"], + ["DiffEqParamEstim", v"0.0.1", "LossFunctions"], + ["DiffEqParamEstim", v"0.0.1", "LsqFit"], + ["DiffEqParamEstim", v"0.0.1", "OrdinaryDiffEq"], + ["DiffEqParamEstim", v"0.0.1", "RecursiveArrayTools"], + ["DiffEqParamEstim", v"0.0.2", "DiffEqBase", v"0.1.2", v"0.14.0"], + ["DiffEqParamEstim", v"0.0.2", "LossFunctions", v"0.0.2"], + ["DiffEqParamEstim", v"0.0.2", "LsqFit", v"0.0.2"], + ["DiffEqParamEstim", v"0.0.2", "OrdinaryDiffEq", v"0.1.1"], + ["DiffEqParamEstim", v"0.0.2", "RecursiveArrayTools", v"0.0.2"], + ["DiffEqParamEstim", v"0.0.4", "DiffEqBase", v"0.1.2", v"0.14.0"], + ["DiffEqParamEstim", v"0.0.4", "LossFunctions", v"0.0.2"], + ["DiffEqParamEstim", v"0.0.4", "LsqFit", v"0.0.2"], + ["DiffEqParamEstim", v"0.0.4", "RecursiveArrayTools", v"0.0.2"], + ["DiffEqParamEstim", v"0.1.0", "Calculus"], + ["DiffEqParamEstim", v"0.1.0", "DiffEqBase", v"0.1.2", v"0.14.0"], + ["DiffEqParamEstim", v"0.1.0", "ForwardDiff"], + ["DiffEqParamEstim", v"0.1.0", "LossFunctions", v"0.0.2"], + ["DiffEqParamEstim", v"0.1.0", "LsqFit", v"0.0.2"], + ["DiffEqParamEstim", v"0.1.0", "RecursiveArrayTools", v"0.0.2"], + ["DiffEqParamEstim", v"0.2.0", "Calculus"], + ["DiffEqParamEstim", v"0.2.0", "Optim"], + ["DiffEqParamEstim", v"0.2.0", "Compat", v"0.17.0"], + ["DiffEqParamEstim", v"0.2.0", "DiffEqBase", v"0.14.0"], + ["DiffEqParamEstim", v"0.2.0", "ForwardDiff"], + ["DiffEqParamEstim", v"0.2.0", "LossFunctions", v"0.0.2"], + ["DiffEqParamEstim", v"0.2.0", "LsqFit", v"0.0.2"], + ["DiffEqParamEstim", v"0.2.0", "RecursiveArrayTools", v"0.0.2"], + ["DiffEqProblemLibrary", v"0.0.1", "AlgebraicDiffEq"], + ["DiffEqProblemLibrary", v"0.0.1", "DiffEqBase", v"0.0.0", v"0.15.0"], + ["DiffEqProblemLibrary", v"0.0.1", "FiniteElementDiffEq"], + ["DiffEqProblemLibrary", v"0.0.1", "JLD", v"0.6.5"], + ["DiffEqProblemLibrary", v"0.0.1", "OrdinaryDiffEq"], + ["DiffEqProblemLibrary", v"0.0.1", "ParameterizedFunctions", v"0.2.0"], + ["DiffEqProblemLibrary", v"0.0.1", "StochasticDiffEq"], + ["DiffEqProblemLibrary", v"0.1.0", "AlgebraicDiffEq"], + ["DiffEqProblemLibrary", v"0.1.0", "DiffEqBase", v"0.0.0", v"0.15.0"], + ["DiffEqProblemLibrary", v"0.1.0", "FiniteElementDiffEq"], + ["DiffEqProblemLibrary", v"0.1.0", "JLD", v"0.6.5"], + ["DiffEqProblemLibrary", v"0.1.0", "ParameterizedFunctions", v"0.2.0"], + ["DiffEqProblemLibrary", v"0.1.0", "StochasticDiffEq"], + ["DiffEqProblemLibrary", v"0.2.0", "AlgebraicDiffEq", v"0.0.2"], + ["DiffEqProblemLibrary", v"0.2.0", "DiffEqBase", v"0.2.0", v"0.15.0"], + ["DiffEqProblemLibrary", v"0.2.0", "FiniteElementDiffEq", v"0.0.5"], + ["DiffEqProblemLibrary", v"0.2.0", "JLD", v"0.6.5"], + ["DiffEqProblemLibrary", v"0.2.0", "ParameterizedFunctions", v"0.2.0"], + ["DiffEqProblemLibrary", v"0.2.0", "StochasticDiffEq", v"0.1.0"], + ["DiffEqProblemLibrary", v"0.3.2", "AlgebraicDiffEq", v"0.0.2"], + ["DiffEqProblemLibrary", v"0.3.2", "DiffEqBase", v"0.2.0", v"0.15.0"], + ["DiffEqProblemLibrary", v"0.3.2", "FiniteElementDiffEq", v"0.0.5"], + ["DiffEqProblemLibrary", v"0.3.2", "JLD", v"0.6.5"], + ["DiffEqProblemLibrary", v"0.3.2", "ParameterizedFunctions", v"0.2.0"], + ["DiffEqProblemLibrary", v"0.4.0", "DiffEqBase", v"0.2.0", v"0.15.0"], + ["DiffEqProblemLibrary", v"0.4.0", "DiffEqPDEBase"], + ["DiffEqProblemLibrary", v"0.4.0", "FiniteElementDiffEq", v"0.0.5"], + ["DiffEqProblemLibrary", v"0.4.0", "JLD", v"0.6.5"], + ["DiffEqProblemLibrary", v"0.4.0", "ParameterizedFunctions", v"0.5.0"], + ["DiffEqProblemLibrary", v"0.5.0", "DiffEqBase", v"0.15.0"], + ["DiffEqProblemLibrary", v"0.5.0", "DiffEqPDEBase"], + ["DiffEqProblemLibrary", v"0.5.0", "JLD", v"0.6.5"], + ["DiffEqProblemLibrary", v"0.5.0", "ParameterizedFunctions", v"0.5.0"], + ["DiffEqSensitivity", v"0.0.1", "DiffEqBase", v"0.0.0", v"0.15.0"], + ["DiffEqSensitivity", v"0.0.2", "DiffEqBase", v"0.1.2", v"0.15.0"], + ["DiffEqSensitivity", v"0.0.4", "DiffEqBase", v"0.2.0", v"0.15.0"], + ["DiffEqSensitivity", v"0.1.0", "DiffEqBase", v"0.15.0"], + ["DifferentialEquations", v"0.4.0", "ChunkedArrays", v"0.0.2"], + ["DifferentialEquations", v"0.4.0", "Compat", v"0.8.8"], + ["DifferentialEquations", v"0.4.0", "DiffEqBase", v"0.0.0", v"0.15.0"], + ["DifferentialEquations", v"0.4.0", "ForwardDiff", v"0.2.4"], + ["DifferentialEquations", v"0.4.0", "GenericSVD", v"0.0.2"], + ["DifferentialEquations", v"0.4.0", "InplaceOps", v"0.0.5"], + ["DifferentialEquations", v"0.4.0", "IterativeSolvers", v"0.2.2"], + ["DifferentialEquations", v"0.4.0", "Parameters", v"0.3.1"], + ["DifferentialEquations", v"0.4.0", "OrdinaryDiffEq", v"0.0.0", v"1.2.0"], + ["DifferentialEquations", v"0.4.0", "Plots", v"0.9.2"], + ["DifferentialEquations", v"0.4.0", "SIUnits", v"0.0.6"], + ["DifferentialEquations", v"0.4.0", "StochasticDiffEq", v"0.0.0", v"1.0.0"], + ["DifferentialEquations", v"0.4.2", "ChunkedArrays", v"0.0.2"], + ["DifferentialEquations", v"0.4.2", "Compat", v"0.8.8"], + ["DifferentialEquations", v"0.4.2", "DiffEqBase", v"0.0.0", v"0.15.0"], + ["DifferentialEquations", v"0.4.2", "ForwardDiff", v"0.2.4"], + ["DifferentialEquations", v"0.4.2", "GenericSVD", v"0.0.2"], + ["DifferentialEquations", v"0.4.2", "InplaceOps", v"0.0.5"], + ["DifferentialEquations", v"0.4.2", "IterativeSolvers", v"0.2.2"], + ["DifferentialEquations", v"0.4.2", "Parameters", v"0.5.0"], + ["DifferentialEquations", v"0.4.2", "OrdinaryDiffEq", v"0.0.0", v"1.2.0"], + ["DifferentialEquations", v"0.4.2", "Plots", v"0.9.2"], + ["DifferentialEquations", v"0.4.2", "SIUnits", v"0.0.6"], + ["DifferentialEquations", v"0.4.2", "StochasticDiffEq", v"0.0.0", v"1.0.0"], + ["DifferentialEquations", v"0.5.0", "ChunkedArrays", v"0.0.2"], + ["DifferentialEquations", v"0.5.0", "Compat", v"0.8.8"], + ["DifferentialEquations", v"0.5.0", "DiffEqBase", v"0.0.0", v"0.15.0"], + ["DifferentialEquations", v"0.5.0", "ForwardDiff", v"0.2.4"], + ["DifferentialEquations", v"0.5.0", "GenericSVD", v"0.0.2"], + ["DifferentialEquations", v"0.5.0", "InplaceOps", v"0.0.5"], + ["DifferentialEquations", v"0.5.0", "IterativeSolvers", v"0.2.2"], + ["DifferentialEquations", v"0.5.0", "NLsolve", v"0.7.3"], + ["DifferentialEquations", v"0.5.0", "Parameters", v"0.5.0"], + ["DifferentialEquations", v"0.5.0", "OrdinaryDiffEq", v"0.0.0", v"1.2.0"], + ["DifferentialEquations", v"0.5.0", "Plots", v"0.9.2"], + ["DifferentialEquations", v"0.5.0", "Ranges", v"0.0.1"], + ["DifferentialEquations", v"0.5.0", "StochasticDiffEq", v"0.0.0", v"1.0.0"], + ["DifferentialEquations", v"0.5.0", "Sundials", v"0.3.0"], + ["DifferentialEquations", v"1.0.0", "AlgebraicDiffEq"], + ["DifferentialEquations", v"1.0.0", "DiffEqDevTools"], + ["DifferentialEquations", v"1.0.0", "DiffEqParamEstim"], + ["DifferentialEquations", v"1.0.0", "DiffEqSensitivity"], + ["DifferentialEquations", v"1.0.0", "FiniteElementDiffEq"], + ["DifferentialEquations", v"1.0.0", "Reexport"], + ["DifferentialEquations", v"1.0.0", "DiffEqBase", v"0.0.0", v"0.15.0"], + ["DifferentialEquations", v"1.0.0", "OrdinaryDiffEq", v"0.0.0", v"1.2.0"], + ["DifferentialEquations", v"1.0.0", "StochasticDiffEq", v"0.0.0", v"1.0.0"], + ["DifferentialEquations", v"1.0.0", "StokesDiffEq"], + ["DifferentialEquations", v"1.0.0", "Sundials"], + ["DifferentialEquations", v"1.1.0", "AlgebraicDiffEq", v"0.0.2"], + ["DifferentialEquations", v"1.1.0", "DiffEqBase", v"0.1.3", v"0.15.0"], + ["DifferentialEquations", v"1.1.0", "DiffEqDevTools", v"0.1.1"], + ["DifferentialEquations", v"1.1.0", "DiffEqParamEstim", v"0.0.2"], + ["DifferentialEquations", v"1.1.0", "DiffEqSensitivity", v"0.0.2"], + ["DifferentialEquations", v"1.1.0", "FiniteElementDiffEq", v"0.0.5"], + ["DifferentialEquations", v"1.1.0", "OrdinaryDiffEq", v"0.1.1", v"1.2.0"], + ["DifferentialEquations", v"1.1.0", "ParameterizedFunctions", v"0.3.2"], + ["DifferentialEquations", v"1.1.0", "Reexport", v"0.0.3"], + ["DifferentialEquations", v"1.1.0", "StochasticDiffEq", v"0.0.5", v"1.0.0"], + ["DifferentialEquations", v"1.1.0", "StokesDiffEq", v"0.0.2"], + ["DifferentialEquations", v"1.1.0", "Sundials", v"0.3.0"], + ["DifferentialEquations", v"1.4.0", "AlgebraicDiffEq", v"0.0.2"], + ["DifferentialEquations", v"1.4.0", "DiffEqBase", v"0.2.0", v"0.15.0"], + ["DifferentialEquations", v"1.4.0", "DiffEqDevTools", v"0.2.0"], + ["DifferentialEquations", v"1.4.0", "DiffEqParamEstim", v"0.0.2"], + ["DifferentialEquations", v"1.4.0", "DiffEqProblemLibrary", v"0.2.0"], + ["DifferentialEquations", v"1.4.0", "DiffEqSensitivity", v"0.0.2"], + ["DifferentialEquations", v"1.4.0", "FiniteElementDiffEq", v"0.0.5"], + ["DifferentialEquations", v"1.4.0", "OrdinaryDiffEq", v"0.2.0", v"1.2.0"], + ["DifferentialEquations", v"1.4.0", "ParameterizedFunctions", v"0.3.2"], + ["DifferentialEquations", v"1.4.0", "Reexport", v"0.0.3"], + ["DifferentialEquations", v"1.4.0", "StochasticDiffEq", v"0.1.0", v"1.0.0"], + ["DifferentialEquations", v"1.4.0", "StokesDiffEq", v"0.0.2"], + ["DifferentialEquations", v"1.4.0", "Sundials", v"0.4.1"], + ["DifferentialEquations", v"1.5.0", "DiffEqPDEBase"], + ["DifferentialEquations", v"1.5.0", "AlgebraicDiffEq", v"0.0.2"], + ["DifferentialEquations", v"1.5.0", "DiffEqBase", v"0.2.0", v"0.15.0"], + ["DifferentialEquations", v"1.5.0", "DiffEqDevTools", v"0.2.0"], + ["DifferentialEquations", v"1.5.0", "DiffEqParamEstim", v"0.0.2"], + ["DifferentialEquations", v"1.5.0", "DiffEqSensitivity", v"0.0.2"], + ["DifferentialEquations", v"1.5.0", "FiniteElementDiffEq", v"0.0.5"], + ["DifferentialEquations", v"1.5.0", "OrdinaryDiffEq", v"0.2.0", v"1.2.0"], + ["DifferentialEquations", v"1.5.0", "ParameterizedFunctions", v"0.3.2"], + ["DifferentialEquations", v"1.5.0", "Reexport", v"0.0.3"], + ["DifferentialEquations", v"1.5.0", "StochasticDiffEq", v"0.1.0", v"1.0.0"], + ["DifferentialEquations", v"1.5.0", "StokesDiffEq", v"0.0.2"], + ["DifferentialEquations", v"1.5.0", "Sundials", v"0.4.1"], + ["DifferentialEquations", v"1.6.0", "AlgebraicDiffEq", v"0.0.2"], + ["DifferentialEquations", v"1.6.0", "DelayDiffEq"], + ["DifferentialEquations", v"1.6.0", "DiffEqBase", v"0.2.0", v"0.15.0"], + ["DifferentialEquations", v"1.6.0", "DiffEqCallbacks"], + ["DifferentialEquations", v"1.6.0", "DiffEqMonteCarlo"], + ["DifferentialEquations", v"1.6.0", "DiffEqPDEBase"], + ["DifferentialEquations", v"1.6.0", "DiffEqDevTools", v"0.2.0"], + ["DifferentialEquations", v"1.6.0", "DiffEqParamEstim", v"0.0.2"], + ["DifferentialEquations", v"1.6.0", "DiffEqSensitivity", v"0.0.2"], + ["DifferentialEquations", v"1.6.0", "FiniteElementDiffEq", v"0.0.5"], + ["DifferentialEquations", v"1.6.0", "Reexport", v"0.0.3"], + ["DifferentialEquations", v"1.6.0", "OrdinaryDiffEq", v"0.2.0", v"1.2.0"], + ["DifferentialEquations", v"1.6.0", "ParameterizedFunctions", v"0.3.2"], + ["DifferentialEquations", v"1.6.0", "StochasticDiffEq", v"0.1.0", v"1.0.0"], + ["DifferentialEquations", v"1.6.0", "StokesDiffEq", v"0.0.2"], + ["DifferentialEquations", v"1.6.0", "Sundials", v"0.4.1"], + ["DifferentialEquations", v"1.7.0", "DiffEqCallbacks"], + ["DifferentialEquations", v"1.7.0", "DiffEqMonteCarlo"], + ["DifferentialEquations", v"1.7.0", "DiffEqPDEBase"], + ["DifferentialEquations", v"1.7.0", "AlgebraicDiffEq", v"0.0.2"], + ["DifferentialEquations", v"1.7.0", "DelayDiffEq", v"0.1.0"], + ["DifferentialEquations", v"1.7.0", "DiffEqDevTools", v"0.2.0"], + ["DifferentialEquations", v"1.7.0", "DiffEqParamEstim", v"0.0.2"], + ["DifferentialEquations", v"1.7.0", "DiffEqSensitivity", v"0.0.2"], + ["DifferentialEquations", v"1.7.0", "FiniteElementDiffEq", v"0.0.5"], + ["DifferentialEquations", v"1.7.0", "OrdinaryDiffEq", v"1.2.0"], + ["DifferentialEquations", v"1.7.0", "ParameterizedFunctions", v"0.3.2"], + ["DifferentialEquations", v"1.7.0", "Reexport", v"0.0.3"], + ["DifferentialEquations", v"1.7.0", "DiffEqBase", v"0.8.0", v"0.15.0"], + ["DifferentialEquations", v"1.7.0", "StochasticDiffEq", v"1.0.0"], + ["DifferentialEquations", v"1.7.0", "StokesDiffEq", v"0.0.2"], + ["DifferentialEquations", v"1.7.0", "Sundials", v"0.4.1"], + ["DifferentialEquations", v"1.9.0", "DiffEqBiological"], + ["DifferentialEquations", v"1.9.0", "DiffEqCallbacks"], + ["DifferentialEquations", v"1.9.0", "AlgebraicDiffEq", v"0.0.2"], + ["DifferentialEquations", v"1.9.0", "DelayDiffEq", v"0.1.0"], + ["DifferentialEquations", v"1.9.0", "DiffEqBase", v"0.8.0", v"0.15.0"], + ["DifferentialEquations", v"1.9.0", "DiffEqFinancial"], + ["DifferentialEquations", v"1.9.0", "DiffEqJump"], + ["DifferentialEquations", v"1.9.0", "DiffEqMonteCarlo"], + ["DifferentialEquations", v"1.9.0", "DiffEqPDEBase"], + ["DifferentialEquations", v"1.9.0", "DiffEqDevTools", v"0.2.0"], + ["DifferentialEquations", v"1.9.0", "DiffEqParamEstim", v"0.0.2"], + ["DifferentialEquations", v"1.9.0", "DiffEqSensitivity", v"0.0.2"], + ["DifferentialEquations", v"1.9.0", "FiniteElementDiffEq", v"0.0.5"], + ["DifferentialEquations", v"1.9.0", "MultiScaleArrays"], + ["DifferentialEquations", v"1.9.0", "OrdinaryDiffEq", v"1.2.0"], + ["DifferentialEquations", v"1.9.0", "PyDSTool"], + ["DifferentialEquations", v"1.9.0", "ParameterizedFunctions", v"0.3.2"], + ["DifferentialEquations", v"1.9.0", "Reexport", v"0.0.3"], + ["DifferentialEquations", v"1.9.0", "StochasticDiffEq", v"1.0.0"], + ["DifferentialEquations", v"1.9.0", "StokesDiffEq", v"0.0.2"], + ["DifferentialEquations", v"1.9.0", "Sundials", v"0.4.1"], + ["DifferentialEquations", v"1.9.1", "DiffEqBiological"], + ["DifferentialEquations", v"1.9.1", "DiffEqCallbacks"], + ["DifferentialEquations", v"1.9.1", "AlgebraicDiffEq", v"0.0.2"], + ["DifferentialEquations", v"1.9.1", "DelayDiffEq", v"0.1.0"], + ["DifferentialEquations", v"1.9.1", "DiffEqBase", v"0.8.0", v"0.15.0"], + ["DifferentialEquations", v"1.9.1", "DiffEqFinancial"], + ["DifferentialEquations", v"1.9.1", "DiffEqJump"], + ["DifferentialEquations", v"1.9.1", "DiffEqMonteCarlo"], + ["DifferentialEquations", v"1.9.1", "DiffEqPDEBase"], + ["DifferentialEquations", v"1.9.1", "DiffEqDevTools", v"0.2.0"], + ["DifferentialEquations", v"1.9.1", "DiffEqParamEstim", v"0.0.2"], + ["DifferentialEquations", v"1.9.1", "DiffEqSensitivity", v"0.0.2"], + ["DifferentialEquations", v"1.9.1", "FiniteElementDiffEq", v"0.0.5"], + ["DifferentialEquations", v"1.9.1", "MultiScaleArrays"], + ["DifferentialEquations", v"1.9.1", "OrdinaryDiffEq", v"1.2.0"], + ["DifferentialEquations", v"1.9.1", "ParameterizedFunctions", v"0.3.2"], + ["DifferentialEquations", v"1.9.1", "Reexport", v"0.0.3"], + ["DifferentialEquations", v"1.9.1", "StochasticDiffEq", v"1.0.0"], + ["DifferentialEquations", v"1.9.1", "StokesDiffEq", v"0.0.2"], + ["DifferentialEquations", v"1.9.1", "Sundials", v"0.4.1"], + ["DifferentialEquations", v"1.10.1", "DiffEqBase", v"0.15.0"], + ["DifferentialEquations", v"1.10.1", "DiffEqBiological"], + ["DifferentialEquations", v"1.10.1", "DiffEqCallbacks"], + ["DifferentialEquations", v"1.10.1", "AlgebraicDiffEq", v"0.0.2"], + ["DifferentialEquations", v"1.10.1", "DiffEqFinancial"], + ["DifferentialEquations", v"1.10.1", "DiffEqJump"], + ["DifferentialEquations", v"1.10.1", "DiffEqMonteCarlo"], + ["DifferentialEquations", v"1.10.1", "DiffEqPDEBase"], + ["DifferentialEquations", v"1.10.1", "MultiScaleArrays"], + ["DifferentialEquations", v"1.10.1", "DelayDiffEq", v"0.1.0"], + ["DifferentialEquations", v"1.10.1", "DiffEqDevTools", v"0.2.0"], + ["DifferentialEquations", v"1.10.1", "DiffEqParamEstim", v"0.0.2"], + ["DifferentialEquations", v"1.10.1", "DiffEqSensitivity", v"0.0.2"], + ["DifferentialEquations", v"1.10.1", "FiniteElementDiffEq", v"0.0.5"], + ["DifferentialEquations", v"1.10.1", "OrdinaryDiffEq", v"1.2.0"], + ["DifferentialEquations", v"1.10.1", "ParameterizedFunctions", v"0.3.2"], + ["DifferentialEquations", v"1.10.1", "Reexport", v"0.0.3"], + ["DifferentialEquations", v"1.10.1", "StochasticDiffEq", v"1.0.0"], + ["DifferentialEquations", v"1.10.1", "StokesDiffEq", v"0.0.2"], + ["DifferentialEquations", v"1.10.1", "Sundials", v"0.4.1"], + ["Distances", v"0.1.1", "ArrayViews", v"0.4.0-"], + ["Distances", v"0.2.0", "ArrayViews", v"0.4.8-"], + ["Distances", v"0.2.2", "Compat"], + ["Distances", v"0.2.2", "ArrayViews", v"0.4.8-"], + ["Distances", v"0.3.2", "Compat", v"0.8.4"], + ["Distances", v"0.4.0"], + ["Distances", v"0.4.1", "Compat", v"0.18.0"], + ["Distributions", v"0.6.4", "ArrayViews", v"0.4.8"], + ["Distributions", v"0.6.4", "Compat", v"0.2.4"], + ["Distributions", v"0.6.4", "PDMats", v"0.3.1", v"0.4.0"], + ["Distributions", v"0.6.4", "StatsBase", v"0.6.10"], + ["Distributions", v"0.6.4", "StatsFuns", v"0.0.0", v"0.3.0"], + ["Distributions", v"0.6.5", "ArrayViews", v"0.4.9"], + ["Distributions", v"0.6.5", "Compat", v"0.3.1"], + ["Distributions", v"0.6.5", "PDMats", v"0.3.1", v"0.4.0"], + ["Distributions", v"0.6.5", "StatsBase", v"0.6.10"], + ["Distributions", v"0.6.5", "StatsFuns", v"0.0.0", v"0.3.0"], + ["Distributions", v"0.6.7", "ArrayViews", v"0.4.10"], + ["Distributions", v"0.6.7", "Compat", v"0.3.2"], + ["Distributions", v"0.6.7", "PDMats", v"0.3.1", v"0.4.0"], + ["Distributions", v"0.6.7", "StatsBase", v"0.6.13"], + ["Distributions", v"0.6.7", "StatsFuns", v"0.0.0", v"0.3.0"], + ["Distributions", v"0.7.6", "ArrayViews", v"0.4.12"], + ["Distributions", v"0.7.6", "Compat", v"0.4.0"], + ["Distributions", v"0.7.6", "PDMats", v"0.3.2", v"0.4.0"], + ["Distributions", v"0.7.6", "StatsBase", v"0.6.14"], + ["Distributions", v"0.7.6", "StatsFuns", v"0.0.0", v"0.3.0"], + ["Distributions", v"0.8.9", "ArrayViews", v"0.4.12"], + ["Distributions", v"0.8.9", "Compat", v"0.4.0"], + ["Distributions", v"0.8.9", "PDMats", v"0.3.2", v"0.4.0"], + ["Distributions", v"0.8.9", "StatsBase", v"0.7.0"], + ["Distributions", v"0.8.9", "StatsFuns", v"0.1.1", v"0.3.0"], + ["Distributions", v"0.8.10", "ArrayViews", v"0.4.12"], + ["Distributions", v"0.8.10", "Compat", v"0.4.0"], + ["Distributions", v"0.8.10", "PDMats", v"0.4.0", v"0.5.0"], + ["Distributions", v"0.8.10", "StatsBase", v"0.7.0"], + ["Distributions", v"0.8.10", "StatsFuns", v"0.1.1", v"0.3.0"], + ["Distributions", v"0.9.0", "Compat", v"0.2.17"], + ["Distributions", v"0.9.0", "PDMats", v"0.4.1", v"0.5.0"], + ["Distributions", v"0.9.0", "StatsBase", v"0.7.0"], + ["Distributions", v"0.9.0", "StatsFuns", v"0.1.1", v"0.3.0"], + ["Distributions", v"0.10.2", "Calculus"], + ["Distributions", v"0.10.2", "Compat", v"0.8.4"], + ["Distributions", v"0.10.2", "PDMats", v"0.4.2", v"0.5.0"], + ["Distributions", v"0.10.2", "StatsBase", v"0.8.3"], + ["Distributions", v"0.10.2", "StatsFuns", v"0.3.0"], + ["Distributions", v"0.11.1", "Calculus"], + ["Distributions", v"0.11.1", "Compat", v"0.9.2"], + ["Distributions", v"0.11.1", "PDMats", v"0.5.0"], + ["Distributions", v"0.11.1", "StatsBase", v"0.8.3"], + ["Distributions", v"0.11.1", "StatsFuns", v"0.3.1"], + ["Distributions", v"0.12.0", "Calculus"], + ["Distributions", v"0.12.0", "Compat", v"0.14.0"], + ["Distributions", v"0.12.0", "PDMats", v"0.5.4"], + ["Distributions", v"0.12.0", "QuadGK", v"0.1.1"], + ["Distributions", v"0.12.0", "StatsBase", v"0.8.3"], + ["Distributions", v"0.12.0", "StatsFuns", v"0.3.1"], + ["Distributions", v"0.12.4", "Calculus"], + ["Distributions", v"0.12.4", "Compat", v"0.18.0"], + ["Distributions", v"0.12.4", "PDMats", v"0.5.4"], + ["Distributions", v"0.12.4", "QuadGK", v"0.1.1"], + ["Distributions", v"0.12.4", "SpecialFunctions", v"0.1.0"], + ["Distributions", v"0.12.4", "StatsBase", v"0.8.3"], + ["Distributions", v"0.12.4", "StatsFuns", v"0.3.1"], + ["Distributions", v"0.12.5", "Calculus"], + ["Distributions", v"0.12.5", "Compat", v"0.18.0"], + ["Distributions", v"0.12.5", "PDMats", v"0.6.0"], + ["Distributions", v"0.12.5", "QuadGK", v"0.1.1"], + ["Distributions", v"0.12.5", "SpecialFunctions", v"0.1.0"], + ["Distributions", v"0.12.5", "StatsBase", v"0.8.3"], + ["Distributions", v"0.12.5", "StatsFuns", v"0.3.1"], + ["Docile", v"0.1.0", "AnsiColor"], + ["Docile", v"0.1.0", "Markdown"], + ["Docile", v"0.3.1"], + ["Docile", v"0.3.2", "Compat"], + ["Docile", v"0.4.6", "Compat"], + ["Docile", v"0.4.13", "Compat", v"0.3.3"], + ["Docile", v"0.5.18", "Compat", v"0.3.5"], + ["Docile", v"0.5.23", "Compat", v"0.7.1"], + ["DualNumbers", v"0.1.0", "Calculus"], + ["DualNumbers", v"0.1.3", "Calculus"], + ["DualNumbers", v"0.1.3", "NaNMath"], + ["DualNumbers", v"0.1.5", "Calculus"], + ["DualNumbers", v"0.1.5", "Compat"], + ["DualNumbers", v"0.1.5", "NaNMath"], + ["DualNumbers", v"0.2.2", "Calculus"], + ["DualNumbers", v"0.2.2", "NaNMath"], + ["DualNumbers", v"0.3.0", "Calculus"], + ["DualNumbers", v"0.3.0", "NaNMath"], + ["DualNumbers", v"0.3.0", "Compat", v"0.9.1"], + ["ELF", v"0.0.0", "StrPack"], + ["ELF", v"0.1.0", "DWARF"], + ["ELF", v"0.1.0", "FileIO"], + ["ELF", v"0.1.0", "ObjFileBase"], + ["ELF", v"0.1.0", "StructIO"], + ["EllipsisNotation", v"0.0.1"], + ["EllipsisNotation", v"0.1.0"], + ["FFTViews", v"0.0.1", "CustomUnitRanges"], + ["FFTViews", v"0.0.2", "CustomUnitRanges"], + ["FFTViews", v"0.0.2", "Compat", v"0.17.0"], + ["FactCheck", v"0.0.0"], + ["FactCheck", v"0.0.2"], + ["FactCheck", v"0.2.2"], + ["FactCheck", v"0.4.2", "Compat"], + ["FactCheck", v"0.4.3", "Compat", v"0.7.18"], + ["FileIO", v"0.0.5", "Compat"], + ["FileIO", v"0.0.5", "Docile"], + ["FileIO", v"0.0.6", "Docile"], + ["FileIO", v"0.0.6", "Compat", v"0.7.15"], + ["FileIO", v"0.1.1", "Compat", v"0.7.19"], + ["FileIO", v"0.2.1", "Compat", v"0.7.19"], + ["FileIO", v"0.3.0", "Compat", v"0.9.5"], + ["FileIO", v"0.3.1", "Compat", v"0.17.0"], + ["FiniteElementDiffEq", v"0.0.3", "ChunkedArrays", v"0.1.0"], + ["FiniteElementDiffEq", v"0.0.3", "DiffEqBase", v"0.0.0", v"0.15.0"], + ["FiniteElementDiffEq", v"0.0.3", "ForwardDiff", v"0.2.4"], + ["FiniteElementDiffEq", v"0.0.3", "GenericSVD", v"0.0.2"], + ["FiniteElementDiffEq", v"0.0.3", "IterativeSolvers", v"0.2.2"], + ["FiniteElementDiffEq", v"0.0.3", "NLsolve", v"0.7.3"], + ["FiniteElementDiffEq", v"0.0.3", "Parameters", v"0.5.0"], + ["FiniteElementDiffEq", v"0.0.3", "Plots", v"0.9.2"], + ["FiniteElementDiffEq", v"0.0.3", "RecipesBase", v"0.1.0"], + ["FiniteElementDiffEq", v"0.0.3", "VectorizedRoutines", v"0.0.2"], + ["FiniteElementDiffEq", v"0.0.4", "ChunkedArrays", v"0.1.0"], + ["FiniteElementDiffEq", v"0.0.4", "DiffEqBase", v"0.0.0", v"0.15.0"], + ["FiniteElementDiffEq", v"0.0.4", "ForwardDiff", v"0.2.4"], + ["FiniteElementDiffEq", v"0.0.4", "GenericSVD", v"0.0.2"], + ["FiniteElementDiffEq", v"0.0.4", "IterativeSolvers", v"0.2.2"], + ["FiniteElementDiffEq", v"0.0.4", "NLsolve", v"0.7.3"], + ["FiniteElementDiffEq", v"0.0.4", "Parameters", v"0.5.0"], + ["FiniteElementDiffEq", v"0.0.4", "RecipesBase", v"0.1.0"], + ["FiniteElementDiffEq", v"0.0.4", "VectorizedRoutines", v"0.0.2"], + ["FiniteElementDiffEq", v"0.0.5", "ChunkedArrays", v"0.1.0"], + ["FiniteElementDiffEq", v"0.0.5", "DiffEqBase", v"0.1.1", v"0.15.0"], + ["FiniteElementDiffEq", v"0.0.5", "ForwardDiff", v"0.2.4"], + ["FiniteElementDiffEq", v"0.0.5", "GenericSVD", v"0.0.2"], + ["FiniteElementDiffEq", v"0.0.5", "IterativeSolvers", v"0.2.2"], + ["FiniteElementDiffEq", v"0.0.5", "Juno", v"0.2.4"], + ["FiniteElementDiffEq", v"0.0.5", "NLsolve", v"0.7.3"], + ["FiniteElementDiffEq", v"0.0.5", "Parameters", v"0.5.0"], + ["FiniteElementDiffEq", v"0.0.5", "RecipesBase", v"0.1.0"], + ["FiniteElementDiffEq", v"0.0.5", "VectorizedRoutines", v"0.0.2"], + ["FiniteElementDiffEq", v"0.2.0", "ChunkedArrays", v"0.1.0"], + ["FiniteElementDiffEq", v"0.2.0", "DiffEqBase", v"0.4.0", v"0.15.0"], + ["FiniteElementDiffEq", v"0.2.0", "ForwardDiff", v"0.2.4"], + ["FiniteElementDiffEq", v"0.2.0", "GenericSVD", v"0.0.2"], + ["FiniteElementDiffEq", v"0.2.0", "IterativeSolvers", v"0.2.2"], + ["FiniteElementDiffEq", v"0.2.0", "Juno", v"0.2.4"], + ["FiniteElementDiffEq", v"0.2.0", "NLsolve", v"0.7.3"], + ["FiniteElementDiffEq", v"0.2.0", "Parameters", v"0.5.0"], + ["FiniteElementDiffEq", v"0.2.0", "RecipesBase", v"0.1.0"], + ["FiniteElementDiffEq", v"0.2.0", "VectorizedRoutines", v"0.0.2"], + ["FiniteElementDiffEq", v"0.2.1", "ChunkedArrays", v"0.1.0"], + ["FiniteElementDiffEq", v"0.2.1", "DiffEqBase", v"0.4.0", v"0.15.0"], + ["FiniteElementDiffEq", v"0.2.1", "DiffEqPDEBase"], + ["FiniteElementDiffEq", v"0.2.1", "ForwardDiff", v"0.2.4"], + ["FiniteElementDiffEq", v"0.2.1", "GenericSVD", v"0.0.2"], + ["FiniteElementDiffEq", v"0.2.1", "IterativeSolvers", v"0.2.2"], + ["FiniteElementDiffEq", v"0.2.1", "Juno", v"0.2.4"], + ["FiniteElementDiffEq", v"0.2.1", "NLsolve", v"0.7.3"], + ["FiniteElementDiffEq", v"0.2.1", "Parameters", v"0.5.0"], + ["FiniteElementDiffEq", v"0.2.1", "VectorizedRoutines", v"0.0.2"], + ["FiniteElementDiffEq", v"0.3.0", "ChunkedArrays", v"0.1.0"], + ["FiniteElementDiffEq", v"0.3.0", "DiffEqBase", v"0.15.0"], + ["FiniteElementDiffEq", v"0.3.0", "DiffEqPDEBase"], + ["FiniteElementDiffEq", v"0.3.0", "ForwardDiff", v"0.2.4"], + ["FiniteElementDiffEq", v"0.3.0", "GenericSVD", v"0.0.2"], + ["FiniteElementDiffEq", v"0.3.0", "IterativeSolvers", v"0.2.2"], + ["FiniteElementDiffEq", v"0.3.0", "Juno", v"0.2.4"], + ["FiniteElementDiffEq", v"0.3.0", "NLsolve", v"0.7.3"], + ["FiniteElementDiffEq", v"0.3.0", "Parameters", v"0.5.0"], + ["FiniteElementDiffEq", v"0.3.0", "VectorizedRoutines", v"0.0.2"], + ["FixedPointNumbers", v"0.0.5"], + ["FixedPointNumbers", v"0.0.12", "Compat", v"0.2.2"], + ["FixedPointNumbers", v"0.1.2"], + ["FixedPointNumbers", v"0.1.4", "Compat", v"0.7.14"], + ["FixedPointNumbers", v"0.1.7", "Compat", v"0.9.1"], + ["FixedPointNumbers", v"0.2.1", "Compat", v"0.9.1"], + ["FixedPointNumbers", v"0.3.0", "Compat", v"0.9.1"], + ["FixedPointNumbers", v"0.3.2", "Compat", v"0.9.5"], + ["FixedPointNumbers", v"0.3.6", "Compat", v"0.17.0"], + ["FixedSizeArrays", v"0.1.0"], + ["FixedSizeArrays", v"0.1.1", "Compat"], + ["FixedSizeArrays", v"0.2.1", "Compat", v"0.7.15"], + ["FixedSizeArrays", v"0.2.2", "Compat", v"0.7.15"], + ["FixedSizeArrays", v"0.2.5", "Compat", v"0.8.7"], + ["ForwardDiff", v"0.2.5", "Calculus"], + ["ForwardDiff", v"0.2.5", "NaNMath"], + ["ForwardDiff", v"0.2.5", "Compat", v"0.8.6"], + ["ForwardDiff", v"0.3.4", "Calculus", v"0.2.0"], + ["ForwardDiff", v"0.3.4", "Compat", v"0.8.6"], + ["ForwardDiff", v"0.3.4", "DiffBase", v"0.0.3"], + ["ForwardDiff", v"0.3.4", "NaNMath", v"0.2.2"], + ["ForwardDiff", v"0.3.5", "Calculus", v"0.1.15"], + ["ForwardDiff", v"0.3.5", "Compat", v"0.8.6"], + ["ForwardDiff", v"0.3.5", "DiffBase", v"0.0.1"], + ["ForwardDiff", v"0.3.5", "NaNMath", v"0.2.1"], + ["ForwardDiff", v"0.4.2", "Calculus", v"0.2.0"], + ["ForwardDiff", v"0.4.2", "Compat", v"0.19.0"], + ["ForwardDiff", v"0.4.2", "DiffBase", v"0.0.3"], + ["ForwardDiff", v"0.4.2", "NaNMath", v"0.2.2"], + ["ForwardDiff", v"0.4.2", "SpecialFunctions", v"0.1.0"], + ["GZip", v"0.2.13"], + ["GZip", v"0.2.16", "Compat"], + ["GZip", v"0.2.18", "Compat", v"0.4.8"], + ["GZip", v"0.2.19", "Compat", v"0.7.9"], + ["GZip", v"0.2.20", "Compat", v"0.8.0"], + ["GZip", v"0.3.0", "Compat", v"0.9.5"], + ["Gallium", v"0.0.1", "ASTInterpreter"], + ["Gallium", v"0.0.1", "AbstractTrees"], + ["Gallium", v"0.0.1", "DWARF"], + ["Gallium", v"0.0.1", "ELF"], + ["Gallium", v"0.0.1", "MachO"], + ["Gallium", v"0.0.1", "TerminalUI"], + ["Gallium", v"0.0.2", "ASTInterpreter"], + ["Gallium", v"0.0.2", "AbstractTrees"], + ["Gallium", v"0.0.2", "DWARF"], + ["Gallium", v"0.0.2", "ELF"], + ["Gallium", v"0.0.2", "MachO"], + ["Gallium", v"0.0.2", "ObjFileBase"], + ["Gallium", v"0.0.2", "TerminalUI"], + ["Gallium", v"0.0.4", "ASTInterpreter"], + ["Gallium", v"0.0.4", "AbstractTrees"], + ["Gallium", v"0.0.4", "COFF"], + ["Gallium", v"0.0.4", "CRC"], + ["Gallium", v"0.0.4", "DWARF"], + ["Gallium", v"0.0.4", "ELF"], + ["Gallium", v"0.0.4", "MachO"], + ["Gallium", v"0.0.4", "ObjFileBase"], + ["Gallium", v"0.0.4", "TerminalUI"], + ["GenericSVD", v"0.0.2", "Compat", v"0.8.6"], + ["GnuTLS", v"0.0.1", "Nettle"], + ["GnuTLS", v"0.0.1", "BinDeps", v"0.2.1-"], + ["GnuTLS", v"0.0.4", "Compat"], + ["GnuTLS", v"0.0.4", "Nettle"], + ["GnuTLS", v"0.0.4", "BinDeps", v"0.2.1-"], + ["GnuTLS", v"0.0.5", "BinDeps"], + ["GnuTLS", v"0.0.5", "Compat"], + ["GnuTLS", v"0.0.5", "Nettle"], + ["Graphics", v"0.1.1"], + ["Graphics", v"0.1.3", "Colors"], + ["Graphics", v"0.1.4", "Colors"], + ["Graphics", v"0.1.4", "Compat", v"0.17.0"], + ["Graphics", v"0.2.0", "Colors"], + ["Graphics", v"0.2.0", "Compat", v"0.17.0"], + ["Graphics", v"0.2.0", "NaNMath", v"0.2.4"], + ["HDF5", v"0.2.1", "StrPack"], + ["HDF5", v"0.2.9"], + ["HDF5", v"0.4.6", "BinDeps"], + ["HDF5", v"0.5.2", "BinDeps"], + ["HDF5", v"0.5.2", "Blosc"], + ["HDF5", v"0.5.2", "Compat"], + ["HDF5", v"0.5.5", "BinDeps"], + ["HDF5", v"0.5.5", "Blosc"], + ["HDF5", v"0.5.5", "Compat", v"0.4.11"], + ["HDF5", v"0.6.0", "BinDeps"], + ["HDF5", v"0.6.0", "Blosc"], + ["HDF5", v"0.6.0", "Compat", v"0.7.1"], + ["HDF5", v"0.6.1", "BinDeps"], + ["HDF5", v"0.6.1", "Blosc"], + ["HDF5", v"0.6.1", "Compat", v"0.7.16"], + ["HDF5", v"0.7.3", "BinDeps"], + ["HDF5", v"0.7.3", "Blosc"], + ["HDF5", v"0.7.3", "Compat", v"0.8.0"], + ["HDF5", v"0.8.0", "BinDeps"], + ["HDF5", v"0.8.0", "Blosc"], + ["HDF5", v"0.8.0", "Compat", v"0.17.0"], + ["Hiccup", v"0.0.0", "Lazy"], + ["Hiccup", v"0.0.1", "Lazy"], + ["Hiccup", v"0.0.1", "MacroTools"], + ["Hiccup", v"0.0.2", "Compat"], + ["Hiccup", v"0.0.2", "Lazy"], + ["Hiccup", v"0.0.2", "MacroTools"], + ["Hiccup", v"0.0.3", "Lazy"], + ["Hiccup", v"0.0.3", "MacroTools"], + ["Hiccup", v"0.0.3", "Compat", v"0.8.2"], + ["Hiccup", v"0.1.1", "Compat", v"0.8.2"], + ["Hiccup", v"0.1.1", "MacroTools", v"0.3.4"], + ["HttpCommon", v"0.0.1"], + ["HttpCommon", v"0.0.2", "Calendar"], + ["HttpCommon", v"0.0.2", "FactCheck", v"0.0.1"], + ["HttpCommon", v"0.0.5", "Calendar"], + ["HttpCommon", v"0.0.5", "FactCheck", v"0.1.0-"], + ["HttpCommon", v"0.0.12", "Dates"], + ["HttpCommon", v"0.1.1", "Compat"], + ["HttpCommon", v"0.1.1", "Dates"], + ["HttpCommon", v"0.2.0", "Compat"], + ["HttpCommon", v"0.2.0", "Dates"], + ["HttpCommon", v"0.2.0", "URIParser"], + ["HttpCommon", v"0.2.4", "URIParser"], + ["HttpCommon", v"0.2.7", "URIParser"], + ["HttpCommon", v"0.2.7", "Compat", v"0.7.20"], + ["HttpParser", v"0.0.0", "HttpCommon"], + ["HttpParser", v"0.0.1", "BinDeps"], + ["HttpParser", v"0.0.1", "HttpCommon"], + ["HttpParser", v"0.0.2"], + ["HttpParser", v"0.0.3", "HttpCommon"], + ["HttpParser", v"0.0.3", "BinDeps", v"0.2.1-"], + ["HttpParser", v"0.0.4", "HttpCommon"], + ["HttpParser", v"0.0.4", "BinDeps", v"0.2.5-"], + ["HttpParser", v"0.0.11", "BinDeps", v"0.2.5-"], + ["HttpParser", v"0.0.11", "HttpCommon", v"0.0.3-"], + ["HttpParser", v"0.1.0", "BinDeps"], + ["HttpParser", v"0.1.0", "Compat"], + ["HttpParser", v"0.1.0", "HttpCommon"], + ["HttpParser", v"0.1.1", "BinDeps"], + ["HttpParser", v"0.1.1", "HttpCommon"], + ["HttpParser", v"0.2.0", "BinDeps"], + ["HttpParser", v"0.2.0", "HttpCommon"], + ["HttpParser", v"0.2.0", "Compat", v"0.7.20"], + ["HttpServer", v"0.0.1", "HttpCommon"], + ["HttpServer", v"0.0.1", "HttpParser"], + ["HttpServer", v"0.0.3", "GnuTLS"], + ["HttpServer", v"0.0.3", "HttpCommon"], + ["HttpServer", v"0.0.3", "HttpParser"], + ["HttpServer", v"0.0.7", "GnuTLS"], + ["HttpServer", v"0.0.7", "HttpCommon", v"0.0.3-"], + ["HttpServer", v"0.0.7", "HttpParser", v"0.0.5-"], + ["HttpServer", v"0.0.8", "GnuTLS"], + ["HttpServer", v"0.0.8", "HttpCommon"], + ["HttpServer", v"0.0.8", "HttpParser"], + ["HttpServer", v"0.0.11", "Docile"], + ["HttpServer", v"0.0.11", "GnuTLS"], + ["HttpServer", v"0.0.11", "HttpCommon"], + ["HttpServer", v"0.0.11", "HttpParser"], + ["HttpServer", v"0.1.2", "Compat"], + ["HttpServer", v"0.1.2", "Docile"], + ["HttpServer", v"0.1.2", "GnuTLS"], + ["HttpServer", v"0.1.2", "HttpCommon"], + ["HttpServer", v"0.1.2", "HttpParser"], + ["HttpServer", v"0.1.5", "HttpCommon"], + ["HttpServer", v"0.1.5", "HttpParser"], + ["HttpServer", v"0.1.5", "MbedTLS"], + ["HttpServer", v"0.1.7", "HttpCommon"], + ["HttpServer", v"0.1.7", "HttpParser"], + ["HttpServer", v"0.1.7", "MbedTLS"], + ["HttpServer", v"0.1.7", "Compat", v"0.7.16"], + ["HttpServer", v"0.2.0", "HttpCommon"], + ["HttpServer", v"0.2.0", "HttpParser"], + ["HttpServer", v"0.2.0", "MbedTLS"], + ["HttpServer", v"0.2.0", "Compat", v"0.17.0"], + ["ICU", v"0.2.1"], + ["ICU", v"0.4.4", "BinDeps"], + ["ImageAxes", v"0.0.2", "AxisArrays"], + ["ImageAxes", v"0.0.2", "Colors"], + ["ImageAxes", v"0.0.2", "ImageCore"], + ["ImageAxes", v"0.0.2", "Reexport"], + ["ImageAxes", v"0.0.2", "SimpleTraits"], + ["ImageAxes", v"0.1.1", "AxisArrays"], + ["ImageAxes", v"0.1.1", "Colors"], + ["ImageAxes", v"0.1.1", "FixedPointNumbers", v"0.3.0"], + ["ImageAxes", v"0.1.1", "ImageCore"], + ["ImageAxes", v"0.1.1", "Reexport"], + ["ImageAxes", v"0.1.1", "SimpleTraits"], + ["ImageAxes", v"0.2.1", "AxisArrays"], + ["ImageAxes", v"0.2.1", "Colors"], + ["ImageAxes", v"0.2.1", "FixedPointNumbers", v"0.3.0"], + ["ImageAxes", v"0.2.1", "MappedArrays"], + ["ImageAxes", v"0.2.1", "Reexport"], + ["ImageAxes", v"0.2.1", "SimpleTraits"], + ["ImageAxes", v"0.2.1", "ImageCore", v"0.2.0"], + ["ImageCore", v"0.0.3", "Colors"], + ["ImageCore", v"0.0.3", "Graphics"], + ["ImageCore", v"0.0.3", "FixedPointNumbers", v"0.0.0-", v"0.3.0"], + ["ImageCore", v"0.0.3", "MappedArrays"], + ["ImageCore", v"0.0.4", "Colors"], + ["ImageCore", v"0.0.4", "Graphics"], + ["ImageCore", v"0.0.4", "FixedPointNumbers", v"0.0.0-", v"0.3.0"], + ["ImageCore", v"0.0.4", "MappedArrays", v"0.0.3"], + ["ImageCore", v"0.0.5", "Colors"], + ["ImageCore", v"0.0.5", "Graphics"], + ["ImageCore", v"0.0.5", "FixedPointNumbers", v"0.0.0-", v"0.3.0"], + ["ImageCore", v"0.0.5", "MappedArrays", v"0.0.3"], + ["ImageCore", v"0.0.5", "OffsetArrays"], + ["ImageCore", v"0.0.5", "ShowItLikeYouBuildIt"], + ["ImageCore", v"0.1.1", "Colors"], + ["ImageCore", v"0.1.1", "Graphics"], + ["ImageCore", v"0.1.1", "FixedPointNumbers", v"0.3.0"], + ["ImageCore", v"0.1.1", "MappedArrays", v"0.0.3"], + ["ImageCore", v"0.1.1", "OffsetArrays"], + ["ImageCore", v"0.1.1", "ShowItLikeYouBuildIt"], + ["ImageCore", v"0.1.2", "ColorTypes"], + ["ImageCore", v"0.1.2", "Colors"], + ["ImageCore", v"0.1.2", "Graphics"], + ["ImageCore", v"0.1.2", "FixedPointNumbers", v"0.3.0"], + ["ImageCore", v"0.1.2", "MappedArrays", v"0.0.3"], + ["ImageCore", v"0.1.2", "OffsetArrays"], + ["ImageCore", v"0.1.2", "ShowItLikeYouBuildIt"], + ["ImageCore", v"0.1.5", "ColorTypes"], + ["ImageCore", v"0.1.5", "Colors"], + ["ImageCore", v"0.1.5", "Graphics"], + ["ImageCore", v"0.1.5", "Compat", v"0.19.0"], + ["ImageCore", v"0.1.5", "FixedPointNumbers", v"0.3.0"], + ["ImageCore", v"0.1.5", "MappedArrays", v"0.0.3"], + ["ImageCore", v"0.1.5", "OffsetArrays"], + ["ImageCore", v"0.1.5", "ShowItLikeYouBuildIt"], + ["ImageCore", v"0.2.0", "ColorTypes"], + ["ImageCore", v"0.2.0", "Colors"], + ["ImageCore", v"0.2.0", "Graphics"], + ["ImageCore", v"0.2.0", "Compat", v"0.19.0"], + ["ImageCore", v"0.2.0", "FixedPointNumbers", v"0.3.0"], + ["ImageCore", v"0.2.0", "MappedArrays", v"0.0.3"], + ["ImageCore", v"0.2.0", "OffsetArrays"], + ["ImageCore", v"0.2.0", "ShowItLikeYouBuildIt"], + ["ImageCore", v"0.3.0", "Colors"], + ["ImageCore", v"0.3.0", "Graphics"], + ["ImageCore", v"0.3.0", "ColorTypes", v"0.4.0"], + ["ImageCore", v"0.3.0", "Compat", v"0.19.0"], + ["ImageCore", v"0.3.0", "FixedPointNumbers", v"0.3.0"], + ["ImageCore", v"0.3.0", "MappedArrays", v"0.0.3"], + ["ImageCore", v"0.3.0", "OffsetArrays"], + ["ImageCore", v"0.3.0", "ShowItLikeYouBuildIt"], + ["ImageFiltering", v"0.0.2", "CatIndices"], + ["ImageFiltering", v"0.0.2", "ColorVectorSpace"], + ["ImageFiltering", v"0.0.2", "Colors"], + ["ImageFiltering", v"0.0.2", "ComputationalResources"], + ["ImageFiltering", v"0.0.2", "ImageCore"], + ["ImageFiltering", v"0.0.2", "DataStructures", v"0.4.6"], + ["ImageFiltering", v"0.0.2", "FFTViews"], + ["ImageFiltering", v"0.0.2", "MappedArrays"], + ["ImageFiltering", v"0.0.2", "OffsetArrays"], + ["ImageFiltering", v"0.0.2", "StaticArrays", v"0.0.5"], + ["ImageFiltering", v"0.0.2", "TiledIteration"], + ["ImageFiltering", v"0.0.2", "FixedPointNumbers", v"0.0.0-", v"0.3.0"], + ["ImageFiltering", v"0.1.2", "CatIndices"], + ["ImageFiltering", v"0.1.2", "ColorVectorSpace"], + ["ImageFiltering", v"0.1.2", "Colors"], + ["ImageFiltering", v"0.1.2", "ComputationalResources"], + ["ImageFiltering", v"0.1.2", "FFTViews"], + ["ImageFiltering", v"0.1.2", "ImageCore"], + ["ImageFiltering", v"0.1.2", "DataStructures", v"0.4.6"], + ["ImageFiltering", v"0.1.2", "MappedArrays"], + ["ImageFiltering", v"0.1.2", "OffsetArrays"], + ["ImageFiltering", v"0.1.2", "FixedPointNumbers", v"0.3.0"], + ["ImageFiltering", v"0.1.2", "StaticArrays", v"0.0.5"], + ["ImageFiltering", v"0.1.2", "TiledIteration"], + ["ImageFiltering", v"0.1.4", "CatIndices"], + ["ImageFiltering", v"0.1.4", "ColorVectorSpace"], + ["ImageFiltering", v"0.1.4", "Colors"], + ["ImageFiltering", v"0.1.4", "ComputationalResources"], + ["ImageFiltering", v"0.1.4", "Compat", v"0.18.0"], + ["ImageFiltering", v"0.1.4", "DataStructures", v"0.4.6"], + ["ImageFiltering", v"0.1.4", "FFTViews"], + ["ImageFiltering", v"0.1.4", "ImageCore"], + ["ImageFiltering", v"0.1.4", "MappedArrays"], + ["ImageFiltering", v"0.1.4", "OffsetArrays"], + ["ImageFiltering", v"0.1.4", "TiledIteration"], + ["ImageFiltering", v"0.1.4", "FixedPointNumbers", v"0.3.0"], + ["ImageFiltering", v"0.1.4", "StaticArrays", v"0.0.5"], + ["ImageMagick", v"0.0.1", "BinDeps"], + ["ImageMagick", v"0.0.1", "ColorTypes"], + ["ImageMagick", v"0.0.1", "Compat"], + ["ImageMagick", v"0.0.1", "FileIO"], + ["ImageMagick", v"0.0.1", "FixedPointNumbers", v"0.0.0-", v"0.3.0"], + ["ImageMagick", v"0.0.1", "Images", v"0.0.0-", v"0.6.0"], + ["ImageMagick", v"0.1.3", "BinDeps"], + ["ImageMagick", v"0.1.3", "ColorTypes", v"0.2.0"], + ["ImageMagick", v"0.1.3", "FileIO"], + ["ImageMagick", v"0.1.3", "FixedPointNumbers", v"0.1.0", v"0.3.0"], + ["ImageMagick", v"0.1.3", "Images", v"0.0.0-", v"0.6.0"], + ["ImageMagick", v"0.1.6", "BinDeps"], + ["ImageMagick", v"0.1.6", "ColorTypes", v"0.2.0"], + ["ImageMagick", v"0.1.6", "Compat", v"0.7.7"], + ["ImageMagick", v"0.1.6", "FileIO"], + ["ImageMagick", v"0.1.6", "FixedPointNumbers", v"0.1.0", v"0.3.0"], + ["ImageMagick", v"0.1.6", "Images", v"0.0.0-", v"0.6.0"], + ["ImageMagick", v"0.1.7", "BinDeps"], + ["ImageMagick", v"0.1.7", "ColorTypes", v"0.2.0"], + ["ImageMagick", v"0.1.7", "Compat", v"0.8.4"], + ["ImageMagick", v"0.1.7", "FileIO"], + ["ImageMagick", v"0.1.7", "FixedPointNumbers", v"0.1.0", v"0.3.0"], + ["ImageMagick", v"0.1.7", "Images", v"0.0.0-", v"0.6.0"], + ["ImageMagick", v"0.1.8", "BinDeps"], + ["ImageMagick", v"0.1.8", "ColorTypes", v"0.2.7"], + ["ImageMagick", v"0.1.8", "Compat", v"0.8.4"], + ["ImageMagick", v"0.1.8", "FileIO"], + ["ImageMagick", v"0.1.8", "FixedPointNumbers", v"0.1.8", v"0.3.0"], + ["ImageMagick", v"0.1.8", "Images", v"0.0.0-", v"0.6.0"], + ["ImageMagick", v"0.2.1", "BinDeps"], + ["ImageMagick", v"0.2.1", "ColorTypes", v"0.2.7"], + ["ImageMagick", v"0.2.1", "FileIO"], + ["ImageMagick", v"0.2.1", "FixedPointNumbers", v"0.3.0"], + ["ImageMagick", v"0.2.3", "BinDeps"], + ["ImageMagick", v"0.2.3", "ColorTypes", v"0.2.7"], + ["ImageMagick", v"0.2.3", "Compat", v"0.18.0"], + ["ImageMagick", v"0.2.3", "FileIO"], + ["ImageMagick", v"0.2.3", "FixedPointNumbers", v"0.3.0"], + ["ImageMagick", v"0.2.3", "ImageCore", v"0.1.0"], + ["ImageMagick", v"0.2.4", "BinDeps"], + ["ImageMagick", v"0.2.4", "ColorTypes", v"0.2.7"], + ["ImageMagick", v"0.2.4", "Compat", v"0.24.0"], + ["ImageMagick", v"0.2.4", "FileIO"], + ["ImageMagick", v"0.2.4", "FixedPointNumbers", v"0.3.0"], + ["ImageMagick", v"0.2.4", "Images", v"0.6.0"], + ["ImageMetadata", v"0.0.1", "Colors"], + ["ImageMetadata", v"0.0.1", "FixedPointNumbers", v"0.0.0-", v"0.3.0"], + ["ImageMetadata", v"0.0.1", "ImageAxes"], + ["ImageMetadata", v"0.0.1", "ColorVectorSpace", v"0.1.11"], + ["ImageMetadata", v"0.0.1", "ImageCore"], + ["ImageMetadata", v"0.0.1", "IndirectArrays"], + ["ImageMetadata", v"0.2.0", "Colors"], + ["ImageMetadata", v"0.2.0", "ImageAxes"], + ["ImageMetadata", v"0.2.0", "ColorVectorSpace", v"0.1.11"], + ["ImageMetadata", v"0.2.0", "FixedPointNumbers", v"0.3.0"], + ["ImageMetadata", v"0.2.0", "ImageCore"], + ["ImageMetadata", v"0.2.0", "IndirectArrays"], + ["ImageMetadata", v"0.2.3", "Colors"], + ["ImageMetadata", v"0.2.3", "ImageAxes"], + ["ImageMetadata", v"0.2.3", "ColorVectorSpace", v"0.1.11"], + ["ImageMetadata", v"0.2.3", "Compat", v"0.19.0"], + ["ImageMetadata", v"0.2.3", "FixedPointNumbers", v"0.3.0"], + ["ImageMetadata", v"0.2.3", "ImageCore"], + ["ImageMetadata", v"0.2.3", "IndirectArrays"], + ["ImageTransformations", v"0.0.1", "ColorVectorSpace", v"0.2.0"], + ["ImageTransformations", v"0.0.1", "Colors", v"0.7.0"], + ["ImageTransformations", v"0.0.1", "CoordinateTransformations", v"0.4.0"], + ["ImageTransformations", v"0.0.1", "ImageCore", v"0.1.2"], + ["ImageTransformations", v"0.0.1", "Interpolations", v"0.3.7"], + ["ImageTransformations", v"0.0.1", "OffsetArrays"], + ["ImageTransformations", v"0.0.1", "StaticArrays"], + ["ImageTransformations", v"0.1.0", "ColorVectorSpace", v"0.2.0"], + ["ImageTransformations", v"0.1.0", "Colors", v"0.7.0"], + ["ImageTransformations", v"0.1.0", "CoordinateTransformations", v"0.4.0"], + ["ImageTransformations", v"0.1.0", "FixedPointNumbers", v"0.3.0"], + ["ImageTransformations", v"0.1.0", "ImageCore", v"0.1.2"], + ["ImageTransformations", v"0.1.0", "Interpolations", v"0.3.7"], + ["ImageTransformations", v"0.1.0", "OffsetArrays"], + ["ImageTransformations", v"0.1.0", "StaticArrays"], + ["ImageTransformations", v"0.2.2", "AxisAlgorithms"], + ["ImageTransformations", v"0.2.2", "ColorVectorSpace", v"0.2.0"], + ["ImageTransformations", v"0.2.2", "Colors", v"0.7.0"], + ["ImageTransformations", v"0.2.2", "Compat", v"0.18.0"], + ["ImageTransformations", v"0.2.2", "CoordinateTransformations", v"0.4.0"], + ["ImageTransformations", v"0.2.2", "OffsetArrays"], + ["ImageTransformations", v"0.2.2", "StaticArrays"], + ["ImageTransformations", v"0.2.2", "FixedPointNumbers", v"0.3.0"], + ["ImageTransformations", v"0.2.2", "ImageCore", v"0.1.2"], + ["ImageTransformations", v"0.2.2", "Interpolations", v"0.4.0"], + ["Images", v"0.4.50", "BinDeps"], + ["Images", v"0.4.50", "ColorVectorSpace"], + ["Images", v"0.4.50", "Colors"], + ["Images", v"0.4.50", "SIUnits"], + ["Images", v"0.4.50", "Compat", v"0.4.0"], + ["Images", v"0.4.50", "FixedPointNumbers", v"0.0.0-", v"0.3.0"], + ["Images", v"0.4.50", "Graphics", v"0.1.0"], + ["Images", v"0.4.50", "Zlib"], + ["Images", v"0.5.4", "FileIO"], + ["Images", v"0.5.4", "SIUnits"], + ["Images", v"0.5.4", "ColorVectorSpace", v"0.1.0"], + ["Images", v"0.5.4", "Colors", v"0.6.0"], + ["Images", v"0.5.4", "Graphics", v"0.1.0"], + ["Images", v"0.5.4", "FixedPointNumbers", v"0.1.0", v"0.3.0"], + ["Images", v"0.5.4", "Zlib"], + ["Images", v"0.5.5", "ColorVectorSpace", v"0.1.0"], + ["Images", v"0.5.5", "Colors", v"0.6.0"], + ["Images", v"0.5.5", "Compat", v"0.7.15"], + ["Images", v"0.5.5", "FileIO"], + ["Images", v"0.5.5", "Graphics", v"0.1.0"], + ["Images", v"0.5.5", "FixedPointNumbers", v"0.1.0", v"0.3.0"], + ["Images", v"0.5.5", "SIUnits"], + ["Images", v"0.5.5", "Zlib"], + ["Images", v"0.5.9", "ColorVectorSpace", v"0.1.0"], + ["Images", v"0.5.9", "Colors", v"0.6.0"], + ["Images", v"0.5.9", "Compat", v"0.8.4"], + ["Images", v"0.5.9", "FileIO"], + ["Images", v"0.5.9", "Graphics", v"0.1.0"], + ["Images", v"0.5.9", "FixedPointNumbers", v"0.1.0", v"0.3.0"], + ["Images", v"0.5.9", "SIUnits"], + ["Images", v"0.5.9", "StatsBase"], + ["Images", v"0.5.9", "Zlib"], + ["Images", v"0.5.14", "ColorVectorSpace", v"0.1.0"], + ["Images", v"0.5.14", "Colors", v"0.6.0"], + ["Images", v"0.5.14", "Compat", v"0.9.1"], + ["Images", v"0.5.14", "FileIO"], + ["Images", v"0.5.14", "Graphics", v"0.1.0"], + ["Images", v"0.5.14", "FixedPointNumbers", v"0.1.0", v"0.3.0"], + ["Images", v"0.5.14", "SIUnits"], + ["Images", v"0.5.14", "StatsBase"], + ["Images", v"0.5.14", "Zlib"], + ["Images", v"0.6.0", "AxisArrays"], + ["Images", v"0.6.0", "FileIO"], + ["Images", v"0.6.0", "ImageAxes"], + ["Images", v"0.6.0", "ImageCore"], + ["Images", v"0.6.0", "ImageFiltering"], + ["Images", v"0.6.0", "ImageMetadata"], + ["Images", v"0.6.0", "IndirectArrays"], + ["Images", v"0.6.0", "MappedArrays"], + ["Images", v"0.6.0", "Reexport"], + ["Images", v"0.6.0", "SIUnits"], + ["Images", v"0.6.0", "StatsBase"], + ["Images", v"0.6.0", "Zlib"], + ["Images", v"0.6.0", "ColorVectorSpace", v"0.2.0"], + ["Images", v"0.6.0", "Colors", v"0.7.0"], + ["Images", v"0.6.0", "Compat", v"0.9.1"], + ["Images", v"0.6.0", "FixedPointNumbers", v"0.3.0"], + ["Images", v"0.6.0", "Graphics", v"0.1.0"], + ["Images", v"0.7.0", "AxisArrays"], + ["Images", v"0.7.0", "FileIO"], + ["Images", v"0.7.0", "ColorVectorSpace", v"0.2.0"], + ["Images", v"0.7.0", "Colors", v"0.7.0"], + ["Images", v"0.7.0", "Compat", v"0.9.1"], + ["Images", v"0.7.0", "Graphics", v"0.1.0"], + ["Images", v"0.7.0", "ImageAxes"], + ["Images", v"0.7.0", "ImageCore"], + ["Images", v"0.7.0", "ImageFiltering"], + ["Images", v"0.7.0", "ImageMetadata"], + ["Images", v"0.7.0", "IndirectArrays"], + ["Images", v"0.7.0", "MappedArrays"], + ["Images", v"0.7.0", "Reexport"], + ["Images", v"0.7.0", "SIUnits"], + ["Images", v"0.7.0", "StatsBase"], + ["Images", v"0.7.0", "FixedPointNumbers", v"0.3.0"], + ["Images", v"0.8.0", "AxisArrays"], + ["Images", v"0.8.0", "FileIO"], + ["Images", v"0.8.0", "ImageAxes"], + ["Images", v"0.8.0", "ImageCore"], + ["Images", v"0.8.0", "ColorVectorSpace", v"0.2.0"], + ["Images", v"0.8.0", "Colors", v"0.7.0"], + ["Images", v"0.8.0", "Compat", v"0.9.1"], + ["Images", v"0.8.0", "Graphics", v"0.1.0"], + ["Images", v"0.8.0", "ImageFiltering"], + ["Images", v"0.8.0", "ImageMetadata"], + ["Images", v"0.8.0", "ImageTransformations"], + ["Images", v"0.8.0", "IndirectArrays"], + ["Images", v"0.8.0", "MappedArrays"], + ["Images", v"0.8.0", "Reexport"], + ["Images", v"0.8.0", "SIUnits"], + ["Images", v"0.8.0", "StatsBase"], + ["Images", v"0.8.0", "FixedPointNumbers", v"0.3.0"], + ["Images", v"0.9.0", "AxisArrays"], + ["Images", v"0.9.0", "FileIO"], + ["Images", v"0.9.0", "Graphics", v"0.1.0"], + ["Images", v"0.9.0", "ImageAxes"], + ["Images", v"0.9.0", "ImageCore"], + ["Images", v"0.9.0", "ColorVectorSpace", v"0.2.0"], + ["Images", v"0.9.0", "Colors", v"0.7.0"], + ["Images", v"0.9.0", "Compat", v"0.18.0"], + ["Images", v"0.9.0", "ImageFiltering"], + ["Images", v"0.9.0", "ImageMetadata"], + ["Images", v"0.9.0", "ImageTransformations"], + ["Images", v"0.9.0", "IndirectArrays"], + ["Images", v"0.9.0", "MappedArrays"], + ["Images", v"0.9.0", "Reexport"], + ["Images", v"0.9.0", "SIUnits"], + ["Images", v"0.9.0", "StatsBase"], + ["Images", v"0.9.0", "FixedPointNumbers", v"0.3.0"], + ["Images", v"0.9.1", "AxisArrays"], + ["Images", v"0.9.1", "FileIO"], + ["Images", v"0.9.1", "ImageAxes"], + ["Images", v"0.9.1", "ImageCore"], + ["Images", v"0.9.1", "ColorVectorSpace", v"0.2.0"], + ["Images", v"0.9.1", "Colors", v"0.7.0"], + ["Images", v"0.9.1", "Compat", v"0.19.0"], + ["Images", v"0.9.1", "ImageFiltering"], + ["Images", v"0.9.1", "ImageMetadata"], + ["Images", v"0.9.1", "ImageTransformations"], + ["Images", v"0.9.1", "IndirectArrays"], + ["Images", v"0.9.1", "MappedArrays"], + ["Images", v"0.9.1", "Reexport"], + ["Images", v"0.9.1", "SIUnits"], + ["Images", v"0.9.1", "StatsBase"], + ["Images", v"0.9.1", "FixedPointNumbers", v"0.3.0"], + ["Images", v"0.9.1", "Graphics", v"0.1.0"], + ["IndirectArrays", v"0.1.0"], + ["IndirectArrays", v"0.1.1", "Compat", v"0.19.0"], + ["InplaceOps", v"0.1.0"], + ["Interpolations", v"0.0.1-beta", "Compat"], + ["Interpolations", v"0.0.1-beta", "WoodburyMatrices"], + ["Interpolations", v"0.1.0", "WoodburyMatrices"], + ["Interpolations", v"0.3.4", "AxisAlgorithms"], + ["Interpolations", v"0.3.4", "Ratios"], + ["Interpolations", v"0.3.4", "WoodburyMatrices", v"0.1.0"], + ["Interpolations", v"0.3.5", "AxisAlgorithms"], + ["Interpolations", v"0.3.5", "Ratios"], + ["Interpolations", v"0.3.5", "WoodburyMatrices", v"0.1.5"], + ["Interpolations", v"0.3.6", "AxisAlgorithms"], + ["Interpolations", v"0.3.6", "Ratios"], + ["Interpolations", v"0.3.6", "Compat", v"0.8.0"], + ["Interpolations", v"0.3.6", "WoodburyMatrices", v"0.1.5"], + ["Interpolations", v"0.3.7", "AxisAlgorithms"], + ["Interpolations", v"0.3.7", "DualNumbers"], + ["Interpolations", v"0.3.7", "Ratios"], + ["Interpolations", v"0.3.7", "Compat", v"0.8.0"], + ["Interpolations", v"0.3.7", "WoodburyMatrices", v"0.1.5"], + ["Interpolations", v"0.3.8", "AxisAlgorithms"], + ["Interpolations", v"0.3.8", "DualNumbers"], + ["Interpolations", v"0.3.8", "Ratios"], + ["Interpolations", v"0.3.8", "Compat", v"0.19.0"], + ["Interpolations", v"0.3.8", "WoodburyMatrices", v"0.1.5"], + ["Interpolations", v"0.4.0", "AxisAlgorithms"], + ["Interpolations", v"0.4.0", "DualNumbers"], + ["Interpolations", v"0.4.0", "Ratios"], + ["Interpolations", v"0.4.0", "Compat", v"0.19.0"], + ["Interpolations", v"0.4.0", "WoodburyMatrices", v"0.1.5"], + ["Interpolations", v"0.5.0", "AxisAlgorithms"], + ["Interpolations", v"0.5.0", "DualNumbers"], + ["Interpolations", v"0.5.0", "Ratios"], + ["Interpolations", v"0.5.0", "ShowItLikeYouBuildIt"], + ["Interpolations", v"0.5.0", "Compat", v"0.19.0"], + ["Interpolations", v"0.5.0", "WoodburyMatrices", v"0.1.5"], + ["IntervalSets", v"0.0.2"], + ["IntervalSets", v"0.0.5", "Compat", v"0.17.0"], + ["IterativeSolvers", v"0.0.1", "Compat"], + ["IterativeSolvers", v"0.0.1", "Docile"], + ["IterativeSolvers", v"0.2.1", "Compat"], + ["IterativeSolvers", v"0.2.2", "Compat"], + ["Iterators", v"0.1.10", "Compat"], + ["Iterators", v"0.3.0"], + ["JLD", v"0.6.4", "Compat", v"0.8.0"], + ["JLD", v"0.6.4", "FileIO"], + ["JLD", v"0.6.4", "HDF5"], + ["JLD", v"0.6.4", "LegacyStrings"], + ["JLD", v"0.6.10", "Compat", v"0.8.0"], + ["JLD", v"0.6.10", "FileIO"], + ["JLD", v"0.6.10", "HDF5"], + ["JLD", v"0.6.10", "LegacyStrings"], + ["JSON", v"0.3.9"], + ["JSON", v"0.4.4", "Compat"], + ["JSON", v"0.4.5", "Compat", v"0.4.12"], + ["JSON", v"0.5.0", "Compat", v"0.7.1"], + ["JSON", v"0.5.4", "Compat", v"0.7.16"], + ["JSON", v"0.6.0", "Compat", v"0.7.20"], + ["JSON", v"0.8.0", "Compat", v"0.8.4"], + ["JSON", v"0.8.2", "Compat", v"0.9.5"], + ["JSON", v"0.8.3", "Compat", v"0.17.0"], + ["JSON", v"0.9.0", "Compat", v"0.17.0"], + ["JuliaParser", v"0.5.3", "FactCheck"], + ["JuliaParser", v"0.6.4", "Compat"], + ["JuliaParser", v"0.6.4", "FactCheck"], + ["JuliaParser", v"0.7.0", "AbstractTrees"], + ["JuliaParser", v"0.7.0", "Compat"], + ["JuliaParser", v"0.7.1", "AbstractTrees"], + ["JuliaParser", v"0.7.1", "Compat"], + ["JuliaParser", v"0.7.4", "AbstractTrees"], + ["JuliaParser", v"0.7.4", "Compat"], + ["Juno", v"0.2.3", "Hiccup"], + ["Juno", v"0.2.3", "MacroTools"], + ["Juno", v"0.2.3", "Media"], + ["Juno", v"0.2.4", "Hiccup"], + ["Juno", v"0.2.4", "MacroTools"], + ["Juno", v"0.2.4", "Media"], + ["Juno", v"0.2.5", "Hiccup"], + ["Juno", v"0.2.5", "MacroTools"], + ["Juno", v"0.2.5", "Media"], + ["Juno", v"0.2.7", "Hiccup"], + ["Juno", v"0.2.7", "MacroTools"], + ["Juno", v"0.2.7", "Media"], + ["LNR", v"0.0.0"], + ["LNR", v"0.0.1", "Lazy"], + ["LNR", v"0.0.2", "Compat"], + ["LNR", v"0.0.2", "Lazy"], + ["Lazy", v"0.9.1"], + ["Lazy", v"0.10.0", "MacroTools"], + ["Lazy", v"0.10.1", "Compat"], + ["Lazy", v"0.10.1", "MacroTools"], + ["Lazy", v"0.11.2", "MacroTools"], + ["Lazy", v"0.11.2", "Compat", v"0.8.0"], + ["Lazy", v"0.11.6", "MacroTools"], + ["Lazy", v"0.11.6", "Compat", v"0.8.0"], + ["LearnBase", v"0.1.0", "StatsBase"], + ["LearnBase", v"0.1.1", "Distributions"], + ["LearnBase", v"0.1.1", "StatsBase"], + ["LearnBase", v"0.1.2", "Distributions"], + ["LearnBase", v"0.1.2", "StatsBase", v"0.8.0"], + ["LearnBase", v"0.1.3", "Distributions"], + ["LearnBase", v"0.1.3", "Compat", v"0.17.0"], + ["LearnBase", v"0.1.3", "StatsBase", v"0.8.0"], + ["LearnBase", v"0.1.5", "Distributions"], + ["LearnBase", v"0.1.5", "Compat", v"0.18.0"], + ["LearnBase", v"0.1.5", "StatsBase", v"0.8.0"], + ["LegacyStrings", v"0.1.0"], + ["LegacyStrings", v"0.2.0", "Compat", v"0.8.4"], + ["LegacyStrings", v"0.2.1", "Compat", v"0.18.0"], + ["LineSearches", v"0.0.2"], + ["LineSearches", v"0.1.1"], + ["LineSearches", v"0.1.5"], + ["LossFunctions", v"0.0.1", "LearnBase", v"0.0.1", v"0.2.0"], + ["LossFunctions", v"0.0.1", "RecipesBase"], + ["LossFunctions", v"0.0.1", "Reexport"], + ["LossFunctions", v"0.0.2", "LearnBase", v"0.0.1", v"0.2.0"], + ["LossFunctions", v"0.0.2", "RecipesBase"], + ["LossFunctions", v"0.0.2", "Reexport"], + ["LossFunctions", v"0.0.3", "LearnBase", v"0.1.2", v"0.2.0"], + ["LossFunctions", v"0.0.3", "RecipesBase"], + ["LossFunctions", v"0.0.3", "StatsBase", v"0.8.0"], + ["LossFunctions", v"0.1.0", "LearnBase", v"0.1.3", v"0.2.0"], + ["LossFunctions", v"0.1.0", "RecipesBase"], + ["LossFunctions", v"0.1.0", "StatsBase", v"0.8.0"], + ["LsqFit", v"0.0.1", "Calculus"], + ["LsqFit", v"0.0.1", "Distributions"], + ["LsqFit", v"0.0.1", "Optim", v"0.0.0", v"0.5.0"], + ["LsqFit", v"0.0.2", "Calculus"], + ["LsqFit", v"0.0.2", "Distributions"], + ["LsqFit", v"0.0.2", "Optim"], + ["LsqFit", v"0.1.0", "Calculus"], + ["LsqFit", v"0.1.0", "Distributions"], + ["LsqFit", v"0.1.0", "Optim", v"0.6.0"], + ["LsqFit", v"0.1.1", "Calculus"], + ["LsqFit", v"0.1.1", "Distributions"], + ["LsqFit", v"0.1.1", "Optim", v"0.7.0"], + ["LsqFit", v"0.2.0", "Calculus"], + ["LsqFit", v"0.2.0", "Distributions"], + ["LsqFit", v"0.2.0", "Compat", v"0.9.1"], + ["LsqFit", v"0.2.0", "Optim", v"0.7.5"], + ["MachO", v"0.0.4", "ObjFileBase"], + ["MachO", v"0.0.4", "StructIO"], + ["MacroTools", v"0.1.0"], + ["MacroTools", v"0.3.0"], + ["MacroTools", v"0.3.1", "Compat"], + ["MacroTools", v"0.3.3", "Compat"], + ["MacroTools", v"0.3.6", "Compat", v"0.7.9"], + ["MappedArrays", v"0.0.2"], + ["MappedArrays", v"0.0.5"], + ["MappedArrays", v"0.0.7", "Compat", v"0.19.0"], + ["Markdown", v"0.1.0"], + ["Markdown", v"0.3.0", "Lazy"], + ["MbedTLS", v"0.2.3", "BinDeps"], + ["MbedTLS", v"0.2.3", "Compat", v"0.7.9"], + ["MbedTLS", v"0.3.0", "BinDeps"], + ["MbedTLS", v"0.3.0", "Compat", v"0.8.0"], + ["MbedTLS", v"0.4.4", "BinDeps"], + ["MbedTLS", v"0.4.5", "BinDeps"], + ["MbedTLS", v"0.4.5", "Compat", v"0.9.5"], + ["Measures", v"0.0.2"], + ["Measures", v"0.0.3", "Compat", v"0.7.15"], + ["Measures", v"0.1.0", "Compat", v"0.18.0"], + ["Media", v"0.1.0", "Lazy"], + ["Media", v"0.1.0", "Requires"], + ["Media", v"0.2.2", "Lazy"], + ["Media", v"0.2.2", "MacroTools"], + ["Media", v"0.2.2", "Requires"], + ["Media", v"0.2.3", "MacroTools"], + ["Media", v"0.2.3", "Lazy", v"0.11.3"], + ["Media", v"0.2.7", "MacroTools"], + ["MultiScaleArrays", v"0.0.1", "Iterators"], + ["MultiScaleArrays", v"0.0.1", "RecursiveArrayTools", v"0.0.2"], + ["MultiScaleArrays", v"0.1.0", "DiffEqBase", v"0.11.0"], + ["MultiScaleArrays", v"0.1.0", "Iterators"], + ["MultiScaleArrays", v"0.1.0", "RecursiveArrayTools", v"0.0.2"], + ["Mustache", v"0.0.1", "DataFrames"], + ["Mustache", v"0.0.7", "Compat"], + ["Mustache", v"0.0.7", "Requires"], + ["Mustache", v"0.0.14", "Requires"], + ["Mustache", v"0.0.14", "Compat", v"0.4.0"], + ["Mustache", v"0.1.0"], + ["Mustache", v"0.1.4", "Compat", v"0.7.18"], + ["Mux", v"0.0.0", "Hiccup"], + ["Mux", v"0.0.0", "HttpServer"], + ["Mux", v"0.0.0", "Lazy"], + ["Mux", v"0.0.0", "URIParser"], + ["Mux", v"0.1.1", "Compat"], + ["Mux", v"0.1.1", "Hiccup"], + ["Mux", v"0.1.1", "HttpCommon"], + ["Mux", v"0.1.1", "HttpServer"], + ["Mux", v"0.1.1", "Lazy"], + ["Mux", v"0.1.1", "URIParser"], + ["Mux", v"0.1.1", "WebSockets"], + ["Mux", v"0.2.2", "Hiccup"], + ["Mux", v"0.2.2", "HttpCommon"], + ["Mux", v"0.2.2", "HttpServer"], + ["Mux", v"0.2.2", "Lazy"], + ["Mux", v"0.2.2", "URIParser"], + ["Mux", v"0.2.2", "WebSockets"], + ["Mux", v"0.2.3", "Hiccup"], + ["Mux", v"0.2.3", "HttpCommon"], + ["Mux", v"0.2.3", "Compat", v"0.7.9"], + ["Mux", v"0.2.3", "HttpServer"], + ["Mux", v"0.2.3", "Lazy"], + ["Mux", v"0.2.3", "URIParser"], + ["Mux", v"0.2.3", "WebSockets"], + ["NLSolversBase", v"2.1.1", "Compat", v"0.17.0"], + ["NLsolve", v"0.7.3", "Calculus"], + ["NLsolve", v"0.7.3", "Distances"], + ["NLsolve", v"0.7.3", "Optim"], + ["NLsolve", v"0.7.3", "Compat", v"0.8.0"], + ["NLsolve", v"0.7.3", "ForwardDiff", v"0.2.0"], + ["NLsolve", v"0.7.3", "LineSearches", v"0.0.1", v"1.0.0-"], + ["NLsolve", v"0.8.0", "Calculus"], + ["NLsolve", v"0.8.0", "Distances"], + ["NLsolve", v"0.8.0", "Optim"], + ["NLsolve", v"0.8.0", "Compat", v"0.8.4"], + ["NLsolve", v"0.8.0", "ForwardDiff", v"0.2.0"], + ["NLsolve", v"0.8.0", "LineSearches", v"0.0.1", v"1.0.0-"], + ["NLsolve", v"0.9.0", "Calculus"], + ["NLsolve", v"0.9.0", "DiffBase"], + ["NLsolve", v"0.9.0", "Distances"], + ["NLsolve", v"0.9.0", "Optim"], + ["NLsolve", v"0.9.0", "Compat", v"0.8.4"], + ["NLsolve", v"0.9.0", "ForwardDiff", v"0.3.0"], + ["NLsolve", v"0.9.0", "LineSearches", v"0.1.2", v"1.0.0-"], + ["NLsolve", v"0.9.1", "Calculus"], + ["NLsolve", v"0.9.1", "DiffBase"], + ["NLsolve", v"0.9.1", "Distances"], + ["NLsolve", v"0.9.1", "Optim"], + ["NLsolve", v"0.9.1", "Compat", v"0.8.4"], + ["NLsolve", v"0.9.1", "ForwardDiff", v"0.3.0"], + ["NLsolve", v"0.9.1", "LineSearches", v"0.1.2", v"1.0.0-"], + ["NaNMath", v"0.1.1", "Compat"], + ["NaNMath", v"0.2.0"], + ["NaNMath", v"0.2.1"], + ["NaNMath", v"0.2.3", "Compat", v"0.9.1"], + ["NaNMath", v"0.2.4", "Compat", v"0.9.1"], + ["Nettle", v"0.1.1"], + ["Nettle", v"0.1.7", "BinDeps"], + ["Nettle", v"0.1.10", "BinDeps"], + ["Nettle", v"0.1.10", "Compat"], + ["Nettle", v"0.2.3", "BinDeps"], + ["Nettle", v"0.2.3", "Compat"], + ["Nettle", v"0.3.0", "BinDeps"], + ["Nettle", v"0.3.0", "Compat", v"0.8.0"], + ["NumericExtensions", v"0.3.6"], + ["NumericExtensions", v"0.4.3", "ArrayViews", v"0.2.0-"], + ["NumericExtensions", v"0.5.6", "ArrayViews", v"0.2.0-"], + ["NumericExtensions", v"0.6.2", "ArrayViews", v"0.2.0-"], + ["NumericExtensions", v"0.6.2", "NumericFuns", v"0.2.1-"], + ["NumericFuns", v"0.2.0"], + ["NumericFuns", v"0.2.3"], + ["NumericFuns", v"0.2.4", "Compat"], + ["ObjFileBase", v"0.0.4"], + ["OffsetArrays", v"0.2.13"], + ["OffsetArrays", v"0.3.0", "Compat", v"0.19.0"], + ["Optim", v"0.4.6", "Calculus"], + ["Optim", v"0.4.6", "Compat"], + ["Optim", v"0.4.6", "DualNumbers"], + ["Optim", v"0.4.6", "LineSearches", v"0.0.1", v"1.0.0-"], + ["Optim", v"0.4.7", "Calculus"], + ["Optim", v"0.4.7", "DualNumbers", v"0.2.0"], + ["Optim", v"0.4.7", "PositiveFactorizations"], + ["Optim", v"0.4.7", "LineSearches", v"0.0.1", v"1.0.0-"], + ["Optim", v"0.5.0", "Calculus"], + ["Optim", v"0.5.0", "PositiveFactorizations"], + ["Optim", v"0.5.0", "Compat", v"0.7.16"], + ["Optim", v"0.5.0", "DualNumbers", v"0.2.0"], + ["Optim", v"0.5.0", "LineSearches", v"0.0.1", v"1.0.0-"], + ["Optim", v"0.6.1", "Calculus"], + ["Optim", v"0.6.1", "PositiveFactorizations"], + ["Optim", v"0.6.1", "Compat", v"0.8.4"], + ["Optim", v"0.6.1", "ForwardDiff", v"0.2.0", v"0.3.0"], + ["Optim", v"0.6.1", "LineSearches", v"0.0.1", v"1.0.0-"], + ["Optim", v"0.7.2", "Calculus"], + ["Optim", v"0.7.2", "PositiveFactorizations"], + ["Optim", v"0.7.2", "Compat", v"0.8.4"], + ["Optim", v"0.7.2", "ForwardDiff", v"0.3.0", v"0.4.0"], + ["Optim", v"0.7.2", "LineSearches", v"0.1.0", v"1.0.0-"], + ["Optim", v"0.7.4", "Calculus"], + ["Optim", v"0.7.4", "PositiveFactorizations"], + ["Optim", v"0.7.4", "Compat", v"0.8.4"], + ["Optim", v"0.7.4", "ForwardDiff", v"0.3.0", v"0.4.0"], + ["Optim", v"0.7.4", "LineSearches", v"0.1.2", v"1.0.0-"], + ["Optim", v"0.7.5", "Calculus"], + ["Optim", v"0.7.5", "PositiveFactorizations"], + ["Optim", v"0.7.5", "Compat", v"0.8.4"], + ["Optim", v"0.7.5", "ForwardDiff", v"0.3.0", v"0.4.0"], + ["Optim", v"0.7.5", "LineSearches", v"0.1.2", v"1.0.0-"], + ["Optim", v"0.7.7", "Calculus"], + ["Optim", v"0.7.7", "PositiveFactorizations"], + ["Optim", v"0.7.7", "Compat", v"0.18.0"], + ["Optim", v"0.7.7", "ForwardDiff", v"0.3.0", v"0.4.0"], + ["Optim", v"0.7.7", "LineSearches", v"0.1.2", v"1.0.0-"], + ["Optim", v"0.7.8", "Calculus"], + ["Optim", v"0.7.8", "PositiveFactorizations"], + ["Optim", v"0.7.8", "Compat", v"0.18.0"], + ["Optim", v"0.7.8", "ForwardDiff", v"0.3.0", v"0.5.0"], + ["Optim", v"0.7.8", "LineSearches", v"0.1.2", v"1.0.0-"], + ["Options", v"0.2.6"], + ["OrdinaryDiffEq", v"0.0.1", "Compat", v"0.8.8"], + ["OrdinaryDiffEq", v"0.0.1", "DiffEqBase", v"0.0.0", v"0.7.0"], + ["OrdinaryDiffEq", v"0.0.1", "ForwardDiff", v"0.2.4"], + ["OrdinaryDiffEq", v"0.0.1", "GenericSVD", v"0.0.2"], + ["OrdinaryDiffEq", v"0.0.1", "InplaceOps", v"0.0.5"], + ["OrdinaryDiffEq", v"0.0.1", "NLsolve", v"0.7.3"], + ["OrdinaryDiffEq", v"0.0.1", "Parameters", v"0.5.0"], + ["OrdinaryDiffEq", v"0.0.1", "Ranges", v"0.0.1"], + ["OrdinaryDiffEq", v"0.0.1", "RecipesBase", v"0.1.0"], + ["OrdinaryDiffEq", v"0.0.1", "Sundials", v"0.3.0"], + ["OrdinaryDiffEq", v"0.0.3", "Compat", v"0.8.8"], + ["OrdinaryDiffEq", v"0.0.3", "DiffEqBase", v"0.0.0", v"0.7.0"], + ["OrdinaryDiffEq", v"0.0.3", "ForwardDiff", v"0.2.4"], + ["OrdinaryDiffEq", v"0.0.3", "GenericSVD", v"0.0.2"], + ["OrdinaryDiffEq", v"0.0.3", "InplaceOps", v"0.0.5"], + ["OrdinaryDiffEq", v"0.0.3", "NLsolve", v"0.7.3"], + ["OrdinaryDiffEq", v"0.0.3", "ParameterizedFunctions", v"0.1.0"], + ["OrdinaryDiffEq", v"0.0.3", "Parameters", v"0.5.0"], + ["OrdinaryDiffEq", v"0.0.3", "Ranges", v"0.0.1"], + ["OrdinaryDiffEq", v"0.0.3", "RecipesBase", v"0.1.0"], + ["OrdinaryDiffEq", v"0.0.3", "Sundials", v"0.3.0"], + ["OrdinaryDiffEq", v"0.0.5", "RecursiveArrayTools"], + ["OrdinaryDiffEq", v"0.0.5", "Compat", v"0.8.8"], + ["OrdinaryDiffEq", v"0.0.5", "DiffEqBase", v"0.0.0", v"0.7.0"], + ["OrdinaryDiffEq", v"0.0.5", "ForwardDiff", v"0.2.4"], + ["OrdinaryDiffEq", v"0.0.5", "GenericSVD", v"0.0.2"], + ["OrdinaryDiffEq", v"0.0.5", "InplaceOps", v"0.0.5"], + ["OrdinaryDiffEq", v"0.0.5", "NLsolve", v"0.7.3"], + ["OrdinaryDiffEq", v"0.0.5", "Parameters", v"0.5.0"], + ["OrdinaryDiffEq", v"0.0.5", "Ranges", v"0.0.1"], + ["OrdinaryDiffEq", v"0.0.5", "RecipesBase", v"0.1.0"], + ["OrdinaryDiffEq", v"0.0.5", "Sundials", v"0.3.0"], + ["OrdinaryDiffEq", v"0.1.0", "Compat", v"0.8.8"], + ["OrdinaryDiffEq", v"0.1.0", "DiffEqBase", v"0.0.0", v"0.7.0"], + ["OrdinaryDiffEq", v"0.1.0", "Juno"], + ["OrdinaryDiffEq", v"0.1.0", "RecursiveArrayTools"], + ["OrdinaryDiffEq", v"0.1.0", "ForwardDiff", v"0.2.4"], + ["OrdinaryDiffEq", v"0.1.0", "GenericSVD", v"0.0.2"], + ["OrdinaryDiffEq", v"0.1.0", "InplaceOps", v"0.0.5"], + ["OrdinaryDiffEq", v"0.1.0", "NLsolve", v"0.7.3"], + ["OrdinaryDiffEq", v"0.1.0", "Parameters", v"0.5.0"], + ["OrdinaryDiffEq", v"0.1.0", "Ranges", v"0.0.1"], + ["OrdinaryDiffEq", v"0.1.0", "RecipesBase", v"0.1.0"], + ["OrdinaryDiffEq", v"0.1.1", "Compat", v"0.8.8"], + ["OrdinaryDiffEq", v"0.1.1", "DiffEqBase", v"0.1.2", v"0.7.0"], + ["OrdinaryDiffEq", v"0.1.1", "ForwardDiff", v"0.2.4"], + ["OrdinaryDiffEq", v"0.1.1", "GenericSVD", v"0.0.2"], + ["OrdinaryDiffEq", v"0.1.1", "InplaceOps", v"0.0.5"], + ["OrdinaryDiffEq", v"0.1.1", "Juno", v"0.2.5"], + ["OrdinaryDiffEq", v"0.1.1", "NLsolve", v"0.7.3"], + ["OrdinaryDiffEq", v"0.1.1", "Parameters", v"0.5.0"], + ["OrdinaryDiffEq", v"0.1.1", "Ranges", v"0.0.1"], + ["OrdinaryDiffEq", v"0.1.1", "RecipesBase", v"0.1.0"], + ["OrdinaryDiffEq", v"0.1.1", "RecursiveArrayTools", v"0.0.2"], + ["OrdinaryDiffEq", v"0.5.0", "Calculus", v"0.1.15"], + ["OrdinaryDiffEq", v"0.5.0", "Compat", v"0.8.8"], + ["OrdinaryDiffEq", v"0.5.0", "DiffEqBase", v"0.2.0", v"0.7.0"], + ["OrdinaryDiffEq", v"0.5.0", "ForwardDiff", v"0.2.4"], + ["OrdinaryDiffEq", v"0.5.0", "GenericSVD", v"0.0.2"], + ["OrdinaryDiffEq", v"0.5.0", "InplaceOps", v"0.0.5"], + ["OrdinaryDiffEq", v"0.5.0", "Juno", v"0.2.5"], + ["OrdinaryDiffEq", v"0.5.0", "NLsolve", v"0.7.3"], + ["OrdinaryDiffEq", v"0.5.0", "Parameters", v"0.5.0"], + ["OrdinaryDiffEq", v"0.5.0", "Ranges", v"0.0.1"], + ["OrdinaryDiffEq", v"0.5.0", "RecipesBase", v"0.1.0"], + ["OrdinaryDiffEq", v"0.5.0", "RecursiveArrayTools", v"0.0.2"], + ["OrdinaryDiffEq", v"0.6.0", "Calculus", v"0.1.15"], + ["OrdinaryDiffEq", v"0.6.0", "Compat", v"0.8.8"], + ["OrdinaryDiffEq", v"0.6.0", "DiffEqBase", v"0.4.0", v"0.7.0"], + ["OrdinaryDiffEq", v"0.6.0", "ForwardDiff", v"0.2.4"], + ["OrdinaryDiffEq", v"0.6.0", "GenericSVD", v"0.0.2"], + ["OrdinaryDiffEq", v"0.6.0", "InplaceOps", v"0.0.5"], + ["OrdinaryDiffEq", v"0.6.0", "Juno", v"0.2.5"], + ["OrdinaryDiffEq", v"0.6.0", "NLsolve", v"0.7.3"], + ["OrdinaryDiffEq", v"0.6.0", "Parameters", v"0.5.0"], + ["OrdinaryDiffEq", v"0.6.0", "Ranges", v"0.0.1"], + ["OrdinaryDiffEq", v"0.6.0", "RecipesBase", v"0.1.0"], + ["OrdinaryDiffEq", v"0.6.0", "RecursiveArrayTools", v"0.0.2"], + ["OrdinaryDiffEq", v"1.0.2", "Calculus", v"0.1.15"], + ["OrdinaryDiffEq", v"1.0.2", "Compat", v"0.8.8"], + ["OrdinaryDiffEq", v"1.0.2", "DataStructures", v"0.4.6"], + ["OrdinaryDiffEq", v"1.0.2", "DiffEqBase", v"0.6.0", v"0.8.0"], + ["OrdinaryDiffEq", v"1.0.2", "ForwardDiff", v"0.2.4"], + ["OrdinaryDiffEq", v"1.0.2", "GenericSVD", v"0.0.2"], + ["OrdinaryDiffEq", v"1.0.2", "InplaceOps", v"0.0.5"], + ["OrdinaryDiffEq", v"1.0.2", "Juno", v"0.2.5"], + ["OrdinaryDiffEq", v"1.0.2", "NLsolve", v"0.9.1"], + ["OrdinaryDiffEq", v"1.0.2", "Parameters", v"0.5.0"], + ["OrdinaryDiffEq", v"1.0.2", "RecursiveArrayTools", v"0.1.2"], + ["OrdinaryDiffEq", v"1.0.2", "Roots", v"0.2.1"], + ["OrdinaryDiffEq", v"1.1.0", "Calculus", v"0.1.15"], + ["OrdinaryDiffEq", v"1.1.0", "DiffEqBase", v"0.7.0", v"0.8.0"], + ["OrdinaryDiffEq", v"1.1.0", "Iterators"], + ["OrdinaryDiffEq", v"1.1.0", "Compat", v"0.8.8"], + ["OrdinaryDiffEq", v"1.1.0", "DataStructures", v"0.4.6"], + ["OrdinaryDiffEq", v"1.1.0", "ForwardDiff", v"0.2.4"], + ["OrdinaryDiffEq", v"1.1.0", "GenericSVD", v"0.0.2"], + ["OrdinaryDiffEq", v"1.1.0", "InplaceOps", v"0.0.5"], + ["OrdinaryDiffEq", v"1.1.0", "Juno", v"0.2.5"], + ["OrdinaryDiffEq", v"1.1.0", "NLsolve", v"0.9.1"], + ["OrdinaryDiffEq", v"1.1.0", "Parameters", v"0.5.0"], + ["OrdinaryDiffEq", v"1.1.0", "RecursiveArrayTools", v"0.1.2"], + ["OrdinaryDiffEq", v"1.1.0", "Roots", v"0.2.1"], + ["OrdinaryDiffEq", v"1.3.1", "Calculus", v"0.1.15"], + ["OrdinaryDiffEq", v"1.3.1", "Compat", v"0.8.8"], + ["OrdinaryDiffEq", v"1.3.1", "DataStructures", v"0.4.6"], + ["OrdinaryDiffEq", v"1.3.1", "DiffEqBase", v"0.8.0", v"0.15.0"], + ["OrdinaryDiffEq", v"1.3.1", "Iterators"], + ["OrdinaryDiffEq", v"1.3.1", "ForwardDiff", v"0.2.4"], + ["OrdinaryDiffEq", v"1.3.1", "GenericSVD", v"0.0.2"], + ["OrdinaryDiffEq", v"1.3.1", "InplaceOps", v"0.0.5"], + ["OrdinaryDiffEq", v"1.3.1", "Juno", v"0.2.5"], + ["OrdinaryDiffEq", v"1.3.1", "NLsolve", v"0.9.1"], + ["OrdinaryDiffEq", v"1.3.1", "Parameters", v"0.5.0"], + ["OrdinaryDiffEq", v"1.3.1", "RecursiveArrayTools", v"0.2.0"], + ["OrdinaryDiffEq", v"1.3.1", "Roots", v"0.2.1"], + ["OrdinaryDiffEq", v"1.4.1", "Calculus", v"0.1.15"], + ["OrdinaryDiffEq", v"1.4.1", "Iterators"], + ["OrdinaryDiffEq", v"1.4.1", "Compat", v"0.8.8"], + ["OrdinaryDiffEq", v"1.4.1", "DataStructures", v"0.4.6"], + ["OrdinaryDiffEq", v"1.4.1", "DiffEqBase", v"0.11.0", v"0.15.0"], + ["OrdinaryDiffEq", v"1.4.1", "ForwardDiff", v"0.2.4"], + ["OrdinaryDiffEq", v"1.4.1", "GenericSVD", v"0.0.2"], + ["OrdinaryDiffEq", v"1.4.1", "InplaceOps", v"0.0.5"], + ["OrdinaryDiffEq", v"1.4.1", "Juno", v"0.2.5"], + ["OrdinaryDiffEq", v"1.4.1", "NLsolve", v"0.9.1"], + ["OrdinaryDiffEq", v"1.4.1", "Parameters", v"0.5.0"], + ["OrdinaryDiffEq", v"1.4.1", "RecursiveArrayTools", v"0.2.0"], + ["OrdinaryDiffEq", v"1.4.1", "Roots", v"0.2.1"], + ["OrdinaryDiffEq", v"1.5.0", "Calculus", v"0.1.15"], + ["OrdinaryDiffEq", v"1.5.0", "Iterators"], + ["OrdinaryDiffEq", v"1.5.0", "Compat", v"0.17.0"], + ["OrdinaryDiffEq", v"1.5.0", "DataStructures", v"0.4.6"], + ["OrdinaryDiffEq", v"1.5.0", "DiffEqBase", v"0.11.0", v"0.15.0"], + ["OrdinaryDiffEq", v"1.5.0", "ForwardDiff", v"0.2.4"], + ["OrdinaryDiffEq", v"1.5.0", "GenericSVD", v"0.0.2"], + ["OrdinaryDiffEq", v"1.5.0", "InplaceOps", v"0.0.5"], + ["OrdinaryDiffEq", v"1.5.0", "Juno", v"0.2.5"], + ["OrdinaryDiffEq", v"1.5.0", "NLsolve", v"0.9.1"], + ["OrdinaryDiffEq", v"1.5.0", "Parameters", v"0.5.0"], + ["OrdinaryDiffEq", v"1.5.0", "RecursiveArrayTools", v"0.2.0"], + ["OrdinaryDiffEq", v"1.5.0", "Roots", v"0.2.1"], + ["OrdinaryDiffEq", v"1.7.0", "Calculus", v"0.1.15"], + ["OrdinaryDiffEq", v"1.7.0", "Iterators"], + ["OrdinaryDiffEq", v"1.7.0", "Compat", v"0.17.0"], + ["OrdinaryDiffEq", v"1.7.0", "DataStructures", v"0.4.6"], + ["OrdinaryDiffEq", v"1.7.0", "DiffEqBase", v"0.13.0", v"0.15.0"], + ["OrdinaryDiffEq", v"1.7.0", "ForwardDiff", v"0.2.4"], + ["OrdinaryDiffEq", v"1.7.0", "GenericSVD", v"0.0.2"], + ["OrdinaryDiffEq", v"1.7.0", "InplaceOps", v"0.0.5"], + ["OrdinaryDiffEq", v"1.7.0", "Juno", v"0.2.5"], + ["OrdinaryDiffEq", v"1.7.0", "NLsolve", v"0.9.1"], + ["OrdinaryDiffEq", v"1.7.0", "Parameters", v"0.5.0"], + ["OrdinaryDiffEq", v"1.7.0", "RecursiveArrayTools", v"0.2.0"], + ["OrdinaryDiffEq", v"1.7.0", "Roots", v"0.2.1"], + ["OrdinaryDiffEq", v"1.8.0", "Calculus", v"0.1.15"], + ["OrdinaryDiffEq", v"1.8.0", "DiffEqBase", v"0.15.0"], + ["OrdinaryDiffEq", v"1.8.0", "Iterators"], + ["OrdinaryDiffEq", v"1.8.0", "Compat", v"0.17.0"], + ["OrdinaryDiffEq", v"1.8.0", "DataStructures", v"0.4.6"], + ["OrdinaryDiffEq", v"1.8.0", "ForwardDiff", v"0.2.4"], + ["OrdinaryDiffEq", v"1.8.0", "GenericSVD", v"0.0.2"], + ["OrdinaryDiffEq", v"1.8.0", "InplaceOps", v"0.0.5"], + ["OrdinaryDiffEq", v"1.8.0", "Juno", v"0.2.5"], + ["OrdinaryDiffEq", v"1.8.0", "NLsolve", v"0.9.1"], + ["OrdinaryDiffEq", v"1.8.0", "Parameters", v"0.5.0"], + ["OrdinaryDiffEq", v"1.8.0", "RecursiveArrayTools", v"0.2.0"], + ["OrdinaryDiffEq", v"1.8.0", "Roots", v"0.2.1"], + ["PDMats", v"0.1.2", "NumericExtensions", v"0.5.0-"], + ["PDMats", v"0.2.5", "ArrayViews", v"0.4.0-"], + ["PDMats", v"0.3.0", "ArrayViews", v"0.4.8-"], + ["PDMats", v"0.3.1", "ArrayViews", v"0.4.8-"], + ["PDMats", v"0.3.6", "ArrayViews", v"0.4.8-"], + ["PDMats", v"0.4.0", "Compat", v"0.7.7"], + ["PDMats", v"0.4.1", "Compat", v"0.7.7"], + ["PDMats", v"0.4.2", "Compat", v"0.7.7"], + ["PDMats", v"0.5.3", "Compat", v"0.9.2"], + ["PDMats", v"0.5.4", "Compat", v"0.9.2"], + ["PDMats", v"0.5.5", "Compat", v"0.17.0"], + ["PDMats", v"0.5.6", "Compat", v"0.18.0"], + ["PDMats", v"0.6.0", "Compat", v"0.18.0"], + ["ParameterizedFunctions", v"0.0.1", "DataStructures", v"0.4.6"], + ["ParameterizedFunctions", v"0.0.1", "DiffEqBase", v"0.0.0", v"0.5.0"], + ["ParameterizedFunctions", v"0.0.1", "SymEngine", v"0.1.1"], + ["ParameterizedFunctions", v"0.1.1", "DataStructures", v"0.4.6"], + ["ParameterizedFunctions", v"0.1.1", "DiffEqBase", v"0.0.0", v"0.5.0"], + ["ParameterizedFunctions", v"0.1.1", "SymEngine", v"0.1.1"], + ["ParameterizedFunctions", v"0.2.2", "DataStructures", v"0.4.6"], + ["ParameterizedFunctions", v"0.2.2", "DiffEqBase", v"0.0.0", v"0.5.0"], + ["ParameterizedFunctions", v"0.2.2", "SymEngine", v"0.1.1"], + ["ParameterizedFunctions", v"0.3.1", "DataStructures", v"0.4.6"], + ["ParameterizedFunctions", v"0.3.1", "DiffEqBase", v"0.1.0", v"0.5.0"], + ["ParameterizedFunctions", v"0.3.1", "SymEngine", v"0.1.2"], + ["ParameterizedFunctions", v"0.3.2", "DataStructures", v"0.4.6"], + ["ParameterizedFunctions", v"0.3.2", "DiffEqBase", v"0.1.0", v"0.5.0"], + ["ParameterizedFunctions", v"0.3.2", "SymEngine", v"0.1.2"], + ["ParameterizedFunctions", v"0.3.3", "DataStructures", v"0.4.6"], + ["ParameterizedFunctions", v"0.3.3", "DiffEqBase", v"0.2.0", v"0.5.0"], + ["ParameterizedFunctions", v"0.3.3", "SymEngine", v"0.1.2"], + ["ParameterizedFunctions", v"0.4.2", "DataStructures", v"0.4.6"], + ["ParameterizedFunctions", v"0.4.2", "SimpleTraits", v"0.1.1"], + ["ParameterizedFunctions", v"0.4.2", "DiffEqBase", v"0.2.0", v"0.5.0"], + ["ParameterizedFunctions", v"0.4.2", "SymEngine", v"0.1.2"], + ["ParameterizedFunctions", v"0.5.1", "DataStructures", v"0.4.6"], + ["ParameterizedFunctions", v"0.5.1", "SimpleTraits", v"0.1.1"], + ["ParameterizedFunctions", v"0.5.1", "DiffEqBase", v"0.4.0", v"0.5.0"], + ["ParameterizedFunctions", v"0.5.1", "SymEngine", v"0.1.2"], + ["ParameterizedFunctions", v"1.2.0", "DataStructures", v"0.4.6"], + ["ParameterizedFunctions", v"1.2.0", "SimpleTraits", v"0.1.1"], + ["ParameterizedFunctions", v"1.2.0", "DiffEqBase", v"0.5.0", v"0.14.0"], + ["ParameterizedFunctions", v"1.2.0", "SymEngine", v"0.1.2"], + ["ParameterizedFunctions", v"1.3.0", "DataStructures", v"0.4.6"], + ["ParameterizedFunctions", v"1.3.0", "DiffEqBase", v"0.14.0"], + ["ParameterizedFunctions", v"1.3.0", "SimpleTraits", v"0.1.1"], + ["ParameterizedFunctions", v"1.3.0", "SymEngine", v"0.1.2"], + ["Parameters", v"0.5.0", "Compat", v"0.7.15"], + ["Parameters", v"0.5.0", "DataStructures", v"0.4.3"], + ["Parameters", v"0.6.0", "DataStructures", v"0.4.3"], + ["Parameters", v"0.7.1", "Compat", v"0.17.0"], + ["Parameters", v"0.7.1", "DataStructures", v"0.5.2"], + ["Parameters", v"0.7.2", "DataStructures", v"0.5.2"], + ["PlotThemes", v"0.1.1", "PlotUtils"], + ["PlotUtils", v"0.0.1"], + ["PlotUtils", v"0.3.0", "Colors"], + ["PlotUtils", v"0.3.0", "Reexport"], + ["Plots", v"0.1.0", "Colors"], + ["Plots", v"0.1.0", "FactCheck"], + ["Plots", v"0.1.0", "JSON", v"0.0.0", v"0.9.0"], + ["Plots", v"0.1.3", "Colors"], + ["Plots", v"0.1.3", "JSON", v"0.0.0", v"0.9.0"], + ["Plots", v"0.3.0", "Colors"], + ["Plots", v"0.3.0", "Reexport"], + ["Plots", v"0.3.0", "JSON", v"0.0.0", v"0.9.0"], + ["Plots", v"0.5.1", "Colors"], + ["Plots", v"0.5.1", "Compat"], + ["Plots", v"0.5.1", "Reexport"], + ["Plots", v"0.5.1", "JSON", v"0.0.0", v"0.9.0"], + ["Plots", v"0.5.2", "Colors"], + ["Plots", v"0.5.2", "Compat"], + ["Plots", v"0.5.2", "Reexport"], + ["Plots", v"0.5.2", "Requires"], + ["Plots", v"0.5.2", "JSON", v"0.0.0", v"0.9.0"], + ["Plots", v"0.6.1", "Colors"], + ["Plots", v"0.6.1", "Compat"], + ["Plots", v"0.6.1", "FixedSizeArrays"], + ["Plots", v"0.6.1", "Reexport"], + ["Plots", v"0.6.1", "Requires"], + ["Plots", v"0.6.1", "JSON", v"0.0.0", v"0.9.0"], + ["Plots", v"0.6.2", "Colors"], + ["Plots", v"0.6.2", "Compat"], + ["Plots", v"0.6.2", "FixedSizeArrays"], + ["Plots", v"0.6.2", "Reexport"], + ["Plots", v"0.6.2", "Requires"], + ["Plots", v"0.6.2", "JSON", v"0.0.0", v"0.9.0"], + ["Plots", v"0.6.2", "RecipesBase", v"0.0.1", v"0.0.2"], + ["Plots", v"0.7.5", "Colors"], + ["Plots", v"0.7.5", "Compat"], + ["Plots", v"0.7.5", "FixedSizeArrays"], + ["Plots", v"0.7.5", "Measures"], + ["Plots", v"0.7.5", "JSON", v"0.0.0", v"0.9.0"], + ["Plots", v"0.7.5", "RecipesBase"], + ["Plots", v"0.7.5", "Reexport"], + ["Plots", v"0.8.0", "Compat"], + ["Plots", v"0.8.0", "FixedSizeArrays"], + ["Plots", v"0.8.0", "Measures"], + ["Plots", v"0.8.0", "PlotUtils"], + ["Plots", v"0.8.0", "JSON", v"0.0.0", v"0.9.0"], + ["Plots", v"0.8.0", "RecipesBase"], + ["Plots", v"0.8.0", "Reexport"], + ["Plots", v"0.9.0", "Compat"], + ["Plots", v"0.9.0", "FixedSizeArrays"], + ["Plots", v"0.9.0", "Measures"], + ["Plots", v"0.9.0", "PlotUtils"], + ["Plots", v"0.9.0", "RecipesBase"], + ["Plots", v"0.9.0", "Reexport"], + ["Plots", v"0.9.0", "JSON", v"0.0.0", v"0.9.0"], + ["Plots", v"0.9.0", "Showoff"], + ["Plots", v"0.9.1", "Compat"], + ["Plots", v"0.9.1", "FixedSizeArrays"], + ["Plots", v"0.9.1", "Measures"], + ["Plots", v"0.9.1", "PlotUtils"], + ["Plots", v"0.9.1", "RecipesBase"], + ["Plots", v"0.9.1", "Reexport"], + ["Plots", v"0.9.1", "Showoff"], + ["Plots", v"0.9.3", "Compat"], + ["Plots", v"0.9.3", "FixedSizeArrays"], + ["Plots", v"0.9.3", "Measures"], + ["Plots", v"0.9.3", "PlotUtils"], + ["Plots", v"0.9.3", "RecipesBase"], + ["Plots", v"0.9.3", "Reexport"], + ["Plots", v"0.9.3", "Showoff"], + ["Plots", v"0.9.4", "FixedSizeArrays"], + ["Plots", v"0.9.4", "Measures"], + ["Plots", v"0.9.4", "PlotUtils"], + ["Plots", v"0.9.4", "RecipesBase"], + ["Plots", v"0.9.4", "Reexport"], + ["Plots", v"0.9.4", "Showoff"], + ["Plots", v"0.10.3", "FixedSizeArrays"], + ["Plots", v"0.10.3", "Measures"], + ["Plots", v"0.10.3", "PlotThemes"], + ["Plots", v"0.10.3", "PlotUtils"], + ["Plots", v"0.10.3", "RecipesBase"], + ["Plots", v"0.10.3", "Reexport"], + ["Plots", v"0.10.3", "Showoff"], + ["PolynomialFactors", v"0.0.1", "Combinatorics", v"0.2.1"], + ["PolynomialFactors", v"0.0.1", "Compat", v"0.7.15"], + ["PolynomialFactors", v"0.0.1", "Iterators", v"0.1.0"], + ["PolynomialFactors", v"0.0.1", "Primes", v"0.1.1"], + ["PolynomialFactors", v"0.0.2", "Combinatorics", v"0.2.1"], + ["PolynomialFactors", v"0.0.2", "Compat", v"0.7.15"], + ["PolynomialFactors", v"0.0.2", "Iterators", v"0.1.0"], + ["PolynomialFactors", v"0.0.2", "Polynomials", v"0.1.1"], + ["PolynomialFactors", v"0.0.2", "Primes", v"0.1.1"], + ["PolynomialFactors", v"0.0.4", "Combinatorics", v"0.2.1"], + ["PolynomialFactors", v"0.0.4", "Compat", v"0.7.15"], + ["PolynomialFactors", v"0.0.4", "Iterators", v"0.1.0"], + ["PolynomialFactors", v"0.0.4", "Polynomials", v"0.1.1"], + ["PolynomialFactors", v"0.0.4", "Primes", v"0.1.1"], + ["Polynomials", v"0.0.2"], + ["Polynomials", v"0.0.3"], + ["Polynomials", v"0.0.4", "Compat"], + ["Polynomials", v"0.0.5", "Compat"], + ["Polynomials", v"0.1.0", "Compat", v"0.7.15"], + ["Polynomials", v"0.1.1", "Compat", v"0.8.0"], + ["Polynomials", v"0.1.5", "Compat", v"0.9.4"], + ["PositiveFactorizations", v"0.0.1"], + ["PositiveFactorizations", v"0.0.3", "Compat", v"0.8.4"], + ["PositiveFactorizations", v"0.0.4", "Compat", v"0.12.0"], + ["PowerSeries", v"0.1.10"], + ["PowerSeries", v"0.1.14", "Compat", v"0.4.7"], + ["PowerSeries", v"0.2.0"], + ["Primes", v"0.1.0"], + ["Primes", v"0.1.1"], + ["Primes", v"0.1.3", "Compat", v"0.9.4"], + ["PyCall", v"0.4.10"], + ["PyCall", v"0.6.2", "Compat", v"0.2.0"], + ["PyCall", v"0.7.3", "Compat", v"0.2.0"], + ["PyCall", v"0.7.3", "Dates"], + ["PyCall", v"0.7.4", "Compat", v"0.3.1"], + ["PyCall", v"0.7.4", "Dates"], + ["PyCall", v"0.7.5", "Compat", v"0.3.4"], + ["PyCall", v"0.7.5", "Dates"], + ["PyCall", v"0.8.1", "Compat", v"0.4.0"], + ["PyCall", v"0.8.1", "Dates"], + ["PyCall", v"1.0.1", "Compat", v"0.4.6"], + ["PyCall", v"1.0.1", "Dates"], + ["PyCall", v"1.0.3", "Compat", v"0.7.1"], + ["PyCall", v"1.0.3", "Dates"], + ["PyCall", v"1.4.0", "Compat", v"0.7.1"], + ["PyCall", v"1.4.0", "Conda", v"0.1.6"], + ["PyCall", v"1.4.0", "Dates"], + ["PyCall", v"1.5.0", "Compat", v"0.7.15"], + ["PyCall", v"1.5.0", "Conda", v"0.1.6"], + ["PyCall", v"1.5.0", "MacroTools", v"0.2.0"], + ["PyCall", v"1.6.2", "Compat", v"0.7.15"], + ["PyCall", v"1.6.2", "Conda", v"0.2.0"], + ["PyCall", v"1.6.2", "MacroTools", v"0.2.0"], + ["PyCall", v"1.7.2", "Compat", v"0.8.0"], + ["PyCall", v"1.7.2", "Conda", v"0.2.0"], + ["PyCall", v"1.7.2", "MacroTools", v"0.2.0"], + ["PyCall", v"1.10.0", "Compat", v"0.9.5"], + ["PyCall", v"1.10.0", "Conda", v"0.2.0"], + ["PyCall", v"1.10.0", "MacroTools", v"0.2.0"], + ["PyCall", v"1.12.0", "Compat", v"0.18.0"], + ["PyCall", v"1.12.0", "Conda", v"0.2.0"], + ["PyCall", v"1.12.0", "MacroTools", v"0.2.0"], + ["PyDSTool", v"0.0.1", "DataStructures"], + ["PyDSTool", v"0.0.1", "PyCall"], + ["PyDSTool", v"0.0.2", "Conda"], + ["PyDSTool", v"0.0.2", "DataStructures"], + ["PyDSTool", v"0.0.2", "PyCall"], + ["PyDSTool", v"0.1.1", "Conda"], + ["PyDSTool", v"0.1.1", "DataStructures"], + ["PyDSTool", v"0.1.1", "DiffEqBase", v"0.11.0"], + ["PyDSTool", v"0.1.1", "PyCall"], + ["PyDSTool", v"0.1.1", "RecipesBase"], + ["PyDSTool", v"0.1.2", "DataStructures"], + ["PyDSTool", v"0.1.2", "PyCall"], + ["PyDSTool", v"0.1.2", "RecipesBase"], + ["PyDSTool", v"0.1.2", "Conda", v"0.2.0"], + ["PyDSTool", v"0.1.2", "DiffEqBase", v"0.11.0"], + ["QuadGK", v"0.1.0"], + ["QuadGK", v"0.1.2", "DataStructures", v"0.5.0"], + ["RangeArrays", v"0.1.1"], + ["RangeArrays", v"0.1.2", "Compat", v"0.19.0"], + ["Ranges", v"0.0.1"], + ["Ratios", v"0.0.3"], + ["Ratios", v"0.0.4", "Compat"], + ["Reactive", v"0.2.4", "FactCheck"], + ["Reactive", v"0.2.4", "Compat", v"0.4.0"], + ["Reactive", v"0.3.4", "Compat"], + ["Reactive", v"0.3.5", "Compat", v"0.9.2"], + ["Reactive", v"0.3.6"], + ["Reactive", v"0.3.7", "DataStructures"], + ["RecipesBase", v"0.1.0"], + ["RecursiveArrayTools", v"0.0.1"], + ["RecursiveArrayTools", v"0.1.1"], + ["RecursiveArrayTools", v"0.1.2"], + ["RecursiveArrayTools", v"0.2.0"], + ["Reexport", v"0.0.2"], + ["Reexport", v"0.0.3"], + ["Requires", v"0.2.3", "MacroTools"], + ["Requires", v"0.4.1"], + ["ResettableStacks", v"0.1.0"], + ["Rmath", v"0.1.0", "BinDeps"], + ["Rmath", v"0.1.2", "BinDeps"], + ["Rmath", v"0.1.2", "Compat", v"0.8.4"], + ["Rmath", v"0.1.6", "BinDeps"], + ["Rmath", v"0.1.6", "Compat", v"0.9.1"], + ["Roots", v"0.1.9", "Polynomials", v"0.0.3"], + ["Roots", v"0.1.9", "ForwardDiff", v"0.0.0", v"0.2.0"], + ["Roots", v"0.1.9", "PowerSeries", v"0.1.0"], + ["Roots", v"0.1.13", "Docile", v"0.4.0"], + ["Roots", v"0.1.13", "Polynomials", v"0.0.3"], + ["Roots", v"0.1.13", "ForwardDiff", v"0.0.0", v"0.2.0"], + ["Roots", v"0.1.13", "PowerSeries", v"0.1.11"], + ["Roots", v"0.1.18", "Compat", v"0.4.0"], + ["Roots", v"0.1.18", "Docile", v"0.4.0"], + ["Roots", v"0.1.18", "Polynomials", v"0.0.3"], + ["Roots", v"0.1.18", "ForwardDiff", v"0.0.0", v"0.2.0"], + ["Roots", v"0.1.18", "PowerSeries", v"0.1.11"], + ["Roots", v"0.1.22", "Compat", v"0.4.0"], + ["Roots", v"0.1.22", "Docile", v"0.4.0"], + ["Roots", v"0.1.22", "Polynomials", v"0.0.3"], + ["Roots", v"0.1.22", "ForwardDiff", v"0.0.0", v"0.2.0"], + ["Roots", v"0.1.26", "Compat", v"0.4.0"], + ["Roots", v"0.1.26", "Docile", v"0.4.0"], + ["Roots", v"0.1.26", "Polynomials", v"0.0.5"], + ["Roots", v"0.1.26", "ForwardDiff", v"0.0.0", v"0.2.0"], + ["Roots", v"0.2.0", "Primes"], + ["Roots", v"0.2.0", "Compat", v"0.4.0"], + ["Roots", v"0.2.0", "Docile", v"0.4.0"], + ["Roots", v"0.2.0", "ForwardDiff", v"0.2.0"], + ["Roots", v"0.2.0", "Polynomials", v"0.0.5"], + ["Roots", v"0.2.1", "Primes"], + ["Roots", v"0.2.1", "Compat", v"0.4.0"], + ["Roots", v"0.2.1", "ForwardDiff", v"0.2.0"], + ["Roots", v"0.2.1", "Polynomials", v"0.0.5"], + ["Roots", v"0.3.0", "Compat", v"0.8.0"], + ["Roots", v"0.3.0", "ForwardDiff", v"0.2.0"], + ["Roots", v"0.3.0", "PolynomialFactors", v"0.0.3"], + ["Roots", v"0.3.0", "Polynomials", v"0.0.5"], + ["Rotations", v"0.3.4", "StaticArrays", v"0.0.3", v"0.3.0-"], + ["Rotations", v"0.3.5", "StaticArrays", v"0.3.0", v"0.4.0-"], + ["Rotations", v"0.4.0", "StaticArrays", v"0.4.0", v"0.5.0-"], + ["SHA", v"0.0.2"], + ["SHA", v"0.0.3"], + ["SHA", v"0.2.0", "Compat", v"0.3.5"], + ["SHA", v"0.2.1", "Compat", v"0.7.9"], + ["SHA", v"0.3.1", "Compat", v"0.9.4"], + ["SHA", v"0.3.2", "Compat", v"0.17.0"], + ["SIUnits", v"0.0.5", "TexExtensions"], + ["SIUnits", v"0.0.6", "Compat"], + ["SIUnits", v"0.0.6", "TexExtensions"], + ["SIUnits", v"0.1.0", "TexExtensions"], + ["SIUnits", v"0.1.0", "Compat", v"0.8.0"], + ["ShowItLikeYouBuildIt", v"0.0.1"], + ["Showoff", v"0.0.1"], + ["Showoff", v"0.0.3", "Iterators"], + ["Showoff", v"0.0.7", "Compat"], + ["Showoff", v"0.0.7", "Iterators"], + ["Showoff", v"0.1.0", "Compat", v"0.9.5"], + ["Showoff", v"0.1.1", "Compat", v"0.18.0"], + ["SimpleTraits", v"0.1.0", "Compat"], + ["SimpleTraits", v"0.1.1"], + ["SimpleTraits", v"0.2.0", "MacroTools", v"0.3.2"], + ["SimpleTraits", v"0.4.0", "Compat", v"0.19.0"], + ["SimpleTraits", v"0.4.0", "MacroTools", v"0.3.2"], + ["SortingAlgorithms", v"0.0.3"], + ["SortingAlgorithms", v"0.0.6", "Compat"], + ["SortingAlgorithms", v"0.1.0", "Compat", v"0.8.4"], + ["SortingAlgorithms", v"0.1.1", "Compat", v"0.9.4"], + ["SortingAlgorithms", v"0.1.1", "DataStructures", v"0.5.3"], + ["SpecialFunctions", v"0.0.1", "Compat", v"0.9.1"], + ["SpecialFunctions", v"0.1.0", "Compat", v"0.9.1"], + ["SpecialFunctions", v"0.1.1", "Compat", v"0.18.0"], + ["StaticArrays", v"0.0.2"], + ["StaticArrays", v"0.0.4"], + ["StaticArrays", v"0.2.1"], + ["StaticArrays", v"0.3.0"], + ["StaticArrays", v"0.4.0"], + ["Stats", v"0.0.1", "StatsBase", v"0.3.0-"], + ["Stats", v"0.1.0", "StatsBase"], + ["StatsBase", v"0.2.4", "NumericExtensions"], + ["StatsBase", v"0.2.9"], + ["StatsBase", v"0.3.9"], + ["StatsBase", v"0.4.1"], + ["StatsBase", v"0.6.8", "ArrayViews", v"0.4.6-"], + ["StatsBase", v"0.6.9", "ArrayViews", v"0.4.8-"], + ["StatsBase", v"0.6.10", "ArrayViews", v"0.4.8-"], + ["StatsBase", v"0.6.12", "ArrayViews", v"0.4.8-"], + ["StatsBase", v"0.6.12", "Compat", v"0.2.11-"], + ["StatsBase", v"0.6.13", "ArrayViews", v"0.4.10"], + ["StatsBase", v"0.6.13", "Compat", v"0.3.2"], + ["StatsBase", v"0.6.16", "ArrayViews", v"0.4.12"], + ["StatsBase", v"0.6.16", "Compat", v"0.4.0"], + ["StatsBase", v"0.7.4", "ArrayViews", v"0.4.12"], + ["StatsBase", v"0.7.4", "Compat", v"0.4.0"], + ["StatsBase", v"0.7.4", "StatsFuns", v"0.1.0"], + ["StatsBase", v"0.8.1", "ArrayViews", v"0.4.12"], + ["StatsBase", v"0.8.1", "Compat", v"0.4.0"], + ["StatsBase", v"0.8.1", "StatsFuns", v"0.1.0"], + ["StatsBase", v"0.8.2", "ArrayViews", v"0.4.12"], + ["StatsBase", v"0.8.2", "Compat", v"0.4.0"], + ["StatsBase", v"0.8.2", "StatsFuns", v"0.1.0"], + ["StatsBase", v"0.8.3", "Compat", v"0.8.4"], + ["StatsBase", v"0.8.3", "StatsFuns", v"0.1.0"], + ["StatsBase", v"0.9.0", "Compat", v"0.8.4"], + ["StatsBase", v"0.9.0", "StatsFuns", v"0.3.0"], + ["StatsBase", v"0.10.0", "Compat", v"0.8.4"], + ["StatsBase", v"0.12.0", "Compat", v"0.8.4"], + ["StatsBase", v"0.13.0", "Compat", v"0.13.0"], + ["StatsBase", v"0.13.0", "DataStructures", v"0.5.0"], + ["StatsBase", v"0.13.1", "Compat", v"0.18.0"], + ["StatsBase", v"0.13.1", "DataStructures", v"0.5.0"], + ["StatsBase", v"0.13.1", "SpecialFunctions", v"0.1.0"], + ["StatsFuns", v"0.0.3", "Compat", v"0.4.0"], + ["StatsFuns", v"0.1.0", "Compat", v"0.4.0"], + ["StatsFuns", v"0.2.1", "Compat", v"0.4.0"], + ["StatsFuns", v"0.2.2", "Compat", v"0.7.18"], + ["StatsFuns", v"0.3.0", "Compat", v"0.8.4"], + ["StatsFuns", v"0.3.0", "Rmath", v"0.1.0"], + ["StatsFuns", v"0.4.0", "Compat", v"0.9.1"], + ["StatsFuns", v"0.4.0", "Rmath", v"0.1.0"], + ["StatsFuns", v"0.5.0", "SpecialFunctions"], + ["StatsFuns", v"0.5.0", "Compat", v"0.9.1"], + ["StatsFuns", v"0.5.0", "Rmath", v"0.1.0"], + ["StochasticDiffEq", v"0.0.3", "ChunkedArrays", v"0.1.0"], + ["StochasticDiffEq", v"0.0.3", "DiffEqBase", v"0.0.0", v"0.8.0"], + ["StochasticDiffEq", v"0.0.3", "ParameterizedFunctions", v"0.1.0"], + ["StochasticDiffEq", v"0.0.3", "Parameters", v"0.5.0"], + ["StochasticDiffEq", v"0.0.4", "RecursiveArrayTools"], + ["StochasticDiffEq", v"0.0.4", "ChunkedArrays", v"0.1.0"], + ["StochasticDiffEq", v"0.0.4", "DiffEqBase", v"0.0.0", v"0.8.0"], + ["StochasticDiffEq", v"0.0.4", "ParameterizedFunctions", v"0.1.0"], + ["StochasticDiffEq", v"0.0.4", "Parameters", v"0.5.0"], + ["StochasticDiffEq", v"0.0.5", "RecursiveArrayTools"], + ["StochasticDiffEq", v"0.0.5", "ChunkedArrays", v"0.1.0"], + ["StochasticDiffEq", v"0.0.5", "DiffEqBase", v"0.0.0", v"0.8.0"], + ["StochasticDiffEq", v"0.0.5", "Parameters", v"0.5.0"], + ["StochasticDiffEq", v"0.2.0", "ChunkedArrays", v"0.1.0"], + ["StochasticDiffEq", v"0.2.0", "DiffEqBase", v"0.2.0", v"0.8.0"], + ["StochasticDiffEq", v"0.2.0", "Parameters", v"0.5.0"], + ["StochasticDiffEq", v"0.2.0", "RecursiveArrayTools", v"0.0.2"], + ["StochasticDiffEq", v"0.3.0", "ChunkedArrays", v"0.1.0"], + ["StochasticDiffEq", v"0.3.0", "DataStructures"], + ["StochasticDiffEq", v"0.3.0", "DiffEqBase", v"0.2.0", v"0.8.0"], + ["StochasticDiffEq", v"0.3.0", "Juno"], + ["StochasticDiffEq", v"0.3.0", "Parameters", v"0.5.0"], + ["StochasticDiffEq", v"0.3.0", "RecursiveArrayTools", v"0.0.2"], + ["StochasticDiffEq", v"0.3.0", "ResettableStacks"], + ["StochasticDiffEq", v"0.5.0", "ChunkedArrays", v"0.1.0"], + ["StochasticDiffEq", v"0.5.0", "DataStructures", v"0.4.6"], + ["StochasticDiffEq", v"0.5.0", "DiffEqBase", v"0.4.0", v"0.8.0"], + ["StochasticDiffEq", v"0.5.0", "Juno", v"0.2.5"], + ["StochasticDiffEq", v"0.5.0", "Parameters", v"0.5.0"], + ["StochasticDiffEq", v"0.5.0", "RecursiveArrayTools", v"0.1.2"], + ["StochasticDiffEq", v"0.5.0", "ResettableStacks", v"0.0.1"], + ["StochasticDiffEq", v"1.0.2", "Iterators"], + ["StochasticDiffEq", v"1.0.2", "Roots"], + ["StochasticDiffEq", v"1.0.2", "DataStructures", v"0.4.6"], + ["StochasticDiffEq", v"1.0.2", "DiffEqBase", v"0.8.0", v"0.15.0"], + ["StochasticDiffEq", v"1.0.2", "Juno", v"0.2.5"], + ["StochasticDiffEq", v"1.0.2", "Parameters", v"0.5.0"], + ["StochasticDiffEq", v"1.0.2", "RecursiveArrayTools", v"0.2.0"], + ["StochasticDiffEq", v"1.0.2", "ResettableStacks", v"0.0.1"], + ["StochasticDiffEq", v"1.1.0", "Iterators"], + ["StochasticDiffEq", v"1.1.0", "Roots"], + ["StochasticDiffEq", v"1.1.0", "DataStructures", v"0.4.6"], + ["StochasticDiffEq", v"1.1.0", "DiffEqBase", v"0.11.0", v"0.15.0"], + ["StochasticDiffEq", v"1.1.0", "Juno", v"0.2.5"], + ["StochasticDiffEq", v"1.1.0", "Parameters", v"0.5.0"], + ["StochasticDiffEq", v"1.1.0", "RecursiveArrayTools", v"0.2.0"], + ["StochasticDiffEq", v"1.1.0", "ResettableStacks", v"0.0.1"], + ["StochasticDiffEq", v"1.2.1", "Compat", v"0.17.0"], + ["StochasticDiffEq", v"1.2.1", "Iterators"], + ["StochasticDiffEq", v"1.2.1", "Roots"], + ["StochasticDiffEq", v"1.2.1", "DataStructures", v"0.4.6"], + ["StochasticDiffEq", v"1.2.1", "DiffEqBase", v"0.11.0", v"0.15.0"], + ["StochasticDiffEq", v"1.2.1", "Juno", v"0.2.5"], + ["StochasticDiffEq", v"1.2.1", "Parameters", v"0.5.0"], + ["StochasticDiffEq", v"1.2.1", "RecursiveArrayTools", v"0.2.0"], + ["StochasticDiffEq", v"1.2.1", "ResettableStacks", v"0.0.1"], + ["StochasticDiffEq", v"1.3.0", "Compat", v"0.17.0"], + ["StochasticDiffEq", v"1.3.0", "Iterators"], + ["StochasticDiffEq", v"1.3.0", "Roots"], + ["StochasticDiffEq", v"1.3.0", "DataStructures", v"0.4.6"], + ["StochasticDiffEq", v"1.3.0", "DiffEqBase", v"0.13.0", v"0.15.0"], + ["StochasticDiffEq", v"1.3.0", "Juno", v"0.2.5"], + ["StochasticDiffEq", v"1.3.0", "Parameters", v"0.5.0"], + ["StochasticDiffEq", v"1.3.0", "RecursiveArrayTools", v"0.2.0"], + ["StochasticDiffEq", v"1.3.0", "ResettableStacks", v"0.0.1"], + ["StochasticDiffEq", v"1.4.0", "Compat", v"0.17.0"], + ["StochasticDiffEq", v"1.4.0", "DiffEqBase", v"0.15.0"], + ["StochasticDiffEq", v"1.4.0", "Iterators"], + ["StochasticDiffEq", v"1.4.0", "Roots"], + ["StochasticDiffEq", v"1.4.0", "DataStructures", v"0.4.6"], + ["StochasticDiffEq", v"1.4.0", "Juno", v"0.2.5"], + ["StochasticDiffEq", v"1.4.0", "Parameters", v"0.5.0"], + ["StochasticDiffEq", v"1.4.0", "RecursiveArrayTools", v"0.2.0"], + ["StochasticDiffEq", v"1.4.0", "ResettableStacks", v"0.0.1"], + ["StokesDiffEq", v"0.0.1", "DiffEqBase"], + ["StokesDiffEq", v"0.0.1", "Parameters", v"0.5.0"], + ["StokesDiffEq", v"0.0.1", "VectorizedRoutines", v"0.0.1"], + ["StokesDiffEq", v"0.0.2", "DiffEqBase"], + ["StokesDiffEq", v"0.0.2", "Parameters", v"0.5.0"], + ["StokesDiffEq", v"0.0.2", "VectorizedRoutines", v"0.0.1"], + ["StokesDiffEq", v"0.1.0", "DiffEqBase", v"0.4.0"], + ["StokesDiffEq", v"0.1.0", "Parameters", v"0.5.0"], + ["StokesDiffEq", v"0.1.0", "VectorizedRoutines", v"0.0.2"], + ["StrPack", v"0.0.1"], + ["StructIO", v"0.0.2"], + ["Sundials", v"0.0.0"], + ["Sundials", v"0.1.2", "BinDeps"], + ["Sundials", v"0.2.0", "BinDeps", v"0.3.0"], + ["Sundials", v"0.2.2", "Compat"], + ["Sundials", v"0.2.2", "BinDeps", v"0.3.0"], + ["Sundials", v"0.3.0", "BinDeps", v"0.4.3"], + ["Sundials", v"0.3.0", "Compat", v"0.9.0"], + ["Sundials", v"0.4.0", "BinDeps", v"0.4.3"], + ["Sundials", v"0.4.0", "Compat", v"0.9.0"], + ["Sundials", v"0.4.0", "DiffEqBase", v"0.0.0", v"0.2.0"], + ["Sundials", v"0.9.0", "BinDeps", v"0.4.3"], + ["Sundials", v"0.9.0", "Compat", v"0.9.0"], + ["Sundials", v"0.9.0", "DiffEqBase", v"0.2.0", v"0.15.0"], + ["Sundials", v"0.10.0", "BinDeps", v"0.4.3"], + ["Sundials", v"0.10.0", "Compat", v"0.9.0"], + ["Sundials", v"0.10.0", "DiffEqBase", v"0.15.0"], + ["SymEngine", v"0.1.0", "BinDeps"], + ["SymEngine", v"0.1.0", "Conda"], + ["SymEngine", v"0.1.0", "Compat", v"0.8.5"], + ["SymEngine", v"0.1.0", "RecipesBase", v"0.0.6"], + ["SymEngine", v"0.1.1", "BinDeps", v"0.4.0"], + ["SymEngine", v"0.1.1", "Compat", v"0.8.5"], + ["SymEngine", v"0.1.1", "Conda", v"0.3.0"], + ["SymEngine", v"0.1.1", "RecipesBase", v"0.0.6"], + ["SymEngine", v"0.1.2", "BinDeps", v"0.4.0"], + ["SymEngine", v"0.1.2", "Compat", v"0.8.5"], + ["SymEngine", v"0.1.2", "Conda", v"0.4.0"], + ["SymEngine", v"0.1.2", "RecipesBase", v"0.0.6"], + ["SymEngine", v"0.1.5", "BinDeps", v"0.4.0"], + ["SymEngine", v"0.1.5", "Compat", v"0.9.5"], + ["SymEngine", v"0.1.5", "Conda", v"0.4.0"], + ["SymEngine", v"0.1.5", "RecipesBase", v"0.0.6"], + ["TerminalUI", v"0.0.1", "Reactive"], + ["TerminalUI", v"0.0.1", "VT100"], + ["TerminalUI", v"0.0.2", "AbstractTrees"], + ["TerminalUI", v"0.0.2", "Colors"], + ["TerminalUI", v"0.0.2", "Compat"], + ["TerminalUI", v"0.0.2", "FixedPointNumbers"], + ["TerminalUI", v"0.0.2", "Reactive"], + ["TerminalUI", v"0.0.2", "VT100"], + ["TexExtensions", v"0.0.2"], + ["TexExtensions", v"0.0.3", "Compat"], + ["TextWrap", v"0.0.0", "Options"], + ["TextWrap", v"0.1.3"], + ["TextWrap", v"0.1.4"], + ["TextWrap", v"0.1.5", "Compat", v"0.7.3"], + ["TextWrap", v"0.1.6", "Compat", v"0.7.15"], + ["TextWrap", v"0.2.0", "Compat", v"0.9.5"], + ["TiledIteration", v"0.0.2", "OffsetArrays"], + ["URIParser", v"0.0.4", "Compat"], + ["URIParser", v"0.0.5", "Compat", v"0.3.5"], + ["URIParser", v"0.1.0", "HttpCommon"], + ["URIParser", v"0.1.0", "Compat", v"0.3.5"], + ["URIParser", v"0.1.3"], + ["URIParser", v"0.1.6", "Compat", v"0.8.0"], + ["URIParser", v"0.1.8", "Compat", v"0.9.5"], + ["VT100", v"0.0.1", "Colors"], + ["VT100", v"0.0.1", "Compat"], + ["VT100", v"0.0.1", "FixedPointNumbers"], + ["VT100", v"0.0.2", "Colors"], + ["VT100", v"0.0.2", "FixedPointNumbers"], + ["VT100", v"0.0.2", "Compat", v"0.7.15"], + ["VT100", v"0.1.0", "ColorTypes", v"0.3.4"], + ["VT100", v"0.1.0", "Compat", v"0.17.0"], + ["VT100", v"0.1.0", "FixedPointNumbers", v"0.3.0"], + ["VectorizedRoutines", v"0.0.1", "Distributions"], + ["VectorizedRoutines", v"0.0.1", "StatsFuns"], + ["VectorizedRoutines", v"0.0.2", "Distributions"], + ["WebSockets", v"0.0.0", "HttpCommon"], + ["WebSockets", v"0.0.0", "HttpServer"], + ["WebSockets", v"0.0.1"], + ["WebSockets", v"0.0.3", "Codecs"], + ["WebSockets", v"0.0.3", "HttpCommon"], + ["WebSockets", v"0.0.3", "HttpServer"], + ["WebSockets", v"0.0.5", "Codecs"], + ["WebSockets", v"0.0.5", "HttpCommon", v"0.0.3-"], + ["WebSockets", v"0.0.5", "HttpServer", v"0.0.4-"], + ["WebSockets", v"0.0.6", "Codecs"], + ["WebSockets", v"0.0.6", "Nettle"], + ["WebSockets", v"0.0.6", "HttpCommon", v"0.0.3-"], + ["WebSockets", v"0.0.6", "HttpServer", v"0.0.4-"], + ["WebSockets", v"0.1.0", "Codecs"], + ["WebSockets", v"0.1.0", "Compat"], + ["WebSockets", v"0.1.0", "Nettle"], + ["WebSockets", v"0.1.0", "HttpCommon", v"0.0.3"], + ["WebSockets", v"0.1.0", "HttpServer", v"0.0.4"], + ["WebSockets", v"0.1.2", "Codecs"], + ["WebSockets", v"0.1.2", "Compat"], + ["WebSockets", v"0.1.2", "HttpCommon", v"0.0.3"], + ["WebSockets", v"0.1.2", "HttpServer", v"0.0.4"], + ["WebSockets", v"0.1.2", "Nettle", v"0.2.0"], + ["WebSockets", v"0.2.1", "Codecs"], + ["WebSockets", v"0.2.1", "MbedTLS"], + ["WebSockets", v"0.2.1", "Compat", v"0.7.16"], + ["WebSockets", v"0.2.1", "HttpCommon", v"0.0.3"], + ["WebSockets", v"0.2.1", "HttpServer", v"0.0.4"], + ["WoodburyMatrices", v"0.0.2"], + ["WoodburyMatrices", v"0.1.3", "Docile"], + ["WoodburyMatrices", v"0.1.4", "Compat"], + ["WoodburyMatrices", v"0.1.4", "Docile"], + ["WoodburyMatrices", v"0.1.5", "Compat"], + ["WoodburyMatrices", v"0.1.5", "Docile"], + ["WoodburyMatrices", v"0.2.1", "Compat"], + ["WoodburyMatrices", v"0.2.2", "Compat", v"0.7.19"], + ["Zlib", v"0.1.9"], + ["Zlib", v"0.1.12", "Compat"], +] + +problematic_data = Any[ + ("CoordinateTransformations", v"0.2.0"), + ("Plots", v"0.6.2"), + ("Roots", v"0.1.9"), + ("Roots", v"0.1.13"), + ("Roots", v"0.1.18"), + ("Roots", v"0.1.22"), + ("Roots", v"0.1.26"), +] + +reqs_data = Any[ + ["Atom"], + ["DifferentialEquations"], + ["ImageMagick"], + ["Plots"], +] + +want_data = Dict( + "ASTInterpreter"=>v"0.0.4", + "AbstractTrees"=>v"0.0.4", + "AlgebraicDiffEq"=>v"0.1.0", + "ArgParse"=>v"0.4.0", + "Atom"=>v"0.5.10", + "AxisAlgorithms"=>v"0.1.6", + "AxisArrays"=>v"0.1.2", + "BinDeps"=>v"0.4.7", + "Blink"=>v"0.5.1", + "COFF"=>v"0.0.2", + "CRC"=>v"1.2.0", + "Calculus"=>v"0.2.2", + "CatIndices"=>v"0.0.2", + "ChunkedArrays"=>v"0.1.1", + "CodeTools"=>v"0.4.3", + "Codecs"=>v"0.3.0", + "ColorTypes"=>v"0.4.1", + "ColorVectorSpace"=>v"0.4.2", + "Colors"=>v"0.7.3", + "Combinatorics"=>v"0.4.0", + "Compat"=>v"0.24.0", + "ComputationalResources"=>v"0.0.2", + "Conda"=>v"0.5.3", + "CoordinateTransformations"=>v"0.4.1", + "CustomUnitRanges"=>v"0.0.4", + "DWARF"=>v"0.1.0", + "DataStructures"=>v"0.5.3", + "DelayDiffEq"=>v"0.3.0", + "DiffBase"=>v"0.1.0", + "DiffEqBase"=>v"0.15.0", + "DiffEqBiological"=>v"0.0.1", + "DiffEqCallbacks"=>v"0.0.2", + "DiffEqDevTools"=>v"0.7.0", + "DiffEqFinancial"=>v"0.1.0", + "DiffEqJump"=>v"0.3.0", + "DiffEqMonteCarlo"=>v"0.2.0", + "DiffEqPDEBase"=>v"0.2.0", + "DiffEqParamEstim"=>v"0.2.0", + "DiffEqSensitivity"=>v"0.1.0", + "DifferentialEquations"=>v"1.10.1", + "Distances"=>v"0.4.1", + "Distributions"=>v"0.12.5", + "DualNumbers"=>v"0.3.0", + "ELF"=>v"0.1.0", + "EllipsisNotation"=>v"0.1.0", + "FFTViews"=>v"0.0.2", + "FileIO"=>v"0.3.1", + "FiniteElementDiffEq"=>v"0.3.0", + "FixedPointNumbers"=>v"0.3.6", + "FixedSizeArrays"=>v"0.2.5", + "ForwardDiff"=>v"0.4.2", + "Gallium"=>v"0.0.4", + "GenericSVD"=>v"0.0.2", + "Graphics"=>v"0.2.0", + "Hiccup"=>v"0.1.1", + "HttpCommon"=>v"0.2.7", + "HttpParser"=>v"0.2.0", + "HttpServer"=>v"0.2.0", + "ImageAxes"=>v"0.2.1", + "ImageCore"=>v"0.3.0", + "ImageFiltering"=>v"0.1.4", + "ImageMagick"=>v"0.2.4", + "ImageMetadata"=>v"0.2.3", + "ImageTransformations"=>v"0.2.2", + "Images"=>v"0.9.1", + "IndirectArrays"=>v"0.1.1", + "InplaceOps"=>v"0.1.0", + "Interpolations"=>v"0.5.0", + "IntervalSets"=>v"0.0.5", + "IterativeSolvers"=>v"0.2.2", + "Iterators"=>v"0.3.0", + "JSON"=>v"0.9.0", + "JuliaParser"=>v"0.7.4", + "Juno"=>v"0.2.7", + "LNR"=>v"0.0.2", + "Lazy"=>v"0.11.6", + "LearnBase"=>v"0.1.5", + "LineSearches"=>v"0.1.5", + "LossFunctions"=>v"0.1.0", + "LsqFit"=>v"0.2.0", + "MachO"=>v"0.0.4", + "MacroTools"=>v"0.3.6", + "MappedArrays"=>v"0.0.7", + "MbedTLS"=>v"0.4.5", + "Measures"=>v"0.1.0", + "Media"=>v"0.2.7", + "MultiScaleArrays"=>v"0.1.0", + "Mustache"=>v"0.1.4", + "Mux"=>v"0.2.3", + "NLsolve"=>v"0.9.1", + "NaNMath"=>v"0.2.4", + "ObjFileBase"=>v"0.0.4", + "OffsetArrays"=>v"0.3.0", + "Optim"=>v"0.7.8", + "OrdinaryDiffEq"=>v"1.8.0", + "PDMats"=>v"0.6.0", + "ParameterizedFunctions"=>v"1.3.0", + "Parameters"=>v"0.7.2", + "PlotThemes"=>v"0.1.1", + "PlotUtils"=>v"0.3.0", + "Plots"=>v"0.10.3", + "PolynomialFactors"=>v"0.0.4", + "Polynomials"=>v"0.1.5", + "PositiveFactorizations"=>v"0.0.4", + "Primes"=>v"0.1.3", + "QuadGK"=>v"0.1.2", + "RangeArrays"=>v"0.1.2", + "Ranges"=>v"0.0.1", + "Ratios"=>v"0.0.4", + "Reactive"=>v"0.3.7", + "RecipesBase"=>v"0.1.0", + "RecursiveArrayTools"=>v"0.2.0", + "Reexport"=>v"0.0.3", + "ResettableStacks"=>v"0.1.0", + "Rmath"=>v"0.1.6", + "Roots"=>v"0.3.0", + "Rotations"=>v"0.4.0", + "SHA"=>v"0.3.2", + "SIUnits"=>v"0.1.0", + "ShowItLikeYouBuildIt"=>v"0.0.1", + "Showoff"=>v"0.1.1", + "SimpleTraits"=>v"0.4.0", + "SpecialFunctions"=>v"0.1.1", + "StaticArrays"=>v"0.4.0", + "StatsBase"=>v"0.13.1", + "StatsFuns"=>v"0.5.0", + "StochasticDiffEq"=>v"1.4.0", + "StokesDiffEq"=>v"0.1.0", + "StructIO"=>v"0.0.2", + "Sundials"=>v"0.10.0", + "SymEngine"=>v"0.1.5", + "TerminalUI"=>v"0.0.2", + "TexExtensions"=>v"0.0.3", + "TextWrap"=>v"0.2.0", + "TiledIteration"=>v"0.0.2", + "URIParser"=>v"0.1.8", + "VT100"=>v"0.1.0", + "VectorizedRoutines"=>v"0.0.2", + "WebSockets"=>v"0.2.1", + "WoodburyMatrices"=>v"0.2.2", +) From 9552d9de9fb34c66fdad926e8ef653600e9d9fc8 Mon Sep 17 00:00:00 2001 From: Mus M Date: Sat, 22 Apr 2017 13:18:33 -0400 Subject: [PATCH 0513/1534] Use Vector/Matrix instead of Array in arpack.jl (#21490) --- base/linalg/arpack.jl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/base/linalg/arpack.jl b/base/linalg/arpack.jl index 4b5d1d147e4e4..5b4a8541c096a 100644 --- a/base/linalg/arpack.jl +++ b/base/linalg/arpack.jl @@ -109,7 +109,7 @@ function eupd_wrapper(T, n::Integer, sym::Bool, cmplx::Bool, bmat::String, TOL::Ref, resid, ncv::Integer, v, ldv, sigma, iparam, ipntr, workd, workl, lworkl, rwork) howmny = "A" - select = Array{BlasInt}(ncv) + select = Vector{BlasInt}(ncv) info = zeros(BlasInt, 1) dmap = x->abs.(x) @@ -126,9 +126,9 @@ function eupd_wrapper(T, n::Integer, sym::Bool, cmplx::Bool, bmat::String, end if cmplx - d = Array{T}(nev+1) + d = Vector{T}(nev+1) sigmar = ones(T, 1)*sigma - workev = Array{T}(2ncv) + workev = Vector{T}(2ncv) neupd(ritzvec, howmny, select, d, v, ldv, sigmar, workev, bmat, n, which, nev, TOL, resid, ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, rwork, info) @@ -139,7 +139,7 @@ function eupd_wrapper(T, n::Integer, sym::Bool, cmplx::Bool, bmat::String, p = sortperm(dmap(d[1:nev]), rev=true) return ritzvec ? (d[p], v[1:n, p],iparam[5],iparam[3],iparam[9],resid) : (d[p],iparam[5],iparam[3],iparam[9],resid) elseif sym - d = Array{T}(nev) + d = Vector{T}(nev) sigmar = ones(T, 1)*sigma seupd(ritzvec, howmny, select, d, v, ldv, sigmar, bmat, n, which, nev, TOL, resid, ncv, v, ldv, @@ -151,20 +151,20 @@ function eupd_wrapper(T, n::Integer, sym::Bool, cmplx::Bool, bmat::String, p = sortperm(dmap(d), rev=true) return ritzvec ? (d[p], v[1:n, p],iparam[5],iparam[3],iparam[9],resid) : (d,iparam[5],iparam[3],iparam[9],resid) else - dr = Array{T}(nev+1) - di = Array{T}(nev+1) + dr = Vector{T}(nev+1) + di = Vector{T}(nev+1) fill!(dr,NaN) fill!(di,NaN) sigmar = ones(T, 1)*real(sigma) sigmai = ones(T, 1)*imag(sigma) - workev = Array{T}(3*ncv) + workev = Vector{T}(3*ncv) neupd(ritzvec, howmny, select, dr, di, v, ldv, sigmar, sigmai, workev, bmat, n, which, nev, TOL, resid, ncv, v, ldv, iparam, ipntr, workd, workl, lworkl, info) if info[1] != 0 throw(ARPACKException(info[1])) end - evec = complex.(Array{T}(n, nev+1), Array{T}(n, nev+1)) + evec = complex.(Matrix{T}(n, nev+1), Matrix{T}(n, nev+1)) j = 1 while j <= nev From 525f99682084e9012a4bb7b64d48e2dba082ab26 Mon Sep 17 00:00:00 2001 From: Mus M Date: Sat, 22 Apr 2017 14:15:31 -0400 Subject: [PATCH 0514/1534] Braces for short form `where` in constructors.md (#21478) --- doc/src/manual/constructors.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/src/manual/constructors.md b/doc/src/manual/constructors.md index 79290ff5f7289..e5d4023799f44 100644 --- a/doc/src/manual/constructors.md +++ b/doc/src/manual/constructors.md @@ -330,10 +330,10 @@ This automatic provision of constructors is equivalent to the following explicit julia> struct Point{T<:Real} x::T y::T - Point{T}(x,y) where T<:Real = new(x,y) + Point{T}(x,y) where {T<:Real} = new(x,y) end -julia> Point(x::T, y::T) where T<:Real = Point{T}(x,y); +julia> Point(x::T, y::T) where {T<:Real} = Point{T}(x,y); ``` Notice that each definition looks like the form of constructor call that it handles. @@ -425,7 +425,7 @@ julia> struct OurRational{T<:Integer} <: Real end end -julia> OurRational(n::T, d::T) where T<:Integer = OurRational{T}(n,d) +julia> OurRational(n::T, d::T) where {T<:Integer} = OurRational{T}(n,d) OurRational julia> OurRational(n::Integer, d::Integer) = OurRational(promote(n,d)...) From 56d976a62c1a6b9a4dd630b6d145036ef1f4accd Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Sat, 22 Apr 2017 11:30:24 -0700 Subject: [PATCH 0515/1534] Stylistic updates to the devdocs for consistency (#21464) --- doc/src/devdocs/ast.md | 2 +- doc/src/devdocs/cartesian.md | 2 +- doc/src/devdocs/compiler.md | 8 +- doc/src/devdocs/debuggingtips.md | 4 +- doc/src/devdocs/eval.md | 30 ++--- doc/src/devdocs/functions.md | 16 +-- doc/src/devdocs/init.md | 210 +++++++++++++++---------------- doc/src/devdocs/object.md | 45 ++++--- doc/src/devdocs/offset-arrays.md | 6 +- doc/src/devdocs/reflection.md | 2 +- doc/src/devdocs/stdio.md | 42 +++---- doc/src/devdocs/types.md | 2 +- 12 files changed, 182 insertions(+), 187 deletions(-) diff --git a/doc/src/devdocs/ast.md b/doc/src/devdocs/ast.md index f5f0c39770096..62006cf4d62d3 100644 --- a/doc/src/devdocs/ast.md +++ b/doc/src/devdocs/ast.md @@ -507,7 +507,7 @@ parses as: Type definition: ```julia -type Foo{T<:S} +mutable struct Foo{T<:S} x::T end ``` diff --git a/doc/src/devdocs/cartesian.md b/doc/src/devdocs/cartesian.md index c63df3f188283..01ca7f265e2a0 100644 --- a/doc/src/devdocs/cartesian.md +++ b/doc/src/devdocs/cartesian.md @@ -69,7 +69,7 @@ Starting in Julia 0.4-pre, the recommended approach is to use a `@generated func an example: ```julia -@generated function mysum{T,N}(A::Array{T,N}) +@generated function mysum(A::Array{T,N}) where {T,N} quote s = zero(T) @nloops $N i A begin diff --git a/doc/src/devdocs/compiler.md b/doc/src/devdocs/compiler.md index d9dd69e5e3b41..0749eafd81bd3 100644 --- a/doc/src/devdocs/compiler.md +++ b/doc/src/devdocs/compiler.md @@ -1,9 +1,5 @@ # High-level Overview of the Native-Code Generation Process - - - - ## Representation of Pointers When emitting code to an object file, pointers will be emitted as relocations. @@ -24,10 +20,10 @@ Function pointers are handled similarly. They are stored as values in a large `fvals` table. Like globals, this allows the deserializer to reference them by index. -Note that extern functions are handled separately, +Note that `extern` functions are handled separately, with names, via the usual symbol resolution mechanism in the linker. -Note too that ccall functions are also handled separately, +Note too that `ccall` functions are also handled separately, via a manual GOT and Procedure Linkage Table (PLT). diff --git a/doc/src/devdocs/debuggingtips.md b/doc/src/devdocs/debuggingtips.md index 2cdddf58b6bc3..7fc16b99f2148 100644 --- a/doc/src/devdocs/debuggingtips.md +++ b/doc/src/devdocs/debuggingtips.md @@ -234,9 +234,9 @@ process) ## Mozilla's Record and Replay Framework (rr) -Julia now works out of the box with [rr,](http://rr-project.org/) the lightweight recording and +Julia now works out of the box with [rr](http://rr-project.org/), the lightweight recording and deterministic debugging framework from Mozilla. This allows you to replay the trace of an execution deterministically. The replayed execution's address spaces, register contents, syscall data etc are exactly the same in every run. -A recent version of `rr` (3.1.0 or higher) is required. +A recent version of rr (3.1.0 or higher) is required. diff --git a/doc/src/devdocs/eval.md b/doc/src/devdocs/eval.md index 4ea9e8cbd2abc..9139a16220329 100644 --- a/doc/src/devdocs/eval.md +++ b/doc/src/devdocs/eval.md @@ -3,10 +3,10 @@ One of the hardest parts about learning how the Julia Language runs code is learning how all of the pieces work together to execute a block of code. -Each chunk of code typically makes a trip through many esoteric acronyms such as (in no particular -order), `flisp`, `AST`, `C++`, `LLVM`, `eval`, `typeinf`, `macroexpand`, `sysimg` (or `system image`), -`bootstrapping`, `compile`, `parse`, `execute`, `JIT`, `interpret`, `box`, `unbox`, `intrinsic function`, -`primitive function` before turning into the desired result (hopefully). +Each chunk of code typically makes a trip through many steps with potentially unfamiliar names, +such as (in no particular order): flisp, AST, C++, LLVM, `eval`, `typeinf`, `macroexpand`, sysimg +(or system image), bootstrapping, compile, parse, execute, JIT, interpret, box, unbox, intrinsic +function, and primitive function, before turning into the desired result (hopefully). !!! sidebar "Definitions" * REPL @@ -25,19 +25,19 @@ The 10,000 foot view of the whole process is as follows: 1. The user starts `julia`. 2. The C function `main()` from `ui/repl.c` gets called. This function processes the command line arguments, filling in the `jl_options` struct and setting the variable `ARGS`. It then initializes - Julia (by calling [julia_init in task.c](https://github.com/JuliaLang/julia/blob/master/src/task.c), + Julia (by calling [`julia_init` in task.c](https://github.com/JuliaLang/julia/blob/master/src/task.c), which may load a previously compiled [sysimg](@ref dev-sysimg)). Finally, it passes off control to Julia - by calling [Base._start()](https://github.com/JuliaLang/julia/blob/master/base/client.jl). + by calling [`Base._start()`](https://github.com/JuliaLang/julia/blob/master/base/client.jl). 3. When `_start()` takes over control, the subsequent sequence of commands depends on the command line arguments given. For example, if a filename was supplied, it will proceed to execute that file. Otherwise, it will start an interactive REPL. 4. Skipping the details about how the REPL interacts with the user, let's just say the program ends up with a block of code that it wants to run. -5. If the block of code to run is in a file, [jl_load(char *filename)](https://github.com/JuliaLang/julia/blob/master/src/toplevel.c) +5. If the block of code to run is in a file, [`jl_load(char *filename)`](https://github.com/JuliaLang/julia/blob/master/src/toplevel.c) gets invoked to load the file and [parse](@ref dev-parsing) it. Each fragment of code is then passed to `eval` to execute. 6. Each fragment of code (or AST), is handed off to [`eval()`](@ref) to turn into results. -7. [`eval()`](@ref) takes each code fragment and tries to run it in [jl_toplevel_eval_flex()](https://github.com/JuliaLang/julia/blob/master/src/toplevel.c). +7. [`eval()`](@ref) takes each code fragment and tries to run it in [`jl_toplevel_eval_flex()`](https://github.com/JuliaLang/julia/blob/master/src/toplevel.c). 8. `jl_toplevel_eval_flex()` decides whether the code is a "toplevel" action (such as `using` or `module`), which would be invalid inside a function. If so, it passes off the code to the toplevel interpreter. @@ -45,16 +45,16 @@ The 10,000 foot view of the whole process is as follows: the AST to make it simpler to execute. 10. `jl_toplevel_eval_flex()` then uses some simple heuristics to decide whether to JIT compiler the AST or to interpret it directly. -11. The bulk of the work to interpret code is handled by [eval in interpreter.c](https://github.com/JuliaLang/julia/blob/master/src/interpreter.c). +11. The bulk of the work to interpret code is handled by [`eval` in interpreter.c](https://github.com/JuliaLang/julia/blob/master/src/interpreter.c). 12. If instead, the code is compiled, the bulk of the work is handled by `codegen.cpp`. Whenever a Julia function is called for the first time with a given set of argument types, [type inference](@ref dev-type-inference) will be run on that function. This information is used by the [codegen](@ref dev-codegen) step to generate faster code. 13. Eventually, the user quits the REPL, or the end of the program is reached, and the `_start()` method returns. -14. Just before exiting, `main()` calls [jl_atexit_hook(exit_code)](https://github.com/JuliaLang/julia/blob/master/src/init.c). +14. Just before exiting, `main()` calls [`jl_atexit_hook(exit_code)`](https://github.com/JuliaLang/julia/blob/master/src/init.c). This calls `Base._atexit()` (which calls any functions registered to [`atexit()`](@ref) inside - Julia). Then it calls [jl_gc_run_all_finalizers()](https://github.com/JuliaLang/julia/blob/master/src/gc.c). + Julia). Then it calls [`jl_gc_run_all_finalizers()`](https://github.com/JuliaLang/julia/blob/master/src/gc.c). Finally, it gracefully cleans up all `libuv` handles and waits for them to flush and close. ## [Parsing](@id dev-parsing) @@ -103,7 +103,7 @@ Type inference may also include other steps such as constant propagation and inl * C++ The programming language that LLVM is implemented in, which means that codegen is also implemented - in this language. The rest of Julia's library is implemented in C, in part because it's smaller + in this language. The rest of Julia's library is implemented in C, in part because its smaller feature set makes it more usable as a cross-language interface layer. * box @@ -135,7 +135,7 @@ Type inference may also include other steps such as constant propagation and inl Codegen is the process of turning a Julia AST into native machine code. -The JIT environment is initialized by an early call to [jl_init_codegen in codegen.cpp](https://github.com/JuliaLang/julia/blob/master/src/codegen.cpp). +The JIT environment is initialized by an early call to [`jl_init_codegen` in codegen.cpp](https://github.com/JuliaLang/julia/blob/master/src/codegen.cpp). On demand, a Julia method is converted into a native function by the function `emit_function(jl_method_instance_t*)`. (note, when using the MCJIT (in LLVM v3.4+), each function must be JIT into a new module.) This @@ -161,7 +161,7 @@ Other parts of codegen are handled by various helper files: !!! sidebar "Bootstrapping" The process of creating a new system image is called "bootstrapping". - The etymology of this word comes from the phrase "pulling one's self up by the bootstraps", and + The etymology of this word comes from the phrase "pulling oneself up by the bootstraps", and refers to the idea of starting from a very limited set of available functions and definitions and ending with the creation of a full-featured environment. @@ -172,7 +172,7 @@ with Julia is one such system image, generated by executing the file [sysimg.jl] and serializing the resulting environment (including Types, Functions, Modules, and all other defined values) into a file. Therefore, it contains a frozen version of the `Main`, `Core`, and `Base` modules (and whatever else was in the environment at the end of bootstrapping). This serializer/deserializer -is implemented by [jl_save_system_image/jl_restore_system_image in dump.c](https://github.com/JuliaLang/julia/blob/master/src/dump.c). +is implemented by [`jl_save_system_image`/`jl_restore_system_image` in dump.c](https://github.com/JuliaLang/julia/blob/master/src/dump.c). If there is no sysimg file (`jl_options.image_file == NULL`), this also implies that `--build` was given on the command line, so the final result should be a new sysimg file. During Julia initialization, diff --git a/doc/src/devdocs/functions.md b/doc/src/devdocs/functions.md index 77c3cefbe3802..5e88f33d0d11b 100644 --- a/doc/src/devdocs/functions.md +++ b/doc/src/devdocs/functions.md @@ -33,14 +33,14 @@ of the argument structure. For example, the following function for performing a call accepts just an `args` pointer, so the first element of the args array will be the function to call: -``` +```c jl_value_t *jl_apply(jl_value_t **args, uint32_t nargs) ``` This entry point for the same functionality accepts the function separately, so the `args` array does not contain the function: -``` +```c jl_value_t *jl_call(jl_function_t *f, jl_value_t **args, int32_t nargs); ``` @@ -110,7 +110,7 @@ a method table via special arrangement. The "builtin" functions, defined in the `Core` module, are: ``` -is typeof sizeof issubtype isa typeassert throw tuple getfield setfield! fieldtype +=== typeof sizeof issubtype isa typeassert throw tuple getfield setfield! fieldtype nfields isdefined arrayref arrayset arraysize applicable invoke apply_type _apply _expr svec ``` @@ -119,7 +119,7 @@ These are all singleton objects whose types are subtypes of `Builtin`, which is `Function`. Their purpose is to expose entry points in the run time that use the "jlcall" calling convention: -``` +```c jl_value_t *(jl_value_t*, jl_value_t**, uint32_t) ``` @@ -152,7 +152,7 @@ actually produces *three* method definitions. The first is a function that accep (including keywords) as positional arguments, and includes the code for the method body. It has an auto-generated name: -``` +```julia function #circle#1(color, fill::Bool, options, circle, center, radius) # draw end @@ -268,11 +268,11 @@ filtering definitions from "replaced modules" out of method tables and caches be system image. A "replaced module" is one that satisfies the condition `m != jl_get_global(m->parent, m->name)` -- in other words, some newer module has taken its name and place. -Another type inference worst case was triggered by the following code from the QuadGK.jl package, +Another type inference worst case was triggered by the following code from the [QuadGK.jl package](https://github.com/JuliaMath/QuadGK.jl), formerly part of Base: ```julia -function do_quadgk{Tw}(f, s, n, ::Type{Tw}, abstol, reltol, maxevals, nrm) +function do_quadgk(f, s, n, ::Type{Tw}, abstol, reltol, maxevals, nrm) where Tw if eltype(s) <: Real # check for infinite or semi-infinite intervals s1 = s[1]; s2 = s[end]; inf1 = isinf(s1); inf2 = isinf(s2) if inf1 || inf2 @@ -300,5 +300,5 @@ function do_quadgk{Tw}(f, s, n, ::Type{Tw}, abstol, reltol, maxevals, nrm) This code has a 3-way tail recursion, where each call wraps the current function argument `f` in a different new closure. Inference must consider 3^n (where n is the call depth) possible signatures. -This blows up way too quickly, so logic was added to typeinf_uncached to immediately widen any +This blows up way too quickly, so logic was added to `typeinf_uncached` to immediately widen any argument that is a subtype of `Function` and that grows in depth down the stack. diff --git a/doc/src/devdocs/init.md b/doc/src/devdocs/init.md index 83d0b8e0f3cea..d1ea013cd6ad5 100644 --- a/doc/src/devdocs/init.md +++ b/doc/src/devdocs/init.md @@ -4,42 +4,42 @@ How does the Julia runtime execute `julia -e 'println("Hello World!")'` ? ## main() -Execution starts at [main() in julia/ui/repl.c](https://github.com/JuliaLang/julia/blob/master/ui/repl.c). +Execution starts at [`main()` in ui/repl.c](https://github.com/JuliaLang/julia/blob/master/ui/repl.c). -main() calls [libsupport_init()](https://github.com/JuliaLang/julia/blob/master/src/support/libsupportinit.c) -to set the C library locale and to initialise the "ios" library (see [ios_init_stdstreams()](https://github.com/JuliaLang/julia/blob/master/src/support/ios.c) +`main()` calls [`libsupport_init()`](https://github.com/JuliaLang/julia/blob/master/src/support/libsupportinit.c) +to set the C library locale and to initialize the "ios" library (see [`ios_init_stdstreams()`](https://github.com/JuliaLang/julia/blob/master/src/support/ios.c) and [Legacy ios.c library](@ref)). -Next [parse_opts()](https://github.com/JuliaLang/julia/blob/master/ui/repl.c) is called to process +Next [`parse_opts()`](https://github.com/JuliaLang/julia/blob/master/ui/repl.c) is called to process command line options. Note that `parse_opts()` only deals with options that affect code generation -or early initialisation. Other options are handled later by [process_options() in base/client.jl](https://github.com/JuliaLang/julia/blob/master/base/client.jl). +or early initialization. Other options are handled later by [`process_options()` in base/client.jl](https://github.com/JuliaLang/julia/blob/master/base/client.jl). -`parse_opts()` stores command line options in the [global jl_options struct](https://github.com/JuliaLang/julia/blob/master/src/julia.h). +`parse_opts()` stores command line options in the [global `jl_options` struct](https://github.com/JuliaLang/julia/blob/master/src/julia.h). ## julia_init() -[julia_init() in task.c](https://github.com/JuliaLang/julia/blob/master/src/task.c) is called -by main() and calls [_julia_init() in init.c](https://github.com/JuliaLang/julia/blob/master/src/init.c). +[`julia_init()` in task.c](https://github.com/JuliaLang/julia/blob/master/src/task.c) is called +by `main()` and calls [`_julia_init()` in init.c](https://github.com/JuliaLang/julia/blob/master/src/init.c). `_julia_init()` begins by calling `libsupport_init()` again (it does nothing the second time). -[restore_signals()](https://github.com/JuliaLang/julia/blob/master/src/signals-unix.c) is called +[`restore_signals()`](https://github.com/JuliaLang/julia/blob/master/src/signals-unix.c) is called to zero the signal handler mask. -[jl_resolve_sysimg_location()](https://github.com/JuliaLang/julia/blob/master/src/init.c) searches +[`jl_resolve_sysimg_location()`](https://github.com/JuliaLang/julia/blob/master/src/init.c) searches configured paths for the base system image. See [Building the Julia system image](@ref). -[jl_gc_init()](https://github.com/JuliaLang/julia/blob/master/src/gc.c) sets up allocation pools -and lists for: weak refs, preserved values and finalization. +[`jl_gc_init()`](https://github.com/JuliaLang/julia/blob/master/src/gc.c) sets up allocation pools +and lists for weak refs, preserved values and finalization. -[jl_init_frontend()](https://github.com/JuliaLang/julia/blob/master/src/ast.c) loads and initialises -a pre-compiled femtolisp image containing the scanner/parser; +[`jl_init_frontend()`](https://github.com/JuliaLang/julia/blob/master/src/ast.c) loads and initializes +a pre-compiled femtolisp image containing the scanner/parser. -[jl_init_types()](https://github.com/JuliaLang/julia/blob/master/src/jltypes.c) creates `jl_datatype_t` +[`jl_init_types()`](https://github.com/JuliaLang/julia/blob/master/src/jltypes.c) creates `jl_datatype_t` type description objects for the [built-in types defined in julia.h](https://github.com/JuliaLang/julia/blob/master/src/julia.h). e.g. -```julia +```c jl_any_type = jl_new_abstracttype(jl_symbol("Any"), NULL, jl_null); jl_any_type->super = jl_any_type; @@ -49,14 +49,14 @@ jl_int32_type = jl_new_bitstype(jl_symbol("Int32"), jl_any_type, jl_null, 32); ``` -[jl_init_tasks()](https://github.com/JuliaLang/julia/blob/master/src/task.c) creates the `jl_datatype_t* jl_task_type` -object; initialises the global `jl_root_task` struct; and sets `jl_current_task` to the root task. +[`jl_init_tasks()`](https://github.com/JuliaLang/julia/blob/master/src/task.c) creates the `jl_datatype_t* jl_task_type` +object; initializes the global `jl_root_task` struct; and sets `jl_current_task` to the root task. -[jl_init_codegen()](https://github.com/JuliaLang/julia/blob/master/src/codegen.cpp) initialises +[`jl_init_codegen()`](https://github.com/JuliaLang/julia/blob/master/src/codegen.cpp) initializes the [LLVM library](http://llvm.org). -[jl_init_serializer()](https://github.com/JuliaLang/julia/blob/master/src/dump.c) initialises -8-bit serialisation tags for 256 frequently used `jl_value_t` values. The serialisation mechanism +[`jl_init_serializer()`](https://github.com/JuliaLang/julia/blob/master/src/dump.c) initializes +8-bit serialization tags for 256 frequently used `jl_value_t` values. The serialization mechanism uses these tags as shorthand (in lieu of storing whole objects) to save storage space. If there is no sysimg file (`!jl_options.image_file`) then the `Core` and `Main` modules are @@ -64,168 +64,168 @@ created and `boot.jl` is evaluated: `jl_core_module = jl_new_module(jl_symbol("Core"))` creates the Julia `Core` module. -[jl_init_intrinsic_functions()](https://github.com/JuliaLang/julia/blob/master/src/intrinsics.cpp) -creates a new Julia module "Intrinsics" containing constant jl_intrinsic_type symbols. These define +[`jl_init_intrinsic_functions()`](https://github.com/JuliaLang/julia/blob/master/src/intrinsics.cpp) +creates a new Julia module `Intrinsics` containing constant `jl_intrinsic_type` symbols. These define an integer code for each [intrinsic function](https://github.com/JuliaLang/julia/blob/master/src/intrinsics.cpp). -[emit_intrinsic()](https://github.com/JuliaLang/julia/blob/master/src/intrinsics.cpp) translates +[`emit_intrinsic()`](https://github.com/JuliaLang/julia/blob/master/src/intrinsics.cpp) translates these symbols into LLVM instructions during code generation. -[jl_init_primitives()](https://github.com/JuliaLang/julia/blob/master/src/builtins.c) hooks C +[`jl_init_primitives()`](https://github.com/JuliaLang/julia/blob/master/src/builtins.c) hooks C functions up to Julia function symbols. e.g. the symbol `Base.is()` is bound to C function pointer `jl_f_is()` by calling `add_builtin_func("eval", jl_f_top_eval)`. -[jl_new_main_module()](https://github.com/JuliaLang/julia/blob/master/src/toplevel.c) creates +[`jl_new_main_module()`](https://github.com/JuliaLang/julia/blob/master/src/toplevel.c) creates the global "Main" module and sets `jl_current_task->current_module = jl_main_module`. -Note: _julia_init() [then sets](https://github.com/JuliaLang/julia/blob/master/src/init.c)`jl_root_task->current_module = jl_core_module`. -`jl_root_task` is an alias of `jl_current_task` at this point, so the current_module set by `jl_new_main_module()` +Note: `_julia_init()` [then sets](https://github.com/JuliaLang/julia/blob/master/src/init.c) `jl_root_task->current_module = jl_core_module`. +`jl_root_task` is an alias of `jl_current_task` at this point, so the `current_module` set by `jl_new_main_module()` above is overwritten. -[jl_load("boot.jl", sizeof("boot.jl"))](https://github.com/JuliaLang/julia/blob/master/src/init.c) -calls [jl_parse_eval_all](https://github.com/JuliaLang/julia/blob/master/src/ast.c) which repeatedly -calls [jl_toplevel_eval_flex()](https://github.com/JuliaLang/julia/blob/master/src/toplevel.c) -to execute [boot.jl](https://github.com/JuliaLang/julia/blob/master/base/boot.jl). TODO – drill -down into eval? +[`jl_load("boot.jl", sizeof("boot.jl"))`](https://github.com/JuliaLang/julia/blob/master/src/init.c) +calls [`jl_parse_eval_all`](https://github.com/JuliaLang/julia/blob/master/src/ast.c) which repeatedly +calls [`jl_toplevel_eval_flex()`](https://github.com/JuliaLang/julia/blob/master/src/toplevel.c) +to execute [boot.jl](https://github.com/JuliaLang/julia/blob/master/base/boot.jl). -[jl_get_builtin_hooks()](https://github.com/JuliaLang/julia/blob/master/src/init.c) initialises -global C pointers to Julia globals defined in `boot.jl`. +[`jl_get_builtin_hooks()`](https://github.com/JuliaLang/julia/blob/master/src/init.c) initializes +global C pointers to Julia globals defined in boot.jl. -[jl_init_box_caches()](https://github.com/JuliaLang/julia/blob/master/src/alloc.c) pre-allocates +[`jl_init_box_caches()`](https://github.com/JuliaLang/julia/blob/master/src/datatype.c) pre-allocates global boxed integer value objects for values up to 1024. This speeds up allocation of boxed ints later on. e.g.: -``` +```c jl_value_t *jl_box_uint8(uint32_t x) { return boxed_uint8_cache[(uint8_t)x]; } ``` -[_julia_init() iterates](https://github.com/JuliaLang/julia/blob/master/src/init.c) over the +[`_julia_init()` iterates](https://github.com/JuliaLang/julia/blob/master/src/init.c) over the `jl_core_module->bindings.table` looking for `jl_datatype_t` values and sets the type name's module prefix to `jl_core_module`. -[jl_add_standard_imports(jl_main_module)](https://github.com/JuliaLang/julia/blob/master/src/toplevel.c) +[`jl_add_standard_imports(jl_main_module)`](https://github.com/JuliaLang/julia/blob/master/src/toplevel.c) does "using Base" in the "Main" module. Note: `_julia_init()` now reverts to `jl_root_task->current_module = jl_main_module` as it was before being set to `jl_core_module` above. -Platform specific signal handlers are initialised for `SIGSEGV` (OSX, Linux), and `SIGFPE` (Windows). +Platform specific signal handlers are initialized for `SIGSEGV` (OSX, Linux), and `SIGFPE` (Windows). Other signals (`SIGINFO, SIGBUS, SIGILL, SIGTERM, SIGABRT, SIGQUIT, SIGSYS` and `SIGPIPE`) are -hooked up to [sigdie_handler()](https://github.com/JuliaLang/julia/blob/master/src/signals-unix.c) +hooked up to [`sigdie_handler()`](https://github.com/JuliaLang/julia/blob/master/src/signals-unix.c) which prints a backtrace. -[jl_init_restored_modules()](https://github.com/JuliaLang/julia/blob/master/src/dump.c) calls -[jl_module_run_initializer()](https://github.com/JuliaLang/julia/blob/master/src/module.c) for -each deserialised module to run the `__init__()` function. +[`jl_init_restored_modules()`](https://github.com/JuliaLang/julia/blob/master/src/dump.c) calls +[`jl_module_run_initializer()`](https://github.com/JuliaLang/julia/blob/master/src/module.c) for +each deserialized module to run the `__init__()` function. -Finally [sigint_handler()](https://github.com/JuliaLang/julia/blob/master/src/signals-unix.c) +Finally [`sigint_handler()`](https://github.com/JuliaLang/julia/blob/master/src/signals-unix.c) is hooked up to `SIGINT` and calls `jl_throw(jl_interrupt_exception)`. -`_julia_init()` then returns [back to main() in julia/ui/repl.c](https://github.com/JuliaLang/julia/blob/master/ui/repl.c) -and main() calls `true_main(argc, (char**)argv)`. +`_julia_init()` then returns [back to `main()` in julia/ui/repl.c](https://github.com/JuliaLang/julia/blob/master/ui/repl.c) +and `main()` calls `true_main(argc, (char**)argv)`. !!! sidebar "sysimg" If there is a sysimg file, it contains a pre-cooked image of the `Core` and `Main` modules (and - whatever else is created by `boot.jl`). See [Building the Julia system image](@ref). + whatever else is created by boot.jl). See [Building the Julia system image](@ref). - [jl_restore_system_image()](https://github.com/JuliaLang/julia/blob/master/src/dump.c) de-serialises - the saved sysimg into the current Julia runtime environment and initialisation continues after + [`jl_restore_system_image()`](https://github.com/JuliaLang/julia/blob/master/src/dump.c) deserializes + the saved sysimg into the current Julia runtime environment and initialization continues after `jl_init_box_caches()` below... - Note: [jl_restore_system_image() (and dump.c in general)](https://github.com/JuliaLang/julia/blob/master/src/dump.c) + Note: [`jl_restore_system_image()` (and dump.c in general)](https://github.com/JuliaLang/julia/blob/master/src/dump.c) uses the [Legacy ios.c library](@ref). ## true_main() -[true_main()](https://github.com/JuliaLang/julia/blob/master/ui/repl.c) loads the contents of +[`true_main()`](https://github.com/JuliaLang/julia/blob/master/ui/repl.c) loads the contents of `argv[]` into [`Base.ARGS`](@ref). -If a .jl "program" file was supplied on the command line, then [exec_program()](https://github.com/JuliaLang/julia/blob/master/ui/repl.c) -calls [jl_load(program,len)](https://github.com/JuliaLang/julia/blob/master/src/toplevel.c) which -calls [jl_parse_eval_all](https://github.com/JuliaLang/julia/blob/master/src/ast.c) which repeatedly -calls [jl_toplevel_eval_flex()](https://github.com/JuliaLang/julia/blob/master/src/toplevel.c) +If a .jl "program" file was supplied on the command line, then [`exec_program()`](https://github.com/JuliaLang/julia/blob/master/ui/repl.c) +calls [`jl_load(program,len)`](https://github.com/JuliaLang/julia/blob/master/src/toplevel.c) which +calls [`jl_parse_eval_all`](https://github.com/JuliaLang/julia/blob/master/src/ast.c) which repeatedly +calls [`jl_toplevel_eval_flex()`](https://github.com/JuliaLang/julia/blob/master/src/toplevel.c) to execute the program. -However, in our example (`julia -e 'println("Hello World!")'`), [jl_get_global(jl_base_module, jl_symbol("_start"))](https://github.com/JuliaLang/julia/blob/master/src/module.c) -looks up [Base._start](https://github.com/JuliaLang/julia/blob/master/base/client.jl) and [jl_apply()](https://github.com/JuliaLang/julia/blob/master/src/julia.h) +However, in our example (`julia -e 'println("Hello World!")'`), [`jl_get_global(jl_base_module, jl_symbol("_start"))`](https://github.com/JuliaLang/julia/blob/master/src/module.c) +looks up [`Base._start`](https://github.com/JuliaLang/julia/blob/master/base/client.jl) and [`jl_apply()`](https://github.com/JuliaLang/julia/blob/master/src/julia.h) executes it. ## Base._start -[Base._start](https://github.com/JuliaLang/julia/blob/master/base/client.jl) calls [Base.process_options](https://github.com/JuliaLang/julia/blob/master/base/client.jl) -which calls [jl_parse_input_line("println("Hello World!")")](https://github.com/JuliaLang/julia/blob/master/src/ast.c) +[`Base._start`](https://github.com/JuliaLang/julia/blob/master/base/client.jl) calls [`Base.process_options`](https://github.com/JuliaLang/julia/blob/master/base/client.jl) +which calls [`jl_parse_input_line("println("Hello World!")")`](https://github.com/JuliaLang/julia/blob/master/src/ast.c) to create an expression object and [`Base.eval()`](@ref eval) to execute it. ## Base.eval -[`Base.eval()`](@ref eval) was [mapped to jl_f_top_eval](https://github.com/JuliaLang/julia/blob/master/src/builtins.c) +[`Base.eval()`](@ref eval) was [mapped to `jl_f_top_eval`](https://github.com/JuliaLang/julia/blob/master/src/builtins.c) by `jl_init_primitives()`. -[jl_f_top_eval()](https://github.com/JuliaLang/julia/blob/master/src/builtins.c) calls [jl_toplevel_eval_in(jl_main_module, ex)](https://github.com/JuliaLang/julia/blob/master/src/builtins.c), -where "ex" is the parsed expression `println("Hello World!")`. +[`jl_f_top_eval()`](https://github.com/JuliaLang/julia/blob/master/src/builtins.c) calls [`jl_toplevel_eval_in(jl_main_module, ex)`](https://github.com/JuliaLang/julia/blob/master/src/builtins.c), +where `ex` is the parsed expression `println("Hello World!")`. -[jl_toplevel_eval_in()](https://github.com/JuliaLang/julia/blob/master/src/builtins.c) calls -[jl_toplevel_eval_flex()](https://github.com/JuliaLang/julia/blob/master/src/toplevel.c) which -calls [eval() in interpreter.c](https://github.com/JuliaLang/julia/blob/master/src/interpreter.c). +[`jl_toplevel_eval_in()`](https://github.com/JuliaLang/julia/blob/master/src/builtins.c) calls +[`jl_toplevel_eval_flex()`](https://github.com/JuliaLang/julia/blob/master/src/toplevel.c) which +calls [`eval()` in interpreter.c](https://github.com/JuliaLang/julia/blob/master/src/interpreter.c). The stack dump below shows how the interpreter works its way through various methods of [`Base.println()`](@ref) -and [`Base.print()`](@ref) before arriving at [write{T}(s::IO, a::Array{T})](https://github.com/JuliaLang/julia/blob/master/base/stream.jl) +and [`Base.print()`](@ref) before arriving at [`write(s::IO, a::Array{T}) where T`](https://github.com/JuliaLang/julia/blob/master/base/stream.jl) which does `ccall(jl_uv_write())`. -[jl_uv_write()](https://github.com/JuliaLang/julia/blob/master/src/jl_uv.c) calls `uv_write()` +[`jl_uv_write()`](https://github.com/JuliaLang/julia/blob/master/src/jl_uv.c) calls `uv_write()` to write "Hello World!" to `JL_STDOUT`. See [Libuv wrappers for stdio](@ref).: ``` Hello World! ``` -| Stack frame | Source code | Notes | -|:---------------------------- |:------------- |:------------------------------------------------- | -| jl_uv_write() | jl_uv.c | called though [`ccall`](@ref) | -| julia_write_282942 | stream.jl | function write!{T}(s::IO, a::Array{T}) | -| julia_print_284639 | ascii.jl | print(io::IO, s::String) = (write(io, s);nothing) | -| jlcall_print_284639 |   |   | -| jl_apply() | julia.h |   | -| jl_trampoline() | builtins.c |   | -| jl_apply() | julia.h |   | -| jl_apply_generic() | gf.c | Base.print(Base.TTY, String) | -| jl_apply() | julia.h |   | -| jl_trampoline() | builtins.c |   | -| jl_apply() | julia.h |   | -| jl_apply_generic() | gf.c | Base.print(Base.TTY, String, Char, Char...) | -| jl_apply() | julia.h |   | -| jl_f_apply() | builtins.c |   | -| jl_apply() | julia.h |   | -| jl_trampoline() | builtins.c |   | -| jl_apply() | julia.h |   | -| jl_apply_generic() | gf.c | Base.println(Base.TTY, String, String...) | -| jl_apply() | julia.h |   | -| jl_trampoline() | builtins.c |   | -| jl_apply() | julia.h |   | -| jl_apply_generic() | gf.c | Base.println(String,) | -| jl_apply() | julia.h |   | -| do_call() | interpreter.c |   | -| eval() | interpreter.c |   | -| jl_interpret_toplevel_expr() | interpreter.c |   | -| jl_toplevel_eval_flex() | toplevel.c |   | -| jl_toplevel_eval() | toplevel.c |   | -| jl_toplevel_eval_in() | builtins.c |   | -| jl_f_top_eval() | builtins.c |   | +| Stack frame | Source code | Notes | +|:------------------------------ |:------------- |:---------------------------------------------------- | +| `jl_uv_write()` | jl_uv.c | called though [`ccall`](@ref) | +| `julia_write_282942` | stream.jl | function `write!(s::IO, a::Array{T}) where T` | +| `julia_print_284639` | ascii.jl | `print(io::IO, s::String) = (write(io, s); nothing)` | +| `jlcall_print_284639` |   |   | +| `jl_apply()` | julia.h |   | +| `jl_trampoline()` | builtins.c |   | +| `jl_apply()` | julia.h |   | +| `jl_apply_generic()` | gf.c | `Base.print(Base.TTY, String)` | +| `jl_apply()` | julia.h |   | +| `jl_trampoline()` | builtins.c |   | +| `jl_apply()` | julia.h |   | +| `jl_apply_generic()` | gf.c | `Base.print(Base.TTY, String, Char, Char...)` | +| `jl_apply()` | julia.h |   | +| `jl_f_apply()` | builtins.c |   | +| `jl_apply()` | julia.h |   | +| `jl_trampoline()` | builtins.c |   | +| `jl_apply()` | julia.h |   | +| `jl_apply_generic()` | gf.c | `Base.println(Base.TTY, String, String...)` | +| `jl_apply()` | julia.h |   | +| `jl_trampoline()` | builtins.c |   | +| `jl_apply()` | julia.h |   | +| `jl_apply_generic()` | gf.c | `Base.println(String,)` | +| `jl_apply()` | julia.h |   | +| `do_call()` | interpreter.c |   | +| `eval()` | interpreter.c |   | +| `jl_interpret_toplevel_expr()` | interpreter.c |   | +| `jl_toplevel_eval_flex()` | toplevel.c |   | +| `jl_toplevel_eval()` | toplevel.c |   | +| `jl_toplevel_eval_in()` | builtins.c |   | +| `jl_f_top_eval()` | builtins.c |   | Since our example has just one function call, which has done its job of printing "Hello World!", the stack now rapidly unwinds back to `main()`. ## jl_atexit_hook() -`main()` calls [jl_atexit_hook()](https://github.com/JuliaLang/julia/blob/master/src/init.c). -This calls _atexit for each module, then calls [jl_gc_run_all_finalizers()](https://github.com/JuliaLang/julia/blob/master/src/gc.c) +`main()` calls [`jl_atexit_hook()`](https://github.com/JuliaLang/julia/blob/master/src/init.c). +This calls `_atexit` for each module, then calls [`jl_gc_run_all_finalizers()`](https://github.com/JuliaLang/julia/blob/master/src/gc.c) and cleans up libuv handles. ## julia_save() -Finally, `main()` calls [julia_save()](https://github.com/JuliaLang/julia/blob/master/src/init.c), -which if requested on the command line, saves the runtime state to a new system image. See [jl_compile_all()](https://github.com/JuliaLang/julia/blob/master/src/gf.c) -and [jl_save_system_image()](https://github.com/JuliaLang/julia/blob/master/src/dump.c). +Finally, `main()` calls [`julia_save()`](https://github.com/JuliaLang/julia/blob/master/src/init.c), +which if requested on the command line, saves the runtime state to a new system image. See [`jl_compile_all()`](https://github.com/JuliaLang/julia/blob/master/src/gf.c) +and [`jl_save_system_image()`](https://github.com/JuliaLang/julia/blob/master/src/dump.c). diff --git a/doc/src/devdocs/object.md b/doc/src/devdocs/object.md index 2b18c1f80d239..da0f3e3cfcad3 100644 --- a/doc/src/devdocs/object.md +++ b/doc/src/devdocs/object.md @@ -6,14 +6,14 @@ The `jl_value_t` struct is the name for a block of memory owned by the Julia Gar representing the data associated with a Julia object in memory. Absent any type information, it is simply an opaque pointer: -``` +```c typedef struct jl_value_t* jl_pvalue_t; ``` Each `jl_value_t` struct is contained in a `jl_typetag_t` struct that contains metadata information about the Julia object, such as its type and garbage collector (gc) reachability: -``` +```c typedef struct { opaque metadata; jl_value_t value; @@ -23,14 +23,14 @@ typedef struct { The type of any Julia object is an instance of a leaf `jl_datatype_t` object. The `jl_typeof()` function can be used to query for it: -```julia +```c jl_value_t *jl_typeof(jl_value_t *v); ``` The layout of the object depends on its type. Reflection methods can be used to inspect that layout. A field can be accessed by calling one of the get-field methods: -``` +```c jl_value_t *jl_get_nth_field_checked(jl_value_t *v, size_t i); jl_value_t *jl_get_field(jl_value_t *o, char *fld); ``` @@ -38,17 +38,17 @@ jl_value_t *jl_get_field(jl_value_t *o, char *fld); If the field types are known, a priori, to be all pointers, the values can also be extracted directly as an array access: -```julia +```c jl_value_t *v = value->fieldptr[n]; ``` As an example, a "boxed" `uint16_t` is stored as follows: -``` +```c struct { opaque metadata; struct { - uint16_t data; -- 2 bytes + uint16_t data; // -- 2 bytes } jl_value_t; }; ``` @@ -58,10 +58,10 @@ data portion, not the metadata at the top of the struct. A value may be stored "unboxed" in many circumstances (just the data, without the metadata, and possibly not even stored but just kept in registers), so it is unsafe to assume that the address -of a box is a unique identifier. The "egal" test (corresponding to the `is()` function in Julia), +of a box is a unique identifier. The "egal" test (corresponding to the `===` function in Julia), should instead be used to compare two unknown objects for equivalence: -``` +```c int jl_egal(jl_value_t *a, jl_value_t *b); ``` @@ -72,22 +72,21 @@ Note that modification of a `jl_value_t` pointer in memory is permitted only if mutable. Otherwise, modification of the value may corrupt the program and the result will be undefined. The mutability property of a value can be queried for with: -``` +```c int jl_is_mutable(jl_value_t *v); ``` If the object being stored is a `jl_value_t`, the Julia garbage collector must be notified also: -``` +```c void jl_gc_wb(jl_value_t *parent, jl_value_t *ptr); ``` However, the [Embedding Julia](@ref) section of the manual is also required reading at this point, - for covering other details of boxing and unboxing various types, and understanding the gc interactions. Mirror structs for some of the built-in types are [defined in julia.h](https://github.com/JuliaLang/julia/blob/master/src/julia.h). -The corresponding global `jl_datatype_t` objects are created by [jl_init_types in jltypes.c](https://github.com/JuliaLang/julia/blob/master/src/jltypes.c). +The corresponding global `jl_datatype_t` objects are created by [`jl_init_types` in jltypes.c](https://github.com/JuliaLang/julia/blob/master/src/jltypes.c). ## Garbage collector mark bits @@ -99,14 +98,14 @@ the [garbage collector implementation in gc.c](https://github.com/JuliaLang/juli Most new objects are allocated by `jl_new_structv()`: -``` +```c jl_value_t *jl_new_struct(jl_datatype_t *type, ...); jl_value_t *jl_new_structv(jl_datatype_t *type, jl_value_t **args, uint32_t na); ``` Although, [`isbits`](@ref) objects can be also constructed directly from memory: -```julia +```c jl_value_t *jl_new_bits(jl_value_t *bt, void *data) ``` @@ -114,7 +113,7 @@ And some objects have special constructors that must be used instead of the abov Types: -``` +```c jl_datatype_t *jl_apply_type(jl_datatype_t *tc, jl_tuple_t *params); jl_datatype_t *jl_apply_array_type(jl_datatype_t *type, size_t dim); jl_uniontype_t *jl_new_uniontype(jl_tuple_t *types); @@ -127,7 +126,7 @@ of the Julia system image. Tuples: -``` +```c jl_tuple_t *jl_tuple(size_t n, ...); jl_tuple_t *jl_tuplev(size_t n, jl_value_t **v); jl_tuple_t *jl_alloc_tuple(size_t n); @@ -137,7 +136,7 @@ The representation of tuples is highly unique in the Julia object representation some cases, a [`Base.tuple()`](@ref) object may be an array of pointers to the objects contained by the tuple equivalent to: -``` +```c typedef struct { size_t length; jl_value_t *data[length]; @@ -150,20 +149,20 @@ stored unboxed, or it may not stored at all (if it is not being used in a generi Symbols: -``` +```c jl_sym_t *jl_symbol(const char *str); ``` Functions and MethodInstance: -```julia +```c jl_function_t *jl_new_generic_function(jl_sym_t *name); jl_method_instance_t *jl_new_method_instance(jl_value_t *ast, jl_tuple_t *sparams); ``` Arrays: -``` +```c jl_array_t *jl_new_array(jl_value_t *atype, jl_tuple_t *dims); jl_array_t *jl_new_arrayv(jl_value_t *atype, ...); jl_array_t *jl_alloc_array_1d(jl_value_t *atype, size_t nr); @@ -179,7 +178,7 @@ list here reflects the more common usages, but a more complete list can be found Internal to Julia, storage is typically allocated by `newstruct()` (or `newobj()` for the special types): -``` +```c jl_value_t *newstruct(jl_value_t *type); jl_value_t *newobj(jl_value_t *type, size_t nfields); ``` @@ -187,7 +186,7 @@ jl_value_t *newobj(jl_value_t *type, size_t nfields); And at the lowest level, memory is getting allocated by a call to the garbage collector (in `gc.c`), then tagged with its type: -``` +```c jl_value_t *jl_gc_allocobj(size_t nbytes); void jl_set_typeof(jl_value_t *v, jl_datatype_t *type); ``` diff --git a/doc/src/devdocs/offset-arrays.md b/doc/src/devdocs/offset-arrays.md index b524fa4af1fe9..805c2fe40fa88 100644 --- a/doc/src/devdocs/offset-arrays.md +++ b/doc/src/devdocs/offset-arrays.md @@ -186,7 +186,7 @@ implement this). In some cases, the fallback definition for `indices(A, d)`: ```julia -indices{T,N}(A::AbstractArray{T,N}, d) = d <= N ? indices(A)[d] : OneTo(1) +indices(A::AbstractArray{T,N}, d) where {T,N} = d <= N ? indices(A)[d] : OneTo(1) ``` may not be what you want: you may need to specialize it to return something other than `OneTo(1)` @@ -195,8 +195,8 @@ to `indices(A, 1)` but which avoids checking (at runtime) whether `ndims(A) > 0` a performance optimization.) It is defined as: ```julia -indices1{T}(A::AbstractArray{T,0}) = OneTo(1) -indices1{T}(A::AbstractArray{T}) = indices(A)[1] +indices1(A::AbstractArray{T,0}) where {T} = OneTo(1) +indices1(A::AbstractArray) = indices(A)[1] ``` If the first of these (the zero-dimensional case) is problematic for your custom array type, be diff --git a/doc/src/devdocs/reflection.md b/doc/src/devdocs/reflection.md index 7902970f8bbde..244731b33f611 100644 --- a/doc/src/devdocs/reflection.md +++ b/doc/src/devdocs/reflection.md @@ -15,7 +15,7 @@ given the following type, `fieldnames(Point)` returns an arrays of [`Symbol`](@r the field names: ```julia -julia> type Point +julia> struct Point x::Int y end diff --git a/doc/src/devdocs/stdio.md b/doc/src/devdocs/stdio.md index 1ccfee543837c..636c1d06847ef 100644 --- a/doc/src/devdocs/stdio.md +++ b/doc/src/devdocs/stdio.md @@ -4,7 +4,7 @@ `julia.h` defines [libuv](http://docs.libuv.org) wrappers for the `stdio.h` streams: -```julia +```c uv_stream_t *JL_STDIN; uv_stream_t *JL_STDOUT; uv_stream_t *JL_STDERR; @@ -12,24 +12,24 @@ uv_stream_t *JL_STDERR; ... and corresponding output functions: -``` +```c int jl_printf(uv_stream_t *s, const char *format, ...); int jl_vprintf(uv_stream_t *s, const char *format, va_list args); ``` -These `printf` functions are used by `julia/{src,ui}/*.c` wherever stdio is needed to ensure that -output buffering is handled in a unified way. +These `printf` functions are used by the `.c` files in the `src/` and `ui/` directories wherever stdio is +needed to ensure that output buffering is handled in a unified way. -In special cases, like signal handlers, where the full `libuv` infrastructure is too heavy, `jl_safe_printf()` +In special cases, like signal handlers, where the full libuv infrastructure is too heavy, `jl_safe_printf()` can be used to [`write(2)`](@ref) directly to `STDERR_FILENO`: -``` +```c void jl_safe_printf(const char *str, ...); ``` ## Interface between JL_STD* and Julia code -[`Base.STDIN`](@ref), [`Base.STDOUT`](@ref) and [`Base.STDERR`](@ref) are bound to the `JL_STD*`[libuv](http://docs.libuv.org) +[`Base.STDIN`](@ref), [`Base.STDOUT`](@ref) and [`Base.STDERR`](@ref) are bound to the `JL_STD*` libuv streams defined in the runtime. Julia's `__init__()` function (in `base/sysimg.jl`) calls `reinit_stdio()` (in `base/stream.jl`) @@ -51,7 +51,7 @@ Tuple{Base.PipeEndpoint,Base.PipeEndpoint,Base.TTY} ``` The [`Base.read()`](@ref) and [`Base.write()`](@ref) methods for these streams use [`ccall`](@ref) -to call `libuv` wrappers in `src/jl_uv.c`, e.g.: +to call libuv wrappers in `src/jl_uv.c`, e.g.: ``` stream.jl: function write(s::IO, p::Ptr, nb::Integer) @@ -60,43 +60,43 @@ stream.jl: function write(s::IO, p::Ptr, nb::Integer) -> uv_write(uvw, stream, buf, ...) ``` -## printf() during initialisation +## printf() during initialization -The `libuv` streams relied upon by `jl_printf()` etc., are not available until midway through -initialisation of the runtime (see `init.c`, `init_stdio()`). Error messages or warnings that +The libuv streams relied upon by `jl_printf()` etc., are not available until midway through +initialization of the runtime (see `init.c`, `init_stdio()`). Error messages or warnings that need to be printed before this are routed to the standard C library `fwrite()` function by the following mechanism: -In `sys.c`, the `JL_STD*` stream pointers are statically initialised to integer constants: `STD*_FILENO (0, 1 and 2)`. +In `sys.c`, the `JL_STD*` stream pointers are statically initialized to integer constants: `STD*_FILENO (0, 1 and 2)`. In `jl_uv.c` the `jl_uv_puts()` function checks its `uv_stream_t* stream` argument and calls `fwrite()` if stream is set to `STDOUT_FILENO` or `STDERR_FILENO`. This allows for uniform use of `jl_printf()` throughout the runtime regardless of whether or not -any particular piece of code is reachable before initialisation is complete. +any particular piece of code is reachable before initialization is complete. ## Legacy ios.c library -The `julia/src/support/ios.c` library is inherited from [femtolisp](https://github.com/JeffBezanson/femtolisp). +The `src/support/ios.c` library is inherited from [femtolisp](https://github.com/JeffBezanson/femtolisp). It provides cross-platform buffered file IO and in-memory temporary buffers. -`ios.c` is still used by: +ios.c is still used by: - * `julia/src/flisp/*.c` - * `julia/src/dump.c` – for serialisation file IO and for memory buffers. - * `base/iostream.jl` – for file IO (see `base/fs.jl` for `libuv` equivalent). + * `src/flisp/*.c` + * `src/dump.c` – for serialization file IO and for memory buffers. + * `base/iostream.jl` – for file IO (see `base/fs.jl` for libuv equivalent). -Use of `ios.c` in these modules is mostly self-contained and separated from the `libuv` I/O system. +Use of ios.c in these modules is mostly self-contained and separated from the libuv I/O system. However, there is [one place](https://github.com/JuliaLang/julia/blob/master/src/flisp/print.c#L654) where femtolisp calls through to `jl_printf()` with a legacy `ios_t` stream. There is a hack in `ios.h` that makes the `ios_t.bm` field line up with the `uv_stream_t.type` -and ensures that the values used for `ios_t.bm` to not overlap with valid UV_HANDLE_TYPE values. +and ensures that the values used for `ios_t.bm` to not overlap with valid `UV_HANDLE_TYPE` values. This allows `uv_stream_t` pointers to point to `ios_t` streams. This is needed because `jl_printf()` caller `jl_static_show()` is passed an `ios_t` stream by femtolisp's `fl_print()` function. Julia's `jl_uv_puts()` function has special handling for this: -``` +```c if (stream->type > UV_HANDLE_TYPE_MAX) { return ios_write((ios_t*)stream, str, n); } diff --git a/doc/src/devdocs/types.md b/doc/src/devdocs/types.md index f59dcfb703ca2..1433117aedc95 100644 --- a/doc/src/devdocs/types.md +++ b/doc/src/devdocs/types.md @@ -229,7 +229,7 @@ field, it's helpful to pick a type that is less heavily used than Array. Let's f own type: ```jldoctest -julia> type MyType{T,N} end +julia> struct MyType{T,N} end julia> MyType{Int,2} MyType{Int64,2} From 2478f29104587289fcf669866c17197518d0c2fd Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Fri, 21 Apr 2017 23:06:16 -0500 Subject: [PATCH 0516/1534] Add show_supertypes in type help --- base/docs/Docs.jl | 7 +++++++ test/docs.jl | 15 +++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/base/docs/Docs.jl b/base/docs/Docs.jl index 2e7a47946a464..97680085858e1 100644 --- a/base/docs/Docs.jl +++ b/base/docs/Docs.jl @@ -400,6 +400,13 @@ function summarize(io::IO, T::DataType, binding) end println(io, "```") end + if supertype(T) != Any + println(io, "**Supertype Hierarchy:**") + println(io, "```") + Base.show_supertypes(io, T) + println(io) + println(io, "```") + end end function summarize(io::IO, m::Module, binding) diff --git a/test/docs.jl b/test/docs.jl index d851b662215da..45296d80241f2 100644 --- a/test/docs.jl +++ b/test/docs.jl @@ -750,6 +750,11 @@ abstract type $(curmod_prefix)Undocumented.B <: $(curmod_prefix)Undocumented.A ``` $(curmod_prefix)Undocumented.D ``` + +**Supertype Hierarchy:** +``` +$(curmod_prefix)Undocumented.B <: $(curmod_prefix)Undocumented.A <: Any +``` """) @test docstrings_equal(@doc(Undocumented.B), doc"$doc_str") @@ -760,6 +765,11 @@ No documentation found. ``` mutable struct $(curmod_prefix)Undocumented.C <: $(curmod_prefix)Undocumented.A ``` + +**Supertype Hierarchy:** +``` +$(curmod_prefix)Undocumented.C <: $(curmod_prefix)Undocumented.A <: Any +``` """) @test docstrings_equal(@doc(Undocumented.C), doc"$doc_str") @@ -777,6 +787,11 @@ one :: Any two :: String three :: Float64 ``` + +**Supertype Hierarchy:** +``` +$(curmod_prefix)Undocumented.D <: $(curmod_prefix)Undocumented.B <: $(curmod_prefix)Undocumented.A <: Any +``` """) @test docstrings_equal(@doc(Undocumented.D), doc"$doc_str") From a761f1096392f05044c74f6febc358b9bda71d73 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Mon, 3 Apr 2017 16:12:26 -0400 Subject: [PATCH 0517/1534] Improve code generation for homogenous tuples of unknown length E.g.: ``` mutable struct foo x::Int end mutable struct bar tup::NTuple{N, foo} where N end function f(b::bar) sum = 0 for i = 1:2 @inbounds sum += b.tup[i].x end sum end global x = bar((foo(1),foo(2))) @benchmark f(x::bar) ``` Before: ``` julia> @benchmark f(x::bar) BenchmarkTools.Trial: memory estimate: 0 bytes allocs estimate: 0 -------------- minimum time: 27.124 ns (0.00% GC) median time: 28.771 ns (0.00% GC) mean time: 29.864 ns (0.00% GC) maximum time: 116.762 ns (0.00% GC) -------------- samples: 10000 evals/sample: 995 ``` After: ``` BenchmarkTools.Trial: memory estimate: 0 bytes allocs estimate: 0 -------------- minimum time: 10.531 ns (0.00% GC) median time: 10.559 ns (0.00% GC) mean time: 10.610 ns (0.00% GC) maximum time: 122.751 ns (0.00% GC) -------------- samples: 10000 evals/sample: 999 time tolerance: 5.00% memory tolerance: 1.00% ``` --- src/cgutils.cpp | 37 +++++++++++++++++++++++++++---------- src/codegen.cpp | 27 +++++++++++++++++++++++++++ src/intrinsics.cpp | 2 +- 3 files changed, 55 insertions(+), 11 deletions(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 1561f7883f1eb..c5a5efcc748b5 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -544,15 +544,24 @@ static bool is_datatype_all_pointers(jl_datatype_t *dt) return true; } -static bool is_tupletype_homogeneous(jl_svec_t *t) +static bool is_tupletype_homogeneous(jl_svec_t *t, bool allow_va = false) { size_t i, l = jl_svec_len(t); if (l > 0) { jl_value_t *t0 = jl_svecref(t, 0); - if (!jl_is_leaf_type(t0)) + if (!jl_is_leaf_type(t0)) { + if (allow_va && jl_is_vararg_type(t0) && + jl_is_leaf_type(jl_unwrap_vararg(t0))) + return true; return false; + } for(i=1; i < l; i++) { - if (!jl_types_equal(t0, jl_svecref(t,i))) + if (allow_va && i == l - 1 && jl_is_vararg_type(jl_svecref(t,i))) { + if (t0 != jl_unwrap_vararg(jl_svecref(t,i))) + return false; + continue; + } + if (t0 != jl_svecref(t,i)) return false; } } @@ -1080,13 +1089,21 @@ static void emit_leafcheck(Value *typ, const std::string &msg, jl_codectx_t *ctx } #define CHECK_BOUNDS 1 +static bool bounds_check_enabled(jl_codectx_t *ctx) { +#if CHECK_BOUNDS==1 + return (!ctx->is_inbounds && + jl_options.check_bounds != JL_OPTIONS_CHECK_BOUNDS_OFF) || + jl_options.check_bounds == JL_OPTIONS_CHECK_BOUNDS_ON; +#else + return 0; +#endif +} + static Value *emit_bounds_check(const jl_cgval_t &ainfo, jl_value_t *ty, Value *i, Value *len, jl_codectx_t *ctx) { Value *im1 = builder.CreateSub(i, ConstantInt::get(T_size, 1)); #if CHECK_BOUNDS==1 - if ((!ctx->is_inbounds && - jl_options.check_bounds != JL_OPTIONS_CHECK_BOUNDS_OFF) || - jl_options.check_bounds == JL_OPTIONS_CHECK_BOUNDS_ON) { + if (bounds_check_enabled(ctx)) { Value *ok = builder.CreateICmpULT(im1, len); BasicBlock *failBB = BasicBlock::Create(jl_LLVMContext,"fail",ctx->f); BasicBlock *passBB = BasicBlock::Create(jl_LLVMContext,"pass"); @@ -1157,7 +1174,7 @@ static unsigned julia_alignment(Value* /*ptr*/, jl_value_t *jltype, unsigned ali static Value *emit_unbox(Type *to, const jl_cgval_t &x, jl_value_t *jt, Value* dest = NULL, bool volatile_store = false); static jl_cgval_t typed_load(Value *ptr, Value *idx_0based, jl_value_t *jltype, - jl_codectx_t *ctx, MDNode *tbaa, unsigned alignment = 0) + jl_codectx_t *ctx, MDNode *tbaa, bool maybe_null_if_boxed = true, unsigned alignment = 0) { bool isboxed; Type *elty = julia_type_to_llvm(jltype, &isboxed); @@ -1187,7 +1204,7 @@ static jl_cgval_t typed_load(Value *ptr, Value *idx_0based, jl_value_t *jltype, else { elt = load; } - if (isboxed) { + if (maybe_null_if_boxed && isboxed) { null_pointer_check(elt, ctx); } //} @@ -1361,7 +1378,7 @@ static bool emit_getfield_unknownidx(jl_cgval_t *ret, const jl_cgval_t &strct, ret->isimmutable = strct.isimmutable; return true; } - *ret = typed_load(ptr, idx, jt, ctx, strct.tbaa); + *ret = typed_load(ptr, idx, jt, ctx, strct.tbaa, false); return true; } else if (strct.isboxed) { @@ -1458,7 +1475,7 @@ static jl_cgval_t emit_getfield_knownidx(const jl_cgval_t &strct, unsigned idx, int align = jl_field_offset(jt, idx); align |= 16; align &= -align; - return typed_load(addr, ConstantInt::get(T_size, 0), jfty, ctx, strct.tbaa, align); + return typed_load(addr, ConstantInt::get(T_size, 0), jfty, ctx, strct.tbaa, true, align); } else if (isa(strct.V)) { return jl_cgval_t(); diff --git a/src/codegen.cpp b/src/codegen.cpp index 5de00ef196c3f..6780af99cadb1 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3010,6 +3010,33 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, } } } + } else { + jl_value_t *utt = jl_unwrap_unionall((jl_value_t*)stt); + if (jl_is_tuple_type(utt) && is_tupletype_homogeneous(((jl_datatype_t*)utt)->types, true)) { + // For tuples, we can emit code even if we don't know the exact + // type (e.g. because we don't know the length). So long as all + // elements are the same and a leaf type. + jl_cgval_t strct = emit_expr(args[1], ctx); + if (strct.ispointer()) { + // Determine which was the type that was homogenous + jl_value_t *jt = jl_tparam0(utt); + if (jl_is_vararg_type(jt)) + jt = jl_unwrap_vararg(jt); + Value *vidx = emit_unbox(T_size, emit_expr(args[2], ctx), (jl_value_t*)jl_long_type); + // This is not necessary for correctness, but allows to omit + // the extra code for getting the length of the tuple + if (!bounds_check_enabled(ctx)) { + vidx = builder.CreateSub(vidx, ConstantInt::get(T_size, 1)); + } else { + vidx = emit_bounds_check(strct, (jl_value_t*)stt, vidx, + emit_datatype_nfields(emit_typeof_boxed(strct, ctx)), ctx); + } + Value *ptr = data_pointer(strct, ctx); + *ret = typed_load(ptr, vidx, jt, ctx, strct.tbaa, false); + JL_GC_POP(); + return true; + } + } } } diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index 1853abead3452..b99c66376387c 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -627,7 +627,7 @@ static jl_cgval_t emit_pointerref(jl_cgval_t *argv, jl_codectx_t *ctx) Type *ptrty = julia_type_to_llvm(e.typ, &isboxed); assert(!isboxed); Value *thePtr = emit_unbox(ptrty, e, e.typ); - return typed_load(thePtr, im1, ety, ctx, tbaa_data, align_nb); + return typed_load(thePtr, im1, ety, ctx, tbaa_data, true, align_nb); } static jl_cgval_t emit_runtime_pointerset(jl_cgval_t *argv, jl_codectx_t *ctx) From 45092ff0012620e155e32b20ee6b0095f2957a45 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 21 Apr 2017 14:37:02 -0400 Subject: [PATCH 0518/1534] fix no COPY_STACKS --- src/dump.c | 2 +- src/gc.c | 4 +++- src/julia_internal.h | 1 - src/task.c | 24 +++++++++++++++++------- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/dump.c b/src/dump.c index 1293667f5a37b..ec57645f712b6 100644 --- a/src/dump.c +++ b/src/dump.c @@ -81,7 +81,7 @@ static const jl_fptr_t id_to_fptrs[] = { jl_f_tuple, jl_f_svec, jl_f_intrinsic_call, jl_f_invoke_kwsorter, jl_f_getfield, jl_f_setfield, jl_f_fieldtype, jl_f_nfields, jl_f_arrayref, jl_f_arrayset, jl_f_arraysize, jl_f_apply_type, - jl_f_applicable, jl_f_invoke, jl_unprotect_stack, jl_f_sizeof, jl_f__expr, + jl_f_applicable, jl_f_invoke, jl_f_sizeof, jl_f__expr, NULL }; static const intptr_t LongSymbol_tag = 23; diff --git a/src/gc.c b/src/gc.c index 9adea74dfa25c..2a59ed76f4b5c 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1734,7 +1734,9 @@ static void mark_roots(jl_ptls_t ptls) if (jl_all_methods != NULL) gc_push_root(ptls, jl_all_methods, 0); - // gc_push_root(ptls, jl_unprotect_stack_func, 0); +#ifndef COPY_STACKS + gc_push_root(ptls, jl_unprotect_stack_func, 0); +#endif // constants gc_push_root(ptls, jl_typetype_type, 0); diff --git a/src/julia_internal.h b/src/julia_internal.h index d9305cacedd93..41e164771a5ef 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -401,7 +401,6 @@ JL_DLLEXPORT void jl_typeassert(jl_value_t *x, jl_value_t *t); #define JL_CALLABLE(name) \ JL_DLLEXPORT jl_value_t *name(jl_value_t *F, jl_value_t **args, uint32_t nargs) -JL_CALLABLE(jl_unprotect_stack); JL_CALLABLE(jl_f_tuple); JL_CALLABLE(jl_f_intrinsic_call); extern jl_function_t *jl_unprotect_stack_func; diff --git a/src/task.c b/src/task.c index be99b9afdda9a..328bb4f4d81e4 100644 --- a/src/task.c +++ b/src/task.c @@ -4,6 +4,16 @@ task.c lightweight processes (symmetric coroutines) */ + +//// enable this for ifndef COPY_STACKS to work on linux +//#ifdef _FORTIFY_SOURCE +//// disable __longjmp_chk validation so that we can jump between stacks +//#pragma push_macro("_FORTIFY_SOURCE") +//#undef _FORTIFY_SOURCE +//#include +//#pragma pop_macro("_FORTIFY_SOURCE") +//#endif + #include "platform.h" #include @@ -625,7 +635,7 @@ JL_DLLEXPORT jl_task_t *jl_new_task(jl_function_t *start, size_t ssize) stk += pagesz; init_task(t, stk); - //jl_gc_add_finalizer((jl_value_t*)t, jl_unprotect_stack_func); + jl_gc_add_finalizer((jl_value_t*)t, jl_unprotect_stack_func); JL_GC_POP(); #endif @@ -635,17 +645,15 @@ JL_DLLEXPORT jl_task_t *jl_new_task(jl_function_t *start, size_t ssize) return t; } -JL_CALLABLE(jl_unprotect_stack) -{ #ifndef COPY_STACKS - jl_task_t *t = (jl_task_t*)args[0]; +static void jl_unprotect_stack(jl_task_t *t) +{ size_t pagesz = jl_page_size; char *stk = (char*)LLT_ALIGN((uintptr_t)t->stkbuf, pagesz); // unprotect stack so it can be reallocated for something else mprotect(stk, pagesz - 1, PROT_READ|PROT_WRITE); -#endif - return jl_nothing; } +#endif JL_DLLEXPORT jl_value_t *jl_get_current_task(void) { @@ -690,7 +698,9 @@ void jl_init_tasks(void) failed_sym = jl_symbol("failed"); runnable_sym = jl_symbol("runnable"); - //jl_unprotect_stack_func = jl_new_closure(jl_unprotect_stack, (jl_value_t*)jl_emptysvec, NULL); +#ifndef COPY_STACKS + jl_unprotect_stack_func = jl_box_voidpointer(&jl_unprotect_stack); +#endif } // Initialize a root task using the given stack. From 65d5762485dfdc3d57f8463ba1852d6526019c70 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 20 Apr 2017 14:42:56 -0400 Subject: [PATCH 0519/1534] improve yieldto error handling previously we couldn't reliably tell the difference between a failure to context switch and an explicitly scheduled error in the former case, we often need to undo some prior action by moving the code for the later into Julia, we can reliably run the necessary undo action when required fix #21442 --- base/channels.jl | 29 +++++----- base/event.jl | 116 +++++++++++++++++++++++-------------- base/stream.jl | 14 +++-- base/task.jl | 4 +- doc/src/stdlib/parallel.md | 2 +- src/gc.c | 1 - src/julia.h | 3 +- src/julia_threads.h | 1 - src/task.c | 36 ++++-------- test/channels.jl | 31 ++++++++++ 10 files changed, 144 insertions(+), 93 deletions(-) diff --git a/base/channels.jl b/base/channels.jl index 403dc73190bc2..5d7b00ca9eb4b 100644 --- a/base/channels.jl +++ b/base/channels.jl @@ -104,10 +104,9 @@ true """ function Channel(func::Function; ctype=Any, csize=0, taskref=nothing) chnl = Channel{ctype}(csize) - task = Task(()->func(chnl)) - bind(chnl,task) - schedule(task) - yield() + task = Task(() -> func(chnl)) + bind(chnl, task) + yield(task) # immediately start it isa(taskref, Ref{Task}) && (taskref[] = task) return chnl @@ -215,14 +214,13 @@ function channeled_tasks(n::Int, funcs...; ctypes=fill(Any,n), csizes=fill(0,n)) @assert length(csizes) == n @assert length(ctypes) == n - chnls = map(i->Channel{ctypes[i]}(csizes[i]), 1:n) - tasks=Task[Task(()->f(chnls...)) for f in funcs] + chnls = map(i -> Channel{ctypes[i]}(csizes[i]), 1:n) + tasks = Task[ Task(() -> f(chnls...)) for f in funcs ] # bind all tasks to all channels and schedule them - foreach(t -> foreach(c -> bind(c,t), chnls), tasks) + foreach(t -> foreach(c -> bind(c, t), chnls), tasks) foreach(schedule, tasks) - - yield() # Allow scheduled tasks to run + yield() # Allow scheduled tasks to run return (chnls, tasks) end @@ -283,9 +281,8 @@ function put_unbuffered(c::Channel, v) end end taker = shift!(c.takers) - schedule(current_task()) - yieldto(taker, v) - v + yield(taker, v) # immediately give taker a chance to run, but don't block the current task + return v end push!(c::Channel, v) = put!(c, v) @@ -328,8 +325,12 @@ function take_unbuffered(c::Channel{T}) where T push!(c.takers, current_task()) try if length(c.putters) > 0 - putter = shift!(c.putters) - return yieldto(putter)::T + let putter = shift!(c.putters) + return Base.try_yieldto(putter) do + # if we fail to start putter, put it back in the queue + unshift!(c.putters, putter) + end::T + end else return wait()::T end diff --git a/base/event.jl b/base/event.jl index 8a5167d047f5f..4516d3a69d89a 100644 --- a/base/event.jl +++ b/base/event.jl @@ -127,8 +127,8 @@ function schedule(t::Task, arg; error=false) return enq_work(t) end -# fast version of schedule(t,v);wait() -function schedule_and_wait(t::Task, v=nothing) +# fast version of `schedule(t, arg); wait()` +function schedule_and_wait(t::Task, arg=nothing) t.state == :runnable || error("schedule: Task not runnable") if isempty(Workqueue) return yieldto(t, v) @@ -149,6 +149,19 @@ tasks. """ yield() = (enq_work(current_task()); wait()) +""" + yield(t::Task, arg = nothing) + +A fast, unfair-scheduling version of `schedule(t, arg); yield()` which +immediately yields to `t` before calling the scheduler. +""" +function yield(t::Task, x::ANY = nothing) + t.state == :runnable || error("schedule: Task not runnable") + t.result = x + enq_work(current_task()) + return try_yieldto(ensure_self_descheduled, t) +end + """ yieldto(t::Task, arg = nothing) @@ -157,12 +170,44 @@ called with no arguments. On subsequent switches, `arg` is returned from the tas call to `yieldto`. This is a low-level call that only switches tasks, not considering states or scheduling in any way. Its use is discouraged. """ -yieldto(t::Task, x::ANY = nothing) = ccall(:jl_switchto, Any, (Any, Any), t, x) +function yieldto(t::Task, x::ANY = nothing) + t.result = x + return try_yieldto(Void, t) +end + +function try_yieldto(undo::F, t::Task) where F + try + ccall(:jl_switchto, Void, (Any,), t) + catch e + undo() + rethrow(e) + end + ct = current_task() + exc = ct.exception + if exc !== nothing + ct.exception = nothing + throw(exc) + end + result = ct.result + ct.result = nothing + return result +end # yield to a task, throwing an exception in it -function throwto(t::Task, exc) +function throwto(t::Task, exc::ANY) t.exception = exc - yieldto(t) + return yieldto(t) +end + +function ensure_self_descheduled() + # return a queued task to the runnable state + ct = current_task() + if ct.state == :queued + i = findfirst(Workqueue, ct) + i == 0 || deleteat!(Workqueue, i) + ct.state = :runnable + end + nothing end function wait() @@ -175,43 +220,28 @@ function wait() pause() end else - t = shift!(Workqueue) - if t.state != :queued - # assume this somehow got queued twice, - # probably broken now, but try discarding this switch and keep going - # can't throw here, because it's probably not the fault of the caller to wait - # and don't want to use print() here, because that may try to incur a task switch - ccall(:jl_safe_printf, Void, (Ptr{UInt8}, Vararg{Int32}), - "\nWARNING: Workqueue inconsistency detected: shift!(Workqueue).state != :queued\n") - continue - end - arg = t.result - t.result = nothing - t.state = :runnable - local result - try - result = yieldto(t, arg) - current_task().state == :runnable || throw(AssertionError("current_task().state == :runnable")) - catch e - ct = current_task() - if ct.state == :queued - if t.state == :runnable - # assume we failed to queue t - # return it to the queue to be scheduled later - t.result = arg - t.state = :queued - push!(Workqueue, t) - end - # return ourself to the runnable state - i = findfirst(Workqueue, ct) - i == 0 || deleteat!(Workqueue, i) - ct.state = :runnable + let t = shift!(Workqueue) + if t.state != :queued + # assume this somehow got queued twice, + # probably broken now, but try discarding this switch and keep going + # can't throw here, because it's probably not the fault of the caller to wait + # and don't want to use print() here, because that may try to incur a task switch + ccall(:jl_safe_printf, Void, (Ptr{UInt8}, Vararg{Int32}), + "\nWARNING: Workqueue inconsistency detected: shift!(Workqueue).state != :queued\n") + continue + end + t.state = :runnable + result = try_yieldto(t) do + # we failed to yield to t + # return it to the head of the queue to be scheduled later + unshift!(Workqueue, t) + t.state = :queued + ensure_self_descheduled() end - rethrow(e) + process_events(false) + # return when we come out of the queue + return result end - process_events(false) - # return when we come out of the queue - return result end end assert(false) @@ -277,8 +307,7 @@ function AsyncCondition(cb::Function) end) # must start the task right away so that it can wait for the AsyncCondition before # we re-enter the event loop. this avoids a race condition. see issue #12719 - enq_work(current_task()) - yieldto(waiter) + yield(waiter) return async end @@ -409,7 +438,6 @@ function Timer(cb::Function, timeout::Real, repeat::Real=0.0) end) # must start the task right away so that it can wait for the Timer before # we re-enter the event loop. this avoids a race condition. see issue #12719 - enq_work(current_task()) - yieldto(waiter) + yield(waiter) return t end diff --git a/base/stream.jl b/base/stream.jl index b695ac664cb8a..aba3457df55cb 100644 --- a/base/stream.jl +++ b/base/stream.jl @@ -794,7 +794,7 @@ uv_write(s::LibuvStream, p::Vector{UInt8}) = uv_write(s, pointer(p), UInt(sizeof function uv_write(s::LibuvStream, p::Ptr{UInt8}, n::UInt) check_open(s) uvw = Libc.malloc(_sizeof_uv_write) - uv_req_set_data(uvw,C_NULL) + uv_req_set_data(uvw, C_NULL) err = ccall(:jl_uv_write, Int32, (Ptr{Void}, Ptr{Void}, UInt, Ptr{Void}, Ptr{Void}), @@ -805,8 +805,14 @@ function uv_write(s::LibuvStream, p::Ptr{UInt8}, n::UInt) uv_error("write", err) end ct = current_task() - uv_req_set_data(uvw,ct) - stream_wait(ct) + preserve_handle(ct) + uv_req_set_data(uvw, ct) + try + wait() + finally + uv_req_set_data(uvw, C_NULL) # make sure we don't get spurious notifications later if the wait failed + unpreserve_handle(ct) + end return Int(n) end @@ -948,7 +954,7 @@ end function connect!(sock::PipeEndpoint, path::AbstractString) @assert sock.status == StatusInit req = Libc.malloc(_sizeof_uv_connect) - uv_req_set_data(req,C_NULL) + uv_req_set_data(req, C_NULL) ccall(:uv_pipe_connect, Void, (Ptr{Void}, Ptr{Void}, Cstring, Ptr{Void}), req, sock.handle, path, uv_jl_connectcb::Ptr{Void}) sock.status = StatusConnecting return sock diff --git a/base/task.jl b/base/task.jl index a25bc78cd65b6..4cfa2ce3781ac 100644 --- a/base/task.jl +++ b/base/task.jl @@ -238,7 +238,7 @@ function task_done_hook(t::Task) if isa(result,InterruptException) && isdefined(Base,:active_repl_backend) && active_repl_backend.backend_task.state == :runnable && isempty(Workqueue) && active_repl_backend.in_eval - throwto(active_repl_backend.backend_task, result) + throwto(active_repl_backend.backend_task, result) # this terminates the task end if !suppress_excp_printing(t) let bt = t.backtrace @@ -253,7 +253,7 @@ function task_done_hook(t::Task) end # Clear sigatomic before waiting sigatomic_end() - wait() + wait() # this will not return end diff --git a/doc/src/stdlib/parallel.md b/doc/src/stdlib/parallel.md index d668f346136d1..730951e9c9540 100644 --- a/doc/src/stdlib/parallel.md +++ b/doc/src/stdlib/parallel.md @@ -4,11 +4,11 @@ ```@docs Core.Task -Base.yieldto Base.current_task Base.istaskdone Base.istaskstarted Base.yield +Base.yieldto Base.task_local_storage(::Any) Base.task_local_storage(::Any, ::Any) Base.task_local_storage(::Function, ::Any, ::Any) diff --git a/src/gc.c b/src/gc.c index 2a59ed76f4b5c..4c013fc396de7 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1710,7 +1710,6 @@ static void jl_gc_mark_thread_local(jl_ptls_t ptls, jl_ptls_t ptls2) gc_push_root(ptls, ptls2->current_task, 0); gc_push_root(ptls, ptls2->root_task, 0); gc_push_root(ptls, ptls2->exception_in_transit, 0); - gc_push_root(ptls, ptls2->task_arg_in_transit, 0); } // mark the initial root set diff --git a/src/julia.h b/src/julia.h index 2368117e58029..d6baf7b3e9d74 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1495,7 +1495,7 @@ typedef struct _jl_task_t { } jl_task_t; JL_DLLEXPORT jl_task_t *jl_new_task(jl_function_t *start, size_t ssize); -JL_DLLEXPORT jl_value_t *jl_switchto(jl_task_t *t, jl_value_t *arg); +JL_DLLEXPORT void jl_switchto(jl_task_t *t); JL_DLLEXPORT void JL_NORETURN jl_throw(jl_value_t *e); JL_DLLEXPORT void JL_NORETURN jl_rethrow(void); JL_DLLEXPORT void JL_NORETURN jl_rethrow_other(jl_value_t *e); @@ -1797,7 +1797,6 @@ typedef struct { #define jl_current_task (jl_get_ptls_states()->current_task) #define jl_root_task (jl_get_ptls_states()->root_task) #define jl_exception_in_transit (jl_get_ptls_states()->exception_in_transit) -#define jl_task_arg_in_transit (jl_get_ptls_states()->task_arg_in_transit) // codegen interface ---------------------------------------------------------- diff --git a/src/julia_threads.h b/src/julia_threads.h index 8fd701f03ae7f..dedab485c1cf1 100644 --- a/src/julia_threads.h +++ b/src/julia_threads.h @@ -105,7 +105,6 @@ typedef struct _jl_tls_states_t { struct _jl_module_t *current_module; struct _jl_task_t *volatile current_task; struct _jl_task_t *root_task; - struct _jl_value_t *volatile task_arg_in_transit; void *stackbase; char *stack_lo; char *stack_hi; diff --git a/src/task.c b/src/task.c index 328bb4f4d81e4..2f8b2a4188af8 100644 --- a/src/task.c +++ b/src/task.c @@ -210,10 +210,15 @@ static void JL_NORETURN finish_task(jl_task_t *t, jl_value_t *resultval) #ifdef COPY_STACKS t->stkbuf = (void*)(intptr_t)-1; #endif + // ensure that state is cleared + ptls->in_finalizer = 0; + ptls->in_pure_callback = 0; + jl_get_ptls_states()->world_age = jl_world_counter; if (ptls->tid != 0) { // For now, only thread 0 runs the task scheduler. // The others return to the thread loop - jl_switchto(ptls->root_task, jl_nothing); + ptls->root_task->result = jl_nothing; + jl_switchto(ptls->root_task); gc_debug_critical_error(); abort(); } @@ -234,15 +239,6 @@ static void JL_NORETURN finish_task(jl_task_t *t, jl_value_t *resultval) abort(); } -static void throw_if_exception_set(jl_task_t *t) -{ - if (t->exception != NULL && t->exception != jl_nothing) { - jl_value_t *exc = t->exception; - t->exception = jl_nothing; - jl_throw(exc); - } -} - static void record_backtrace(void) { jl_ptls_t ptls = jl_get_ptls_states(); @@ -256,7 +252,7 @@ static void NOINLINE JL_NORETURN start_task(void) jl_task_t *t = ptls->current_task; jl_value_t *res; t->started = 1; - if (t->exception != NULL && t->exception != jl_nothing) { + if (t->exception != jl_nothing) { record_backtrace(); res = t->exception; } @@ -276,7 +272,6 @@ static void NOINLINE JL_NORETURN start_task(void) jl_gc_wb(t, res); } } - jl_get_ptls_states()->world_age = jl_world_counter; // TODO finish_task(t, res); gc_debug_critical_error(); abort(); @@ -400,18 +395,17 @@ static void ctx_switch(jl_ptls_t ptls, jl_task_t *t, jl_jmp_buf *where) #endif } -JL_DLLEXPORT jl_value_t *jl_switchto(jl_task_t *t, jl_value_t *arg) +JL_DLLEXPORT void jl_switchto(jl_task_t *t) { jl_ptls_t ptls = jl_get_ptls_states(); if (t == ptls->current_task) { - throw_if_exception_set(t); - return arg; + return; } if (t->state == done_sym || t->state == failed_sym || (t->stkbuf == (void*)(intptr_t)-1)) { - if (t->exception != jl_nothing) - jl_throw(t->exception); - return t->result; + ptls->current_task->exception = t->exception; + ptls->current_task->result = t->result; + return; } if (ptls->in_finalizer) jl_error("task switch not allowed from inside gc finalizer"); @@ -419,17 +413,12 @@ JL_DLLEXPORT jl_value_t *jl_switchto(jl_task_t *t, jl_value_t *arg) jl_error("task switch not allowed from inside staged nor pure functions"); sig_atomic_t defer_signal = ptls->defer_signal; int8_t gc_state = jl_gc_unsafe_enter(ptls); - ptls->task_arg_in_transit = arg; ctx_switch(ptls, t, &t->ctx); - jl_value_t *val = ptls->task_arg_in_transit; - ptls->task_arg_in_transit = jl_nothing; - throw_if_exception_set(ptls->current_task); jl_gc_unsafe_leave(ptls, gc_state); sig_atomic_t other_defer_signal = ptls->defer_signal; ptls->defer_signal = defer_signal; if (other_defer_signal && !defer_signal) jl_sigint_safepoint(ptls); - return val; } #ifndef COPY_STACKS @@ -738,7 +727,6 @@ void jl_init_root_task(void *stack, size_t ssize) ptls->root_task = ptls->current_task; ptls->exception_in_transit = (jl_value_t*)jl_nothing; - ptls->task_arg_in_transit = (jl_value_t*)jl_nothing; } JL_DLLEXPORT int jl_is_task_started(jl_task_t *t) diff --git a/test/channels.jl b/test/channels.jl index d3260f57920a1..ac94a9e8ce731 100644 --- a/test/channels.jl +++ b/test/channels.jl @@ -217,3 +217,34 @@ end end @test isready(rr1) end + + +# test for yield/wait/event failures +@noinline garbage_finalizer(f) = finalizer("gar" * "bage", f) +let t, run = Ref(0) + gc_enable(false) + garbage_finalizer((x) -> (run[] += 1; sleep(1))) + garbage_finalizer((x) -> (run[] += 1; yield())) + garbage_finalizer((x) -> (run[] += 1; yieldto(@task () -> ()))) + t = @task begin + gc_enable(true) + gc() + end + oldstderr = STDERR + local newstderr, errstream + try + newstderr = redirect_stderr() + errstream = @async readstring(newstderr[1]) + yield(t) + finally + redirect_stderr(oldstderr) + close(newstderr[2]) + end + wait(t) + @test run[] == 3 + @test wait(errstream) == """ + error in running finalizer: ErrorException("task switch not allowed from inside gc finalizer") + error in running finalizer: ErrorException("task switch not allowed from inside gc finalizer") + error in running finalizer: ErrorException("task switch not allowed from inside gc finalizer") + """ +end From 7747f2806fe3bb02a5cf420a2713827e587fc3be Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Wed, 5 Apr 2017 15:48:14 -0400 Subject: [PATCH 0520/1534] Don't emit symbols with at in them on Linux The linker interprets them as versioning annotations causing all sorts of trouble --- src/cgutils.cpp | 9 +++++---- src/codegen.cpp | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 1561f7883f1eb..f3c965aabbe95 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -249,13 +249,14 @@ static Value *julia_pgv(const char *prefix, jl_sym_t *name, jl_module_t *mod, vo } char *fullname = (char*)alloca(len); strcpy(fullname, prefix); - len -= strlen(jl_symbol_name(name))+1; - strcpy(fullname + len, jl_symbol_name(name)); + int skipfirst = jl_symbol_name(name)[0] == '@'; + len -= strlen(jl_symbol_name(name)) + 1 - skipfirst; + strcpy(fullname + len, jl_symbol_name(name) + skipfirst); parent = mod; prev = NULL; while (parent != NULL && parent != prev) { - size_t part = strlen(jl_symbol_name(parent->name))+1; - strcpy(fullname+len-part,jl_symbol_name(parent->name)); + size_t part = strlen(jl_symbol_name(parent->name))+1-skipfirst; + strcpy(fullname+len-part,jl_symbol_name(parent->name)+skipfirst); fullname[len-1] = '.'; len -= part; prev = parent; diff --git a/src/codegen.cpp b/src/codegen.cpp index a9ea6ffed4584..2ff6cb4e97145 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -5264,7 +5264,7 @@ static std::unique_ptr emit_function( else funcName << "japi1_"; const char* unadorned_name = ctx.name; -#if (defined(_OS_LINUX_) && JL_LLVM_VERSION < 30400) +#if defined(_OS_LINUX_) if (unadorned_name[0] == '@') unadorned_name++; #endif From cae6ca798c793a1550c39eee83a8f7785a3e836c Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Sat, 22 Apr 2017 15:32:56 -0400 Subject: [PATCH 0521/1534] Add infrastructure for testing julia's LLVM passes --- deps/llvm-options.mk | 21 +++++++++++++++++++++ deps/llvm.mk | 24 ++---------------------- test/llvmpasses/Makefile | 11 +++++++++++ test/llvmpasses/lit.cfg | 15 +++++++++++++++ 4 files changed, 49 insertions(+), 22 deletions(-) create mode 100644 deps/llvm-options.mk create mode 100644 test/llvmpasses/Makefile create mode 100644 test/llvmpasses/lit.cfg diff --git a/deps/llvm-options.mk b/deps/llvm-options.mk new file mode 100644 index 0000000000000..0afd1d64ed991 --- /dev/null +++ b/deps/llvm-options.mk @@ -0,0 +1,21 @@ +ifeq ($(LLVM_DEBUG),1) +LLVM_BUILDTYPE := Debug +else +LLVM_BUILDTYPE := Release +endif +LLVM_CMAKE_BUILDTYPE := $(LLVM_BUILDTYPE) +ifeq ($(LLVM_ASSERTIONS),1) +LLVM_BUILDTYPE := $(LLVM_BUILDTYPE)+Asserts +endif +LLVM_FLAVOR := $(LLVM_BUILDTYPE) +ifeq ($(LLVM_SANITIZE),1) +ifeq ($(SANITIZE_MEMORY),1) +LLVM_BUILDTYPE := $(LLVM_BUILDTYPE)+MSAN +else +LLVM_BUILDTYPE := $(LLVM_BUILDTYPE)+ASAN +endif +endif + +LLVM_SRC_DIR:=$(SRCDIR)/srccache/llvm-$(LLVM_VER) +LLVM_BUILD_DIR:=$(BUILDDIR)/llvm-$(LLVM_VER) +LLVM_BUILDDIR_withtype := $(LLVM_BUILD_DIR)/build_$(LLVM_BUILDTYPE) diff --git a/deps/llvm.mk b/deps/llvm.mk index d878d6d470418..411d07954add5 100644 --- a/deps/llvm.mk +++ b/deps/llvm.mk @@ -23,27 +23,7 @@ endif endif endif -ifeq ($(LLVM_DEBUG),1) -LLVM_BUILDTYPE := Debug -else -LLVM_BUILDTYPE := Release -endif -LLVM_CMAKE_BUILDTYPE := $(LLVM_BUILDTYPE) -ifeq ($(LLVM_ASSERTIONS),1) -LLVM_BUILDTYPE := $(LLVM_BUILDTYPE)+Asserts -endif -LLVM_FLAVOR := $(LLVM_BUILDTYPE) -ifeq ($(LLVM_SANITIZE),1) -ifeq ($(SANITIZE_MEMORY),1) -LLVM_BUILDTYPE := $(LLVM_BUILDTYPE)+MSAN -else -LLVM_BUILDTYPE := $(LLVM_BUILDTYPE)+ASAN -endif -endif - -LLVM_SRC_DIR:=$(SRCDIR)/srccache/llvm-$(LLVM_VER) -LLVM_BUILD_DIR:=$(BUILDDIR)/llvm-$(LLVM_VER) -LLVM_BUILDDIR_withtype := $(LLVM_BUILD_DIR)/build_$(LLVM_BUILDTYPE) +include $(SRCDIR)/llvm-options.mk LLVM_LIB_FILE := libLLVMCodeGen.a ifeq ($(LLVM_VER), 3.3) @@ -124,7 +104,7 @@ ifeq ($(USE_LLVM_SHLIB),1) # NOTE: we could also --disable-static here (on the condition we link tools # against libLLVM) but there doesn't seem to be a CMake counterpart option LLVM_FLAGS += --enable-shared -LLVM_CMAKE += -DLLVM_BUILD_LLVM_DYLIB:BOOL=ON +LLVM_CMAKE += -DLLVM_BUILD_LLVM_DYLIB:BOOL=ON -DLLVM_LINK_LLVM_DYLIB:BOOL=ON # NOTE: starting with LLVM 3.8, all symbols are exported ifeq ($(LLVM_VER_SHORT),$(filter $(LLVM_VER_SHORT),3.3 3.4 3.5 3.6 3.7)) LLVM_CMAKE += -DLLVM_DYLIB_EXPORT_ALL:BOOL=ON diff --git a/test/llvmpasses/Makefile b/test/llvmpasses/Makefile new file mode 100644 index 0000000000000..76c8301803c71 --- /dev/null +++ b/test/llvmpasses/Makefile @@ -0,0 +1,11 @@ +SRCDIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) +JULIAHOME := $(abspath $(SRCDIR)/../..) +include $(JULIAHOME)/deps/Versions.make +include $(JULIAHOME)/Make.inc +include $(JULIAHOME)/deps/llvm-ver.make +BUILDDIR = $(JULIAHOME)/deps/scratch +include $(JULIAHOME)/deps/llvm-options.mk +LLVM_SRC_DIR:=$(JULIAHOME)/deps/srccache/llvm-$(LLVM_VER) +test: + PATH=$$PATH:$(LLVM_BUILDDIR_withtype)/bin $(LLVM_SRC_DIR)/utils/lit/lit.py -v . +.PHONY: test diff --git a/test/llvmpasses/lit.cfg b/test/llvmpasses/lit.cfg new file mode 100644 index 0000000000000..c5b5ace6ec526 --- /dev/null +++ b/test/llvmpasses/lit.cfg @@ -0,0 +1,15 @@ +import os +import sys +import re +import platform + +import lit.util +import lit.formats + +config.name = 'Julia' +config.suffixes = ['.ll'] +config.test_source_root = os.path.dirname(__file__) +config.test_format = lit.formats.ShTest(False) + +path = os.path.pathsep.join((os.path.join(os.path.dirname(__file__),"../../usr/tools"), config.environment['PATH'])) +config.environment['PATH'] = path From 418afaa4d4c2ccdddd1ce926b2e190b39ed35ffa Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Sat, 22 Apr 2017 16:09:55 -0400 Subject: [PATCH 0522/1534] Use new test infrastructure to test simdloop --- src/llvm-simdloop.cpp | 10 ++++++++-- test/llvmpasses/simdloop.ll | 22 ++++++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 test/llvmpasses/simdloop.ll diff --git a/src/llvm-simdloop.cpp b/src/llvm-simdloop.cpp index f5f9d90cdd54e..672b4160a97df 100644 --- a/src/llvm-simdloop.cpp +++ b/src/llvm-simdloop.cpp @@ -144,8 +144,14 @@ void LowerSIMDLoop::enableUnsafeAlgebraIfReduction(PHINode *Phi, Loop *L) const bool LowerSIMDLoop::runOnLoop(Loop *L, LPPassManager &LPM) { - if (!simd_loop_mdkind) - return false; // Fast rejection test. + if (!simd_loop_mdkind) { + simd_loop_mdkind = L->getHeader()->getContext().getMDKindID("simd_loop"); +#if JL_LLVM_VERSION >= 30600 + simd_loop_md = MDNode::get(L->getHeader()->getContext(), ArrayRef()); +#else + simd_loop_md = MDNode::get(L->getHeader()->getContext(), ArrayRef()); +#endif + } if (!hasSIMDLoopMetadata(L)) return false; diff --git a/test/llvmpasses/simdloop.ll b/test/llvmpasses/simdloop.ll new file mode 100644 index 0000000000000..812e71f154895 --- /dev/null +++ b/test/llvmpasses/simdloop.ll @@ -0,0 +1,22 @@ +; RUN: opt -load libjulia.so -LowerSIMDLoop -S %s | FileCheck %s + +define void @simd_test(double *%a, double *%b) { +top: + br label %loop +loop: + %i = phi i64 [0, %top], [%nexti, %loop] + %aptr = getelementptr double, double *%a, i64 %i + %bptr = getelementptr double, double *%b, i64 %i +; CHECK: llvm.mem.parallel_loop_access + %aval = load double, double *%aptr + %bval = load double, double *%aptr + %cval = fadd double %aval, %bval + store double %cval, double *%bptr + %nexti = add i64 %i, 1, !simd_loop !1 + %done = icmp sgt i64 %nexti, 500 + br i1 %done, label %loopdone, label %loop +loopdone: + ret void +} + +!1 = !{} From ed985953010e025c96acbebe4ecdee1f8776681d Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Sat, 22 Apr 2017 16:14:30 -0400 Subject: [PATCH 0523/1534] Clarify comment --- src/codegen.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 6780af99cadb1..247b9fa8d0671 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3014,8 +3014,8 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, jl_value_t *utt = jl_unwrap_unionall((jl_value_t*)stt); if (jl_is_tuple_type(utt) && is_tupletype_homogeneous(((jl_datatype_t*)utt)->types, true)) { // For tuples, we can emit code even if we don't know the exact - // type (e.g. because we don't know the length). So long as all - // elements are the same and a leaf type. + // type (e.g. because we don't know the length). This is possible + // as long as we know that all elements are of the same (leaf) type. jl_cgval_t strct = emit_expr(args[1], ctx); if (strct.ispointer()) { // Determine which was the type that was homogenous From cb42a51b1022445b21c33beb118c40e5d9758867 Mon Sep 17 00:00:00 2001 From: Mus M Date: Sat, 22 Apr 2017 16:08:00 -0400 Subject: [PATCH 0524/1534] New where syntax in misc places --- base/broadcast.jl | 10 ++--- base/checked.jl | 80 +++++++++++++++++------------------ base/complex.jl | 22 +++++----- base/dict.jl | 2 +- base/fastmath.jl | 14 +++--- base/fft/FFTW.jl | 2 +- base/grisu/float.jl | 2 +- base/linalg/dense.jl | 2 +- base/linalg/symmetric.jl | 2 +- base/markdown/parse/config.jl | 2 +- base/mpfr.jl | 2 +- base/operators.jl | 2 +- base/rational.jl | 44 +++++++++---------- base/special/trig.jl | 16 +++---- 14 files changed, 101 insertions(+), 101 deletions(-) diff --git a/base/broadcast.jl b/base/broadcast.jl index c6dfb006e8f8e..f519ebb1cc01c 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -135,7 +135,7 @@ Base.@propagate_inbounds _broadcast_getindex(::Any, A, I) = A[I] ## Broadcasting core # nargs encodes the number of As arguments (which matches the number # of keeps). The first two type parameters are to ensure specialization. -@generated function _broadcast!{K,ID,AT,BT,N}(f, B::AbstractArray, keeps::K, Idefaults::ID, A::AT, Bs::BT, ::Type{Val{N}}, iter) +@generated function _broadcast!(f, B::AbstractArray, keeps::K, Idefaults::ID, A::AT, Bs::BT, ::Type{Val{N}}, iter) where {K,ID,AT,BT,N} nargs = N + 1 quote $(Expr(:meta, :inline)) @@ -158,7 +158,7 @@ end # For BitArray outputs, we cache the result in a "small" Vector{Bool}, # and then copy in chunks into the output -@generated function _broadcast!{K,ID,AT,BT,N}(f, B::BitArray, keeps::K, Idefaults::ID, A::AT, Bs::BT, ::Type{Val{N}}, iter) +@generated function _broadcast!(f, B::BitArray, keeps::K, Idefaults::ID, A::AT, Bs::BT, ::Type{Val{N}}, iter) where {K,ID,AT,BT,N} nargs = N + 1 quote $(Expr(:meta, :inline)) @@ -213,7 +213,7 @@ as in `broadcast!(f, A, A, B)` to perform `A[:] = broadcast(f, A, B)`. end # broadcast with computed element type -@generated function _broadcast!{K,ID,AT,nargs}(f, B::AbstractArray, keeps::K, Idefaults::ID, As::AT, ::Type{Val{nargs}}, iter, st, count) +@generated function _broadcast!(f, B::AbstractArray, keeps::K, Idefaults::ID, As::AT, ::Type{Val{nargs}}, iter, st, count) where {K,ID,AT,nargs} quote $(Expr(:meta, :noinline)) # destructure the keeps and As tuples @@ -262,7 +262,7 @@ function broadcast_t(f, ::Type{Any}, shape, iter, As...) B[I] = val return _broadcast!(f, B, keeps, Idefaults, As, Val{nargs}, iter, st, 1) end -@inline function broadcast_t{N}(f, T, shape, iter, A, Bs::Vararg{Any,N}) +@inline function broadcast_t(f, T, shape, iter, A, Bs::Vararg{Any,N}) where N C = similar(Array{T}, shape) keeps, Idefaults = map_newindexer(shape, A, Bs) _broadcast!(f, C, keeps, Idefaults, A, Bs, Val{N}, iter) @@ -273,7 +273,7 @@ end # in the common case where this is used for logical array indexing; in # performance-critical cases where Array{Bool} is desired, one can always # use broadcast! instead. -@inline function broadcast_t{N}(f, ::Type{Bool}, shape, iter, A, Bs::Vararg{Any,N}) +@inline function broadcast_t(f, ::Type{Bool}, shape, iter, A, Bs::Vararg{Any,N}) where N C = similar(BitArray, shape) keeps, Idefaults = map_newindexer(shape, A, Bs) _broadcast!(f, C, keeps, Idefaults, A, Bs, Val{N}, iter) diff --git a/base/checked.jl b/base/checked.jl index 37310d0a35e90..2ae2e3cc5e649 100644 --- a/base/checked.jl +++ b/base/checked.jl @@ -27,7 +27,7 @@ checked_cld(x::Integer, y::Integer) = checked_cld(promote(x,y)...) # fallback catchall rules to prevent infinite recursion if promotion succeeds, # but no method exists to handle those types -checked_abs{T<:Integer}(x::T) = no_op_err("checked_abs", T) +checked_abs(x::T) where {T<:Integer} = no_op_err("checked_abs", T) const SignedInt = Union{Int8,Int16,Int32,Int64,Int128} const UnsignedInt = Union{UInt8,UInt16,UInt32,UInt64,UInt128} @@ -87,7 +87,7 @@ represent `-typemin(Int)`, thus leading to an overflow. The overflow protection may impose a perceptible performance penalty. """ -function checked_neg{T<:Integer}(x::T) +function checked_neg(x::T) where T<:Integer checked_sub(T(0), x) end if BrokenSignedInt != Union{} @@ -98,7 +98,7 @@ function checked_neg(x::BrokenSignedInt) end end if BrokenUnsignedInt != Union{} -function checked_neg{T<:BrokenUnsignedInt}(x::T) +function checked_neg(x::T) where T<:BrokenUnsignedInt x != 0 && throw(OverflowError()) T(0) end @@ -131,12 +131,12 @@ checked_abs(x::Bool) = x Calculates `r = x+y`, with the flag `f` indicating whether overflow has occurred. """ function add_with_overflow end -add_with_overflow{T<:SignedInt}(x::T, y::T) = checked_sadd_int(x, y) -add_with_overflow{T<:UnsignedInt}(x::T, y::T) = checked_uadd_int(x, y) -add_with_overflow(x::Bool, y::Bool) = x+y, false +add_with_overflow(x::T, y::T) where {T<:SignedInt} = checked_sadd_int(x, y) +add_with_overflow(x::T, y::T) where {T<:UnsignedInt} = checked_uadd_int(x, y) +add_with_overflow(x::Bool, y::Bool) = (x+y, false) if BrokenSignedInt != Union{} -function add_with_overflow{T<:BrokenSignedInt}(x::T, y::T) +function add_with_overflow(x::T, y::T) where T<:BrokenSignedInt r = x + y # x and y have the same sign, and the result has a different sign f = (x<0) == (y<0) != (r<0) @@ -144,7 +144,7 @@ function add_with_overflow{T<:BrokenSignedInt}(x::T, y::T) end end if BrokenUnsignedInt != Union{} -function add_with_overflow{T<:BrokenUnsignedInt}(x::T, y::T) +function add_with_overflow(x::T, y::T) where T<:BrokenUnsignedInt # x + y > typemax(T) # Note: ~y == -y-1 x + y, x > ~y @@ -159,7 +159,7 @@ Calculates `x+y`, checking for overflow errors where applicable. The overflow protection may impose a perceptible performance penalty. """ -function checked_add{T<:Integer}(x::T, y::T) +function checked_add(x::T, y::T) where T<:Integer @_inline_meta z, b = add_with_overflow(x, y) b && throw(OverflowError()) @@ -170,17 +170,17 @@ end checked_add(x) = x checked_add(x::Bool) = +x -checked_add{T}(x1::T, x2::T, x3::T) = +checked_add(x1::T, x2::T, x3::T) where {T} = checked_add(checked_add(x1, x2), x3) -checked_add{T}(x1::T, x2::T, x3::T, x4::T) = +checked_add(x1::T, x2::T, x3::T, x4::T) where {T} = checked_add(checked_add(x1, x2), x3, x4) -checked_add{T}(x1::T, x2::T, x3::T, x4::T, x5::T) = +checked_add(x1::T, x2::T, x3::T, x4::T, x5::T) where {T} = checked_add(checked_add(x1, x2), x3, x4, x5) -checked_add{T}(x1::T, x2::T, x3::T, x4::T, x5::T, x6::T) = +checked_add(x1::T, x2::T, x3::T, x4::T, x5::T, x6::T) where {T} = checked_add(checked_add(x1, x2), x3, x4, x5, x6) -checked_add{T}(x1::T, x2::T, x3::T, x4::T, x5::T, x6::T, x7::T) = +checked_add(x1::T, x2::T, x3::T, x4::T, x5::T, x6::T, x7::T) where {T} = checked_add(checked_add(x1, x2), x3, x4, x5, x6, x7) -checked_add{T}(x1::T, x2::T, x3::T, x4::T, x5::T, x6::T, x7::T, x8::T) = +checked_add(x1::T, x2::T, x3::T, x4::T, x5::T, x6::T, x7::T, x8::T) where {T} = checked_add(checked_add(x1, x2), x3, x4, x5, x6, x7, x8) @@ -190,12 +190,12 @@ checked_add{T}(x1::T, x2::T, x3::T, x4::T, x5::T, x6::T, x7::T, x8::T) = Calculates `r = x-y`, with the flag `f` indicating whether overflow has occurred. """ function sub_with_overflow end -sub_with_overflow{T<:SignedInt}(x::T, y::T) = checked_ssub_int(x, y) -sub_with_overflow{T<:UnsignedInt}(x::T, y::T) = checked_usub_int(x, y) -sub_with_overflow(x::Bool, y::Bool) = x-y, false +sub_with_overflow(x::T, y::T) where {T<:SignedInt} = checked_ssub_int(x, y) +sub_with_overflow(x::T, y::T) where {T<:UnsignedInt} = checked_usub_int(x, y) +sub_with_overflow(x::Bool, y::Bool) = (x-y, false) if BrokenSignedInt != Union{} -function sub_with_overflow{T<:BrokenSignedInt}(x::T, y::T) +function sub_with_overflow(x::T, y::T) where T<:BrokenSignedInt r = x - y # x and y have different signs, and the result has a different sign than x f = (x<0) != (y<0) == (r<0) @@ -203,7 +203,7 @@ function sub_with_overflow{T<:BrokenSignedInt}(x::T, y::T) end end if BrokenUnsignedInt != Union{} -function sub_with_overflow{T<:BrokenUnsignedInt}(x::T, y::T) +function sub_with_overflow(x::T, y::T) where T<:BrokenUnsignedInt # x - y < 0 x - y, x < y end @@ -216,7 +216,7 @@ Calculates `x-y`, checking for overflow errors where applicable. The overflow protection may impose a perceptible performance penalty. """ -function checked_sub{T<:Integer}(x::T, y::T) +function checked_sub(x::T, y::T) where T<:Integer @_inline_meta z, b = sub_with_overflow(x, y) b && throw(OverflowError()) @@ -230,19 +230,19 @@ end Calculates `r = x*y`, with the flag `f` indicating whether overflow has occurred. """ function mul_with_overflow end -mul_with_overflow{T<:SignedInt}(x::T, y::T) = checked_smul_int(x, y) -mul_with_overflow{T<:UnsignedInt}(x::T, y::T) = checked_umul_int(x, y) -mul_with_overflow(x::Bool, y::Bool) = x*y, false +mul_with_overflow(x::T, y::T) where {T<:SignedInt} = checked_smul_int(x, y) +mul_with_overflow(x::T, y::T) where {T<:UnsignedInt} = checked_umul_int(x, y) +mul_with_overflow(x::Bool, y::Bool) = (x*y, false) if BrokenSignedIntMul != Union{} && BrokenSignedIntMul != Int128 -function mul_with_overflow{T<:BrokenSignedIntMul}(x::T, y::T) +function mul_with_overflow(x::T, y::T) where T<:BrokenSignedIntMul r = widemul(x, y) f = r % T != r r % T, f end end if BrokenUnsignedIntMul != Union{} && BrokenUnsignedIntMul != UInt128 -function mul_with_overflow{T<:BrokenUnsignedIntMul}(x::T, y::T) +function mul_with_overflow(x::T, y::T) where T<:BrokenUnsignedIntMul r = widemul(x, y) f = r % T != r r % T, f @@ -250,7 +250,7 @@ end end if Int128 <: BrokenSignedIntMul # Avoid BigInt - function mul_with_overflow{T<:Int128}(x::T, y::T) + function mul_with_overflow(x::T, y::T) where T<:Int128 f = if y > 0 # x * y > typemax(T) # x * y < typemin(T) @@ -268,7 +268,7 @@ if Int128 <: BrokenSignedIntMul end if UInt128 <: BrokenUnsignedIntMul # Avoid BigInt - function mul_with_overflow{T<:UInt128}(x::T, y::T) + function mul_with_overflow(x::T, y::T) where T<:UInt128 # x * y > typemax(T) x * y, y > 0 && x > fld(typemax(T), y) end @@ -281,7 +281,7 @@ Calculates `x*y`, checking for overflow errors where applicable. The overflow protection may impose a perceptible performance penalty. """ -function checked_mul{T<:Integer}(x::T, y::T) +function checked_mul(x::T, y::T) where T<:Integer @_inline_meta z, b = mul_with_overflow(x, y) b && throw(OverflowError()) @@ -290,17 +290,17 @@ end # Handle multiple arguments checked_mul(x) = x -checked_mul{T}(x1::T, x2::T, x3::T) = +checked_mul(x1::T, x2::T, x3::T) where {T} = checked_mul(checked_mul(x1, x2), x3) -checked_mul{T}(x1::T, x2::T, x3::T, x4::T) = +checked_mul(x1::T, x2::T, x3::T, x4::T) where {T} = checked_mul(checked_mul(x1, x2), x3, x4) -checked_mul{T}(x1::T, x2::T, x3::T, x4::T, x5::T) = +checked_mul(x1::T, x2::T, x3::T, x4::T, x5::T) where {T} = checked_mul(checked_mul(x1, x2), x3, x4, x5) -checked_mul{T}(x1::T, x2::T, x3::T, x4::T, x5::T, x6::T) = +checked_mul(x1::T, x2::T, x3::T, x4::T, x5::T, x6::T) where {T} = checked_mul(checked_mul(x1, x2), x3, x4, x5, x6) -checked_mul{T}(x1::T, x2::T, x3::T, x4::T, x5::T, x6::T, x7::T) = +checked_mul(x1::T, x2::T, x3::T, x4::T, x5::T, x6::T, x7::T) where {T} = checked_mul(checked_mul(x1, x2), x3, x4, x5, x6, x7) -checked_mul{T}(x1::T, x2::T, x3::T, x4::T, x5::T, x6::T, x7::T, x8::T) = +checked_mul(x1::T, x2::T, x3::T, x4::T, x5::T, x6::T, x7::T, x8::T) where {T} = checked_mul(checked_mul(x1, x2), x3, x4, x5, x6, x7, x8) """ @@ -310,7 +310,7 @@ Calculates `div(x,y)`, checking for overflow errors where applicable. The overflow protection may impose a perceptible performance penalty. """ -checked_div{T<:Integer}(x::T, y::T) = div(x, y) # Base.div already checks +checked_div(x::T, y::T) where {T<:Integer} = div(x, y) # Base.div already checks """ Base.checked_rem(x, y) @@ -319,7 +319,7 @@ Calculates `x%y`, checking for overflow errors where applicable. The overflow protection may impose a perceptible performance penalty. """ -checked_rem{T<:Integer}(x::T, y::T) = rem(x, y) # Base.rem already checks +checked_rem(x::T, y::T) where {T<:Integer} = rem(x, y) # Base.rem already checks """ Base.checked_fld(x, y) @@ -328,7 +328,7 @@ Calculates `fld(x,y)`, checking for overflow errors where applicable. The overflow protection may impose a perceptible performance penalty. """ -checked_fld{T<:Integer}(x::T, y::T) = fld(x, y) # Base.fld already checks +checked_fld(x::T, y::T) where {T<:Integer} = fld(x, y) # Base.fld already checks """ Base.checked_mod(x, y) @@ -337,7 +337,7 @@ Calculates `mod(x,y)`, checking for overflow errors where applicable. The overflow protection may impose a perceptible performance penalty. """ -checked_mod{T<:Integer}(x::T, y::T) = mod(x, y) # Base.mod already checks +checked_mod(x::T, y::T) where {T<:Integer} = mod(x, y) # Base.mod already checks """ Base.checked_cld(x, y) @@ -346,6 +346,6 @@ Calculates `cld(x,y)`, checking for overflow errors where applicable. The overflow protection may impose a perceptible performance penalty. """ -checked_cld{T<:Integer}(x::T, y::T) = cld(x, y) # Base.cld already checks +checked_cld(x::T, y::T) where {T<:Integer} = cld(x, y) # Base.cld already checks end diff --git a/base/complex.jl b/base/complex.jl index eb27aeff7b7fa..0e9df4b8f7038 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -31,7 +31,7 @@ promote_rule(::Type{Complex{T}}, ::Type{S}) where {T<:Real,S<:Real} = promote_rule(::Type{Complex{T}}, ::Type{Complex{S}}) where {T<:Real,S<:Real} = Complex{promote_type(T,S)} -widen{T}(::Type{Complex{T}}) = Complex{widen(T)} +widen(::Type{Complex{T}}) where {T} = Complex{widen(T)} """ real(z) @@ -134,8 +134,8 @@ julia> complex(Int) Complex{Int64} ``` """ -complex{T<:Real}(::Type{T}) = Complex{T} -complex{T<:Real}(::Type{Complex{T}}) = Complex{T} +complex(::Type{T}) where {T<:Real} = Complex{T} +complex(::Type{Complex{T}}) where {T<:Real} = Complex{T} flipsign(x::Complex, y::Real) = ifelse(signbit(y), -x, x) @@ -589,13 +589,13 @@ function ^(z::Complex{T}, p::Complex{T})::Complex{T} where T<:AbstractFloat end end -function exp2{T}(z::Complex{T}) +function exp2(z::Complex{T}) where T er = exp2(real(z)) theta = imag(z) * log(convert(T, 2)) Complex(er*cos(theta), er*sin(theta)) end -function exp10{T}(z::Complex{T}) +function exp10(z::Complex{T}) where T er = exp10(real(z)) theta = imag(z) * log(convert(T, 10)) Complex(er*cos(theta), er*sin(theta)) @@ -669,7 +669,7 @@ end n>=0 ? power_by_squaring(z,n) : power_by_squaring(inv(z),-n) ^(z::Complex{<:Integer}, n::Integer) = power_by_squaring(z,n) # DomainError for n<0 -function sin{T}(z::Complex{T}) +function sin(z::Complex{T}) where T F = float(T) zr, zi = reim(z) if zr == 0 @@ -686,7 +686,7 @@ function sin{T}(z::Complex{T}) end -function cos{T}(z::Complex{T}) +function cos(z::Complex{T}) where T F = float(T) zr, zi = reim(z) if zr == 0 @@ -764,7 +764,7 @@ function cosh(z::Complex) cos(Complex(zi,-zr)) end -function tanh{T<:AbstractFloat}(z::Complex{T}) +function tanh(z::Complex{T}) where T<:AbstractFloat const Ω = prevfloat(typemax(T)) ξ, η = reim(z) if isnan(ξ) && η==0 return Complex(ξ, η) end @@ -809,7 +809,7 @@ function acosh(z::Complex) Complex(ξ, η) end -function atanh{T<:AbstractFloat}(z::Complex{T}) +function atanh(z::Complex{T}) where T<:AbstractFloat const Ω = prevfloat(typemax(T)) const θ = sqrt(Ω)/4 const ρ = 1/θ @@ -866,7 +866,7 @@ breaking ties using the specified [`RoundingMode`](@ref)s. The first [`RoundingMode`](@ref) is used for rounding the real components while the second is used for rounding the imaginary components. """ -function round{MR, MI}(z::Complex{<:AbstractFloat}, ::RoundingMode{MR}, ::RoundingMode{MI}) +function round(z::Complex{<:AbstractFloat}, ::RoundingMode{MR}, ::RoundingMode{MI}) where {MR,MI} Complex(round(real(z), RoundingMode{MR}()), round(imag(z), RoundingMode{MI}())) end @@ -887,7 +887,7 @@ big(z::Complex{<:Integer}) = Complex{BigInt}(z) complex(A::AbstractArray{<:Complex}) = A -function complex{T}(A::AbstractArray{T}) +function complex(A::AbstractArray{T}) where T if !isleaftype(T) error("`complex` not defined on abstractly-typed arrays; please convert to a more specific type") end diff --git a/base/dict.jl b/base/dict.jl index bfe6ca4322a73..67e6ba23c4f0f 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -213,7 +213,7 @@ isslotempty(h::Dict, i::Int) = h.slots[i] == 0x0 isslotfilled(h::Dict, i::Int) = h.slots[i] == 0x1 isslotmissing(h::Dict, i::Int) = h.slots[i] == 0x2 -function rehash!{K,V}(h::Dict{K,V}, newsz = length(h.keys)) +function rehash!(h::Dict{K,V}, newsz = length(h.keys)) where V where K olds = h.slots oldk = h.keys oldv = h.vals diff --git a/base/fastmath.jl b/base/fastmath.jl index 7d51eba54a6d4..39c6ac7b4637f 100644 --- a/base/fastmath.jl +++ b/base/fastmath.jl @@ -274,7 +274,7 @@ atan2_fast(x::Float64, y::Float64) = # explicit implementations @fastmath begin - exp10_fast{T<:FloatTypes}(x::T) = exp2(log2(T(10))*x) + exp10_fast(x::T) where {T<:FloatTypes} = exp2(log2(T(10))*x) exp10_fast(x::Integer) = exp10(float(x)) hypot_fast{T<:FloatTypes}(x::T, y::T) = sqrt(x*x + y*y) @@ -293,20 +293,20 @@ atan2_fast(x::Float64, y::Float64) = pow_fast{T<:ComplexTypes}(x::T, y::T) = exp(y*log(x)) pow_fast{T<:FloatTypes}(x::T, y::Complex{T}) = exp(y*log(x)) pow_fast{T<:FloatTypes}(x::Complex{T}, y::T) = exp(y*log(x)) - acos_fast{T<:ComplexTypes}(x::T) = + acos_fast(x::T) where {T<:ComplexTypes} = convert(T,π)/2 + im*log(im*x + sqrt(1-x*x)) acosh_fast(x::ComplexTypes) = log(x + sqrt(x+1) * sqrt(x-1)) angle_fast(x::ComplexTypes) = atan2(imag(x), real(x)) asin_fast(x::ComplexTypes) = -im*asinh(im*x) asinh_fast(x::ComplexTypes) = log(x + sqrt(1+x*x)) atan_fast(x::ComplexTypes) = -im*atanh(im*x) - atanh_fast{T<:ComplexTypes}(x::T) = convert(T,1)/2*(log(1+x) - log(1-x)) + atanh_fast(x::T) where {T<:ComplexTypes} = convert(T,1)/2*(log(1+x) - log(1-x)) cis_fast(x::ComplexTypes) = exp(-imag(x)) * cis(real(x)) cos_fast(x::ComplexTypes) = cosh(im*x) - cosh_fast{T<:ComplexTypes}(x::T) = convert(T,1)/2*(exp(x) + exp(-x)) - exp10_fast{T<:ComplexTypes}(x::T) = + cosh_fast(x::T) where {T<:ComplexTypes} = convert(T,1)/2*(exp(x) + exp(-x)) + exp10_fast(x::T) where {T<:ComplexTypes} = exp10(real(x)) * cis(imag(x)*log(convert(T,10))) - exp2_fast{T<:ComplexTypes}(x::T) = + exp2_fast(x::T) where {T<:ComplexTypes} = exp2(real(x)) * cis(imag(x)*log(convert(T,2))) exp_fast(x::ComplexTypes) = exp(real(x)) * cis(imag(x)) expm1_fast(x::ComplexTypes) = exp(x)-1 @@ -315,7 +315,7 @@ atan2_fast(x::Float64, y::Float64) = log2_fast{T<:ComplexTypes}(x::T) = log(x) / log(convert(T,2)) log_fast{T<:ComplexTypes}(x::T) = T(log(abs2(x))/2, angle(x)) sin_fast(x::ComplexTypes) = -im*sinh(im*x) - sinh_fast{T<:ComplexTypes}(x::T) = convert(T,1)/2*(exp(x) - exp(-x)) + sinh_fast(x::T) where {T<:ComplexTypes} = convert(T,1)/2*(exp(x) - exp(-x)) sqrt_fast(x::ComplexTypes) = sqrt(abs(x)) * cis(angle(x)/2) tan_fast(x::ComplexTypes) = -im*tanh(im*x) tanh_fast(x::ComplexTypes) = (a=exp(x); b=exp(-x); (a-b)/(a+b)) diff --git a/base/fft/FFTW.jl b/base/fft/FFTW.jl index bcf93a7e05a80..34b57d06c0c31 100644 --- a/base/fft/FFTW.jl +++ b/base/fft/FFTW.jl @@ -578,7 +578,7 @@ end # Convert arrays of numeric types to FFTW-supported packed complex-float types # (FIXME: is there a way to use the Julia promotion rules more cleverly here?) fftwcomplex(X::StridedArray{<:fftwComplex}) = X -fftwcomplex{T<:fftwReal}(X::AbstractArray{T}) = +fftwcomplex(X::AbstractArray{T}) where {T<:fftwReal} = copy!(Array{typeof(complex(zero(T)))}(size(X)), X) fftwcomplex(X::AbstractArray{<:Real}) = copy!(Array{Complex128}(size(X)),X) fftwcomplex(X::AbstractArray{<:Complex}) = copy!(Array{Complex128}(size(X)), X) diff --git a/base/grisu/float.jl b/base/grisu/float.jl index 24073c5c3a4cf..4581b8bb2ccea 100644 --- a/base/grisu/float.jl +++ b/base/grisu/float.jl @@ -104,7 +104,7 @@ SignificandMask(::Type{Float16}) = 0x03ff HiddenBit(::Type{Float16}) = 0x0400 uint_t(d::Float16) = reinterpret(UInt16,d) -function _exponent{T<:AbstractFloat}(d::T) +function _exponent(d::T) where T<:AbstractFloat isdenormal(d) && return DenormalExponent(T) biased_e::Int32 = Int32((uint_t(d) & ExponentMask(T)) >> PhysicalSignificandSize(T)) return Int32(biased_e - ExponentBias(T)) diff --git a/base/linalg/dense.jl b/base/linalg/dense.jl index 6b37b15a212b6..4cf1e819ae334 100644 --- a/base/linalg/dense.jl +++ b/base/linalg/dense.jl @@ -372,7 +372,7 @@ expm(x::Number) = exp(x) ## Destructive matrix exponential using algorithm from Higham, 2008, ## "Functions of Matrices: Theory and Computation", SIAM -function expm!{T<:BlasFloat}(A::StridedMatrix{T}) +function expm!(A::StridedMatrix{T}) where T<:BlasFloat n = checksquare(A) if ishermitian(A) return full(expm(Hermitian(A))) diff --git a/base/linalg/symmetric.jl b/base/linalg/symmetric.jl index 2278afa943cd7..88eb2c73e4621 100644 --- a/base/linalg/symmetric.jl +++ b/base/linalg/symmetric.jl @@ -408,7 +408,7 @@ function expm(A::Symmetric) F = eigfact(A) return Symmetric((F.vectors * Diagonal(exp.(F.values))) * F.vectors') end -function expm{T}(A::Hermitian{T}) +function expm(A::Hermitian{T}) where T n = checksquare(A) F = eigfact(A) retmat = (F.vectors * Diagonal(exp.(F.values))) * F.vectors' diff --git a/base/markdown/parse/config.jl b/base/markdown/parse/config.jl index 0defc1f1fac08..eb44d311c74a6 100644 --- a/base/markdown/parse/config.jl +++ b/base/markdown/parse/config.jl @@ -25,7 +25,7 @@ triggers(f) = get(meta(f), :triggers, Set{Char}()) # Macros isexpr(x::Expr, ts...) = x.head in ts -isexpr{T}(x::T, ts...) = T in ts +isexpr(x::T, ts...) where {T} = T in ts macro breaking(ex) isexpr(ex, :->) || error("invalid @breaking form, use ->") diff --git a/base/mpfr.jl b/base/mpfr.jl index 0a80427c20b2c..3dd414f7b1293 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -201,7 +201,7 @@ function ceil{T<:Union{Signed,Unsigned}}(::Type{T}, x::BigFloat) unsafe_cast(T,x,RoundUp) end -function round{T<:Union{Signed,Unsigned}}(::Type{T}, x::BigFloat) +function round(::Type{T}, x::BigFloat) where T<:Union{Signed,Unsigned} (typemin(T) <= x <= typemax(T)) || throw(InexactError()) unsafe_cast(T,x,ROUNDING_MODE[]) end diff --git a/base/operators.jl b/base/operators.jl index b6ea643d310fd..dad670c8678d1 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -840,7 +840,7 @@ For matrices or vectors ``A`` and ``B``, calculates ``Aᴴ`` \\ ``Bᵀ``. """ Ac_ldiv_Bt(a,b) = Ac_ldiv_B(a,transpose(b)) -widen{T<:Number}(x::T) = convert(widen(T), x) +widen(x::T) where {T<:Number} = convert(widen(T), x) # function pipelining diff --git a/base/rational.jl b/base/rational.jl index fa13a8e14e980..9c26565744424 100644 --- a/base/rational.jl +++ b/base/rational.jl @@ -60,7 +60,7 @@ function show(io::IO, x::Rational) show(io, denominator(x)) end -function read{T<:Integer}(s::IO, ::Type{Rational{T}}) +function read(s::IO, ::Type{Rational{T}}) where T<:Integer r = read(s,T) i = read(s,T) r//i @@ -99,7 +99,7 @@ promote_rule(::Type{Rational{T}}, ::Type{S}) where {T<:Integer,S<:Integer} = Rat promote_rule(::Type{Rational{T}}, ::Type{Rational{S}}) where {T<:Integer,S<:Integer} = Rational{promote_type(T,S)} promote_rule(::Type{Rational{T}}, ::Type{S}) where {T<:Integer,S<:AbstractFloat} = promote_type(T,S) -widen{T}(::Type{Rational{T}}) = Rational{widen(T)} +widen(::Type{Rational{T}}) where {T} = Rational{widen(T)} """ rationalize([T<:Integer=Int,] x; tol::Real=eps(x)) @@ -119,7 +119,7 @@ julia> typeof(numerator(a)) BigInt ``` """ -function rationalize{T<:Integer}(::Type{T}, x::AbstractFloat, tol::Real) +function rationalize(::Type{T}, x::AbstractFloat, tol::Real) where T<:Integer if tol < 0 throw(ArgumentError("negative tolerance $tol")) end @@ -178,7 +178,7 @@ function rationalize{T<:Integer}(::Type{T}, x::AbstractFloat, tol::Real) return p // q end end -rationalize{T<:Integer}(::Type{T}, x::AbstractFloat; tol::Real=eps(x)) = rationalize(T, x, tol)::Rational{T} +rationalize(::Type{T}, x::AbstractFloat; tol::Real = eps(x)) where {T<:Integer} = rationalize(T, x, tol)::Rational{T} rationalize(x::AbstractFloat; kvs...) = rationalize(Int, x; kvs...) """ @@ -218,8 +218,8 @@ signbit(x::Rational) = signbit(x.num) copysign(x::Rational, y::Real) = copysign(x.num,y) // x.den copysign(x::Rational, y::Rational) = copysign(x.num,y.num) // x.den -typemin{T<:Integer}(::Type{Rational{T}}) = -one(T)//zero(T) -typemax{T<:Integer}(::Type{Rational{T}}) = one(T)//zero(T) +typemin(::Type{Rational{T}}) where {T<:Integer} = -one(T)//zero(T) +typemax(::Type{Rational{T}}) where {T<:Integer} = one(T)//zero(T) isinteger(x::Rational) = x.den == 1 @@ -345,12 +345,12 @@ for op in (:div, :fld, :cld) end end -trunc{T}(::Type{T}, x::Rational) = convert(T,div(x.num,x.den)) -floor{T}(::Type{T}, x::Rational) = convert(T,fld(x.num,x.den)) -ceil{ T}(::Type{T}, x::Rational) = convert(T,cld(x.num,x.den)) +trunc(::Type{T}, x::Rational) where {T} = convert(T,div(x.num,x.den)) +floor(::Type{T}, x::Rational) where {T} = convert(T,fld(x.num,x.den)) +ceil(::Type{T}, x::Rational) where {T} = convert(T,cld(x.num,x.den)) -function round{T, Tr}(::Type{T}, x::Rational{Tr}, ::RoundingMode{:Nearest}) +function round(::Type{T}, x::Rational{Tr}, ::RoundingMode{:Nearest}) where {T,Tr} if denominator(x) == zero(Tr) && T <: Integer throw(DivideError()) elseif denominator(x) == zero(Tr) @@ -364,9 +364,9 @@ function round{T, Tr}(::Type{T}, x::Rational{Tr}, ::RoundingMode{:Nearest}) convert(T, s) end -round{T}(::Type{T}, x::Rational) = round(T, x, RoundNearest) +round(::Type{T}, x::Rational) where {T} = round(T, x, RoundNearest) -function round{T, Tr}(::Type{T}, x::Rational{Tr}, ::RoundingMode{:NearestTiesAway}) +function round(::Type{T}, x::Rational{Tr}, ::RoundingMode{:NearestTiesAway}) where {T,Tr} if denominator(x) == zero(Tr) && T <: Integer throw(DivideError()) elseif denominator(x) == zero(Tr) @@ -380,7 +380,7 @@ function round{T, Tr}(::Type{T}, x::Rational{Tr}, ::RoundingMode{:NearestTiesAwa convert(T, s) end -function round{T, Tr}(::Type{T}, x::Rational{Tr}, ::RoundingMode{:NearestTiesUp}) +function round(::Type{T}, x::Rational{Tr}, ::RoundingMode{:NearestTiesUp}) where {T,Tr} if denominator(x) == zero(Tr) && T <: Integer throw(DivideError()) elseif denominator(x) == zero(Tr) @@ -394,22 +394,22 @@ function round{T, Tr}(::Type{T}, x::Rational{Tr}, ::RoundingMode{:NearestTiesUp} convert(T, s) end -function round{T}(::Type{T}, x::Rational{Bool}) +function round(::Type{T}, x::Rational{Bool}) where T if denominator(x) == false && issubtype(T, Union{Integer, Bool}) throw(DivideError()) end convert(T, x) end -round{T}(::Type{T}, x::Rational{Bool}, ::RoundingMode{:Nearest}) = round(T, x) -round{T}(::Type{T}, x::Rational{Bool}, ::RoundingMode{:NearestTiesAway}) = round(T, x) -round{T}(::Type{T}, x::Rational{Bool}, ::RoundingMode{:NearestTiesUp}) = round(T, x) -round{T}(::Type{T}, x::Rational{Bool}, ::RoundingMode) = round(T, x) +round(::Type{T}, x::Rational{Bool}, ::RoundingMode{:Nearest}) where {T} = round(T, x) +round(::Type{T}, x::Rational{Bool}, ::RoundingMode{:NearestTiesAway}) where {T} = round(T, x) +round(::Type{T}, x::Rational{Bool}, ::RoundingMode{:NearestTiesUp}) where {T} = round(T, x) +round(::Type{T}, x::Rational{Bool}, ::RoundingMode) where {T} = round(T, x) -trunc{T}(x::Rational{T}) = Rational(trunc(T,x)) -floor{T}(x::Rational{T}) = Rational(floor(T,x)) -ceil{ T}(x::Rational{T}) = Rational(ceil(T,x)) -round{T}(x::Rational{T}) = Rational(round(T,x)) +trunc(x::Rational{T}) where {T} = Rational(trunc(T,x)) +floor(x::Rational{T}) where {T} = Rational(floor(T,x)) +ceil(x::Rational{T}) where {T} = Rational(ceil(T,x)) +round(x::Rational{T}) where {T} = Rational(round(T,x)) function ^(x::Rational, n::Integer) n >= 0 ? power_by_squaring(x,n) : power_by_squaring(inv(x),-n) diff --git a/base/special/trig.jl b/base/special/trig.jl index 80a0d9073bf61..95b33529a3ca6 100644 --- a/base/special/trig.jl +++ b/base/special/trig.jl @@ -103,7 +103,7 @@ mulpi_ext(x::Real) = pi*x # Fallback Compute ``\\sin(\\pi x)`` more accurately than `sin(pi*x)`, especially for large `x`. """ -function sinpi{T<:AbstractFloat}(x::T) +function sinpi(x::T) where T<:AbstractFloat if !isfinite(x) isnan(x) && return x throw(DomainError()) @@ -133,7 +133,7 @@ function sinpi{T<:AbstractFloat}(x::T) end # Rationals and other Real types -function sinpi{T<:Real}(x::T) +function sinpi(x::T) where T<:Real Tf = typeof(float(x)) if !isfinite(x) throw(DomainError()) @@ -166,7 +166,7 @@ end Compute ``\\cos(\\pi x)`` more accurately than `cos(pi*x)`, especially for large `x`. """ -function cospi{T<:AbstractFloat}(x::T) +function cospi(x::T) where T<:AbstractFloat if !isfinite(x) isnan(x) && return x throw(DomainError()) @@ -192,7 +192,7 @@ function cospi{T<:AbstractFloat}(x::T) end # Rationals and other Real types -function cospi{T<:Real}(x::T) +function cospi(x::T) where T<:Real if !isfinite(x) throw(DomainError()) end @@ -218,7 +218,7 @@ end sinpi(x::Integer) = x >= 0 ? zero(float(x)) : -zero(float(x)) cospi(x::Integer) = isodd(x) ? -one(float(x)) : one(float(x)) -function sinpi{T}(z::Complex{T}) +function sinpi(z::Complex{T}) where T F = float(T) zr, zi = reim(z) if isinteger(zr) @@ -250,7 +250,7 @@ function sinpi{T}(z::Complex{T}) end end -function cospi{T}(z::Complex{T}) +function cospi(z::Complex{T}) where T F = float(T) zr, zi = reim(z) if isinteger(zr) @@ -292,7 +292,7 @@ Compute ``\\sin(\\pi x) / (\\pi x)`` if ``x \\neq 0``, and ``1`` if ``x = 0``. """ sinc(x::Number) = x==0 ? one(x) : oftype(x,sinpi(x)/(pi*x)) sinc(x::Integer) = x==0 ? one(x) : zero(x) -sinc{T<:Integer}(x::Complex{T}) = sinc(float(x)) +sinc(x::Complex{T}) where {T<:Integer} = sinc(float(x)) sinc(x::Real) = x==0 ? one(x) : isinf(x) ? zero(x) : sinpi(x)/(pi*x) """ @@ -303,7 +303,7 @@ Compute ``\\cos(\\pi x) / x - \\sin(\\pi x) / (\\pi x^2)`` if ``x \\neq 0``, and """ cosc(x::Number) = x==0 ? zero(x) : oftype(x,(cospi(x)-sinpi(x)/(pi*x))/x) cosc(x::Integer) = cosc(float(x)) -cosc{T<:Integer}(x::Complex{T}) = cosc(float(x)) +cosc(x::Complex{T}) where {T<:Integer} = cosc(float(x)) cosc(x::Real) = x==0 || isinf(x) ? zero(x) : (cospi(x)-sinpi(x)/(pi*x))/x for (finv, f) in ((:sec, :cos), (:csc, :sin), (:cot, :tan), From 011810a5fb028b06c0adc30a25972a5ef1aeaeb8 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 21 Apr 2017 15:10:08 -0400 Subject: [PATCH 0525/1534] fix use-after-free race code in uv_write wrapper/callback --- base/stream.jl | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/base/stream.jl b/base/stream.jl index aba3457df55cb..af03c678ea9b7 100644 --- a/base/stream.jl +++ b/base/stream.jl @@ -794,7 +794,7 @@ uv_write(s::LibuvStream, p::Vector{UInt8}) = uv_write(s, pointer(p), UInt(sizeof function uv_write(s::LibuvStream, p::Ptr{UInt8}, n::UInt) check_open(s) uvw = Libc.malloc(_sizeof_uv_write) - uv_req_set_data(uvw, C_NULL) + uv_req_set_data(uvw, C_NULL) # in case we get interrupted before arriving at the wait call err = ccall(:jl_uv_write, Int32, (Ptr{Void}, Ptr{Void}, UInt, Ptr{Void}, Ptr{Void}), @@ -806,11 +806,18 @@ function uv_write(s::LibuvStream, p::Ptr{UInt8}, n::UInt) end ct = current_task() preserve_handle(ct) - uv_req_set_data(uvw, ct) try + uv_req_set_data(uvw, ct) wait() finally - uv_req_set_data(uvw, C_NULL) # make sure we don't get spurious notifications later if the wait failed + if uv_req_data(uvw) != C_NULL + # uvw is still alive, + # so make sure we don't get spurious notifications later + uv_req_set_data(uvw, C_NULL) + else + # done with uvw + Libc.free(uvw) + end unpreserve_handle(ct) end return Int(n) @@ -861,14 +868,17 @@ write(s::LibuvStream, b::UInt8) = write(s, Ref{UInt8}(b)) function uv_writecb_task(req::Ptr{Void}, status::Cint) d = uv_req_data(req) if d != C_NULL + uv_req_set_data(req, C_NULL) if status < 0 - err = UVError("write",status) - schedule(unsafe_pointer_to_objref(d)::Task,err,error=true) + err = UVError("write", status) + schedule(unsafe_pointer_to_objref(d)::Task, err, error=true) else schedule(unsafe_pointer_to_objref(d)::Task) end + else + # no owner for this req, safe to just free it + Libc.free(req) end - Libc.free(req) nothing end From bc9012250a423145d61170ba627ba9642fae2f21 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 17 Apr 2017 20:22:41 -0400 Subject: [PATCH 0526/1534] try to bring some sanity to the embedding makefile we'll still want to eventually decide how to make julia-config.jl output correct relative rpaths but this should at least get `make -C embedding' working correctly --- .travis.yml | 18 +++++++-- Make.inc | 1 - Makefile | 7 ++-- appveyor.yml | 4 +- base/Makefile | 1 - contrib/julia-config.jl | 58 +++++++++++----------------- contrib/windows/msys_build.sh | 2 +- examples/Makefile | 30 +++++--------- examples/embedding/.gitignore | 2 + examples/embedding/Makefile | 25 ++++++++---- examples/embedding/embedding-test.jl | 20 ++++++++++ test/embedding.jl | 14 ------- 12 files changed, 92 insertions(+), 90 deletions(-) create mode 100644 examples/embedding/.gitignore create mode 100644 examples/embedding/embedding-test.jl delete mode 100644 test/embedding.jl diff --git a/.travis.yml b/.travis.yml index 8c75dc224245f..07ca0927c7215 100644 --- a/.travis.yml +++ b/.travis.yml @@ -96,6 +96,7 @@ before_install: script: - echo BUILDOPTS=$BUILDOPTS - export BUILDOPTS + # compile / install dependencies - contrib/download_cmake.sh - make -C moreutils mispipe - make $BUILDOPTS -C base version_git.jl.phony @@ -113,6 +114,7 @@ script: cat deps.log; echo "-- end of deps build log -----------------------------------------------"; false; } + # compile / install Julia - make $BUILDOPTS NO_GIT=1 prefix=/tmp/julia install | moreutils/ts -s "%.s" - make $BUILDOPTS NO_GIT=1 build-stats - du -sk /tmp/julia/* @@ -121,16 +123,24 @@ script: install -pm755 usr/lib/lib${name}*.dylib* /tmp/julia/lib/julia/; done; fi - - make $BUILDOPTS NO_GIT=1 prefix=/tmp/julia -C examples - cd .. && mv julia julia2 + # run tests - /tmp/julia/bin/julia --precompiled=no -e 'true' && /tmp/julia/bin/julia-debug --precompiled=no -e 'true' - /tmp/julia/bin/julia -e 'versioninfo()' + - pushd /tmp/julia/share/julia/test - export JULIA_CPU_CORES=2 && export JULIA_TEST_MAXRSS_MB=600 && - cd /tmp/julia/share/julia/test && /tmp/julia/bin/julia --check-bounds=yes runtests.jl $TESTSTORUN && - /tmp/julia/bin/julia --check-bounds=yes runtests.jl libgit2-online download pkg embedding - - cd `dirname $TRAVIS_BUILD_DIR` && mv julia2 julia && + /tmp/julia/bin/julia --check-bounds=yes runtests.jl libgit2-online download pkg + - popd + # test that the embedding code works on our installation + - mkdir /tmp/embedding-test && + make check -C /tmp/julia/share/doc/julia/examples/embedding \ + JULIA="DYLD_FALLBACK_LIBRARY_PATH='$DYLD_FALLBACK_LIBRARY_PATH' /tmp/julia/bin/julia" \ + BIN=/tmp/embedding-test \ + "$(cd julia2 && make print-CC)" + # restore initial state and prepare for travis caching + - mv julia2 julia && rm -f julia/deps/scratch/libgit2-*/CMakeFiles/CMakeOutput.log # uncomment the following if failures are suspected to be due to the out-of-memory killer # - dmesg diff --git a/Make.inc b/Make.inc index 568582c425d06..0f185de08b67d 100644 --- a/Make.inc +++ b/Make.inc @@ -219,7 +219,6 @@ libdir_rel := $(shell $(JULIAHOME)/contrib/relative_path.sh $(bindir) $(libdir)) build_private_libdir_rel := $(shell $(JULIAHOME)/contrib/relative_path.sh $(build_bindir) $(build_private_libdir)) private_libdir_rel := $(shell $(JULIAHOME)/contrib/relative_path.sh $(bindir) $(private_libdir)) datarootdir_rel := $(shell $(JULIAHOME)/contrib/relative_path.sh $(bindir) $(datarootdir)) -libexecdir_rel := $(shell $(JULIAHOME)/contrib/relative_path.sh $(bindir) $(libexecdir)) docdir_rel := $(shell $(JULIAHOME)/contrib/relative_path.sh $(bindir) $(docdir)) sysconfdir_rel := $(shell $(JULIAHOME)/contrib/relative_path.sh $(bindir) $(sysconfdir)) includedir_rel := $(shell $(JULIAHOME)/contrib/relative_path.sh $(bindir) $(includedir)) diff --git a/Makefile b/Makefile index 59be4206adc1b..f2eff432666a5 100644 --- a/Makefile +++ b/Makefile @@ -64,12 +64,12 @@ clean-docdir: @-rm -fr $(abspath $(build_docdir)) $(build_prefix)/.examples: $(wildcard $(JULIAHOME)/examples/*.jl) \ - $(shell find $(JULIAHOME)/examples/clustermanager) + $(shell find $(JULIAHOME)/examples/clustermanager) \ + $(shell find $(JULIAHOME)/examples/embedding) @echo Copying in usr/share/doc/julia/examples @-rm -fr $(build_docdir)/examples @mkdir -p $(build_docdir)/examples @cp -R $(JULIAHOME)/examples/*.jl $(build_docdir)/examples/ - @cp -R $(JULIAHOME)/examples/Makefile $(build_docdir)/examples/ @cp -R $(JULIAHOME)/examples/clustermanager $(build_docdir)/examples/ @cp -R $(JULIAHOME)/examples/embedding $(build_docdir)/examples @echo 1 > $@ @@ -334,12 +334,11 @@ endef install: $(build_depsbindir)/stringreplace $(BUILDROOT)/doc/_build/html/en/index.html @$(MAKE) $(QUIET_MAKE) all - @for subdir in $(bindir) $(libexecdir) $(datarootdir)/julia/site/$(VERSDIR) $(docdir) $(man1dir) $(includedir)/julia $(libdir) $(private_libdir) $(sysconfdir); do \ + @for subdir in $(bindir) $(datarootdir)/julia/site/$(VERSDIR) $(docdir) $(man1dir) $(includedir)/julia $(libdir) $(private_libdir) $(sysconfdir); do \ mkdir -p $(DESTDIR)$$subdir; \ done $(INSTALL_M) $(build_bindir)/julia* $(DESTDIR)$(bindir)/ - -cp -a $(build_libexecdir) $(DESTDIR)$(prefix) ifeq ($(OS),WINNT) -$(INSTALL_M) $(build_bindir)/*.dll $(DESTDIR)$(bindir)/ -$(INSTALL_M) $(build_libdir)/libjulia.dll.a $(DESTDIR)$(libdir)/ diff --git a/appveyor.yml b/appveyor.yml index e2f7543300df3..44027c9244827 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -56,4 +56,6 @@ test_script: - usr\bin\julia -e "versioninfo()" - usr\bin\julia --precompiled=no -e "true" - cd julia-* && .\bin\julia.exe --check-bounds=yes share\julia\test\runtests.jl all && - .\bin\julia.exe --check-bounds=yes share\julia\test\runtests.jl libgit2-online download pkg embedding + .\bin\julia.exe --check-bounds=yes share\julia\test\runtests.jl libgit2-online download pkg + - cd .. + - usr\bin\julia usr\share\doc\julia\examples\embedding\embedding-test.jl examples\embedding\embedding.exe diff --git a/base/Makefile b/base/Makefile index 11515409e19e6..04c97fda88e8d 100644 --- a/base/Makefile +++ b/base/Makefile @@ -63,7 +63,6 @@ endif @echo "const DOCDIR = \"$(docdir_rel)\"" >> $@ @echo "const LIBDIR = \"$(libdir_rel)\"" >> $@ @echo "const PRIVATE_LIBDIR = \"$(private_libdir_rel)\"" >> $@ - @echo "const LIBEXECDIR = \"$(libexecdir_rel)\"" >> $@ @echo "const INCLUDEDIR = \"$(includedir_rel)\"" >> $@ @# This to ensure that we always rebuild this file, but only when it is modified do we touch build_h.jl, diff --git a/contrib/julia-config.jl b/contrib/julia-config.jl index 8b8ae445d64d1..2a177240d536f 100755 --- a/contrib/julia-config.jl +++ b/contrib/julia-config.jl @@ -1,8 +1,7 @@ #!/usr/bin/env julia # This file is a part of Julia. License is MIT: https://julialang.org/license -const options = -[ +const options = [ "--cflags", "--ldflags", "--ldlibs" @@ -10,9 +9,14 @@ const options = threadingOn() = ccall(:jl_threading_enabled, Cint, ()) != 0 +function shell_escape(str) + str = replace(str, "'", "'\''") + return "'$str'" +end + function imagePath() opts = Base.JLOptions() - unsafe_string(opts.image_file) + return unsafe_string(opts.image_file) end function libDir() @@ -23,35 +27,14 @@ function libDir() end end -private_libDir() = joinpath(JULIA_HOME, Base.PRIVATE_LIBDIR) +private_libDir() = abspath(JULIA_HOME, Base.PRIVATE_LIBDIR) function includeDir() - joinpath(match(r"(.*)(bin)",JULIA_HOME).captures[1],"include","julia") -end - -function unixInitDir() - filePart = split(imagePath(),"/")[end] - return match(Regex("(.*)(/julia/$filePart)"),imagePath()).captures[1] -end - -function windowsInitDir() - if imagePath()[end-1:end] == "ji" - return match(r"(.*)(\\julia\\sys.ji)",imagePath()).captures[1] - else - return match(r"(.*)(\\julia\\sys.dll)",imagePath()).captures[1] - end -end - -function initDir() - if is_unix() - return unixInitDir() - else - return windowsInitDir() - end + return abspath(JULIA_HOME, Base.INCLUDEDIR, "julia") end function ldflags() - fl = replace("""-L$(libDir())""","\\","\\\\") + fl = "-L$(shell_escape(libDir()))" if is_windows() fl = fl * " -Wl,--stack,8388608" elseif is_linux() @@ -67,27 +50,30 @@ function ldlibs() "julia" end if is_unix() - return replace("""-Wl,-rpath,$(libDir()) -Wl,-rpath,$(private_libDir()) -l$libname""","\\","\\\\") + return "-Wl,-rpath,$(shell_escape(libDir())) -Wl,-rpath,$(shell_escape(private_libDir())) -l$libname" else return "-l$libname -lopenlibm" end end function cflags() - arg1 = replace(initDir(),"\\","\\\\\\\\") - arg2 = replace(includeDir(),"\\","\\\\") - threading_def = threadingOn() ? "-DJULIA_ENABLE_THREADING=1 " : "" + flags = IOBuffer() + print(flags, "-std=gnu99") + include = shell_escape(includeDir()) + print(flags, " -I", include) + if threadingOn() + print(flags, " -DJULIA_ENABLE_THREADING=1") + end if is_unix() - return """-std=gnu99 $(threading_def)-fPIC -DJULIA_INIT_DIR=\\"$arg1\\" -I$arg2""" - else - return """-std=gnu99 $(threading_def)-DJULIA_INIT_DIR=\\"$arg1\\" -I$arg2""" + print(flags, " -fPIC") end + return String(take!(flags)) end function check_args(args) - checked = intersect(args,options) + checked = intersect(args, options) if length(checked) == 0 || length(checked) != length(args) - println(STDERR,"Usage: julia-config [",reduce((x,y)->"$x|$y",options),"]") + println(STDERR, "Usage: julia-config [", join(options, " | "), "]") exit(1) end end diff --git a/contrib/windows/msys_build.sh b/contrib/windows/msys_build.sh index 36dd0eaeb7762..9edba7e3d64a0 100755 --- a/contrib/windows/msys_build.sh +++ b/contrib/windows/msys_build.sh @@ -204,6 +204,6 @@ echo 'FORCE_ASSERTIONS = 1' >> Make.user cat Make.user make -j3 VERBOSE=1 install +make VERBOSE=1 -C examples cp usr/bin/busybox.exe julia-*/bin make build-stats -make VERBOSE=1 -C examples diff --git a/examples/Makefile b/examples/Makefile index bc065d751530b..08e2ff962966e 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -1,25 +1,13 @@ +## this is a simple wrapper just to forward on known commands to the +## embedding example with values pulled from Make.inc SRCDIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) -BUILDDIR := . JULIAHOME := $(abspath $(SRCDIR)/..) +BUILDDIR := . include $(JULIAHOME)/Make.inc -outdir := $(libexecdir) - -embedding_binary := $(abspath $(outdir)/embedding$(JULIA_LIBSUFFIX)$(EXE)) - -release: embedding -debug: embedding-debug - -embedding: $(embedding_binary) -embedding-debug: $(embedding_binary) - -$(embedding_binary): $(wildcard embedding/*) - @$(MAKE) $(QUIET_MAKE) -C $(BUILDROOT)/examples/embedding $(JULIA_BUILD_MODE) \ - JULIA="$(bindir)/julia$(JULIA_LIBSUFFIX)$(EXE)" BIN="$(outdir)" \ - SPAWN="$(spawn)" CC="$(CC)" - -clean: - -rm -f $(embedding_binary) $(embedding_binary)-debug - -.PHONY: all embedding clean - +release: # default target +# forward all variables expected by the embedding example +JULIA:=$(call spawn,$(JULIA_EXECUTABLE)) +BIN:=$(BUILDDIR)/embedding +CC:=$(CC) +include $(SRCDIR)/embedding/Makefile diff --git a/examples/embedding/.gitignore b/examples/embedding/.gitignore new file mode 100644 index 0000000000000..4ce246ef16619 --- /dev/null +++ b/examples/embedding/.gitignore @@ -0,0 +1,2 @@ +/embedding +/embedding-debug diff --git a/examples/embedding/Makefile b/examples/embedding/Makefile index c5710924abbb8..38e9bc33b2cae 100644 --- a/examples/embedding/Makefile +++ b/examples/embedding/Makefile @@ -1,3 +1,5 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + # This Makefile template requires the following variables to be set # in the environment or on the command-line: # JULIA: path to julia[.exe] executable @@ -18,9 +20,10 @@ SRCDIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) EXE := $(suffix $(abspath $(JULIA))) # get compiler and linker flags. (see: `contrib/julia-config.jl`) -CFLAGS += -lm $(shell $(SPAWN) $(JULIA) -e \ - 'include(joinpath(JULIA_HOME,Base.DATAROOTDIR,"julia","julia-config.jl"))' \ - -- --cflags --ldflags --ldlibs) +JULIA_CONFIG := $(JULIA) -e 'include(joinpath(JULIA_HOME, Base.DATAROOTDIR, "julia", "julia-config.jl"))' -- +CPPFLAGS_ADD := +CFLAGS_ADD = $(shell $(JULIA_CONFIG) --cflags) +LDFLAGS_ADD = -lm $(shell $(JULIA_CONFIG) --ldflags --ldlibs) DEBUGFLAGS += -g @@ -30,13 +33,21 @@ release: $(BIN)/embedding$(EXE) debug: $(BIN)/embedding-debug$(EXE) $(BIN)/embedding$(EXE): $(SRCDIR)/embedding.c - $(CC) $^ -o $@ $(CFLAGS) + $(CC) $^ -o $@ $(CPPFLAGS_ADD) $(CPPFLAGS) $(CFLAGS_ADD) $(CFLAGS) $(LDFLAGS_ADD) $(LDFLAGS) $(BIN)/embedding-debug$(EXE): $(SRCDIR)/embedding.c - $(CC) $^ -o $@ $(CFLAGS) $(DEBUGFLAGS) + $(CC) $^ -o $@ $(CPPFLAGS_ADD) $(CPPFLAGS) $(CFLAGS_ADD) $(CFLAGS) $(LDFLAGS_ADD) $(LDFLAGS) $(DEBUGFLAGS) + +check: $(BIN)/embedding$(EXE) + $(JULIA) $(SRCDIR)/embedding-test.jl $< + @echo SUCCESS clean: - @rm -f $(BIN)/embedding-debug$(EXE) $(BIN)/embedding$(EXE) + -rm -f $(BIN)/embedding-debug$(EXE) $(BIN)/embedding$(EXE) -.PHONY: release debug clean +.PHONY: release debug clean check +# Makefile debugging trick: +# call print-VARIABLE to see the runtime value of any variable +print-%: + @echo '$*=$($*)' diff --git a/examples/embedding/embedding-test.jl b/examples/embedding/embedding-test.jl new file mode 100644 index 0000000000000..336169085db4c --- /dev/null +++ b/examples/embedding/embedding-test.jl @@ -0,0 +1,20 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + +# tests the output of the embedding example is correct +using Base.Test + +@test length(ARGS) == 1 +let + stdout = Pipe() + stderr = Pipe() + p = spawn(pipeline(Cmd(ARGS), stdin=DevNull, stdout=stdout, stderr=stderr)) + close(stdout.in) + close(stderr.in) + stderr_task = @async readlines(stderr) + lines = readlines(stdout) + @test length(lines) == 6 + @test parse(Float64, lines[1]) ≈ sqrt(2) + lines = wait(stderr_task) + @test lines == ["UndefVarError(:this_function_does_not_exist)"] + @test success(p) +end diff --git a/test/embedding.jl b/test/embedding.jl deleted file mode 100644 index 4212589e3f52a..0000000000000 --- a/test/embedding.jl +++ /dev/null @@ -1,14 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -# test that the embedding example runs without error -let - if is_windows() - embedding_bin = joinpath(JULIA_HOME,Base.LIBEXECDIR,"embedding.exe") - else - embedding_bin = joinpath(JULIA_HOME,Base.LIBEXECDIR,"embedding") - end - lines = readlines(pipeline(`$(embedding_bin)`, - stderr=DevNull)) - @test length(lines) == 6 - @test parse(Float64, lines[1]) ≈ sqrt(2) -end From 217c806ca5681b9e924584d74a7cdfb272ea88d5 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Sat, 22 Apr 2017 18:27:35 -0700 Subject: [PATCH 0527/1534] Upgrade documenter, fix doctests (#21473) * run NEWS-update.jl #20648 was partially reverted by #20782 * Fix doctest line numbers * Upgrade Documenter, add linkcheck exception bugs.kde.org fails to load from nanosoldier for some reason, gives a CURLE_RECV_ERROR (56) Failure with receiving network data fix alloc.c dead link in devdocs/init.md * fix timeit_init macro in test/perf/perfutil.jl needed to escape its arguments --- NEWS.md | 3 ++- base/array.jl | 4 ++-- base/docs/helpdb/Base.jl | 2 +- doc/REQUIRE | 6 +++--- doc/make.jl | 1 + doc/src/manual/constructors.md | 2 +- doc/src/manual/mathematical-operations.md | 12 ++++++------ doc/src/manual/types.md | 2 +- test/perf/perfutil.jl | 2 +- 9 files changed, 18 insertions(+), 16 deletions(-) diff --git a/NEWS.md b/NEWS.md index e48a0b28245fb..c86332d51a338 100644 --- a/NEWS.md +++ b/NEWS.md @@ -410,6 +410,7 @@ Deprecated or removed [#12563]: https://github.com/JuliaLang/julia/issues/12563 [#16213]: https://github.com/JuliaLang/julia/issues/16213 [#16961]: https://github.com/JuliaLang/julia/issues/16961 +[#16984]: https://github.com/JuliaLang/julia/issues/16984 [#16986]: https://github.com/JuliaLang/julia/issues/16986 [#17057]: https://github.com/JuliaLang/julia/issues/17057 [#17261]: https://github.com/JuliaLang/julia/issues/17261 @@ -450,6 +451,7 @@ Deprecated or removed [#19469]: https://github.com/JuliaLang/julia/issues/19469 [#19533]: https://github.com/JuliaLang/julia/issues/19533 [#19543]: https://github.com/JuliaLang/julia/issues/19543 +[#19594]: https://github.com/JuliaLang/julia/issues/19594 [#19598]: https://github.com/JuliaLang/julia/issues/19598 [#19635]: https://github.com/JuliaLang/julia/issues/19635 [#19670]: https://github.com/JuliaLang/julia/issues/19670 @@ -492,5 +494,4 @@ Deprecated or removed [#20530]: https://github.com/JuliaLang/julia/issues/20530 [#20543]: https://github.com/JuliaLang/julia/issues/20543 [#20609]: https://github.com/JuliaLang/julia/issues/20609 -[#20648]: https://github.com/JuliaLang/julia/issues/20648 [#20889]: https://github.com/JuliaLang/julia/issues/20889 diff --git a/base/array.jl b/base/array.jl index ff7e5673556ec..b8fb3f9bb0370 100644 --- a/base/array.jl +++ b/base/array.jl @@ -853,8 +853,8 @@ julia> deleteat!([6, 5, 4, 3, 2, 1], [true, false, true, false, true, false]) julia> deleteat!([6, 5, 4, 3, 2, 1], (2, 2)) ERROR: ArgumentError: indices must be unique and sorted Stacktrace: - [1] _deleteat!(::Array{Int64,1}, ::Tuple{Int64,Int64}) at ./array.jl:862 - [2] deleteat!(::Array{Int64,1}, ::Tuple{Int64,Int64}) at ./array.jl:849 + [1] _deleteat!(::Array{Int64,1}, ::Tuple{Int64,Int64}) at ./array.jl:873 + [2] deleteat!(::Array{Int64,1}, ::Tuple{Int64,Int64}) at ./array.jl:860 ``` """ deleteat!(a::Vector, inds) = _deleteat!(a, inds) diff --git a/base/docs/helpdb/Base.jl b/base/docs/helpdb/Base.jl index 83019ba7d477b..e0da5a28c17ce 100644 --- a/base/docs/helpdb/Base.jl +++ b/base/docs/helpdb/Base.jl @@ -1945,7 +1945,7 @@ julia> convert(Int, 3.0) julia> convert(Int, 3.5) ERROR: InexactError() Stacktrace: - [1] convert(::Type{Int64}, ::Float64) at ./float.jl:675 + [1] convert(::Type{Int64}, ::Float64) at ./float.jl:679 ``` If `T` is a `AbstractFloat` or `Rational` type, diff --git a/doc/REQUIRE b/doc/REQUIRE index 04046565e012b..165c8fcb20b26 100644 --- a/doc/REQUIRE +++ b/doc/REQUIRE @@ -1,3 +1,3 @@ -Compat 0.21.0 0.21.0+ -DocStringExtensions 0.3.2 0.3.2+ -Documenter 0.9.2 0.9.2+ +Compat 0.24.0 0.24.0+ +DocStringExtensions 0.3.3 0.3.3+ +Documenter 0.10.0 0.10.0+ diff --git a/doc/make.jl b/doc/make.jl index 4ef4222db9e8f..7f6a533b0777b 100644 --- a/doc/make.jl +++ b/doc/make.jl @@ -120,6 +120,7 @@ makedocs( clean = false, doctest = "doctest" in ARGS, linkcheck = "linkcheck" in ARGS, + linkcheck_ignore = ["https://bugs.kde.org/show_bug.cgi?id=136779"], # fails to load from nanosoldier? strict = true, checkdocs = :none, format = "pdf" in ARGS ? :latex : :html, diff --git a/doc/src/manual/constructors.md b/doc/src/manual/constructors.md index e5d4023799f44..e0f0c430cdc7c 100644 --- a/doc/src/manual/constructors.md +++ b/doc/src/manual/constructors.md @@ -301,7 +301,7 @@ Point{Int64}(1, 2) julia> Point{Int64}(1.0,2.5) ## explicit T ## ERROR: InexactError() Stacktrace: - [1] convert(::Type{Int64}, ::Float64) at ./float.jl:675 + [1] convert(::Type{Int64}, ::Float64) at ./float.jl:679 [2] Point{Int64}(::Float64, ::Float64) at ./none:2 julia> Point{Float64}(1.0, 2.5) ## explicit T ## diff --git a/doc/src/manual/mathematical-operations.md b/doc/src/manual/mathematical-operations.md index 718d95b5ad2aa..fe6ea8f769da6 100644 --- a/doc/src/manual/mathematical-operations.md +++ b/doc/src/manual/mathematical-operations.md @@ -366,10 +366,10 @@ You can also find the numerical precedence for any given operator via the built- ```jldoctest julia> Base.operator_precedence(:+), Base.operator_precedence(:*), Base.operator_precedence(:.) -(9,11,15) +(9, 11, 15) julia> Base.operator_precedence(:+=), Base.operator_precedence(:(=)) # (Note the necessary parens on `:(=)`) -(1,1) +(1, 1) ``` ## Numerical Conversions @@ -405,13 +405,13 @@ julia> Int8(127.0) julia> Int8(3.14) ERROR: InexactError() Stacktrace: - [1] convert(::Type{Int8}, ::Float64) at ./float.jl:654 + [1] convert(::Type{Int8}, ::Float64) at ./float.jl:658 [2] Int8(::Float64) at ./sysimg.jl:24 julia> Int8(128.0) ERROR: InexactError() Stacktrace: - [1] convert(::Type{Int8}, ::Float64) at ./float.jl:654 + [1] convert(::Type{Int8}, ::Float64) at ./float.jl:658 [2] Int8(::Float64) at ./sysimg.jl:24 julia> 127 % Int8 @@ -426,8 +426,8 @@ julia> round(Int8,127.4) julia> round(Int8,127.6) ERROR: InexactError() Stacktrace: - [1] trunc(::Type{Int8}, ::Float64) at ./float.jl:647 - [2] round(::Type{Int8}, ::Float64) at ./float.jl:333 + [1] trunc(::Type{Int8}, ::Float64) at ./float.jl:651 + [2] round(::Type{Int8}, ::Float64) at ./float.jl:337 ``` See [Conversion and Promotion](@ref conversion-and-promotion) for how to define your own conversions and promotions. diff --git a/doc/src/manual/types.md b/doc/src/manual/types.md index 6e5ed12fd99cc..dda0cb71bd540 100644 --- a/doc/src/manual/types.md +++ b/doc/src/manual/types.md @@ -341,7 +341,7 @@ must be convertible to `Int`: julia> Foo((), 23.5, 1) ERROR: InexactError() Stacktrace: - [1] convert(::Type{Int64}, ::Float64) at ./float.jl:675 + [1] convert(::Type{Int64}, ::Float64) at ./float.jl:679 [2] Foo(::Tuple{}, ::Float64, ::Int64) at ./none:2 ``` diff --git a/test/perf/perfutil.jl b/test/perf/perfutil.jl index 98a4c49b4b833..7e0ddf8cbc072 100644 --- a/test/perf/perfutil.jl +++ b/test/perf/perfutil.jl @@ -96,7 +96,7 @@ macro timeit_init(ex,init,name,desc,group...) t[i] = e end end - @output_timings t $name $desc $group + @output_timings t $(esc(name)) $(esc(desc)) $(esc(group)) end end From 02d7b14d70945cd4b4072fd7a4144fb9e028f340 Mon Sep 17 00:00:00 2001 From: Mus M Date: Sun, 23 Apr 2017 03:12:11 -0400 Subject: [PATCH 0528/1534] Misc changes to where syntax plus other clean ups (#21487) * Misc changes to where syntax plus other clean ups --- base/abstractarray.jl | 50 +++++++++++++++++++++---------------------- base/associative.jl | 10 ++++----- base/linalg/bidiag.jl | 10 +++------ base/replutil.jl | 4 ++-- base/rounding.jl | 14 ++++++------ base/set.jl | 2 +- base/sharedarray.jl | 21 +++++++++--------- base/sort.jl | 8 +++---- base/subarray.jl | 2 +- 9 files changed, 58 insertions(+), 63 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 16f6db4192499..bb5dfa258feaf 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -60,8 +60,8 @@ end # Performance optimization: get rid of a branch on `d` in `indices(A, # d)` for d=1. 1d arrays are heavily used, and the first dimension # comes up in other applications. -indices1{T}(A::AbstractArray{T,0}) = OneTo(1) -indices1(A::AbstractArray) = (@_inline_meta; indices(A)[1]) +indices1(A::AbstractArray{<:Any,0}) = OneTo(1) +indices1(A::AbstractArray) = (@_inline_meta; indices(A)[1]) indices1(iter) = OneTo(length(iter)) unsafe_indices(A) = indices(A) @@ -184,7 +184,7 @@ function stride(a::AbstractArray, i::Integer) return length(a) end s = 1 - for n=1:(i-1) + for n = 1:(i-1) s *= size(a, n) end return s @@ -204,8 +204,8 @@ julia> strides(A) ``` """ strides(A::AbstractArray) = _strides((1,), A) -_strides{T,N}(out::NTuple{N,Any}, A::AbstractArray{T,N}) = out -function _strides{M}(out::NTuple{M,Any}, A::AbstractArray) +_strides(out::NTuple{N,Any}, A::AbstractArray{T,N}) where {T,N} = out +function _strides(out::NTuple{M,Any}, A::AbstractArray) where M @_inline_meta _strides((out..., out[M]*size(A, M)), A) end @@ -340,7 +340,7 @@ function checkbounds(::Type{Bool}, A::AbstractArray, i) checkindex(Bool, linearindices(A), i) end # As a special extension, allow using logical arrays that match the source array exactly -function checkbounds{_,N}(::Type{Bool}, A::AbstractArray{_,N}, I::AbstractArray{Bool,N}) +function checkbounds(::Type{Bool}, A::AbstractArray{<:Any,N}, I::AbstractArray{Bool,N}) where N @_inline_meta indices(A) == indices(I) end @@ -690,8 +690,8 @@ function copy(a::AbstractArray) copymutable(a) end -function copy!{R,S}(B::AbstractVecOrMat{R}, ir_dest::Range{Int}, jr_dest::Range{Int}, - A::AbstractVecOrMat{S}, ir_src::Range{Int}, jr_src::Range{Int}) +function copy!(B::AbstractVecOrMat{R}, ir_dest::Range{Int}, jr_dest::Range{Int}, + A::AbstractVecOrMat{S}, ir_src::Range{Int}, jr_src::Range{Int}) where {R,S} if length(ir_dest) != length(ir_src) throw(ArgumentError(string("source and destination must have same size (got ", length(ir_src)," and ",length(ir_dest),")"))) @@ -749,8 +749,8 @@ zero(x::AbstractArray{T}) where {T} = fill!(similar(x), zero(T)) # own, IndexCartesian's CartesianRange is more complicated and requires explicit # inlining. start(A::AbstractArray) = (@_inline_meta; itr = eachindex(A); (itr, start(itr))) -next(A::AbstractArray,i) = (@_propagate_inbounds_meta; (idx, s) = next(i[1], i[2]); (A[idx], (i[1], s))) -done(A::AbstractArray,i) = (@_propagate_inbounds_meta; done(i[1], i[2])) +next(A::AbstractArray, i) = (@_propagate_inbounds_meta; (idx, s) = next(i[1], i[2]); (A[idx], (i[1], s))) +done(A::AbstractArray, i) = (@_propagate_inbounds_meta; done(i[1], i[2])) # eachindex iterates over all indices. IndexCartesian definitions are later. eachindex(A::AbstractVector) = (@_inline_meta(); indices1(A)) @@ -826,7 +826,7 @@ isempty(a::AbstractArray) = (_length(a) == 0) convert(::Type{AbstractArray{T,N}}, A::AbstractArray{T,N}) where {T,N } = A convert(::Type{AbstractArray{T,N}}, A::AbstractArray{S,N}) where {T,S,N} = copy!(similar(A,T), A) -convert(::Type{AbstractArray{T }}, A::AbstractArray{S,N}) where {T,S,N} = convert(AbstractArray{T,N}, A) +convert(::Type{AbstractArray{T}}, A::AbstractArray{S,N}) where {T,S,N} = convert(AbstractArray{T,N}, A) convert(::Type{Array}, A::AbstractArray{T,N}) where {T,N} = convert(Array{T,N}, A) @@ -853,10 +853,10 @@ end # note: the following type definitions don't mean any AbstractArray is convertible to # a data Ref. they just map the array element type to the pointer type for # convenience in cases that work. -pointer{T}(x::AbstractArray{T}) = unsafe_convert(Ptr{T}, x) -function pointer{T}(x::AbstractArray{T}, i::Integer) +pointer(x::AbstractArray{T}) where {T} = unsafe_convert(Ptr{T}, x) +function pointer(x::AbstractArray{T}, i::Integer) where T @_inline_meta - unsafe_convert(Ptr{T},x) + (i-first(linearindices(x)))*elsize(x) + unsafe_convert(Ptr{T}, x) + (i - first(linearindices(x)))*elsize(x) end ## Approach: @@ -882,7 +882,7 @@ end error_if_canonical_indexing(::IndexLinear, A::AbstractArray, ::Int) = error("indexing not defined for ", typeof(A)) -error_if_canonical_indexing{T,N}(::IndexCartesian, A::AbstractArray{T,N}, ::Vararg{Int, N}) = +error_if_canonical_indexing(::IndexCartesian, A::AbstractArray{T,N}, ::Vararg{Int,N}) where {T,N} = error("indexing not defined for ", typeof(A)) error_if_canonical_indexing(::IndexStyle, ::AbstractArray, ::Any...) = nothing @@ -1003,7 +1003,7 @@ get(A::AbstractArray, i::Integer, default) = checkbounds(Bool, A, i) ? A[i] : de get(A::AbstractArray, I::Tuple{}, default) = similar(A, typeof(default), 0) get(A::AbstractArray, I::Dims, default) = checkbounds(Bool, A, I...) ? A[I...] : default -function get!(X::AbstractVector{T}, A::AbstractVector, I::Union{Range, AbstractVector{Int}}, default::T) where T +function get!(X::AbstractVector{T}, A::AbstractVector, I::Union{Range,AbstractVector{Int}}, default::T) where T # 1d is not linear indexing ind = findin(I, indices1(A)) X[ind] = A[I[ind]] @@ -1012,7 +1012,7 @@ function get!(X::AbstractVector{T}, A::AbstractVector, I::Union{Range, AbstractV X[last(ind)+1:last(Xind)] = default X end -function get!(X::AbstractArray{T}, A::AbstractArray, I::Union{Range, AbstractVector{Int}}, default::T) where T +function get!(X::AbstractArray{T}, A::AbstractArray, I::Union{Range,AbstractVector{Int}}, default::T) where T # Linear indexing ind = findin(I, 1:length(A)) X[ind] = A[I[ind]] @@ -1647,12 +1647,12 @@ _div(ind, d::Integer) = div(ind, d), 1, d _div(ind, r::AbstractUnitRange) = (d = unsafe_length(r); (div(ind, d), first(r), d)) # Vectorized forms -function sub2ind{T<:Integer}(inds::Indices{1}, I1::AbstractVector{T}, I::AbstractVector{T}...) +function sub2ind(inds::Indices{1}, I1::AbstractVector{T}, I::AbstractVector{T}...) where T<:Integer throw(ArgumentError("Linear indexing is not defined for one-dimensional arrays")) end -sub2ind{T<:Integer}(inds::Tuple{OneTo}, I1::AbstractVector{T}, I::AbstractVector{T}...) = +sub2ind(inds::Tuple{OneTo}, I1::AbstractVector{T}, I::AbstractVector{T}...) where {T<:Integer} = _sub2ind_vecs(inds, I1, I...) -sub2ind{T<:Integer}(inds::Union{DimsInteger,Indices}, I1::AbstractVector{T}, I::AbstractVector{T}...) = +sub2ind(inds::Union{DimsInteger,Indices}, I1::AbstractVector{T}, I::AbstractVector{T}...) where {T<:Integer} = _sub2ind_vecs(inds, I1, I...) function _sub2ind_vecs(inds, I::AbstractVector...) I1 = I[1] @@ -1678,7 +1678,7 @@ sub2ind_vec(inds, i, I) = (@_inline_meta; _sub2ind_vec(inds, (), i, I...)) _sub2ind_vec(inds, out, i, I1, I...) = (@_inline_meta; _sub2ind_vec(inds, (out..., I1[i]), i, I...)) _sub2ind_vec(inds, out, i) = (@_inline_meta; sub2ind(inds, out...)) -function ind2sub{N}(inds::Union{DimsInteger{N},Indices{N}}, ind::AbstractVector{<:Integer}) +function ind2sub(inds::Union{DimsInteger{N},Indices{N}}, ind::AbstractVector{<:Integer}) where N M = length(ind) t = ntuple(n->similar(ind),Val{N}) for (i,idx) in enumerate(IndexLinear(), ind) @@ -1690,7 +1690,7 @@ function ind2sub{N}(inds::Union{DimsInteger{N},Indices{N}}, ind::AbstractVector{ t end -function ind2sub!{T<:Integer}(sub::Array{T}, dims::Tuple{Vararg{T}}, ind::T) +function ind2sub!(sub::Array{T}, dims::Tuple{Vararg{T}}, ind::T) where T<:Integer ndims = length(dims) for i=1:ndims-1 ind2 = div(ind-1,dims[i])+1 @@ -1806,7 +1806,7 @@ function mapslices(f, A::AbstractArray, dims::AbstractVector) if !isa(r1, AbstractArray) || ndims(r1) == 0 r1 = [r1] end - nextra = max(0,length(dims)-ndims(r1)) + nextra = max(0, length(dims)-ndims(r1)) if eltype(Rsize) == Int Rsize[dims] = [size(r1)..., ntuple(d->1, nextra)...] else @@ -1893,7 +1893,7 @@ end @inline ith_all(i, ::Tuple{}) = () @inline ith_all(i, as) = (as[1][i], ith_all(i, tail(as))...) -function map_n!{F}(f::F, dest::AbstractArray, As) +function map_n!(f::F, dest::AbstractArray, As) where F for i = linearindices(As[1]) dest[i] = f(ith_all(i, As)...) end @@ -1933,7 +1933,7 @@ unshift!(A, a, b, c...) = unshift!(unshift!(A, c...), a, b) ## hashing collections ## const hashaa_seed = UInt === UInt64 ? 0x7f53e68ceb575e76 : 0xeb575e76 -const hashrle_seed = UInt == UInt64 ? 0x2aab8909bfea414c : 0xbfea414c +const hashrle_seed = UInt === UInt64 ? 0x2aab8909bfea414c : 0xbfea414c function hash(a::AbstractArray, h::UInt) h += hashaa_seed h += hash(size(a)) diff --git a/base/associative.jl b/base/associative.jl index b49c5b54bfd47..cf9ac14ac3a71 100644 --- a/base/associative.jl +++ b/base/associative.jl @@ -39,8 +39,8 @@ show(io::IO, iter::Union{KeyIterator,ValueIterator}) = show(io, collect(iter)) length(v::Union{KeyIterator,ValueIterator}) = length(v.dict) isempty(v::Union{KeyIterator,ValueIterator}) = isempty(v.dict) -_tt1{A,B}(::Type{Pair{A,B}}) = A -_tt2{A,B}(::Type{Pair{A,B}}) = B +_tt1(::Type{Pair{A,B}}) where {A,B} = A +_tt2(::Type{Pair{A,B}}) where {A,B} = B eltype(::Type{KeyIterator{D}}) where {D} = _tt1(eltype(D)) eltype(::Type{ValueIterator{D}}) where {D} = _tt2(eltype(D)) @@ -203,9 +203,9 @@ julia> keytype(Dict(Int32(1) => "foo")) Int32 ``` """ -keytype{K,V}(::Type{Associative{K,V}}) = K +keytype(::Type{Associative{K,V}}) where {K,V} = K keytype(a::Associative) = keytype(typeof(a)) -keytype{A<:Associative}(::Type{A}) = keytype(supertype(A)) +keytype(::Type{A}) where {A<:Associative} = keytype(supertype(A)) """ valtype(type) @@ -217,7 +217,7 @@ julia> valtype(Dict(Int32(1) => "foo")) String ``` """ -valtype{K,V}(::Type{Associative{K,V}}) = V +valtype(::Type{Associative{K,V}}) where {K,V} = V valtype{A<:Associative}(::Type{A}) = valtype(supertype(A)) valtype(a::Associative) = valtype(typeof(a)) diff --git a/base/linalg/bidiag.jl b/base/linalg/bidiag.jl index 91538ef7cddaf..9e9af0bb890ff 100644 --- a/base/linalg/bidiag.jl +++ b/base/linalg/bidiag.jl @@ -522,7 +522,7 @@ function A_ldiv_B!(A::Union{Bidiagonal,AbstractTriangular}, B::AbstractMatrix) B end for func in (:Ac_ldiv_B!, :At_ldiv_B!) - @eval function ($func)(A::Union{Bidiagonal, AbstractTriangular}, B::AbstractMatrix) + @eval function ($func)(A::Union{Bidiagonal,AbstractTriangular}, B::AbstractMatrix) nA,mA = size(A) tmp = similar(B,size(B,1)) n = size(B, 1) @@ -615,11 +615,7 @@ _valuefields(::Type{<:Tridiagonal}) = [:dl, :d, :du] _valuefields(::Type{<:SymTridiagonal}) = [:dv, :ev] _valuefields(::Type{<:AbstractTriangular}) = [:data] -SpecialArrays = Union{Diagonal, - Bidiagonal, - Tridiagonal, - SymTridiagonal, - AbstractTriangular} +const SpecialArrays = Union{Diagonal,Bidiagonal,Tridiagonal,SymTridiagonal,AbstractTriangular} @generated function fillslots!(A::SpecialArrays, x) ex = :(xT = convert(eltype(A), x)) @@ -637,7 +633,7 @@ _small_enough(A::Bidiagonal) = size(A, 1) <= 1 _small_enough(A::Tridiagonal) = size(A, 1) <= 2 _small_enough(A::SymTridiagonal) = size(A, 1) <= 2 -function fill!(A::Union{Bidiagonal, Tridiagonal, SymTridiagonal}, x) +function fill!(A::Union{Bidiagonal,Tridiagonal,SymTridiagonal}, x) xT = convert(eltype(A), x) (xT == zero(eltype(A)) || _small_enough(A)) && return fillslots!(A, xT) throw(ArgumentError("array A of type $(typeof(A)) and size $(size(A)) can diff --git a/base/replutil.jl b/base/replutil.jl index 2923e8db186fa..26a17c42e4a36 100644 --- a/base/replutil.jl +++ b/base/replutil.jl @@ -34,7 +34,7 @@ function show(io::IO, ::MIME"text/plain", iter::Union{KeyIterator,ValueIterator} end end -function show{K,V}(io::IO, ::MIME"text/plain", t::Associative{K,V}) +function show(io::IO, ::MIME"text/plain", t::Associative{K,V}) where {K,V} # show more descriptively, with one line per key/value pair recur_io = IOContext(io, :SHOWN_SET => t) limit::Bool = get(io, :limit, false) @@ -418,7 +418,7 @@ function showerror(io::IO, ex::MethodError) end end -striptype{T}(::Type{T}) = T +striptype(::Type{T}) where {T} = T striptype(::Any) = nothing function showerror_ambiguous(io::IO, meth, f, args) diff --git a/base/rounding.jl b/base/rounding.jl index 526510a6b2c4b..67f71d9dda57d 100644 --- a/base/rounding.jl +++ b/base/rounding.jl @@ -139,10 +139,10 @@ See [`RoundingMode`](@ref) for available modes. """ :rounding -setrounding_raw(::Type{<:Union{Float32,Float64}},i::Integer) = ccall(:fesetround, Int32, (Int32,), i) +setrounding_raw(::Type{<:Union{Float32,Float64}}, i::Integer) = ccall(:fesetround, Int32, (Int32,), i) rounding_raw(::Type{<:Union{Float32,Float64}}) = ccall(:fegetround, Int32, ()) -setrounding(::Type{T},r::RoundingMode) where {T<:Union{Float32,Float64}} = setrounding_raw(T,to_fenv(r)) +setrounding(::Type{T}, r::RoundingMode) where {T<:Union{Float32,Float64}} = setrounding_raw(T,to_fenv(r)) rounding(::Type{T}) where {T<:Union{Float32,Float64}} = from_fenv(rounding_raw(T)) """ @@ -199,18 +199,18 @@ end # Assumes conversion is performed by rounding to nearest value. # To avoid ambiguous dispatch with methods in mpfr.jl: -(::Type{T})(x::Real,r::RoundingMode) where {T<:AbstractFloat} = _convert_rounding(T,x,r) +(::Type{T})(x::Real, r::RoundingMode) where {T<:AbstractFloat} = _convert_rounding(T,x,r) -_convert_rounding(::Type{T},x::Real,r::RoundingMode{:Nearest}) where {T<:AbstractFloat} = convert(T,x) -function _convert_rounding(::Type{T},x::Real,r::RoundingMode{:Down}) where T<:AbstractFloat +_convert_rounding(::Type{T}, x::Real, r::RoundingMode{:Nearest}) where {T<:AbstractFloat} = convert(T,x) +function _convert_rounding(::Type{T}, x::Real, r::RoundingMode{:Down}) where T<:AbstractFloat y = convert(T,x) y > x ? prevfloat(y) : y end -function _convert_rounding(::Type{T},x::Real,r::RoundingMode{:Up}) where T<:AbstractFloat +function _convert_rounding(::Type{T}, x::Real, r::RoundingMode{:Up}) where T<:AbstractFloat y = convert(T,x) y < x ? nextfloat(y) : y end -function _convert_rounding(::Type{T},x::Real,r::RoundingMode{:ToZero}) where T<:AbstractFloat +function _convert_rounding(::Type{T}, x::Real, r::RoundingMode{:ToZero}) where T<:AbstractFloat y = convert(T,x) if x > 0.0 y > x ? prevfloat(y) : y diff --git a/base/set.jl b/base/set.jl index f3f6a736c6c1c..96683a96d29f5 100644 --- a/base/set.jl +++ b/base/set.jl @@ -220,7 +220,7 @@ end allunique(::Set) = true -allunique{T}(r::Range{T}) = (step(r) != zero(T)) || (length(r) <= 1) +allunique(r::Range{T}) where {T} = (step(r) != zero(T)) || (length(r) <= 1) function filter(f, s::Set) u = similar(s) diff --git a/base/sharedarray.jl b/base/sharedarray.jl index 5ad6ec9c4ad24..ea4c4b3a0a1b9 100644 --- a/base/sharedarray.jl +++ b/base/sharedarray.jl @@ -103,7 +103,7 @@ function (::Type{SharedArray{T,N}})(dims::Dims{N}; init=false, pids=Int[]) where func_mapshmem = () -> shm_mmap_array(T, dims, shm_seg_name, JL_O_RDWR) - refs = Array{Future}(length(pids)) + refs = Vector{Future}(length(pids)) for (i, p) in enumerate(pids) refs[i] = remotecall(func_mapshmem, p) end @@ -127,7 +127,7 @@ function (::Type{SharedArray{T,N}})(dims::Dims{N}; init=false, pids=Int[]) where shm_seg_name = "" finally - if shm_seg_name != "" + if !isempty(shm_seg_name) remotecall_fetch(shm_unlink, shmmem_create_pid, shm_seg_name) end end @@ -147,8 +147,8 @@ end (::Type{SharedArray{T}})(m::Integer, n::Integer, o::Integer; kwargs...) where {T} = SharedArray{T,3}(m, n, o; kwargs...) -function (::Type{SharedArray{T,N}})(filename::AbstractString, dims::NTuple{N,Int}, - offset::Integer=0; mode=nothing, init=false, pids::Vector{Int}=Int[]) where T where N +function (::Type{SharedArray{T,N}})(filename::AbstractString, dims::NTuple{N,Int}, offset::Integer=0; + mode=nothing, init=false, pids::Vector{Int}=Int[]) where T where N if !isabspath(filename) throw(ArgumentError("$filename is not an absolute path; try abspath(filename)?")) end @@ -180,7 +180,7 @@ function (::Type{SharedArray{T,N}})(filename::AbstractString, dims::NTuple{N,Int end # Create the file if it doesn't exist, map it if it does - refs = Array{Future}(length(pids)) + refs = Vector{Future}(length(pids)) func_mmap = mode -> open(filename, mode) do io Mmap.mmap(io, Array{T,N}, dims, offset; shared=true) end @@ -214,7 +214,7 @@ function (::Type{SharedArray{T,N}})(filename::AbstractString, dims::NTuple{N,Int end (::Type{SharedArray{T}})(filename::AbstractString, dims::NTuple{N,Int}, offset::Integer=0; - mode=nothing, init=false, pids::Vector{Int}=Int[]) where {T,N} = + mode=nothing, init=false, pids::Vector{Int}=Int[]) where {T,N} = SharedArray{T,N}(filename, dims, offset; mode=mode, init=init, pids=pids) function initialize_shared_array(S, onlocalhost, init, pids) @@ -237,7 +237,7 @@ function initialize_shared_array(S, onlocalhost, init, pids) S end -function finalize_refs{T,N}(S::SharedArray{T,N}) +function finalize_refs(S::SharedArray{T,N}) where T where N if length(S.pids) > 0 for r in S.refs finalize(r) @@ -377,7 +377,7 @@ end sub_1dim(S::SharedArray, pidx) = view(S.s, range_1dim(S, pidx)) -function init_loc_flds{T,N}(S::SharedArray{T,N}, empty_local=false) +function init_loc_flds(S::SharedArray{T,N}, empty_local=false) where T where N if myid() in S.pids S.pidx = findfirst(S.pids, myid()) if isa(S.refs[1], Future) @@ -507,12 +507,11 @@ similar(S::SharedArray, dims::Dims) = similar(S.s, eltype(S), dims) similar(S::SharedArray) = similar(S.s, eltype(S), size(S)) reduce(f, S::SharedArray) = - mapreduce(fetch, f, - Any[ @spawnat p reduce(f, S.loc_subarr_1d) for p in procs(S) ]) + mapreduce(fetch, f, Any[ @spawnat p reduce(f, S.loc_subarr_1d) for p in procs(S) ]) function map!(f, S::SharedArray, Q::SharedArray) - if !(S === Q) && (procs(S) != procs(Q) || localindexes(S) != localindexes(Q)) + if (S !== Q) && (procs(S) != procs(Q) || localindexes(S) != localindexes(Q)) throw(ArgumentError("incompatible source and destination arguments")) end @sync for p in procs(S) diff --git a/base/sort.jl b/base/sort.jl index f323d636b83c8..846723518a9b7 100644 --- a/base/sort.jl +++ b/base/sort.jl @@ -819,13 +819,13 @@ function sortcols(A::AbstractMatrix; kws...) A[:,p] end -function slicetypeof{T}(A::AbstractArray{T}, i1, i2) +function slicetypeof(A::AbstractArray{T}, i1, i2) where T I = map(slice_dummy, to_indices(A, (i1, i2))) fast = isa(IndexStyle(viewindexing(I), IndexStyle(A)), IndexLinear) SubArray{T,1,typeof(A),typeof(I),fast} end slice_dummy(S::Slice) = S -slice_dummy{T}(::AbstractUnitRange{T}) = oneunit(T) +slice_dummy(::AbstractUnitRange{T}) where {T} = oneunit(T) ## fast clever sorting for floats ## @@ -848,8 +848,8 @@ right(::DirectOrdering) = Right() left(o::Perm) = Perm(left(o.order), o.data) right(o::Perm) = Perm(right(o.order), o.data) -lt{T<:Floats}(::Left, x::T, y::T) = slt_int(y, x) -lt{T<:Floats}(::Right, x::T, y::T) = slt_int(x, y) +lt(::Left, x::T, y::T) where {T<:Floats} = slt_int(y, x) +lt(::Right, x::T, y::T) where {T<:Floats} = slt_int(x, y) isnan(o::DirectOrdering, x::Floats) = (x!=x) isnan(o::Perm, i::Int) = isnan(o.order,o.data[i]) diff --git a/base/subarray.jl b/base/subarray.jl index fc24afe113f29..fd223d905efad 100644 --- a/base/subarray.jl +++ b/base/subarray.jl @@ -303,7 +303,7 @@ pointer(V::SubArray, i::Int) = _pointer(V, i) _pointer(V::SubArray{<:Any,1}, i::Int) = pointer(V, (i,)) _pointer(V::SubArray, i::Int) = pointer(V, ind2sub(indices(V), i)) -function pointer{T,N}(V::SubArray{T,N,<:Array,<:Tuple{Vararg{RangeIndex}}}, is::Tuple{Vararg{Int}}) +function pointer(V::SubArray{T,N,<:Array,<:Tuple{Vararg{RangeIndex}}}, is::Tuple{Vararg{Int}}) where {T,N} index = first_index(V) strds = strides(V) for d = 1:length(is) From 09352848e597727510ab768f05dca43acb5101f3 Mon Sep 17 00:00:00 2001 From: Massimiliano Fasi Date: Wed, 12 Aug 2015 10:55:35 +0100 Subject: [PATCH 0529/1534] Make the algorithm for real powers of a matrix robust fixed Matrix^Real_Number functionality reverted logm changes remove ambiguous Diagonal^Real method --- base/linalg/dense.jl | 59 ++++++++-- base/linalg/diagonal.jl | 1 + base/linalg/linalg.jl | 1 + base/linalg/symmetric.jl | 57 +++++++-- base/linalg/triangular.jl | 236 +++++++++++++++++++++++++++++++++++++- test/linalg/dense.jl | 33 ++++++ 6 files changed, 366 insertions(+), 21 deletions(-) diff --git a/base/linalg/dense.jl b/base/linalg/dense.jl index d70f7c2549f08..c4f08d6bf1847 100644 --- a/base/linalg/dense.jl +++ b/base/linalg/dense.jl @@ -323,17 +323,53 @@ kron(a::AbstractVector, b::AbstractVector)=vec(kron(reshape(a,length(a),1),resha kron(a::AbstractMatrix, b::AbstractVector)=kron(a,reshape(b,length(b),1)) kron(a::AbstractVector, b::AbstractMatrix)=kron(reshape(a,length(a),1),b) -^(A::AbstractMatrix, p::Integer) = p < 0 ? inv(A^-p) : Base.power_by_squaring(A,p) - -function ^(A::AbstractMatrix, p::Number) +# Matrix power +^(A::AbstractMatrix, p::Integer) = p < 0 ? Base.power_by_squaring(inv(A),-p) : Base.power_by_squaring(A,p) +function ^{T}(A::AbstractMatrix{T}, p::Real) + # For integer powers, use repeated squaring if isinteger(p) return A^Integer(real(p)) end - checksquare(A) - v, X = eig(A) - any(v.<0) && (v = complex(v)) - Xinv = ishermitian(A) ? X' : inv(X) - (X * Diagonal(v.^p)) * Xinv + + # If possible, use diagonalization + if issymmetric(A) && T <: Real + return full(Symmetric(A)^p) + end + if ishermitian(A) + return full(Hermitian(A)^p) + end + + # Otherwise, use Schur decomposition + n = checksquare(A) + if istriu(A) + #Integer part + retmat = full(A) ^ floor(p) + #Real part + retmat = retmat * full(powm(UpperTriangular(A), real(p - floor(p)))) + d = diag(A) + else + S,Q,d = schur(complex(A)) + R = UpperTriangular(S)^p + retmat = Q * R * Q' + end + + # Check whether the matrix has nonpositive real eigs + np_real_eigs = false + for i = 1:n + if imag(d[i]) < eps() && real(d[i]) <= 0 + np_real_eigs = true + break + end + end + if np_real_eigs + warn("Matrix with nonpositive real eigenvalues, a nonprincipal matrix power will be returned.") + end + + if isreal(A) && !np_real_eigs + return real(retmat) + else + return retmat + end end # Matrix exponential @@ -466,7 +502,7 @@ function rcswap!(i::Integer, j::Integer, X::StridedMatrix{<:Number}) end """ - logm(A::StridedMatrix) + logm(A{T}::StridedMatrix{T}) If `A` has no negative real eigenvalue, compute the principal matrix logarithm of `A`, i.e. the unique matrix ``X`` such that ``e^X = A`` and ``-\\pi < Im(\\lambda) < \\pi`` for all @@ -497,8 +533,11 @@ julia> logm(A) 0.0 1.0 ``` """ -function logm(A::StridedMatrix) +function logm{T}(A::StridedMatrix{T}) # If possible, use diagonalization + if issymmetric(A) && T <: Real + return full(logm(Symmetric(A))) + end if ishermitian(A) return full(logm(Hermitian(A))) end diff --git a/base/linalg/diagonal.jl b/base/linalg/diagonal.jl index 34e1d632d6df6..9c8647fe2c22f 100644 --- a/base/linalg/diagonal.jl +++ b/base/linalg/diagonal.jl @@ -288,6 +288,7 @@ end # identity matrices via eye(Diagonal{type},n) eye(::Type{Diagonal{T}}, n::Int) where {T} = Diagonal(ones(T,n)) +# Matrix functions expm(D::Diagonal) = Diagonal(exp.(D.diag)) expm(D::Diagonal{<:AbstractMatrix}) = Diagonal(expm.(D.diag)) logm(D::Diagonal) = Diagonal(log.(D.diag)) diff --git a/base/linalg/linalg.jl b/base/linalg/linalg.jl index b4004f008536e..0f0b8f253d98c 100644 --- a/base/linalg/linalg.jl +++ b/base/linalg/linalg.jl @@ -113,6 +113,7 @@ export ordschur, peakflops, pinv, + powm, qr, qrfact!, qrfact, diff --git a/base/linalg/symmetric.jl b/base/linalg/symmetric.jl index f0163356afc15..83fbbedbfefe3 100644 --- a/base/linalg/symmetric.jl +++ b/base/linalg/symmetric.jl @@ -403,8 +403,55 @@ function svdvals!{T<:Real,S}(A::Union{Hermitian{T,S}, Symmetric{T,S}, Hermitian{ return sort!(vals, rev = true) end -#Matrix-valued functions -function expm(A::Symmetric) +#Matrix functions +function ^{T<:Real}(A::Symmetric{T}, p::Integer) + if p < 0 + return Symmetric(Base.power_by_squaring(inv(A), -p)) + else + return Symmetric(Base.power_by_squaring(A, p)) + end +end +function ^{T<:Real}(A::Symmetric{T}, p::Real) + F = eigfact(full(A)) + if isposdef(F) + retmat = (F.vectors * Diagonal((F.values).^p)) * F.vectors' + else + retmat = (F.vectors * Diagonal((complex(F.values)).^p)) * F.vectors' + end + return Symmetric(retmat) +end +function ^(A::Hermitian, p::Integer) + n = checksquare(A) + if p < 0 + retmat = Base.power_by_squaring(inv(A), -p) + else + retmat = Base.power_by_squaring(A, p) + end + for i = 1:n + retmat[i,i] = real(retmat[i,i]) + end + return Hermitian(retmat) +end +function ^{T}(A::Hermitian{T}, p::Real) + n = checksquare(A) + F = eigfact(A) + if isposdef(F) + retmat = (F.vectors * Diagonal((F.values).^p)) * F.vectors' + if T <: Real + return Hermitian(retmat) + else + for i = 1:n + retmat[i,i] = real(retmat[i,i]) + end + return Hermitian(retmat) + end + else + retmat = (F.vectors * Diagonal((complex(F.values).^p))) * F.vectors' + return retmat + end +end + +function expm{T<:Real}(A::Symmetric{T}) F = eigfact(A) return Symmetric((F.vectors * Diagonal(exp.(F.values))) * F.vectors') end @@ -423,10 +470,8 @@ function expm{T}(A::Hermitian{T}) end for (funm, func) in ([:logm,:log], [:sqrtm,:sqrt]) - @eval begin - - function ($funm)(A::Symmetric) + function ($funm){T<:Real}(A::Symmetric{T}) F = eigfact(A) if isposdef(F) retmat = (F.vectors * Diagonal(($func).(F.values))) * F.vectors' @@ -454,7 +499,5 @@ for (funm, func) in ([:logm,:log], [:sqrtm,:sqrt]) return retmat end end - end - end diff --git a/base/linalg/triangular.jl b/base/linalg/triangular.jl index cd517d1985c22..2b70b42ee8fa9 100644 --- a/base/linalg/triangular.jl +++ b/base/linalg/triangular.jl @@ -1662,13 +1662,79 @@ At_ldiv_B(::Union{UnitUpperTriangular,UnitLowerTriangular}, ::RowVector) = throw Ac_ldiv_B(::Union{UpperTriangular,LowerTriangular}, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) Ac_ldiv_B(::Union{UnitUpperTriangular,UnitLowerTriangular}, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) +# Complex matrix power for upper triangular factor, see: +# Higham and Lin, "A Schur-Padé algorithm for fractional powers of a Matrix", +# SIAM J. Matrix Anal. & Appl., 32 (3), (2011) 1056–1078. +# Higham and Lin, "An improved Schur-Padé algorithm for fractional powers of +# a matrix and their Fréchet derivatives", SIAM. J. Matrix Anal. & Appl., +# 34(3), (2013) 1341–1360. +function powm(A0::UpperTriangular{T}, p::Real) where T<:BlasFloat + + if abs(p) >= 1 + ArgumentError("p must be a real number in (-1,1), got $p") + end + + theta = [1.53e-5, 2.25e-3, 1.92e-2, 6.08e-2, 1.25e-1, 2.03e-1, 2.84e-1] + n = checksquare(A0) + + A, m, s = invsquaring(A0,theta) + A = I - A + + # Compute accurate diagonal of I - T + sqrt_diag!(A0,A,s) + for i = 1:n + A[i,i] = -A[i,i] + end + # Compute the Padé approximant + c = 0.5 * (p - m) / (2 * m - 1) + triu!(A) + S = c * A + Stmp = similar(S) + for j = m-1:-1:1 + j4 = 4 * j + c = (-p - j) / (j4 + 2) + for i = 1:n + @inbounds S[i,i] = S[i,i] + 1 + end + copy!(Stmp,S) + scale!(S,A,c) + A_ldiv_B!(Stmp,S.data) + + c = (p - j) / (j4 - 2) + for i = 1:n + @inbounds S[i,i] = S[i,i] + 1 + end + copy!(Stmp,S) + scale!(S,A,c) + A_ldiv_B!(Stmp,S.data) + end + for i = 1:n + S[i,i] = S[i,i] + 1 + end + copy!(Stmp,S) + scale!(S,A,-p) + A_ldiv_B!(Stmp,S.data) + for i = 1:n + @inbounds S[i,i] = S[i,i] + 1 + end + + blockpower!(A0,S,p/(2^s)) + for m = 1:s + A_mul_B!(Stmp.data,S,S) + copy!(S,Stmp) + blockpower!(A0,S,p/(2^(s-m))) + end + return S +end +^(A::LowerTriangular, p::Integer) = ^(A.', p::Integer).' +powm(A::LowerTriangular, p::Real) = powm(A.', p::Real).' # Complex matrix logarithm for the upper triangular factor, see: # Al-Mohy and Higham, "Improved inverse scaling and squaring algorithms for -# the matrix logarithm", SIAM J. Sci. Comput., 34(4), (2012), pp. C153-C169. +# the matrix logarithm", SIAM J. Sci. Comput., 34(4), (2012), pp. C153–C169. # Al-Mohy, Higham and Relton, "Computing the Frechet derivative of the matrix -# logarithm and estimating the condition number", SIAM J. Sci. Comput., 35(4), -# (2013), C394-C410. +# logarithm and estimating the condition number", SIAM J. Sci. Comput., +# 35(4), (2013), C394–C410. # # Based on the code available at http://eprints.ma.man.ac.uk/1851/02/logm.zip, # Copyright (c) 2011, Awad H. Al-Mohy and Nicholas J. Higham @@ -1809,7 +1875,7 @@ function logm{T<:Union{Float64,Complex{Float64}}}(A0::UpperTriangular{T}) A[i,i] = z0 / r end - # Compute the Gauss-Legendre quadrature formula + # Get the Gauss-Legendre quadrature points and weights R = zeros(Float64, m, m) for i = 1:m - 1 R[i,i+1] = i / sqrt((2 * i)^2 - 1) @@ -1854,6 +1920,168 @@ function logm{T<:Union{Float64,Complex{Float64}}}(A0::UpperTriangular{T}) end logm(A::LowerTriangular) = logm(A.').' +# Auxiliary functions for logm and matrix power + +# Compute accurate diagonal of A = A0^s - I +# Al-Mohy, "A more accurate Briggs method for the logarithm", +# Numer. Algorithms, 59, (2012), 393–402. +function sqrt_diag!(A0::UpperTriangular, A::UpperTriangular, s) + n = checksquare(A0) + @inbounds for i = 1:n + a = complex(A0[i,i]) + if s == 0 + A[i,i] = a - 1 + else + s0 = s + if imag(a) >= 0 && real(a) <= 0 && a != 0 + a = sqrt(a) + s0 = s - 1 + end + z0 = a - 1 + a = sqrt(a) + r = 1 + a + for j = 1:s0-1 + a = sqrt(a) + r = r * (1 + a) + end + A[i,i] = z0 / r + end + end +end + +# Repeatedly compute the square roots of A so that in the end its +# eigenvalues are close enough to the positive real line +function invsquaring(A0::UpperTriangular, theta) + maxsqrt = 100 + tmax = size(theta, 1) + n = checksquare(A0) + A = complex(copy(A0)) + p = 0 + m = 0 + + # Compute repeated roots + d = complex(diag(A)) + dm1 = similar(d, n) + s = 0 + for i = 1:n + dm1[i] = d[i] - 1. + end + while norm(dm1, Inf) > theta[tmax] + for i = 1:n + d[i] = sqrt(d[i]) + end + for i = 1:n + dm1[i] = d[i] - 1 + end + s = s + 1 + end + s0 = s + for k = 1:min(s, maxsqrt) + A = sqrtm(A) + end + + AmI = A - I + d2 = sqrt(norm(AmI^2, 1)) + d3 = cbrt(norm(AmI^3, 1)) + alpha2 = max(d2, d3) + foundm = false + if alpha2 <= theta[2] + m = alpha2<=theta[1]?1:2 + foundm = true + end + + while !foundm + more = false + if s > s0 + d3 = cbrt(norm(AmI^3, 1)) + end + d4 = norm(AmI^4, 1)^(1/4) + alpha3 = max(d3, d4) + if alpha3 <= theta[tmax] + for j = 3:tmax + if alpha3 <= theta[j] + break + elseif alpha3 / 2 <= theta[5] && p < 2 + more = true + p = p + 1 + end + end + if j <= 6 + m = j + foundm = true + break + elseif alpha3 / 2 <= theta[5] && p < 2 + more = true + p = p + 1 + end + end + + if !more + d5 = norm(AmI^5, 1)^(1/5) + alpha4 = max(d4, d5) + eta = min(alpha3, alpha4) + if eta <= theta[tmax] + j = 0 + for j = 6:tmax + if eta <= theta[j] + m = j + break + end + break + end + end + if s == maxsqrt + m = tmax + break + end + A = sqrtm(A) + AmI = A - I + s = s + 1 + end + end + + # Compute accurate superdiagonal of T + p = 1 / 2^s + A = complex(A) + blockpower!(A, A0, p) + return A,m,s + +end + +# Compute accurate diagonal and superdiagonal of A = A0^p +function blockpower!(A::UpperTriangular, A0::UpperTriangular, p) + n = checksquare(A0) + @inbounds for k = 1:n-1 + + Ak = complex(A0[k,k]) + Akp1 = complex(A0[k+1,k+1]) + + Akp = Ak^p + Akp1p = Akp1^p + + A[k,k] = Akp + A[k+1,k+1] = Akp1p + + if Ak == Akp1 + A[k,k+1] = p * A0[k,k+1] * Ak^(p-1) + elseif 2 * abs(Ak) < abs(Akp1) || 2 * abs(Akp1) < abs(Ak) + A[k,k+1] = A0[k,k+1] * (Akp1p - Akp) / (Akp1 - Ak) + else + logAk = log(Ak) + logAkp1 = log(Akp1) + w = atanh((Akp1 - Ak)/(Akp1 + Ak)) + im * pi * unw(logAkp1-logAk) + dd = 2 * exp(p*(logAk+logAkp1)/2) * sinh(p*w) / (Akp1 - Ak); + A[k,k+1] = A0[k,k+1] * dd + end + end +end + +# Unwinding number +unw(x::Real) = 0 +unw(x::Number) = ceil((imag(x) - pi) / (2 * pi)) + +# End of auxiliary functions for logm and matrix power + function sqrtm(A::UpperTriangular) realmatrix = false if isreal(A) diff --git a/test/linalg/dense.jl b/test/linalg/dense.jl index fdf107d743469..3a7893f73ea05 100644 --- a/test/linalg/dense.jl +++ b/test/linalg/dense.jl @@ -512,6 +512,39 @@ end @test_throws ArgumentError diag(zeros(0,1),2) end +@testset "New matrix ^ implementation" for elty in (Float64, Complex{Float64}) + A11 = convert(Matrix{elty}, [1 2 3; 4 7 1; 2 1 4]) + + OLD_STDERR = STDERR + rd,wr = redirect_stderr() + + @test A11^(1/2) ≈ sqrtm(A11) + s = readline(rd) + @test contains(s, "WARNING: Matrix with nonpositive real eigenvalues, a nonprincipal matrix power will be returned.") + + @test A11^(-1/2) ≈ inv(sqrtm(A11)) + s = readline(rd) + @test contains(s, "WARNING: Matrix with nonpositive real eigenvalues, a nonprincipal matrix power will be returned.") + + @test A11^(3/4) ≈ sqrtm(A11) * sqrtm(sqrtm(A11)) + s = readline(rd) + @test contains(s, "WARNING: Matrix with nonpositive real eigenvalues, a nonprincipal matrix power will be returned.") + + @test A11^(-3/4) ≈ inv(A11) * sqrtm(sqrtm(A11)) + s = readline(rd) + @test contains(s, "WARNING: Matrix with nonpositive real eigenvalues, a nonprincipal matrix power will be returned.") + + @test A11^(17/8) ≈ A11^2 * sqrtm(sqrtm(sqrtm(A11))) + s = readline(rd) + @test contains(s, "WARNING: Matrix with nonpositive real eigenvalues, a nonprincipal matrix power will be returned.") + + @test A11^(-17/8) ≈ inv(A11^2 * sqrtm(sqrtm(sqrtm(A11)))) + s = readline(rd) + @test contains(s, "WARNING: Matrix with nonpositive real eigenvalues, a nonprincipal matrix power will be returned.") + + redirect_stderr(OLD_STDERR) +end + @testset "Least squares solutions" begin a = [ones(20) 1:20 1:20] b = reshape(eye(8, 5), 20, 2) From 9d633ffd44caf00d28c8e46c9aa56dc3ca63b292 Mon Sep 17 00:00:00 2001 From: iamnapo Date: Mon, 27 Mar 2017 22:48:38 +0300 Subject: [PATCH 0530/1534] reverted powm export. Small fix if Upper-triangular matrix contains Integers. added a few more test for ^;now uses random 10x10 matrix as well. fixed some ambiguities, corrected the algorithm a bit. correctly promotes Matrix{Int}^Float64 reverted some wrong changes reverted logm changes speedup if A is diagonal, fixed some tests small changes based on feedback powm is now scale-invariant powm scales in-place, fixed testing a bit, corrected some bugs removed full() calls added rollback for Matrix^Complex added schur() support for Symmetric,Hermitian,Triangular,Tridiagonal matrices --- base/linalg/dense.jl | 59 ++++++++++++++++----------- base/linalg/linalg.jl | 4 +- base/linalg/schur.jl | 6 +++ base/linalg/symmetric.jl | 8 ++-- base/linalg/triangular.jl | 55 +++++++++++++------------ test/linalg/dense.jl | 85 +++++++++++++++++++++++++-------------- 6 files changed, 131 insertions(+), 86 deletions(-) diff --git a/base/linalg/dense.jl b/base/linalg/dense.jl index c4f08d6bf1847..279691b00d052 100644 --- a/base/linalg/dense.jl +++ b/base/linalg/dense.jl @@ -324,53 +324,66 @@ kron(a::AbstractMatrix, b::AbstractVector)=kron(a,reshape(b,length(b),1)) kron(a::AbstractVector, b::AbstractMatrix)=kron(reshape(a,length(a),1),b) # Matrix power -^(A::AbstractMatrix, p::Integer) = p < 0 ? Base.power_by_squaring(inv(A),-p) : Base.power_by_squaring(A,p) +^{T}(A::AbstractMatrix{T}, p::Integer) = p < 0 ? Base.power_by_squaring(inv(A), -p) : Base.power_by_squaring(A, p) function ^{T}(A::AbstractMatrix{T}, p::Real) # For integer powers, use repeated squaring if isinteger(p) - return A^Integer(real(p)) + TT = Base.promote_op(^, eltype(A), typeof(p)) + return (TT == eltype(A) ? A : copy!(similar(A, TT), A))^Integer(p) end # If possible, use diagonalization - if issymmetric(A) && T <: Real - return full(Symmetric(A)^p) + if T <: Real && issymmetric(A) + return (Symmetric(A)^p) end if ishermitian(A) - return full(Hermitian(A)^p) + return (Hermitian(A)^p) end - # Otherwise, use Schur decomposition n = checksquare(A) + + # Quicker return if A is diagonal + if isdiag(A) + retmat = copy(A) + for i in 1:n + retmat[i, i] = retmat[i, i] ^ p + end + return retmat + end + + # Otherwise, use Schur decomposition if istriu(A) #Integer part - retmat = full(A) ^ floor(p) + retmat = A ^ floor(p) #Real part - retmat = retmat * full(powm(UpperTriangular(A), real(p - floor(p)))) - d = diag(A) + if p - floor(p) == 0.5 + # special case: A^0.5 === sqrtm(A) + retmat = retmat * sqrtm(A) + else + retmat = retmat * powm!(UpperTriangular(float.(A)), real(p - floor(p))) + end else S,Q,d = schur(complex(A)) - R = UpperTriangular(S)^p - retmat = Q * R * Q' - end - - # Check whether the matrix has nonpositive real eigs - np_real_eigs = false - for i = 1:n - if imag(d[i]) < eps() && real(d[i]) <= 0 - np_real_eigs = true - break + #Integer part + R = S ^ floor(p) + #Real part + if p - floor(p) == 0.5 + # special case: A^0.5 === sqrtm(A) + R = R * sqrtm(S) + else + R = R * powm!(UpperTriangular(float.(S)), real(p - floor(p))) end - end - if np_real_eigs - warn("Matrix with nonpositive real eigenvalues, a nonprincipal matrix power will be returned.") + retmat = Q * R * Q' end - if isreal(A) && !np_real_eigs + # if A has nonpositive real eigenvalues, retmat is a nonprincipal matrix power. + if isreal(retmat) return real(retmat) else return retmat end end +^(A::AbstractMatrix, p::Number) = expm(p*logm(A)) # Matrix exponential diff --git a/base/linalg/linalg.jl b/base/linalg/linalg.jl index 0f0b8f253d98c..d92d2c39d8baa 100644 --- a/base/linalg/linalg.jl +++ b/base/linalg/linalg.jl @@ -113,7 +113,6 @@ export ordschur, peakflops, pinv, - powm, qr, qrfact!, qrfact, @@ -263,7 +262,6 @@ include("hessenberg.jl") include("lq.jl") include("eigen.jl") include("svd.jl") -include("schur.jl") include("symmetric.jl") include("cholesky.jl") include("lu.jl") @@ -275,6 +273,8 @@ include("givens.jl") include("special.jl") include("bitarray.jl") include("ldlt.jl") +include("schur.jl") + include("arpack.jl") include("arnoldi.jl") diff --git a/base/linalg/schur.jl b/base/linalg/schur.jl index ad6cd33b800cb..da63220b5128a 100644 --- a/base/linalg/schur.jl +++ b/base/linalg/schur.jl @@ -107,6 +107,12 @@ function schur(A::StridedMatrix) SchurF = schurfact(A) SchurF[:T], SchurF[:Z], SchurF[:values] end +schur(A::Symmetric) = schur(full(A)) +schur(A::Hermitian) = schur(full(A)) +schur(A::UpperTriangular) = schur(full(A)) +schur(A::LowerTriangular) = schur(full(A)) +schur(A::Tridiagonal) = schur(full(A)) + """ ordschur!(F::Schur, select::Union{Vector{Bool},BitVector}) -> F::Schur diff --git a/base/linalg/symmetric.jl b/base/linalg/symmetric.jl index 83fbbedbfefe3..d5e60c038b728 100644 --- a/base/linalg/symmetric.jl +++ b/base/linalg/symmetric.jl @@ -412,8 +412,8 @@ function ^{T<:Real}(A::Symmetric{T}, p::Integer) end end function ^{T<:Real}(A::Symmetric{T}, p::Real) - F = eigfact(full(A)) - if isposdef(F) + F = eigfact(A) + if all(λ -> λ ≥ 0, F.values) retmat = (F.vectors * Diagonal((F.values).^p)) * F.vectors' else retmat = (F.vectors * Diagonal((complex(F.values)).^p)) * F.vectors' @@ -435,7 +435,7 @@ end function ^{T}(A::Hermitian{T}, p::Real) n = checksquare(A) F = eigfact(A) - if isposdef(F) + if all(λ -> λ ≥ 0, F.values) retmat = (F.vectors * Diagonal((F.values).^p)) * F.vectors' if T <: Real return Hermitian(retmat) @@ -451,7 +451,7 @@ function ^{T}(A::Hermitian{T}, p::Real) end end -function expm{T<:Real}(A::Symmetric{T}) +function expm(A::Symmetric) F = eigfact(A) return Symmetric((F.vectors * Diagonal(exp.(F.values))) * F.vectors') end diff --git a/base/linalg/triangular.jl b/base/linalg/triangular.jl index 2b70b42ee8fa9..abdcc93bc3e8d 100644 --- a/base/linalg/triangular.jl +++ b/base/linalg/triangular.jl @@ -1668,22 +1668,25 @@ Ac_ldiv_B(::Union{UnitUpperTriangular,UnitLowerTriangular}, ::RowVector) = throw # Higham and Lin, "An improved Schur-Padé algorithm for fractional powers of # a matrix and their Fréchet derivatives", SIAM. J. Matrix Anal. & Appl., # 34(3), (2013) 1341–1360. -function powm(A0::UpperTriangular{T}, p::Real) where T<:BlasFloat +function powm!(A0::UpperTriangular{<:BlasFloat}, p::Real) if abs(p) >= 1 ArgumentError("p must be a real number in (-1,1), got $p") end + normA0 = norm(A0, 1) + scale!(A0, 1/normA0) + theta = [1.53e-5, 2.25e-3, 1.92e-2, 6.08e-2, 1.25e-1, 2.03e-1, 2.84e-1] n = checksquare(A0) - A, m, s = invsquaring(A0,theta) + A, m, s = invsquaring(A0, theta) A = I - A # Compute accurate diagonal of I - T - sqrt_diag!(A0,A,s) + sqrt_diag!(A0, A, s) for i = 1:n - A[i,i] = -A[i,i] + A[i, i] = -A[i, i] end # Compute the Padé approximant c = 0.5 * (p - m) / (2 * m - 1) @@ -1694,39 +1697,39 @@ function powm(A0::UpperTriangular{T}, p::Real) where T<:BlasFloat j4 = 4 * j c = (-p - j) / (j4 + 2) for i = 1:n - @inbounds S[i,i] = S[i,i] + 1 + @inbounds S[i, i] = S[i, i] + 1 end - copy!(Stmp,S) - scale!(S,A,c) - A_ldiv_B!(Stmp,S.data) + copy!(Stmp, S) + scale!(S, A, c) + A_ldiv_B!(Stmp, S.data) c = (p - j) / (j4 - 2) for i = 1:n - @inbounds S[i,i] = S[i,i] + 1 + @inbounds S[i, i] = S[i, i] + 1 end - copy!(Stmp,S) - scale!(S,A,c) - A_ldiv_B!(Stmp,S.data) + copy!(Stmp, S) + scale!(S, A, c) + A_ldiv_B!(Stmp, S.data) end for i = 1:n - S[i,i] = S[i,i] + 1 + S[i, i] = S[i, i] + 1 end - copy!(Stmp,S) - scale!(S,A,-p) - A_ldiv_B!(Stmp,S.data) + copy!(Stmp, S) + scale!(S, A, -p) + A_ldiv_B!(Stmp, S.data) for i = 1:n - @inbounds S[i,i] = S[i,i] + 1 + @inbounds S[i, i] = S[i, i] + 1 end - blockpower!(A0,S,p/(2^s)) + blockpower!(A0, S, p/(2^s)) for m = 1:s - A_mul_B!(Stmp.data,S,S) - copy!(S,Stmp) - blockpower!(A0,S,p/(2^(s-m))) + A_mul_B!(Stmp.data, S, S) + copy!(S, Stmp) + blockpower!(A0, S, p/(2^(s-m))) end + scale!(S, normA0^p) return S end -^(A::LowerTriangular, p::Integer) = ^(A.', p::Integer).' powm(A::LowerTriangular, p::Real) = powm(A.', p::Real).' # Complex matrix logarithm for the upper triangular factor, see: @@ -1949,9 +1952,11 @@ function sqrt_diag!(A0::UpperTriangular, A::UpperTriangular, s) end end +# Used only by powm at the moment # Repeatedly compute the square roots of A so that in the end its # eigenvalues are close enough to the positive real line function invsquaring(A0::UpperTriangular, theta) + # assumes theta is in ascending order maxsqrt = 100 tmax = size(theta, 1) n = checksquare(A0) @@ -1964,13 +1969,11 @@ function invsquaring(A0::UpperTriangular, theta) dm1 = similar(d, n) s = 0 for i = 1:n - dm1[i] = d[i] - 1. + dm1[i] = d[i] - 1 end while norm(dm1, Inf) > theta[tmax] for i = 1:n d[i] = sqrt(d[i]) - end - for i = 1:n dm1[i] = d[i] - 1 end s = s + 1 @@ -1986,7 +1989,7 @@ function invsquaring(A0::UpperTriangular, theta) alpha2 = max(d2, d3) foundm = false if alpha2 <= theta[2] - m = alpha2<=theta[1]?1:2 + m = alpha2 <= theta[1] ? 1 : 2 foundm = true end diff --git a/test/linalg/dense.jl b/test/linalg/dense.jl index 3a7893f73ea05..c7639f13a0d06 100644 --- a/test/linalg/dense.jl +++ b/test/linalg/dense.jl @@ -512,37 +512,60 @@ end @test_throws ArgumentError diag(zeros(0,1),2) end -@testset "New matrix ^ implementation" for elty in (Float64, Complex{Float64}) - A11 = convert(Matrix{elty}, [1 2 3; 4 7 1; 2 1 4]) - - OLD_STDERR = STDERR - rd,wr = redirect_stderr() - - @test A11^(1/2) ≈ sqrtm(A11) - s = readline(rd) - @test contains(s, "WARNING: Matrix with nonpositive real eigenvalues, a nonprincipal matrix power will be returned.") - - @test A11^(-1/2) ≈ inv(sqrtm(A11)) - s = readline(rd) - @test contains(s, "WARNING: Matrix with nonpositive real eigenvalues, a nonprincipal matrix power will be returned.") - - @test A11^(3/4) ≈ sqrtm(A11) * sqrtm(sqrtm(A11)) - s = readline(rd) - @test contains(s, "WARNING: Matrix with nonpositive real eigenvalues, a nonprincipal matrix power will be returned.") - - @test A11^(-3/4) ≈ inv(A11) * sqrtm(sqrtm(A11)) - s = readline(rd) - @test contains(s, "WARNING: Matrix with nonpositive real eigenvalues, a nonprincipal matrix power will be returned.") - - @test A11^(17/8) ≈ A11^2 * sqrtm(sqrtm(sqrtm(A11))) - s = readline(rd) - @test contains(s, "WARNING: Matrix with nonpositive real eigenvalues, a nonprincipal matrix power will be returned.") - - @test A11^(-17/8) ≈ inv(A11^2 * sqrtm(sqrtm(sqrtm(A11)))) - s = readline(rd) - @test contains(s, "WARNING: Matrix with nonpositive real eigenvalues, a nonprincipal matrix power will be returned.") - - redirect_stderr(OLD_STDERR) +@testset "Matrix to real power" for elty in (Float64, Complex{Float64}) +# Tests proposed at Higham, Deadman: Testing Matrix Function Algorithms Using Identities, March 2014 + + #Aa : only positive real eigenvalues + Aa = convert(Matrix{elty}, [5 4 2 1; 0 1 -1 -1; -1 -1 3 0; 1 1 -1 2]) + + @test Aa^(1/2) ≈ sqrtm(Aa) + @test Aa^(-1/2) ≈ inv(sqrtm(Aa)) + @test Aa^(3/4) ≈ sqrtm(Aa) * sqrtm(sqrtm(Aa)) + @test Aa^(-3/4) ≈ inv(Aa) * sqrtm(sqrtm(Aa)) + @test Aa^(17/8) ≈ Aa^2 * sqrtm(sqrtm(sqrtm(Aa))) + @test Aa^(-17/8) ≈ inv(Aa^2 * sqrtm(sqrtm(sqrtm(Aa)))) + @test (Aa^0.2)^5 ≈ Aa + @test (Aa^(2/3))*(Aa^(1/3)) ≈ Aa + @test (Aa^im)^(-im) ≈ Aa + + #Ab : both positive and negative real eigenvalues + Ab = convert(Matrix{elty}, [1 2 3; 4 7 1; 2 1 4]) + + @test Ab^(1/2) ≈ sqrtm(Ab) + @test Ab^(-1/2) ≈ inv(sqrtm(Ab)) + @test Ab^(3/4) ≈ sqrtm(Ab) * sqrtm(sqrtm(Ab)) + @test Ab^(-3/4) ≈ inv(Ab) * sqrtm(sqrtm(Ab)) + @test Ab^(17/8) ≈ Ab^2 * sqrtm(sqrtm(sqrtm(Ab))) + @test Ab^(-17/8) ≈ inv(Ab^2 * sqrtm(sqrtm(sqrtm(Ab)))) + @test (Ab^0.2)^5 ≈ Ab + @test (Ab^(2/3))*(Ab^(1/3)) ≈ Ab + @test (Ab^im)^(-im) ≈ Ab + + #Ac : complex eigenvalues + Ac = convert(Matrix{elty}, [5 4 2 1;0 1 -1 -1;-1 -1 3 6;1 1 -1 5]) + + @test Ac^(1/2) ≈ sqrtm(Ac) + @test Ac^(-1/2) ≈ inv(sqrtm(Ac)) + @test Ac^(3/4) ≈ sqrtm(Ac) * sqrtm(sqrtm(Ac)) + @test Ac^(-3/4) ≈ inv(Ac) * sqrtm(sqrtm(Ac)) + @test Ac^(17/8) ≈ Ac^2 * sqrtm(sqrtm(sqrtm(Ac))) + @test Ac^(-17/8) ≈ inv(Ac^2 * sqrtm(sqrtm(sqrtm(Ac)))) + @test (Ac^0.2)^5 ≈ Ac + @test (Ac^(2/3))*(Ac^(1/3)) ≈ Ac + @test (Ac^im)^(-im) ≈ Ac + + #Ad : defective Matrix + Ad = convert(Matrix{elty}, [3 1; 0 3]) + + @test Ad^(1/2) ≈ sqrtm(Ad) + @test Ad^(-1/2) ≈ inv(sqrtm(Ad)) + @test Ad^(3/4) ≈ sqrtm(Ad) * sqrtm(sqrtm(Ad)) + @test Ad^(-3/4) ≈ inv(Ad) * sqrtm(sqrtm(Ad)) + @test Ad^(17/8) ≈ Ad^2 * sqrtm(sqrtm(sqrtm(Ad))) + @test Ad^(-17/8) ≈ inv(Ad^2 * sqrtm(sqrtm(sqrtm(Ad)))) + @test (Ad^0.2)^5 ≈ Ad + @test (Ad^(2/3))*(Ad^(1/3)) ≈ Ad + @test (Ad^im)^(-im) ≈ Ad end @testset "Least squares solutions" begin From 2fbeba3faee6197fadf475364538b9b17fbef9e6 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Sun, 23 Apr 2017 08:56:16 -0400 Subject: [PATCH 0531/1534] Remove some blank lines at start or end of blocks and be uniform about space after # in comments --- base/linalg/dense.jl | 10 +++++----- base/linalg/symmetric.jl | 8 ++++---- base/linalg/triangular.jl | 8 ++------ test/linalg/dense.jl | 1 - 4 files changed, 11 insertions(+), 16 deletions(-) diff --git a/base/linalg/dense.jl b/base/linalg/dense.jl index 279691b00d052..70222f62844c0 100644 --- a/base/linalg/dense.jl +++ b/base/linalg/dense.jl @@ -29,7 +29,7 @@ function scale!(X::Array{T}, s::Real) where T<:BlasComplex X end -#Test whether a matrix is positive-definite +# Test whether a matrix is positive-definite isposdef!(A::StridedMatrix{<:BlasFloat}, UL::Symbol) = LAPACK.potrf!(char_uplo(UL), A)[2] == 0 """ @@ -353,9 +353,9 @@ function ^{T}(A::AbstractMatrix{T}, p::Real) # Otherwise, use Schur decomposition if istriu(A) - #Integer part + # Integer part retmat = A ^ floor(p) - #Real part + # Real part if p - floor(p) == 0.5 # special case: A^0.5 === sqrtm(A) retmat = retmat * sqrtm(A) @@ -364,9 +364,9 @@ function ^{T}(A::AbstractMatrix{T}, p::Real) end else S,Q,d = schur(complex(A)) - #Integer part + # Integer part R = S ^ floor(p) - #Real part + # Real part if p - floor(p) == 0.5 # special case: A^0.5 === sqrtm(A) R = R * sqrtm(S) diff --git a/base/linalg/symmetric.jl b/base/linalg/symmetric.jl index d5e60c038b728..f417ce2ead09f 100644 --- a/base/linalg/symmetric.jl +++ b/base/linalg/symmetric.jl @@ -1,6 +1,6 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -#Symmetric and Hermitian matrices +# Symmetric and Hermitian matrices struct Symmetric{T,S<:AbstractMatrix} <: AbstractMatrix{T} data::S uplo::Char @@ -181,7 +181,7 @@ trace(A::Hermitian) = real(trace(A.data)) Base.conj(A::HermOrSym) = typeof(A)(conj(A.data), A.uplo) Base.conj!(A::HermOrSym) = typeof(A)(conj!(A.data), A.uplo) -#tril/triu +# tril/triu function tril(A::Hermitian, k::Integer=0) if A.uplo == 'U' && k <= 0 return tril!(A.data',k) @@ -235,7 +235,7 @@ end ## Matvec A_mul_B!{T<:BlasFloat}(y::StridedVector{T}, A::Symmetric{T,<:StridedMatrix}, x::StridedVector{T}) = BLAS.symv!(A.uplo, one(T), A.data, x, zero(T), y) A_mul_B!{T<:BlasComplex}(y::StridedVector{T}, A::Hermitian{T,<:StridedMatrix}, x::StridedVector{T}) = BLAS.hemv!(A.uplo, one(T), A.data, x, zero(T), y) -##Matmat +## Matmat A_mul_B!{T<:BlasFloat}(C::StridedMatrix{T}, A::Symmetric{T,<:StridedMatrix}, B::StridedMatrix{T}) = BLAS.symm!('L', A.uplo, one(T), A.data, B, zero(T), C) A_mul_B!{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedMatrix{T}, B::Symmetric{T,<:StridedMatrix}) = BLAS.symm!('R', B.uplo, one(T), B.data, A, zero(T), C) A_mul_B!{T<:BlasComplex}(C::StridedMatrix{T}, A::Hermitian{T,<:StridedMatrix}, B::StridedMatrix{T}) = BLAS.hemm!('L', A.uplo, one(T), A.data, B, zero(T), C) @@ -403,7 +403,7 @@ function svdvals!{T<:Real,S}(A::Union{Hermitian{T,S}, Symmetric{T,S}, Hermitian{ return sort!(vals, rev = true) end -#Matrix functions +# Matrix functions function ^{T<:Real}(A::Symmetric{T}, p::Integer) if p < 0 return Symmetric(Base.power_by_squaring(inv(A), -p)) diff --git a/base/linalg/triangular.jl b/base/linalg/triangular.jl index abdcc93bc3e8d..e940ff2c138e8 100644 --- a/base/linalg/triangular.jl +++ b/base/linalg/triangular.jl @@ -1669,7 +1669,6 @@ Ac_ldiv_B(::Union{UnitUpperTriangular,UnitLowerTriangular}, ::RowVector) = throw # a matrix and their Fréchet derivatives", SIAM. J. Matrix Anal. & Appl., # 34(3), (2013) 1341–1360. function powm!(A0::UpperTriangular{<:BlasFloat}, p::Real) - if abs(p) >= 1 ArgumentError("p must be a real number in (-1,1), got $p") end @@ -1919,7 +1918,6 @@ function logm{T<:Union{Float64,Complex{Float64}}}(A0::UpperTriangular{T}) end return UpperTriangular(Y) - end logm(A::LowerTriangular) = logm(A.').' @@ -2048,14 +2046,12 @@ function invsquaring(A0::UpperTriangular, theta) A = complex(A) blockpower!(A, A0, p) return A,m,s - end # Compute accurate diagonal and superdiagonal of A = A0^p function blockpower!(A::UpperTriangular, A0::UpperTriangular, p) n = checksquare(A0) @inbounds for k = 1:n-1 - Ak = complex(A0[k,k]) Akp1 = complex(A0[k+1,k+1]) @@ -2138,7 +2134,7 @@ end sqrtm(A::LowerTriangular) = sqrtm(A.').' sqrtm(A::UnitLowerTriangular) = sqrtm(A.').' -#Generic eigensystems +# Generic eigensystems eigvals(A::AbstractTriangular) = diag(A) function eigvecs{T}(A::AbstractTriangular{T}) TT = promote_type(T, Float32) @@ -2169,7 +2165,7 @@ end eigfact(A::AbstractTriangular) = Eigen(eigvals(A), eigvecs(A)) -#Generic singular systems +# Generic singular systems for func in (:svd, :svdfact, :svdfact!, :svdvals) @eval begin ($func)(A::AbstractTriangular) = ($func)(full(A)) diff --git a/test/linalg/dense.jl b/test/linalg/dense.jl index c7639f13a0d06..29a7659caad0f 100644 --- a/test/linalg/dense.jl +++ b/test/linalg/dense.jl @@ -514,7 +514,6 @@ end @testset "Matrix to real power" for elty in (Float64, Complex{Float64}) # Tests proposed at Higham, Deadman: Testing Matrix Function Algorithms Using Identities, March 2014 - #Aa : only positive real eigenvalues Aa = convert(Matrix{elty}, [5 4 2 1; 0 1 -1 -1; -1 -1 3 0; 1 1 -1 2]) From 73afd870b2ac191d2193acde13e2bc1cfd447c79 Mon Sep 17 00:00:00 2001 From: Chris Foster Date: Sun, 23 Apr 2017 21:37:42 +1000 Subject: [PATCH 0532/1534] Ignore nulls from terminal CTRL-space in LineEdit By default some terminals (eg, xterm) generate '\0' when CTRL-space is pressed. However, '\0' is used internally by the key map system to represent a wildcard (see normalize_key()), so cannot be handled without a larger overhaul. Instead, just ignore it to avoid user confusion with lines containing an invisible, unparsable character. Fixes #7001 --- base/LineEdit.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/base/LineEdit.jl b/base/LineEdit.jl index 5df447d9837a6..9909082adf97e 100644 --- a/base/LineEdit.jl +++ b/base/LineEdit.jl @@ -725,6 +725,9 @@ function match_input(k::Dict, s, term=terminal(s), cs=Char[], keymap = k) # return an empty keymap function eof(term) && return keymap_fcn(nothing, "") c = read(term, Char) + # Ignore any '\0' (eg, CTRL-space in xterm), as this is used as a + # placeholder for the wildcard (see normalize_key("*")) + c != '\0' || return keymap_fcn(nothing, "") push!(cs, c) key = haskey(k, c) ? c : '\0' # if we don't match on the key, look for a default action then fallback on 'nothing' to ignore From 099e619cb2e1d6f2d6d8071f7ab31dc81f3c84be Mon Sep 17 00:00:00 2001 From: Mus M Date: Sun, 23 Apr 2017 11:25:47 -0400 Subject: [PATCH 0533/1534] Fix the printing of flags in build_sysimg.jl --- contrib/build_sysimg.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/build_sysimg.jl b/contrib/build_sysimg.jl index 2805695612273..8c08248f5a767 100644 --- a/contrib/build_sysimg.jl +++ b/contrib/build_sysimg.jl @@ -157,7 +157,7 @@ function link_sysimg(sysimg_path=nothing, cc=find_system_compiler(), debug=false sysimg_file = "$sysimg_path.$(Libdl.dlext)" info("Linking sys.$(Libdl.dlext)") - info("$cc $FLAGS -o $sysimg_file $sysimg_path.o") + info("$cc $(join(FLAGS, ' ')) -o $sysimg_file $sysimg_path.o") # Windows has difficulties overwriting a file in use so we first link to a temp file if is_windows() && isfile(sysimg_file) if success(pipeline(`$cc $FLAGS -o $sysimg_path.tmp $sysimg_path.o`; stdout=STDOUT, stderr=STDERR)) From 91eddf82f37b1b7d95147baea2d2421db56dffa2 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Sun, 23 Apr 2017 11:49:24 -0400 Subject: [PATCH 0534/1534] Fix clang warnings --- src/julia_internal.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/julia_internal.h b/src/julia_internal.h index 205471b1e7d2e..00cb0f60c955f 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -47,9 +47,14 @@ #endif #if jl_has_builtin(__builtin_assume) -#define jl_assume(cond) (__extension__ ({ \ - __builtin_assume(!!(cond)); \ - cond; \ +static inline void jl_assume_(int cond) +{ + __builtin_assume(cond); +} +#define jl_assume(cond) (__extension__ ({ \ + __typeof__(cond) cond_ = (cond); \ + jl_assume_(!!(cond_)); \ + cond; \ })) #elif defined(_COMPILER_GCC_) static inline void jl_assume_(int cond) From a7aecd3f5e9facd5814b1cf4634b0928dabcadcb Mon Sep 17 00:00:00 2001 From: Mus M Date: Sun, 23 Apr 2017 13:17:54 -0400 Subject: [PATCH 0535/1534] Use isempty to check for empty strings (#21496) --- base/distributed/cluster.jl | 4 ++-- base/interactiveutil.jl | 2 +- base/markdown/Common/block.jl | 2 +- base/markdown/GitHub/table.jl | 6 +++--- base/markdown/render/html.jl | 2 +- base/pkg/entry.jl | 2 +- base/socket.jl | 2 +- base/version.jl | 4 ++-- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/base/distributed/cluster.jl b/base/distributed/cluster.jl index 053f600da025a..03e9173d5c5a8 100644 --- a/base/distributed/cluster.jl +++ b/base/distributed/cluster.jl @@ -232,13 +232,13 @@ function read_worker_host_port(io::IO) !istaskdone(readtask) && break conninfo = wait(readtask) - if conninfo == "" && !isopen(io) + if isempty(conninfo) && !isopen(io) error("Unable to read host:port string from worker. Launch command exited with error?") end ntries -= 1 bind_addr, port = parse_connection_info(conninfo) - if bind_addr != "" + if !isempty(bind_addr) return bind_addr, port end diff --git a/base/interactiveutil.jl b/base/interactiveutil.jl index 2d82b0bdd05b6..8c949d1710706 100644 --- a/base/interactiveutil.jl +++ b/base/interactiveutil.jl @@ -273,7 +273,7 @@ function versioninfo(io::IO=STDOUT, verbose::Bool=false) if is_windows() try lsb = strip(readstring(`$(ENV["COMSPEC"]) /c ver`)) end end - if lsb != "" + if !isempty(lsb) println(io, " ", lsb) end if is_unix() diff --git a/base/markdown/Common/block.jl b/base/markdown/Common/block.jl index 6815ac87a9b56..a0c4a095d3bae 100644 --- a/base/markdown/Common/block.jl +++ b/base/markdown/Common/block.jl @@ -77,7 +77,7 @@ function setextheader(stream::IO, md::MD) withstream(stream) do eatindent(stream) || return false header = strip(readline(stream)) - header == "" && return false + isempty(header) && return false eatindent(stream) || return false underline = strip(readline(stream)) diff --git a/base/markdown/GitHub/table.jl b/base/markdown/GitHub/table.jl index 31898506507f1..a8313e3fa6629 100644 --- a/base/markdown/GitHub/table.jl +++ b/base/markdown/GitHub/table.jl @@ -10,9 +10,9 @@ function parserow(stream::IO) line = readline(stream) row = split(line, r"(? strip(replace(x, "\\|", "|")), row, row) - row[end] == "" && pop!(row) + isempty(row[end]) && pop!(row) return row end end @@ -45,7 +45,7 @@ function github_table(stream::IO, md::MD) align = nothing while (row = parserow(stream)) !== nothing if length(rows) == 0 - row[1] == "" && return false + isempty(row[1]) && return false cols = length(row) end if align === nothing && length(rows) == 1 # Must have a --- row diff --git a/base/markdown/render/html.jl b/base/markdown/render/html.jl index 3aadf0e914ddb..ae74794168c35 100644 --- a/base/markdown/render/html.jl +++ b/base/markdown/render/html.jl @@ -67,7 +67,7 @@ end function html(io::IO, code::Code) withtag(io, :pre) do - maybe_lang = code.language != "" ? Any[:class=>"language-$(code.language)"] : [] + maybe_lang = !isempty(code.language) ? Any[:class=>"language-$(code.language)"] : [] withtag(io, :code, maybe_lang...) do htmlesc(io, code.code) # TODO should print newline if this is longer than one line ? diff --git a/base/pkg/entry.jl b/base/pkg/entry.jl index 926f77c83ed5d..945953859d2b2 100644 --- a/base/pkg/entry.jl +++ b/base/pkg/entry.jl @@ -125,7 +125,7 @@ function installed(pkg::AbstractString) end function status(io::IO; pkgname::AbstractString = "") - showpkg(pkg) = (pkgname == "") ? (true) : (pkg == pkgname) + showpkg(pkg) = isempty(pkgname) ? true : (pkg == pkgname) reqs = Reqs.parse("REQUIRE") instd = Read.installed() required = sort!(collect(keys(reqs))) diff --git a/base/socket.jl b/base/socket.jl index ed990e9945d7e..57a83640a2a57 100644 --- a/base/socket.jl +++ b/base/socket.jl @@ -199,7 +199,7 @@ function parseipv6fields(fields,num_fields) cf = 7 ret = UInt128(0) for f in fields - if f == "" + if isempty(f) # ::abc:... and ..:abc:: if cf != 7 && cf != 0 cf -= num_fields-length(fields) diff --git a/base/version.jl b/base/version.jl index 480faa91796e8..1bae427a64576 100644 --- a/base/version.jl +++ b/base/version.jl @@ -226,7 +226,7 @@ end function banner(io::IO = STDOUT) if GIT_VERSION_INFO.tagged_commit commit_string = TAGGED_RELEASE_BANNER - elseif GIT_VERSION_INFO.commit == "" + elseif isempty(GIT_VERSION_INFO.commit) commit_string = "" else days = Int(floor((ccall(:jl_clock_now, Float64, ()) - GIT_VERSION_INFO.fork_master_timestamp) / (60 * 60 * 24))) @@ -242,7 +242,7 @@ function banner(io::IO = STDOUT) commit_string = "$(branch)/$(commit) (fork: $(distance) commits, $(days) $(unit))" end end - commit_date = GIT_VERSION_INFO.date_string != "" ? " ($(GIT_VERSION_INFO.date_string))": "" + commit_date = !isempty(GIT_VERSION_INFO.date_string) ? " ($(GIT_VERSION_INFO.date_string))": "" if have_color c = text_colors From 5955d79289a3e27f863c401831d2c647a957d289 Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Sun, 23 Apr 2017 11:30:09 -0700 Subject: [PATCH 0536/1534] Fix behavior of foldr on single-element arrays (#21497) Fixes #21493 --- base/reduce.jl | 2 +- test/reduce.jl | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/base/reduce.jl b/base/reduce.jl index a5996af9b5dee..a8b3e80d802be 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -104,7 +104,7 @@ foldl(op, itr) = mapfoldl(identity, op, itr) function mapfoldr_impl(f, op, v0, itr, i::Integer) # Unroll the while loop once; if v0 is known, the call to op may # be evaluated at compile time - if isempty(itr) + if isempty(itr) || i == 0 return r_promote(op, v0) else x = itr[i] diff --git a/test/reduce.jl b/test/reduce.jl index d27ef930c929f..74a4c72eee030 100644 --- a/test/reduce.jl +++ b/test/reduce.jl @@ -22,6 +22,7 @@ @test foldr(+, Int16[]) === Int32(0) @test foldr(-, 1:5) == 3 @test foldr(-, 10, 1:5) == -7 +@test foldr(+, [1]) == 1 # Issue #21493 @test Base.mapfoldr(abs2, -, 2:5) == -14 @test Base.mapfoldr(abs2, -, 10, 2:5) == -4 From 9959cc0f87e71bcb2252cca9406f2d7428752f0c Mon Sep 17 00:00:00 2001 From: Rory-Finnegan Date: Sun, 23 Apr 2017 15:39:55 -0500 Subject: [PATCH 0537/1534] Replaced `isempty` block in `filter!(f, a::AbstractVector)` with single line check. --- base/array.jl | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/base/array.jl b/base/array.jl index d88a9ab44cc97..d40960d19dc91 100644 --- a/base/array.jl +++ b/base/array.jl @@ -1807,21 +1807,21 @@ julia> filter(isodd, a) filter(f, As::AbstractArray) = As[map(f, As)::AbstractArray{Bool}] function filter!(f, a::AbstractVector) - if !isempty(a) - idx = eachindex(a) - state = start(idx) - i, state = next(idx, state) - - for acurr in a - if f(acurr) - a[i] = acurr - i, state = next(idx, state) - end - end + isempty(a) && return a + + idx = eachindex(a) + state = start(idx) + i, state = next(idx, state) - deleteat!(a, i:last(idx)) + for acurr in a + if f(acurr) + a[i] = acurr + i, state = next(idx, state) + end end + deleteat!(a, i:last(idx)) + return a end From 0ec079a32a572b777fa79f35308a3ab5d88c0ed7 Mon Sep 17 00:00:00 2001 From: Chris Foster Date: Mon, 24 Apr 2017 00:18:02 +1000 Subject: [PATCH 0538/1534] Test that LineEdit ignores null bytes --- test/repl.jl | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/repl.jl b/test/repl.jl index ff42c4c69fc3d..2b9eaa9932b62 100644 --- a/test/repl.jl +++ b/test/repl.jl @@ -125,6 +125,14 @@ if !is_windows() || Sys.windows_version() >= Sys.WINDOWS_VISTA_VER startswith(s, "\e[0m\e[1m\e[91mERROR: \e[39m\e[22m\e[91munterminated single quote\e[39m\nStacktrace:\n [1] ") end + # Issue #7001 + # Test ignoring '\0' + let + write(stdin_write, "\0\n") + s = readuntil(stdout_read, "\n\n") + @test !contains(s, "invalid character") + end + # Test that accepting a REPL result immediately shows up, not # just on the next keystroke write(stdin_write, "1+1\n") # populate history with a trivial input @@ -137,6 +145,7 @@ if !is_windows() || Sys.windows_version() >= Sys.WINDOWS_VISTA_VER # yield make sure this got processed readuntil(stdout_read, "1+1") close(t) + readuntil(stdout_read, "\n\n") # Issue #10222 # Test ignoring insert key in standard and prefix search modes From 5f7797f0ca0efc898f5f62e43eb5e5d2f94f19bb Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Mon, 24 Apr 2017 10:26:35 +0900 Subject: [PATCH 0539/1534] relax timing bounds in test/pollfd due to potential timing jitter --- test/pollfd.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/pollfd.jl b/test/pollfd.jl index 6751fb0942485..0218ac8fc104c 100644 --- a/test/pollfd.jl +++ b/test/pollfd.jl @@ -136,7 +136,7 @@ end e = @elapsed for i = 1:5 wait(t) end - @test 1.5 > e > 0.5 + @test 1.5 > e >= 0.4 @test a[] == 0 nothing end From c18e0391c62d966646dc29d6ef3e60b2fec89865 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 24 Apr 2017 00:21:07 -0400 Subject: [PATCH 0540/1534] fix #21516, `where` with constructor of non-parametric type --- src/julia-syntax.scm | 12 ++++++++++-- test/core.jl | 9 +++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index ce9c7dd6d1361..0b099375d97e4 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -763,12 +763,20 @@ (curlyargs (if curly? (cddr name) '())) (name (if curly? (cadr name) name))) (cond ((not (eq? name Tname)) - `(,keyword ,(with-wheres `(call (curly ,name ,@curlyargs) ,@sig) wheres) + `(,keyword ,(with-wheres `(call ,(if curly? + `(curly ,name ,@curlyargs) + name) + ,@sig) + wheres) ;; pass '() in order to require user-specified parameters with ;; new{...} inside a non-ctor inner definition. ,(ctor-body body '()))) (wheres - `(,keyword (where (call (curly ,name ,@curlyargs) ,@sig) ,@wheres) + `(,keyword ,(with-wheres `(call ,(if curly? + `(curly ,name ,@curlyargs) + name) + ,@sig) + wheres) ,(ctor-body body curlyargs))) (else (let* ((temp (ctor-signature name params bounds curlyargs sig)) diff --git a/test/core.jl b/test/core.jl index d685007287bd4..41bec99537842 100644 --- a/test/core.jl +++ b/test/core.jl @@ -4856,3 +4856,12 @@ let ni128 = sizeof(FP128test) ÷ sizeof(Int), end @test reinterpret(UInt128, arr[2].fp) == expected end + +# issue #21516 +struct T21516 + x::Vector{Float64} + y::Vector{Float64} + # check that this definition works + T21516(x::Vector{T}, y::Vector{T}) where {T<:Real} = new(float.(x), float.(y)) +end +@test isa(T21516([1],[2]).x, Vector{Float64}) From 36bb61a536e522b6dc9443fc4d8408ea12ae0dd3 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Mon, 24 Apr 2017 13:28:09 +0900 Subject: [PATCH 0541/1534] check if cachefile dependencies can be fulfilled (#21492) --- base/loading.jl | 38 +++++++++++++++++++++++++++----------- test/compile.jl | 41 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 65 insertions(+), 14 deletions(-) diff --git a/base/loading.jl b/base/loading.jl index 9bda0da89d14f..b85828e37a8b3 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -699,7 +699,16 @@ function parse_cache_header(f::IO) push!(files, (String(read(f, n)), ntoh(read(f, Float64)))) end @assert totbytes == 4 "header of cache file appears to be corrupt" - return modules, files + # read the list of modules that are required to be present during loading + required_modules = Dict{Symbol,UInt64}() + while true + n = ntoh(read(f, Int32)) + n == 0 && break + sym = Symbol(read(f, n)) # module symbol + uuid = ntoh(read(f, UInt64)) # module UUID + required_modules[sym] = uuid + end + return modules, files, required_modules end function parse_cache_header(cachefile::String) @@ -713,15 +722,7 @@ function parse_cache_header(cachefile::String) end function cache_dependencies(f::IO) - defs, files = parse_cache_header(f) - modules = [] - while true - n = ntoh(read(f, Int32)) - n == 0 && break - sym = Symbol(read(f, n)) # module symbol - uuid = ntoh(read(f, UInt64)) # module UUID (mostly just a timestamp) - push!(modules, (sym, uuid)) - end + defs, files, modules = parse_cache_header(f) return modules, files end @@ -742,7 +743,22 @@ function stale_cachefile(modpath::String, cachefile::String) DEBUG_LOADING[] && info("JL_DEBUG_LOADING: Rejecting cache file $cachefile due to it containing an invalid cache header.") return true # invalid cache file end - modules, files = parse_cache_header(io) + modules, files, required_modules = parse_cache_header(io) + + # Check if transitive dependencies can be fullfilled + for mod in keys(required_modules) + if mod == :Main || mod == :Core || mod == :Base + continue + # Module is already loaded + elseif isdefined(Main, mod) + continue + end + name = string(mod) + path = find_in_node_path(name, nothing, 1) + if path === nothing + return true # Won't be able to fullfill dependency + end + end # check if this file is going to provide one of our concrete dependencies # or if it provides a version that conflicts with our concrete dependencies diff --git a/test/compile.jl b/test/compile.jl index a762f39c43c24..0e7274eb9e108 100644 --- a/test/compile.jl +++ b/test/compile.jl @@ -184,13 +184,13 @@ try @test stringmime("text/plain", Base.Docs.doc(Foo.foo)) == "foo function\n" @test stringmime("text/plain", Base.Docs.doc(Foo.Bar.bar)) == "bar function\n" - modules, deps = Base.parse_cache_header(cachefile) + modules, deps, required_modules = Base.parse_cache_header(cachefile) @test modules == Dict(Foo_module => Base.module_uuid(Foo)) @test map(x -> x[1], sort(deps)) == [Foo_file, joinpath(dir, "bar.jl"), joinpath(dir, "foo.jl")] modules, deps1 = Base.cache_dependencies(cachefile) - @test sort(modules) == Any[(s, Base.module_uuid(getfield(Foo, s))) for s in - [:Base, :Core, Foo2_module, FooBase_module, :Main]] + @test modules == Dict(s => Base.module_uuid(getfield(Foo, s)) for s in + [:Base, :Core, Foo2_module, FooBase_module, :Main]) @test deps == deps1 @test current_task()(0x01, 0x4000, 0x30031234) == 2 @@ -325,6 +325,41 @@ try isa(exc, ErrorException) || rethrow(exc) !isempty(search(exc.msg, "ERROR: LoadError: break me")) && rethrow(exc) end + + # Test transitive dependency for #21266 + FooBarT_file = joinpath(dir, "FooBarT.jl") + write(FooBarT_file, + """ + __precompile__(true) + module FooBarT + end + """) + FooBarT1_file = joinpath(dir, "FooBarT1.jl") + write(FooBarT1_file, + """ + __precompile__(true) + module FooBarT1 + using FooBarT + end + """) + FooBarT2_file = joinpath(dir, "FooBarT2.jl") + write(FooBarT2_file, + """ + __precompile__(true) + module FooBarT2 + using FooBarT1 + end + """) + Base.compilecache("FooBarT2") + write(FooBarT1_file, + """ + __precompile__(true) + module FooBarT1 + end + """) + rm(FooBarT_file) + @test Base.stale_cachefile(FooBarT2_file, joinpath(dir2, "FooBarT2.ji")) + @test Base.require(:FooBarT2) === nothing finally splice!(Base.LOAD_CACHE_PATH, 1:2) splice!(LOAD_PATH, 1) From dc907c760fbc73314965aa8ce9db277c1e0c6ad8 Mon Sep 17 00:00:00 2001 From: Viktor Qvarfordt Date: Mon, 24 Apr 2017 06:37:38 +0200 Subject: [PATCH 0542/1534] Add iff, to, implies, and impliedby LaTeX completions (#21495) --- base/latex_symbols.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/base/latex_symbols.jl b/base/latex_symbols.jl index 65b237f28a9d3..2a546b01259eb 100644 --- a/base/latex_symbols.jl +++ b/base/latex_symbols.jl @@ -84,6 +84,10 @@ const latex_symbols = Dict( "\\backpprime" => "‶", "\\backppprime" => "‷", "\\xor" => "⊻", + "\\iff" => "⟺", + "\\implies" => "⟹", + "\\impliedby" => "⟸", + "\\to" => "→", # Superscripts "\\^0" => "⁰", From c1c626d17ffe55f7537840fbb8da001571d10ea1 Mon Sep 17 00:00:00 2001 From: Carlo Baldassi Date: Mon, 24 Apr 2017 18:40:38 +0200 Subject: [PATCH 0543/1534] A few fixes for the unicode table generation code 1. Due to a typo, the combining characters were not actually fixed (where the fix is to prepend a dotted circle) 2. Only fix combining characters that appear as the first char (e.g. \neqsim is U+02242 + U+00338, we don't want to fix the second one) 3. Characters in category ME (code 8) are also combining. --- doc/src/manual/unicode-input.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/doc/src/manual/unicode-input.md b/doc/src/manual/unicode-input.md index 39cf0d7d75048..69c7d3eb5452c 100644 --- a/doc/src/manual/unicode-input.md +++ b/doc/src/manual/unicode-input.md @@ -41,6 +41,13 @@ function unicode_data() return names end +# Prepend a dotted circle ('◌' i.e. '\u25CC') to combining characters +function fix_combining_chars(char) + cat = Base.UTF8proc.category_code(char) + return string(cat == 6 || cat == 8 ? "◌" : "", char) +end + + function table_entries(completions, unicode_dict) entries = [[ "Code point(s)", "Character(s)", @@ -51,10 +58,10 @@ function table_entries(completions, unicode_dict) for char in chars push!(code_points, "U+$(uppercase(hex(char, 5)))") push!(unicode_names, get(unicode_dict, UInt32(char), "(No Unicode name)")) - push!(characters, Base.UTF8proc.category_code(char) == 6 ? "◌$char" : "$char") + push!(characters, isempty(characters) ? fix_combining_chars(char) : "$char") end push!(entries, [ - join(code_points, " + "), join(chars), + join(code_points, " + "), join(characters), join(inputs, ", "), join(unicode_names, " + ") ]) end From 3c7acc56ca8e3e28de5772a228f6930083bad1e9 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 24 Apr 2017 14:00:03 -0400 Subject: [PATCH 0544/1534] small performance enhancements for isabspath and regexes in general --- base/path.jl | 9 +++++++-- base/pcre.jl | 12 ++++++------ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/base/path.jl b/base/path.jl index 5a1861d64c675..f9b7ab3a233ac 100644 --- a/base/path.jl +++ b/base/path.jl @@ -19,7 +19,6 @@ export if is_unix() const path_separator = "/" const path_separator_re = r"/+" - const path_absolute_re = r"^/" const path_directory_re = r"(?:^|/)\.{0,2}$" const path_dir_splitter = r"^(.*?)(/+)([^/]*)$" const path_ext_splitter = r"^((?:.*/)?(?:\.|[^/\.])[^/]*?)(\.[^/\.]*|)$" @@ -73,6 +72,12 @@ function homedir() end +if is_windows() + isabspath(path::String) = ismatch(path_absolute_re, path) +else + isabspath(path::String) = startswith(path, '/') +end + """ isabspath(path::AbstractString) -> Bool @@ -86,7 +91,7 @@ julia> isabspath("home") false ``` """ -isabspath(path::String) = ismatch(path_absolute_re, path) +isabspath(path::AbstractString) """ isdirpath(path::AbstractString) -> Bool diff --git a/base/pcre.jl b/base/pcre.jl index 36e169e824364..1ce746c96fac5 100644 --- a/base/pcre.jl +++ b/base/pcre.jl @@ -8,20 +8,20 @@ include(string(length(Core.ARGS)>=2?Core.ARGS[2]:"","pcre_h.jl")) # include($BU const PCRE_LIB = "libpcre2-8" -global JIT_STACK = C_NULL -global MATCH_CONTEXT = C_NULL +const JIT_STACK = Ref{Ptr{Void}}(C_NULL) +const MATCH_CONTEXT = Ref{Ptr{Void}}(C_NULL) function __init__() try JIT_STACK_START_SIZE = 32768 JIT_STACK_MAX_SIZE = 1048576 - global JIT_STACK = ccall((:pcre2_jit_stack_create_8, PCRE_LIB), Ptr{Void}, + JIT_STACK[] = ccall((:pcre2_jit_stack_create_8, PCRE_LIB), Ptr{Void}, (Cint, Cint, Ptr{Void}), JIT_STACK_START_SIZE, JIT_STACK_MAX_SIZE, C_NULL) - global MATCH_CONTEXT = ccall((:pcre2_match_context_create_8, PCRE_LIB), + MATCH_CONTEXT[] = ccall((:pcre2_match_context_create_8, PCRE_LIB), Ptr{Void}, (Ptr{Void},), C_NULL) ccall((:pcre2_jit_stack_assign_8, PCRE_LIB), Void, - (Ptr{Void}, Ptr{Void}, Ptr{Void}), MATCH_CONTEXT, C_NULL, JIT_STACK) + (Ptr{Void}, Ptr{Void}, Ptr{Void}), MATCH_CONTEXT[], C_NULL, JIT_STACK[]) catch ex Base.showerror_nostdio(ex, "WARNING: Error during initialization of module PCRE") @@ -129,7 +129,7 @@ end function exec(re,subject,offset,options,match_data) rc = ccall((:pcre2_match_8, PCRE_LIB), Cint, (Ptr{Void}, Ptr{UInt8}, Csize_t, Csize_t, Cuint, Ptr{Void}, Ptr{Void}), - re, subject, sizeof(subject), offset, options, match_data, MATCH_CONTEXT) + re, subject, sizeof(subject), offset, options, match_data, MATCH_CONTEXT[]) # rc == -1 means no match, -2 means partial match. rc < -2 && error("PCRE.exec error: $(err_message(rc))") rc >= 0 From 04e601069392fd5e97d635a8be5209e6a21a1bde Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 24 Apr 2017 15:04:18 -0400 Subject: [PATCH 0545/1534] fix #21510, keyword arg with declared type `ANY` --- src/julia-syntax.scm | 17 ++++++++++++++--- test/keywordargs.jl | 5 +++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 0b099375d97e4..0adfd65f28d5e 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -506,9 +506,20 @@ (not (any (lambda (s) (expr-contains-eq (car s) (caddr k))) keyword-sparams))) - `(call (core typeassert) - ,rval0 - ,(caddr k)) + (let ((T (caddr k))) + `(call (core typeassert) + ,rval0 + ;; work around `ANY` not being a type. if arg type + ;; looks like `ANY`, test whether it is `ANY` at run + ;; time and if so, substitute `Any`. issue #21510 + ,(if (or (eq? T 'ANY) + (and (globalref? T) + (eq? (caddr T) 'ANY))) + `(call (|.| (core Intrinsics) 'select_value) + (call (core ===) ,T (core ANY)) + (core Any) + ,T) + T))) rval0))) ;; if kw[ii] == 'k; k = kw[ii+1]::Type; end `(if (comparison ,elt === (quote ,(decl-var k))) diff --git a/test/keywordargs.jl b/test/keywordargs.jl index 14199e2bc7a66..5a0abed112104 100644 --- a/test/keywordargs.jl +++ b/test/keywordargs.jl @@ -270,3 +270,8 @@ function g21147(f::Tuple{A}, k = 2) where {B,A<:Tuple{B}} end @test g21147(((1,),)) === Int @test g21147(((1,),), 2) === Int + +# issue #21510 +f21510(; a::ANY = 2) = a +@test f21510(a=:b) == :b +@test f21510() == 2 From 502d96f0bd6778fb99d70378987b9def5b729def Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Mon, 24 Apr 2017 13:47:52 -0700 Subject: [PATCH 0546/1534] Misc small tests for Associatives (#21503) --- test/dict.jl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/dict.jl b/test/dict.jl index ebbdab44273b4..1ac24f0bb33b4 100644 --- a/test/dict.jl +++ b/test/dict.jl @@ -394,6 +394,9 @@ let ca = empty!(ca) @test length(ca) == 0 @test length(a) == 2 + + d = Dict('a'=>1, 'b'=>1, 'c'=> 3) + @test a != d end @test length(ObjectIdDict(1=>2, 1.0=>3)) == 2 @@ -706,3 +709,12 @@ end @inferred merge!(-, d1, d2) @test d1 == Dict("A" => 1, "B" => 15, "C" => 28) end + +@testset "misc error/io" begin + d = Dict('a'=>1, 'b'=>1, 'c'=> 3) + @test_throws ErrorException 'a' in d + key_str = sprint(show, keys(d)) + @test 'a' ∈ key_str + @test 'b' ∈ key_str + @test 'c' ∈ key_str +end From 7cd0324e030dba49e90f327b539e03ee93025383 Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Mon, 24 Apr 2017 15:37:38 -0700 Subject: [PATCH 0547/1534] Consistently apply code formatting to paths and file names (#21500) Consistently apply code formatting to paths and file names and correct the Julia/C comparison example's indexing --- doc/src/devdocs/backtraces.md | 6 +- doc/src/devdocs/debuggingtips.md | 2 +- doc/src/devdocs/eval.md | 28 +++--- doc/src/devdocs/functions.md | 6 +- doc/src/devdocs/init.md | 92 ++++++++++---------- doc/src/devdocs/object.md | 10 +-- doc/src/devdocs/offset-arrays.md | 4 +- doc/src/devdocs/stdio.md | 6 +- doc/src/manual/calling-c-and-fortran-code.md | 47 +++++----- doc/src/manual/constructors.md | 4 +- doc/src/manual/conversion-and-promotion.md | 10 +-- doc/src/manual/dates.md | 4 +- doc/src/manual/embedding.md | 14 +-- doc/src/manual/mathematical-operations.md | 2 +- doc/src/manual/metaprogramming.md | 2 +- doc/src/manual/parallel-computing.md | 6 +- doc/src/manual/performance-tips.md | 4 +- doc/src/stdlib/sort.md | 2 +- 18 files changed, 125 insertions(+), 124 deletions(-) diff --git a/doc/src/devdocs/backtraces.md b/doc/src/devdocs/backtraces.md index 5917e26ba7ac5..c053f4cf48c1e 100644 --- a/doc/src/devdocs/backtraces.md +++ b/doc/src/devdocs/backtraces.md @@ -8,7 +8,7 @@ to figure out why your script is running slower than expected. If you've been directed to this page, find the symptom that best matches what you're experiencing and follow the instructions to generate the debugging information requested. Table of symptoms: - * [Segfaults during bootstrap (sysimg.jl)](@ref) + * [Segfaults during bootstrap (`sysimg.jl`)](@ref) * [Segfaults when running a script](@ref) * [Errors during Julia startup](@ref) @@ -32,7 +32,7 @@ Platform Info: LLVM: libLLVM-3.3 ``` -## Segfaults during bootstrap (sysimg.jl) +## Segfaults during bootstrap (`sysimg.jl`) Segfaults toward the end of the `make` process of building Julia are a common symptom of something going wrong while Julia is preparsing the corpus of code in the `base/` folder. Many factors @@ -64,7 +64,7 @@ on Github with a link to the gist. ## Segfaults when running a script -The procedure is very similar to [Segfaults during bootstrap (sysimg.jl)](@ref). Create a debug +The procedure is very similar to [Segfaults during bootstrap (`sysimg.jl`)](@ref). Create a debug build of Julia, and run your script inside of a debugged Julia process: ``` diff --git a/doc/src/devdocs/debuggingtips.md b/doc/src/devdocs/debuggingtips.md index 7fc16b99f2148..fcc7ea99e159b 100644 --- a/doc/src/devdocs/debuggingtips.md +++ b/doc/src/devdocs/debuggingtips.md @@ -26,7 +26,7 @@ Julia's flisp interpreter uses `value_t` objects; these can be displayed with `c ## Useful Julia variables for Inspecting While the addresses of many variables, like singletons, can be be useful to print for many failures, -there are a number of additional variables (see julia.h for a complete list) that are even more +there are a number of additional variables (see `julia.h` for a complete list) that are even more useful. * (when in `jl_apply_generic`) `mfunc` and `jl_uncompress_ast(mfunc->def, mfunc->code)` :: for diff --git a/doc/src/devdocs/eval.md b/doc/src/devdocs/eval.md index 9139a16220329..8413ca31bc7b2 100644 --- a/doc/src/devdocs/eval.md +++ b/doc/src/devdocs/eval.md @@ -25,7 +25,7 @@ The 10,000 foot view of the whole process is as follows: 1. The user starts `julia`. 2. The C function `main()` from `ui/repl.c` gets called. This function processes the command line arguments, filling in the `jl_options` struct and setting the variable `ARGS`. It then initializes - Julia (by calling [`julia_init` in task.c](https://github.com/JuliaLang/julia/blob/master/src/task.c), + Julia (by calling [`julia_init` in `task.c`](https://github.com/JuliaLang/julia/blob/master/src/task.c), which may load a previously compiled [sysimg](@ref dev-sysimg)). Finally, it passes off control to Julia by calling [`Base._start()`](https://github.com/JuliaLang/julia/blob/master/base/client.jl). 3. When `_start()` takes over control, the subsequent sequence of commands depends on the command @@ -45,7 +45,7 @@ The 10,000 foot view of the whole process is as follows: the AST to make it simpler to execute. 10. `jl_toplevel_eval_flex()` then uses some simple heuristics to decide whether to JIT compiler the AST or to interpret it directly. -11. The bulk of the work to interpret code is handled by [`eval` in interpreter.c](https://github.com/JuliaLang/julia/blob/master/src/interpreter.c). +11. The bulk of the work to interpret code is handled by [`eval` in `interpreter.c`](https://github.com/JuliaLang/julia/blob/master/src/interpreter.c). 12. If instead, the code is compiled, the bulk of the work is handled by `codegen.cpp`. Whenever a Julia function is called for the first time with a given set of argument types, [type inference](@ref dev-type-inference) will be run on that function. This information is used by the [codegen](@ref dev-codegen) step to generate @@ -62,12 +62,12 @@ The 10,000 foot view of the whole process is as follows: The Julia parser is a small lisp program written in femtolisp, the source-code for which is distributed inside Julia in [src/flisp](https://github.com/JuliaLang/julia/tree/master/src/flisp). -The interface functions for this are primarily defined in [jlfrontend.scm](https://github.com/JuliaLang/julia/blob/master/src/jlfrontend.scm). -The code in [ast.c](https://github.com/JuliaLang/julia/blob/master/src/ast.c) handles this handoff +The interface functions for this are primarily defined in [`jlfrontend.scm`](https://github.com/JuliaLang/julia/blob/master/src/jlfrontend.scm). +The code in [`ast.c`](https://github.com/JuliaLang/julia/blob/master/src/ast.c) handles this handoff on the Julia side. -The other relevant files at this stage are [julia-parser.scm](https://github.com/JuliaLang/julia/blob/master/src/julia-parser.scm), -which handles tokenizing Julia code and turning it into an AST, and [julia-syntax.scm](https://github.com/JuliaLang/julia/blob/master/src/julia-syntax.scm), +The other relevant files at this stage are [`julia-parser.scm`](https://github.com/JuliaLang/julia/blob/master/src/julia-parser.scm), +which handles tokenizing Julia code and turning it into an AST, and [`julia-syntax.scm`](https://github.com/JuliaLang/julia/blob/master/src/julia-syntax.scm), which handles transforming complex AST representations into simpler, "lowered" AST representations which are more suitable for analysis and execution. @@ -83,7 +83,7 @@ although it can also be invoked directly by a call to [`macroexpand()`](@ref)/`j ## [Type Inference](@id dev-type-inference) -Type inference is implemented in Julia by [typeinf() in inference.jl](https://github.com/JuliaLang/julia/blob/master/base/inference.jl). +Type inference is implemented in Julia by [`typeinf()` in `inference.jl`](https://github.com/JuliaLang/julia/blob/master/base/inference.jl). Type inference is the process of examining a Julia function and determining bounds for the types of each of its variables, as well as bounds on the type of the return value from the function. This enables many future optimizations, such as unboxing of known immutable values, and compile-time @@ -135,7 +135,7 @@ Type inference may also include other steps such as constant propagation and inl Codegen is the process of turning a Julia AST into native machine code. -The JIT environment is initialized by an early call to [`jl_init_codegen` in codegen.cpp](https://github.com/JuliaLang/julia/blob/master/src/codegen.cpp). +The JIT environment is initialized by an early call to [`jl_init_codegen` in `codegen.cpp`](https://github.com/JuliaLang/julia/blob/master/src/codegen.cpp). On demand, a Julia method is converted into a native function by the function `emit_function(jl_method_instance_t*)`. (note, when using the MCJIT (in LLVM v3.4+), each function must be JIT into a new module.) This @@ -143,18 +143,18 @@ function recursively calls `emit_expr()` until the entire function has been emit Much of the remaining bulk of this file is devoted to various manual optimizations of specific code patterns. For example, `emit_known_call()` knows how to inline many of the primitive functions -(defined in [builtins.c](https://github.com/JuliaLang/julia/blob/master/src/builtins.c)) for various +(defined in [`builtins.c`](https://github.com/JuliaLang/julia/blob/master/src/builtins.c)) for various combinations of argument types. Other parts of codegen are handled by various helper files: - * [debuginfo.cpp](https://github.com/JuliaLang/julia/blob/master/src/debuginfo.cpp) + * [`debuginfo.cpp`](https://github.com/JuliaLang/julia/blob/master/src/debuginfo.cpp) Handles backtraces for JIT functions - * [ccall.cpp](https://github.com/JuliaLang/julia/blob/master/src/ccall.cpp) + * [`ccall.cpp`](https://github.com/JuliaLang/julia/blob/master/src/ccall.cpp) Handles the ccall and llvmcall FFI, along with various `abi_*.cpp` files - * [intrinsics.cpp](https://github.com/JuliaLang/julia/blob/master/src/intrinsics.cpp) + * [`intrinsics.cpp`](https://github.com/JuliaLang/julia/blob/master/src/intrinsics.cpp) Handles the emission of various low-level intrinsic functions @@ -168,11 +168,11 @@ Other parts of codegen are handled by various helper files: ## [System Image](@id dev-sysimg) The system image is a precompiled archive of a set of Julia files. The `sys.ji` file distributed -with Julia is one such system image, generated by executing the file [sysimg.jl](https://github.com/JuliaLang/julia/blob/master/base/sysimg.jl), +with Julia is one such system image, generated by executing the file [`sysimg.jl`](https://github.com/JuliaLang/julia/blob/master/base/sysimg.jl), and serializing the resulting environment (including Types, Functions, Modules, and all other defined values) into a file. Therefore, it contains a frozen version of the `Main`, `Core`, and `Base` modules (and whatever else was in the environment at the end of bootstrapping). This serializer/deserializer -is implemented by [`jl_save_system_image`/`jl_restore_system_image` in dump.c](https://github.com/JuliaLang/julia/blob/master/src/dump.c). +is implemented by [`jl_save_system_image`/`jl_restore_system_image` in `dump.c`](https://github.com/JuliaLang/julia/blob/master/src/dump.c). If there is no sysimg file (`jl_options.image_file == NULL`), this also implies that `--build` was given on the command line, so the final result should be a new sysimg file. During Julia initialization, diff --git a/doc/src/devdocs/functions.md b/doc/src/devdocs/functions.md index 5e88f33d0d11b..456f09b218056 100644 --- a/doc/src/devdocs/functions.md +++ b/doc/src/devdocs/functions.md @@ -261,9 +261,9 @@ some number of handlers (currently 25). Presumably no performance-critical funct more than 25 exception handlers. If one ever does, I'm willing to raise the limit to 26. A minor issue occurs during the bootstrap process due to storing all constructors in a single -method table. In the second bootstrap step, where inference.ji is compiled using inference0.ji, -constructors for inference0's types remain in the table, so there are still references to the -old inference module and inference.ji is 2x the size it should be. This was fixed in dump.c by +method table. In the second bootstrap step, where `inference.ji` is compiled using `inference0.ji`, +constructors for `inference0`'s types remain in the table, so there are still references to the +old inference module and `inference.ji` is 2x the size it should be. This was fixed in `dump.c` by filtering definitions from "replaced modules" out of method tables and caches before saving a system image. A "replaced module" is one that satisfies the condition `m != jl_get_global(m->parent, m->name)` -- in other words, some newer module has taken its name and place. diff --git a/doc/src/devdocs/init.md b/doc/src/devdocs/init.md index d1ea013cd6ad5..b67e34661e240 100644 --- a/doc/src/devdocs/init.md +++ b/doc/src/devdocs/init.md @@ -4,22 +4,22 @@ How does the Julia runtime execute `julia -e 'println("Hello World!")'` ? ## main() -Execution starts at [`main()` in ui/repl.c](https://github.com/JuliaLang/julia/blob/master/ui/repl.c). +Execution starts at [`main()` in `ui/repl.c`](https://github.com/JuliaLang/julia/blob/master/ui/repl.c). `main()` calls [`libsupport_init()`](https://github.com/JuliaLang/julia/blob/master/src/support/libsupportinit.c) to set the C library locale and to initialize the "ios" library (see [`ios_init_stdstreams()`](https://github.com/JuliaLang/julia/blob/master/src/support/ios.c) -and [Legacy ios.c library](@ref)). +and [Legacy `ios.c` library](@ref)). Next [`parse_opts()`](https://github.com/JuliaLang/julia/blob/master/ui/repl.c) is called to process command line options. Note that `parse_opts()` only deals with options that affect code generation -or early initialization. Other options are handled later by [`process_options()` in base/client.jl](https://github.com/JuliaLang/julia/blob/master/base/client.jl). +or early initialization. Other options are handled later by [`process_options()` in `base/client.jl`](https://github.com/JuliaLang/julia/blob/master/base/client.jl). `parse_opts()` stores command line options in the [global `jl_options` struct](https://github.com/JuliaLang/julia/blob/master/src/julia.h). ## julia_init() -[`julia_init()` in task.c](https://github.com/JuliaLang/julia/blob/master/src/task.c) is called -by `main()` and calls [`_julia_init()` in init.c](https://github.com/JuliaLang/julia/blob/master/src/init.c). +[`julia_init()` in `task.c`](https://github.com/JuliaLang/julia/blob/master/src/task.c) is called +by `main()` and calls [`_julia_init()` in `init.c`](https://github.com/JuliaLang/julia/blob/master/src/init.c). `_julia_init()` begins by calling `libsupport_init()` again (it does nothing the second time). @@ -36,7 +36,7 @@ and lists for weak refs, preserved values and finalization. a pre-compiled femtolisp image containing the scanner/parser. [`jl_init_types()`](https://github.com/JuliaLang/julia/blob/master/src/jltypes.c) creates `jl_datatype_t` -type description objects for the [built-in types defined in julia.h](https://github.com/JuliaLang/julia/blob/master/src/julia.h). +type description objects for the [built-in types defined in `julia.h`](https://github.com/JuliaLang/julia/blob/master/src/julia.h). e.g. ```c @@ -84,11 +84,11 @@ above is overwritten. [`jl_load("boot.jl", sizeof("boot.jl"))`](https://github.com/JuliaLang/julia/blob/master/src/init.c) calls [`jl_parse_eval_all`](https://github.com/JuliaLang/julia/blob/master/src/ast.c) which repeatedly calls [`jl_toplevel_eval_flex()`](https://github.com/JuliaLang/julia/blob/master/src/toplevel.c) -to execute [boot.jl](https://github.com/JuliaLang/julia/blob/master/base/boot.jl). [`jl_get_builtin_hooks()`](https://github.com/JuliaLang/julia/blob/master/src/init.c) initializes -global C pointers to Julia globals defined in boot.jl. +global C pointers to Julia globals defined in `boot.jl`. [`jl_init_box_caches()`](https://github.com/JuliaLang/julia/blob/master/src/datatype.c) pre-allocates global boxed integer value objects for values up to 1024. This speeds up allocation of boxed ints @@ -124,26 +124,26 @@ each deserialized module to run the `__init__()` function. Finally [`sigint_handler()`](https://github.com/JuliaLang/julia/blob/master/src/signals-unix.c) is hooked up to `SIGINT` and calls `jl_throw(jl_interrupt_exception)`. -`_julia_init()` then returns [back to `main()` in julia/ui/repl.c](https://github.com/JuliaLang/julia/blob/master/ui/repl.c) +`_julia_init()` then returns [back to `main()` in `ui/repl.c`](https://github.com/JuliaLang/julia/blob/master/ui/repl.c) and `main()` calls `true_main(argc, (char**)argv)`. !!! sidebar "sysimg" If there is a sysimg file, it contains a pre-cooked image of the `Core` and `Main` modules (and - whatever else is created by boot.jl). See [Building the Julia system image](@ref). + whatever else is created by `boot.jl`). See [Building the Julia system image](@ref). [`jl_restore_system_image()`](https://github.com/JuliaLang/julia/blob/master/src/dump.c) deserializes the saved sysimg into the current Julia runtime environment and initialization continues after `jl_init_box_caches()` below... - Note: [`jl_restore_system_image()` (and dump.c in general)](https://github.com/JuliaLang/julia/blob/master/src/dump.c) - uses the [Legacy ios.c library](@ref). + Note: [`jl_restore_system_image()` (and `dump.c` in general)](https://github.com/JuliaLang/julia/blob/master/src/dump.c) + uses the [Legacy `ios.c` library](@ref). ## true_main() [`true_main()`](https://github.com/JuliaLang/julia/blob/master/ui/repl.c) loads the contents of `argv[]` into [`Base.ARGS`](@ref). -If a .jl "program" file was supplied on the command line, then [`exec_program()`](https://github.com/JuliaLang/julia/blob/master/ui/repl.c) +If a `.jl` "program" file was supplied on the command line, then [`exec_program()`](https://github.com/JuliaLang/julia/blob/master/ui/repl.c) calls [`jl_load(program,len)`](https://github.com/JuliaLang/julia/blob/master/src/toplevel.c) which calls [`jl_parse_eval_all`](https://github.com/JuliaLang/julia/blob/master/src/ast.c) which repeatedly calls [`jl_toplevel_eval_flex()`](https://github.com/JuliaLang/julia/blob/master/src/toplevel.c) @@ -169,7 +169,7 @@ where `ex` is the parsed expression `println("Hello World!")`. [`jl_toplevel_eval_in()`](https://github.com/JuliaLang/julia/blob/master/src/builtins.c) calls [`jl_toplevel_eval_flex()`](https://github.com/JuliaLang/julia/blob/master/src/toplevel.c) which -calls [`eval()` in interpreter.c](https://github.com/JuliaLang/julia/blob/master/src/interpreter.c). +calls [`eval()` in `interpreter.c`](https://github.com/JuliaLang/julia/blob/master/src/interpreter.c). The stack dump below shows how the interpreter works its way through various methods of [`Base.println()`](@ref) and [`Base.print()`](@ref) before arriving at [`write(s::IO, a::Array{T}) where T`](https://github.com/JuliaLang/julia/blob/master/base/stream.jl) @@ -182,38 +182,38 @@ to write "Hello World!" to `JL_STDOUT`. See [Libuv wrappers for stdio](@ref).: Hello World! ``` -| Stack frame | Source code | Notes | -|:------------------------------ |:------------- |:---------------------------------------------------- | -| `jl_uv_write()` | jl_uv.c | called though [`ccall`](@ref) | -| `julia_write_282942` | stream.jl | function `write!(s::IO, a::Array{T}) where T` | -| `julia_print_284639` | ascii.jl | `print(io::IO, s::String) = (write(io, s); nothing)` | -| `jlcall_print_284639` |   |   | -| `jl_apply()` | julia.h |   | -| `jl_trampoline()` | builtins.c |   | -| `jl_apply()` | julia.h |   | -| `jl_apply_generic()` | gf.c | `Base.print(Base.TTY, String)` | -| `jl_apply()` | julia.h |   | -| `jl_trampoline()` | builtins.c |   | -| `jl_apply()` | julia.h |   | -| `jl_apply_generic()` | gf.c | `Base.print(Base.TTY, String, Char, Char...)` | -| `jl_apply()` | julia.h |   | -| `jl_f_apply()` | builtins.c |   | -| `jl_apply()` | julia.h |   | -| `jl_trampoline()` | builtins.c |   | -| `jl_apply()` | julia.h |   | -| `jl_apply_generic()` | gf.c | `Base.println(Base.TTY, String, String...)` | -| `jl_apply()` | julia.h |   | -| `jl_trampoline()` | builtins.c |   | -| `jl_apply()` | julia.h |   | -| `jl_apply_generic()` | gf.c | `Base.println(String,)` | -| `jl_apply()` | julia.h |   | -| `do_call()` | interpreter.c |   | -| `eval()` | interpreter.c |   | -| `jl_interpret_toplevel_expr()` | interpreter.c |   | -| `jl_toplevel_eval_flex()` | toplevel.c |   | -| `jl_toplevel_eval()` | toplevel.c |   | -| `jl_toplevel_eval_in()` | builtins.c |   | -| `jl_f_top_eval()` | builtins.c |   | +| Stack frame | Source code | Notes | +|:------------------------------ |:--------------- |:---------------------------------------------------- | +| `jl_uv_write()` | `jl_uv.c` | called though [`ccall`](@ref) | +| `julia_write_282942` | `stream.jl` | function `write!(s::IO, a::Array{T}) where T` | +| `julia_print_284639` | `ascii.jl` | `print(io::IO, s::String) = (write(io, s); nothing)` | +| `jlcall_print_284639` |   |   | +| `jl_apply()` | `julia.h` |   | +| `jl_trampoline()` | `builtins.c` |   | +| `jl_apply()` | `julia.h` |   | +| `jl_apply_generic()` | `gf.c` | `Base.print(Base.TTY, String)` | +| `jl_apply()` | `julia.h` |   | +| `jl_trampoline()` | `builtins.c` |   | +| `jl_apply()` | `julia.h` |   | +| `jl_apply_generic()` | `gf.c` | `Base.print(Base.TTY, String, Char, Char...)` | +| `jl_apply()` | `julia.h` |   | +| `jl_f_apply()` | `builtins.c` |   | +| `jl_apply()` | `julia.h` |   | +| `jl_trampoline()` | `builtins.c` |   | +| `jl_apply()` | `julia.h` |   | +| `jl_apply_generic()` | `gf.c` | `Base.println(Base.TTY, String, String...)` | +| `jl_apply()` | `julia.h` |   | +| `jl_trampoline()` | `builtins.c` |   | +| `jl_apply()` | `julia.h` |   | +| `jl_apply_generic()` | `gf.c` | `Base.println(String,)` | +| `jl_apply()` | `julia.h` |   | +| `do_call()` | `interpreter.c` |   | +| `eval()` | `interpreter.c` |   | +| `jl_interpret_toplevel_expr()` | `interpreter.c` |   | +| `jl_toplevel_eval_flex()` | `toplevel.c` |   | +| `jl_toplevel_eval()` | `toplevel.c` |   | +| `jl_toplevel_eval_in()` | `builtins.c` |   | +| `jl_f_top_eval()` | `builtins.c` |   | Since our example has just one function call, which has done its job of printing "Hello World!", the stack now rapidly unwinds back to `main()`. diff --git a/doc/src/devdocs/object.md b/doc/src/devdocs/object.md index da0f3e3cfcad3..bfb096fbf980c 100644 --- a/doc/src/devdocs/object.md +++ b/doc/src/devdocs/object.md @@ -85,14 +85,14 @@ void jl_gc_wb(jl_value_t *parent, jl_value_t *ptr); However, the [Embedding Julia](@ref) section of the manual is also required reading at this point, for covering other details of boxing and unboxing various types, and understanding the gc interactions. -Mirror structs for some of the built-in types are [defined in julia.h](https://github.com/JuliaLang/julia/blob/master/src/julia.h). -The corresponding global `jl_datatype_t` objects are created by [`jl_init_types` in jltypes.c](https://github.com/JuliaLang/julia/blob/master/src/jltypes.c). +Mirror structs for some of the built-in types are [defined in `julia.h`](https://github.com/JuliaLang/julia/blob/master/src/julia.h). +The corresponding global `jl_datatype_t` objects are created by [`jl_init_types` in `jltypes.c`](https://github.com/JuliaLang/julia/blob/master/src/jltypes.c). ## Garbage collector mark bits The garbage collector uses several bits from the metadata portion of the `jl_typetag_t` to track each object in the system. Further details about this algorithm can be found in the comments of -the [garbage collector implementation in gc.c](https://github.com/JuliaLang/julia/blob/master/src/gc.c). +the [garbage collector implementation in `gc.c`](https://github.com/JuliaLang/julia/blob/master/src/gc.c). ## Object allocation @@ -120,7 +120,7 @@ jl_uniontype_t *jl_new_uniontype(jl_tuple_t *types); ``` While these are the most commonly used options, there are more low-level constructors too, which -you can find declared in [julia.h](https://github.com/JuliaLang/julia/blob/master/src/julia.h). +you can find declared in [`julia.h`](https://github.com/JuliaLang/julia/blob/master/src/julia.h). These are used in `jl_init_types()` to create the initial types needed to bootstrap the creation of the Julia system image. @@ -173,7 +173,7 @@ jl_array_t *jl_alloc_vec_any(size_t n); Note that many of these have alternative allocation functions for various special-purposes. The list here reflects the more common usages, but a more complete list can be found by reading the -[julia.h header file](https://github.com/JuliaLang/julia/blob/master/src/julia.h). +[`julia.h` header file](https://github.com/JuliaLang/julia/blob/master/src/julia.h). Internal to Julia, storage is typically allocated by `newstruct()` (or `newobj()` for the special types): diff --git a/doc/src/devdocs/offset-arrays.md b/doc/src/devdocs/offset-arrays.md index 805c2fe40fa88..443473d16a61d 100644 --- a/doc/src/devdocs/offset-arrays.md +++ b/doc/src/devdocs/offset-arrays.md @@ -169,8 +169,8 @@ is (perhaps counterintuitively) an advantage: `ModuleA.ZeroRange` indicates that create a `ModuleA.ZeroArray`, whereas `ModuleB.ZeroRange` indicates a `ModuleB.ZeroArray` type. This design allows peaceful coexistence among many different custom array types. -Note that the Julia package `CustomUnitRanges.jl` can sometimes be used to avoid the need to write -your own `ZeroRange` type. +Note that the Julia package [CustomUnitRanges.jl](https://github.com/JuliaArrays/CustomUnitRanges.jl) +can sometimes be used to avoid the need to write your own `ZeroRange` type. ### Specializing `indices` diff --git a/doc/src/devdocs/stdio.md b/doc/src/devdocs/stdio.md index 636c1d06847ef..9f36f37bf1fad 100644 --- a/doc/src/devdocs/stdio.md +++ b/doc/src/devdocs/stdio.md @@ -74,18 +74,18 @@ In `jl_uv.c` the `jl_uv_puts()` function checks its `uv_stream_t* stream` argume This allows for uniform use of `jl_printf()` throughout the runtime regardless of whether or not any particular piece of code is reachable before initialization is complete. -## Legacy ios.c library +## Legacy `ios.c` library The `src/support/ios.c` library is inherited from [femtolisp](https://github.com/JeffBezanson/femtolisp). It provides cross-platform buffered file IO and in-memory temporary buffers. -ios.c is still used by: +`ios.c` is still used by: * `src/flisp/*.c` * `src/dump.c` – for serialization file IO and for memory buffers. * `base/iostream.jl` – for file IO (see `base/fs.jl` for libuv equivalent). -Use of ios.c in these modules is mostly self-contained and separated from the libuv I/O system. +Use of `ios.c` in these modules is mostly self-contained and separated from the libuv I/O system. However, there is [one place](https://github.com/JuliaLang/julia/blob/master/src/flisp/print.c#L654) where femtolisp calls through to `jl_printf()` with a legacy `ios_t` stream. diff --git a/doc/src/manual/calling-c-and-fortran-code.md b/doc/src/manual/calling-c-and-fortran-code.md index 8c9c83c74f562..b5cfa8e76fd6b 100644 --- a/doc/src/manual/calling-c-and-fortran-code.md +++ b/doc/src/manual/calling-c-and-fortran-code.md @@ -95,7 +95,7 @@ uses in Julia functions that set up arguments and then check for errors in whate C or Fortran function indicates them, propagating to the Julia caller as exceptions. This is especially important since C and Fortran APIs are notoriously inconsistent about how they indicate error conditions. For example, the `getenv` C library function is wrapped in the following Julia function, -which is a simplified version of the actual definition from [env.jl](https://github.com/JuliaLang/julia/blob/master/base/env.jl): +which is a simplified version of the actual definition from [`env.jl`](https://github.com/JuliaLang/julia/blob/master/base/env.jl): ```julia function getenv(var::AbstractString) @@ -149,7 +149,7 @@ throw a conversion error. It is possible to pass Julia functions to native C functions that accept function pointer arguments. For example, to match C prototypes of the form: -``` +```c typedef returntype (*functiontype)(argumenttype,...) ``` @@ -162,7 +162,7 @@ Julia library function. Arguments to [`cfunction()`](@ref) are as follows: A classic example is the standard C library `qsort` function, declared as: -``` +```c void qsort(void *base, size_t nmemb, size_t size, int(*compare)(const void *a, const void *b)); ``` @@ -176,7 +176,7 @@ calling `qsort` and passing arguments, we need to write a comparison function th arbitrary type T: ```jldoctest mycompare -julia> function mycompare{T}(a::T, b::T) +julia> function mycompare(a::T, b::T) where T return convert(Cint, a < b ? -1 : a > b ? +1 : 0)::Cint end mycompare (generic function with 1 method) @@ -409,7 +409,7 @@ checks and is only meant to improve readability of the call. C functions that take an argument of the type `char**` can be called by using a `Ptr{Ptr{UInt8}}` type within Julia. For example, C functions of the form: - ``` + ```c int main(int argc, char **argv); ``` @@ -451,17 +451,17 @@ struct B { b_a_2 = B.A[2]; in Julia: -type B +struct B A::NTuple{3, CInt} end -b_a_2 = B.A[2] +b_a_2 = B.A[3] # note the difference in indexing (1-based in Julia, 0-based in C) ``` Arrays of unknown size (C99-compliant variable length structs specified by `[]` or `[0]`) are not directly supported. Often the best way to deal with these is to deal with the byte offsets directly. -For example, if a c-library declared a proper string type and returned a pointer to it: +For example, if a C library declared a proper string type and returned a pointer to it: -``` +```c struct String { int strlen; char data[]; @@ -470,7 +470,7 @@ struct String { In Julia, we can access the parts independently to make a copy of that string: -``` +```julia str = from_c::Ptr{Void} len = unsafe_load(Ptr{Cint}(str)) unsafe_string(str + Core.sizeof(Cint), len) @@ -489,9 +489,9 @@ However, while the type layout must be known statically to compute the `ccall` A the static parameters of the function are considered to be part of this static environment. The static parameters of the function may be used as type parameters in the `ccall` signature, as long as they don't affect the layout of the type. -For example, `f{T}(x::T) = ccall(:valid, Ptr{T}, (Ptr{T},), x)` +For example, `f(x::T) where {T} = ccall(:valid, Ptr{T}, (Ptr{T},), x)` is valid, since `Ptr` is always a word-size primitive type. -But, `g{T}(x::T) = ccall(:notvalid, T, (T,), x)` +But, `g(x::T) where {T} = ccall(:notvalid, T, (T,), x)` is not valid, since the type layout of `T` is not known statically. ### SIMD Values @@ -508,7 +508,7 @@ Julia type is a homogeneous tuple of `VecElement` that naturally maps to the SIM For instance, consider this C routine that uses AVX intrinsics: -``` +```c #include __m256 dist( __m256 a, __m256 b ) { @@ -677,14 +677,14 @@ arguments, as noted above). The following example computes a dot product using a ```julia function compute_dot(DX::Vector{Float64}, DY::Vector{Float64}) - assert(length(DX) == length(DY)) - n = length(DX) - incx = incy = 1 - product = ccall((:ddot_, "libLAPACK"), - Float64, - (Ptr{Int32}, Ptr{Float64}, Ptr{Int32}, Ptr{Float64}, Ptr{Int32}), - &n, DX, &incx, DY, &incy) - return product + @assert length(DX) == length(DY) + n = length(DX) + incx = incy = 1 + product = ccall((:ddot_, "libLAPACK"), + Float64, + (Ptr{Int32}, Ptr{Float64}, Ptr{Int32}, Ptr{Float64}, Ptr{Int32}), + &n, DX, &incx, DY, &incy) + return product end ``` @@ -702,7 +702,7 @@ converted to type `T`. Here is a simple example of a C wrapper that returns a `Ptr` type: ```julia -type gsl_permutation +mutable struct gsl_permutation end # The corresponding C signature is @@ -977,4 +977,5 @@ For more details on how to pass callbacks to C libraries, see this [blog post](h ## C++ -For direct C++ interfacing, see the [Cxx](https://github.com/Keno/Cxx.jl) package. For tools to create C++ bindings, see the [CxxWrap](https://github.com/JuliaInterop/CxxWrap.jl) package. +For direct C++ interfacing, see the [Cxx](https://github.com/Keno/Cxx.jl) package. For tools to create C++ +bindings, see the [CxxWrap](https://github.com/JuliaInterop/CxxWrap.jl) package. diff --git a/doc/src/manual/constructors.md b/doc/src/manual/constructors.md index e0f0c430cdc7c..dcf9fe4b68719 100644 --- a/doc/src/manual/constructors.md +++ b/doc/src/manual/constructors.md @@ -407,7 +407,7 @@ defining sophisticated behavior is typically quite simple. ## Case Study: Rational Perhaps the best way to tie all these pieces together is to present a real world example of a -parametric composite type and its constructor methods. To that end, here is the (slightly modified) beginning of [rational.jl](https://github.com/JuliaLang/julia/blob/master/base/rational.jl), +parametric composite type and its constructor methods. To that end, here is the (slightly modified) beginning of [`rational.jl`](https://github.com/JuliaLang/julia/blob/master/base/rational.jl), which implements Julia's [Rational Numbers](@ref): ```jldoctest rational @@ -502,7 +502,7 @@ false Thus, although the [`//`](@ref) operator usually returns an instance of `OurRational`, if either of its arguments are complex integers, it will return an instance of `Complex{OurRational}` instead. -The interested reader should consider perusing the rest of [rational.jl](https://github.com/JuliaLang/julia/blob/master/base/rational.jl): +The interested reader should consider perusing the rest of [`rational.jl`](https://github.com/JuliaLang/julia/blob/master/base/rational.jl): it is short, self-contained, and implements an entire basic Julia type. ## [Constructors and Conversion](@id constructors-and-conversion) diff --git a/doc/src/manual/conversion-and-promotion.md b/doc/src/manual/conversion-and-promotion.md index 663a8e7388dd8..12166fb148c61 100644 --- a/doc/src/manual/conversion-and-promotion.md +++ b/doc/src/manual/conversion-and-promotion.md @@ -143,7 +143,7 @@ ERROR: InexactError() ### [Case Study: Rational Conversions](@id man-rational-conversion) -To continue our case study of Julia's `Rational` type, here are the conversions declared in [rational.jl](https://github.com/JuliaLang/julia/blob/master/base/rational.jl), +To continue our case study of Julia's `Rational` type, here are the conversions declared in [`rational.jl`](https://github.com/JuliaLang/julia/blob/master/base/rational.jl), right after the declaration of the type and its constructors: ```julia @@ -231,7 +231,7 @@ promoted to the appropriate kind of complex value. That is really all there is to using promotions. The rest is just a matter of clever application, the most typical "clever" application being the definition of catch-all methods for numeric operations like the arithmetic operators `+`, `-`, `*` and `/`. Here are some of the catch-all method definitions -given in [promotion.jl](https://github.com/JuliaLang/julia/blob/master/base/promotion.jl): +given in [`promotion.jl`](https://github.com/JuliaLang/julia/blob/master/base/promotion.jl): ```julia +(x::Number, y::Number) = +(promote(x,y)...) @@ -245,11 +245,11 @@ multiplying and dividing pairs of numeric values, promote the values to a common try again. That's all there is to it: nowhere else does one ever need to worry about promotion to a common numeric type for arithmetic operations -- it just happens automatically. There are definitions of catch-all promotion methods for a number of other arithmetic and mathematical functions -in [promotion.jl](https://github.com/JuliaLang/julia/blob/master/base/promotion.jl), but beyond +in [`promotion.jl`](https://github.com/JuliaLang/julia/blob/master/base/promotion.jl), but beyond that, there are hardly any calls to `promote` required in the Julia standard library. The most common usages of `promote` occur in outer constructors methods, provided for convenience, to allow constructor calls with mixed types to delegate to an inner type with fields promoted to an appropriate -common type. For example, recall that [rational.jl](https://github.com/JuliaLang/julia/blob/master/base/rational.jl) +common type. For example, recall that [`rational.jl`](https://github.com/JuliaLang/julia/blob/master/base/rational.jl) provides the following outer constructor method: ```julia @@ -309,7 +309,7 @@ Int64 Internally, `promote_type` is used inside of `promote` to determine what type argument values should be converted to for promotion. It can, however, be useful in its own right. The curious -reader can read the code in [promotion.jl](https://github.com/JuliaLang/julia/blob/master/base/promotion.jl), +reader can read the code in [`promotion.jl`](https://github.com/JuliaLang/julia/blob/master/base/promotion.jl), which defines the complete promotion mechanism in about 35 lines. ### Case Study: Rational Promotions diff --git a/doc/src/manual/dates.md b/doc/src/manual/dates.md index ce0fbea3f7f3f..56bf2bcdeb731 100644 --- a/doc/src/manual/dates.md +++ b/doc/src/manual/dates.md @@ -124,7 +124,7 @@ julia> for i = 1:10^5 end ``` -A full suite of parsing and formatting tests and examples is available in [tests/dates/io.jl](https://github.com/JuliaLang/julia/blob/master/test/dates/io.jl). +A full suite of parsing and formatting tests and examples is available in [`tests/dates/io.jl`](https://github.com/JuliaLang/julia/blob/master/test/dates/io.jl). ## Durations/Comparisons @@ -503,7 +503,7 @@ julia> filter(dr) do x 2014-11-11 ``` -Additional examples and tests are available in [test/dates/adjusters.jl](https://github.com/JuliaLang/julia/blob/master/test/dates/adjusters.jl). +Additional examples and tests are available in [`test/dates/adjusters.jl`](https://github.com/JuliaLang/julia/blob/master/test/dates/adjusters.jl). ## Period Types diff --git a/doc/src/manual/embedding.md b/doc/src/manual/embedding.md index 64aeee8442202..77a132c5b3d20 100644 --- a/doc/src/manual/embedding.md +++ b/doc/src/manual/embedding.md @@ -75,7 +75,7 @@ example program calls this before returning from `main`. ### Using julia-config to automatically determine build parameters -The script *julia-config.jl* was created to aid in determining what build parameters are required +The script `julia-config.jl` was created to aid in determining what build parameters are required by a program that uses embedded Julia. This script uses the build parameters and system configuration of the particular Julia distribution it is invoked by to export the necessary compiler flags for an embedding program to interact with that distribution. This script is located in the Julia @@ -97,8 +97,8 @@ int main(int argc, char *argv[]) #### On the command line -A simple use of this script is from the command line. Assuming that *julia-config.jl* is located -in */usr/local/julia/share/julia*, it can be invoked on the command line directly and takes any +A simple use of this script is from the command line. Assuming that `julia-config.jl` is located +in `/usr/local/julia/share/julia`, it can be invoked on the command line directly and takes any combination of 3 flags: ``` @@ -106,7 +106,7 @@ combination of 3 flags: Usage: julia-config [--cflags|--ldflags|--ldlibs] ``` -If the above example source is saved in the file *embed_example.c*, then the following command +If the above example source is saved in the file `embed_example.c`, then the following command will compile it into a running program on Linux and Windows (MSYS2 environment), or if on OS/X, then substitute `clang` for `gcc`.: @@ -118,8 +118,8 @@ then substitute `clang` for `gcc`.: But in general, embedding projects will be more complicated than the above, and so the following allows general makefile support as well – assuming GNU make because of the use of the **shell** -macro expansions. Additionally, though many times *julia-config.jl* may be found in the directory -*/usr/local*, this is not necessarily the case, but Julia can be used to locate *julia-config.jl* +macro expansions. Additionally, though many times `julia-config.jl` may be found in the directory +`/usr/local`, this is not necessarily the case, but Julia can be used to locate `julia-config.jl` too, and the makefile can be used to take advantage of that. The above example is extended to use a Makefile: @@ -133,7 +133,7 @@ LDLIBS += $(shell $(JL_SHARE)/julia-config.jl --ldlibs) all: embed_example ``` -Now the build command is simply **make**. +Now the build command is simply `make`. ## Converting Types diff --git a/doc/src/manual/mathematical-operations.md b/doc/src/manual/mathematical-operations.md index fe6ea8f769da6..150acc2c0322d 100644 --- a/doc/src/manual/mathematical-operations.md +++ b/doc/src/manual/mathematical-operations.md @@ -360,7 +360,7 @@ Julia applies the following order of operations, from highest precedence to lowe | Assignments | `= += -= *= /= //= \= ^= ÷= %= \|= &= ⊻= <<= >>= >>>=` | For a complete list of *every* Julia operator's precedence, see the top of this file: -[julia/src/julia-parser.scm](https://github.com/JuliaLang/julia/blob/master/src/julia-parser.scm) +[`src/julia-parser.scm`](https://github.com/JuliaLang/julia/blob/master/src/julia-parser.scm) You can also find the numerical precedence for any given operator via the built-in function `Base.operator_precedence`, where higher numbers take precedence: diff --git a/doc/src/manual/metaprogramming.md b/doc/src/manual/metaprogramming.md index f3820d04ba602..6e937ba18b8c2 100644 --- a/doc/src/manual/metaprogramming.md +++ b/doc/src/manual/metaprogramming.md @@ -609,7 +609,7 @@ Expr So now instead of getting a plain string in `msg_body`, the macro is receiving a full expression that will need to be evaluated in order to display as expected. This can be spliced directly into -the returned expression as an argument to the [`string()`](@ref) call; see [error.jl](https://github.com/JuliaLang/julia/blob/master/base/error.jl) +the returned expression as an argument to the [`string()`](@ref) call; see [`error.jl`](https://github.com/JuliaLang/julia/blob/master/base/error.jl) for the complete implementation. The `@assert` macro makes great use of splicing into quoted expressions to simplify the manipulation diff --git a/doc/src/manual/parallel-computing.md b/doc/src/manual/parallel-computing.md index d3d84f6a652dd..35a509e98d6c8 100644 --- a/doc/src/manual/parallel-computing.md +++ b/doc/src/manual/parallel-computing.md @@ -131,7 +131,7 @@ ERROR: RemoteException(2, CapturedException(UndefVarError(Symbol("#rand2")) Process 1 knew about the function `rand2`, but process 2 did not. Most commonly you'll be loading code from files or packages, and you have a considerable amount -of flexibility in controlling which processes load code. Consider a file, `"DummyModule.jl"`, +of flexibility in controlling which processes load code. Consider a file, `DummyModule.jl`, containing the following code: ```julia @@ -814,8 +814,8 @@ Once finalized, a reference becomes invalid and cannot be used in any further ca ## [Shared Arrays](@id man-shared-arrays) Shared Arrays use system shared memory to map the same array across many processes. While there -are some similarities to a [DArray](https://github.com/JuliaParallel/DistributedArrays.jl), the -behavior of a [`SharedArray`](@ref) is quite different. In a [DArray](https://github.com/JuliaParallel/DistributedArrays.jl), +are some similarities to a [`DArray`](https://github.com/JuliaParallel/DistributedArrays.jl), the +behavior of a [`SharedArray`](@ref) is quite different. In a [`DArray`](https://github.com/JuliaParallel/DistributedArrays.jl), each process has local access to just a chunk of the data, and no two processes share the same chunk; in contrast, in a [`SharedArray`](@ref) each "participating" process has access to the entire array. A [`SharedArray`](@ref) is a good choice when you want to have a large amount of diff --git a/doc/src/manual/performance-tips.md b/doc/src/manual/performance-tips.md index 00f2a313ea640..b4a542c433be3 100644 --- a/doc/src/manual/performance-tips.md +++ b/doc/src/manual/performance-tips.md @@ -81,7 +81,7 @@ problem with type-stability. Consequently, in addition to the allocation itself, that the code generated for your function is far from optimal. Take such indications seriously and follow the advice below. -For more serious benchmarking, consider the [`BenchmarkTools.jl`](https://github.com/JuliaCI/BenchmarkTools.jl) +For more serious benchmarking, consider the [BenchmarkTools.jl](https://github.com/JuliaCI/BenchmarkTools.jl) package which evaluates the function multiple times in order to reduce noise. As a teaser, an improved version of this function allocates no memory @@ -629,7 +629,7 @@ of `fill_twos!` for different types of `a`. The second form is also often better style and can lead to more code reuse. This pattern is used in several places in the standard library. For example, see `hvcat_fill` -in [abstractarray.jl](https://github.com/JuliaLang/julia/blob/master/base/abstractarray.jl), or +in [`abstractarray.jl`](https://github.com/JuliaLang/julia/blob/master/base/abstractarray.jl), or the [`fill!`](@ref) function, which we could have used instead of writing our own `fill_twos!`. Functions like `strange_twos` occur when dealing with data of uncertain type, for example data diff --git a/doc/src/stdlib/sort.md b/doc/src/stdlib/sort.md index 83ef65eef01ca..acd98784759bd 100644 --- a/doc/src/stdlib/sort.md +++ b/doc/src/stdlib/sort.md @@ -174,7 +174,7 @@ your preferred algorithm, e.g. `sort!(v, alg=QuickSort)`. The mechanism by which Julia picks default sorting algorithms is implemented via the `Base.Sort.defalg` function. It allows a particular algorithm to be registered as the default in all sorting functions -for specific arrays. For example, here are the two default methods from [sort.jl](https://github.com/JuliaLang/julia/blob/master/base/sort.jl): +for specific arrays. For example, here are the two default methods from [`sort.jl`](https://github.com/JuliaLang/julia/blob/master/base/sort.jl): ```julia defalg(v::AbstractArray) = MergeSort From 6c92f26c95886c844e81f39b86daee5844850ae1 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Tue, 25 Apr 2017 08:57:46 +0900 Subject: [PATCH 0548/1534] don't use isdefined in stale_cachefile `isdefined` will immediatly resolve the binding. Since we are only trying to skip the path lookup the weaker version `isbindingresolved` is enough. `isbindingresolved` is also used for this purpose in `read_verify_mod_list` in `src/dump.c`. --- base/loading.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/loading.jl b/base/loading.jl index b85828e37a8b3..8d0c3b87f2f8a 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -750,7 +750,7 @@ function stale_cachefile(modpath::String, cachefile::String) if mod == :Main || mod == :Core || mod == :Base continue # Module is already loaded - elseif isdefined(Main, mod) + elseif isbindingresolved(Main, mod) continue end name = string(mod) From 5cdff93ebafdb87d6f7a447e4ad22d5d0fa75667 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Tue, 25 Apr 2017 05:33:02 +0200 Subject: [PATCH 0549/1534] =?UTF-8?q?Fix=20typo:=20promt=20=E2=86=92=20pro?= =?UTF-8?q?mpt=20(#21538)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- base/REPL.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/base/REPL.jl b/base/REPL.jl index 90f97799a8408..dda4a65ac0dad 100644 --- a/base/REPL.jl +++ b/base/REPL.jl @@ -685,8 +685,8 @@ end repl_filename(repl, hp::REPLHistoryProvider) = "REPL[$(length(hp.history)-hp.start_idx)]" repl_filename(repl, hp) = "REPL" -const JL_PROMT_PASTE = Ref(true) -enable_promtpaste(v::Bool) = JL_PROMT_PASTE[] = v +const JL_PROMPT_PASTE = Ref(true) +enable_promptpaste(v::Bool) = JL_PROMPT_PASTE[] = v function setup_interface(repl::LineEditREPL; hascolor = repl.hascolor, extra_repl_keymap = Dict{Any,Any}[]) ### @@ -836,7 +836,7 @@ function setup_interface(repl::LineEditREPL; hascolor = repl.hascolor, extra_rep firstline = true isprompt_paste = false while !done(input, oldpos) # loop until all lines have been executed - if JL_PROMT_PASTE[] + if JL_PROMPT_PASTE[] # Check if the next statement starts with "julia> ", in that case # skip it. But first skip whitespace while input[oldpos] in ('\n', ' ', '\t') From cd227e9cec0d65b0c07089cbe5b3a9ef05220c05 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Tue, 25 Apr 2017 15:05:05 +0900 Subject: [PATCH 0550/1534] add test for module name conflict --- test/compile.jl | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/test/compile.jl b/test/compile.jl index 0e7274eb9e108..3814cc8e5c678 100644 --- a/test/compile.jl +++ b/test/compile.jl @@ -411,6 +411,39 @@ let dir = mktempdir(), end end +# test loading a package with conflicting namespace +let dir = mktempdir() + Test_module = :Test6c92f26 + try + write(joinpath(dir, "Iterators.jl"), + """ + module Iterators + __precompile__(true) + end + """) + + write(joinpath(dir, "$Test_module.jl"), + """ + module $Test_module + __precompile__(true) + using Iterators + end + """) + + testcode = """ + insert!(LOAD_PATH, 1, $(repr(dir))) + insert!(Base.LOAD_CACHE_PATH, 1, $(repr(dir))) + using $Test_module + """ + + exename = `$(Base.julia_cmd()) --startup-file=no` + @test readchomp(`$exename -E $(testcode)`) == "nothing" + @test readchomp(`$exename -E $(testcode)`) == "nothing" + finally + rm(dir, recursive=true) + end +end + let module_name = string("a",randstring()) insert!(LOAD_PATH, 1, pwd()) file_name = string(module_name, ".jl") From 6e0a2f8c94f050faa4a4997757037a4f9754866d Mon Sep 17 00:00:00 2001 From: Mus M Date: Tue, 25 Apr 2017 10:57:26 -0400 Subject: [PATCH 0551/1534] Update misc methods to where syntax (#21501) * Update misc methods to where syntax * More funcs to new where syntax * More syntax to where * More * M * More * Address review * Update syntax and use Vector in linalg --- base/atomics.jl | 4 +- base/complex.jl | 4 +- base/datafmt.jl | 4 +- base/dates/io.jl | 12 ++-- base/dates/parse.jl | 22 +++--- base/dates/periods.jl | 38 +++++------ base/dates/ranges.jl | 6 +- base/dates/types.jl | 6 +- base/dft.jl | 2 +- base/dsp.jl | 24 ++++--- base/fastmath.jl | 78 ++++++++++----------- base/fft/FFTW.jl | 133 ++++++++++++++++++------------------ base/fft/dct.jl | 12 ++-- base/int.jl | 4 +- base/io.jl | 18 ++--- base/iobuffer.jl | 4 +- base/linalg/cholesky.jl | 8 +-- base/linalg/linalg.jl | 4 +- base/linalg/lq.jl | 10 +-- base/linalg/rowvector.jl | 16 ++--- base/linalg/schur.jl | 18 ++--- base/linalg/triangular.jl | 120 ++++++++++++++++---------------- base/mmap.jl | 40 +++++------ base/multidimensional.jl | 54 +++++++-------- base/multimedia.jl | 10 +-- base/nullable.jl | 28 ++++---- base/operators.jl | 8 +-- base/parse.jl | 16 ++--- base/permuteddimsarray.jl | 10 +-- base/pkg/query.jl | 4 +- base/pointer.jl | 12 ++-- base/range.jl | 6 +- base/serialize.jl | 12 ++-- base/shell.jl | 13 ++-- base/sparse/linalg.jl | 76 ++++++++++----------- base/sparse/sparsematrix.jl | 2 +- base/sparse/sparsevector.jl | 2 +- base/subarray.jl | 16 ++--- base/twiceprecision.jl | 30 ++++---- 39 files changed, 438 insertions(+), 448 deletions(-) diff --git a/base/atomics.jl b/base/atomics.jl index 18790d6f6e477..7374bad3f4f2e 100644 --- a/base/atomics.jl +++ b/base/atomics.jl @@ -63,8 +63,8 @@ Atomic operations use an `atomic_` prefix, such as `atomic_add!`, """ mutable struct Atomic{T<:AtomicTypes} value::T - Atomic{T}() where T<:AtomicTypes = new(zero(T)) - Atomic{T}(value) where T<:AtomicTypes = new(value) + Atomic{T}() where {T<:AtomicTypes} = new(zero(T)) + Atomic{T}(value) where {T<:AtomicTypes} = new(value) end Atomic() = Atomic{Int}() diff --git a/base/complex.jl b/base/complex.jl index 65dd79f9cf155..71b8e8c001d1b 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -158,7 +158,7 @@ end show(io::IO, z::Complex{Bool}) = print(io, z == im ? "im" : "Complex($(z.re),$(z.im))") -function read{T<:Real}(s::IO, ::Type{Complex{T}}) +function read(s::IO, ::Type{Complex{T}}) where T<:Real r = read(s,T) i = read(s,T) Complex{T}(r,i) @@ -440,7 +440,7 @@ Compute the phase angle in radians of a complex number `z`. """ angle(z::Complex) = atan2(imag(z), real(z)) -function log{T<:AbstractFloat}(z::Complex{T}) +function log(z::Complex{T}) where T<:AbstractFloat const T1::T = 1.25 const T2::T = 3 const ln2::T = log(convert(T,2)) #0.6931471805599453 diff --git a/base/datafmt.jl b/base/datafmt.jl index eaad3f8368415..9253c4bf236d4 100644 --- a/base/datafmt.jl +++ b/base/datafmt.jl @@ -457,8 +457,8 @@ end colval(sbuff::String, startpos::Int, endpos::Int, cells::Array, row::Int, col::Int) = true function dlm_parse(dbuff::String, eol::D, dlm::D, qchar::D, cchar::D, - ign_adj_dlm::Bool, allow_quote::Bool, allow_comments::Bool, - skipstart::Int, skipblanks::Bool, dh::DLMHandler) where D + ign_adj_dlm::Bool, allow_quote::Bool, allow_comments::Bool, + skipstart::Int, skipblanks::Bool, dh::DLMHandler) where D ncols = nrows = col = 0 is_default_dlm = (dlm == invalid_dlm(D)) error_str = "" diff --git a/base/dates/io.jl b/base/dates/io.jl index 0a6292bc5058d..7274425c1444d 100644 --- a/base/dates/io.jl +++ b/base/dates/io.jl @@ -74,13 +74,13 @@ end @inline min_width(d::DatePart) = d.fixed ? d.width : 1 @inline max_width(d::DatePart) = d.fixed ? d.width : 0 -function _show_content{c}(io::IO, d::DatePart{c}) +function _show_content(io::IO, d::DatePart{c}) where c for i = 1:d.width write(io, c) end end -function Base.show{c}(io::IO, d::DatePart{c}) +function Base.show(io::IO, d::DatePart{c}) where c write(io, "DatePart(") _show_content(io, d) write(io, ")") @@ -174,7 +174,7 @@ end Delim(d::Char) = Delim{Char, 1}(d) Delim(d::String) = Delim{String, length(d)}(d) -@inline function tryparsenext{N}(d::Delim{Char, N}, str, i::Int, len) +@inline function tryparsenext(d::Delim{Char, N}, str, i::Int, len) where N R = Nullable{Bool} for j=1:N i > len && return (R(), i) @@ -184,7 +184,7 @@ Delim(d::String) = Delim{String, length(d)}(d) return R(true), i end -@inline function tryparsenext{N}(d::Delim{String, N}, str, i::Int, len) +@inline function tryparsenext(d::Delim{String, N}, str, i::Int, len) where N R = Nullable{Bool} i1 = i i2 = start(d.d) @@ -205,7 +205,7 @@ end write(io, d.d) end -function _show_content{N}(io::IO, d::Delim{Char, N}) +function _show_content(io::IO, d::Delim{Char, N}) where N if d.d in keys(CONVERSION_SPECIFIERS) for i = 1:N write(io, '\\', d.d) @@ -534,6 +534,6 @@ end function format(Y::AbstractArray{<:TimeType}, f::AbstractString; locale::Locale=ENGLISH) format(Y, DateFormat(f, locale)) end -function format{T<:TimeType}(Y::AbstractArray{T}, df::DateFormat=default_format(T)) +function format(Y::AbstractArray{T}, df::DateFormat=default_format(T)) where T<:TimeType return reshape([format(y, df) for y in Y], size(Y)) end diff --git a/base/dates/parse.jl b/base/dates/parse.jl index 1dc76323521e8..1d036a5a92ab9 100644 --- a/base/dates/parse.jl +++ b/base/dates/parse.jl @@ -2,9 +2,9 @@ ### Parsing utilities -_directives{S,T}(::Type{DateFormat{S,T}}) = T.parameters +_directives(::Type{DateFormat{S,T}}) where {S,T} = T.parameters -character_codes{S,T}(df::Type{DateFormat{S,T}}) = character_codes(_directives(df)) +character_codes(df::Type{DateFormat{S,T}}) where {S,T} = character_codes(_directives(df)) function character_codes(directives::SimpleVector) letters = sizehint!(Char[], length(directives)) for (i, directive) in enumerate(directives) @@ -34,9 +34,8 @@ Returns a 3-element tuple `(values, pos, num_parsed)`: * `num_parsed::Int`: The number of values which were parsed and stored within `values`. Useful for distinguishing parsed values from default values. """ -@generated function tryparsenext_core( - str::AbstractString, pos::Int, len::Int, df::DateFormat, raise::Bool=false, -) +@generated function tryparsenext_core(str::AbstractString, pos::Int, len::Int, + df::DateFormat, raise::Bool=false) directives = _directives(df) letters = character_codes(directives) @@ -125,9 +124,8 @@ Returns a 2-element tuple `(values, pos)`: the passed in type. * `pos::Int`: The character index at which parsing stopped. """ -@generated function tryparsenext_internal{T<:TimeType}( - ::Type{T}, str::AbstractString, pos::Int, len::Int, df::DateFormat, raise::Bool=false, -) +@generated function tryparsenext_internal(::Type{T}, str::AbstractString, pos::Int, len::Int, + df::DateFormat, raise::Bool=false) where T<:TimeType letters = character_codes(df) tokens = Type[CONVERSION_SPECIFIERS[letter] for letter in letters] @@ -267,17 +265,13 @@ function Base.parse(::Type{DateTime}, s::AbstractString, df::typeof(ISODateTimeF throw(ArgumentError("Invalid DateTime string")) end -function Base.parse{T<:TimeType}( - ::Type{T}, str::AbstractString, df::DateFormat=default_format(T), -) +function Base.parse(::Type{T}, str::AbstractString, df::DateFormat=default_format(T)) where T<:TimeType pos, len = start(str), endof(str) values, pos = tryparsenext_internal(T, str, pos, len, df, true) T(unsafe_get(values)...) end -function Base.tryparse{T<:TimeType}( - ::Type{T}, str::AbstractString, df::DateFormat=default_format(T), -) +function Base.tryparse(::Type{T}, str::AbstractString, df::DateFormat=default_format(T)) where T<:TimeType pos, len = start(str), endof(str) values, pos = tryparsenext_internal(T, str, pos, len, df, false) if isnull(values) diff --git a/base/dates/periods.jl b/base/dates/periods.jl index 51baecb51717b..6dcfab7ff96c2 100644 --- a/base/dates/periods.jl +++ b/base/dates/periods.jl @@ -41,10 +41,10 @@ end #Print/show/traits Base.string(x::Period) = string(value(x), _units(x)) Base.show(io::IO,x::Period) = print(io, string(x)) -Base.zero{P<:Period}(::Union{Type{P},P}) = P(0) -Base.one{P<:Period}(::Union{Type{P},P}) = 1 # see #16116 -Base.typemin{P<:Period}(::Type{P}) = P(typemin(Int64)) -Base.typemax{P<:Period}(::Type{P}) = P(typemax(Int64)) +Base.zero(::Union{Type{P},P}) where {P<:Period} = P(0) +Base.one(::Union{Type{P},P}) where {P<:Period} = 1 # see #16116 +Base.typemin(::Type{P}) where {P<:Period} = P(typemin(Int64)) +Base.typemax(::Type{P}) where {P<:Period} = P(typemax(Int64)) # Default values (as used by TimeTypes) """ @@ -55,35 +55,35 @@ Month, and Day, and `T(0)` for Hour, Minute, Second, and Millisecond. """ function default end -default{T<:DatePeriod}(p::Union{T,Type{T}}) = T(1) -default{T<:TimePeriod}(p::Union{T,Type{T}}) = T(0) +default(p::Union{T,Type{T}}) where {T<:DatePeriod} = T(1) +default(p::Union{T,Type{T}}) where {T<:TimePeriod} = T(0) (-)(x::P) where {P<:Period} = P(-value(x)) -Base.isless{P<:Period}(x::P, y::P) = isless(value(x), value(y)) -==(x::P, y::P) where {P<:Period} = value(x) == value(y) +Base.isless(x::P, y::P) where {P<:Period} = isless(value(x), value(y)) +(==)(x::P, y::P) where {P<:Period} = value(x) == value(y) # Period Arithmetic, grouped by dimensionality: import Base: div, fld, mod, rem, gcd, lcm, +, -, *, /, % for op in (:+, :-, :lcm, :gcd) - @eval ($op){P<:Period}(x::P, y::P) = P(($op)(value(x), value(y))) + @eval ($op)(x::P, y::P) where {P<:Period} = P(($op)(value(x), value(y))) end for op in (:/, :div, :fld) @eval begin - ($op){P<:Period}(x::P, y::P) = ($op)(value(x), value(y)) - ($op){P<:Period}(x::P, y::Real) = P(($op)(value(x), Int64(y))) + ($op)(x::P, y::P) where {P<:Period} = ($op)(value(x), value(y)) + ($op)(x::P, y::Real) where {P<:Period} = P(($op)(value(x), Int64(y))) end end for op in (:rem, :mod) @eval begin - ($op){P<:Period}(x::P, y::P) = P(($op)(value(x), value(y))) - ($op){P<:Period}(x::P, y::Real) = P(($op)(value(x), Int64(y))) + ($op)(x::P, y::P) where {P<:Period} = P(($op)(value(x), value(y))) + ($op)(x::P, y::Real) where {P<:Period} = P(($op)(value(x), Int64(y))) end end -*(x::P, y::Real) where {P<:Period} = P(value(x) * Int64(y)) -*(y::Real, x::Period) = x * y +(*)(x::P, y::Real) where {P<:Period} = P(value(x) * Int64(y)) +(*)(y::Real, x::Period) = x * y for (op, Ty, Tz) in ((:*, Real, :P), (:/, :P, Float64), (:/, Real, :P)) @eval begin @@ -426,8 +426,8 @@ for i = 1:length(fixedperiod_conversions) end end # have to declare thusly so that diagonal dispatch above takes precedence: -(==){T<:FixedPeriod, S<:FixedPeriod}(x::T, y::S) = (==)(promote(x, y)...) -Base.isless{T<:FixedPeriod, S<:FixedPeriod}(x::T, y::S) = isless(promote(x, y)...) +(==)(x::T, y::S) where {T<:FixedPeriod,S<:FixedPeriod} = (==)(promote(x, y)...) +Base.isless(x::T, y::S) where {T<:FixedPeriod,S<:FixedPeriod} = isless(promote(x, y)...) # other periods with fixed conversions but which aren't fixed time periods const OtherPeriod = Union{Month, Year} @@ -439,8 +439,8 @@ let vmax = typemax(Int64) ÷ 12, vmin = typemin(Int64) ÷ 12 end Base.convert(::Type{Year}, x::Month) = Year(divexact(value(x), 12)) Base.promote_rule(::Type{Year}, ::Type{Month}) = Month -(==){T<:OtherPeriod, S<:OtherPeriod}(x::T, y::S) = (==)(promote(x, y)...) -Base.isless{T<:OtherPeriod, S<:OtherPeriod}(x::T, y::S) = isless(promote(x, y)...) +(==)(x::T, y::S) where {T<:OtherPeriod,S<:OtherPeriod} = (==)(promote(x, y)...) +Base.isless(x::T, y::S) where {T<:OtherPeriod,S<:OtherPeriod} = isless(promote(x, y)...) # truncating conversions to milliseconds and days: toms(c::Nanosecond) = div(value(c), 1000000) diff --git a/base/dates/ranges.jl b/base/dates/ranges.jl index e58d3e7a0f841..0004d84d85bec 100644 --- a/base/dates/ranges.jl +++ b/base/dates/ranges.jl @@ -3,9 +3,9 @@ # Date/DateTime Ranges # Override default step; otherwise it would be Millisecond(1) -Base.colon{T<:DateTime}(start::T, stop::T) = StepRange(start, Day(1), stop) -Base.colon{T<:Date}(start::T, stop::T) = StepRange(start, Day(1), stop) -Base.colon{T<:Time}(start::T, stop::T) = StepRange(start, Second(1), stop) +Base.colon(start::T, stop::T) where {T<:DateTime} = StepRange(start, Day(1), stop) +Base.colon(start::T, stop::T) where {T<:Date} = StepRange(start, Day(1), stop) +Base.colon(start::T, stop::T) where {T<:Time} = StepRange(start, Second(1), stop) Base.range(start::DateTime, len::Integer) = range(start, Day(1), len) Base.range(start::Date, len::Integer) = range(start, Day(1), len) diff --git a/base/dates/types.jl b/base/dates/types.jl index 431ceee32bf14..587e7b1be6042 100644 --- a/base/dates/types.jl +++ b/base/dates/types.jl @@ -270,7 +270,7 @@ Date(y, m=1, d=1) = Date(Int64(y), Int64(m), Int64(d)) Time(h, mi=0, s=0, ms=0, us=0, ns=0) = Time(Int64(h), Int64(mi), Int64(s), Int64(ms), Int64(us), Int64(ns)) # Traits, Equality -Base.isfinite{T<:TimeType}(::Union{Type{T}, T}) = true +Base.isfinite(::Union{Type{T}, T}) where {T<:TimeType} = true calendar(dt::DateTime) = ISOCalendar calendar(dt::Date) = ISOCalendar @@ -298,13 +298,13 @@ Base.eltype(::Type{T}) where {T<:Period} = T Base.promote_rule(::Type{Date}, x::Type{DateTime}) = DateTime Base.isless(x::T, y::T) where {T<:TimeType} = isless(value(x), value(y)) Base.isless(x::TimeType, y::TimeType) = isless(Base.promote_noncircular(x, y)...) -==(x::T, y::T) where {T<:TimeType} = ==(value(x), value(y)) +(==)(x::T, y::T) where {T<:TimeType} = (==)(value(x), value(y)) function ==(a::Time, b::Time) return hour(a) == hour(b) && minute(a) == minute(b) && second(a) == second(b) && millisecond(a) == millisecond(b) && microsecond(a) == microsecond(b) && nanosecond(a) == nanosecond(b) end -==(x::TimeType, y::TimeType) = ===(promote(x, y)...) +(==)(x::TimeType, y::TimeType) = (===)(promote(x, y)...) import Base: sleep, Timer, timedwait sleep(time::Period) = sleep(toms(time) / 1000) diff --git a/base/dft.jl b/base/dft.jl index d2e467e5acdd6..d332501719b5c 100644 --- a/base/dft.jl +++ b/base/dft.jl @@ -337,7 +337,7 @@ function brfft_output_size(x::AbstractArray, d::Integer, region) return osize end -plan_irfft{T}(x::AbstractArray{Complex{T}}, d::Integer, region; kws...) = +plan_irfft(x::AbstractArray{Complex{T}}, d::Integer, region; kws...) where {T} = ScaledPlan(plan_brfft(x, d, region; kws...), normalization(T, brfft_output_size(x, d, region), region)) diff --git a/base/dsp.jl b/base/dsp.jl index c4cf7fceb8514..470852e84b561 100644 --- a/base/dsp.jl +++ b/base/dsp.jl @@ -14,8 +14,8 @@ _zerosi(b,a,T) = zeros(promote_type(eltype(b), eltype(a), T), max(length(a), len Apply filter described by vectors `a` and `b` to vector `x`, with an optional initial filter state vector `si` (defaults to zeros). """ -function filt{T,S}(b::Union{AbstractVector, Number}, a::Union{AbstractVector, Number}, - x::AbstractArray{T}, si::AbstractArray{S}=_zerosi(b,a,T)) +function filt(b::Union{AbstractVector, Number}, a::Union{AbstractVector, Number}, + x::AbstractArray{T}, si::AbstractArray{S} = _zerosi(b,a,T)) where {T,S} filt!(Array{promote_type(eltype(b), eltype(a), T, S)}(size(x)), b, a, x, si) end @@ -28,8 +28,8 @@ end Same as [`filt`](@ref) but writes the result into the `out` argument, which may alias the input `x` to modify it in-place. """ -function filt!{T,S,N}(out::AbstractArray, b::Union{AbstractVector, Number}, a::Union{AbstractVector, Number}, - x::AbstractArray{T}, si::AbstractArray{S,N}=_zerosi(b,a,T)) +function filt!(out::AbstractArray, b::Union{AbstractVector, Number}, a::Union{AbstractVector, Number}, + x::AbstractArray{T}, si::AbstractArray{S,N} = _zerosi(b,a,T)) where {T,S,N} isempty(b) && throw(ArgumentError("filter vector b must be non-empty")) isempty(a) && throw(ArgumentError("filter vector a must be non-empty")) a[1] == 0 && throw(ArgumentError("filter vector a[1] must be nonzero")) @@ -108,7 +108,7 @@ end Construct vector `c` such that `b = conv(a,c) + r`. Equivalent to polynomial division. """ -function deconv{T}(b::StridedVector{T}, a::StridedVector{T}) +function deconv(b::StridedVector{T}, a::StridedVector{T}) where T lb = size(b,1) la = size(a,1) if lb < la @@ -125,7 +125,7 @@ end Convolution of two vectors. Uses FFT algorithm. """ -function conv{T<:Base.LinAlg.BlasFloat}(u::StridedVector{T}, v::StridedVector{T}) +function conv(u::StridedVector{T}, v::StridedVector{T}) where T<:Base.LinAlg.BlasFloat nu = length(u) nv = length(v) n = nu + nv - 1 @@ -141,7 +141,7 @@ function conv{T<:Base.LinAlg.BlasFloat}(u::StridedVector{T}, v::StridedVector{T} end return y[1:n] end -conv{T<:Integer}(u::StridedVector{T}, v::StridedVector{T}) = round.(Int,conv(float(u), float(v))) +conv(u::StridedVector{T}, v::StridedVector{T}) where {T<:Integer} = round.(Int, conv(float(u), float(v))) conv(u::StridedVector{<:Integer}, v::StridedVector{<:Base.LinAlg.BlasFloat}) = conv(float(u), v) conv(u::StridedVector{<:Base.LinAlg.BlasFloat}, v::StridedVector{<:Integer}) = conv(u, float(v)) @@ -152,7 +152,7 @@ conv(u::StridedVector{<:Base.LinAlg.BlasFloat}, v::StridedVector{<:Integer}) = c the vectors `u` and `v`. Uses 2-D FFT algorithm. """ -function conv2{T}(u::StridedVector{T}, v::StridedVector{T}, A::StridedMatrix{T}) +function conv2(u::StridedVector{T}, v::StridedVector{T}, A::StridedMatrix{T}) where T m = length(u)+size(A,1)-1 n = length(v)+size(A,2)-1 B = zeros(T, m, n) @@ -171,7 +171,7 @@ end 2-D convolution of the matrix `B` with the matrix `A`. Uses 2-D FFT algorithm. """ -function conv2{T}(A::StridedMatrix{T}, B::StridedMatrix{T}) +function conv2(A::StridedMatrix{T}, B::StridedMatrix{T}) where T sa, sb = size(A), size(B) At = zeros(T, sa[1]+sb[1]-1, sa[2]+sb[2]-1) Bt = zeros(T, sa[1]+sb[1]-1, sa[2]+sb[2]-1) @@ -184,8 +184,10 @@ function conv2{T}(A::StridedMatrix{T}, B::StridedMatrix{T}) end return C end -conv2{T<:Integer}(A::StridedMatrix{T}, B::StridedMatrix{T}) = round.(Int,conv2(float(A), float(B))) -conv2{T<:Integer}(u::StridedVector{T}, v::StridedVector{T}, A::StridedMatrix{T}) = round.(Int,conv2(float(u), float(v), float(A))) +conv2(A::StridedMatrix{T}, B::StridedMatrix{T}) where {T<:Integer} = + round.(Int, conv2(float(A), float(B))) +conv2(u::StridedVector{T}, v::StridedVector{T}, A::StridedMatrix{T}) where {T<:Integer} = + round.(Int, conv2(float(u), float(v), float(A))) """ xcorr(u,v) diff --git a/base/fastmath.jl b/base/fastmath.jl index 13e0677eb9046..fbef3beb0f836 100644 --- a/base/fastmath.jl +++ b/base/fastmath.jl @@ -134,11 +134,11 @@ FloatTypes = Union{Float32, Float64} sub_fast(x::FloatTypes) = neg_float_fast(x) -add_fast{T<:FloatTypes}(x::T, y::T) = add_float_fast(x, y) -sub_fast{T<:FloatTypes}(x::T, y::T) = sub_float_fast(x, y) -mul_fast{T<:FloatTypes}(x::T, y::T) = mul_float_fast(x, y) -div_fast{T<:FloatTypes}(x::T, y::T) = div_float_fast(x, y) -rem_fast{T<:FloatTypes}(x::T, y::T) = rem_float_fast(x, y) +add_fast(x::T, y::T) where {T<:FloatTypes} = add_float_fast(x, y) +sub_fast(x::T, y::T) where {T<:FloatTypes} = sub_float_fast(x, y) +mul_fast(x::T, y::T) where {T<:FloatTypes} = mul_float_fast(x, y) +div_fast(x::T, y::T) where {T<:FloatTypes} = div_float_fast(x, y) +rem_fast(x::T, y::T) where {T<:FloatTypes} = rem_float_fast(x, y) add_fast{T<:FloatTypes}(x::T, y::T, zs::T...) = add_fast(add_fast(x, y), zs...) @@ -146,13 +146,13 @@ mul_fast{T<:FloatTypes}(x::T, y::T, zs::T...) = mul_fast(mul_fast(x, y), zs...) @fastmath begin - cmp_fast{T<:FloatTypes}(x::T, y::T) = ifelse(x==y, 0, ifelse(x x, y, x) - min_fast{T<:FloatTypes}(x::T, y::T) = ifelse(y > x, x, y) - minmax_fast{T<:FloatTypes}(x::T, y::T) = ifelse(y > x, (x,y), (y,x)) + max_fast(x::T, y::T) where {T<:FloatTypes} = ifelse(y > x, y, x) + min_fast(x::T, y::T) where {T<:FloatTypes} = ifelse(y > x, x, y) + minmax_fast(x::T, y::T) where {T<:FloatTypes} = ifelse(y > x, (x,y), (y,x)) # complex numbers - cis_fast{T<:FloatTypes}(x::T) = Complex{T}(cos(x), sin(x)) + cis_fast(x::T) where {T<:FloatTypes} = Complex{T}(cos(x), sin(x)) # See - pow_fast{T<:ComplexTypes}(x::T, y::T) = exp(y*log(x)) - pow_fast{T<:FloatTypes}(x::T, y::Complex{T}) = exp(y*log(x)) - pow_fast{T<:FloatTypes}(x::Complex{T}, y::T) = exp(y*log(x)) + pow_fast(x::T, y::T) where {T<:ComplexTypes} = exp(y*log(x)) + pow_fast(x::T, y::Complex{T}) where {T<:FloatTypes} = exp(y*log(x)) + pow_fast(x::Complex{T}, y::T) where {T<:FloatTypes} = exp(y*log(x)) acos_fast(x::T) where {T<:ComplexTypes} = convert(T,π)/2 + im*log(im*x + sqrt(1-x*x)) acosh_fast(x::ComplexTypes) = log(x + sqrt(x+1) * sqrt(x-1)) @@ -310,10 +310,10 @@ atan2_fast(x::Float64, y::Float64) = exp2(real(x)) * cis(imag(x)*log(convert(T,2))) exp_fast(x::ComplexTypes) = exp(real(x)) * cis(imag(x)) expm1_fast(x::ComplexTypes) = exp(x)-1 - log10_fast{T<:ComplexTypes}(x::T) = log(x) / log(convert(T,10)) + log10_fast(x::T) where {T<:ComplexTypes} = log(x) / log(convert(T,10)) log1p_fast(x::ComplexTypes) = log(1+x) - log2_fast{T<:ComplexTypes}(x::T) = log(x) / log(convert(T,2)) - log_fast{T<:ComplexTypes}(x::T) = T(log(abs2(x))/2, angle(x)) + log2_fast(x::T) where {T<:ComplexTypes} = log(x) / log(convert(T,2)) + log_fast(x::T) where {T<:ComplexTypes} = T(log(abs2(x))/2, angle(x)) sin_fast(x::ComplexTypes) = -im*sinh(im*x) sinh_fast(x::T) where {T<:ComplexTypes} = convert(T,1)/2*(exp(x) - exp(-x)) sqrt_fast(x::ComplexTypes) = sqrt(abs(x)) * cis(angle(x)/2) @@ -341,7 +341,7 @@ for f in (:^, :atan2, :hypot, :max, :min, :minmax) # type promotion $f_fast(x::Number, y::Number) = $f_fast(promote(x, y)...) # fall-back implementation that applies after promotion - $f_fast{T<:Number}(x::T, y::T) = $f(x, y) + $f_fast(x::T, y::T) where {T<:Number} = $f(x, y) end end diff --git a/base/fft/FFTW.jl b/base/fft/FFTW.jl index a34d60aadd8bf..4ef2f701e0c78 100644 --- a/base/fft/FFTW.jl +++ b/base/fft/FFTW.jl @@ -68,16 +68,15 @@ const fftwTypeSingle = Union{Type{Float32},Type{Complex64}} # since it is not written to. Hence, it is convenient to create an # array-like type that carries a size and a stride like a "real" array # but which is converted to C_NULL as a pointer. -struct FakeArray{T, N} <: DenseArray{T, N} - sz::NTuple{N, Int} - st::NTuple{N, Int} +struct FakeArray{T,N} <: DenseArray{T,N} + sz::NTuple{N,Int} + st::NTuple{N,Int} end size(a::FakeArray) = a.sz strides(a::FakeArray) = a.st unsafe_convert(::Type{Ptr{T}}, a::FakeArray{T}) where {T} = convert(Ptr{T}, C_NULL) -pointer{T}(a::FakeArray{T}) = convert(Ptr{T}, C_NULL) -FakeArray{T, N}(::Type{T}, sz::NTuple{N, Int}) = - FakeArray{T, N}(sz, colmajorstrides(sz)) +pointer(a::FakeArray{T}) where {T} = convert(Ptr{T}, C_NULL) +FakeArray{T,N}(::Type{T}, sz::NTuple{N,Int}) = FakeArray{T,N}(sz, colmajorstrides(sz)) FakeArray{T}(::Type{T}, sz::Int...) = FakeArray(T, sz) fakesimilar(flags, X, T) = flags & ESTIMATE != 0 ? FakeArray(T, size(X)) : Array{T}(size(X)) alignment_of(A::FakeArray) = Int32(0) @@ -213,17 +212,17 @@ for P in (:cFFTWPlan, :rFFTWPlan, :r2rFFTWPlan) # complex, r2c/c2r, and r2r @eval begin mutable struct $P{T<:fftwNumber,K,inplace,N} <: FFTWPlan{T,K,inplace} plan::PlanPtr - sz::NTuple{N, Int} # size of array on which plan operates (Int tuple) - osz::NTuple{N, Int} # size of output array (Int tuple) - istride::NTuple{N, Int} # strides of input - ostride::NTuple{N, Int} # strides of output + sz::NTuple{N,Int} # size of array on which plan operates (Int tuple) + osz::NTuple{N,Int} # size of output array (Int tuple) + istride::NTuple{N,Int} # strides of input + ostride::NTuple{N,Int} # strides of output ialign::Int32 # alignment mod 16 of input oalign::Int32 # alignment mod 16 of input flags::UInt32 # planner flags region::Any # region (iterable) of dims that are transormed pinv::ScaledPlan function $P{T,K,inplace,N}(plan::PlanPtr, flags::Integer, R::Any, - X::StridedArray{T, N}, Y::StridedArray) where {T<:fftwNumber,K,inplace,N} + X::StridedArray{T,N}, Y::StridedArray) where {T<:fftwNumber,K,inplace,N} p = new(plan, size(X), size(Y), strides(X), strides(Y), alignment_of(X), alignment_of(Y), flags, R) finalizer(p, destroy_plan) @@ -250,8 +249,8 @@ cost(plan::FFTWPlan{<:fftwSingle}) = function arithmetic_ops(plan::FFTWPlan{<:fftwDouble}) # Change to individual Ref after we can allocate them on stack - ref = Ref{NTuple{3, Float64}}() - ptr = Ptr{Float64}(Base.unsafe_convert(Ptr{NTuple{3, Float64}}, ref)) + ref = Ref{NTuple{3,Float64}}() + ptr = Ptr{Float64}(Base.unsafe_convert(Ptr{NTuple{3,Float64}}, ref)) ccall((:fftw_flops,libfftw), Void, (PlanPtr,Ptr{Float64},Ptr{Float64},Ptr{Float64}), plan, ptr, ptr + 8, ptr + 16) @@ -259,8 +258,8 @@ function arithmetic_ops(plan::FFTWPlan{<:fftwDouble}) end function arithmetic_ops(plan::FFTWPlan{<:fftwSingle}) # Change to individual Ref after we can allocate them on stack - ref = Ref{NTuple{3, Float64}}() - ptr = Ptr{Float64}(Base.unsafe_convert(Ptr{NTuple{3, Float64}}, ref)) + ref = Ref{NTuple{3,Float64}}() + ptr = Ptr{Float64}(Base.unsafe_convert(Ptr{NTuple{3,Float64}}, ref)) ccall((:fftwf_flops,libfftwf), Void, (PlanPtr,Ptr{Float64},Ptr{Float64},Ptr{Float64}), plan, ptr, ptr + 8, ptr + 16) @@ -333,7 +332,7 @@ end # Check whether a FFTWPlan is applicable to a given input array, and # throw an informative error if not: -function assert_applicable{T}(p::FFTWPlan{T}, X::StridedArray{T}) +function assert_applicable(p::FFTWPlan{T}, X::StridedArray{T}) where T if size(X) != p.sz throw(ArgumentError("FFTW plan applied to wrong-size array")) elseif strides(X) != p.istride @@ -343,7 +342,7 @@ function assert_applicable{T}(p::FFTWPlan{T}, X::StridedArray{T}) end end -function assert_applicable{T,K,inplace}(p::FFTWPlan{T,K,inplace}, X::StridedArray{T}, Y::StridedArray) +function assert_applicable(p::FFTWPlan{T,K,inplace}, X::StridedArray{T}, Y::StridedArray) where {T,K,inplace} assert_applicable(p, X) if size(Y) != p.osz throw(ArgumentError("FFTW plan applied to wrong-size output")) @@ -371,13 +370,13 @@ unsafe_execute!(plan::FFTWPlan{<:fftwDouble}) = unsafe_execute!(plan::FFTWPlan{<:fftwSingle}) = ccall((:fftwf_execute,libfftwf), Void, (PlanPtr,), plan) -unsafe_execute!{T<:fftwDouble}(plan::cFFTWPlan{T}, - X::StridedArray{T}, Y::StridedArray{T}) = +unsafe_execute!(plan::cFFTWPlan{T}, + X::StridedArray{T}, Y::StridedArray{T}) where {T<:fftwDouble} = ccall((:fftw_execute_dft,libfftw), Void, (PlanPtr,Ptr{T},Ptr{T}), plan, X, Y) -unsafe_execute!{T<:fftwSingle}(plan::cFFTWPlan{T}, - X::StridedArray{T}, Y::StridedArray{T}) = +unsafe_execute!(plan::cFFTWPlan{T}, + X::StridedArray{T}, Y::StridedArray{T}) where {T<:fftwSingle} = ccall((:fftwf_execute_dft,libfftwf), Void, (PlanPtr,Ptr{T},Ptr{T}), plan, X, Y) @@ -401,13 +400,13 @@ unsafe_execute!(plan::rFFTWPlan{Complex64,BACKWARD}, ccall((:fftwf_execute_dft_c2r,libfftwf), Void, (PlanPtr,Ptr{Complex64},Ptr{Float32}), plan, X, Y) -unsafe_execute!{T<:fftwDouble}(plan::r2rFFTWPlan{T}, - X::StridedArray{T}, Y::StridedArray{T}) = +unsafe_execute!(plan::r2rFFTWPlan{T}, + X::StridedArray{T}, Y::StridedArray{T}) where {T<:fftwDouble} = ccall((:fftw_execute_r2r,libfftw), Void, (PlanPtr,Ptr{T},Ptr{T}), plan, X, Y) -unsafe_execute!{T<:fftwSingle}(plan::r2rFFTWPlan{T}, - X::StridedArray{T}, Y::StridedArray{T}) = +unsafe_execute!(plan::r2rFFTWPlan{T}, + X::StridedArray{T}, Y::StridedArray{T}) where {T<:fftwSingle} = ccall((:fftwf_execute_r2r,libfftwf), Void, (PlanPtr,Ptr{T},Ptr{T}), plan, X, Y) @@ -447,7 +446,7 @@ function fix_kinds(region, kinds) if isempty(kinds) throw(ArgumentError("must supply a transform kind")) end - k = Array{Int32}(length(region)) + k = Vector{Int32}(length(region)) k[1:length(kinds)] = [kinds...] k[length(kinds)+1:end] = kinds[end] kinds = k @@ -467,9 +466,9 @@ end for (Tr,Tc,fftw,lib) in ((:Float64,:Complex128,"fftw",libfftw), (:Float32,:Complex64,"fftwf",libfftwf)) - @eval function (::Type{cFFTWPlan{$Tc,K,inplace,N}}){K,inplace,N}(X::StridedArray{$Tc,N}, - Y::StridedArray{$Tc,N}, - region, flags::Integer, timelimit::Real) + @eval function (::Type{cFFTWPlan{$Tc,K,inplace,N}})(X::StridedArray{$Tc,N}, + Y::StridedArray{$Tc,N}, + region, flags::Integer, timelimit::Real) where {K,inplace,N} direction = K set_timelimit($Tr, timelimit) R = isa(region, Tuple) ? region : copy(region) @@ -487,9 +486,9 @@ for (Tr,Tc,fftw,lib) in ((:Float64,:Complex128,"fftw",libfftw), return cFFTWPlan{$Tc,K,inplace,N}(plan, flags, R, X, Y) end - @eval function (::Type{rFFTWPlan{$Tr,$FORWARD,inplace,N}}){inplace,N}(X::StridedArray{$Tr,N}, - Y::StridedArray{$Tc,N}, - region, flags::Integer, timelimit::Real) + @eval function (::Type{rFFTWPlan{$Tr,$FORWARD,inplace,N}})(X::StridedArray{$Tr,N}, + Y::StridedArray{$Tc,N}, + region, flags::Integer, timelimit::Real) where {inplace,N} R = isa(region, Tuple) ? region : copy(region) region = circshift([region...],-1) # FFTW halves last dim set_timelimit($Tr, timelimit) @@ -507,9 +506,9 @@ for (Tr,Tc,fftw,lib) in ((:Float64,:Complex128,"fftw",libfftw), return rFFTWPlan{$Tr,$FORWARD,inplace,N}(plan, flags, R, X, Y) end - @eval function (::Type{rFFTWPlan{$Tc,$BACKWARD,inplace,N}}){inplace,N}(X::StridedArray{$Tc,N}, - Y::StridedArray{$Tr,N}, - region, flags::Integer, timelimit::Real) + @eval function (::Type{rFFTWPlan{$Tc,$BACKWARD,inplace,N}})(X::StridedArray{$Tc,N}, + Y::StridedArray{$Tr,N}, + region, flags::Integer, timelimit::Real) where {inplace,N} R = isa(region, Tuple) ? region : copy(region) region = circshift([region...],-1) # FFTW halves last dim set_timelimit($Tr, timelimit) @@ -527,10 +526,10 @@ for (Tr,Tc,fftw,lib) in ((:Float64,:Complex128,"fftw",libfftw), return rFFTWPlan{$Tc,$BACKWARD,inplace,N}(plan, flags, R, X, Y) end - @eval function (::Type{r2rFFTWPlan{$Tr,ANY,inplace,N}}){inplace,N}(X::StridedArray{$Tr,N}, - Y::StridedArray{$Tr,N}, - region, kinds, flags::Integer, - timelimit::Real) + @eval function (::Type{r2rFFTWPlan{$Tr,ANY,inplace,N}})(X::StridedArray{$Tr,N}, + Y::StridedArray{$Tr,N}, + region, kinds, flags::Integer, + timelimit::Real) where {inplace,N} R = isa(region, Tuple) ? region : copy(region) knd = fix_kinds(region, kinds) set_timelimit($Tr, timelimit) @@ -549,10 +548,10 @@ for (Tr,Tc,fftw,lib) in ((:Float64,:Complex128,"fftw",libfftw), end # support r2r transforms of complex = transforms of real & imag parts - @eval function (::Type{r2rFFTWPlan{$Tc,ANY,inplace,N}}){inplace,N}(X::StridedArray{$Tc,N}, - Y::StridedArray{$Tc,N}, - region, kinds, flags::Integer, - timelimit::Real) + @eval function (::Type{r2rFFTWPlan{$Tc,ANY,inplace,N}})(X::StridedArray{$Tc,N}, + Y::StridedArray{$Tc,N}, + region, kinds, flags::Integer, + timelimit::Real) where {inplace,N} R = isa(region, Tuple) ? region : copy(region) knd = fix_kinds(region, kinds) set_timelimit($Tr, timelimit) @@ -591,16 +590,16 @@ for (f,direction) in ((:fft,FORWARD), (:bfft,BACKWARD)) plan_f! = Symbol("plan_",f,"!") idirection = -direction @eval begin - function $plan_f{T<:fftwComplex,N}(X::StridedArray{T,N}, region; - flags::Integer=ESTIMATE, - timelimit::Real=NO_TIMELIMIT) + function $plan_f(X::StridedArray{T,N}, region; + flags::Integer=ESTIMATE, + timelimit::Real=NO_TIMELIMIT) where {T<:fftwComplex,N} cFFTWPlan{T,$direction,false,N}(X, fakesimilar(flags, X, T), region, flags, timelimit) end - function $plan_f!{T<:fftwComplex,N}(X::StridedArray{T,N}, region; - flags::Integer=ESTIMATE, - timelimit::Real=NO_TIMELIMIT) + function $plan_f!(X::StridedArray{T,N}, region; + flags::Integer=ESTIMATE, + timelimit::Real=NO_TIMELIMIT) where {T<:fftwComplex,N} cFFTWPlan{T,$direction,true,N}(X, X, region, flags, timelimit) end $plan_f(X::StridedArray{<:fftwComplex}; kws...) = @@ -608,7 +607,7 @@ for (f,direction) in ((:fft,FORWARD), (:bfft,BACKWARD)) $plan_f!(X::StridedArray{<:fftwComplex}; kws...) = $plan_f!(X, 1:ndims(X); kws...) - function plan_inv{T<:fftwComplex,N,inplace}(p::cFFTWPlan{T,$direction,inplace,N}) + function plan_inv(p::cFFTWPlan{T,$direction,inplace,N}) where {T<:fftwComplex,N,inplace} X = Array{T}(p.sz) Y = inplace ? X : fakesimilar(p.flags, X, T) ScaledPlan(cFFTWPlan{T,$idirection,inplace,N}(X, Y, p.region, @@ -642,17 +641,17 @@ end for (Tr,Tc) in ((:Float32,:Complex64),(:Float64,:Complex128)) # Note: use $FORWARD and $BACKWARD below because of issue #9775 @eval begin - function plan_rfft{N}(X::StridedArray{$Tr,N}, region; - flags::Integer=ESTIMATE, - timelimit::Real=NO_TIMELIMIT) + function plan_rfft(X::StridedArray{$Tr,N}, region; + flags::Integer=ESTIMATE, + timelimit::Real=NO_TIMELIMIT) where N osize = rfft_output_size(X, region) Y = flags&ESTIMATE != 0 ? FakeArray($Tc,osize...) : Array{$Tc}(osize...) rFFTWPlan{$Tr,$FORWARD,false,N}(X, Y, region, flags, timelimit) end - function plan_brfft{N}(X::StridedArray{$Tc,N}, d::Integer, region; - flags::Integer=ESTIMATE, - timelimit::Real=NO_TIMELIMIT) + function plan_brfft(X::StridedArray{$Tc,N}, d::Integer, region; + flags::Integer=ESTIMATE, + timelimit::Real=NO_TIMELIMIT) where N osize = brfft_output_size(X, d, region) Y = flags&ESTIMATE != 0 ? FakeArray($Tr,osize...) : Array{$Tr}(osize...) @@ -672,7 +671,7 @@ for (Tr,Tc) in ((:Float32,:Complex64),(:Float64,:Complex128)) plan_rfft(X::StridedArray{$Tr};kws...)=plan_rfft(X,1:ndims(X);kws...) plan_brfft(X::StridedArray{$Tr};kws...)=plan_brfft(X,1:ndims(X);kws...) - function plan_inv{N}(p::rFFTWPlan{$Tr,$FORWARD,false,N}) + function plan_inv(p::rFFTWPlan{$Tr,$FORWARD,false,N}) where N X = Array{$Tr}(p.sz) Y = p.flags&ESTIMATE != 0 ? FakeArray($Tc,p.osz) : Array{$Tc}(p.osz) ScaledPlan(rFFTWPlan{$Tc,$BACKWARD,false,N}(Y, X, p.region, @@ -682,7 +681,7 @@ for (Tr,Tc) in ((:Float32,:Complex64),(:Float64,:Complex128)) normalization(X, p.region)) end - function plan_inv{N}(p::rFFTWPlan{$Tc,$BACKWARD,false,N}) + function plan_inv(p::rFFTWPlan{$Tc,$BACKWARD,false,N}) where N X = Arra{$Tc}(p.sz) Y = p.flags&ESTIMATE != 0 ? FakeArray($Tr,p.osz) : Array{$Tr}(p.osz) ScaledPlan(rFFTWPlan{$Tr,$FORWARD,false,N}(Y, X, p.region, @@ -701,14 +700,14 @@ for (Tr,Tc) in ((:Float32,:Complex64),(:Float64,:Complex128)) return y end - function *{N}(p::rFFTWPlan{$Tr,$FORWARD,false}, x::StridedArray{$Tr,N}) + function *(p::rFFTWPlan{$Tr,$FORWARD,false}, x::StridedArray{$Tr,N}) where N assert_applicable(p, x) y = Array{$Tc}(p.osz)::Array{$Tc,N} unsafe_execute!(p, x, y) return y end - function *{N}(p::rFFTWPlan{$Tc,$BACKWARD,false}, x::StridedArray{$Tc,N}) + function *(p::rFFTWPlan{$Tc,$BACKWARD,false}, x::StridedArray{$Tc,N}) where N if p.flags & PRESERVE_INPUT != 0 assert_applicable(p, x) y = Array{$Tr}(p.osz)::Array{$Tr,N} @@ -739,16 +738,16 @@ for f in (:r2r, :r2r!) end end -function plan_r2r{T<:fftwNumber,N}(X::StridedArray{T,N}, kinds, region; - flags::Integer=ESTIMATE, - timelimit::Real=NO_TIMELIMIT) +function plan_r2r(X::StridedArray{T,N}, kinds, region; + flags::Integer=ESTIMATE, + timelimit::Real=NO_TIMELIMIT) where {T<:fftwNumber,N} r2rFFTWPlan{T,ANY,false,N}(X, fakesimilar(flags, X, T), region, kinds, flags, timelimit) end -function plan_r2r!{T<:fftwNumber,N}(X::StridedArray{T,N}, kinds, region; - flags::Integer=ESTIMATE, - timelimit::Real=NO_TIMELIMIT) +function plan_r2r!(X::StridedArray{T,N}, kinds, region; + flags::Integer=ESTIMATE, + timelimit::Real=NO_TIMELIMIT) where {T<:fftwNumber,N} r2rFFTWPlan{T,ANY,true,N}(X, X, region, kinds, flags, timelimit) end @@ -770,7 +769,7 @@ function logical_size(n::Integer, k::Integer) return 2n end -function plan_inv{T<:fftwNumber,K,inplace,N}(p::r2rFFTWPlan{T,K,inplace,N}) +function plan_inv(p::r2rFFTWPlan{T,K,inplace,N}) where {T<:fftwNumber,K,inplace,N} X = Array{T}(p.sz) iK = fix_kinds(p.region, [inv_kind[k] for k in K]) Y = inplace ? X : fakesimilar(p.flags, X, T) diff --git a/base/fft/dct.jl b/base/fft/dct.jl index 436fd8671dc6d..a3410961a7f89 100644 --- a/base/fft/dct.jl +++ b/base/fft/dct.jl @@ -30,7 +30,7 @@ for (pf, pfr, K, inplace) in ((:plan_dct, :plan_r2r, REDFT10, false), (:plan_dct!, :plan_r2r!, REDFT10, true), (:plan_idct, :plan_r2r, REDFT01, false), (:plan_idct!, :plan_r2r!, REDFT01, true)) - @eval function $pf{T<:fftwNumber}(X::StridedArray{T}, region; kws...) + @eval function $pf(X::StridedArray{T}, region; kws...) where T<:fftwNumber r = [1:n for n in size(X)] nrm = sqrt(0.5^length(region) * normalization(X,region)) DCTPlan{T,$K,$inplace}($pfr(X, $K, region; kws...), r, nrm, @@ -38,7 +38,7 @@ for (pf, pfr, K, inplace) in ((:plan_dct, :plan_r2r, REDFT10, false), end end -function plan_inv{T,K,inplace}(p::DCTPlan{T,K,inplace}) +function plan_inv(p::DCTPlan{T,K,inplace}) where {T,K,inplace} X = Array{T}(p.plan.sz) iK = inv_kind[K] DCTPlan{T,iK,inplace}(inplace ? @@ -63,8 +63,8 @@ const sqrthalf = sqrt(0.5) const sqrt2 = sqrt(2.0) const onerange = 1:1 -function A_mul_B!{T}(y::StridedArray{T}, p::DCTPlan{T,REDFT10}, - x::StridedArray{T}) +function A_mul_B!(y::StridedArray{T}, p::DCTPlan{T,REDFT10}, + x::StridedArray{T}) where T assert_applicable(p.plan, x, y) unsafe_execute!(p.plan, x, y) scale!(y, p.nrm) @@ -79,8 +79,8 @@ function A_mul_B!{T}(y::StridedArray{T}, p::DCTPlan{T,REDFT10}, end # note: idct changes input data -function A_mul_B!{T}(y::StridedArray{T}, p::DCTPlan{T,REDFT01}, - x::StridedArray{T}) +function A_mul_B!(y::StridedArray{T}, p::DCTPlan{T,REDFT01}, + x::StridedArray{T}) where T assert_applicable(p.plan, x, y) scale!(x, p.nrm) r = p.r diff --git a/base/int.jl b/base/int.jl index 023917dc40c82..1597c0320dd0a 100644 --- a/base/int.jl +++ b/base/int.jl @@ -259,7 +259,7 @@ julia> count_zeros(Int32(2 ^ 16 - 1)) 16 ``` """ -count_zeros( x::Integer) = count_ones(~x) +count_zeros(x::Integer) = count_ones(~x) """ leading_ones(x::Integer) -> Integer @@ -271,7 +271,7 @@ julia> leading_ones(UInt32(2 ^ 32 - 2)) 31 ``` """ -leading_ones( x::Integer) = leading_zeros(~x) +leading_ones(x::Integer) = leading_zeros(~x) """ trailing_ones(x::Integer) -> Integer diff --git a/base/io.jl b/base/io.jl index 3e57236326a1a..6e9e8c87a4267 100644 --- a/base/io.jl +++ b/base/io.jl @@ -354,20 +354,20 @@ function write(to::IO, from::IO) end end -@noinline unsafe_read{T}(s::IO, p::Ref{T}, n::Integer) = unsafe_read(s, unsafe_convert(Ref{T}, p)::Ptr, n) # mark noinline to ensure ref is gc-rooted somewhere (by the caller) +@noinline unsafe_read(s::IO, p::Ref{T}, n::Integer) where {T} = unsafe_read(s, unsafe_convert(Ref{T}, p)::Ptr, n) # mark noinline to ensure ref is gc-rooted somewhere (by the caller) unsafe_read(s::IO, p::Ptr, n::Integer) = unsafe_read(s, convert(Ptr{UInt8}, p), convert(UInt, n)) -read{T}(s::IO, x::Ref{T}) = (unsafe_read(s, x, Core.sizeof(T)); x) +read(s::IO, x::Ref{T}) where {T} = (unsafe_read(s, x, Core.sizeof(T)); x) read(s::IO, ::Type{Int8}) = reinterpret(Int8, read(s, UInt8)) function read(s::IO, T::Union{Type{Int16},Type{UInt16},Type{Int32},Type{UInt32},Type{Int64},Type{UInt64},Type{Int128},Type{UInt128},Type{Float16},Type{Float32},Type{Float64}}) return read(s, Ref{T}(0))[]::T end -read(s::IO, ::Type{Bool}) = (read(s,UInt8)!=0) -read{T}(s::IO, ::Type{Ptr{T}}) = convert(Ptr{T}, read(s, UInt)) +read(s::IO, ::Type{Bool}) = (read(s, UInt8) != 0) +read(s::IO, ::Type{Ptr{T}}) where {T} = convert(Ptr{T}, read(s, UInt)) -read{T}(s::IO, t::Type{T}, d1::Int, dims::Int...) = read(s, t, tuple(d1,dims...)) -read{T}(s::IO, t::Type{T}, d1::Integer, dims::Integer...) = +read(s::IO, t::Type{T}, d1::Int, dims::Int...) where {T} = read(s, t, tuple(d1,dims...)) +read(s::IO, t::Type{T}, d1::Integer, dims::Integer...) where {T} = read(s, t, convert(Tuple{Vararg{Int}},tuple(d1,dims...))) """ @@ -377,14 +377,14 @@ Read a series of values of type `T` from `stream`, in canonical binary represent `dims` is either a tuple or a series of integer arguments specifying the size of the `Array{T}` to return. """ -read{T}(s::IO, ::Type{T}, dims::Dims) = read!(s, Array{T}(dims)) +read(s::IO, ::Type{T}, dims::Dims) where {T} = read!(s, Array{T}(dims)) @noinline function read!(s::IO, a::Array{UInt8}) # mark noinline to ensure the array is gc-rooted somewhere (by the caller) unsafe_read(s, pointer(a), sizeof(a)) return a end -@noinline function read!{T}(s::IO, a::Array{T}) # mark noinline to ensure the array is gc-rooted somewhere (by the caller) +@noinline function read!(s::IO, a::Array{T}) where T # mark noinline to ensure the array is gc-rooted somewhere (by the caller) if isbits(T) unsafe_read(s, pointer(a), sizeof(a)) else @@ -614,7 +614,7 @@ previously marked position. Throws an error if the stream is not marked. See also [`mark`](@ref), [`unmark`](@ref), [`ismarked`](@ref). """ -function reset{T<:IO}(io::T) +function reset(io::T) where T<:IO ismarked(io) || throw(ArgumentError("$(T) not marked")) m = io.mark seek(io, m) diff --git a/base/iobuffer.jl b/base/iobuffer.jl index 85a3e1a717379..c9d4226462dac 100644 --- a/base/iobuffer.jl +++ b/base/iobuffer.jl @@ -143,7 +143,7 @@ function peek(from::AbstractIOBuffer) return from.data[from.ptr] end -read{T}(from::AbstractIOBuffer, ::Type{Ptr{T}}) = convert(Ptr{T}, read(from, UInt)) +read(from::AbstractIOBuffer, ::Type{Ptr{T}}) where {T} = convert(Ptr{T}, read(from, UInt)) isreadable(io::AbstractIOBuffer) = io.readable iswritable(io::AbstractIOBuffer) = io.writable @@ -241,7 +241,7 @@ end eof(io::AbstractIOBuffer) = (io.ptr-1 == io.size) -@noinline function close{T}(io::AbstractIOBuffer{T}) +@noinline function close(io::AbstractIOBuffer{T}) where T io.readable = false io.writable = false io.seekable = false diff --git a/base/linalg/cholesky.jl b/base/linalg/cholesky.jl index 47c0d3610650e..f43e9364db459 100644 --- a/base/linalg/cholesky.jl +++ b/base/linalg/cholesky.jl @@ -144,7 +144,7 @@ function chol(A::Hermitian) end chol!(Hermitian(AA, :U)) end -function chol{T<:Real}(A::Symmetric{T,<:AbstractMatrix}) +function chol(A::Symmetric{T,<:AbstractMatrix}) where T<:Real TT = promote_type(typeof(chol(one(T))), Float32) AA = similar(A, TT, size(A)) if A.uplo == 'U' @@ -443,7 +443,7 @@ end show(io::IO, C::Cholesky{<:Any,<:AbstractMatrix}) = (println(io, "$(typeof(C)) with factor:");show(io,C[:UL])) -A_ldiv_B!{T<:BlasFloat}(C::Cholesky{T,<:AbstractMatrix}, B::StridedVecOrMat{T}) = +A_ldiv_B!(C::Cholesky{T,<:AbstractMatrix}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = LAPACK.potrs!(C.uplo, C.factors, B) function A_ldiv_B!(C::Cholesky{<:Any,<:AbstractMatrix}, B::StridedVecOrMat) @@ -454,11 +454,11 @@ function A_ldiv_B!(C::Cholesky{<:Any,<:AbstractMatrix}, B::StridedVecOrMat) end end -function A_ldiv_B!{T<:BlasFloat}(C::CholeskyPivoted{T}, B::StridedVector{T}) +function A_ldiv_B!(C::CholeskyPivoted{T}, B::StridedVector{T}) where T<:BlasFloat chkfullrank(C) ipermute!(LAPACK.potrs!(C.uplo, C.factors, permute!(B, C.piv)), C.piv) end -function A_ldiv_B!{T<:BlasFloat}(C::CholeskyPivoted{T}, B::StridedMatrix{T}) +function A_ldiv_B!(C::CholeskyPivoted{T}, B::StridedMatrix{T}) where T<:BlasFloat chkfullrank(C) n = size(C, 1) for i=1:size(B, 2) diff --git a/base/linalg/linalg.jl b/base/linalg/linalg.jl index d92d2c39d8baa..ffc97a3dd78c4 100644 --- a/base/linalg/linalg.jl +++ b/base/linalg/linalg.jl @@ -237,8 +237,8 @@ function char_uplo(uplo::Symbol) end end -copy_oftype{T}(A::AbstractArray{T}, ::Type{T}) = copy(A) -copy_oftype{T,N,S}(A::AbstractArray{T,N}, ::Type{S}) = convert(AbstractArray{S,N}, A) +copy_oftype(A::AbstractArray{T}, ::Type{T}) where {T} = copy(A) +copy_oftype(A::AbstractArray{T,N}, ::Type{S}) where {T,N,S} = convert(AbstractArray{S,N}, A) include("conjarray.jl") include("transpose.jl") diff --git a/base/linalg/lq.jl b/base/linalg/lq.jl index 0e1f1a7ab43d6..a647550bcf9a4 100644 --- a/base/linalg/lq.jl +++ b/base/linalg/lq.jl @@ -122,7 +122,7 @@ size(A::LQPackedQ) = size(A.factors) A_mul_B!(A::LQ{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = A[:L]*LAPACK.ormlq!('L','N',A.factors,A.τ,B) A_mul_B!(A::LQ{T}, B::QR{T}) where {T<:BlasFloat} = A[:L]*LAPACK.ormlq!('L','N',A.factors,A.τ,full(B)) A_mul_B!(A::QR{T}, B::LQ{T}) where {T<:BlasFloat} = A_mul_B!(zeros(full(A)), full(A), full(B)) -function *(A::LQ{TA},B::StridedVecOrMat{TB}) where {TA,TB} +function *(A::LQ{TA}, B::StridedVecOrMat{TB}) where {TA,TB} TAB = promote_type(TA, TB) A_mul_B!(convert(Factorization{TAB},A), copy_oftype(B, TAB)) end @@ -138,7 +138,7 @@ end ## Multiplication by Q ### QB A_mul_B!(A::LQPackedQ{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = LAPACK.ormlq!('L','N',A.factors,A.τ,B) -function (*)(A::LQPackedQ,B::StridedVecOrMat) +function (*)(A::LQPackedQ, B::StridedVecOrMat) TAB = promote_type(eltype(A), eltype(B)) A_mul_B!(convert(AbstractMatrix{TAB}, A), copy_oftype(B, TAB)) end @@ -172,7 +172,7 @@ end ### AQ A_mul_B!(A::StridedMatrix{T}, B::LQPackedQ{T}) where {T<:BlasFloat} = LAPACK.ormlq!('R', 'N', B.factors, B.τ, A) -function *(A::StridedMatrix{TA},B::LQPackedQ{TB}) where {TA,TB} +function *(A::StridedMatrix{TA}, B::LQPackedQ{TB}) where {TA,TB} TAB = promote_type(TA,TB) if size(B.factors,2) == size(A,2) A_mul_B!(copy_oftype(A, TAB),convert(AbstractMatrix{TAB},B)) @@ -186,7 +186,7 @@ end ### AQc A_mul_Bc!(A::StridedMatrix{T}, B::LQPackedQ{T}) where {T<:BlasReal} = LAPACK.ormlq!('R','T',B.factors,B.τ,A) A_mul_Bc!(A::StridedMatrix{T}, B::LQPackedQ{T}) where {T<:BlasComplex} = LAPACK.ormlq!('R','C',B.factors,B.τ,A) -function A_mul_Bc( A::StridedVecOrMat{TA}, B::LQPackedQ{TB}) where {TA<:Number,TB<:Number} +function A_mul_Bc(A::StridedVecOrMat{TA}, B::LQPackedQ{TB}) where {TA<:Number,TB<:Number} TAB = promote_type(TA,TB) A_mul_Bc!(copy_oftype(A, TAB), convert(AbstractMatrix{TAB},(B))) end @@ -230,7 +230,7 @@ function (\)(F::LQ{T}, B::VecOrMat{Complex{T}}) where T<:BlasReal end -function A_ldiv_B!{T}(A::LQ{T}, B::StridedVecOrMat{T}) +function A_ldiv_B!(A::LQ{T}, B::StridedVecOrMat{T}) where T Ac_mul_B!(A[:Q], A_ldiv_B!(LowerTriangular(A[:L]),B)) return B end diff --git a/base/linalg/rowvector.jl b/base/linalg/rowvector.jl index d7e9074e6143c..513e379ad3c2b 100644 --- a/base/linalg/rowvector.jl +++ b/base/linalg/rowvector.jl @@ -21,8 +21,8 @@ struct RowVector{T,V<:AbstractVector} <: AbstractMatrix{T} end end -@inline check_types{T1,T2}(::Type{T1},::AbstractVector{T2}) = check_types(T1, T2) -@pure check_types{T1,T2}(::Type{T1},::Type{T2}) = T1 === transpose_type(T2) ? nothing : +@inline check_types(::Type{T1}, ::AbstractVector{T2}) where {T1,T2} = check_types(T1, T2) +@pure check_types(::Type{T1}, ::Type{T2}) where {T1,T2} = T1 === transpose_type(T2) ? nothing : error("Element type mismatch. Tried to create a `RowVector{$T1}` from an `AbstractVector{$T2}`") ConjRowVector{T, CV <: ConjVector} = RowVector{T, CV} @@ -50,10 +50,10 @@ convert(::Type{RowVector{T,V}}, rowvec::RowVector) where {T,V<:AbstractVector} = # similar tries to maintain the RowVector wrapper and the parent type @inline similar(rowvec::RowVector) = RowVector(similar(parent(rowvec))) -@inline similar{T}(rowvec::RowVector, ::Type{T}) = RowVector(similar(parent(rowvec), transpose_type(T))) +@inline similar(rowvec::RowVector, ::Type{T}) where {T} = RowVector(similar(parent(rowvec), transpose_type(T))) # Resizing similar currently loses its RowVector property. -@inline similar{T,N}(rowvec::RowVector, ::Type{T}, dims::Dims{N}) = similar(parent(rowvec), T, dims) +@inline similar(rowvec::RowVector, ::Type{T}, dims::Dims{N}) where {T,N} = similar(parent(rowvec), T, dims) # Basic methods """ @@ -159,16 +159,16 @@ end @inline hcat(X::RowVector...) = transpose(vcat(map(transpose, X)...)) @inline hcat(X::Union{RowVector,Number}...) = transpose(vcat(map(transpose, X)...)) -@inline typed_hcat{T}(::Type{T}, X::RowVector...) = +@inline typed_hcat(::Type{T}, X::RowVector...) where {T} = transpose(typed_vcat(T, map(transpose, X)...)) -@inline typed_hcat{T}(::Type{T}, X::Union{RowVector,Number}...) = +@inline typed_hcat(::Type{T}, X::Union{RowVector,Number}...) where {T} = transpose(typed_vcat(T, map(transpose, X)...)) # Multiplication # # inner product -> dot product specializations -@inline *{T<:Real}(rowvec::RowVector{T}, vec::AbstractVector{T}) = dot(parent(rowvec), vec) -@inline *{T<:Real}(rowvec::ConjRowVector{T}, vec::AbstractVector{T}) = dot(rowvec', vec) +@inline *(rowvec::RowVector{T}, vec::AbstractVector{T}) where {T<:Real} = dot(parent(rowvec), vec) +@inline *(rowvec::ConjRowVector{T}, vec::AbstractVector{T}) where {T<:Real} = dot(rowvec', vec) @inline *(rowvec::ConjRowVector, vec::AbstractVector) = dot(rowvec', vec) # Generic behavior diff --git a/base/linalg/schur.jl b/base/linalg/schur.jl index da63220b5128a..5f4378cc9710e 100644 --- a/base/linalg/schur.jl +++ b/base/linalg/schur.jl @@ -143,7 +143,7 @@ ordschur(schur::Schur, select::Union{Vector{Bool},BitVector}) = Same as [`ordschur`](@ref) but overwrites the input arguments. """ -ordschur!{Ty<:BlasFloat}(T::StridedMatrix{Ty}, Z::StridedMatrix{Ty}, select::Union{Vector{Bool},BitVector}) = +ordschur!(T::StridedMatrix{Ty}, Z::StridedMatrix{Ty}, select::Union{Vector{Bool},BitVector}) where {Ty<:BlasFloat} = LinAlg.LAPACK.trsen!(convert(Vector{BlasInt}, select), T, Z) """ @@ -156,7 +156,7 @@ corresponding leading columns of `Z` form an orthogonal/unitary basis of the cor right invariant subspace. In the real case, a complex conjugate pair of eigenvalues must be either both included or both excluded via `select`. """ -ordschur{Ty<:BlasFloat}(T::StridedMatrix{Ty}, Z::StridedMatrix{Ty}, select::Union{Vector{Bool},BitVector}) = +ordschur(T::StridedMatrix{Ty}, Z::StridedMatrix{Ty}, select::Union{Vector{Bool},BitVector}) where {Ty<:BlasFloat} = ordschur!(copy(T), copy(Z), select) struct GeneralizedSchur{Ty,M<:AbstractMatrix} <: Factorization{Ty} @@ -181,7 +181,7 @@ end Same as [`schurfact`](@ref) but uses the input matrices `A` and `B` as workspace. """ -schurfact!{T<:BlasFloat}(A::StridedMatrix{T}, B::StridedMatrix{T}) = +schurfact!(A::StridedMatrix{T}, B::StridedMatrix{T}) where {T<:BlasFloat} = GeneralizedSchur(LinAlg.LAPACK.gges!('V', 'V', A, B)...) """ @@ -194,8 +194,8 @@ and `F[:T]`, the left unitary/orthogonal Schur vectors can be obtained with `F[: `F[:Z]` such that `A=F[:left]*F[:S]*F[:right]'` and `B=F[:left]*F[:T]*F[:right]'`. The generalized eigenvalues of `A` and `B` can be obtained with `F[:alpha]./F[:beta]`. """ -schurfact{T<:BlasFloat}(A::StridedMatrix{T},B::StridedMatrix{T}) = schurfact!(copy(A),copy(B)) -function schurfact{TA,TB}(A::StridedMatrix{TA}, B::StridedMatrix{TB}) +schurfact(A::StridedMatrix{T},B::StridedMatrix{T}) where {T<:BlasFloat} = schurfact!(copy(A),copy(B)) +function schurfact(A::StridedMatrix{TA}, B::StridedMatrix{TB}) where {TA,TB} S = promote_type(Float32, typeof(one(TA)/norm(one(TA))), TB) return schurfact!(copy_oftype(A, S), copy_oftype(B, S)) end @@ -230,8 +230,8 @@ ordschur(gschur::GeneralizedSchur, select::Union{Vector{Bool},BitVector}) = Same as [`ordschur`](@ref) but overwrites the factorization the input arguments. """ -ordschur!{Ty<:BlasFloat}(S::StridedMatrix{Ty}, T::StridedMatrix{Ty}, Q::StridedMatrix{Ty}, - Z::StridedMatrix{Ty}, select::Union{Vector{Bool},BitVector}) = +ordschur!(S::StridedMatrix{Ty}, T::StridedMatrix{Ty}, Q::StridedMatrix{Ty}, + Z::StridedMatrix{Ty}, select::Union{Vector{Bool},BitVector}) where {Ty<:BlasFloat} = LinAlg.LAPACK.tgsen!(convert(Vector{BlasInt}, select), S, T, Q, Z) """ @@ -244,8 +244,8 @@ and `T`, and the left and right unitary/orthogonal Schur vectors are also reorde that `(A, B) = Q*(S, T)*Z'` still holds and the generalized eigenvalues of `A` and `B` can still be obtained with `α./β`. """ -ordschur{Ty<:BlasFloat}(S::StridedMatrix{Ty}, T::StridedMatrix{Ty}, Q::StridedMatrix{Ty}, - Z::StridedMatrix{Ty}, select::Union{Vector{Bool},BitVector}) = +ordschur(S::StridedMatrix{Ty}, T::StridedMatrix{Ty}, Q::StridedMatrix{Ty}, + Z::StridedMatrix{Ty}, select::Union{Vector{Bool},BitVector}) where {Ty<:BlasFloat} = ordschur!(copy(S), copy(T), copy(Q), copy(Z), select) function getindex(F::GeneralizedSchur, d::Symbol) diff --git a/base/linalg/triangular.jl b/base/linalg/triangular.jl index e940ff2c138e8..097a20441e41a 100644 --- a/base/linalg/triangular.jl +++ b/base/linalg/triangular.jl @@ -21,16 +21,16 @@ for t in (:LowerTriangular, :UnitLowerTriangular, :UpperTriangular, size(A::$t, d) = size(A.data, d) size(A::$t) = size(A.data) - convert{T}(::Type{$t{T}}, A::$t{T}) = A - function convert{T}(::Type{$t{T}}, A::$t) + convert(::Type{$t{T}}, A::$t{T}) where {T} = A + function convert(::Type{$t{T}}, A::$t) where T Anew = convert(AbstractMatrix{T}, A.data) $t(Anew) end - convert{T}(::Type{AbstractMatrix{T}}, A::$t{T}) = A - convert{T}(::Type{AbstractMatrix{T}}, A::$t) = convert($t{T}, A) - convert{T}(::Type{Matrix}, A::$t{T}) = convert(Matrix{T}, A) + convert(::Type{AbstractMatrix{T}}, A::$t{T}) where {T} = A + convert(::Type{AbstractMatrix{T}}, A::$t) where {T} = convert($t{T}, A) + convert(::Type{Matrix}, A::$t{T}) where {T} = convert(Matrix{T}, A) - function similar{T}(A::$t, ::Type{T}) + function similar(A::$t, ::Type{T}) where T B = similar(A.data, T) return $t(B) end @@ -62,13 +62,13 @@ parent(A::AbstractTriangular) = A.data # then handle all methods that requires specific handling of upper/lower and unit diagonal function convert(::Type{Matrix{T}}, A::LowerTriangular) where T - B = Array{T}(size(A, 1), size(A, 1)) + B = Matrix{T}(size(A, 1), size(A, 1)) copy!(B, A.data) tril!(B) B end function convert(::Type{Matrix{T}}, A::UnitLowerTriangular) where T - B = Array{T}(size(A, 1), size(A, 1)) + B = Matrix{T}(size(A, 1), size(A, 1)) copy!(B, A.data) tril!(B) for i = 1:size(B,1) @@ -77,13 +77,13 @@ function convert(::Type{Matrix{T}}, A::UnitLowerTriangular) where T B end function convert(::Type{Matrix{T}}, A::UpperTriangular) where T - B = Array{T}(size(A, 1), size(A, 1)) + B = Matrix{T}(size(A, 1), size(A, 1)) copy!(B, A.data) triu!(B) B end function convert(::Type{Matrix{T}}, A::UnitUpperTriangular) where T - B = Array{T}(size(A, 1), size(A, 1)) + B = Matrix{T}(size(A, 1), size(A, 1)) copy!(B, A.data) triu!(B) for i = 1:size(B,1) @@ -189,7 +189,7 @@ istril(A::UnitLowerTriangular) = true istriu(A::UpperTriangular) = true istriu(A::UnitUpperTriangular) = true -function tril!(A::UpperTriangular,k::Integer=0) +function tril!(A::UpperTriangular, k::Integer=0) n = size(A,1) if abs(k) > n throw(ArgumentError("requested diagonal, $k, out of bounds in matrix of size ($n,$n)")) @@ -205,9 +205,9 @@ function tril!(A::UpperTriangular,k::Integer=0) return UpperTriangular(tril!(A.data,k)) end end -triu!(A::UpperTriangular,k::Integer=0) = UpperTriangular(triu!(A.data,k)) +triu!(A::UpperTriangular, k::Integer=0) = UpperTriangular(triu!(A.data,k)) -function tril!{T}(A::UnitUpperTriangular{T},k::Integer=0) +function tril!{T}(A::UnitUpperTriangular{T}, k::Integer=0) n = size(A,1) if abs(k) > n throw(ArgumentError("requested diagonal, $k, out of bounds in matrix of size ($n,$n)")) @@ -228,14 +228,14 @@ function tril!{T}(A::UnitUpperTriangular{T},k::Integer=0) end end -function triu!(A::UnitUpperTriangular,k::Integer=0) +function triu!(A::UnitUpperTriangular, k::Integer=0) for i in diagind(A) A.data[i] = oneunit(eltype(A)) end return triu!(UpperTriangular(A.data),k) end -function triu!(A::LowerTriangular,k::Integer=0) +function triu!(A::LowerTriangular, k::Integer=0) n = size(A,1) if abs(k) > n throw(ArgumentError("requested diagonal, $k, out of bounds in matrix of size ($n,$n)")) @@ -252,9 +252,9 @@ function triu!(A::LowerTriangular,k::Integer=0) end end -tril!(A::LowerTriangular,k::Integer=0) = LowerTriangular(tril!(A.data,k)) +tril!(A::LowerTriangular, k::Integer=0) = LowerTriangular(tril!(A.data,k)) -function triu!{T}(A::UnitLowerTriangular{T},k::Integer=0) +function triu!(A::UnitLowerTriangular{T}, k::Integer=0) where T n = size(A,1) if abs(k) > n throw(ArgumentError("requested diagonal, $k, out of bounds in matrix of size ($n,$n)")) @@ -275,7 +275,7 @@ function triu!{T}(A::UnitLowerTriangular{T},k::Integer=0) end end -function tril!(A::UnitLowerTriangular,k::Integer=0) +function tril!(A::UnitLowerTriangular, k::Integer=0) for i in diagind(A) A.data[i] = oneunit(eltype(A)) end @@ -367,7 +367,7 @@ function scale!(A::LowerTriangular, B::Union{LowerTriangular,UnitLowerTriangular end return A end -scale!(A::Union{UpperTriangular,LowerTriangular},c::Number) = scale!(A,A,c) +scale!(A::Union{UpperTriangular,LowerTriangular}, c::Number) = scale!(A,A,c) scale!(c::Number, A::Union{UpperTriangular,LowerTriangular}) = scale!(A,c) # Binary operations @@ -411,61 +411,61 @@ for (t, uploc, isunitc) in ((:LowerTriangular, 'L', 'N'), (:UnitUpperTriangular, 'U', 'U')) @eval begin # Vector multiplication - A_mul_B!{T<:BlasFloat}(A::$t{T,<:StridedMatrix}, b::StridedVector{T}) = + A_mul_B!(A::$t{T,<:StridedMatrix}, b::StridedVector{T}) where {T<:BlasFloat} = BLAS.trmv!($uploc, 'N', $isunitc, A.data, b) - At_mul_B!{T<:BlasFloat}(A::$t{T,<:StridedMatrix}, b::StridedVector{T}) = + At_mul_B!(A::$t{T,<:StridedMatrix}, b::StridedVector{T}) where {T<:BlasFloat} = BLAS.trmv!($uploc, 'T', $isunitc, A.data, b) - Ac_mul_B!{T<:BlasReal}(A::$t{T,<:StridedMatrix}, b::StridedVector{T}) = + Ac_mul_B!(A::$t{T,<:StridedMatrix}, b::StridedVector{T}) where {T<:BlasReal} = BLAS.trmv!($uploc, 'T', $isunitc, A.data, b) - Ac_mul_B!{T<:BlasComplex}(A::$t{T,<:StridedMatrix}, b::StridedVector{T}) = + Ac_mul_B!(A::$t{T,<:StridedMatrix}, b::StridedVector{T}) where {T<:BlasComplex} = BLAS.trmv!($uploc, 'C', $isunitc, A.data, b) # Matrix multiplication - A_mul_B!{T<:BlasFloat}(A::$t{T,<:StridedMatrix}, B::StridedMatrix{T}) = + A_mul_B!(A::$t{T,<:StridedMatrix}, B::StridedMatrix{T}) where {T<:BlasFloat} = BLAS.trmm!('L', $uploc, 'N', $isunitc, one(T), A.data, B) - A_mul_B!{T<:BlasFloat}(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) = + A_mul_B!(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) where {T<:BlasFloat} = BLAS.trmm!('R', $uploc, 'N', $isunitc, one(T), B.data, A) - At_mul_B!{T<:BlasFloat}(A::$t{T,<:StridedMatrix}, B::StridedMatrix{T}) = + At_mul_B!(A::$t{T,<:StridedMatrix}, B::StridedMatrix{T}) where {T<:BlasFloat} = BLAS.trmm!('L', $uploc, 'T', $isunitc, one(T), A.data, B) - Ac_mul_B!{T<:BlasComplex}(A::$t{T,<:StridedMatrix}, B::StridedMatrix{T}) = + Ac_mul_B!(A::$t{T,<:StridedMatrix}, B::StridedMatrix{T}) where {T<:BlasComplex} = BLAS.trmm!('L', $uploc, 'C', $isunitc, one(T), A.data, B) - Ac_mul_B!{T<:BlasReal}(A::$t{T,<:StridedMatrix}, B::StridedMatrix{T}) = + Ac_mul_B!(A::$t{T,<:StridedMatrix}, B::StridedMatrix{T}) where {T<:BlasReal} = BLAS.trmm!('L', $uploc, 'T', $isunitc, one(T), A.data, B) - A_mul_Bt!{T<:BlasFloat}(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) = + A_mul_Bt!(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) where {T<:BlasFloat} = BLAS.trmm!('R', $uploc, 'T', $isunitc, one(T), B.data, A) - A_mul_Bc!{T<:BlasComplex}(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) = + A_mul_Bc!(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) where {T<:BlasComplex} = BLAS.trmm!('R', $uploc, 'C', $isunitc, one(T), B.data, A) - A_mul_Bc!{T<:BlasReal}(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) = + A_mul_Bc!(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) where {T<:BlasReal} = BLAS.trmm!('R', $uploc, 'T', $isunitc, one(T), B.data, A) # Left division - A_ldiv_B!{T<:BlasFloat}(A::$t{T,<:StridedMatrix}, B::StridedVecOrMat{T}) = + A_ldiv_B!(A::$t{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = LAPACK.trtrs!($uploc, 'N', $isunitc, A.data, B) - At_ldiv_B!{T<:BlasFloat}(A::$t{T,<:StridedMatrix}, B::StridedVecOrMat{T}) = + At_ldiv_B!(A::$t{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = LAPACK.trtrs!($uploc, 'T', $isunitc, A.data, B) - Ac_ldiv_B!{T<:BlasReal}(A::$t{T,<:StridedMatrix}, B::StridedVecOrMat{T}) = + Ac_ldiv_B!(A::$t{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:BlasReal} = LAPACK.trtrs!($uploc, 'T', $isunitc, A.data, B) - Ac_ldiv_B!{T<:BlasComplex}(A::$t{T,<:StridedMatrix}, B::StridedVecOrMat{T}) = + Ac_ldiv_B!(A::$t{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:BlasComplex} = LAPACK.trtrs!($uploc, 'C', $isunitc, A.data, B) # Right division - A_rdiv_B!{T<:BlasFloat}(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) = + A_rdiv_B!(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) where {T<:BlasFloat} = BLAS.trsm!('R', $uploc, 'N', $isunitc, one(T), B.data, A) - A_rdiv_Bt!{T<:BlasFloat}(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) = + A_rdiv_Bt!(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) where {T<:BlasFloat} = BLAS.trsm!('R', $uploc, 'T', $isunitc, one(T), B.data, A) - A_rdiv_Bc!{T<:BlasReal}(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) = + A_rdiv_Bc!(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) where {T<:BlasReal} = BLAS.trsm!('R', $uploc, 'T', $isunitc, one(T), B.data, A) - A_rdiv_Bc!{T<:BlasComplex}(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) = + A_rdiv_Bc!(A::StridedMatrix{T}, B::$t{T,<:StridedMatrix}) where {T<:BlasComplex} = BLAS.trsm!('R', $uploc, 'C', $isunitc, one(T), B.data, A) # Matrix inverse - inv!{T<:BlasFloat,S<:StridedMatrix}(A::$t{T,S}) = + inv!(A::$t{T,S}) where {T<:BlasFloat,S<:StridedMatrix} = $t{T,S}(LAPACK.trtri!($uploc, $isunitc, A.data)) # Error bounds for triangular solve - errorbounds{T<:BlasFloat}(A::$t{T,<:StridedMatrix}, X::StridedVecOrMat{T}, B::StridedVecOrMat{T}) = + errorbounds(A::$t{T,<:StridedMatrix}, X::StridedVecOrMat{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = LAPACK.trrfs!($uploc, 'N', $isunitc, A.data, B, X) # Condition numbers @@ -482,20 +482,20 @@ for (t, uploc, isunitc) in ((:LowerTriangular, 'L', 'N'), end end -function inv{T}(A::LowerTriangular{T}) +function inv(A::LowerTriangular{T}) where T S = typeof((zero(T)*one(T) + zero(T))/one(T)) LowerTriangular(A_ldiv_B!(convert(AbstractArray{S}, A), eye(S, size(A, 1)))) end -function inv{T}(A::UpperTriangular{T}) +function inv(A::UpperTriangular{T}) where T S = typeof((zero(T)*one(T) + zero(T))/one(T)) UpperTriangular(A_ldiv_B!(convert(AbstractArray{S}, A), eye(S, size(A, 1)))) end -inv{T}(A::UnitUpperTriangular{T}) = UnitUpperTriangular(A_ldiv_B!(A, eye(T, size(A, 1)))) -inv{T}(A::UnitLowerTriangular{T}) = UnitLowerTriangular(A_ldiv_B!(A, eye(T, size(A, 1)))) +inv(A::UnitUpperTriangular{T}) where {T} = UnitUpperTriangular(A_ldiv_B!(A, eye(T, size(A, 1)))) +inv(A::UnitLowerTriangular{T}) where {T} = UnitLowerTriangular(A_ldiv_B!(A, eye(T, size(A, 1)))) -errorbounds{T<:Union{BigFloat, Complex{BigFloat}}}(A::AbstractTriangular{T,<:StridedMatrix}, X::StridedVecOrMat{T}, B::StridedVecOrMat{T}) = +errorbounds(A::AbstractTriangular{T,<:StridedMatrix}, X::StridedVecOrMat{T}, B::StridedVecOrMat{T}) where {T<:Union{BigFloat,Complex{BigFloat}}} = error("not implemented yet! Please submit a pull request.") -function errorbounds{TA<:Number,TX<:Number,TB<:Number}(A::AbstractTriangular{TA,<:StridedMatrix}, X::StridedVecOrMat{TX}, B::StridedVecOrMat{TB}) +function errorbounds(A::AbstractTriangular{TA,<:StridedMatrix}, X::StridedVecOrMat{TX}, B::StridedVecOrMat{TB}) where {TA<:Number,TX<:Number,TB<:Number} TAXB = promote_type(TA, TB, TX, Float32) errorbounds(convert(AbstractMatrix{TAXB}, A), convert(AbstractArray{TAXB}, X), convert(AbstractArray{TAXB}, B)) end @@ -1741,7 +1741,7 @@ powm(A::LowerTriangular, p::Real) = powm(A.', p::Real).' # Based on the code available at http://eprints.ma.man.ac.uk/1851/02/logm.zip, # Copyright (c) 2011, Awad H. Al-Mohy and Nicholas J. Higham # Julia version relicensed with permission from original authors -function logm{T<:Union{Float64,Complex{Float64}}}(A0::UpperTriangular{T}) +function logm(A0::UpperTriangular{T}) where T<:Union{Float64,Complex{Float64}} maxsqrt = 100 theta = [1.586970738772063e-005, 2.313807884242979e-003, @@ -1758,7 +1758,7 @@ function logm{T<:Union{Float64,Complex{Float64}}}(A0::UpperTriangular{T}) # Compute repeated roots d = diag(A) - dm1 = Array{T}(n) + dm1 = Vector{T}(n) s = 0 for i = 1:n dm1[i] = d[i] - 1. @@ -1884,7 +1884,7 @@ function logm{T<:Union{Float64,Complex{Float64}}}(A0::UpperTriangular{T}) R[i+1,i] = R[i,i+1] end x,V = eig(R) - w = Array{Float64}(m) + w = Vector{Float64}(m) for i = 1:m x[i] = (x[i] + 1) / 2 w[i] = V[1,i]^2 @@ -2095,7 +2095,7 @@ function sqrtm(A::UpperTriangular) end sqrtm(A,Val{realmatrix}) end -function sqrtm{T,realmatrix}(A::UpperTriangular{T},::Type{Val{realmatrix}}) +function sqrtm(A::UpperTriangular{T},::Type{Val{realmatrix}}) where {T,realmatrix} B = A.data n = checksquare(B) t = realmatrix ? typeof(sqrt(zero(T))) : typeof(sqrt(complex(zero(T)))) @@ -2113,7 +2113,7 @@ function sqrtm{T,realmatrix}(A::UpperTriangular{T},::Type{Val{realmatrix}}) end return UpperTriangular(R) end -function sqrtm{T}(A::UnitUpperTriangular{T}) +function sqrtm(A::UnitUpperTriangular{T}) where T B = A.data n = checksquare(B) t = typeof(sqrt(zero(T))) @@ -2136,7 +2136,7 @@ sqrtm(A::UnitLowerTriangular) = sqrtm(A.').' # Generic eigensystems eigvals(A::AbstractTriangular) = diag(A) -function eigvecs{T}(A::AbstractTriangular{T}) +function eigvecs(A::AbstractTriangular{T}) where T TT = promote_type(T, Float32) if TT <: BlasFloat return eigvecs(convert(AbstractMatrix{TT}, A)) @@ -2144,15 +2144,15 @@ function eigvecs{T}(A::AbstractTriangular{T}) throw(ArgumentError("eigvecs type $(typeof(A)) not supported. Please submit a pull request.")) end end -det{T}(A::UnitUpperTriangular{T}) = one(T) -det{T}(A::UnitLowerTriangular{T}) = one(T) -logdet{T}(A::UnitUpperTriangular{T}) = zero(T) -logdet{T}(A::UnitLowerTriangular{T}) = zero(T) -logabsdet{T}(A::UnitUpperTriangular{T}) = zero(T), one(T) -logabsdet{T}(A::UnitLowerTriangular{T}) = zero(T), one(T) +det(A::UnitUpperTriangular{T}) where {T} = one(T) +det(A::UnitLowerTriangular{T}) where {T} = one(T) +logdet(A::UnitUpperTriangular{T}) where {T} = zero(T) +logdet(A::UnitLowerTriangular{T}) where {T} = zero(T) +logabsdet(A::UnitUpperTriangular{T}) where {T} = zero(T), one(T) +logabsdet(A::UnitLowerTriangular{T}) where {T} = zero(T), one(T) det(A::UpperTriangular) = prod(diag(A.data)) det(A::LowerTriangular) = prod(diag(A.data)) -function logabsdet{T}(A::Union{UpperTriangular{T},LowerTriangular{T}}) +function logabsdet(A::Union{UpperTriangular{T},LowerTriangular{T}}) where T sgn = one(T) abs_det = zero(real(T)) @inbounds for i in 1:size(A,1) diff --git a/base/mmap.jl b/base/mmap.jl index b91e67a1bad97..eaac57e30b4df 100644 --- a/base/mmap.jl +++ b/base/mmap.jl @@ -94,10 +94,10 @@ else end # os-test # core implementation of mmap -function mmap{T,N}(io::IO, - ::Type{Array{T,N}}=Vector{UInt8}, - dims::NTuple{N,Integer}=(div(filesize(io)-position(io),sizeof(T)),), - offset::Integer=position(io); grow::Bool=true, shared::Bool=true) +function mmap(io::IO, + ::Type{Array{T,N}}=Vector{UInt8}, + dims::NTuple{N,Integer}=(div(filesize(io)-position(io),sizeof(T)),), + offset::Integer=position(io); grow::Bool=true, shared::Bool=true) where {T,N} # check inputs isopen(io) || throw(ArgumentError("$io must be open to mmap")) isbits(T) || throw(ArgumentError("unable to mmap $T; must satisfy isbits(T) == true")) @@ -149,24 +149,24 @@ function mmap{T,N}(io::IO, return A end -mmap{T<:Array,N}(file::AbstractString, - ::Type{T}=Vector{UInt8}, - dims::NTuple{N,Integer}=(div(filesize(file),sizeof(eltype(T))),), - offset::Integer=Int64(0); grow::Bool=true, shared::Bool=true) = +mmap(file::AbstractString, + ::Type{T}=Vector{UInt8}, + dims::NTuple{N,Integer}=(div(filesize(file),sizeof(eltype(T))),), + offset::Integer=Int64(0); grow::Bool=true, shared::Bool=true) where {T<:Array,N} = open(io->mmap(io, T, dims, offset; grow=grow, shared=shared), file, isfile(file) ? "r+" : "w+")::Array{eltype(T),N} # using a length argument instead of dims -mmap{T<:Array}(io::IO, ::Type{T}, len::Integer, offset::Integer=position(io); grow::Bool=true, shared::Bool=true) = +mmap(io::IO, ::Type{T}, len::Integer, offset::Integer=position(io); grow::Bool=true, shared::Bool=true) where {T<:Array} = mmap(io, T, (len,), offset; grow=grow, shared=shared) -mmap{T<:Array}(file::AbstractString, ::Type{T}, len::Integer, offset::Integer=Int64(0); grow::Bool=true, shared::Bool=true) = +mmap(file::AbstractString, ::Type{T}, len::Integer, offset::Integer=Int64(0); grow::Bool=true, shared::Bool=true) where {T<:Array} = open(io->mmap(io, T, (len,), offset; grow=grow, shared=shared), file, isfile(file) ? "r+" : "w+")::Vector{eltype(T)} # constructors for non-file-backed (anonymous) mmaps -mmap{T<:Array,N}(::Type{T}, dims::NTuple{N,Integer}; shared::Bool=true) = mmap(Anonymous(), T, dims, Int64(0); shared=shared) -mmap{T<:Array}(::Type{T}, i::Integer...; shared::Bool=true) = mmap(Anonymous(), T, convert(Tuple{Vararg{Int}},i), Int64(0); shared=shared) +mmap(::Type{T}, dims::NTuple{N,Integer}; shared::Bool=true) where {T<:Array,N} = mmap(Anonymous(), T, dims, Int64(0); shared=shared) +mmap(::Type{T}, i::Integer...; shared::Bool=true) where {T<:Array} = mmap(Anonymous(), T, convert(Tuple{Vararg{Int}},i), Int64(0); shared=shared) -function mmap{N}(io::IOStream, ::Type{<:BitArray}, dims::NTuple{N,Integer}, - offset::Int64=position(io); grow::Bool=true, shared::Bool=true) +function mmap(io::IOStream, ::Type{<:BitArray}, dims::NTuple{N,Integer}, + offset::Int64=position(io); grow::Bool=true, shared::Bool=true) where N n = prod(dims) nc = Base.num_bit_chunks(n) chunks = mmap(io, Vector{UInt64}, (nc,), offset; grow=grow, shared=shared) @@ -186,25 +186,25 @@ function mmap{N}(io::IOStream, ::Type{<:BitArray}, dims::NTuple{N,Integer}, return B end -mmap{T<:BitArray,N}(file::AbstractString, ::Type{T}, dims::NTuple{N,Integer}, offset::Integer=Int64(0); grow::Bool=true, shared::Bool=true) = +mmap(file::AbstractString, ::Type{T}, dims::NTuple{N,Integer}, offset::Integer=Int64(0);grow::Bool=true, shared::Bool=true) where {T<:BitArray,N} = open(io->mmap(io, T, dims, offset; grow=grow, shared=shared), file, isfile(file) ? "r+" : "w+")::BitArray{N} # using a length argument instead of dims -mmap{T<:BitArray}(io::IO, ::Type{T}, len::Integer, offset::Integer=position(io); grow::Bool=true, shared::Bool=true) = +mmap(io::IO, ::Type{T}, len::Integer, offset::Integer=position(io); grow::Bool=true, shared::Bool=true) where {T<:BitArray} = mmap(io, T, (len,), offset; grow=grow, shared=shared) -mmap{T<:BitArray}(file::AbstractString, ::Type{T}, len::Integer, offset::Integer=Int64(0); grow::Bool=true, shared::Bool=true) = +mmap(file::AbstractString, ::Type{T}, len::Integer, offset::Integer=Int64(0); grow::Bool=true, shared::Bool=true) where {T<:BitArray} = open(io->mmap(io, T, (len,), offset; grow=grow, shared=shared), file, isfile(file) ? "r+" : "w+")::BitVector # constructors for non-file-backed (anonymous) mmaps -mmap{T<:BitArray,N}(::Type{T}, dims::NTuple{N,Integer}; shared::Bool=true) = mmap(Anonymous(), T, dims, Int64(0); shared=shared) -mmap{T<:BitArray}(::Type{T}, i::Integer...; shared::Bool=true) = mmap(Anonymous(), T, convert(Tuple{Vararg{Int}},i), Int64(0); shared=shared) +mmap(::Type{T}, dims::NTuple{N,Integer}; shared::Bool=true) where {T<:BitArray,N} = mmap(Anonymous(), T, dims, Int64(0); shared=shared) +mmap(::Type{T}, i::Integer...; shared::Bool=true) where {T<:BitArray} = mmap(Anonymous(), T, convert(Tuple{Vararg{Int}},i), Int64(0); shared=shared) # msync flags for unix const MS_ASYNC = 1 const MS_INVALIDATE = 2 const MS_SYNC = 4 -function sync!{T}(m::Array{T}, flags::Integer=MS_SYNC) +function sync!(m::Array{T}, flags::Integer=MS_SYNC) where T offset = rem(UInt(pointer(m)), PAGESIZE) ptr = pointer(m) - offset @static if is_unix() diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 3dfa450ec7e1f..f29b49fe31efd 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -52,8 +52,8 @@ module IteratorsMD CartesianIndex(index::Tuple{Vararg{Union{Integer, CartesianIndex}}}) = CartesianIndex(index...) # length - length{N}(::CartesianIndex{N})=N - length{N}(::Type{CartesianIndex{N}})=N + length(::CartesianIndex{N}) where {N} = N + length(::Type{CartesianIndex{N}}) where {N} = N # indexing getindex(index::CartesianIndex, i::Integer) = index.I[i] @@ -182,7 +182,7 @@ module IteratorsMD last(iter::CartesianRange) = iter.stop - @inline function in{I<:CartesianIndex}(i::I, r::CartesianRange{I}) + @inline function in(i::I, r::CartesianRange{I}) where I<:CartesianIndex _in(true, i.I, r.start.I, r.stop.I) end _in(b, ::Tuple{}, ::Tuple{}, ::Tuple{}) = b @@ -207,9 +207,9 @@ module IteratorsMD @inline split(t, V::Type{<:Val}) = _split((), t, V) @inline _split(tN, trest, V) = _split((tN..., trest[1]), tail(trest), V) # exit either when we've exhausted the input tuple or when tN has length N - @inline _split{N}(tN::NTuple{N,Any}, ::Tuple{}, ::Type{Val{N}}) = tN, () # ambig. - @inline _split{N}(tN, ::Tuple{}, ::Type{Val{N}}) = tN, () - @inline _split{N}(tN::NTuple{N,Any}, trest, ::Type{Val{N}}) = tN, trest + @inline _split(tN::NTuple{N,Any}, ::Tuple{}, ::Type{Val{N}}) where {N} = tN, () # ambig. + @inline _split(tN, ::Tuple{}, ::Type{Val{N}}) where {N} = tN, () + @inline _split(tN::NTuple{N,Any}, trest, ::Type{Val{N}}) where {N} = tN, trest @inline function split(I::CartesianIndex, V::Type{<:Val}) i, j = split(I.I, V) @@ -250,20 +250,20 @@ end # Support indexing with an array of CartesianIndex{N}s # Here we try to consume N of the indices (if there are that many available) # The first two simply handle ambiguities -@inline function checkbounds_indices{N}(::Type{Bool}, ::Tuple{}, - I::Tuple{AbstractArray{CartesianIndex{N}},Vararg{Any}}) +@inline function checkbounds_indices(::Type{Bool}, ::Tuple{}, + I::Tuple{AbstractArray{CartesianIndex{N}},Vararg{Any}}) where N checkindex(Bool, (), I[1]) & checkbounds_indices(Bool, (), tail(I)) end @inline function checkbounds_indices(::Type{Bool}, IA::Tuple{Any}, I::Tuple{AbstractArray{CartesianIndex{0}},Vararg{Any}}) checkbounds_indices(Bool, IA, tail(I)) end -@inline function checkbounds_indices{N}(::Type{Bool}, IA::Tuple{Any}, - I::Tuple{AbstractArray{CartesianIndex{N}},Vararg{Any}}) +@inline function checkbounds_indices(::Type{Bool}, IA::Tuple{Any}, + I::Tuple{AbstractArray{CartesianIndex{N}},Vararg{Any}}) where N checkindex(Bool, IA, I[1]) & checkbounds_indices(Bool, (), tail(I)) end -@inline function checkbounds_indices{N}(::Type{Bool}, IA::Tuple, - I::Tuple{AbstractArray{CartesianIndex{N}},Vararg{Any}}) +@inline function checkbounds_indices(::Type{Bool}, IA::Tuple, + I::Tuple{AbstractArray{CartesianIndex{N}},Vararg{Any}}) where N IA1, IArest = IteratorsMD.split(IA, Val{N}) checkindex(Bool, IA1, I[1]) & checkbounds_indices(Bool, IArest, tail(I)) end @@ -370,11 +370,11 @@ end @inline done(L::LogicalIndex{Int,<:BitArray}, s) = s[2] > length(L) # Checking bounds with LogicalIndex{Int} is tricky since we allow linear indexing over trailing dimensions -@inline checkbounds_indices{N}(::Type{Bool},IA::Tuple{},I::Tuple{LogicalIndex{Int,AbstractArray{Bool,N}}}) = +@inline checkbounds_indices(::Type{Bool},IA::Tuple{},I::Tuple{LogicalIndex{Int,AbstractArray{Bool,N}}}) where {N} = checkindex(Bool, IA, I[1]) -@inline checkbounds_indices{N}(::Type{Bool},IA::Tuple{Any},I::Tuple{LogicalIndex{Int,AbstractArray{Bool,N}}}) = +@inline checkbounds_indices(::Type{Bool},IA::Tuple{Any},I::Tuple{LogicalIndex{Int,AbstractArray{Bool,N}}}) where {N} = checkindex(Bool, IA[1], I[1]) -@inline function checkbounds_indices{N}(::Type{Bool}, IA::Tuple, I::Tuple{LogicalIndex{Int,AbstractArray{Bool,N}}}) +@inline function checkbounds_indices(::Type{Bool}, IA::Tuple, I::Tuple{LogicalIndex{Int,AbstractArray{Bool,N}}}) where N IA1, IArest = IteratorsMD.split(IA, Val{N}) checkindex(Bool, IA1, I[1]) end @@ -397,17 +397,17 @@ to_indices(A, I::Tuple{}) = () @inline to_indices(A, inds, I::Tuple{CartesianIndex, Vararg{Any}}) = to_indices(A, inds, (I[1].I..., tail(I)...)) # But for arrays of CartesianIndex, we just skip the appropriate number of inds -@inline function to_indices{N}(A, inds, I::Tuple{AbstractArray{CartesianIndex{N}}, Vararg{Any}}) +@inline function to_indices(A, inds, I::Tuple{AbstractArray{CartesianIndex{N}}, Vararg{Any}}) where N _, indstail = IteratorsMD.split(inds, Val{N}) (to_index(A, I[1]), to_indices(A, indstail, tail(I))...) end # And boolean arrays behave similarly; they also skip their number of dimensions -@inline function to_indices{N}(A, inds, I::Tuple{AbstractArray{Bool, N}, Vararg{Any}}) +@inline function to_indices(A, inds, I::Tuple{AbstractArray{Bool, N}, Vararg{Any}}) where N _, indstail = IteratorsMD.split(inds, Val{N}) (to_index(A, I[1]), to_indices(A, indstail, tail(I))...) end # As an optimization, we allow trailing Array{Bool} and BitArray to be linear over trailing dimensions -@inline to_indices{N}(A, inds, I::Tuple{Union{Array{Bool,N}, BitArray{N}}}) = +@inline to_indices(A, inds, I::Tuple{Union{Array{Bool,N}, BitArray{N}}}) where {N} = (_maybe_linear_logical_index(IndexStyle(A), A, I[1]),) _maybe_linear_logical_index(::IndexStyle, A, i) = to_index(A, i) _maybe_linear_logical_index(::IndexLinear, A, i) = LogicalIndex{Int}(i) @@ -510,7 +510,7 @@ end ## -@generated function findn{T,N}(A::AbstractArray{T,N}) +@generated function findn(A::AbstractArray{T,N}) where {T,N} quote nnzA = countnz(A) @nexprs $N d->(I_d = Vector{Int}(nnzA)) @@ -540,7 +540,7 @@ rcum_promote_type(op, ::Type{Array{T,N}}) where {T,N} = Array{rcum_promote_type( # stable in certain situations (e.g. sums). # it does double the number of operations compared to accumulate, # though for cheap operations like + this does not have much impact (20%) -function _accumulate_pairwise!{T, Op}(op::Op, c::AbstractVector{T}, v::AbstractVector, s, i1, n)::T +function _accumulate_pairwise!(op::Op, c::AbstractVector{T}, v::AbstractVector, s, i1, n)::T where {T,Op} @inbounds if n < 128 s_ = v[i1] c[i1] = op(s, s_) @@ -556,7 +556,7 @@ function _accumulate_pairwise!{T, Op}(op::Op, c::AbstractVector{T}, v::AbstractV return s_ end -function accumulate_pairwise!{Op}(op::Op, result::AbstractVector, v::AbstractVector) +function accumulate_pairwise!(op::Op, result::AbstractVector, v::AbstractVector) where Op li = linearindices(v) li != linearindices(result) && throw(DimensionMismatch("input and output array sizes and indices must match")) n = length(li) @@ -568,7 +568,7 @@ function accumulate_pairwise!{Op}(op::Op, result::AbstractVector, v::AbstractVec return result end -function accumulate_pairwise{T}(op, v::AbstractVector{T}) +function accumulate_pairwise(op, v::AbstractVector{T}) where T out = similar(v, rcum_promote_type(op, T)) return accumulate_pairwise!(op, out, v) end @@ -607,7 +607,7 @@ julia> cumsum(a,2) 4 9 15 ``` """ -function cumsum{T}(A::AbstractArray{T}, axis::Integer=1) +function cumsum(A::AbstractArray{T}, axis::Integer=1) where T out = similar(A, rcum_promote_type(+, T)) cumsum!(out, A, axis) end @@ -709,7 +709,7 @@ function accumulate(op, v0, A, axis::Integer=1) accumulate!(op, out, v0, A, 1) end -function accumulate!{Op}(op::Op, B, A::AbstractVector, axis::Integer=1) +function accumulate!(op::Op, B, A::AbstractVector, axis::Integer=1) where Op isempty(A) && return B v1 = first(A) _accumulate1!(op, B, v1, A, axis) @@ -852,7 +852,7 @@ alias each other). See also `circshift`. """ -@noinline function circshift!{T,N}(dest::AbstractArray{T,N}, src, shiftamt::DimsInteger) +@noinline function circshift!(dest::AbstractArray{T,N}, src, shiftamt::DimsInteger) where {T,N} dest === src && throw(ArgumentError("dest and src must be separate arrays")) inds = indices(src) indices(dest) == inds || throw(ArgumentError("indices of src and dest must match (got $inds and $(indices(dest)))")) @@ -1336,7 +1336,7 @@ julia> unique(A, 3) false false ``` """ -@generated function unique{T,N}(A::AbstractArray{T,N}, dim::Int) +@generated function unique(A::AbstractArray{T,N}, dim::Int) where {T,N} inds = inds -> zeros(UInt, inds) quote 1 <= dim <= $N || return copy(A) @@ -1440,7 +1440,7 @@ function extrema(A::AbstractArray, dims) return extrema!(B, A) end -@generated function extrema!{T,N}(B, A::AbstractArray{T,N}) +@generated function extrema!(B, A::AbstractArray{T,N}) where {T,N} return quote sA = size(A) sB = size(B) diff --git a/base/multimedia.jl b/base/multimedia.jl index 30b16ec1ba801..db765279a44f6 100644 --- a/base/multimedia.jl +++ b/base/multimedia.jl @@ -19,7 +19,7 @@ import Base: MIME, @MIME_str import Base: show, print, string, convert MIME(s) = MIME{Symbol(s)}() show(io::IO, ::MIME{mime}) where {mime} = print(io, "MIME type ", string(mime)) -print{mime}(io::IO, ::MIME{mime}) = print(io, mime) +print(io::IO, ::MIME{mime}) where {mime} = print(io, mime) ########################################################################### # For any type T one can define show(io, ::MIME"type", x::T) = ... @@ -32,8 +32,8 @@ Returns a boolean value indicating whether or not the object `x` can be written `mime` type. (By default, this is determined automatically by the existence of the corresponding [`show`](@ref) method for `typeof(x)`.) """ -mimewritable{mime}(::MIME{mime}, x) = - method_exists(show, Tuple{IO, MIME{mime}, typeof(x)}) +mimewritable(::MIME{mime}, x) where {mime} = + method_exists(show, Tuple{IO, MIME{mime}, typeof(x)}) # it is convenient to accept strings instead of ::MIME show(io::IO, m::AbstractString, x) = show(io, MIME(m), x) @@ -215,8 +215,8 @@ function display(m::MIME, x) throw(MethodError(display, (m, x))) end -displayable{D<:Display,mime}(d::D, ::MIME{mime}) = - method_exists(display, Tuple{D, MIME{mime}, Any}) +displayable(d::D, ::MIME{mime}) where {D<:Display,mime} = + method_exists(display, Tuple{D,MIME{mime},Any}) function displayable(m::MIME) for d in displays diff --git a/base/nullable.jl b/base/nullable.jl index 2a631d5512cee..9762cfdaa57d6 100644 --- a/base/nullable.jl +++ b/base/nullable.jl @@ -54,8 +54,8 @@ convert(::Type{Nullable }, ::Void) = Nullable{Union{}}() promote_rule(::Type{Nullable{S}}, ::Type{T}) where {S,T} = Nullable{promote_type(S, T)} promote_rule(::Type{Nullable{S}}, ::Type{Nullable{T}}) where {S,T} = Nullable{promote_type(S, T)} -promote_op{S,T}(op::Any, ::Type{Nullable{S}}, ::Type{Nullable{T}}) = Nullable{promote_op(op, S, T)} -promote_op{S,T}(op::Type, ::Type{Nullable{S}}, ::Type{Nullable{T}}) = Nullable{promote_op(op, S, T)} +promote_op(op::Any, ::Type{Nullable{S}}, ::Type{Nullable{T}}) where {S,T} = Nullable{promote_op(op, S, T)} +promote_op(op::Type, ::Type{Nullable{S}}, ::Type{Nullable{T}}) where {S,T} = Nullable{promote_op(op, S, T)} function show(io::IO, x::Nullable) if get(io, :compact, false) @@ -81,7 +81,7 @@ end Attempt to access the value of `x`. Returns the value if it is present; otherwise, returns `y` if provided, or throws a `NullException` if not. """ -@inline function get{T}(x::Nullable{T}, y) +@inline function get(x::Nullable{T}, y) where T if isbits(T) ifelse(isnull(x), y, x.value) else @@ -186,13 +186,13 @@ const NullSafeFloats = Union{Type{Float16}, Type{Float32}, Type{Float64}} const NullSafeTypes = Union{NullSafeInts, NullSafeFloats} const EqualOrLess = Union{typeof(isequal), typeof(isless)} -null_safe_op{T}(::typeof(identity), ::Type{T}) = isbits(T) +null_safe_op(::typeof(identity), ::Type{T}) where {T} = isbits(T) null_safe_op(f::EqualOrLess, ::NullSafeTypes, ::NullSafeTypes) = true -null_safe_op{S,T}(f::EqualOrLess, ::Type{Rational{S}}, ::Type{T}) = +null_safe_op(f::EqualOrLess, ::Type{Rational{S}}, ::Type{T}) where {S,T} = null_safe_op(f, T, S) # complex numbers can be compared for equality but not in general ordered -null_safe_op{S,T}(::typeof(isequal), ::Type{Complex{S}}, ::Type{T}) = +null_safe_op(::typeof(isequal), ::Type{Complex{S}}, ::Type{T}) where {S,T} = null_safe_op(isequal, T, S) """ @@ -202,7 +202,7 @@ If neither `x` nor `y` is null, compare them according to their values (i.e. `isequal(get(x), get(y))`). Else, return `true` if both arguments are null, and `false` if one is null but not the other: nulls are considered equal. """ -@inline function isequal{S,T}(x::Nullable{S}, y::Nullable{T}) +@inline function isequal(x::Nullable{S}, y::Nullable{T}) where {S,T} if null_safe_op(isequal, S, T) (isnull(x) & isnull(y)) | (!isnull(x) & !isnull(y) & isequal(x.value, y.value)) else @@ -222,7 +222,7 @@ If neither `x` nor `y` is null, compare them according to their values otherwise: nulls are always considered greater than non-nulls, but not greater than another null. """ -@inline function isless{S,T}(x::Nullable{S}, y::Nullable{T}) +@inline function isless(x::Nullable{S}, y::Nullable{T}) where {S,T} # NULL values are sorted last if null_safe_op(isless, S, T) (!isnull(x) & isnull(y)) | (!isnull(x) & !isnull(y) & isless(x.value, y.value)) @@ -253,7 +253,7 @@ end Return null if either `x` is null or `p(get(x))` is false, and `x` otherwise. """ -function filter{T}(p, x::Nullable{T}) +function filter(p, x::Nullable{T}) where T if isbits(T) val = unsafe_get(x) Nullable{T}(val, !isnull(x) && p(val)) @@ -265,7 +265,7 @@ end """ Return the given type if it is concrete, and `Union{}` otherwise. """ -nullable_returntype{T}(::Type{T}) = isleaftype(T) ? T : Union{} +nullable_returntype(::Type{T}) where {T} = isleaftype(T) ? T : Union{} """ map(f, x::Nullable) @@ -303,8 +303,8 @@ all(f::typeof(hasvalue), t::Tuple{}) = true # Note this list does not include sqrt since it can raise a DomainError for op in (+, -, abs, abs2) null_safe_op(::typeof(op), ::NullSafeTypes) = true - null_safe_op{S}(::typeof(op), ::Type{Complex{S}}) = null_safe_op(op, S) - null_safe_op{S}(::typeof(op), ::Type{Rational{S}}) = null_safe_op(op, S) + null_safe_op(::typeof(op), ::Type{Complex{S}}) where {S} = null_safe_op(op, S) + null_safe_op(::typeof(op), ::Type{Rational{S}}) where {S} = null_safe_op(op, S) end null_safe_op(::typeof(~), ::NullSafeInts) = true @@ -323,8 +323,8 @@ for op in (+, -, *, /, &, |, <<, >>, >>>, null_safe_op(::typeof(op), ::NullSafeUnsignedInts, ::NullSafeUnsignedInts) = true end for op in (+, -, *, /) - null_safe_op{S,T}(::typeof(op), ::Type{Complex{S}}, ::Type{T}) = + null_safe_op(::typeof(op), ::Type{Complex{S}}, ::Type{T}) where {S,T} = null_safe_op(op, T, S) - null_safe_op{S,T}(::typeof(op), ::Type{Rational{S}}, ::Type{T}) = + null_safe_op(::typeof(op), ::Type{Rational{S}}, ::Type{T}) where {S,T} = null_safe_op(op, T, S) end diff --git a/base/operators.jl b/base/operators.jl index c569272b21a2b..fc712541e303d 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -664,9 +664,9 @@ julia> x == (fld1(x, y) - 1) * y + mod1(x, y) true ``` """ -fld1{T<:Real}(x::T, y::T) = (m=mod(x,y); fld(x-m,y)) +fld1(x::T, y::T) where {T<:Real} = (m=mod(x,y); fld(x-m,y)) # efficient version for integers -fld1{T<:Integer}(x::T, y::T) = fld(x+y-T(1),y) +fld1(x::T, y::T) where {T<:Integer} = fld(x+y-T(1),y) """ fldmod1(x, y) @@ -675,9 +675,9 @@ Return `(fld1(x,y), mod1(x,y))`. See also: [`fld1`](@ref), [`mod1`](@ref). """ -fldmod1{T<:Real}(x::T, y::T) = (fld1(x,y), mod1(x,y)) +fldmod1(x::T, y::T) where {T<:Real} = (fld1(x,y), mod1(x,y)) # efficient version for integers -fldmod1{T<:Integer}(x::T, y::T) = (fld1(x,y), mod1(x,y)) +fldmod1(x::T, y::T) where {T<:Integer} = (fld1(x,y), mod1(x,y)) # transpose diff --git a/base/parse.jl b/base/parse.jl index 2cc5f6be8e5d6..27c00e36dcd07 100644 --- a/base/parse.jl +++ b/base/parse.jl @@ -4,7 +4,7 @@ import Base.Checked: add_with_overflow, mul_with_overflow ## string to integer functions ## -function parse{T<:Integer}(::Type{T}, c::Char, base::Integer=36) +function parse(::Type{T}, c::Char, base::Integer=36) where T<:Integer a::Int = (base <= 36 ? 10 : 36) 2 <= base <= 62 || throw(ArgumentError("invalid base: base must be 2 ≤ base ≤ 62, got $base")) d = '0' <= c <= '9' ? c-'0' : @@ -56,7 +56,7 @@ function parseint_preamble(signed::Bool, base::Int, s::AbstractString, startpos: return sgn, base, j end -function tryparse_internal{T<:Integer}(::Type{T}, s::AbstractString, startpos::Int, endpos::Int, base_::Integer, raise::Bool) +function tryparse_internal(::Type{T}, s::AbstractString, startpos::Int, endpos::Int, base_::Integer, raise::Bool) where T<:Integer _n = Nullable{T}() sgn, base, i = parseint_preamble(T<:Signed, Int(base_), s, startpos, endpos) if sgn == 0 && base == 0 && i == 0 @@ -171,16 +171,16 @@ end throw(ArgumentError("invalid base: base must be 2 ≤ base ≤ 62, got $base")) end -tryparse{T<:Integer}(::Type{T}, s::AbstractString, base::Integer) = +tryparse(::Type{T}, s::AbstractString, base::Integer) where {T<:Integer} = tryparse_internal(T, s, start(s), endof(s), check_valid_base(base), false) -tryparse{T<:Integer}(::Type{T}, s::AbstractString) = +tryparse(::Type{T}, s::AbstractString) where {T<:Integer} = tryparse_internal(T, s, start(s), endof(s), 0, false) -function parse{T<:Integer}(::Type{T}, s::AbstractString, base::Integer) +function parse(::Type{T}, s::AbstractString, base::Integer) where T<:Integer get(tryparse_internal(T, s, start(s), endof(s), check_valid_base(base), true)) end -function parse{T<:Integer}(::Type{T}, s::AbstractString) +function parse(::Type{T}, s::AbstractString) where T<:Integer get(tryparse_internal(T, s, start(s), endof(s), 0, true)) # Zero means, "figure it out" end @@ -193,9 +193,9 @@ tryparse(::Type{Float64}, s::SubString{String}) = ccall(:jl_try_substrtod, Nulla tryparse(::Type{Float32}, s::String) = ccall(:jl_try_substrtof, Nullable{Float32}, (Ptr{UInt8},Csize_t,Csize_t), s, 0, sizeof(s)) tryparse(::Type{Float32}, s::SubString{String}) = ccall(:jl_try_substrtof, Nullable{Float32}, (Ptr{UInt8},Csize_t,Csize_t), s.string, s.offset, s.endof) -tryparse{T<:Union{Float32,Float64}}(::Type{T}, s::AbstractString) = tryparse(T, String(s)) +tryparse(::Type{T}, s::AbstractString) where {T<:Union{Float32,Float64}} = tryparse(T, String(s)) -function parse{T<:AbstractFloat}(::Type{T}, s::AbstractString) +function parse(::Type{T}, s::AbstractString) where T<:AbstractFloat result = tryparse(T, s) if isnull(result) throw(ArgumentError("cannot parse $(repr(s)) as $T")) diff --git a/base/permuteddimsarray.jl b/base/permuteddimsarray.jl index a21f869456d9e..c51b8cb34caff 100644 --- a/base/permuteddimsarray.jl +++ b/base/permuteddimsarray.jl @@ -49,7 +49,7 @@ Base.parent(A::PermutedDimsArray) = A.parent Base.size(A::PermutedDimsArray{T,N,perm}) where {T,N,perm} = genperm(size(parent(A)), perm) Base.indices(A::PermutedDimsArray{T,N,perm}) where {T,N,perm} = genperm(indices(parent(A)), perm) -Base.unsafe_convert{T}(::Type{Ptr{T}}, A::PermutedDimsArray{T}) = Base.unsafe_convert(Ptr{T}, parent(A)) +Base.unsafe_convert(::Type{Ptr{T}}, A::PermutedDimsArray{T}) where {T} = Base.unsafe_convert(Ptr{T}, parent(A)) # It's OK to return a pointer to the first element, and indeed quite # useful for wrapping C routines that require a different storage @@ -58,24 +58,24 @@ Base.unsafe_convert{T}(::Type{Ptr{T}}, A::PermutedDimsArray{T}) = Base.unsafe_co # or a linear index? Base.pointer(A::PermutedDimsArray, i::Integer) = throw(ArgumentError("pointer(A, i) is deliberately unsupported for PermutedDimsArray")) -function Base.strides{T,N,perm}(A::PermutedDimsArray{T,N,perm}) +function Base.strides(A::PermutedDimsArray{T,N,perm}) where {T,N,perm} s = strides(parent(A)) ntuple(d->s[perm[d]], Val{N}) end -@inline function Base.getindex{T,N,perm,iperm}(A::PermutedDimsArray{T,N,perm,iperm}, I::Vararg{Int,N}) +@inline function Base.getindex(A::PermutedDimsArray{T,N,perm,iperm}, I::Vararg{Int,N}) where {T,N,perm,iperm} @boundscheck checkbounds(A, I...) @inbounds val = getindex(A.parent, genperm(I, iperm)...) val end -@inline function Base.setindex!{T,N,perm,iperm}(A::PermutedDimsArray{T,N,perm,iperm}, val, I::Vararg{Int,N}) +@inline function Base.setindex!(A::PermutedDimsArray{T,N,perm,iperm}, val, I::Vararg{Int,N}) where {T,N,perm,iperm} @boundscheck checkbounds(A, I...) @inbounds setindex!(A.parent, val, genperm(I, iperm)...) val end # For some reason this is faster than ntuple(d->I[perm[d]], Val{N}) (#15276?) -@inline genperm{N}(I::NTuple{N,Any}, perm::Dims{N}) = _genperm((), I, perm...) +@inline genperm(I::NTuple{N,Any}, perm::Dims{N}) where {N} = _genperm((), I, perm...) _genperm(out, I) = out @inline _genperm(out, I, p, perm...) = _genperm((out..., I[p]), I, perm...) @inline genperm(I, perm::AbstractVector{Int}) = genperm(I, (perm...,)) diff --git a/base/pkg/query.jl b/base/pkg/query.jl index 5f8eee36d6721..dbe1919f0664d 100644 --- a/base/pkg/query.jl +++ b/base/pkg/query.jl @@ -180,8 +180,8 @@ end const PackageState = Union{Void,VersionNumber} function diff(have::Dict, want::Dict, avail::Dict, fixed::Dict) - change = Array{Tuple{String,Tuple{PackageState,PackageState}}}(0) - remove = Array{Tuple{String,Tuple{PackageState,PackageState}}}(0) + change = Vector{Tuple{String,Tuple{PackageState,PackageState}}}(0) + remove = Vector{Tuple{String,Tuple{PackageState,PackageState}}}(0) for pkg in collect(union(keys(have),keys(want))) h, w = haskey(have,pkg), haskey(want,pkg) diff --git a/base/pointer.jl b/base/pointer.jl index 2b27fae3753ca..9ef25ebcd0936 100644 --- a/base/pointer.jl +++ b/base/pointer.jl @@ -57,17 +57,17 @@ calling `free` on the pointer when the array is no longer referenced. This function is labelled "unsafe" because it will crash if `pointer` is not a valid memory address to data of the requested length. """ -function unsafe_wrap{T,N}(::Union{Type{Array},Type{Array{T}},Type{Array{T,N}}}, - p::Ptr{T}, dims::NTuple{N,Int}, own::Bool=false) +function unsafe_wrap(::Union{Type{Array},Type{Array{T}},Type{Array{T,N}}}, + p::Ptr{T}, dims::NTuple{N,Int}, own::Bool=false) where {T,N} ccall(:jl_ptr_to_array, Array{T,N}, (Any, Ptr{Void}, Any, Int32), Array{T,N}, p, dims, own) end -function unsafe_wrap{T}(::Union{Type{Array},Type{Array{T}},Type{Array{T,1}}}, - p::Ptr{T}, d::Integer, own::Bool=false) +function unsafe_wrap(::Union{Type{Array},Type{Array{T}},Type{Array{T,1}}}, + p::Ptr{T}, d::Integer, own::Bool=false) where {T} ccall(:jl_ptr_to_array_1d, Array{T,1}, (Any, Ptr{Void}, Csize_t, Cint), Array{T,1}, p, d, own) end -unsafe_wrap{N}(Atype::Type, p::Ptr, dims::NTuple{N,<:Integer}, own::Bool=false) = +unsafe_wrap(Atype::Type, p::Ptr, dims::NTuple{N,<:Integer}, own::Bool=false) where {N} = unsafe_wrap(Atype, p, convert(Tuple{Vararg{Int}}, dims), own) """ @@ -93,7 +93,7 @@ pointer `p` to ensure that it is valid. Incorrect usage may corrupt or segfault program, in the same manner as C. """ unsafe_store!(p::Ptr{Any}, x::ANY, i::Integer=1) = pointerset(p, x, Int(i), 1) -unsafe_store!{T}(p::Ptr{T}, x, i::Integer=1) = pointerset(p, convert(T,x), Int(i), 1) +unsafe_store!(p::Ptr{T}, x, i::Integer=1) where {T} = pointerset(p, convert(T,x), Int(i), 1) # convert a raw Ptr to an object reference, and vice-versa """ diff --git a/base/range.jl b/base/range.jl index 06e746ba5eeda..3736f721bf597 100644 --- a/base/range.jl +++ b/base/range.jl @@ -233,10 +233,10 @@ julia> linspace(1.3,2.9,9) linspace(start, stop, len::Real=50) = linspace(promote_noncircular(start, stop)..., Int(len)) linspace(start::Real, stop::Real, len::Integer) = linspace(promote(start, stop)..., len) -linspace{T<:Integer}(start::T, stop::T, len::Integer) = linspace(Float64, start, stop, len, 1) +linspace(start::T, stop::T, len::Integer) where {T<:Integer} = linspace(Float64, start, stop, len, 1) # for Float16, Float32, and Float64 see twiceprecision.jl -linspace{T<:Real}(start::T, stop::T, len::Integer) = LinSpace{T}(start, stop, len) -linspace{T}(start::T, stop::T, len::Integer) = LinSpace{T}(start, stop, len) +linspace(start::T, stop::T, len::Integer) where {T<:Real} = LinSpace{T}(start, stop, len) +linspace(start::T, stop::T, len::Integer) where {T} = LinSpace{T}(start, stop, len) function show(io::IO, r::LinSpace) print(io, "linspace(") diff --git a/base/serialize.jl b/base/serialize.jl index 1e7277dd9ca63..749bcb893abd0 100644 --- a/base/serialize.jl +++ b/base/serialize.jl @@ -232,12 +232,12 @@ function serialize(s::AbstractSerializer, a::Array) end end -function serialize{T,N,A<:Array}(s::AbstractSerializer, a::SubArray{T,N,A}) +function serialize(s::AbstractSerializer, a::SubArray{T,N,A}) where {T,N,A<:Array} b = trimmedsubarray(a) serialize_any(s, b) end -function trimmedsubarray{T,N,A<:Array}(V::SubArray{T,N,A}) +function trimmedsubarray(V::SubArray{T,N,A}) where {T,N,A<:Array} dest = Array{eltype(V)}(trimmedsize(V)) copy!(dest, V) _trimmedsubarray(dest, V, (), V.indexes...) @@ -245,7 +245,7 @@ end trimmedsize(V) = index_lengths(V.indexes...) -function _trimmedsubarray{T,N,P,I,LD}(A, V::SubArray{T,N,P,I,LD}, newindexes) +function _trimmedsubarray(A, V::SubArray{T,N,P,I,LD}, newindexes) where {T,N,P,I,LD} LD && return SubArray{T,N,P,I,LD}(A, newindexes, Base.compute_offset1(A, 1, newindexes), 1) SubArray{T,N,P,I,LD}(A, newindexes, 0, 0) end @@ -262,7 +262,7 @@ function serialize(s::AbstractSerializer, ss::String) write(s.io, ss) end -function serialize{T<:AbstractString}(s::AbstractSerializer, ss::SubString{T}) +function serialize(s::AbstractSerializer, ss::SubString{T}) where T<:AbstractString # avoid saving a copy of the parent string, keeping the type of ss serialize_any(s, convert(SubString{T}, convert(T,ss))) end @@ -768,7 +768,7 @@ function deserialize_expr(s::AbstractSerializer, len) e = Expr(hd) deserialize_cycle(s, e) ty = deserialize(s) - e.args = Any[ deserialize(s) for i=1:len ] + e.args = Any[ deserialize(s) for i = 1:len ] e.typ = ty e end @@ -967,7 +967,7 @@ function deserialize(s::AbstractSerializer, t::DataType) end end -function deserialize{K,V}(s::AbstractSerializer, T::Type{Dict{K,V}}) +function deserialize(s::AbstractSerializer, T::Type{Dict{K,V}}) where {K,V} n = read(s.io, Int32) t = T(); sizehint!(t, n) deserialize_cycle(s, t) diff --git a/base/shell.jl b/base/shell.jl index b103a22472781..a191a1725b826 100644 --- a/base/shell.jl +++ b/base/shell.jl @@ -8,11 +8,8 @@ const shell_special = "#{}()[]<>|&*?~;" @noinline warn_shell_special(special) = depwarn("special characters \"$special\" should now be quoted in commands", :warn_shell_special) -function shell_parse( - str::AbstractString, - interpolate::Bool=true; - special::AbstractString="" - ) +function shell_parse(str::AbstractString, interpolate::Bool=true; + special::AbstractString="") s = lstrip(str) # strips the end but respects the space when the string ends with "\\ " r = RevString(s) @@ -164,10 +161,8 @@ function print_shell_word(io::IO, word::AbstractString, special::AbstractString end end -function print_shell_escaped( - io::IO, cmd::AbstractString, args::AbstractString...; - special::AbstractString="" - ) +function print_shell_escaped(io::IO, cmd::AbstractString, args::AbstractString...; + special::AbstractString="") print_shell_word(io, cmd, special) for arg in args print(io, ' ') diff --git a/base/sparse/linalg.jl b/base/sparse/linalg.jl index 7a3aab3044eb0..4689ff521e5c9 100644 --- a/base/sparse/linalg.jl +++ b/base/sparse/linalg.jl @@ -5,14 +5,14 @@ import Base.LinAlg: checksquare ## Functions to switch to 0-based indexing to call external sparse solvers # Convert from 1-based to 0-based indices -function decrement!{T<:Integer}(A::AbstractArray{T}) +function decrement!(A::AbstractArray{T}) where T<:Integer for i in 1:length(A); A[i] -= oneunit(T) end A end decrement(A::AbstractArray{<:Integer}) = decrement!(copy(A)) # Convert from 0-based to 1-based indices -function increment!{T<:Integer}(A::AbstractArray{T}) +function increment!(A::AbstractArray{T}) where T<:Integer for i in 1:length(A); A[i] += oneunit(T) end A end @@ -27,13 +27,13 @@ for f in (:A_mul_Bt, :A_mul_Bc, :At_mul_B, :Ac_mul_B, :At_mul_Bt, :Ac_mul_Bc) @eval begin - function ($f){TvA,TiA,TvB,TiB}(A::SparseMatrixCSC{TvA,TiA}, B::SparseMatrixCSC{TvB,TiB}) + function ($f)(A::SparseMatrixCSC{TvA,TiA}, B::SparseMatrixCSC{TvB,TiB}) where {TvA,TiA,TvB,TiB} ($f)(sppromote(A, B)...) end end end -function sppromote{TvA,TiA,TvB,TiB}(A::SparseMatrixCSC{TvA,TiA}, B::SparseMatrixCSC{TvB,TiB}) +function sppromote(A::SparseMatrixCSC{TvA,TiA}, B::SparseMatrixCSC{TvB,TiB}) where {TvA,TiA,TvB,TiB} Tv = promote_type(TvA, TvB) Ti = promote_type(TiA, TiB) A = convert(SparseMatrixCSC{Tv,Ti}, A) @@ -80,11 +80,11 @@ for (f, op, transp) in ((:A_mul_B, :identity, false), C end - function $(f){TA,S,Tx}(A::SparseMatrixCSC{TA,S}, x::StridedVector{Tx}) + function $(f)(A::SparseMatrixCSC{TA,S}, x::StridedVector{Tx}) where {TA,S,Tx} T = promote_type(TA, Tx) $(Symbol(f,:!))(one(T), A, x, zero(T), similar(x, T, A.n)) end - function $(f){TA,S,Tx}(A::SparseMatrixCSC{TA,S}, B::StridedMatrix{Tx}) + function $(f)(A::SparseMatrixCSC{TA,S}, B::StridedMatrix{Tx}) where {TA,S,Tx} T = promote_type(TA, Tx) $(Symbol(f,:!))(one(T), A, B, zero(T), similar(B, T, (A.n, size(B, 2)))) end @@ -130,14 +130,14 @@ for (f, opA, opB) in ((:A_mul_Bt, :identity, :transpose), (:At_mul_Bt, :transpose, :transpose), (:Ac_mul_Bc, :ctranspose, :ctranspose)) @eval begin - function ($f){Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, B::SparseMatrixCSC{Tv,Ti}) + function ($f)(A::SparseMatrixCSC{Tv,Ti}, B::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} spmatmul(($opA)(A), ($opB)(B)) end end end -function spmatmul{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, B::SparseMatrixCSC{Tv,Ti}; - sortindices::Symbol = :sortcols) +function spmatmul(A::SparseMatrixCSC{Tv,Ti}, B::SparseMatrixCSC{Tv,Ti}; + sortindices::Symbol = :sortcols) where {Tv,Ti} mA, nA = size(A) mB, nB = size(B) nA==mB || throw(DimensionMismatch()) @@ -284,20 +284,20 @@ function bwdTriSolve!(A::SparseMatrixCSC, B::AbstractVecOrMat) B end -A_ldiv_B!{T}(L::LowerTriangular{T,<:SparseMatrixCSC{T}}, B::StridedVecOrMat) = fwdTriSolve!(L.data, B) -A_ldiv_B!{T}(U::UpperTriangular{T,<:SparseMatrixCSC{T}}, B::StridedVecOrMat) = bwdTriSolve!(U.data, B) +A_ldiv_B!(L::LowerTriangular{T,<:SparseMatrixCSC{T}}, B::StridedVecOrMat) where {T} = fwdTriSolve!(L.data, B) +A_ldiv_B!(U::UpperTriangular{T,<:SparseMatrixCSC{T}}, B::StridedVecOrMat) where {T} = bwdTriSolve!(U.data, B) -(\){T}(L::LowerTriangular{T,<:SparseMatrixCSC{T}}, B::SparseMatrixCSC) = A_ldiv_B!(L, Array(B)) -(\){T}(U::UpperTriangular{T,<:SparseMatrixCSC{T}}, B::SparseMatrixCSC) = A_ldiv_B!(U, Array(B)) +(\)(L::LowerTriangular{T,<:SparseMatrixCSC{T}}, B::SparseMatrixCSC) where {T} = A_ldiv_B!(L, Array(B)) +(\)(U::UpperTriangular{T,<:SparseMatrixCSC{T}}, B::SparseMatrixCSC) where {T} = A_ldiv_B!(U, Array(B)) ## triu, tril -function triu{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}, k::Integer=0) +function triu(S::SparseMatrixCSC{Tv,Ti}, k::Integer=0) where {Tv,Ti} m,n = size(S) if (k > 0 && k > n) || (k < 0 && -k > m) throw(BoundsError()) end - colptr = Array{Ti}(n+1) + colptr = Vector{Ti}(n+1) nnz = 0 for col = 1 : min(max(k+1,1), n+1) colptr[col] = 1 @@ -309,8 +309,8 @@ function triu{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}, k::Integer=0) end colptr[col+1] = nnz+1 end - rowval = Array{Ti}(nnz) - nzval = Array{Tv}(nnz) + rowval = Vector{Ti}(nnz) + nzval = Vector{Tv}(nnz) A = SparseMatrixCSC(m, n, colptr, rowval, nzval) for col = max(k+1,1) : n c1 = S.colptr[col] @@ -323,12 +323,12 @@ function triu{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}, k::Integer=0) A end -function tril{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}, k::Integer=0) +function tril(S::SparseMatrixCSC{Tv,Ti}, k::Integer=0) where {Tv,Ti} m,n = size(S) if (k > 0 && k > n) || (k < 0 && -k > m) throw(BoundsError()) end - colptr = Array{Ti}(n+1) + colptr = Vector{Ti}(n+1) nnz = 0 colptr[1] = 1 for col = 1 : min(n, m+k) @@ -342,8 +342,8 @@ function tril{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}, k::Integer=0) for col = max(min(n, m+k)+2,1) : n+1 colptr[col] = nnz+1 end - rowval = Array{Ti}(nnz) - nzval = Array{Tv}(nnz) + rowval = Vector{Ti}(nnz) + nzval = Vector{Tv}(nnz) A = SparseMatrixCSC(m, n, colptr, rowval, nzval) for col = 1 : min(n, m+k) c1 = S.colptr[col+1]-1 @@ -359,13 +359,13 @@ end ## diff -function sparse_diff1{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}) +function sparse_diff1(S::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} m,n = size(S) m > 1 || return SparseMatrixCSC(0, n, ones(Ti,n+1), Ti[], Tv[]) - colptr = Array{Ti}(n+1) + colptr = Vector{Ti}(n+1) numnz = 2 * nnz(S) # upper bound; will shrink later - rowval = Array{Ti}(numnz) - nzval = Array{Tv}(numnz) + rowval = Vector{Ti}(numnz) + nzval = Vector{Tv}(numnz) numnz = 0 colptr[1] = 1 for col = 1 : n @@ -399,12 +399,12 @@ function sparse_diff1{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}) return SparseMatrixCSC(m-1, n, colptr, rowval, nzval) end -function sparse_diff2{Tv,Ti}(a::SparseMatrixCSC{Tv,Ti}) +function sparse_diff2(a::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} m,n = size(a) - colptr = Array{Ti}(max(n,1)) + colptr = Vector{Ti}(max(n,1)) numnz = 2 * nnz(a) # upper bound; will shrink later - rowval = Array{Ti}(numnz) - nzval = Array{Tv}(numnz) + rowval = Vector{Ti}(numnz) + nzval = Vector{Tv}(numnz) z = zero(Tv) @@ -545,7 +545,7 @@ function cond(A::SparseMatrixCSC, p::Real=2) end end -function normestinv{T}(A::SparseMatrixCSC{T}, t::Integer = min(2,maximum(size(A)))) +function normestinv(A::SparseMatrixCSC{T}, t::Integer = min(2,maximum(size(A)))) where T maxiter = 5 # Check the input n = checksquare(A) @@ -556,8 +556,8 @@ function normestinv{T}(A::SparseMatrixCSC{T}, t::Integer = min(2,maximum(size(A) if t > n throw(ArgumentError("number of blocks must not be greater than $n")) end - ind = Array{Int64}(n) - ind_hist = Array{Int64}(maxiter * t) + ind = Vector{Int64}(n) + ind_hist = Vector{Int64}(maxiter * t) Ti = typeof(float(zero(T))) @@ -579,7 +579,7 @@ function normestinv{T}(A::SparseMatrixCSC{T}, t::Integer = min(2,maximum(size(A) end # Generate the block matrix - X = Array{Ti}(n, t) + X = Matrix{Ti}(n, t) X[1:n,1] = 1 for j = 2:t while true @@ -718,7 +718,7 @@ end # kron -function kron{Tv,Ti}(a::SparseMatrixCSC{Tv,Ti}, b::SparseMatrixCSC{Tv,Ti}) +function kron(a::SparseMatrixCSC{Tv,Ti}, b::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} numnzA = nnz(a) numnzB = nnz(b) @@ -729,9 +729,9 @@ function kron{Tv,Ti}(a::SparseMatrixCSC{Tv,Ti}, b::SparseMatrixCSC{Tv,Ti}) m,n = mA*mB, nA*nB - colptr = Array{Ti}(n+1) - rowval = Array{Ti}(numnz) - nzval = Array{Tv}(numnz) + colptr = Vector{Ti}(n+1) + rowval = Vector{Ti}(numnz) + nzval = Vector{Tv}(numnz) colptr[1] = 1 @@ -773,7 +773,7 @@ function kron{Tv,Ti}(a::SparseMatrixCSC{Tv,Ti}, b::SparseMatrixCSC{Tv,Ti}) SparseMatrixCSC(m, n, colptr, rowval, nzval) end -function kron{Tv1,Ti1,Tv2,Ti2}(A::SparseMatrixCSC{Tv1,Ti1}, B::SparseMatrixCSC{Tv2,Ti2}) +function kron(A::SparseMatrixCSC{Tv1,Ti1}, B::SparseMatrixCSC{Tv2,Ti2}) where {Tv1,Ti1,Tv2,Ti2} Tv_res = promote_type(Tv1, Tv2) Ti_res = promote_type(Ti1, Ti2) A = convert(SparseMatrixCSC{Tv_res,Ti_res}, A) diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl index 8ed7628cd4c95..8f7661c98a139 100644 --- a/base/sparse/sparsematrix.jl +++ b/base/sparse/sparsematrix.jl @@ -292,7 +292,7 @@ function copy!(A::SparseMatrixCSC, B::SparseMatrixCSC) return A end -similar(S::SparseMatrixCSC, Tv::Type=eltype(S)) = SparseMatrixCSC(S.m, S.n, copy(S.colptr), copy(S.rowval), Array{Tv}(length(S.nzval))) +similar(S::SparseMatrixCSC, Tv::Type = eltype(S)) = SparseMatrixCSC(S.m, S.n, copy(S.colptr), copy(S.rowval), Vector{Tv}(length(S.nzval))) function similar(S::SparseMatrixCSC, ::Type{Tv}, ::Type{Ti}) where {Tv,Ti} new_colptr = copy!(similar(S.colptr, Ti), S.colptr) new_rowval = copy!(similar(S.rowval, Ti), S.rowval) diff --git a/base/sparse/sparsevector.jl b/base/sparse/sparsevector.jl index 1d7e0a17e26d6..eb513b2f9bef4 100644 --- a/base/sparse/sparsevector.jl +++ b/base/sparse/sparsevector.jl @@ -789,7 +789,7 @@ function convert(::Type{SparseMatrixCSC{Tv,Ti}}, x::AbstractSparseVector) where SparseMatrixCSC(n, 1, colptr, rowval, nzval) end -convert{Tv,Ti}(::Type{SparseMatrixCSC{Tv}}, x::AbstractSparseVector{<:Any,Ti}) = +convert(::Type{SparseMatrixCSC{Tv}}, x::AbstractSparseVector{<:Any,Ti}) where {Tv,Ti} = convert(SparseMatrixCSC{Tv,Ti}, x) convert(::Type{SparseMatrixCSC}, x::AbstractSparseVector{Tv,Ti}) where {Tv,Ti} = diff --git a/base/subarray.jl b/base/subarray.jl index fd223d905efad..6f7a09f12fee0 100644 --- a/base/subarray.jl +++ b/base/subarray.jl @@ -33,8 +33,8 @@ function SubArray(::IndexLinear, parent::P, indexes::I, ::NTuple{N,Any}) where { end check_parent_index_match(parent, indexes) = check_parent_index_match(parent, index_ndims(indexes...)) -check_parent_index_match{T,N}(parent::AbstractArray{T,N}, ::NTuple{N, Bool}) = nothing -check_parent_index_match{N}(parent, ::NTuple{N, Bool}) = +check_parent_index_match(parent::AbstractArray{T,N}, ::NTuple{N, Bool}) where {T,N} = nothing +check_parent_index_match(parent, ::NTuple{N, Bool}) where {N} = throw(ArgumentError("number of indices ($N) must match the parent dimensionality ($(ndims(parent)))")) # This computes the linear indexing compatability for a given tuple of indices @@ -74,9 +74,9 @@ parentindexes(a::AbstractArray) = ntuple(i->OneTo(size(a,i)), ndims(a)) # ReshapedArray view if necessary. The trouble is that arrays of `CartesianIndex` # can make the number of effective indices not equal to length(I). _maybe_reshape_parent(A::AbstractArray, ::NTuple{1, Bool}) = reshape(A, Val{1}) -_maybe_reshape_parent{_}(A::AbstractArray{_,1}, ::NTuple{1, Bool}) = reshape(A, Val{1}) -_maybe_reshape_parent{_,N}(A::AbstractArray{_,N}, ::NTuple{N, Bool}) = A -_maybe_reshape_parent{N}(A::AbstractArray, ::NTuple{N, Bool}) = reshape(A, Val{N}) # TODO: DEPRECATE FOR #14770 +_maybe_reshape_parent(A::AbstractArray{<:Any,1}, ::NTuple{1, Bool}) = reshape(A, Val{1}) +_maybe_reshape_parent(A::AbstractArray{<:Any,N}, ::NTuple{N, Bool}) where {N} = A +_maybe_reshape_parent(A::AbstractArray, ::NTuple{N, Bool}) where {N} = reshape(A, Val{N}) # TODO: DEPRECATE FOR #14770 """ view(A, inds...) @@ -167,7 +167,7 @@ reindex(V, idxs::Tuple{AbstractMatrix, Vararg{Any}}, subidxs::Tuple{Any, Any, Va (@_propagate_inbounds_meta; (idxs[1][subidxs[1], subidxs[2]], reindex(V, tail(idxs), tail(tail(subidxs)))...)) # In general, we index N-dimensional parent arrays with N indices -@generated function reindex{T,N}(V, idxs::Tuple{AbstractArray{T,N}, Vararg{Any}}, subidxs::Tuple{Vararg{Any}}) +@generated function reindex(V, idxs::Tuple{AbstractArray{T,N}, Vararg{Any}}, subidxs::Tuple{Vararg{Any}}) where {T,N} if length(subidxs.parameters) >= N subs = [:(subidxs[$d]) for d in 1:N] tail = [:(subidxs[$d]) for d in N+1:length(subidxs.parameters)] @@ -237,7 +237,7 @@ substrides(s, parent, dim, I::Tuple{Any, Vararg{Any}}) = throw(ArgumentError("st stride(V::SubArray, d::Integer) = d <= ndims(V) ? strides(V)[d] : strides(V)[end] * size(V)[end] -compute_stride1{N}(parent::AbstractArray, I::NTuple{N,Any}) = +compute_stride1(parent::AbstractArray, I::NTuple{N,Any}) where {N} = (@_inline_meta; compute_stride1(1, fill_to_length(indices(parent), OneTo(1), Val{N}), I)) compute_stride1(s, inds, I::Tuple{}) = s compute_stride1(s, inds, I::Tuple{ScalarIndex, Vararg{Any}}) = @@ -294,7 +294,7 @@ _find_extended_dims(dims, inds, dim, ::ScalarIndex, I...) = _find_extended_dims(dims, inds, dim, i1, I...) = (@_inline_meta; _find_extended_dims((dims..., dim), (inds..., i1), dim+1, I...)) -unsafe_convert{T,N,P}(::Type{Ptr{T}}, V::SubArray{T,N,P,<:Tuple{Vararg{RangeIndex}}}) = +unsafe_convert(::Type{Ptr{T}}, V::SubArray{T,N,P,<:Tuple{Vararg{RangeIndex}}}) where {T,N,P} = unsafe_convert(Ptr{T}, V.parent) + (first_index(V)-1)*sizeof(T) pointer(V::FastSubArray, i::Int) = pointer(V.parent, V.offset1 + V.stride1*i) diff --git a/base/twiceprecision.jl b/base/twiceprecision.jl index 646705ea4e511..30ace134c09fa 100644 --- a/base/twiceprecision.jl +++ b/base/twiceprecision.jl @@ -90,7 +90,7 @@ StepRangeLen{T}(ref::TwicePrecision{T}, step::TwicePrecision{T}, len::Integer, o StepRangeLen{T,TwicePrecision{T},TwicePrecision{T}}(ref, step, len, offset) # Construct range for rational start=start_n/den, step=step_n/den -function floatrange{T}(::Type{T}, start_n::Integer, step_n::Integer, len::Integer, den::Integer) +function floatrange(::Type{T}, start_n::Integer, step_n::Integer, len::Integer, den::Integer) where T if len < 2 return StepRangeLen(TwicePrecision{T}((start_n, den)), TwicePrecision{T}((step_n, den)), Int(len), 1) @@ -161,7 +161,7 @@ function colon(start::T, step::T, stop::T) where T<:Union{Float16,Float32,Float6 StepRangeLen(TwicePrecision(start, zero(T)), twiceprecision(step, nbitslen(T, len, 1)), len) end -function range{T<:Union{Float16,Float32,Float64}}(a::T, st::T, len::Integer) +function range(a::T, st::T, len::Integer) where T<:Union{Float16,Float32,Float64} start_n, start_d = rat(a) step_n, step_d = rat(st) if start_d != 0 && step_d != 0 && @@ -178,7 +178,7 @@ function range{T<:Union{Float16,Float32,Float64}}(a::T, st::T, len::Integer) StepRangeLen(TwicePrecision(a, zero(T)), TwicePrecision(st, zero(T)), len) end -step{T,R,S<:TwicePrecision}(r::StepRangeLen{T,R,S}) = convert(eltype(S), r.step) +step(r::StepRangeLen{T,R,S}) where {T,R,S<:TwicePrecision} = convert(eltype(S), r.step) start(r::StepRangeLen{<:Any,<:TwicePrecision,<:TwicePrecision}) = 1 done(r::StepRangeLen{<:Any,<:TwicePrecision,<:TwicePrecision}, i::Int) = length(r) < i @@ -188,7 +188,7 @@ function next(r::StepRangeLen{<:Any,<:TwicePrecision,<:TwicePrecision}, i::Int) end # This assumes that r.step has already been split so that (0:len-1)*r.step.hi is exact -function unsafe_getindex{T}(r::StepRangeLen{T,<:TwicePrecision,<:TwicePrecision}, i::Integer) +function unsafe_getindex(r::StepRangeLen{T,<:TwicePrecision,<:TwicePrecision}, i::Integer) where T # Very similar to _getindex_hiprec, but optimized to avoid a 2nd call to add2 @_inline_meta u = i - r.offset @@ -205,7 +205,7 @@ function _getindex_hiprec(r::StepRangeLen{<:Any,<:TwicePrecision,<:TwicePrecisio TwicePrecision(x_hi, x_lo) end -function getindex{T}(r::StepRangeLen{T,<:TwicePrecision,<:TwicePrecision}, s::OrdinalRange{<:Integer}) +function getindex(r::StepRangeLen{T,<:TwicePrecision,<:TwicePrecision}, s::OrdinalRange{<:Integer}) where T @_inline_meta @boundscheck checkbounds(r, s) soffset = 1 + round(Int, (r.offset - first(s))/step(s)) @@ -240,15 +240,15 @@ convert(::Type{StepRangeLen{T}}, r::StepRangeLen) where {T<:Union{Float16,Float3 convert(::Type{StepRangeLen{T}}, r::Range) where {T<:Union{Float16,Float32,Float64}} = _convertSRL(StepRangeLen{T,TwicePrecision{T},TwicePrecision{T}}, r) -function _convertSRL{T,R,S}(::Type{StepRangeLen{T,R,S}}, r::StepRangeLen{<:Integer}) +function _convertSRL(::Type{StepRangeLen{T,R,S}}, r::StepRangeLen{<:Integer}) where {T,R,S} StepRangeLen{T,R,S}(R(r.ref), S(r.step), length(r), r.offset) end -function _convertSRL{T,R,S}(::Type{StepRangeLen{T,R,S}}, r::Range{<:Integer}) +function _convertSRL(::Type{StepRangeLen{T,R,S}}, r::Range{<:Integer}) where {T,R,S} StepRangeLen{T,R,S}(R(first(r)), S(step(r)), length(r)) end -function _convertSRL{T,R,S,U}(::Type{StepRangeLen{T,R,S}}, r::Range{U}) +function _convertSRL(::Type{StepRangeLen{T,R,S}}, r::Range{U}) where {T,R,S,U} # if start and step have a rational approximation in the old type, # then we transfer that rational approximation to the new type f, s = first(r), step(r) @@ -268,10 +268,10 @@ function _convertSRL{T,R,S,U}(::Type{StepRangeLen{T,R,S}}, r::Range{U}) __convertSRL(StepRangeLen{T,R,S}, r) end -function __convertSRL{T,R,S,U}(::Type{StepRangeLen{T,R,S}}, r::StepRangeLen{U}) +function __convertSRL(::Type{StepRangeLen{T,R,S}}, r::StepRangeLen{U}) where {T,R,S,U} StepRangeLen{T,R,S}(R(r.ref), S(r.step), length(r), r.offset) end -function __convertSRL{T,R,S,U}(::Type{StepRangeLen{T,R,S}}, r::Range{U}) +function __convertSRL(::Type{StepRangeLen{T,R,S}}, r::Range{U}) where {T,R,S,U} StepRangeLen{T,R,S}(R(first(r)), S(step(r)), length(r)) end @@ -316,7 +316,7 @@ end ## LinSpace # For Float16, Float32, and Float64, linspace returns a StepRangeLen -function linspace{T<:Union{Float16,Float32,Float64}}(start::T, stop::T, len::Integer) +function linspace(start::T, stop::T, len::Integer) where T<:Union{Float16,Float32,Float64} len < 2 && return _linspace1(T, start, stop, len) if start == stop return StepRangeLen(TwicePrecision(start,zero(T)), TwicePrecision(zero(T),zero(T)), len) @@ -338,7 +338,7 @@ function linspace{T<:Union{Float16,Float32,Float64}}(start::T, stop::T, len::Int _linspace(start, stop, len) end -function _linspace{T<:Union{Float16,Float32,Float64}}(start::T, stop::T, len::Integer) +function _linspace(start::T, stop::T, len::Integer) where T<:Union{Float16,Float32,Float64} (isfinite(start) && isfinite(stop)) || throw(ArgumentError("start and stop must be finite, got $start and $stop")) # Find the index that returns the smallest-magnitude element Δ, Δfac = stop-start, 1 @@ -383,7 +383,7 @@ end # linspace for rational numbers, start = start_n/den, stop = stop_n/den # Note this returns a StepRangeLen -function linspace{T}(::Type{T}, start_n::Integer, stop_n::Integer, len::Integer, den::Integer) +function linspace(::Type{T}, start_n::Integer, stop_n::Integer, len::Integer, den::Integer) where T len < 2 && return _linspace1(T, start_n/den, stop_n/den, len) start_n == stop_n && return StepRangeLen(TwicePrecision{T}((start_n, den)), zero(TwicePrecision{T}), len) tmin = -start_n/(Float64(stop_n) - Float64(start_n)) @@ -403,7 +403,7 @@ function linspace{T}(::Type{T}, start_n::Integer, stop_n::Integer, len::Integer, end # For len < 2 -function _linspace1{T}(::Type{T}, start, stop, len::Integer) +function _linspace1(::Type{T}, start, stop, len::Integer) where T len >= 0 || throw(ArgumentError("linspace($start, $stop, $len): negative length")) if len <= 1 len == 1 && (start == stop || throw(ArgumentError("linspace($start, $stop, $len): endpoints differ"))) @@ -447,7 +447,7 @@ function add2{T<:Number}(u::T, v::T) end add2(u, v) = _add2(promote(u, v)...) -_add2{T<:Number}(u::T, v::T) = add2(u, v) +_add2(u::T, v::T) where {T<:Number} = add2(u, v) _add2(u, v) = error("$u::$(typeof(u)) and $v::$(typeof(v)) cannot be promoted to a common type") function +(x::TwicePrecision, y::Number) From 5b9af50269ab1520245dd929904000c86d8ad811 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 25 Apr 2017 14:39:26 -0400 Subject: [PATCH 0552/1534] fix `let` with type declaration this was a regression caused by an optimization for closures --- src/julia-syntax.scm | 1 + test/core.jl | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 0adfd65f28d5e..c5f801b0795dc 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -1850,6 +1850,7 @@ 'const expand-const-decl 'local expand-local-or-global-decl 'global expand-local-or-global-decl + 'local-def expand-local-or-global-decl '= (lambda (e) diff --git a/test/core.jl b/test/core.jl index 41bec99537842..9188117f87e48 100644 --- a/test/core.jl +++ b/test/core.jl @@ -4865,3 +4865,9 @@ struct T21516 T21516(x::Vector{T}, y::Vector{T}) where {T<:Real} = new(float.(x), float.(y)) end @test isa(T21516([1],[2]).x, Vector{Float64}) + +# let with type declaration +let letvar::Int = 2 + letvar = 3.0 + @test letvar === 3 +end From 10853737047c4dd78120fd2ec6dad333c2964717 Mon Sep 17 00:00:00 2001 From: kshyatt Date: Tue, 25 Apr 2017 13:48:03 -0700 Subject: [PATCH 0553/1534] Add a test for mergeing with a committish --- test/libgit2.jl | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/libgit2.jl b/test/libgit2.jl index 12d981c6a6e5c..ca9192fd4a21e 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -685,6 +685,26 @@ mktempdir() do dir # ff merge them @test LibGit2.merge!(repo, [upst_ann], true) @test LibGit2.is_ancestor_of(string(oldhead), string(LibGit2.head_oid(repo)), repo) + + oldhead = LibGit2.head_oid(repo) + LibGit2.branch!(repo, "branch/ff_b") + open(joinpath(LibGit2.path(repo),"ff_file3"),"w") do f + write(f, "333\n") + end + LibGit2.add!(repo, "ff_file3") + LibGit2.commit(repo, "add ff_file3") + + open(joinpath(LibGit2.path(repo),"ff_file4"),"w") do f + write(f, "444\n") + end + LibGit2.add!(repo, "ff_file4") + LibGit2.commit(repo, "add ff_file4") + branchhead = LibGit2.head_oid(repo) + LibGit2.branch!(repo, "master") + # switch back, now try to ff-merge the changes + # from branch/a using committish + @test LibGit2.merge!(repo, committish=string(branchhead)) + @test LibGit2.is_ancestor_of(string(oldhead), string(LibGit2.head_oid(repo)), repo) finally close(repo) end From 1b2f3f820319d05c42cf4b4288b78d5b47df1832 Mon Sep 17 00:00:00 2001 From: Mus M Date: Tue, 25 Apr 2017 21:00:13 -0400 Subject: [PATCH 0554/1534] Use Vector in misc places (#21533) * Use Vector in misc places * Use Vector instead of Array in lapack --- base/array.jl | 6 +- base/associative.jl | 2 +- base/file.jl | 4 +- base/libgit2/reference.jl | 2 +- base/linalg/lapack.jl | 160 +++++++++++++++++++------------------- base/sparse/cholmod.jl | 6 +- 6 files changed, 90 insertions(+), 90 deletions(-) diff --git a/base/array.jl b/base/array.jl index f30ed8bc04401..5d503bd1fcc2e 100644 --- a/base/array.jl +++ b/base/array.jl @@ -399,7 +399,7 @@ function _collect(cont, itr, ::HasEltype, isz::SizeUnknown) return a end -_collect_indices(::Tuple{}, A) = copy!(Array{eltype(A)}(), A) +_collect_indices(::Tuple{}, A) = copy!(Vector{eltype(A)}(), A) _collect_indices(indsA::Tuple{Vararg{OneTo}}, A) = copy!(Array{eltype(A)}(length.(indsA)), A) function _collect_indices(indsA, A) @@ -1826,7 +1826,7 @@ function filter!(f, a::AbstractVector) end function filter(f, a::Vector) - r = Array{eltype(a)}(0) + r = Vector{eltype(a)}(0) for ai in a if f(ai) push!(r, ai) @@ -1839,7 +1839,7 @@ end # These are moderately efficient, preserve order, and remove dupes. function intersect(v1, vs...) - ret = Array{promote_eltype(v1, vs...)}(0) + ret = Vector{promote_eltype(v1, vs...)}(0) for v_elem in v1 inall = true for vsi in vs diff --git a/base/associative.jl b/base/associative.jl index cf9ac14ac3a71..f46378b56d266 100644 --- a/base/associative.jl +++ b/base/associative.jl @@ -296,7 +296,7 @@ function emptymergedict(d::Associative, others::Associative...) end function filter!(f, d::Associative) - badkeys = Array{keytype(d)}(0) + badkeys = Vector{keytype(d)}(0) for (k,v) in d # don't delete!(d, k) here, since associative types # may not support mutation during iteration diff --git a/base/file.jl b/base/file.jl index dd4ebe089d3f1..0180ff28de8f9 100644 --- a/base/file.jl +++ b/base/file.jl @@ -463,8 +463,8 @@ function walkdir(root; topdown=true, follow_symlinks=false, onerror=throw) close(chnl) return chnl end - dirs = Array{eltype(content)}(0) - files = Array{eltype(content)}(0) + dirs = Vector{eltype(content)}(0) + files = Vector{eltype(content)}(0) for name in content if isdir(joinpath(root, name)) push!(dirs, name) diff --git a/base/libgit2/reference.jl b/base/libgit2/reference.jl index be6336815eef5..00acb2513131a 100644 --- a/base/libgit2/reference.jl +++ b/base/libgit2/reference.jl @@ -334,7 +334,7 @@ function Base.map(f::Function, bi::GitBranchIter) while !done(bi, s) val = f(s[1:2]) if res === nothing - res = Array{typeof(val)}(0) + res = Vector{typeof(val)}(0) end push!(res, val) val, s = next(bi, s) diff --git a/base/linalg/lapack.jl b/base/linalg/lapack.jl index 357f28e2d7813..db1c9eee7f994 100644 --- a/base/linalg/lapack.jl +++ b/base/linalg/lapack.jl @@ -282,7 +282,7 @@ for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt, geqrt3, gerqf, getrf, elty, relty e = similar(A, $relty, k) tauq = similar(A, $elty, k) taup = similar(A, $elty, k) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -316,7 +316,7 @@ for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt, geqrt3, gerqf, getrf, elty, relty throw(DimensionMismatch("tau has length $(length(tau)), but needs length $(min(m,n))")) end lwork = BlasInt(-1) - work = Array{$elty}(1) + work = Vector{$elty}(1) info = Ref{BlasInt}() for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($gelqf), liblapack), Void, @@ -346,7 +346,7 @@ for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt, geqrt3, gerqf, getrf, elty, relty throw(DimensionMismatch("tau has length $(length(tau)), but needs length $(min(m,n))")) end lwork = BlasInt(-1) - work = Array{$elty}(1) + work = Vector{$elty}(1) info = Ref{BlasInt}() for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($geqlf), liblapack), Void, @@ -381,7 +381,7 @@ for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt, geqrt3, gerqf, getrf, elty, relty if lda == 0 return A, tau, jpvt end # Early exit - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) cmplx = eltype(A)<:Complex if cmplx @@ -474,7 +474,7 @@ for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt, geqrt3, gerqf, getrf, elty, relty if length(tau) != min(m,n) throw(DimensionMismatch("tau has length $(length(tau)), but needs length $(min(m,n))")) end - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 # first call returns lwork as work[1] @@ -503,7 +503,7 @@ for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt, geqrt3, gerqf, getrf, elty, relty throw(DimensionMismatch("tau has length $(length(tau)), but needs length $(min(m,n))")) end lwork = BlasInt(-1) - work = Array{$elty}(1) + work = Vector{$elty}(1) info = Ref{BlasInt}() for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($gerqf), liblapack), Void, @@ -758,7 +758,7 @@ for (tzrzf, ormrz, elty) in end lda = max(1, m) tau = similar(A, $elty, m) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -795,7 +795,7 @@ for (tzrzf, ormrz, elty) in l = size(A, 2) - size(A, 1) lda = max(1, stride(A,2)) ldc = max(1, stride(C,2)) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -860,7 +860,7 @@ for (gels, gesv, getrs, getri, elty) in throw(DimensionMismatch("matrix A has dimensions ($m,$n), transposed: $btrn, but leading dimension of B is $(size(B,1))")) end info = Ref{BlasInt}() - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) for i = 1:2 ccall((@blasfunc($gels), liblapack), Void, @@ -949,7 +949,7 @@ for (gels, gesv, getrs, getri, elty) in end lda = max(1,stride(A, 2)) lwork = BlasInt(-1) - work = Array{$elty}(1) + work = Vector{$elty}(1) info = Ref{BlasInt}() for i = 1:2 ccall((@blasfunc($getri), liblapack), Void, @@ -1040,7 +1040,7 @@ for (gesvx, elty) in ldaf = stride(AF,2) nrhs = size(B,2) ldb = stride(B,2) - rcond = Array{$elty}(1) + rcond = Vector{$elty}(1) ferr = similar(A, $elty, nrhs) berr = similar(A, $elty, nrhs) work = Array{$elty}(4n) @@ -1109,7 +1109,7 @@ for (gesvx, elty, relty) in ldaf = stride(AF,2) nrhs = size(B,2) ldb = stride(B,2) - rcond = Array{$relty}(1) + rcond = Vector{$relty}(1) ferr = similar(A, $relty, nrhs) berr = similar(A, $relty, nrhs) work = Array{$elty}(2n) @@ -1206,7 +1206,7 @@ for (gelsd, gelsy, elty) in newB = [B; zeros($elty, max(0, n - size(B, 1)), size(B, 2))] s = similar(A, $elty, min(m, n)) rcond = convert($elty, rcond) - rnk = Array{BlasInt}(1) + rnk = Vector{BlasInt}(1) info = Ref{BlasInt}() work = Array{$elty}(1) lwork = BlasInt(-1) @@ -1251,7 +1251,7 @@ for (gelsd, gelsy, elty) in ldb = max(1, m, n) jpvt = zeros(BlasInt, n) rcond = convert($elty, rcond) - rnk = Array{BlasInt}(1) + rnk = Vector{BlasInt}(1) work = Array{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() @@ -1299,7 +1299,7 @@ for (gelsd, gelsy, elty, relty) in newB = [B; zeros($elty, max(0, n - size(B, 1)), size(B, 2))] s = similar(A, $relty, min(m, n)) rcond = convert($relty, rcond) - rnk = Array{BlasInt}(1) + rnk = Vector{BlasInt}(1) info = Ref{BlasInt}() work = Array{$elty}(1) lwork = BlasInt(-1) @@ -1346,7 +1346,7 @@ for (gelsd, gelsy, elty, relty) in ldb = max(1, m, n) jpvt = zeros(BlasInt, n) rcond = convert($relty, rcond) - rnk = Array{BlasInt}(1) + rnk = Vector{BlasInt}(1) work = Array{$elty}(1) lwork = BlasInt(-1) rwork = Array{$relty}(2n) @@ -1423,7 +1423,7 @@ for (gglse, elty) in ((:dgglse_, :Float64), end X = zeros($elty, n) info = Ref{BlasInt}() - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) for i = 1:2 ccall((@blasfunc($gglse), liblapack), Void, @@ -1484,7 +1484,7 @@ for (geev, gesvd, gesdd, ggsvd, elty, relty) in WR = similar(A, $elty, n) WI = similar(A, $elty, n) end - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -1541,7 +1541,7 @@ for (geev, gesvd, gesdd, ggsvd, elty, relty) in U = similar(A, $elty, (m, 0)) VT = similar(A, $elty, (n, 0)) end - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) S = similar(A, $relty, minmn) cmplx = eltype(A)<:Complex @@ -1612,7 +1612,7 @@ for (geev, gesvd, gesdd, ggsvd, elty, relty) in S = similar(A, $relty, minmn) U = similar(A, $elty, jobu == 'A'? (m, m):(jobu == 'S'? (m, minmn) : (m, 0))) VT = similar(A, $elty, jobvt == 'A'? (n, n):(jobvt == 'S'? (minmn, n) : (n, 0))) - work = Array{$elty}(1) + work = Vector{$elty}(1) cmplx = eltype(A) <: Complex if cmplx rwork = Array{$relty}(5minmn) @@ -1680,7 +1680,7 @@ for (geev, gesvd, gesdd, ggsvd, elty, relty) in throw(DimensionMismatch("B has second dimension $(size(B,2)) but needs $n")) end p = size(B, 1) - k = Array{BlasInt}(1) + k = Vector{BlasInt}(1) l = Array{BlasInt}(1) lda = max(1,stride(A, 2)) ldb = max(1,stride(B, 2)) @@ -1814,7 +1814,7 @@ for (f, elty) in ((:dggsvd3_, :Float64), V = jobv == 'V' ? similar(A, $elty, ldv, p) : similar(A, $elty, 0) ldq = max(1, n) Q = jobq == 'Q' ? similar(A, $elty, ldq, n) : similar(A, $elty, 0) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) iwork = Array{BlasInt}(n) info = Ref{BlasInt}() @@ -1858,7 +1858,7 @@ for (f, elty, relty) in ((:zggsvd3_, :Complex128, :Float64), throw(DimensionMismatch("B has second dimension $(size(B,2)) but needs $n")) end p = size(B, 1) - k = Array{BlasInt}(1) + k = Vector{BlasInt}(1) l = Array{BlasInt}(1) lda = max(1,stride(A, 2)) ldb = max(1,stride(B, 2)) @@ -1870,7 +1870,7 @@ for (f, elty, relty) in ((:zggsvd3_, :Complex128, :Float64), V = jobv == 'V' ? similar(A, $elty, ldv, p) : similar(A, $elty, 0) ldq = max(1, n) Q = jobq == 'Q' ? similar(A, $elty, ldq, n) : similar(A, $elty, 0) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) rwork = Array{$relty}(2n) iwork = Array{BlasInt}(n) @@ -1971,7 +1971,7 @@ for (geevx, ggev, elty) in abnrm = Ref{$elty}() rconde = similar(A, $elty, n) rcondv = similar(A, $elty, n) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) iworksize = 0 if sense == 'N' || sense == 'E' @@ -2045,7 +2045,7 @@ for (geevx, ggev, elty) in throw(ArgumentError("jobvr must be 'V' or 'N', but $jobvr was passed")) end vr = similar(A, $elty, ldvr, n) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -2124,7 +2124,7 @@ for (geevx, ggev, elty, relty) in abnrm = Ref{$relty}() rconde = similar(A, $relty, n) rcondv = similar(A, $relty, n) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) rwork = Array{$relty}(2n) info = Ref{BlasInt}() @@ -2190,7 +2190,7 @@ for (geevx, ggev, elty, relty) in throw(ArgumentError("jobvr must be 'V' or 'N', but $jobvr was passed")) end vr = similar(A, $elty, ldvr, n) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) rwork = Array{$relty}(8n) info = Ref{BlasInt}() @@ -2265,7 +2265,7 @@ for (laic1, elty) in if j != length(w) throw(DimensionMismatch("vectors must have same length, but length of x is $j and length of w is $(length(w))")) end - sestpr = Array{$elty}(1) + sestpr = Vector{$elty}(1) s = Array{$elty}(1) c = Array{$elty}(1) ccall((@blasfunc($laic1), liblapack), Void, @@ -2298,7 +2298,7 @@ for (laic1, elty, relty) in if j != length(w) throw(DimensionMismatch("vectors must have same length, but length of x is $j and length of w is $(length(w))")) end - sestpr = Array{$relty}(1) + sestpr = Vector{$relty}(1) s = Array{$elty}(1) c = Array{$elty}(1) ccall((@blasfunc($laic1), liblapack), Void, @@ -2461,7 +2461,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in if k > m throw(DimensionMismatch("invalid number of reflectors: k = $k should be <= m = $m")) end - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -2494,7 +2494,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in if k > n throw(DimensionMismatch("invalid number of reflectors: k = $k should be <= n = $n")) end - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -2529,7 +2529,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in if k > n throw(DimensionMismatch("invalid number of reflectors: k = $k should be <= n = $n")) end - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -2564,7 +2564,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in if k > n throw(DimensionMismatch("invalid number of reflectors: k = $k should be <= n = $n")) end - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -2614,7 +2614,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in if side == 'R' && k > n throw(DimensionMismatch("invalid number of reflectors: k = $k should be <= n = $n")) end - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -2660,7 +2660,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in if side == 'R' && k > n throw(DimensionMismatch("invalid number of reflectors: k = $k should be <= n = $n")) end - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -2709,7 +2709,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in if side == 'R' && k > n throw(DimensionMismatch("invalid number of reflectors: k = $k should be <= n = $n")) end - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -2758,7 +2758,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in if side == 'R' && k > n throw(DimensionMismatch("invalid number of reflectors: k = $k should be <= n = $n")) end - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -3029,7 +3029,7 @@ for (posv, potrf, potri, potrs, pstrf, elty, rtyp) in n = checksquare(A) chkuplo(uplo) piv = similar(A, BlasInt, n) - rank = Array{BlasInt}(1) + rank = Vector{BlasInt}(1) work = Array{$rtyp}(2n) info = Ref{BlasInt}() ccall((@blasfunc($pstrf), liblapack), Void, @@ -3334,7 +3334,7 @@ for (trcon, trevc, trrfs, elty) in chkdiag(diag) n = checksquare(A) chkuplo(uplo) - rcond = Array{$elty}(1) + rcond = Vector{$elty}(1) work = Array{$elty}(3n) iwork = Array{BlasInt}(n) info = Ref{BlasInt}() @@ -3462,7 +3462,7 @@ for (trcon, trevc, trrfs, elty, relty) in n = checksquare(A) chkuplo(uplo) chkdiag(diag) - rcond = Array{$relty}(1) + rcond = Vector{$relty}(1) work = Array{$elty}(2n) rwork = Array{$relty}(n) info = Ref{BlasInt}() @@ -3649,7 +3649,7 @@ for (stev, stebz, stegr, stein, elty) in throw(DimensionMismatch("ev has length $(length(ev)) but needs one less than dv's length, $n)")) end m = Ref{BlasInt}() - nsplit = Array{BlasInt}(1) + nsplit = Vector{BlasInt}(1) w = similar(dv, $elty, n) tmp = 0.0 iblock = similar(dv, BlasInt,n) @@ -3679,13 +3679,13 @@ for (stev, stebz, stegr, stein, elty) in throw(DimensionMismatch("ev has length $(length(ev)) but needs one less than dv's length, $n)")) end eev = [ev; zero($elty)] - abstol = Array{$elty}(1) + abstol = Vector{$elty}(1) m = Ref{BlasInt}() w = similar(dv, $elty, n) ldz = jobz == 'N' ? 1 : n Z = similar(dv, $elty, ldz, range == 'I' ? iu-il+1 : n) isuppz = similar(dv, BlasInt, 2*size(Z, 2)) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) iwork = Array{BlasInt}(1) liwork = BlasInt(-1) @@ -3860,7 +3860,7 @@ for (syconv, sysv, sytrf, sytri, sytrs, elty) in throw(DimensionMismatch("B has first dimension $(size(B,1)), but needs $n")) end ipiv = similar(A, BlasInt, n) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -3894,7 +3894,7 @@ for (syconv, sysv, sytrf, sytri, sytrs, elty) in if n == 0 return A, ipiv end - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -3922,7 +3922,7 @@ for (syconv, sysv, sytrf, sytri, sytrs, elty) in # chkstride1(A) # n = checksquare(A) # chkuplo(uplo) -# work = Array{$elty}(1) +# work = Vector{$elty}(1) # lwork = BlasInt(-1) # info = Ref{BlasInt}() # for i in 1:2 @@ -4010,7 +4010,7 @@ for (sysv, sytrf, sytri, sytrs, elty) in throw(DimensionMismatch("B has first dimension $(size(B,1)), but needs $n")) end ipiv = similar(A, BlasInt, n) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -4044,7 +4044,7 @@ for (sysv, sytrf, sytri, sytrs, elty) in if n == 0 return A, ipiv end - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -4155,7 +4155,7 @@ for (syconv, hesv, hetrf, hetri, hetrs, elty, relty) in throw(DimensionMismatch("B has first dimension $(size(B,1)), but needs $n")) end ipiv = similar(A, BlasInt, n) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -4186,7 +4186,7 @@ for (syconv, hesv, hetrf, hetri, hetrs, elty, relty) in n = checksquare(A) chkuplo(uplo) ipiv = similar(A, BlasInt, n) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i in 1:2 @@ -4215,7 +4215,7 @@ for (syconv, hesv, hetrf, hetri, hetrs, elty, relty) in # chkstride1(A) # n = checksquare(A) # chkuplo(uplo) -# work = Array{$elty}(1) +# work = Vector{$elty}(1) # lwork = BlasInt(-1) # info = Ref{BlasInt}() # for i in 1:2 @@ -4301,7 +4301,7 @@ for (hesv, hetrf, hetri, hetrs, elty, relty) in throw(DimensionMismatch("B has first dimension $(size(B,1)), but needs $n")) end ipiv = similar(A, BlasInt, n) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -4332,7 +4332,7 @@ for (hesv, hetrf, hetri, hetrs, elty, relty) in n = checksquare(A) chkuplo(uplo) ipiv = similar(A, BlasInt, n) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i in 1:2 @@ -4418,7 +4418,7 @@ for (sysv, sytrf, sytri, sytrs, elty, relty) in throw(DimensionMismatch("B has first dimension $(size(B,1)), but needs $n")) end ipiv = similar(A, BlasInt, n) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -4453,7 +4453,7 @@ for (sysv, sytrf, sytri, sytrs, elty, relty) in if n == 0 return A, ipiv end - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -4482,7 +4482,7 @@ for (sysv, sytrf, sytri, sytrs, elty, relty) in # chkstride1(A) # n = checksquare(A) # chkuplo(uplo) -# work = Array{$elty}(1) +# work = Vector{$elty}(1) # lwork = BlasInt(-1) # info = Ref{BlasInt}() # for i in 1:2 @@ -4569,7 +4569,7 @@ for (sysv, sytrf, sytri, sytrs, elty, relty) in throw(DimensionMismatch("B has first dimension $(size(B,1)), but needs $n")) end ipiv = similar(A, BlasInt, n) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -4604,7 +4604,7 @@ for (sysv, sytrf, sytri, sytrs, elty, relty) in if n == 0 return A, ipiv end - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -4785,7 +4785,7 @@ for (syev, syevr, sygvd, elty) in chkstride1(A) n = checksquare(A) W = similar(A, $elty, n) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -4833,7 +4833,7 @@ for (syev, syevr, sygvd, elty) in Z = similar(A, $elty, ldz, n) end isuppz = similar(A, BlasInt, 2*n) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) iwork = Array{BlasInt}(1) liwork = BlasInt(-1) @@ -4884,7 +4884,7 @@ for (syev, syevr, sygvd, elty) in lda = max(1, stride(A, 2)) ldb = max(1, stride(B, 2)) w = similar(A, $elty, n) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) iwork = Array{BlasInt}(1) liwork = BlasInt(-1) @@ -4929,7 +4929,7 @@ for (syev, syevr, sygvd, elty, relty) in chkstride1(A) n = checksquare(A) W = similar(A, $relty, n) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) rwork = Array{$relty}(max(1, 3n-2)) info = Ref{BlasInt}() @@ -4981,7 +4981,7 @@ for (syev, syevr, sygvd, elty, relty) in Z = similar(A, $elty, ldz, n) end isuppz = similar(A, BlasInt, 2*n) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) rwork = Array{$relty}(1) lrwork = BlasInt(-1) @@ -5036,7 +5036,7 @@ for (syev, syevr, sygvd, elty, relty) in lda = max(1, stride(A, 2)) ldb = max(1, stride(B, 2)) w = similar(A, $relty, n) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) iwork = Array{BlasInt}(1) liwork = BlasInt(-1) @@ -5258,7 +5258,7 @@ for (gecon, elty) in chkstride1(A) n = checksquare(A) lda = max(1, stride(A, 2)) - rcond = Array{$elty}(1) + rcond = Vector{$elty}(1) work = Array{$elty}(4n) iwork = Array{BlasInt}(n) info = Ref{BlasInt}() @@ -5292,7 +5292,7 @@ for (gecon, elty, relty) in chkstride1(A) n = checksquare(A) lda = max(1, stride(A, 2)) - rcond = Array{$relty}(1) + rcond = Vector{$relty}(1) work = Array{$elty}(2n) rwork = Array{$relty}(2n) info = Ref{BlasInt}() @@ -5335,7 +5335,7 @@ for (gehrd, elty) in n = checksquare(A) chkfinite(A) # balancing routines don't support NaNs and Infs tau = similar(A, $elty, max(0,n - 1)) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -5385,7 +5385,7 @@ for (orghr, elty) in if n - length(tau) != 1 throw(DimensionMismatch("tau has length $(length(tau)), needs $(n - 1)")) end - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -5441,7 +5441,7 @@ for (ormhr, elty) in throw(DimensionMismatch("A and C matrices are not conformable")) end - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -5480,12 +5480,12 @@ for (gees, gges, elty) in function gees!(jobvs::Char, A::StridedMatrix{$elty}) chkstride1(A) n = checksquare(A) - sdim = Array{BlasInt}(1) + sdim = Vector{BlasInt}(1) wr = similar(A, $elty, n) wi = similar(A, $elty, n) ldvs = jobvs == 'V' ? n : 1 vs = similar(A, $elty, ldvs, n) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -5530,7 +5530,7 @@ for (gees, gges, elty) in vsl = similar(A, $elty, ldvsl, n) ldvsr = jobvsr == 'V' ? n : 1 vsr = similar(A, $elty, ldvsr, n) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -5578,7 +5578,7 @@ for (gees, gges, elty, relty) in w = similar(A, $elty, n) ldvs = jobvs == 'V' ? n : 1 vs = similar(A, $elty, ldvs, n) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) rwork = Array{$relty}(n) info = Ref{BlasInt}() @@ -5624,7 +5624,7 @@ for (gees, gges, elty, relty) in vsl = similar(A, $elty, ldvsl, n) ldvsr = jobvsr == 'V' ? n : 1 vsr = similar(A, $elty, ldvsr, n) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) rwork = Array{$relty}(8n) info = Ref{BlasInt}() @@ -5727,7 +5727,7 @@ for (trexc, trsen, tgsen, elty) in wr = similar(T, $elty, n) wi = similar(T, $elty, n) m = sum(select) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) iwork = Array{BlasInt}(1) liwork = BlasInt(-1) @@ -5793,7 +5793,7 @@ for (trexc, trsen, tgsen, elty) in alphar = similar(T, $elty, n) beta = similar(T, $elty, n) lwork = BlasInt(-1) - work = Array{$elty}(1) + work = Vector{$elty}(1) liwork = BlasInt(-1) iwork = Array{BlasInt}(1) info = Ref{BlasInt}() @@ -5874,7 +5874,7 @@ for (trexc, trsen, tgsen, elty) in ldq = max(1, stride(Q, 2)) w = similar(T, $elty, n) m = sum(select) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() select = convert(Array{BlasInt}, select) @@ -5935,7 +5935,7 @@ for (trexc, trsen, tgsen, elty) in alpha = similar(T, $elty, n) beta = similar(T, $elty, n) lwork = BlasInt(-1) - work = Array{$elty}(1) + work = Vector{$elty}(1) liwork = BlasInt(-1) iwork = Array{BlasInt}(1) info = Ref{BlasInt}() @@ -6018,7 +6018,7 @@ for (fn, elty, relty) in ((:dtrsyl_, :Float64, :Float64), throw(DimensionMismatch("dimensions of A, ($m,$n), and C, ($m1,$n1), must match")) end ldc = max(1, stride(C, 2)) - scale = Array{$relty}(1) + scale = Vector{$relty}(1) info = Ref{BlasInt}() ccall((@blasfunc($fn), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, diff --git a/base/sparse/cholmod.jl b/base/sparse/cholmod.jl index 64eed3488df84..2ad4ecfab2e75 100644 --- a/base/sparse/cholmod.jl +++ b/base/sparse/cholmod.jl @@ -29,7 +29,7 @@ const CHOLMOD_MIN_VERSION = v"2.1.1" ### These offsets are defined in SuiteSparse_wrapper.c const common_size = ccall((:jl_cholmod_common_size,:libsuitesparse_wrapper),Int,()) -const cholmod_com_offsets = Array{Csize_t}(19) +const cholmod_com_offsets = Vector{Csize_t}(19) ccall((:jl_cholmod_common_offsets, :libsuitesparse_wrapper), Void, (Ptr{Csize_t},), cholmod_com_offsets) @@ -58,7 +58,7 @@ end common() = commonStruct -const build_version_array = Array{Cint}(3) +const build_version_array = Vector{Cint}(3) ccall((:jl_cholmod_version, :libsuitesparse_wrapper), Cint, (Ptr{Cint},), build_version_array) const build_version = VersionNumber(build_version_array...) @@ -66,7 +66,7 @@ function __init__() try ### Check if the linked library is compatible with the Julia code if Libdl.dlsym_e(Libdl.dlopen("libcholmod"), :cholmod_version) != C_NULL - current_version_array = Array{Cint}(3) + current_version_array = Vector{Cint}(3) ccall((:cholmod_version, :libcholmod), Cint, (Ptr{Cint},), current_version_array) current_version = VersionNumber(current_version_array...) else # CHOLMOD < 2.1.1 does not include cholmod_version() From db9709c6f282877f5afe3fd1fef45e0a459b81b0 Mon Sep 17 00:00:00 2001 From: Mus M Date: Tue, 25 Apr 2017 21:07:43 -0400 Subject: [PATCH 0555/1534] Conversion to new where syntax (#21536) * Conversion to new where syntax * Address review * Review + misc * Review --- base/linalg/dense.jl | 65 +++++++++++++++++-------------- base/linalg/diagonal.jl | 24 ++++++------ base/linalg/eigen.jl | 26 ++++++------- base/pkg/resolve/versionweight.jl | 28 ++++++------- base/sparse/cholmod.jl | 20 +++++----- base/sparse/spqr.jl | 10 ++--- base/special/gamma.jl | 4 +- 7 files changed, 91 insertions(+), 86 deletions(-) diff --git a/base/linalg/dense.jl b/base/linalg/dense.jl index 7beccb480789a..cd3422938eaef 100644 --- a/base/linalg/dense.jl +++ b/base/linalg/dense.jl @@ -53,8 +53,10 @@ julia> A """ isposdef!(A::StridedMatrix) = ishermitian(A) && isposdef!(A, :U) -isposdef{T}(A::AbstractMatrix{T}, UL::Symbol) = (S = typeof(sqrt(one(T))); isposdef!(S == T ? copy(A) : convert(AbstractMatrix{S}, A), UL)) - +function isposdef(A::AbstractMatrix{T}, UL::Symbol) where T + S = typeof(sqrt(one(T))) + isposdef!(S == T ? copy(A) : convert(AbstractMatrix{S}, A), UL) +end """ isposdef(A) -> Bool @@ -72,23 +74,26 @@ julia> isposdef(A) true ``` """ -isposdef{T}(A::AbstractMatrix{T}) = (S = typeof(sqrt(one(T))); isposdef!(S == T ? copy(A) : convert(AbstractMatrix{S}, A))) +function isposdef(A::AbstractMatrix{T}) where T + S = typeof(sqrt(one(T))) + isposdef!(S == T ? copy(A) : convert(AbstractMatrix{S}, A)) +end isposdef(x::Number) = imag(x)==0 && real(x) > 0 stride1(x::Array) = 1 stride1(x::StridedVector) = stride(x, 1)::Int -function norm{T<:BlasFloat, TI<:Integer}(x::StridedVector{T}, rx::Union{UnitRange{TI},Range{TI}}) +function norm(x::StridedVector{T}, rx::Union{UnitRange{TI},Range{TI}}) where {T<:BlasFloat,TI<:Integer} if minimum(rx) < 1 || maximum(rx) > length(x) throw(BoundsError(x, rx)) end BLAS.nrm2(length(rx), pointer(x)+(first(rx)-1)*sizeof(T), step(rx)) end -vecnorm1{T<:BlasReal}(x::Union{Array{T},StridedVector{T}}) = +vecnorm1(x::Union{Array{T},StridedVector{T}}) where {T<:BlasReal} = length(x) < ASUM_CUTOFF ? generic_vecnorm1(x) : BLAS.asum(x) -vecnorm2{T<:BlasFloat}(x::Union{Array{T},StridedVector{T}}) = +vecnorm2(x::Union{Array{T},StridedVector{T}}) where {T<:BlasFloat} = length(x) < NRM2_CUTOFF ? generic_vecnorm2(x) : BLAS.nrm2(x) """ @@ -260,16 +265,16 @@ julia> diagm([1,2,3],1) 0 0 0 0 ``` """ -function diagm{T}(v::AbstractVector{T}, k::Integer=0) +function diagm(v::AbstractVector{T}, k::Integer=0) where T n = length(v) + abs(k) A = zeros(T,n,n) A[diagind(A,k)] = v A end -diagm(x::Number) = (X = Array{typeof(x)}(1,1); X[1,1] = x; X) +diagm(x::Number) = (X = Matrix{typeof(x)}(1,1); X[1,1] = x; X) -function trace{T}(A::Matrix{T}) +function trace(A::Matrix{T}) where T n = checksquare(A) t = zero(T) for i=1:n @@ -304,8 +309,8 @@ julia> kron(A, B) 3+0im 0-3im 4+0im 0-4im ``` """ -function kron{T,S}(a::AbstractMatrix{T}, b::AbstractMatrix{S}) - R = Array{promote_op(*,T,S)}(size(a,1)*size(b,1), size(a,2)*size(b,2)) +function kron(a::AbstractMatrix{T}, b::AbstractMatrix{S}) where {T,S} + R = Matrix{promote_op(*,T,S)}(size(a,1)*size(b,1), size(a,2)*size(b,2)) m = 1 for j = 1:size(a,2), l = 1:size(b,2), i = 1:size(a,1) aij = a[i,j] @@ -319,13 +324,13 @@ end kron(a::Number, b::Union{Number, AbstractVecOrMat}) = a * b kron(a::AbstractVecOrMat, b::Number) = a * b -kron(a::AbstractVector, b::AbstractVector)=vec(kron(reshape(a,length(a),1),reshape(b,length(b),1))) -kron(a::AbstractMatrix, b::AbstractVector)=kron(a,reshape(b,length(b),1)) -kron(a::AbstractVector, b::AbstractMatrix)=kron(reshape(a,length(a),1),b) +kron(a::AbstractVector, b::AbstractVector) = vec(kron(reshape(a ,length(a), 1), reshape(b, length(b), 1))) +kron(a::AbstractMatrix, b::AbstractVector) = kron(a, reshape(b, length(b), 1)) +kron(a::AbstractVector, b::AbstractMatrix) = kron(reshape(a, length(a), 1), b) # Matrix power -^{T}(A::AbstractMatrix{T}, p::Integer) = p < 0 ? Base.power_by_squaring(inv(A), -p) : Base.power_by_squaring(A, p) -function ^{T}(A::AbstractMatrix{T}, p::Real) +(^)(A::AbstractMatrix{T}, p::Integer) where {T} = p < 0 ? Base.power_by_squaring(inv(A), -p) : Base.power_by_squaring(A, p) +function (^)(A::AbstractMatrix{T}, p::Real) where T # For integer powers, use repeated squaring if isinteger(p) TT = Base.promote_op(^, eltype(A), typeof(p)) @@ -383,7 +388,7 @@ function ^{T}(A::AbstractMatrix{T}, p::Real) return retmat end end -^(A::AbstractMatrix, p::Number) = expm(p*logm(A)) +(^)(A::AbstractMatrix, p::Number) = expm(p*logm(A)) # Matrix exponential @@ -546,7 +551,7 @@ julia> logm(A) 0.0 1.0 ``` """ -function logm{T}(A::StridedMatrix{T}) +function logm(A::StridedMatrix{T}) where T # If possible, use diagonalization if issymmetric(A) && T <: Real return full(logm(Symmetric(A))) @@ -648,7 +653,7 @@ end sqrtm(a::Number) = (b = sqrt(complex(a)); imag(b) == 0 ? real(b) : b) sqrtm(a::Complex) = sqrt(a) -function inv{T}(A::StridedMatrix{T}) +function inv(A::StridedMatrix{T}) where T checksquare(A) S = typeof((one(T)*zero(T) + one(T)*zero(T))/one(T)) AA = convert(AbstractArray{S}, A) @@ -710,7 +715,7 @@ julia> factorize(A) # factorize will check to see that A is already factorized This returns a `5×5 Bidiagonal{Float64}`, which can now be passed to other linear algebra functions (e.g. eigensolvers) which will use specialized methods for `Bidiagonal` types. """ -function factorize{T}(A::StridedMatrix{T}) +function factorize(A::StridedMatrix{T}) where T m, n = size(A) if m == n if m == 1 return A[1] end @@ -831,11 +836,11 @@ julia> M * N [^KY88]: Konstantinos Konstantinides and Kung Yao, "Statistical analysis of effective singular values in matrix rank determination", IEEE Transactions on Acoustics, Speech and Signal Processing, 36(5), 1988, 757-763. [doi:10.1109/29.1585](http://dx.doi.org/10.1109/29.1585) """ -function pinv{T}(A::StridedMatrix{T}, tol::Real) +function pinv(A::StridedMatrix{T}, tol::Real) where T m, n = size(A) Tout = typeof(zero(T)/sqrt(one(T) + one(T))) if m == 0 || n == 0 - return Array{Tout}(n, m) + return Matrix{Tout}(n, m) end if istril(A) if istriu(A) @@ -860,7 +865,7 @@ function pinv{T}(A::StridedMatrix{T}, tol::Real) Sinv[find(.!isfinite.(Sinv))] = zero(Stype) return SVD.Vt' * (Diagonal(Sinv) * SVD.U') end -function pinv{T}(A::StridedMatrix{T}) +function pinv(A::StridedMatrix{T}) where T tol = eps(real(float(one(T))))*maximum(size(A)) return pinv(A, tol) end @@ -893,7 +898,7 @@ julia> nullspace(M) 1.0 ``` """ -function nullspace{T}(A::StridedMatrix{T}) +function nullspace(A::StridedMatrix{T}) where T m, n = size(A) (m == 0 || n == 0) && return eye(T, n) SVD = svdfact(A, thin = false) @@ -930,7 +935,7 @@ end Computes the solution `X` to the Sylvester equation `AX + XB + C = 0`, where `A`, `B` and `C` have compatible dimensions and `A` and `-B` have no eigenvalues with equal real part. """ -function sylvester{T<:BlasFloat}(A::StridedMatrix{T},B::StridedMatrix{T},C::StridedMatrix{T}) +function sylvester(A::StridedMatrix{T},B::StridedMatrix{T},C::StridedMatrix{T}) where T<:BlasFloat RA, QA = schur(A) RB, QB = schur(B) @@ -938,9 +943,9 @@ function sylvester{T<:BlasFloat}(A::StridedMatrix{T},B::StridedMatrix{T},C::Stri Y, scale = LAPACK.trsyl!('N','N', RA, RB, D) scale!(QA*A_mul_Bc(Y,QB), inv(scale)) end -sylvester{T<:Integer}(A::StridedMatrix{T},B::StridedMatrix{T},C::StridedMatrix{T}) = sylvester(float(A), float(B), float(C)) +sylvester(A::StridedMatrix{T}, B::StridedMatrix{T}, C::StridedMatrix{T}) where {T<:Integer} = sylvester(float(A), float(B), float(C)) -sylvester(a::Union{Real,Complex},b::Union{Real,Complex},c::Union{Real,Complex}) = -c / (a + b) +sylvester(a::Union{Real,Complex}, b::Union{Real,Complex}, c::Union{Real,Complex}) = -c / (a + b) # AX + XA' + C = 0 @@ -951,12 +956,12 @@ Computes the solution `X` to the continuous Lyapunov equation `AX + XA' + C = 0` eigenvalue of `A` has a zero real part and no two eigenvalues are negative complex conjugates of each other. """ -function lyap{T<:BlasFloat}(A::StridedMatrix{T},C::StridedMatrix{T}) +function lyap(A::StridedMatrix{T}, C::StridedMatrix{T}) where {T<:BlasFloat} R, Q = schur(A) D = -Ac_mul_B(Q,C*Q) Y, scale = LAPACK.trsyl!('N', T <: Complex ? 'C' : 'T', R, R, D) scale!(Q*A_mul_Bc(Y,Q), inv(scale)) end -lyap{T<:Integer}(A::StridedMatrix{T},C::StridedMatrix{T}) = lyap(float(A), float(C)) -lyap{T<:Number}(a::T, c::T) = -c/(2a) +lyap(A::StridedMatrix{T}, C::StridedMatrix{T}) where {T<:Integer} = lyap(float(A), float(C)) +lyap(a::T, c::T) where {T<:Number} = -c/(2a) diff --git a/base/linalg/diagonal.jl b/base/linalg/diagonal.jl index 9c8647fe2c22f..a5308cd8dcdf2 100644 --- a/base/linalg/diagonal.jl +++ b/base/linalg/diagonal.jl @@ -135,16 +135,16 @@ function tril!(D::Diagonal,k::Integer=0) return D end -==(Da::Diagonal, Db::Diagonal) = Da.diag == Db.diag --(A::Diagonal)=Diagonal(-A.diag) -+(Da::Diagonal, Db::Diagonal) = Diagonal(Da.diag + Db.diag) --(Da::Diagonal, Db::Diagonal) = Diagonal(Da.diag - Db.diag) +(==)(Da::Diagonal, Db::Diagonal) = Da.diag == Db.diag +(-)(A::Diagonal) = Diagonal(-A.diag) +(+)(Da::Diagonal, Db::Diagonal) = Diagonal(Da.diag + Db.diag) +(-)(Da::Diagonal, Db::Diagonal) = Diagonal(Da.diag - Db.diag) -*(x::Number, D::Diagonal) = Diagonal(x * D.diag) -*(D::Diagonal, x::Number) = Diagonal(D.diag * x) -/(D::Diagonal, x::Number) = Diagonal(D.diag / x) -*(Da::Diagonal, Db::Diagonal) = Diagonal(Da.diag .* Db.diag) -*(D::Diagonal, V::AbstractVector) = D.diag .* V +(*)(x::Number, D::Diagonal) = Diagonal(x * D.diag) +(*)(D::Diagonal, x::Number) = Diagonal(D.diag * x) +(/)(D::Diagonal, x::Number) = Diagonal(D.diag / x) +(*)(Da::Diagonal, Db::Diagonal) = Diagonal(Da.diag .* Db.diag) +(*)(D::Diagonal, V::AbstractVector) = D.diag .* V (*)(A::AbstractTriangular, D::Diagonal) = A_mul_B!(copy(A), D) (*)(D::Diagonal, B::AbstractTriangular) = A_mul_B!(D, copy(B)) @@ -235,8 +235,8 @@ Ac_mul_B!(out::AbstractMatrix, A::Diagonal, in::AbstractMatrix) = out .= ctransp At_mul_B!(out::AbstractMatrix, A::Diagonal, in::AbstractMatrix) = out .= transpose.(A.diag) .* in -/(Da::Diagonal, Db::Diagonal) = Diagonal(Da.diag ./ Db.diag) -function A_ldiv_B!{T}(D::Diagonal{T}, v::AbstractVector{T}) +(/)(Da::Diagonal, Db::Diagonal) = Diagonal(Da.diag ./ Db.diag) +function A_ldiv_B!(D::Diagonal{T}, v::AbstractVector{T}) where T if length(v) != length(D.diag) throw(DimensionMismatch("diagonal matrix is $(length(D.diag)) by $(length(D.diag)) but right hand side has $(length(v)) rows")) end @@ -249,7 +249,7 @@ function A_ldiv_B!{T}(D::Diagonal{T}, v::AbstractVector{T}) end v end -function A_ldiv_B!{T}(D::Diagonal{T}, V::AbstractMatrix{T}) +function A_ldiv_B!(D::Diagonal{T}, V::AbstractMatrix{T}) where T if size(V,1) != length(D.diag) throw(DimensionMismatch("diagonal matrix is $(length(D.diag)) by $(length(D.diag)) but right hand side has $(size(V,1)) rows")) end diff --git a/base/linalg/eigen.jl b/base/linalg/eigen.jl index 40d66d423139c..e342101321066 100644 --- a/base/linalg/eigen.jl +++ b/base/linalg/eigen.jl @@ -35,7 +35,7 @@ isposdef(A::Union{Eigen,GeneralizedEigen}) = isreal(A.values) && all(x -> x > 0, Same as [`eigfact`](@ref), but saves space by overwriting the input `A` (and `B`), instead of creating a copy. """ -function eigfact!{T<:BlasReal}(A::StridedMatrix{T}; permute::Bool=true, scale::Bool=true) +function eigfact!(A::StridedMatrix{T}; permute::Bool=true, scale::Bool=true) where T<:BlasReal n = size(A, 2) n == 0 && return Eigen(zeros(T, 0), zeros(T, 0, 0)) issymmetric(A) && return eigfact!(Symmetric(A)) @@ -58,7 +58,7 @@ function eigfact!{T<:BlasReal}(A::StridedMatrix{T}; permute::Bool=true, scale::B return Eigen(complex.(WR, WI), evec) end -function eigfact!{T<:BlasComplex}(A::StridedMatrix{T}; permute::Bool=true, scale::Bool=true) +function eigfact!(A::StridedMatrix{T}; permute::Bool=true, scale::Bool=true) where T<:BlasComplex n = size(A, 2) n == 0 && return Eigen(zeros(T, 0), zeros(T, 0, 0)) ishermitian(A) && return eigfact!(Hermitian(A)) @@ -98,7 +98,7 @@ julia> F[:vectors] 0.0 0.0 1.0 ``` """ -function eigfact{T}(A::StridedMatrix{T}; permute::Bool=true, scale::Bool=true) +function eigfact(A::StridedMatrix{T}; permute::Bool=true, scale::Bool=true) where T S = promote_type(Float32, typeof(one(T)/norm(one(T)))) eigfact!(copy_oftype(A, S), permute = permute, scale = scale) end @@ -156,9 +156,9 @@ julia> eigvecs([1.0 0.0 0.0; 0.0 3.0 0.0; 0.0 0.0 18.0]) """ eigvecs(A::Union{Number, AbstractMatrix}; permute::Bool=true, scale::Bool=true) = eigvecs(eigfact(A, permute=permute, scale=scale)) -eigvecs{T,V,S,U}(F::Union{Eigen{T,V,S,U}, GeneralizedEigen{T,V,S,U}}) = F[:vectors]::S +eigvecs(F::Union{Eigen{T,V,S,U}, GeneralizedEigen{T,V,S,U}}) where {T,V,S,U} = F[:vectors]::S -eigvals{T,V,S,U}(F::Union{Eigen{T,V,S,U}, GeneralizedEigen{T,V,S,U}}) = F[:values]::U +eigvals(F::Union{Eigen{T,V,S,U}, GeneralizedEigen{T,V,S,U}}) where {T,V,S,U} = F[:values]::U """ eigvals!(A; permute::Bool=true, scale::Bool=true) -> values @@ -189,11 +189,11 @@ become closer to upper triangular, and `scale=true` scales the matrix by its dia elements to make rows and columns more equal in norm. The default is `true` for both options. """ -function eigvals{T}(A::StridedMatrix{T}; permute::Bool=true, scale::Bool=true) +function eigvals(A::StridedMatrix{T}; permute::Bool=true, scale::Bool=true) where T S = promote_type(Float32, typeof(one(T)/norm(one(T)))) return eigvals!(copy_oftype(A, S), permute = permute, scale = scale) end -function eigvals{T<:Number}(x::T; kwargs...) +function eigvals(x::T; kwargs...) where T<:Number val = convert(promote_type(Float32, typeof(one(T)/norm(one(T)))), x) return imag(val) == 0 ? [real(val)] : [val] end @@ -286,7 +286,7 @@ inv(A::Eigen) = A.vectors * inv(Diagonal(A.values)) / A.vectors det(A::Eigen) = prod(A.values) # Generalized eigenproblem -function eigfact!{T<:BlasReal}(A::StridedMatrix{T}, B::StridedMatrix{T}) +function eigfact!(A::StridedMatrix{T}, B::StridedMatrix{T}) where T<:BlasReal issymmetric(A) && isposdef(B) && return eigfact!(Symmetric(A), Symmetric(B)) n = size(A, 1) alphar, alphai, beta, _, vr = LAPACK.ggev!('N', 'V', A, B) @@ -309,7 +309,7 @@ function eigfact!{T<:BlasReal}(A::StridedMatrix{T}, B::StridedMatrix{T}) return GeneralizedEigen(complex.(alphar, alphai)./beta, vecs) end -function eigfact!{T<:BlasComplex}(A::StridedMatrix{T}, B::StridedMatrix{T}) +function eigfact!(A::StridedMatrix{T}, B::StridedMatrix{T}) where T<:BlasComplex ishermitian(A) && isposdef(B) && return eigfact!(Hermitian(A), Hermitian(B)) alpha, beta, _, vr = LAPACK.ggev!('N', 'V', A, B) return GeneralizedEigen(alpha./beta, vr) @@ -323,7 +323,7 @@ Computes the generalized eigenvalue decomposition of `A` and `B`, returning a `F[:values]` and the generalized eigenvectors in the columns of the matrix `F[:vectors]`. (The `k`th generalized eigenvector can be obtained from the slice `F[:vectors][:, k]`.) """ -function eigfact{TA,TB}(A::AbstractMatrix{TA}, B::AbstractMatrix{TB}) +function eigfact(A::AbstractMatrix{TA}, B::AbstractMatrix{TB}) where {TA,TB} S = promote_type(Float32, typeof(one(TA)/norm(one(TA))),TB) return eigfact!(copy_oftype(A, S), copy_oftype(B, S)) end @@ -369,12 +369,12 @@ end Same as [`eigvals`](@ref), but saves space by overwriting the input `A` (and `B`), instead of creating copies. """ -function eigvals!{T<:BlasReal}(A::StridedMatrix{T}, B::StridedMatrix{T}) +function eigvals!(A::StridedMatrix{T}, B::StridedMatrix{T}) where T<:BlasReal issymmetric(A) && isposdef(B) && return eigvals!(Symmetric(A), Symmetric(B)) alphar, alphai, beta, vl, vr = LAPACK.ggev!('N', 'N', A, B) return (iszero(alphai) ? alphar : complex.(alphar, alphai))./beta end -function eigvals!{T<:BlasComplex}(A::StridedMatrix{T}, B::StridedMatrix{T}) +function eigvals!(A::StridedMatrix{T}, B::StridedMatrix{T}) where T<:BlasComplex ishermitian(A) && isposdef(B) && return eigvals!(Hermitian(A), Hermitian(B)) alpha, beta, vl, vr = LAPACK.ggev!('N', 'N', A, B) alpha./beta @@ -404,7 +404,7 @@ julia> eigvals(A,B) 0.0-1.0im ``` """ -function eigvals{TA,TB}(A::AbstractMatrix{TA}, B::AbstractMatrix{TB}) +function eigvals(A::AbstractMatrix{TA}, B::AbstractMatrix{TB}) where {TA,TB} S = promote_type(Float32, typeof(one(TA)/norm(one(TA))),TB) return eigvals!(copy_oftype(A, S), copy_oftype(B, S)) end diff --git a/base/pkg/resolve/versionweight.jl b/base/pkg/resolve/versionweight.jl index 249662d07c3ed..72df6ba95ff43 100644 --- a/base/pkg/resolve/versionweight.jl +++ b/base/pkg/resolve/versionweight.jl @@ -14,12 +14,12 @@ end HierarchicalValue{T}(v::Vector{T}) = HierarchicalValue{T}(v, zero(T)) HierarchicalValue(T::Type) = HierarchicalValue(T[]) -Base.zero{T}(::Type{HierarchicalValue{T}}) = HierarchicalValue(T) +Base.zero(::Type{HierarchicalValue{T}}) where {T} = HierarchicalValue(T) -Base.typemin{T}(::Type{HierarchicalValue{T}}) = HierarchicalValue(T[], typemin(T)) +Base.typemin(::Type{HierarchicalValue{T}}) where {T} = HierarchicalValue(T[], typemin(T)) for f in (:-, :+) - @eval function Base.$f{T}(a::HierarchicalValue{T}, b::HierarchicalValue{T}) + @eval function Base.$f(a::HierarchicalValue{T}, b::HierarchicalValue{T}) where T av = a.v bv = b.v la = length(a.v) @@ -44,7 +44,7 @@ end Base.:-(a::HierarchicalValue) = HierarchicalValue(-a.v, -a.rest) -function Base.cmp{T}(a::HierarchicalValue{T}, b::HierarchicalValue{T}) +function Base.cmp(a::HierarchicalValue{T}, b::HierarchicalValue{T}) where T av = a.v bv = b.v la = length(a.v) @@ -63,12 +63,12 @@ function Base.cmp{T}(a::HierarchicalValue{T}, b::HierarchicalValue{T}) end return cmp(a.rest, b.rest) end -Base.isless{T}(a::HierarchicalValue{T}, b::HierarchicalValue{T}) = cmp(a,b) < 0 -Base.:(==){T}(a::HierarchicalValue{T}, b::HierarchicalValue{T}) = cmp(a,b) == 0 +Base.isless(a::HierarchicalValue{T}, b::HierarchicalValue{T}) where {T} = cmp(a,b) < 0 +Base.:(==)(a::HierarchicalValue{T}, b::HierarchicalValue{T}) where {T} = cmp(a,b) == 0 -Base.abs{T}(a::HierarchicalValue{T}) = HierarchicalValue(T[abs(x) for x in a.v], abs(a.rest)) +Base.abs(a::HierarchicalValue{T}) where {T} = HierarchicalValue(T[abs(x) for x in a.v], abs(a.rest)) -Base.copy{T}(a::HierarchicalValue{T}) = HierarchicalValue(T[copy(x) for x in a.v], copy(a.rest)) +Base.copy(a::HierarchicalValue{T}) where {T} = HierarchicalValue(T[copy(x) for x in a.v], copy(a.rest)) struct VWPreBuildItem nonempty::Int @@ -126,18 +126,18 @@ Base.zero(::Type{VWPreBuild}) = VWPreBuild() const _vwprebuild_min = VWPreBuild(typemin(Int), typemin(HierarchicalValue{VWPreBuildItem})) Base.typemin(::Type{VWPreBuild}) = _vwprebuild_min -function Base.:-(a::VWPreBuild, b::VWPreBuild) +function Base.:(-)(a::VWPreBuild, b::VWPreBuild) b === _vwprebuild_zero && return a a === _vwprebuild_zero && return -b VWPreBuild(a.nonempty-b.nonempty, a.w-b.w) end -function Base.:+(a::VWPreBuild, b::VWPreBuild) +function Base.:(+)(a::VWPreBuild, b::VWPreBuild) b === _vwprebuild_zero && return a a === _vwprebuild_zero && return b VWPreBuild(a.nonempty+b.nonempty, a.w+b.w) end -function Base.:-(a::VWPreBuild) +function Base.:(-)(a::VWPreBuild) a === _vwprebuild_zero && return a VWPreBuild(-a.nonempty, -a.w) end @@ -190,15 +190,15 @@ Base.zero(::Type{VersionWeight}) = VersionWeight() Base.typemin(::Type{VersionWeight}) = (x=typemin(Int); y=typemin(VWPreBuild); VersionWeight(x, x, x, y, y)) -Base.:-(a::VersionWeight, b::VersionWeight) = +Base.:(-)(a::VersionWeight, b::VersionWeight) = VersionWeight(a.major-b.major, a.minor-b.minor, a.patch-b.patch, a.prerelease-b.prerelease, a.build-b.build) -Base.:+(a::VersionWeight, b::VersionWeight) = +Base.:(+)(a::VersionWeight, b::VersionWeight) = VersionWeight(a.major+b.major, a.minor+b.minor, a.patch+b.patch, a.prerelease+b.prerelease, a.build+b.build) -Base.:-(a::VersionWeight) = +Base.:(-)(a::VersionWeight) = VersionWeight(-a.major, -a.minor, -a.patch, -a.prerelease, -a.build) diff --git a/base/sparse/cholmod.jl b/base/sparse/cholmod.jl index 2ad4ecfab2e75..f7b0bb6009deb 100644 --- a/base/sparse/cholmod.jl +++ b/base/sparse/cholmod.jl @@ -1546,36 +1546,36 @@ ldltfact(A::Union{SparseMatrixCSC{T},SparseMatrixCSC{Complex{T}}, for (T, f) in ((:Dense, :solve), (:Sparse, :spsolve)) @eval begin # Solve Lx = b and L'x=b where A = L*L' - function (\){T}(L::FactorComponent{T,:L}, B::$T) + function (\)(L::FactorComponent{T,:L}, B::$T) where T ($f)(CHOLMOD_L, Factor(L), B) end - function (\){T}(L::FactorComponent{T,:U}, B::$T) + function (\)(L::FactorComponent{T,:U}, B::$T) where T ($f)(CHOLMOD_Lt, Factor(L), B) end # Solve PLx = b and L'P'x=b where A = P*L*L'*P' - function (\){T}(L::FactorComponent{T,:PtL}, B::$T) + function (\)(L::FactorComponent{T,:PtL}, B::$T) where T F = Factor(L) ($f)(CHOLMOD_L, F, ($f)(CHOLMOD_P, F, B)) # Confusingly, CHOLMOD_P solves P'x = b end - function (\){T}(L::FactorComponent{T,:UP}, B::$T) + function (\)(L::FactorComponent{T,:UP}, B::$T) where T F = Factor(L) ($f)(CHOLMOD_Pt, F, ($f)(CHOLMOD_Lt, F, B)) end # Solve various equations for A = L*D*L' and A = P*L*D*L'*P' - function (\){T}(L::FactorComponent{T,:D}, B::$T) + function (\)(L::FactorComponent{T,:D}, B::$T) where T ($f)(CHOLMOD_D, Factor(L), B) end - function (\){T}(L::FactorComponent{T,:LD}, B::$T) + function (\)(L::FactorComponent{T,:LD}, B::$T) where T ($f)(CHOLMOD_LD, Factor(L), B) end - function (\){T}(L::FactorComponent{T,:DU}, B::$T) + function (\)(L::FactorComponent{T,:DU}, B::$T) where T ($f)(CHOLMOD_DLt, Factor(L), B) end - function (\){T}(L::FactorComponent{T,:PtLD}, B::$T) + function (\)(L::FactorComponent{T,:PtLD}, B::$T) where T F = Factor(L) ($f)(CHOLMOD_LD, F, ($f)(CHOLMOD_P, F, B)) end - function (\){T}(L::FactorComponent{T,:DUP}, B::$T) + function (\)(L::FactorComponent{T,:DUP}, B::$T) where T F = Factor(L) ($f)(CHOLMOD_Pt, F, ($f)(CHOLMOD_DLt, F, B)) end @@ -1597,7 +1597,7 @@ end Ac_ldiv_B(L::FactorComponent, B) = ctranspose(L)\B Ac_ldiv_B(L::FactorComponent, B::RowVector) = ctranspose(L)\B # ambiguity -(\){T<:VTypes}(L::Factor{T}, B::Dense{T}) = solve(CHOLMOD_A, L, B) +(\)(L::Factor{T}, B::Dense{T}) where {T<:VTypes} = solve(CHOLMOD_A, L, B) # Explicit typevars are necessary to avoid ambiguities with defs in linalg/factorizations.jl # Likewise the two following explicit Vector and Matrix defs (rather than a single VecOrMat) (\)(L::Factor{T}, B::Vector{Complex{T}}) where {T<:Float64} = complex.(L\real(B), L\imag(B)) diff --git a/base/sparse/spqr.jl b/base/sparse/spqr.jl index 9e2910422915f..c7a88f7a1ea7c 100644 --- a/base/sparse/spqr.jl +++ b/base/sparse/spqr.jl @@ -76,13 +76,13 @@ function size(F::Factorization, i::Integer) return 1 end -function free!{Tv<:VTypes}(F::Factorization{Tv}) +function free!(F::Factorization{Tv}) where Tv<:VTypes ccall((:SuiteSparseQR_C_free, :libspqr), Cint, (Ptr{Ptr{C_Factorization{Tv}}}, Ptr{Void}), &F.p, common()) == 1 end -function backslash{Tv<:VTypes}(ordering::Integer, tol::Real, A::Sparse{Tv}, B::Dense{Tv}) +function backslash(ordering::Integer, tol::Real, A::Sparse{Tv}, B::Dense{Tv}) where Tv<:VTypes m, n = size(A) if m != size(B, 1) throw(DimensionMismatch("left hand side and right hand side must have same number of rows")) @@ -94,7 +94,7 @@ function backslash{Tv<:VTypes}(ordering::Integer, tol::Real, A::Sparse{Tv}, B::D d end -function factorize{Tv<:VTypes}(ordering::Integer, tol::Real, A::Sparse{Tv}) +function factorize(ordering::Integer, tol::Real, A::Sparse{Tv}) where Tv<:VTypes s = unsafe_load(A.p) if s.stype != 0 throw(ArgumentError("stype must be zero")) @@ -121,7 +121,7 @@ function solve(system::Integer, QR::Factorization{Tv}, B::Dense{Tv}) where Tv<:V d end -function qmult{Tv<:VTypes}(method::Integer, QR::Factorization{Tv}, X::Dense{Tv}) +function qmult(method::Integer, QR::Factorization{Tv}, X::Dense{Tv}) where Tv<:VTypes mQR, nQR = size(QR) mX, nX = size(X) if (method == QTX || method == QX) && mQR != mX @@ -174,7 +174,7 @@ function (\)(F::Factorization{Float64}, B::VecOrMat{Complex{Float64}}) return reinterpret(Complex{Float64}, transpose(reshape(x, (length(x) >> 1), 2)), _ret_size(F, B)) end -function (\){T<:VTypes}(F::Factorization{T}, B::StridedVecOrMat{T}) +function (\)(F::Factorization{T}, B::StridedVecOrMat{T}) where T<:VTypes QtB = qmult(QTX, F, Dense(B)) convert(typeof(B), solve(RETX_EQUALS_B, F, QtB)) end diff --git a/base/special/gamma.jl b/base/special/gamma.jl index 778a00ae62391..479ab58adfc0a 100644 --- a/base/special/gamma.jl +++ b/base/special/gamma.jl @@ -131,8 +131,8 @@ function lgamma(z::Complex{Float64}) end return lgamma_asymptotic(Complex(x,y)) - shift end -lgamma{T<:Union{Integer,Rational}}(z::Complex{T}) = lgamma(float(z)) -lgamma{T<:Union{Float32,Float16}}(z::Complex{T}) = Complex{T}(lgamma(Complex{Float64}(z))) +lgamma(z::Complex{T}) where {T<:Union{Integer,Rational}} = lgamma(float(z)) +lgamma(z::Complex{T}) where {T<:Union{Float32,Float16}} = Complex{T}(lgamma(Complex{Float64}(z))) gamma(z::Complex) = exp(lgamma(z)) From 4f4a72fa33bfe598ebdb151d1676ae43d0866a64 Mon Sep 17 00:00:00 2001 From: Fengyang Wang Date: Tue, 25 Apr 2017 21:33:39 -0400 Subject: [PATCH 0556/1534] Elaborate on how to restore bold to REPL (#20240) --- doc/src/manual/interacting-with-julia.md | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/doc/src/manual/interacting-with-julia.md b/doc/src/manual/interacting-with-julia.md index f6834751d0131..f388251f77802 100644 --- a/doc/src/manual/interacting-with-julia.md +++ b/doc/src/manual/interacting-with-julia.md @@ -313,8 +313,9 @@ fields if the function is type stable. ## Customizing Colors -The colors used by Julia and the REPL can be customized, as well. To change the color of the Julia -prompt you can add something like the following to your `juliarc.jl` file: +The colors used by Julia and the REPL can be customized, as well. To change the +color of the Julia prompt you can add something like the following to your +`.juliarc.jl` file, which is to be placed inside your home directory: ```julia function customize_colors(repl) @@ -333,9 +334,22 @@ input and answer text by setting the appropriate field of `repl` in the `customi above (respectively, `help_color`, `shell_color`, `input_color`, and `answer_color`). For the latter two, be sure that the `envcolors` field is also set to false. +It is also possible to apply boldface formatting by using +`Base.text_colors[:bold]` as a color. For instance, to print answers in +boldface font, one can use the following as a `.juliarc.jl`: + +```julia +function customize_colors(repl) + repl.envcolors = false + repl.answer_color = Base.text_colors[:bold] +end + +atreplinit(customize_colors) +``` + You can also customize the color used to render warning and informational messages by setting the appropriate environment variables. For instance, to render error, warning, and informational -messages respectively in magenta, yellow, and cyan you can add the following to your `juliarc.jl` file: +messages respectively in magenta, yellow, and cyan you can add the following to your `.juliarc.jl` file: ```julia ENV["JULIA_ERROR_COLOR"] = :magenta From bf2d011e382ca32963a479030185493cd9d061d8 Mon Sep 17 00:00:00 2001 From: Mus M Date: Tue, 25 Apr 2017 23:22:23 -0400 Subject: [PATCH 0557/1534] Use Vector in misc places --- base/docs/utils.jl | 2 +- base/inference.jl | 2 +- base/linalg/matmul.jl | 2 +- base/pkg/resolve/versionweight.jl | 4 ++-- base/refpointer.jl | 4 ++-- base/replutil.jl | 4 ++-- base/sparse/cholmod.jl | 2 +- base/stacktraces.jl | 2 +- base/stat.jl | 2 +- base/subarray.jl | 2 +- base/threadcall.jl | 4 ++-- 11 files changed, 15 insertions(+), 15 deletions(-) diff --git a/base/docs/utils.jl b/base/docs/utils.jl index 533ae9c88fd53..0daf26f78c183 100644 --- a/base/docs/utils.jl +++ b/base/docs/utils.jl @@ -269,7 +269,7 @@ function levenshtein(s1, s2) a, b = collect(s1), collect(s2) m = length(a) n = length(b) - d = Array{Int}(m+1, n+1) + d = Matrix{Int}(m+1, n+1) d[1:m+1, 1] = 0:m d[1, 1:n+1] = 0:n diff --git a/base/inference.jl b/base/inference.jl index cb6275e0ea723..cb8b1973cd5f9 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -297,7 +297,7 @@ end #### current global inference state #### const active = Vector{Any}() # set of all InferenceState objects being processed -const nactive = Array{Int}(()) +const nactive = Array{Int,0}() nactive[] = 0 const workq = Vector{InferenceState}() # set of InferenceState objects that can make immediate progress diff --git a/base/linalg/matmul.jl b/base/linalg/matmul.jl index 83a1d8e342201..94a6cb0b7e0a8 100644 --- a/base/linalg/matmul.jl +++ b/base/linalg/matmul.jl @@ -320,7 +320,7 @@ function herk_wrapper!(C::Union{StridedMatrix{T}, StridedMatrix{Complex{T}}}, tA end # Result array does not need to be initialized as long as beta==0 - # C = Array{T}(mA, mA) + # C = Matrix{T}(mA, mA) if stride(A, 1) == stride(C, 1) == 1 && stride(A, 2) >= size(A, 1) && stride(C, 2) >= size(C, 1) return copytri!(BLAS.herk!('U', tA, one(T), A, zero(T), C), 'U', true) diff --git a/base/pkg/resolve/versionweight.jl b/base/pkg/resolve/versionweight.jl index 72df6ba95ff43..5c787dbce69b6 100644 --- a/base/pkg/resolve/versionweight.jl +++ b/base/pkg/resolve/versionweight.jl @@ -27,7 +27,7 @@ for f in (:-, :+) l0 = min(la, lb) l1 = max(la, lb) ld = la - lb - rv = Array{T}(l1) + rv = Vector{T}(l1) rf = ($f)(a.rest, b.rest) @inbounds for i = 1:l0 rv[i] = ($f)(av[i], bv[i]) @@ -111,7 +111,7 @@ function VWPreBuild(ispre::Bool, desc::Tuple{Vararg{Union{Int,String}}}) isempty(desc) && return _vwprebuild_zero desc == ("",) && return VWPreBuild(ispre ? -1 : 1, HierarchicalValue(VWPreBuildItem[])) nonempty = ispre ? -1 : 0 - w = Array{VWPreBuildItem}(length(desc)) + w = Vector{VWPreBuildItem}(length(desc)) i = 1 @inbounds for item in desc w[i] = VWPreBuildItem(item) diff --git a/base/refpointer.jl b/base/refpointer.jl index bf094e3f01220..03dff1180270f 100644 --- a/base/refpointer.jl +++ b/base/refpointer.jl @@ -97,8 +97,8 @@ function (::Type{Ref{P}}){P<:Union{Ptr,Cwstring,Cstring},T}(a::Array{T}) # Ref{P # this Array already has the right memory layout for the requested Ref return RefArray(a,1,false) # root something, so that this function is type-stable else - ptrs = Array{P}(length(a)+1) - roots = Array{Any}(length(a)) + ptrs = Vector{P}(length(a)+1) + roots = Vector{Any}(length(a)) for i = 1:length(a) root = cconvert(P, a[i]) ptrs[i] = unsafe_convert(P, root)::P diff --git a/base/replutil.jl b/base/replutil.jl index 26a17c42e4a36..f18f807cfc84f 100644 --- a/base/replutil.jl +++ b/base/replutil.jl @@ -55,8 +55,8 @@ function show(io::IO, ::MIME"text/plain", t::Associative{K,V}) where {K,V} rows -= 2 # Subtract the summary and final ⋮ continuation lines # determine max key width to align the output, caching the strings - ks = Array{AbstractString}(min(rows, length(t))) - vs = Array{AbstractString}(min(rows, length(t))) + ks = Vector{AbstractString}(min(rows, length(t))) + vs = Vector{AbstractString}(min(rows, length(t))) keylen = 0 vallen = 0 for (i, (k, v)) in enumerate(t) diff --git a/base/sparse/cholmod.jl b/base/sparse/cholmod.jl index f7b0bb6009deb..85cdb5cd4743c 100644 --- a/base/sparse/cholmod.jl +++ b/base/sparse/cholmod.jl @@ -1055,7 +1055,7 @@ function convert(::Type{Vector{T}}, D::Dense{T}) where T if size(D, 2) > 1 throw(DimensionMismatch("input must be a vector but had $(size(D, 2)) columns")) end - copy!(Array{T}(size(D, 1)), D) + copy!(Vector{T}(size(D, 1)), D) end convert(::Type{Vector}, D::Dense{T}) where {T} = convert(Vector{T}, D) diff --git a/base/stacktraces.jl b/base/stacktraces.jl index 5b5fab65731bb..6189c127f2742 100644 --- a/base/stacktraces.jl +++ b/base/stacktraces.jl @@ -124,7 +124,7 @@ inlined at that point, innermost function first. function lookup(pointer::Ptr{Void}) infos = ccall(:jl_lookup_code_address, Any, (Ptr{Void}, Cint), pointer - 1, false) isempty(infos) && return [StackFrame(empty_sym, empty_sym, -1, Nullable{Core.MethodInstance}(), true, false, convert(UInt64, pointer))] - res = Array{StackFrame}(length(infos)) + res = Vector{StackFrame}(length(infos)) for i in 1:length(infos) info = infos[i] @assert(length(info) == 7) diff --git a/base/stat.jl b/base/stat.jl index 3cf4c1664633b..0de651cd9f6de 100644 --- a/base/stat.jl +++ b/base/stat.jl @@ -61,7 +61,7 @@ show(io::IO, st::StatStruct) = print(io, "StatStruct(mode=0o$(oct(filemode(st),6 # stat & lstat functions -const stat_buf = Array{UInt8}(ccall(:jl_sizeof_stat, Int32, ())) +const stat_buf = Vector{UInt8}(ccall(:jl_sizeof_stat, Int32, ())) macro stat_call(sym, arg1type, arg) quote fill!(stat_buf,0) diff --git a/base/subarray.jl b/base/subarray.jl index 6f7a09f12fee0..9c2e31aae95e9 100644 --- a/base/subarray.jl +++ b/base/subarray.jl @@ -327,7 +327,7 @@ end # deprecate? function parentdims(s::SubArray) nd = ndims(s) - dimindex = Array{Int}(nd) + dimindex = Vector{Int}(nd) sp = strides(s.parent) sv = strides(s) j = 1 diff --git a/base/threadcall.jl b/base/threadcall.jl index 0fff4e3d5c31d..d1e0b75e65f23 100644 --- a/base/threadcall.jl +++ b/base/threadcall.jl @@ -69,7 +69,7 @@ function do_threadcall(wrapper::Function, rettype::Type, argtypes::Vector, argva # cconvert, root and unsafe_convert arguments roots = Any[] args_size = isempty(argtypes) ? 0 : sum(sizeof, argtypes) - args_arr = Array{UInt8}(args_size) + args_arr = Vector{UInt8}(args_size) ptr = pointer(args_arr) for (T, x) in zip(argtypes, argvals) y = cconvert(T, x) @@ -79,7 +79,7 @@ function do_threadcall(wrapper::Function, rettype::Type, argtypes::Vector, argva end # create return buffer - ret_arr = Array{UInt8}(sizeof(rettype)) + ret_arr = Vector{UInt8}(sizeof(rettype)) # wait for a worker thread to be available acquire(threadcall_restrictor) From 49c96ec2c6e42321c2fa8dfa2290c029f67150dc Mon Sep 17 00:00:00 2001 From: Harsha Byadarahalli Mahesh Date: Tue, 25 Apr 2017 13:45:02 +0530 Subject: [PATCH 0558/1534] Includes FFTW if USE_INTEL_MKL is enabled Setting USE_INTEL_MKL to 1 will make sure FFTW is included in the final build (Even if Base.USE_GPL_LIBS is disabled) --- base/dft.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/base/dft.jl b/base/dft.jl index d332501719b5c..49024b36bd04b 100644 --- a/base/dft.jl +++ b/base/dft.jl @@ -579,8 +579,7 @@ module FFTW correspond to [`r2r`](@ref) and [`r2r!`](@ref), respectively. """ function plan_r2r end - - Base.USE_GPL_LIBS && include(joinpath("fft", "FFTW.jl")) + (Base.USE_GPL_LIBS || Base.fftw_vendor() == :mkl) && include(joinpath("fft", "FFTW.jl")) end importall .FFTW From a957c4627a40f1f21e0bd2a2ed98598ca1f5651b Mon Sep 17 00:00:00 2001 From: Harsha Byadarahalli Mahesh Date: Wed, 26 Apr 2017 09:57:46 +0530 Subject: [PATCH 0559/1534] Adding an extra use-case to fftw_vendor function to provide support on Windows On Windows, MKL dll is called mkl_rt, fftw_vendor() was not handling this use-case, this commit makes sure fftw_vendor() handles this situation and returns appropriate value. --- base/util.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/util.jl b/base/util.jl index 4ac8709967eeb..51615f1f343ba 100644 --- a/base/util.jl +++ b/base/util.jl @@ -383,7 +383,7 @@ macro timed(ex) end function fftw_vendor() - if Base.libfftw_name == "libmkl_rt" + if Base.libfftw_name == "libmkl_rt" || (is_windows() && Base.libfftw_name == "mkl_rt") return :mkl else return :fftw From e768fc6e6cbb3c509f50c04ffa7ecde3aae53491 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Wed, 26 Apr 2017 08:36:52 -0700 Subject: [PATCH 0560/1534] Replace Array with Vector in various locations. --- base/array.jl | 2 +- base/linalg/lapack.jl | 80 +++++++++++++++++++++--------------------- base/sparse/umfpack.jl | 8 ++--- 3 files changed, 45 insertions(+), 45 deletions(-) diff --git a/base/array.jl b/base/array.jl index 5d503bd1fcc2e..ec727a6998238 100644 --- a/base/array.jl +++ b/base/array.jl @@ -1855,7 +1855,7 @@ function intersect(v1, vs...) end function union(vs...) - ret = Array{promote_eltype(vs...)}(0) + ret = Vector{promote_eltype(vs...)}(0) seen = Set() for v in vs for v_elem in v diff --git a/base/linalg/lapack.jl b/base/linalg/lapack.jl index db1c9eee7f994..e9b23bdb9443f 100644 --- a/base/linalg/lapack.jl +++ b/base/linalg/lapack.jl @@ -1208,9 +1208,9 @@ for (gelsd, gelsy, elty) in rcond = convert($elty, rcond) rnk = Vector{BlasInt}(1) info = Ref{BlasInt}() - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) - iwork = Array{BlasInt}(1) + iwork = Vector{BlasInt}(1) for i = 1:2 ccall((@blasfunc($gelsd), liblapack), Void, (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, @@ -1252,7 +1252,7 @@ for (gelsd, gelsy, elty) in jpvt = zeros(BlasInt, n) rcond = convert($elty, rcond) rnk = Vector{BlasInt}(1) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -1301,10 +1301,10 @@ for (gelsd, gelsy, elty, relty) in rcond = convert($relty, rcond) rnk = Vector{BlasInt}(1) info = Ref{BlasInt}() - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) - rwork = Array{$relty}(1) - iwork = Array{BlasInt}(1) + rwork = Vector{$relty}(1) + iwork = Vector{BlasInt}(1) for i = 1:2 ccall((@blasfunc($gelsd), liblapack), Void, (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, @@ -1347,9 +1347,9 @@ for (gelsd, gelsy, elty, relty) in jpvt = zeros(BlasInt, n) rcond = convert($relty, rcond) rnk = Vector{BlasInt}(1) - work = Array{$elty}(1) + work = Vector{$elty}(1) lwork = BlasInt(-1) - rwork = Array{$relty}(2n) + rwork = Vector{$relty}(2n) info = Ref{BlasInt}() for i = 1:2 ccall((@blasfunc($gelsy), liblapack), Void, @@ -1364,7 +1364,7 @@ for (gelsd, gelsy, elty, relty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end subsetrows(B, newB, n), rnk[1] @@ -1681,7 +1681,7 @@ for (geev, gesvd, gesdd, ggsvd, elty, relty) in end p = size(B, 1) k = Vector{BlasInt}(1) - l = Array{BlasInt}(1) + l = Vector{BlasInt}(1) lda = max(1,stride(A, 2)) ldb = max(1,stride(B, 2)) alpha = similar(A, $relty, n) @@ -1692,12 +1692,12 @@ for (geev, gesvd, gesdd, ggsvd, elty, relty) in V = jobv == 'V' ? similar(A, $elty, ldv, p) : similar(A, $elty, 0) ldq = max(1, n) Q = jobq == 'Q' ? similar(A, $elty, ldq, n) : similar(A, $elty, 0) - work = Array{$elty}(max(3n, m, p) + n) + work = Vector{$elty}(max(3n, m, p) + n) cmplx = eltype(A) <: Complex if cmplx - rwork = Array{$relty}(2n) + rwork = Vector{$relty}(2n) end - iwork = Array{BlasInt}(n) + iwork = Vector{BlasInt}(n) info = Ref{BlasInt}() if cmplx ccall((@blasfunc($ggsvd), liblapack), Void, @@ -1859,7 +1859,7 @@ for (f, elty, relty) in ((:zggsvd3_, :Complex128, :Float64), end p = size(B, 1) k = Vector{BlasInt}(1) - l = Array{BlasInt}(1) + l = Vector{BlasInt}(1) lda = max(1,stride(A, 2)) ldb = max(1,stride(B, 2)) alpha = similar(A, $relty, n) @@ -1872,8 +1872,8 @@ for (f, elty, relty) in ((:zggsvd3_, :Complex128, :Float64), Q = jobq == 'Q' ? similar(A, $elty, ldq, n) : similar(A, $elty, 0) work = Vector{$elty}(1) lwork = BlasInt(-1) - rwork = Array{$relty}(2n) - iwork = Array{BlasInt}(n) + rwork = Vector{$relty}(2n) + iwork = Vector{BlasInt}(n) info = Ref{BlasInt}() for i = 1:2 ccall((@blasfunc($f), liblapack), Void, @@ -1894,7 +1894,7 @@ for (f, elty, relty) in ((:zggsvd3_, :Complex128, :Float64), chklapackerror(info[]) if i == 1 lwork = BlasInt(work[1]) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end if m - k[1] - l[1] >= 0 @@ -2266,8 +2266,8 @@ for (laic1, elty) in throw(DimensionMismatch("vectors must have same length, but length of x is $j and length of w is $(length(w))")) end sestpr = Vector{$elty}(1) - s = Array{$elty}(1) - c = Array{$elty}(1) + s = Vector{$elty}(1) + c = Vector{$elty}(1) ccall((@blasfunc($laic1), liblapack), Void, (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{$elty}, Ptr{$elty}, Ptr{$elty}, Ptr{$elty}, @@ -2299,8 +2299,8 @@ for (laic1, elty, relty) in throw(DimensionMismatch("vectors must have same length, but length of x is $j and length of w is $(length(w))")) end sestpr = Vector{$relty}(1) - s = Array{$elty}(1) - c = Array{$elty}(1) + s = Vector{$elty}(1) + c = Vector{$elty}(1) ccall((@blasfunc($laic1), liblapack), Void, (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$relty}, Ptr{$elty}, Ptr{$elty}, Ptr{$relty}, Ptr{$elty}, @@ -3687,7 +3687,7 @@ for (stev, stebz, stegr, stein, elty) in isuppz = similar(dv, BlasInt, 2*size(Z, 2)) work = Vector{$elty}(1) lwork = BlasInt(-1) - iwork = Array{BlasInt}(1) + iwork = Vector{BlasInt}(1) liwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -3705,9 +3705,9 @@ for (stev, stebz, stegr, stein, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(work[1]) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) liwork = iwork[1] - iwork = Array{BlasInt}(liwork) + iwork = Vector{BlasInt}(liwork) end end m[] == length(w) ? w : w[1:m[]], m[] == size(Z, 2) ? Z : Z[:,1:m[]] @@ -4835,7 +4835,7 @@ for (syev, syevr, sygvd, elty) in isuppz = similar(A, BlasInt, 2*n) work = Vector{$elty}(1) lwork = BlasInt(-1) - iwork = Array{BlasInt}(1) + iwork = Vector{BlasInt}(1) liwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -4886,7 +4886,7 @@ for (syev, syevr, sygvd, elty) in w = similar(A, $elty, n) work = Vector{$elty}(1) lwork = BlasInt(-1) - iwork = Array{BlasInt}(1) + iwork = Vector{BlasInt}(1) liwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -4902,9 +4902,9 @@ for (syev, syevr, sygvd, elty) in chkargsok(info[]) if i == 1 lwork = BlasInt(work[1]) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) liwork = iwork[1] - iwork = Array{BlasInt}(liwork) + iwork = Vector{BlasInt}(liwork) end end chkposdef(info[]) @@ -4983,9 +4983,9 @@ for (syev, syevr, sygvd, elty, relty) in isuppz = similar(A, BlasInt, 2*n) work = Vector{$elty}(1) lwork = BlasInt(-1) - rwork = Array{$relty}(1) + rwork = Vector{$relty}(1) lrwork = BlasInt(-1) - iwork = Array{BlasInt}(1) + iwork = Vector{BlasInt}(1) liwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -5038,7 +5038,7 @@ for (syev, syevr, sygvd, elty, relty) in w = similar(A, $relty, n) work = Vector{$elty}(1) lwork = BlasInt(-1) - iwork = Array{BlasInt}(1) + iwork = Vector{BlasInt}(1) liwork = BlasInt(-1) rwork = Array{$relty}() lrwork = BlasInt(-1) @@ -5729,7 +5729,7 @@ for (trexc, trsen, tgsen, elty) in m = sum(select) work = Vector{$elty}(1) lwork = BlasInt(-1) - iwork = Array{BlasInt}(1) + iwork = Vector{BlasInt}(1) liwork = BlasInt(-1) info = Ref{BlasInt}() select = convert(Array{BlasInt}, select) @@ -5749,8 +5749,8 @@ for (trexc, trsen, tgsen, elty) in if i == 1 # only estimated optimal lwork, liwork lwork = BlasInt(real(work[1])) liwork = BlasInt(real(iwork[1])) - work = Array{$elty}(lwork) - iwork = Array{BlasInt}(liwork) + work = Vector{$elty}(lwork) + iwork = Vector{BlasInt}(liwork) end end T, Q, iszero(wi) ? wr : complex.(wr, wi) @@ -5795,7 +5795,7 @@ for (trexc, trsen, tgsen, elty) in lwork = BlasInt(-1) work = Vector{$elty}(1) liwork = BlasInt(-1) - iwork = Array{BlasInt}(1) + iwork = Vector{BlasInt}(1) info = Ref{BlasInt}() select = convert(Array{BlasInt}, select) for i = 1:2 @@ -5817,9 +5817,9 @@ for (trexc, trsen, tgsen, elty) in chklapackerror(info[]) if i == 1 # only estimated optimal lwork, liwork lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) liwork = BlasInt(real(iwork[1])) - iwork = Array{BlasInt}(liwork) + iwork = Vector{BlasInt}(liwork) end end S, T, complex.(alphar, alphai), beta, Q, Z @@ -5937,7 +5937,7 @@ for (trexc, trsen, tgsen, elty) in lwork = BlasInt(-1) work = Vector{$elty}(1) liwork = BlasInt(-1) - iwork = Array{BlasInt}(1) + iwork = Vector{BlasInt}(1) info = Ref{BlasInt}() select = convert(Array{BlasInt}, select) for i = 1:2 @@ -5959,9 +5959,9 @@ for (trexc, trsen, tgsen, elty) in chklapackerror(info[]) if i == 1 # only estimated optimal lwork, liwork lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) liwork = BlasInt(real(iwork[1])) - iwork = Array{BlasInt}(liwork) + iwork = Vector{BlasInt}(liwork) end end S, T, alpha, beta, Q, Z diff --git a/base/sparse/umfpack.jl b/base/sparse/umfpack.jl index a3deb6a37a567..e827fd7362b47 100644 --- a/base/sparse/umfpack.jl +++ b/base/sparse/umfpack.jl @@ -197,7 +197,7 @@ for itype in UmfpackIndexTypes @eval begin function umfpack_symbolic!(U::UmfpackLU{Float64,$itype}) if U.symbolic != C_NULL return U end - tmp = Array{Ptr{Void}}(1) + tmp = Vector{Ptr{Void}}(1) @isok ccall(($sym_r, :libumfpack), $itype, ($itype, $itype, Ptr{$itype}, Ptr{$itype}, Ptr{Float64}, Ptr{Void}, Ptr{Float64}, Ptr{Float64}), @@ -208,7 +208,7 @@ for itype in UmfpackIndexTypes end function umfpack_symbolic!(U::UmfpackLU{Complex128,$itype}) if U.symbolic != C_NULL return U end - tmp = Array{Ptr{Void}}(1) + tmp = Vector{Ptr{Void}}(1) @isok ccall(($sym_c, :libumfpack), $itype, ($itype, $itype, Ptr{$itype}, Ptr{$itype}, Ptr{Float64}, Ptr{Float64}, Ptr{Void}, Ptr{Float64}, Ptr{Float64}), @@ -220,7 +220,7 @@ for itype in UmfpackIndexTypes function umfpack_numeric!(U::UmfpackLU{Float64,$itype}) if U.numeric != C_NULL return U end if U.symbolic == C_NULL umfpack_symbolic!(U) end - tmp = Array{Ptr{Void}}(1) + tmp = Vector{Ptr{Void}}(1) status = ccall(($num_r, :libumfpack), $itype, (Ptr{$itype}, Ptr{$itype}, Ptr{Float64}, Ptr{Void}, Ptr{Void}, Ptr{Float64}, Ptr{Float64}), @@ -235,7 +235,7 @@ for itype in UmfpackIndexTypes function umfpack_numeric!(U::UmfpackLU{Complex128,$itype}) if U.numeric != C_NULL return U end if U.symbolic == C_NULL umfpack_symbolic!(U) end - tmp = Array{Ptr{Void}}(1) + tmp = Vector{Ptr{Void}}(1) status = ccall(($num_c, :libumfpack), $itype, (Ptr{$itype}, Ptr{$itype}, Ptr{Float64}, Ptr{Float64}, Ptr{Void}, Ptr{Void}, Ptr{Float64}, Ptr{Float64}), From 8e12b77a929ce9ed90b605855948dc87a01b916e Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 26 Apr 2017 11:52:26 -0400 Subject: [PATCH 0561/1534] Fix breakage caused by #21458 (#21544) * Improve code-coverage testing of event scheduler so that we would have caught this breakage in CI * Ensure that Windows libc stdio is also redirected by redirect_stdio, since jl_safe_printf is using the msvcrt-compatibility library rather than directly using the Win32 API * Stop leaking a handle to the current process to child processes --- base/event.jl | 6 +-- base/libc.jl | 21 +++++++++- base/stream.jl | 19 ++++----- src/threading.c | 2 +- test/channels.jl | 101 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 134 insertions(+), 15 deletions(-) diff --git a/base/event.jl b/base/event.jl index bbb9aea2f097a..d6aaf36263fcd 100644 --- a/base/event.jl +++ b/base/event.jl @@ -131,9 +131,9 @@ end function schedule_and_wait(t::Task, arg=nothing) t.state == :runnable || error("schedule: Task not runnable") if isempty(Workqueue) - return yieldto(t, v) + return yieldto(t, arg) else - t.result = v + t.result = arg push!(Workqueue, t) t.state = :queued end @@ -244,7 +244,7 @@ function wait() end end end - assert(false) + # unreachable end if is_windows() diff --git a/base/libc.jl b/base/libc.jl index d0414f45fd54b..3c4a93b8d65e5 100644 --- a/base/libc.jl +++ b/base/libc.jl @@ -26,7 +26,7 @@ Base.cconvert(::Type{Int32}, fd::RawFD) = fd.fd dup(x::RawFD) = RawFD(ccall((@static is_windows() ? :_dup : :dup), Int32, (Int32,), x.fd)) dup(src::RawFD, target::RawFD) = systemerror("dup", -1 == ccall((@static is_windows() ? :_dup2 : :dup2), Int32, - (Int32, Int32), src.fd, target.fd)) + (Int32, Int32), src.fd, target.fd)) # Wrapper for an OS file descriptor (for Windows) if is_windows() @@ -34,8 +34,25 @@ if is_windows() handle::Ptr{Void} # On Windows file descriptors are HANDLE's and 64-bit on 64-bit Windows end Base.cconvert(::Type{Ptr{Void}}, fd::WindowsRawSocket) = fd.handle - _get_osfhandle(fd::RawFD) = WindowsRawSocket(ccall(:_get_osfhandle,Ptr{Void},(Cint,),fd.fd)) + _get_osfhandle(fd::RawFD) = WindowsRawSocket(ccall(:_get_osfhandle, Ptr{Void}, (Cint, ), fd.fd)) _get_osfhandle(fd::WindowsRawSocket) = fd + function dup(src::WindowsRawSocket) + new_handle = Ref{Ptr{Void}}(-1) + my_process = ccall(:GetCurrentProcess, stdcall, Ptr{Void}, ()) + const DUPLICATE_SAME_ACCESS = 0x2 + status = ccall(:DuplicateHandle, stdcall, Int32, + (Ptr{Void}, Ptr{Void}, Ptr{Void}, Ptr{Ptr{Void}}, UInt32, Int32, UInt32), + my_process, src.handle, my_process, new_handle, 0, false, DUPLICATE_SAME_ACCESS) + status == 0 && error("dup failed: $(FormatMessage())") + return new_handle[] + end + function dup(src::WindowsRawSocket, target::RawFD) + fd = ccall(:_open_osfhandle, Int32, (Ptr{Void}, Int32), dup(src), 0) + dup(RawFD(fd), target) + ccall(:_close, Int32, (Int32,), fd) + nothing + end + else _get_osfhandle(fd::RawFD) = fd end diff --git a/base/stream.jl b/base/stream.jl index dc39f64082446..4c0d931e72282 100644 --- a/base/stream.jl +++ b/base/stream.jl @@ -1007,25 +1007,26 @@ for (x, writable, unix_fd, c_symbol) in @eval begin function ($_f)(stream) global $x + posix_fd = _fd(stream) @static if is_windows() - ccall(:SetStdHandle,stdcall,Int32,(Int32,Ptr{Void}), - $(-10 - unix_fd), Libc._get_osfhandle(_fd(stream)).handle) - else - dup(_fd(stream), RawFD($unix_fd)) + ccall(:SetStdHandle, stdcall, Int32, (Int32, Ptr{Void}), + $(-10 - unix_fd), Libc._get_osfhandle(posix_fd).handle) end + dup(posix_fd, RawFD($unix_fd)) $x = stream + nothing end function ($f)(handle::Union{LibuvStream,IOStream}) $(_f)(handle) unsafe_store!(cglobal($(Expr(:quote,c_symbol)),Ptr{Void}), handle.handle) - handle + return handle end function ($f)() - read,write = (PipeEndpoint(), PipeEndpoint()) - link_pipe(read,$(writable),write,$(!writable)) - ($f)($(writable? :write : :read)) - (read,write) + read, write = (PipeEndpoint(), PipeEndpoint()) + link_pipe(read, $(writable), write, $(!writable)) + ($f)($(writable ? :write : :read)) + return (read, write) end end end diff --git a/src/threading.c b/src/threading.c index b7027b5864bdf..baf4c2f808a4b 100644 --- a/src/threading.c +++ b/src/threading.c @@ -298,7 +298,7 @@ static void ti_init_master_thread(void) #ifdef _OS_WINDOWS_ if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &hMainThread, 0, - TRUE, DUPLICATE_SAME_ACCESS)) { + FALSE, DUPLICATE_SAME_ACCESS)) { jl_printf(JL_STDERR, "WARNING: failed to access handle to main thread\n"); hMainThread = INVALID_HANDLE_VALUE; } diff --git a/test/channels.jl b/test/channels.jl index 005c33585b08a..7f5d206f99e70 100644 --- a/test/channels.jl +++ b/test/channels.jl @@ -223,6 +223,7 @@ end @noinline garbage_finalizer(f) = finalizer("gar" * "bage", f) let t, run = Ref(0) gc_enable(false) + # test for finalizers trying to yield leading to failed attempts to context switch garbage_finalizer((x) -> (run[] += 1; sleep(1))) garbage_finalizer((x) -> (run[] += 1; yield())) garbage_finalizer((x) -> (run[] += 1; yieldto(@task () -> ()))) @@ -247,4 +248,104 @@ let t, run = Ref(0) error in running finalizer: ErrorException("task switch not allowed from inside gc finalizer") error in running finalizer: ErrorException("task switch not allowed from inside gc finalizer") """ + # test for invalid state in Workqueue during yield + t = @schedule nothing + t.state = :invalid + try + newstderr = redirect_stderr() + errstream = @async readstring(newstderr[1]) + yield() + finally + redirect_stderr(oldstderr) + close(newstderr[2]) + end + @test wait(errstream) == "\nWARNING: Workqueue inconsistency detected: shift!(Workqueue).state != :queued\n" +end + +# schedule_and_wait tests +let t = @schedule(nothing), + ct = current_task(), + testobject = "testobject" + @test length(Base.Workqueue) == 1 + @test Base.schedule_and_wait(ct, 8) == 8 + @test isempty(Base.Workqueue) + @test Base.schedule_and_wait(ct, testobject) === testobject +end + +# throwto tests +let t = @task(nothing), + ct = current_task(), + testerr = ErrorException("expected") + @async Base.throwto(t, testerr) + @test try + wait(t) + false + catch ex + ex + end === testerr +end + +# Timer / AsyncCondition triggering and race #12719 +let tc = Ref(0), + t = Timer(0) do t + tc[] += 1 + end + @test isopen(t) + Base.process_events(false) + @test !isopen(t) + @test tc[] == 0 + yield() + @test tc[] == 1 +end +let tc = Ref(0), + t = Timer(0) do t + tc[] += 1 + end + @test isopen(t) + close(t) + @test !isopen(t) + sleep(0.1) + @test tc[] == 0 +end +let tc = Ref(0), + async = Base.AsyncCondition() do async + tc[] += 1 + end + @test isopen(async) + ccall(:uv_async_send, Void, (Ptr{Void},), async) + Base.process_events(false) # schedule event + ccall(:uv_async_send, Void, (Ptr{Void},), async) + is_windows() && Base.process_events(false) # schedule event (windows?) + @test tc[] == 0 + yield() # consume event + @test tc[] == 1 + sleep(0.1) # no further events + @test tc[] == 1 + ccall(:uv_async_send, Void, (Ptr{Void},), async) + ccall(:uv_async_send, Void, (Ptr{Void},), async) + close(async) + @test !isopen(async) + @test tc[] == 1 + Base.process_events(false) # schedule event & then close + is_windows() && Base.process_events(false) # schedule event (windows?) + yield() # consume event & then close + @test tc[] == 2 + sleep(0.1) # no further events + @test tc[] == 2 +end +let tc = Ref(0), + async = Base.AsyncCondition() do async + tc[] += 1 + end + @test isopen(async) + ccall(:uv_async_send, Void, (Ptr{Void},), async) + close(async) + @test !isopen(async) + Base.process_events(false) # schedule event & then close + is_windows() && Base.process_events(false) # schedule event (windows) + @test tc[] == 0 + yield() # consume event & then close + @test tc[] == 1 + sleep(0.1) + @test tc[] == 1 end From 53161af5c9695182fb3f483a076b56443974efab Mon Sep 17 00:00:00 2001 From: Mus M Date: Wed, 26 Apr 2017 12:25:49 -0400 Subject: [PATCH 0562/1534] Use Vector in more misc places (#21549) --- base/dates/periods.jl | 2 +- base/distributed/macros.jl | 3 +-- base/env.jl | 2 +- base/grisu/bignums.jl | 6 +++--- base/libc.jl | 2 +- base/pkg/resolve/interface.jl | 6 +++--- base/pkg/resolve/maxsum.jl | 2 +- base/random.jl | 4 ++-- base/sparse/sparsevector.jl | 2 +- 9 files changed, 14 insertions(+), 15 deletions(-) diff --git a/base/dates/periods.jl b/base/dates/periods.jl index 6dcfab7ff96c2..1c08edfdaf385 100644 --- a/base/dates/periods.jl +++ b/base/dates/periods.jl @@ -211,7 +211,7 @@ julia> Dates.CompoundPeriod(Dates.Minute(50000)) 50000 minutes ``` """ -CompoundPeriod(p::Vector{<:Period}) = CompoundPeriod(Array{Period}(p)) +CompoundPeriod(p::Vector{<:Period}) = CompoundPeriod(Vector{Period}(p)) CompoundPeriod(t::Time) = CompoundPeriod(Period[Hour(t), Minute(t), Second(t), Millisecond(t), Microsecond(t), Nanosecond(t)]) diff --git a/base/distributed/macros.jl b/base/distributed/macros.jl index e0f7b82f1f068..0720172bcc101 100644 --- a/base/distributed/macros.jl +++ b/base/distributed/macros.jl @@ -102,7 +102,7 @@ function splitrange(N::Int, np::Int) each = div(N,np) extras = rem(N,np) nchunks = each > 0 ? np : extras - chunks = Array{UnitRange{Int}}(nchunks) + chunks = Vector{UnitRange{Int}}(nchunks) lo = 1 for i in 1:nchunks hi = lo + each - 1 @@ -203,4 +203,3 @@ macro parallel(args...) end thecall end - diff --git a/base/env.jl b/base/env.jl index 985347f37dca6..485987f1afddc 100644 --- a/base/env.jl +++ b/base/env.jl @@ -97,7 +97,7 @@ if is_windows() pos = block[1] blk = block[2] len = ccall(:wcslen, UInt, (Ptr{UInt16},), pos) - buf = Array{UInt16}(len) + buf = Vector{UInt16}(len) unsafe_copy!(pointer(buf), pos, len) env = transcode(String, buf) m = match(r"^(=?[^=]+)=(.*)$"s, env) diff --git a/base/grisu/bignums.jl b/base/grisu/bignums.jl index 14fb922edb3df..7398028b81202 100644 --- a/base/grisu/bignums.jl +++ b/base/grisu/bignums.jl @@ -47,14 +47,14 @@ const kBigitSize = 28 const kBigitMask = Chunk((1 << kBigitSize) - 1) # Every instance allocates kBigitLength chunks on the stack. Bignums cannot # grow. There are no checks if the stack-allocated space is sufficient. -const kBigitCapacity = div(kMaxSignificantBits,kBigitSize) +const kBigitCapacity = div(kMaxSignificantBits, kBigitSize) mutable struct Bignum - bigits::Array{UInt32,1} + bigits::Vector{UInt32} used_digits::Int32 exponent::Int32 function Bignum() - bigits = Array{UInt32}(kBigitCapacity) + bigits = Vector{UInt32}(kBigitCapacity) @inbounds for i = 1:kBigitCapacity bigits[i] = 0 end diff --git a/base/libc.jl b/base/libc.jl index 3c4a93b8d65e5..50da588f3665f 100644 --- a/base/libc.jl +++ b/base/libc.jl @@ -301,7 +301,7 @@ if is_windows() C_NULL, e, 0, lpMsgBuf, 0, C_NULL) p = lpMsgBuf[] len == 0 && return "" - buf = Array{UInt16}(len) + buf = Vector{UInt16}(len) unsafe_copy!(pointer(buf), p, len) ccall(:LocalFree, stdcall, Ptr{Void}, (Ptr{Void},), p) return transcode(String, buf) diff --git a/base/pkg/resolve/interface.jl b/base/pkg/resolve/interface.jl index c29b758c8a200..0fc14623562c7 100644 --- a/base/pkg/resolve/interface.jl +++ b/base/pkg/resolve/interface.jl @@ -52,7 +52,7 @@ mutable struct Interface pdict = Dict{String,Int}(pkgs[i] => i for i = 1:np) # generate spp and pvers - spp = Array{Int}(np) + spp = Vector{Int}(np) pvers = [VersionNumber[] for i = 1:np] @@ -82,11 +82,11 @@ mutable struct Interface end ## generate wveights: - vweight = Array{Vector{VersionWeight}}(np) + vweight = Vector{Vector{VersionWeight}}(np) for p0 = 1:np pvers0 = pvers[p0] spp0 = spp[p0] - vweight0 = vweight[p0] = Array{VersionWeight}(spp0) + vweight0 = vweight[p0] = Vector{VersionWeight}(spp0) for v0 = 1:spp0-1 vweight0[v0] = VersionWeight(pvers0[v0]) end diff --git a/base/pkg/resolve/maxsum.jl b/base/pkg/resolve/maxsum.jl index 1c39500273320..3bb9f71a24b11 100644 --- a/base/pkg/resolve/maxsum.jl +++ b/base/pkg/resolve/maxsum.jl @@ -240,7 +240,7 @@ function getsolution(msgs::Messages) fld = msgs.fld np = length(fld) - sol = Array{Int}(np) + sol = Vector{Int}(np) for p0 = 1:np fld0 = fld[p0] s0 = indmax(fld0) diff --git a/base/random.jl b/base/random.jl index 62e1433cef42d..fd4a5765d17a1 100644 --- a/base/random.jl +++ b/base/random.jl @@ -1506,7 +1506,7 @@ To randomly permute a arbitrary vector, see [`shuffle`](@ref) or [`shuffle!`](@ref). """ function randperm(r::AbstractRNG, n::Integer) - a = Array{typeof(n)}(n) + a = Vector{typeof(n)}(n) @assert n <= Int64(2)^52 if n == 0 return a @@ -1532,7 +1532,7 @@ Construct a random cyclic permutation of length `n`. The optional `rng` argument specifies a random number generator, see [Random Numbers](@ref). """ function randcycle(r::AbstractRNG, n::Integer) - a = Array{typeof(n)}(n) + a = Vector{typeof(n)}(n) n == 0 && return a @assert n <= Int64(2)^52 a[1] = 1 diff --git a/base/sparse/sparsevector.jl b/base/sparse/sparsevector.jl index eb513b2f9bef4..2c870762b1dc4 100644 --- a/base/sparse/sparsevector.jl +++ b/base/sparse/sparsevector.jl @@ -951,7 +951,7 @@ end function hvcat(rows::Tuple{Vararg{Int}}, X::_SparseConcatGroup...) nbr = length(rows) # number of block rows - tmp_rows = Array{SparseMatrixCSC}(nbr) + tmp_rows = Vector{SparseMatrixCSC}(nbr) k = 0 @inbounds for i = 1 : nbr tmp_rows[i] = hcat(X[(1 : rows[i]) + k]...) From 4aeb2d499686beab0e66978e8719357387dc1b25 Mon Sep 17 00:00:00 2001 From: Fabian R Lischka Date: Thu, 27 Apr 2017 00:28:44 +0800 Subject: [PATCH 0563/1534] add docstring to base/Dates, base/Pkg (#21429) * add docstring to base/Dates, base/Pkg * use jldoctest, backticks, clean up, typos * add module name on first line of docstring * add space after comma in tuples (as in 0.6) * add link to ISO 8601 wikipedia --- base/dates/Dates.jl | 30 ++++++++++++++++++++++++++++++ base/docs/Docs.jl | 10 +++++++--- base/pkg/pkg.jl | 11 +++++++++++ doc/src/manual/dates.md | 7 ++++--- 4 files changed, 52 insertions(+), 6 deletions(-) diff --git a/base/dates/Dates.jl b/base/dates/Dates.jl index c8a5321432a3a..cf5631a9f7244 100644 --- a/base/dates/Dates.jl +++ b/base/dates/Dates.jl @@ -1,5 +1,35 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license +""" + Dates + +The `Dates` module provides `Date`, `DateTime`, `Time` types, and related functions. + +The types are not aware of time zones, based on UT seconds +(86400 seconds a day, avoiding leap seconds), and +use the proleptic Gregorian calendar, as specified in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601). +For time zone functionality, see the TimeZones.jl package. + +```jldoctest +julia> dt = DateTime(2017,12,31,23,59,59,999) +2017-12-31T23:59:59.999 + +julia> d1 = Date(Dates.Month(12), Dates.Year(2017)) +2017-12-01 + +julia> d2 = Date("2017-12-31", Dates.DateFormat("y-m-d")) +2017-12-31 + +julia> Dates.yearmonthday(d2) +(2017, 12, 31) + +julia> d2-d1 +30 days +``` + +Please see the manual section on [`Date`](@ref) and [`DateTime`](@ref) +for more information. +""" module Dates importall ..Base.Operators diff --git a/base/docs/Docs.jl b/base/docs/Docs.jl index a40e1e8ee9189..d1cf074440804 100644 --- a/base/docs/Docs.jl +++ b/base/docs/Docs.jl @@ -1,8 +1,12 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license """ -The Docs module provides the `@doc` macro which can be used to set and retrieve -documentation metadata for Julia objects. Please see docs for the `@doc` macro for more + Docs + +The `Docs` module provides the `@doc` macro which can be used to set and retrieve +documentation metadata for Julia objects. + +Please see the manual section on documentation for more information. """ module Docs @@ -409,7 +413,7 @@ function summarize(io::IO, m::Module, binding) println(io, "---\n") println(io, readstring(readme)) else - println(io, "No `README.md` found for module `", m, "`.\n") + println(io, "No docstring or `README.md` found for module `", m, "`.\n") end end diff --git a/base/pkg/pkg.jl b/base/pkg/pkg.jl index af1a8ec27e31d..7d60ec9e6ce9d 100644 --- a/base/pkg/pkg.jl +++ b/base/pkg/pkg.jl @@ -1,5 +1,16 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license +""" + Pkg + +The `Pkg` module provides package management for Julia. +Use +`Pkg.status()` for a list of installed packages, +`Pkg.add("")` to add a package, +`Pkg.update()` to update the installed packages. + +Please see the manual section on packages for more information. +""" module Pkg export Dir, Types, Reqs, Cache, Read, Query, Resolve, Write, Entry diff --git a/doc/src/manual/dates.md b/doc/src/manual/dates.md index 56bf2bcdeb731..70645cacd1d93 100644 --- a/doc/src/manual/dates.md +++ b/doc/src/manual/dates.md @@ -14,11 +14,12 @@ time, and leap seconds are unnecessary and avoided. Both [`Date`](@ref) and [`DateTime`](@ref) are basically immutable `Int64` wrappers. The single `instant` field of either type is actually a `UTInstant{P}` type, which represents a continuously -increasing machine timeline based on the UT second [^1]. The [`DateTime`](@ref) type is *timezone-unaware* -(in Python parlance) or is analogous to a *LocalDateTime* in Java 8. Additional time zone functionality +increasing machine timeline based on the UT second [^1]. The [`DateTime`](@ref) +type is not aware of time zones (*naive*, in Python parlance), +analogous to a *LocalDateTime* in Java 8. Additional time zone functionality can be added through the [TimeZones.jl package](https://github.com/JuliaTime/TimeZones.jl/), which compiles the [IANA time zone database](http://www.iana.org/time-zones). Both [`Date`](@ref) and -[`DateTime`](@ref) are based on the ISO 8601 standard, which follows the proleptic Gregorian calendar. +[`DateTime`](@ref) are based on the [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) standard, which follows the proleptic Gregorian calendar. One note is that the ISO 8601 standard is particular about BC/BCE dates. In general, the last day of the BC/BCE era, 1-12-31 BC/BCE, was followed by 1-1-1 AD/CE, thus no year zero exists. The ISO standard, however, states that 1 BC/BCE is year zero, so `0000-12-31` is the day before From ff98f8a8737d74fcd540646b1f088f013feef80c Mon Sep 17 00:00:00 2001 From: kshyatt Date: Wed, 26 Apr 2017 09:37:52 -0700 Subject: [PATCH 0564/1534] Test some libgit2 warnings --- test/libgit2.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/libgit2.jl b/test/libgit2.jl index 12d981c6a6e5c..4960b57883a8b 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -729,9 +729,9 @@ mktempdir() do dir head_ann = LibGit2.GitAnnotated(repo, "master") # (fail to) merge them because we can't fastforward - @test !LibGit2.merge!(repo, [upst_ann], true) + @test_warn "WARNING: Cannot perform fast-forward merge." !LibGit2.merge!(repo, [upst_ann], true) # merge them now that we allow non-ff - @test LibGit2.merge!(repo, [upst_ann], false) + @test_warn "INFO: Review and commit merged changes." LibGit2.merge!(repo, [upst_ann], false) @test LibGit2.is_ancestor_of(string(oldhead), string(LibGit2.head_oid(repo)), repo) # go back to merge_a and rename a file @@ -744,7 +744,7 @@ mktempdir() do dir rename_flag = 0 rename_flag = LibGit2.toggle(rename_flag, 0) # turns on the find renames opt mos = LibGit2.MergeOptions(flags=rename_flag) - @test LibGit2.merge!(repo, [upst_ann], merge_opts=mos) + @test_warn "INFO: Review and commit merged changes." LibGit2.merge!(repo, [upst_ann], merge_opts=mos) finally close(repo) end @@ -1053,7 +1053,7 @@ mktempdir() do dir LibGit2.commit(repo, "add merge_file1") LibGit2.branch!(repo, "master") a_head_ann = LibGit2.GitAnnotated(repo, "branch/merge_a") - @test LibGit2.merge!(repo, [a_head_ann]) #merge returns true if successful + @test_warn "INFO: Review and commit merged changes." LibGit2.merge!(repo, [a_head_ann]) #merge returns true if successful finally close(repo) end From 95014827b2a7af787bdab7fde6d50e0034e6b154 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Wed, 26 Apr 2017 17:39:42 +0100 Subject: [PATCH 0565/1534] add some docs for QR objects, fixed an error in QRCompactWY (#21373) * add some docs for QR objects, fixed an error in QRCompactWY * add a bit more content, fix some issues * simplify qrfact doc (and fix error regarding pivoting of non-BLAS types) * remove mention of permutation from non-pivoted QR types and remove trailing blank lines within docstrings * add links to docs * Change to imperitive form * more language changes * more changes * mention size of matrix * fix type name --- base/linalg/qr.jl | 179 ++++++++++++++++++++++++++++++--------- doc/src/stdlib/linalg.md | 3 + 2 files changed, 140 insertions(+), 42 deletions(-) diff --git a/base/linalg/qr.jl b/base/linalg/qr.jl index 99f04b0059a76..51d40690f6e05 100644 --- a/base/linalg/qr.jl +++ b/base/linalg/qr.jl @@ -1,14 +1,90 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license # QR and Hessenberg Factorizations +""" + QR <: Factorization + +A QR matrix factorization stored in a packed format, typically obtained from +[`qrfact`](@ref). If ``A`` is an `m`×`n` matrix, then + +```math +A = Q R +``` + +where ``Q`` is an orthogonal/unitary matrix and ``R`` is upper triangular. +The matrix ``Q`` is stored as a sequence of Householder reflectors ``v_i`` +and coefficients ``\\tau_i`` where: + +```math +Q = \\prod_{i=1}^{\\min(m,n)} (I - \\tau_i v_i v_i^T). +``` + +The object has two fields: + +* `factors` is an `m`×`n` matrix. + - The upper triangular part contains the elements of ``R``, that is `R = + triu(F.factors)` for a `QR` object `F`. + + - The subdiagonal part contains the reflectors ``v_i`` stored in a packed format where + ``v_i`` is the ``i``th column of the matrix `V = eye(m,n) + tril(F.factors,-1)`. + +* `τ` is a vector of length `min(m,n)` containing the coefficients ``\tau_i``. + +""" struct QR{T,S<:AbstractMatrix} <: Factorization{T} factors::S τ::Vector{T} QR{T,S}(factors::AbstractMatrix{T}, τ::Vector{T}) where {T,S<:AbstractMatrix} = new(factors, τ) end QR(factors::AbstractMatrix{T}, τ::Vector{T}) where {T} = QR{T,typeof(factors)}(factors, τ) + # Note. For QRCompactWY factorization without pivoting, the WY representation based method introduced in LAPACK 3.4 +""" + QRCompactWY <: Factorization + +A QR matrix factorization stored in a compact blocked format, typically obtained from +[`qrfact`](@ref). If ``A`` is an `m`×`n` matrix, then + +```math +A = Q R +``` + +where ``Q`` is an orthogonal/unitary matrix and ``R`` is upper triangular. It is similar +to the [`QR`](@ref) format except that the orthogonal/unitary matrix ``Q`` is stored in +*Compact WY* format [^Schreiber1989], as a lower trapezoidal matrix ``V`` and an upper +triangular matrix ``T`` where + +```math +Q = \\prod_{i=1}^{\\min(m,n)} (I - \\tau_i v_i v_i^T) = I - V T V^T +``` + +such that ``v_i`` is the ``i``th column of ``V``, and ``\tau_i`` is the ``i``th diagonal +element of ``T``. + +The object has two fields: + +* `factors`, as in the [`QR`](@ref) type, is an `m`×`n` matrix. + + - The upper triangular part contains the elements of ``R``, that is `R = + triu(F.factors)` for a `QR` object `F`. + + - The subdiagonal part contains the reflectors ``v_i`` stored in a packed format such + that `V = eye(m,n) + tril(F.factors,-1)`. + +* `T` is a square matrix with `min(m,n)` columns, whose upper triangular part gives the + matrix ``T`` above (the subdiagonal elements are ignored). + +!!! note + + This format should not to be confused with the older *WY* representation + [^Bischof1987]. + + +[^Bischof1987]: C Bischof and C Van Loan, "The WY representation for products of Householder matrices", SIAM J Sci Stat Comput 8 (1987), s2-s13. [doi:10.1137/0908009](http://dx.doi.org/10.1137/0908009) + +[^Schreiber1989]: R Schreiber and C Van Loan, "A storage-efficient WY representation for products of Householder transformations", SIAM J Sci Stat Comput 10 (1989), 53-57. [doi:10.1137/0910005](http://dx.doi.org/10.1137/0910005) +""" struct QRCompactWY{S,M<:AbstractMatrix} <: Factorization{S} factors::M T::Matrix{S} @@ -16,6 +92,37 @@ struct QRCompactWY{S,M<:AbstractMatrix} <: Factorization{S} end QRCompactWY(factors::AbstractMatrix{S}, T::AbstractMatrix{S}) where {S} = QRCompactWY{S,typeof(factors)}(factors, T) +""" + QRPivoted <: Factorization + +A QR matrix factorization with column pivoting in a packed format, typically obtained from +[`qrfact`](@ref). If ``A`` is an `m`×`n` matrix, then + +```math +A P = Q R +``` + +where ``P`` is a permutation matrix, ``Q`` is an orthogonal/unitary matrix and ``R`` is +upper triangular. The matrix ``Q`` is stored as a sequence of Householder reflectors: + +```math +Q = \\prod_{i=1}^{\\min(m,n)} (I - \\tau_i v_i v_i^T). +``` + +The object has three fields: + +* `factors` is an `m`×`n` matrix. + + - The upper triangular part contains the elements of ``R``, that is `R = + triu(F.factors)` for a `QR` object `F`. + + - The subdiagonal part contains the reflectors ``v_i`` stored in a packed format where + ``v_i`` is the ``i``th column of the matrix `V = eye(m,n) + tril(F.factors,-1)`. + +* `τ` is a vector of length `min(m,n)` containing the coefficients ``\tau_i``. + +* `jpvt` is an integer vector of length `n` corresponding to the permutation ``P``. +""" struct QRPivoted{T,S<:AbstractMatrix} <: Factorization{T} factors::S τ::Vector{T} @@ -108,25 +215,28 @@ qrfact!(A::StridedMatrix) = qrfact!(A, Val{false}) """ qrfact(A, pivot=Val{false}) -> F -Computes the QR factorization of `A`. The return type of `F` depends on the element type of -`A` and whether pivoting is specified (with `pivot==Val{true}`). +Compute the QR factorization of the matrix `A`: an orthogonal (or unitary if `A` is +complex-valued) matrix `Q`, and an upper triangular matrix `R` such that + +```math +A = Q R +``` -| Return type | `eltype(A)` | `pivot` | Relationship between `F` and `A` | -|:--------------|:----------------|:-------------|:---------------------------------| -| `QR` | not `BlasFloat` | either | `A==F[:Q]*F[:R]` | -| `QRCompactWY` | `BlasFloat` | `Val{false}` | `A==F[:Q]*F[:R]` | -| `QRPivoted` | `BlasFloat` | `Val{true}` | `A[:,F[:p]]==F[:Q]*F[:R]` | +The returned object `F` stores the factorization in a packed format: -`BlasFloat` refers to any of: `Float32`, `Float64`, `Complex64` or `Complex128`. + - if `pivot == Val{true}` then `F` is a [`QRPivoted`](@ref) object, -The individual components of the factorization `F` can be accessed by indexing: + - otherwise if the element type of `A` is a BLAS type (`Float32`, `Float64`, `Complex64` + or `Complex128`), then `F` is a [`QRCompactWY`](@ref) object, -| Component | Description | `QR` | `QRCompactWY` | `QRPivoted` | -|:----------|:------------------------------------------|:----------------|:-------------------|:----------------| -| `F[:Q]` | `Q` (orthogonal/unitary) part of `QR` | ✓ (`QRPackedQ`) | ✓ (`QRCompactWYQ`) | ✓ (`QRPackedQ`) | -| `F[:R]` | `R` (upper right triangular) part of `QR` | ✓ | ✓ | ✓ | -| `F[:p]` | pivot `Vector` | | | ✓ | -| `F[:P]` | (pivot) permutation `Matrix` | | | ✓ | + - otherwise `F` is a [`QR`](@ref) object. + +The individual components of the factorization `F` can be accessed by indexing with a symbol: + + - `F[:Q]`: the orthogonal/unitary matrix `Q` + - `F[:R]`: the upper triangular matrix `R` + - `F[:p]`: the permutation vector of the pivot ([`QRPivoted`](@ref) only) + - `F[:P]`: the permutation matrix of the pivot ([`QRPivoted`](@ref) only) The following functions are available for the `QR` objects: [`size`](@ref) and [`\\`](@ref). When `A` is rectangular, `\\` will return a least squares @@ -159,33 +269,6 @@ true that minimize the memory storage requirements of products of Householder elementary reflectors, so that the `Q` and `R` matrices can be stored compactly rather as two separate dense matrices. - - The data contained in `QR` or `QRPivoted` can be used to construct the - `QRPackedQ` type, which is a compact representation of the rotation matrix: - - ```math - Q = \\prod_{i=1}^{\\min(m,n)} (I - \\tau_i v_i v_i^T) - ``` - - where ``\\tau_i`` is the scale factor and ``v_i`` is the projection vector - associated with the ``i^{th}`` Householder elementary reflector. - - The data contained in `QRCompactWY` can be used to construct the - `QRCompactWYQ` type, which is a compact representation of the rotation - matrix - - ```math - Q = I + Y T Y^T - ``` - - where `Y` is ``m \\times r`` lower trapezoidal and `T` is ``r \\times r`` - upper triangular. The *compact WY* representation [^Schreiber1989] is not - to be confused with the older, *WY* representation [^Bischof1987]. (The - LAPACK documentation uses `V` in lieu of `Y`.) - - [^Bischof1987]: C Bischof and C Van Loan, "The WY representation for products of Householder matrices", SIAM J Sci Stat Comput 8 (1987), s2-s13. [doi:10.1137/0908009](http://dx.doi.org/10.1137/0908009) - - [^Schreiber1989]: R Schreiber and C Van Loan, "A storage-efficient WY representation for products of Householder transformations", SIAM J Sci Stat Comput 10 (1989), 53-57. [doi:10.1137/0910005](http://dx.doi.org/10.1137/0910005) """ function qrfact{T}(A::AbstractMatrix{T}, arg) AA = similar(A, typeof(zero(T)/norm(one(T))), size(A)) @@ -343,6 +426,12 @@ end getq(A::QRCompactWY) = QRCompactWYQ(A.factors,A.T) getq(A::Union{QR, QRPivoted}) = QRPackedQ(A.factors,A.τ) +""" + QRPackedQ <: AbstractMatrix + +The orthogonal/unitary ``Q`` matrix of a QR factorization stored in [`QR`](@ref) or +[`QRPivoted`](@ref) format. +""" struct QRPackedQ{T,S<:AbstractMatrix} <: AbstractMatrix{T} factors::S τ::Vector{T} @@ -350,6 +439,12 @@ struct QRPackedQ{T,S<:AbstractMatrix} <: AbstractMatrix{T} end QRPackedQ(factors::AbstractMatrix{T}, τ::Vector{T}) where {T} = QRPackedQ{T,typeof(factors)}(factors, τ) +""" + QRCompactWYQ <: AbstractMatrix + +The orthogonal/unitary ``Q`` matrix of a QR factorization stored in [`QRCompactWY`](@ref) +format. +""" struct QRCompactWYQ{S, M<:AbstractMatrix} <: AbstractMatrix{S} factors::M T::Matrix{S} diff --git a/doc/src/stdlib/linalg.md b/doc/src/stdlib/linalg.md index f8dc0fe81446d..bee85bb152227 100644 --- a/doc/src/stdlib/linalg.md +++ b/doc/src/stdlib/linalg.md @@ -34,6 +34,9 @@ Base.LinAlg.qr Base.LinAlg.qr! Base.LinAlg.qrfact Base.LinAlg.qrfact! +Base.LinAlg.QR +Base.LinAlg.QRCompactWY +Base.LinAlg.QRPivoted Base.LinAlg.lqfact! Base.LinAlg.lqfact Base.LinAlg.lq From 6d76c23f701a1d8a7105b2a0bda26d5e282c56d8 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Wed, 26 Apr 2017 18:41:11 +0200 Subject: [PATCH 0566/1534] Disable FFT plan check with FFTW < 3.3.4 (#21546) fftw_sprint_plan wasn't available in FFTW 3.3.3. Hence show of a plan in FFTW 3.3.3 doesn't actually show the plan contents and the test will fail. --- test/fft.jl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/fft.jl b/test/fft.jl index 0e673ab40d2d1..63a1a2440e031 100644 --- a/test/fft.jl +++ b/test/fft.jl @@ -8,8 +8,10 @@ let a = randn(10^5,1), p1 = plan_rfft(a, flags=FFTW.ESTIMATE) @test p1*a ≈ p2*a # make sure threads are actually being used for p2 # (tests #21163). - @test !contains(string(p1), "dft-thr") - @test contains(string(p2), "dft-thr") + if FFTW.version >= v"3.3.4" + @test !contains(string(p1), "dft-thr") + @test contains(string(p2), "dft-thr") + end end # fft From c326b1caacec881519a202c849f6c900ede1d0f3 Mon Sep 17 00:00:00 2001 From: WooKyoung Noh Date: Thu, 27 Apr 2017 01:42:24 +0900 Subject: [PATCH 0567/1534] Add a test throws an error by invalid subtyping in definition (#19414) (#20548) --- test/subtype.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/subtype.jl b/test/subtype.jl index ec133c33d026b..c8cfe8668f78f 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -1071,6 +1071,11 @@ end Tuple{C20992{S, n, T, D, d} where d where D where T where n where S, Any}, Tuple{C20992, Int}) +# Issue #19414 +let ex = try struct A19414 <: Base.AbstractSet end catch e; e end + @test isa(ex, ErrorException) && ex.msg == "invalid subtyping in definition of A19414" +end + # issue #20103, OP and comments struct TT20103{X,Y} end f20103{X,Y}(::Type{TT20103{X,Y}},x::X,y::Y) = 1 From ba8e3bbb3a69564015dd33e85878d90360a16114 Mon Sep 17 00:00:00 2001 From: Fengyang Wang Date: Wed, 26 Apr 2017 13:07:02 -0400 Subject: [PATCH 0568/1534] Fix #16742, document Iterators.filter (#21550) --- base/iterators.jl | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/base/iterators.jl b/base/iterators.jl index 230909f4984c0..e193a865c62ae 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -247,6 +247,21 @@ struct Filter{F,I} itr::I end +""" + Iterators.filter(flt, itr) + +Given a predicate function `flt` and an iterable object `itr`, return an +iterable object which upon iteration yields the elements `x` of `itr` that +satisfy `flt(x)`. The order of the original iterator is preserved. + +This function is *lazy*; that is, it is guaranteed to return in ``Θ(1)`` time +and use ``Θ(1)`` additional space, and `flt` will not be called by an +invocation of `filter`. Calls to `flt` will be made when iterating over the +returned iterable object. These calls are not cached and repeated calls will be +made when reiterating. + +See [`Base.filter`](@ref) for an eager implementation of filtering for arrays. +""" filter(flt, itr) = Filter(flt, itr) start(f::Filter) = start_filter(f.flt, f.itr) From b373129e15108b73135675b77ab236ff9477a25c Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 26 Apr 2017 14:21:02 -0400 Subject: [PATCH 0569/1534] fix #21545, `<: A{T} where T` should give `where` higher precedence --- src/julia-parser.scm | 21 ++++++++++++++++++++- test/parse.jl | 7 +++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 4bd9723fce02f..aceffdb772164 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -822,7 +822,7 @@ (define (parse-term s) (parse-with-chains s parse-rational is-prec-times? '(*))) -(define (parse-rational s) (parse-LtoR s (lambda (s) (parse-where s parse-unary)) is-prec-rational?)) +(define (parse-rational s) (parse-LtoR s (lambda (s) (parse-unary-subtype s)) is-prec-rational?)) (define (parse-pipes s) (parse-LtoR s parse-range is-prec-pipe?)) @@ -900,6 +900,25 @@ (define (invalid-identifier-name? ex) (or (syntactic-op? ex) (eq? ex '....))) +;; parse `<: A where B` as `<: (A where B)` (issue #21545) +(define (parse-unary-subtype s) + (let ((op (require-token s))) + (if (or (eq? op '|<:|) (eq? op '|>:|)) + (begin (take-token s) + (let ((next (peek-token s))) + (cond ((or (closing-token? next) (newline? next) (eq? next '=)) + op) ; return operator by itself, as in (<:) + ;; parse <:{T}(x::T) or <:(x::T) like other unary operators + ((or (eqv? next #\{) (eqv? next #\( )) + (ts:put-back! s op) + (parse-where s parse-unary)) + (else + (let ((arg (parse-where s parse-unary))) + (if (and (pair? arg) (eq? (car arg) 'tuple)) + (cons op (cdr arg)) + (list op arg))))))) + (parse-where s parse-unary)))) + (define (parse-unary s) (let ((t (require-token s))) (if (closing-token? t) diff --git a/test/parse.jl b/test/parse.jl index 7528507ed7b6a..da6e4e16574de 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -1107,3 +1107,10 @@ end # issue #21440 @test parse("+(x::T,y::T) where {T} = 0") == parse("(+)(x::T,y::T) where {T} = 0") @test parse("a::b::c") == Expr(:(::), Expr(:(::), :a, :b), :c) + +# issue #21545 +f21545(::Type{<: AbstractArray{T,N} where N}) where T = T +@test f21545(Array{Int8}) === Int8 +@test parse("<:{T} where T") == Expr(:where, Expr(:curly, :(<:), :T), :T) +@test parse("<:(T) where T") == Expr(:where, Expr(:(<:), :T), :T) +@test parse("<:{T}(T) where T") == Expr(:where, Expr(:call, Expr(:curly, :(<:), :T), :T), :T) From 4dc6070bfa12df204ac8bfa6714d28045ee6a789 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 25 Apr 2017 15:23:35 -0400 Subject: [PATCH 0570/1534] don't drop profile / coverage information for function with statements inlined into them --- base/inference.jl | 1 + test/backtrace.jl | 17 +++++++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index cb6275e0ea723..a944621d21c57 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -5075,6 +5075,7 @@ function meta_elim_pass!(code::Array{Any,1}, propagate_inbounds::Bool, do_covera code[push_loc] = nothing code[i] = nothing else + prev_dbg_stack[end] = 0 push_loc_pos_stack[end] = 0 end else diff --git a/test/backtrace.jl b/test/backtrace.jl index 140d8c2098f5e..3c4d5abfb1f57 100644 --- a/test/backtrace.jl +++ b/test/backtrace.jl @@ -26,12 +26,15 @@ end # same-file inline eval(Expr(:function, Expr(:call, :test_inline_1), - Expr(:block, Expr(:line, 42, Symbol("backtrace.jl")), - Expr(:block, Expr(:meta, :push_loc, Symbol("backtrace.jl"), :inlfunc), + Expr(:block, Expr(:line, 99, Symbol("backtrace.jl")), + Expr(:block, Expr(:line, 42), + Expr(:meta, :push_loc, Symbol("backtrace.jl"), :inlfunc), Expr(:line, 37), Expr(:call, :throw, "foo"), - Expr(:meta, :pop_loc))))) + Expr(:meta, :pop_loc), + Expr(:line, 99))))) +@test functionloc(test_inline_1) == ("backtrace.jl", 99) try test_inline_1() error("unexpected") @@ -48,12 +51,14 @@ end # different-file inline const absfilepath = is_windows() ? "C:\\foo\\bar\\baz.jl" : "/foo/bar/baz.jl" eval(Expr(:function, Expr(:call, :test_inline_2), - Expr(:block, Expr(:line, 99, Symbol("backtrace.jl")), + Expr(:block, Expr(:line, 81, Symbol("backtrace.jl")), Expr(:block, Expr(:meta, :push_loc, Symbol(absfilepath)), Expr(:line, 111), Expr(:call, :throw, "foo"), - Expr(:meta, :pop_loc))))) + Expr(:meta, :pop_loc), + Expr(:line, 99))))) +@test functionloc(test_inline_2) == ("backtrace.jl", 81) try test_inline_2() error("unexpected") @@ -61,7 +66,7 @@ catch err lkup = get_bt_frames(:test_inline_2, catch_backtrace()) @test length(lkup) == 2 @test endswith(string(lkup[2].file), "backtrace.jl") - @test lkup[2].line == 99 + @test lkup[2].line == 81 @test string(lkup[1].file) == absfilepath @test lkup[1].line == 111 end From 261093c87f10786e95ab9725f50a1d78aa42b2fc Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 26 Apr 2017 16:28:17 -0400 Subject: [PATCH 0571/1534] fix #21568, crash on certain out-of-scope method adds --- src/julia-syntax.scm | 8 ++++---- test/core.jl | 10 ++++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index c5f801b0795dc..eb5ad37cd525a 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -3084,10 +3084,10 @@ f(x) = yt(x) (newlam (renumber-slots-and-labels (linearize (car exprs))))) `(toplevel-butlast ,@top-stmts - ,@sp-inits - (method ,name ,(cl-convert sig fname lam namemap toplevel interp) - ,(julia-expand-macros `(quote ,newlam)) - ,(last e)))))) + (block ,@sp-inits + (method ,name ,(cl-convert sig fname lam namemap toplevel interp) + ,(julia-expand-macros `(quote ,newlam)) + ,(last e))))))) ;; local case - lift to a new type at top level (let* ((exists (get namemap name #f)) (type-name (or exists diff --git a/test/core.jl b/test/core.jl index 9188117f87e48..f1b4867abb50d 100644 --- a/test/core.jl +++ b/test/core.jl @@ -4871,3 +4871,13 @@ let letvar::Int = 2 letvar = 3.0 @test letvar === 3 end + +# issue #21568 +f21568() = 0 +function foo21568() + y = 1 + global f21568 + f21568{T<:Real}(x::AbstractArray{T,1}) = y +end +foo21568() +@test f21568([0]) == 1 From 530496eee918e69b99da6319b3dfd4fcb5a0f870 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Wed, 26 Apr 2017 15:23:48 +0200 Subject: [PATCH 0572/1534] add method to isposdef! for Hermitian and Symmetric --- base/linalg/symmetric.jl | 2 ++ test/linalg/symmetric.jl | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/base/linalg/symmetric.jl b/base/linalg/symmetric.jl index 83485d2701469..2f576fc147c2b 100644 --- a/base/linalg/symmetric.jl +++ b/base/linalg/symmetric.jl @@ -264,6 +264,8 @@ det(A::Symmetric) = det(bkfact(A)) inv{T<:BlasFloat,S<:StridedMatrix}(A::Hermitian{T,S}) = Hermitian{T,S}(inv(bkfact(A)), A.uplo) inv{T<:BlasFloat,S<:StridedMatrix}(A::Symmetric{T,S}) = Symmetric{T,S}(inv(bkfact(A)), A.uplo) +isposdef!(A::HermOrSym{<:BlasFloat,<:StridedMatrix}) = ishermitian(A) && LAPACK.potrf!(A.uplo, A.data)[2] == 0 + eigfact!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}) = Eigen(LAPACK.syevr!('V', 'A', A.uplo, A.data, 0.0, 0.0, 0, 0, -1.0)...) # Because of #6721 it is necessary to specify the parameters explicitly here. eigfact(A::RealHermSymComplexHerm{<:Real}) = (T = eltype(A); S = promote_type(Float32, typeof(zero(T)/norm(one(T)))); eigfact!(S != T ? convert(AbstractMatrix{S}, A) : copy(A))) diff --git a/test/linalg/symmetric.jl b/test/linalg/symmetric.jl index cc03937982cde..bf2a045ba7b06 100644 --- a/test/linalg/symmetric.jl +++ b/test/linalg/symmetric.jl @@ -129,6 +129,14 @@ let n=10 @test det(a + a.') ≈ det(Symmetric(a + a.', :U)) @test det(a + a.') ≈ det(Symmetric(a + a.', :L)) + # isposdef[!] + @test isposdef(Symmetric(asym)) == isposdef(full(Symmetric(asym))) + @test isposdef(Hermitian(asym)) == isposdef(full(Hermitian(asym))) + if eltya != Int + @test isposdef!(Symmetric(copy(asym))) == isposdef(full(Symmetric(asym))) + @test isposdef!(Hermitian(copy(asym))) == isposdef(full(Hermitian(asym))) + end + # rank let A = a[:,1:5]*a[:,1:5]' # Make sure A is Hermitian even in the present of rounding error From f7dbb05eed579a1cdfc41e112915a069dd6ac1d5 Mon Sep 17 00:00:00 2001 From: kshyatt Date: Wed, 26 Apr 2017 15:53:21 -0700 Subject: [PATCH 0573/1534] Add a test for a failing rebase case --- test/libgit2.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/libgit2.jl b/test/libgit2.jl index ca9192fd4a21e..a9ca74ce8e1b5 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -799,6 +799,10 @@ mktempdir() do dir LibGit2.set!(cfg, "user.name", "AAAA") LibGit2.set!(cfg, "user.email", "BBBB@BBBB.COM") + # If upstream argument is empty, libgit2 will look for tracking + # information. If the current branch isn't tracking any upstream + # the rebase should fail. + @test_throws LibGit2.GitError LibGit2.rebase!(repo) # Try rebasing on master instead newhead = LibGit2.rebase!(repo, master_branch) @test newhead == head_oid From 9b1aeb1e2573c564b62d2b6dff06ab78d0e73b97 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 26 Apr 2017 20:02:03 -0400 Subject: [PATCH 0574/1534] fix parsing and lowering of multi-line anon functions with `where` --- src/julia-parser.scm | 35 +++++++++++++++++++++++------------ src/julia-syntax.scm | 7 ++++++- test/parse.jl | 13 +++++++++++++ 3 files changed, 42 insertions(+), 13 deletions(-) diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 4bd9723fce02f..a51ff05b2cb16 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -1137,6 +1137,16 @@ (and (eq? (car sig) 'where) (valid-func-sig? paren (cadr sig)))))) +(define (unwrap-where x) + (if (and (pair? x) (eq? (car x) 'where)) + (unwrap-where (cadr x)) + x)) + +(define (rewrap-where x w) + (if (and (pair? w) (eq? (car w) 'where)) + (list 'where (rewrap-where x (cadr w)) (caddr w)) + x)) + (define (parse-struct-def s mut? word) (if (reserved-word? (peek-token s)) (error (string "invalid type name \"" (take-token s) "\""))) @@ -1258,18 +1268,19 @@ (error (string "expected \"end\" in definition of function \"" sig "\""))) (take-token s) `(function ,sig)) - (let* ((def (if (or (symbol? sig) - (and (pair? sig) (eq? (car sig) '|::|) - (symbol? (cadr sig)))) - (if paren - ;; in "function (x)" the (x) is a tuple - `(tuple ,sig) - ;; function foo => syntax error - (error (string "expected \"(\" in " word " definition"))) - (if (not (valid-func-sig? paren sig)) - (error (string "expected \"(\" in " word " definition")) - sig))) - (body (parse-block s))) + (let* ((usig (unwrap-where sig)) + (def (if (or (symbol? usig) + (and (pair? usig) (eq? (car usig) '|::|) + (symbol? (cadr usig)))) + (if paren + ;; in "function (x)" the (x) is a tuple + (rewrap-where `(tuple ,usig) sig) + ;; function foo => syntax error + (error (string "expected \"(\" in " word " definition"))) + (if (not (valid-func-sig? paren sig)) + (error (string "expected \"(\" in " word " definition")) + sig))) + (body (parse-block s))) (expect-end s word) (list word def body))))) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index c5f801b0795dc..b44447a261497 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -969,8 +969,13 @@ (list* g (if isamp `(& ,ca) ca) C)))))))) (define (expand-function-def e) ;; handle function or stagedfunction + (define (just-arglist? ex) + (and (pair? ex) + (or (memq (car ex) '(tuple block)) + (and (eq? (car ex) 'where) + (just-arglist? (cadr ex)))))) (let ((name (cadr e))) - (if (and (pair? name) (memq (car name) '(tuple block))) + (if (just-arglist? name) (expand-forms (cons '-> (cdr e))) (expand-function-def- e)))) diff --git a/test/parse.jl b/test/parse.jl index 7528507ed7b6a..6d5716dbedb4f 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -1018,6 +1018,19 @@ end short_where_call = :(f(x::T) where T = T) @test short_where_call.args[2].head == :block +# `where` with multi-line anonymous functions +let f = function (x::T) where T + T + end + @test f(:x) === Symbol +end + +let f = function (x::T, y::S) where T<:S where S + (T,S) + end + @test f(0,1) === (Int,Int) +end + # issue #20541 @test parse("[a .!b]") == Expr(:hcat, :a, Expr(:call, :(.!), :b)) From 2d803f30ef2ca9eb143da9b32a6243d31e85aa18 Mon Sep 17 00:00:00 2001 From: Martin Holters Date: Thu, 27 Apr 2017 06:03:47 +0200 Subject: [PATCH 0575/1534] Only evaluate `fexpr` in `fexpr(kw=...)` once (#21519) * Only evaluate `fexpr` in `fexpr(kw=...)` once Lower e.g. `get_inner()(kw=1)` to ``` SSAValue(n) = get_inner() ((Core.kwfunc)(SSAValue(n)))((Base.vector_any)(:kw, 1), SSAValue(n)) ``` instead of ``` ((Core.kwfunc)(get_inner()))((Base.vector_any)(:kw, 1), get_inner()) ``` as the latter would call `get_inner` twice. Fixes #21518. --- src/julia-syntax.scm | 11 +++++++---- test/keywordargs.jl | 10 ++++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index eb5ad37cd525a..a0b2ced82bbdb 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -1425,14 +1425,17 @@ (reverse a)))))) ;; lower function call containing keyword arguments -(define (lower-kw-call f kw pa) +(define (lower-kw-call fexpr kw pa) (let ((container (make-ssavalue))) (let loop ((kw kw) (initial-kw '()) ;; keyword args before any splats (stmts '()) (has-kw #f)) ;; whether there are definitely >0 kwargs (if (null? kw) - (if (null? stmts) + (let ((f (if (sym-ref? fexpr) fexpr (make-ssavalue)))) + `(block + ,@(if (eq? f fexpr) '() `((= ,f, fexpr))) + ,(if (null? stmts) `(call (call (core kwfunc) ,f) (call (top vector_any) ,@(reverse initial-kw)) ,f ,@pa) `(block (= ,container (call (top vector_any) ,@(reverse initial-kw))) @@ -1446,8 +1449,8 @@ ,@stmts (if (call (top isempty) ,container) (call ,f ,@pa) - (call (call (core kwfunc) ,f) ,container ,f ,@pa))))))) - (let ((arg (car kw))) + (call (call (core kwfunc) ,f) ,container ,f ,@pa))))))))) + (let ((arg (car kw))) (cond ((and (pair? arg) (eq? (car arg) 'parameters)) (error "more than one semicolon in argument list")) ((kwarg? arg) diff --git a/test/keywordargs.jl b/test/keywordargs.jl index 5a0abed112104..0ac76fa7bcaaf 100644 --- a/test/keywordargs.jl +++ b/test/keywordargs.jl @@ -275,3 +275,13 @@ end f21510(; a::ANY = 2) = a @test f21510(a=:b) == :b @test f21510() == 2 + +# issue #21518 +let a = 0 + f21518(;kw=nothing) = kw + g21518() = (a+=1; f21518) + g21518()(kw=1) + @test a == 1 + g21518()(; :kw=>1) + @test a == 2 +end From 2815324075921fdc3b0b4a37e010c6f78ed84827 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Thu, 27 Apr 2017 01:08:52 -0400 Subject: [PATCH 0576/1534] add invokelatest to circumvent world-age problems (#19784) add invokelatest function to work around world-age problems (#19774) without using eval use invokelatest in libuv getaddrinfo callback update manual to mention invokelatest --- NEWS.md | 4 ++++ base/essentials.jl | 12 ++++++++++++ base/socket.jl | 6 +++--- doc/src/manual/methods.md | 11 +++-------- doc/src/stdlib/base.md | 1 + src/builtin_proto.h | 1 + src/builtins.c | 13 +++++++++++++ src/codegen.cpp | 1 + src/dump.c | 2 +- test/misc.jl | 9 +++++++++ 10 files changed, 48 insertions(+), 12 deletions(-) diff --git a/NEWS.md b/NEWS.md index c86332d51a338..886602c3c6845 100644 --- a/NEWS.md +++ b/NEWS.md @@ -322,6 +322,10 @@ Library improvements * `logging` can now be used to redirect `info`, `warn`, and `error` messages either universally or on a per-module/function basis ([#16213]). + * New function `Base.invokelatest(f, args...)` to call the latest version + of a function in circumstances where an older version may be called + instead (e.g. in a function calling `eval`) ([#19784]). + * A new `iszero(x)` function was added, to quickly check whether `x` is zero (or is all zeros, for an array) ([#19950]). diff --git a/base/essentials.jl b/base/essentials.jl index b5af539f7edf0..145ea6bb50486 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -337,3 +337,15 @@ function vector_any(xs::ANY...) end isempty(itr) = done(itr, start(itr)) + +""" + invokelatest(f, args...) + +Calls `f(args...)`, but guarantees that the most recent method of `f` +will be executed. This is useful in specialized circumstances, +e.g. long-running event loops or callback functions that may +call obsolete versions of a function `f`. +(The drawback is that `invokelatest` is somewhat slower than calling +`f` directly, and the type of the result cannot be inferred by the compiler.) +""" +invokelatest(f, args...) = Core._apply_latest(f, args) diff --git a/base/socket.jl b/base/socket.jl index 57a83640a2a57..14bb412a94406 100644 --- a/base/socket.jl +++ b/base/socket.jl @@ -589,18 +589,18 @@ function uv_getaddrinfocb(req::Ptr{Void}, status::Cint, addrinfo::Ptr{Void}) cb = unsafe_pointer_to_objref(data)::Function pop!(callback_dict,cb) # using pop forces an error if cb not in callback_dict if status != 0 || addrinfo == C_NULL - cb(UVError("uv_getaddrinfocb received an unexpected status code", status)) + invokelatest(cb, UVError("uv_getaddrinfocb received an unexpected status code", status)) else freeaddrinfo = addrinfo while addrinfo != C_NULL sockaddr = ccall(:jl_sockaddr_from_addrinfo, Ptr{Void}, (Ptr{Void},), addrinfo) if ccall(:jl_sockaddr_is_ip4, Int32, (Ptr{Void},), sockaddr) == 1 - cb(IPv4(ntoh(ccall(:jl_sockaddr_host4, UInt32, (Ptr{Void},), sockaddr)))) + invokelatest(cb, IPv4(ntoh(ccall(:jl_sockaddr_host4, UInt32, (Ptr{Void},), sockaddr)))) break #elseif ccall(:jl_sockaddr_is_ip6, Int32, (Ptr{Void},), sockaddr) == 1 # host = Vector{UInt128}(1) # scope_id = ccall(:jl_sockaddr_host6, UInt32, (Ptr{Void}, Ptr{UInt128}), sockaddr, host) - # cb(IPv6(ntoh(host[1]))) + # invokelatest(cb, IPv6(ntoh(host[1]))) # break end addrinfo = ccall(:jl_next_from_addrinfo, Ptr{Void}, (Ptr{Void},), addrinfo) diff --git a/doc/src/manual/methods.md b/doc/src/manual/methods.md index 330ec3a7746b8..1b46b99ab47c7 100644 --- a/doc/src/manual/methods.md +++ b/doc/src/manual/methods.md @@ -455,17 +455,12 @@ In the example above, we see that the "current world" (in which the method `newf is one greater than the task-local "runtime world" that was fixed when the execution of `tryeval` started. Sometimes it is necessary to get around this (for example, if you are implementing the above REPL). -Well, don't despair, since there's an easy solution: just call `eval` a second time. -For example, here we create a zero-argument closure over `ans` and `eval` a call to it: +Fortunately, there is an easy solution: call the function using [`Base.invokelatest`](@ref): ```jldoctest julia> function tryeval2() - ans = (@eval newfun2() = 1) - res = eval(Expr(:call, - function() - return ans() + 1 - end)) - return res + @eval newfun2() = 2 + Base.invokelatest(newfun2) end tryeval2 (generic function with 1 method) diff --git a/doc/src/stdlib/base.md b/doc/src/stdlib/base.md index 770ab55f9131b..c19859b07cf98 100644 --- a/doc/src/stdlib/base.md +++ b/doc/src/stdlib/base.md @@ -121,6 +121,7 @@ Base.instances Base.method_exists Core.applicable Core.invoke +Base.invokelatest Base.:(|>) Base.:(∘) ``` diff --git a/src/builtin_proto.h b/src/builtin_proto.h index 001cf160ea15a..754e9824ac4b0 100644 --- a/src/builtin_proto.h +++ b/src/builtin_proto.h @@ -23,6 +23,7 @@ DECLARE_BUILTIN(throw); DECLARE_BUILTIN(is); DECLARE_BUILTIN(typeof); DECLARE_BUILTIN(sizeof); DECLARE_BUILTIN(issubtype); DECLARE_BUILTIN(isa); DECLARE_BUILTIN(_apply); DECLARE_BUILTIN(_apply_pure); +DECLARE_BUILTIN(_apply_latest); DECLARE_BUILTIN(isdefined); DECLARE_BUILTIN(nfields); DECLARE_BUILTIN(tuple); DECLARE_BUILTIN(svec); DECLARE_BUILTIN(getfield); DECLARE_BUILTIN(setfield); diff --git a/src/builtins.c b/src/builtins.c index e117eae5dd54e..e7f29e0051e73 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -454,6 +454,18 @@ JL_CALLABLE(jl_f__apply_pure) return ret; } +// this is like `_apply`, but always runs in the newest world +JL_CALLABLE(jl_f__apply_latest) +{ + jl_ptls_t ptls = jl_get_ptls_states(); + size_t last_age = ptls->world_age; + if (!ptls->in_pure_callback) + ptls->world_age = jl_world_counter; + jl_value_t *ret = jl_f__apply(NULL, args, nargs); + ptls->world_age = last_age; + return ret; +} + // eval ----------------------------------------------------------------------- JL_DLLEXPORT jl_value_t *jl_toplevel_eval_in(jl_module_t *m, jl_value_t *ex) @@ -1089,6 +1101,7 @@ void jl_init_primitives(void) add_builtin_func("apply_type", jl_f_apply_type); add_builtin_func("_apply", jl_f__apply); add_builtin_func("_apply_pure", jl_f__apply_pure); + add_builtin_func("_apply_latest", jl_f__apply_latest); add_builtin_func("_expr", jl_f__expr); add_builtin_func("svec", jl_f_svec); diff --git a/src/codegen.cpp b/src/codegen.cpp index 178f2675e3c44..e55424d47170e 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -6761,6 +6761,7 @@ static void init_julia_llvm_env(Module *m) builtin_func_map[jl_f_typeassert] = jlcall_func_to_llvm("jl_f_typeassert", &jl_f_typeassert, m); builtin_func_map[jl_f__apply] = jlcall_func_to_llvm("jl_f__apply", &jl_f__apply, m); builtin_func_map[jl_f__apply_pure] = jlcall_func_to_llvm("jl_f__apply_pure", &jl_f__apply_pure, m); + builtin_func_map[jl_f__apply_latest] = jlcall_func_to_llvm("jl_f__apply_latest", &jl_f__apply_latest, m); builtin_func_map[jl_f_throw] = jlcall_func_to_llvm("jl_f_throw", &jl_f_throw, m); builtin_func_map[jl_f_tuple] = jlcall_func_to_llvm("jl_f_tuple", &jl_f_tuple, m); builtin_func_map[jl_f_svec] = jlcall_func_to_llvm("jl_f_svec", &jl_f_svec, m); diff --git a/src/dump.c b/src/dump.c index 7a32a63715d83..63fb83a042d91 100644 --- a/src/dump.c +++ b/src/dump.c @@ -77,7 +77,7 @@ static htable_t fptr_to_id; static const jl_fptr_t id_to_fptrs[] = { NULL, NULL, jl_f_throw, jl_f_is, jl_f_typeof, jl_f_issubtype, jl_f_isa, - jl_f_typeassert, jl_f__apply, jl_f__apply_pure, jl_f_isdefined, + jl_f_typeassert, jl_f__apply, jl_f__apply_pure, jl_f__apply_latest, jl_f_isdefined, jl_f_tuple, jl_f_svec, jl_f_intrinsic_call, jl_f_invoke_kwsorter, jl_f_getfield, jl_f_setfield, jl_f_fieldtype, jl_f_nfields, jl_f_arrayref, jl_f_arrayset, jl_f_arraysize, jl_f_apply_type, diff --git a/test/misc.jl b/test/misc.jl index f03edaa1ea34b..197cd00f0fa86 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -669,3 +669,12 @@ if Bool(parse(Int,(get(ENV, "JULIA_TESTFULL", "0")))) @test_throws StackOverflowError f_19433(+, 1, 2) end end + +# invokelatest function for issue #19774 +issue19774(x) = 1 +let foo() = begin + eval(:(issue19774(x::Int) = 2)) + return Base.invokelatest(issue19774, 0) + end + @test foo() == 2 +end From 638fa886d7bae9f74edb3da6350c5f38857eb3db Mon Sep 17 00:00:00 2001 From: Fengyang Wang Date: Thu, 27 Apr 2017 01:33:40 -0400 Subject: [PATCH 0577/1534] Remove obsolete comparison LHS code --- src/julia-syntax.scm | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 3828112cf4b60..1adb8c862e3b4 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -1865,18 +1865,13 @@ (define lhs (cadr e)) (define (function-lhs? lhs) (and (pair? lhs) - (or (and (eq? (car lhs) 'comparison) (length= lhs 4)) - (eq? (car lhs) 'call) + (or (eq? (car lhs) 'call) (eq? (car lhs) 'where) (and (eq? (car lhs) '|::|) (pair? (cadr lhs)) (eq? (car (cadr lhs)) 'call))))) (define (assignment-to-function lhs e) ;; convert '= expr to 'function expr - (if (eq? (car lhs) 'comparison) - ;; allow defining functions that use comparison syntax - (list* 'function - `(call ,(caddr lhs) ,(cadr lhs) ,(cadddr lhs)) (cddr e)) - (cons 'function (cdr e)))) + (cons 'function (cdr e))) (cond ((function-lhs? lhs) (expand-forms (assignment-to-function lhs e))) From 5d0e0650aaabe6ac0da51b179d705fd09ce9d455 Mon Sep 17 00:00:00 2001 From: Fengyang Wang Date: Thu, 27 Apr 2017 02:06:24 -0400 Subject: [PATCH 0578/1534] Unescape A in A=B keyword argument --- src/macroexpand.scm | 4 ++-- test/parse.jl | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/macroexpand.scm b/src/macroexpand.scm index 2258a8b41f4d1..62d6b611bf097 100644 --- a/src/macroexpand.scm +++ b/src/macroexpand.scm @@ -270,12 +270,12 @@ ,(if inarg (resolve-expansion-vars- (cadr (cadr e)) env m inarg) ;; in keyword arg A=B, don't transform "A" - (cadr (cadr e))) + (unescape (cadr (cadr e)))) ,(resolve-expansion-vars- (caddr (cadr e)) env m inarg)) ,(resolve-expansion-vars- (caddr e) env m inarg)) `(kw ,(if inarg (resolve-expansion-vars- (cadr e) env m inarg) - (cadr e)) + (unescape (cadr e))) ,(resolve-expansion-vars- (caddr e) env m inarg)))) ((let) diff --git a/test/parse.jl b/test/parse.jl index d46ba3ea62fa2..4570ba7248f62 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -1127,3 +1127,11 @@ f21545(::Type{<: AbstractArray{T,N} where N}) where T = T @test parse("<:{T} where T") == Expr(:where, Expr(:curly, :(<:), :T), :T) @test parse("<:(T) where T") == Expr(:where, Expr(:(<:), :T), :T) @test parse("<:{T}(T) where T") == Expr(:where, Expr(:call, Expr(:curly, :(<:), :T), :T), :T) + +# issue #21586 +macro m21586(x) + Expr(:kw, esc(x), 42) +end + +f21586(; @m21586(a), @m21586(b)) = a + b +@test f21586(a=10) == 52 From bd804ee3224d8fddb4e3d33eb053922fb33af079 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sat, 22 Apr 2017 19:48:59 -0400 Subject: [PATCH 0579/1534] improvements to serializer --- base/distributed/clusterserialize.jl | 3 +- base/serialize.jl | 407 +++++++++++++++++---------- test/serialize.jl | 17 +- 3 files changed, 275 insertions(+), 152 deletions(-) diff --git a/base/distributed/clusterserialize.jl b/base/distributed/clusterserialize.jl index 9f010b79d7f96..6dca89ec15365 100644 --- a/base/distributed/clusterserialize.jl +++ b/base/distributed/clusterserialize.jl @@ -10,6 +10,7 @@ mutable struct ClusterSerializer{I<:IO} <: AbstractSerializer io::I counter::Int table::ObjectIdDict + pending_refs::Vector{Int} pid::Int # Worker we are connected to. tn_obj_sent::Set{UInt64} # TypeName objects sent @@ -19,7 +20,7 @@ mutable struct ClusterSerializer{I<:IO} <: AbstractSerializer anonfunc_id::UInt64 function ClusterSerializer{I}(io::I) where I<:IO - new(io, 0, ObjectIdDict(), Base.worker_id_from_socket(io), + new(io, 0, ObjectIdDict(), Int[], Base.worker_id_from_socket(io), Set{UInt64}(), Dict{UInt64, UInt64}(), Dict{UInt64, Vector{Symbol}}(), 0) end end diff --git a/base/serialize.jl b/base/serialize.jl index 1e7277dd9ca63..199c452b1cc4f 100644 --- a/base/serialize.jl +++ b/base/serialize.jl @@ -2,7 +2,7 @@ module Serializer -import Base: GMP, Bottom, unsafe_convert, uncompressed_ast, datatype_pointerfree +import Base: GMP, Bottom, unsafe_convert, uncompressed_ast import Core: svec using Base: ViewIndex, Slice, index_lengths, unwrap_unionall @@ -12,8 +12,9 @@ mutable struct SerializationState{I<:IO} <: AbstractSerializer io::I counter::Int table::ObjectIdDict + pending_refs::Vector{Int} known_object_data::Dict{UInt64,Any} - SerializationState{I}(io::I) where I<:IO = new(io, 0, ObjectIdDict(), Dict{UInt64,Any}()) + SerializationState{I}(io::I) where I<:IO = new(io, 0, ObjectIdDict(), Int[], Dict{UInt64,Any}()) end SerializationState(io::IO) = SerializationState{typeof(io)}(io) @@ -22,74 +23,103 @@ SerializationState(io::IO) = SerializationState{typeof(io)}(io) # types AbstractSerializer and Serializer # defined in dict.jl +const n_int_literals = 33 +const n_reserved_slots = 12 + const TAGS = Any[ - Symbol, Int8, UInt8, Int16, UInt16, Int32, UInt32, - Int64, UInt64, Int128, UInt128, Float32, Float64, Char, Ptr, - DataType, Union, TypeName, Tuple, Array, Expr, - #LongSymbol, LongTuple, LongExpr, - Symbol, Tuple, Expr, # dummy entries, intentionally shadowed by earlier ones - LineNumberNode, Slot, LabelNode, GotoNode, - QuoteNode, CodeInfo, TypeVar, Core.Box, Core.MethodInstance, - Module, #=UndefRefTag=#Symbol, Task, String, Float16, - SimpleVector, #=BackrefTag=#Symbol, Method, GlobalRef, UnionAll, - - (), Bool, Any, :Any, Bottom, Core.TypeofBottom, :reserved22, Type, - :Array, :TypeVar, :Box, - :lambda, :body, :return, :call, Symbol("::"), - :(=), :null, :gotoifnot, :A, :B, :C, :M, :N, :T, :S, :X, :Y, - :a, :b, :c, :d, :e, :f, :g, :h, :i, :j, :k, :l, :m, :n, :o, - :p, :q, :r, :s, :t, :u, :v, :w, :x, :y, :z, - :add_int, :sub_int, :mul_int, :add_float, :sub_float, - :mul_float, :bitcast, :box, - :eq_int, :slt_int, :sle_int, :ne_int, - :arrayset, :arrayref, - :Core, :Base, svec(), Tuple{}, - :reserved17, :reserved18, :reserved19, :reserved20, - false, true, nothing, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32 + Symbol, Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128, + Float16, Float32, Float64, Char, DataType, Union, UnionAll, TypeName, Tuple, + Array, Expr, LineNumberNode, LabelNode, GotoNode, QuoteNode, CodeInfo, TypeVar, + Core.Box, Core.MethodInstance, Module, Task, String, SimpleVector, Method, + GlobalRef, SlotNumber, TypedSlot, NewvarNode, SSAValue, + + # dummy entries for tags that don't correspond directly to types + Symbol, # UNDEFREF_TAG + Symbol, # BACKREF_TAG + Symbol, # LONGBACKREF_TAG + Symbol, # SHORTBACKREF_TAG + Symbol, # LONGTUPLE_TAG + Symbol, # LONGSYMBOL_TAG + Symbol, # LONGEXPR_TAG + Symbol, # LONGSTRING_TAG + Symbol, # SHORTINT64_TAG + Symbol, # FULL_DATATYPE_TAG + Symbol, # WRAPPER_DATATYPE_TAG + Symbol, # OBJECT_TAG + Symbol, # REF_OBJECT_TAG + Symbol, # FULL_GLOBALREF_TAG + + (), Bool, Any, Bottom, Core.TypeofBottom, Type, svec(), Tuple{}, false, true, nothing, + :Any, :Array, :TypeVar, :Box, :Tuple, :Ptr, :return, :call, Symbol("::"), :Function, + :(=), :(==), :(===), :gotoifnot, :A, :B, :C, :M, :N, :T, :S, :X, :Y, :a, :b, :c, :d, :e, :f, + :g, :h, :i, :j, :k, :l, :m, :n, :o, :p, :q, :r, :s, :t, :u, :v, :w, :x, :y, :z, :add_int, + :sub_int, :mul_int, :add_float, :sub_float, :new, :mul_float, :bitcast, :start, :done, :next, + :indexed_next, :getfield, :meta, :eq_int, :slt_int, :sle_int, :ne_int, :push_loc, :pop_loc, + :pop, :arrayset, :arrayref, :apply_type, :inbounds, :getindex, :setindex!, :Core, :!, :+, + :Base, :static_parameter, :convert, :colon, Symbol("#self#"), Symbol("#temp#"), :tuple, + + fill(:_reserved_, n_reserved_slots)..., + + (Int32(0):Int32(n_int_literals-1))..., + (Int64(0):Int64(n_int_literals-1))... ] -const ser_version = 5 # do not make changes without bumping the version #! +@assert length(TAGS) <= 255 + +const ser_version = 6 # do not make changes without bumping the version #! const NTAGS = length(TAGS) function sertag(v::ANY) ptr = pointer_from_objref(v) ptags = convert(Ptr{Ptr{Void}}, pointer(TAGS)) - @inbounds for i in 1:NTAGS - ptr == unsafe_load(ptags,i) && return (i+1)%Int32 + # note: constant ints & reserved slots never returned here + @inbounds for i in 1:(NTAGS-(n_reserved_slots+2*n_int_literals)) + ptr == unsafe_load(ptags,i) && return i%Int32 end return Int32(-1) end -desertag(i::Int32) = TAGS[i-1] +desertag(i::Int32) = TAGS[i] # tags >= this just represent themselves, their whole representation is 1 byte const VALUE_TAGS = sertag(()) -const ZERO_TAG = sertag(0) +const ZERO32_TAG = Int32(NTAGS-(2*n_int_literals-1)) +const ZERO64_TAG = Int64(NTAGS-(n_int_literals-1)) const TRUE_TAG = sertag(true) const FALSE_TAG = sertag(false) const EMPTYTUPLE_TAG = sertag(()) const TUPLE_TAG = sertag(Tuple) -const LONGTUPLE_TAG = Int32(sertag(Expr)+2) const SIMPLEVECTOR_TAG = sertag(SimpleVector) const SYMBOL_TAG = sertag(Symbol) -const LONGSYMBOL_TAG = Int32(sertag(Expr)+1) const ARRAY_TAG = sertag(Array) -const UNDEFREF_TAG = Int32(sertag(Module)+1) -const BACKREF_TAG = Int32(sertag(SimpleVector)+1) const EXPR_TAG = sertag(Expr) -const LONGEXPR_TAG = Int32(sertag(Expr)+3) const MODULE_TAG = sertag(Module) const METHODINSTANCE_TAG = sertag(Core.MethodInstance) const METHOD_TAG = sertag(Method) const TASK_TAG = sertag(Task) const DATATYPE_TAG = sertag(DataType) const TYPENAME_TAG = sertag(TypeName) -const INT_TAG = sertag(Int) +const INT32_TAG = sertag(Int32) +const INT64_TAG = sertag(Int64) const GLOBALREF_TAG = sertag(GlobalRef) const BOTTOM_TAG = sertag(Bottom) const UNIONALL_TAG = sertag(UnionAll) +const STRING_TAG = sertag(String) +const o0 = sertag(SSAValue) +const UNDEFREF_TAG = Int32(o0+1) +const BACKREF_TAG = Int32(o0+2) +const LONGBACKREF_TAG = Int32(o0+3) +const SHORTBACKREF_TAG = Int32(o0+4) +const LONGTUPLE_TAG = Int32(o0+5) +const LONGSYMBOL_TAG = Int32(o0+6) +const LONGEXPR_TAG = Int32(o0+7) +const LONGSTRING_TAG = Int32(o0+8) +const SHORTINT64_TAG = Int32(o0+9) +const FULL_DATATYPE_TAG = Int32(o0+10) +const WRAPPER_DATATYPE_TAG = Int32(o0+11) +const OBJECT_TAG = Int32(o0+12) +const REF_OBJECT_TAG = Int32(o0+13) +const FULL_GLOBALREF_TAG = Int32(o0+14) writetag(s::IO, tag) = write(s, UInt8(tag)) @@ -100,30 +130,35 @@ end # cycle handling function serialize_cycle(s::AbstractSerializer, x) - if !isimmutable(x) && !datatype_pointerfree(typeof(x)) - offs = get(s.table, x, -1) - if offs != -1 + offs = get(s.table, x, -1) + if offs != -1 + if offs <= typemax(UInt16) + writetag(s.io, SHORTBACKREF_TAG) + write(s.io, UInt16(offs)) + elseif offs <= typemax(Int32) writetag(s.io, BACKREF_TAG) - write(s.io, Int(offs)) - return true + write(s.io, Int32(offs)) + else + writetag(s.io, LONGBACKREF_TAG) + write(s.io, Int64(offs)) end - s.table[x] = s.counter - s.counter += 1 + return true end + s.table[x] = s.counter + s.counter += 1 return false end function serialize_cycle_header(s::AbstractSerializer, x::ANY) - t = typeof(x) - t.mutable && haskey(s.table, x) && serialize_cycle(s, x) && return true - serialize_type(s, t) - t.mutable && serialize_cycle(s, x) + serialize_cycle(s, x) && return true + serialize_type(s, typeof(x), true) return false end function reset_state(s::AbstractSerializer) s.counter = 0 s.table = ObjectIdDict() + empty!(s.pending_refs) s end @@ -162,15 +197,18 @@ function serialize(s::AbstractSerializer, x::Symbol) return write_as_tag(s.io, tag) end pname = unsafe_convert(Ptr{UInt8}, x) - ln = Int(ccall(:strlen, Csize_t, (Cstring,), pname)) - if ln <= 255 + len = Int(ccall(:strlen, Csize_t, (Cstring,), pname)) + if len > 7 + serialize_cycle(s, x) && return + end + if len <= 255 writetag(s.io, SYMBOL_TAG) - write(s.io, UInt8(ln)) + write(s.io, UInt8(len)) else writetag(s.io, LONGSYMBOL_TAG) - write(s.io, Int32(ln)) + write(s.io, Int32(len)) end - unsafe_write(s.io, pname, ln) + unsafe_write(s.io, pname, len) end function serialize_array_data(s::IO, a) @@ -194,26 +232,12 @@ function serialize_array_data(s::IO, a) end function serialize(s::AbstractSerializer, a::Array) + serialize_cycle(s, a) && return elty = eltype(a) - if !isbits(elty) - # This is subtle: whether Arrays are put in the table depends on - # the eltype, so we need to be able to deserialize the eltype first. - # However deserializing the eltype might also use the table. - offs = get(s.table, a, -1) - if offs != -1 - writetag(s.io, BACKREF_TAG) - write(s.io, Int(offs)) - return - end - end writetag(s.io, ARRAY_TAG) if elty !== UInt8 serialize(s, elty) end - if !isbits(elty) - s.table[a] = s.counter - s.counter += 1 - end if ndims(a) != 1 serialize(s, size(a)) else @@ -257,8 +281,14 @@ trimmedindex(P, d, i::Slice) = i trimmedindex(P, d, i::AbstractArray) = oftype(i, reshape(linearindices(i), indices(i))) function serialize(s::AbstractSerializer, ss::String) - serialize_type(s, String) - write(s.io, sizeof(ss)) + len = sizeof(ss) + if len <= 255 + writetag(s.io, STRING_TAG) + write(s.io, UInt8(len)) + else + writetag(s.io, LONGSTRING_TAG) + write(s.io, Int64(len)) + end write(s.io, ss) end @@ -302,10 +332,10 @@ function serialize(s::AbstractSerializer, ex::Expr) end end -function serialize(s::AbstractSerializer, t::Dict) - serialize_cycle_header(s, t) && return - write(s.io, Int32(length(t))) - for (k,v) in t +function serialize(s::AbstractSerializer, d::Dict) + serialize_cycle_header(s, d) && return + write(s.io, Int32(length(d))) + for (k,v) in d serialize(s, k) serialize(s, v) end @@ -404,24 +434,22 @@ function serialize(s::AbstractSerializer, t::Task) end function serialize(s::AbstractSerializer, g::GlobalRef) - writetag(s.io, GLOBALREF_TAG) if g.mod === Main && isdefined(g.mod, g.name) && isconst(g.mod, g.name) v = getfield(g.mod, g.name) unw = unwrap_unionall(v) if isa(unw,DataType) && v === unw.name.wrapper && should_send_whole_type(s, unw) # handle references to types in Main by sending the whole type. # needed to be able to send nested functions (#15451). - write(s.io, UInt8(1)) + writetag(s.io, FULL_GLOBALREF_TAG) serialize(s, v) return end end - write(s.io, UInt8(0)) + writetag(s.io, GLOBALREF_TAG) serialize(s, g.mod) serialize(s, g.name) end - function serialize(s::AbstractSerializer, t::TypeName) serialize_cycle(s, t) && return writetag(s.io, TYPENAME_TAG) @@ -475,30 +503,33 @@ function should_send_whole_type(s, t::DataType) return false end -# `type_itself` means we are serializing a type object. when it's false, we are -# sending the type tag part of some other object's representation. -function serialize_type_data(s, t::DataType, type_itself::Bool) +function serialize_type_data(s, t::DataType) whole = should_send_whole_type(s, t) - form = type_itself ? UInt8(0) : UInt8(1) - if whole - form |= UInt8(2) + iswrapper = (t === unwrap_unionall(t.name.wrapper)) + if whole && iswrapper + writetag(s.io, WRAPPER_DATATYPE_TAG) + serialize(s, t.name) + return end - writetag(s.io, DATATYPE_TAG) - write(s.io, form) + serialize_cycle(s, t) && return if whole + writetag(s.io, FULL_DATATYPE_TAG) serialize(s, t.name) else + writetag(s.io, DATATYPE_TAG) tname = t.name.name serialize(s, tname) mod = t.name.module serialize(s, mod) end if !isempty(t.parameters) - if (whole ? (t === unwrap_unionall(t.name.wrapper)) : - (isdefined(mod,tname) && t === unwrap_unionall(getfield(mod,tname)))) - serialize(s, svec()) + if iswrapper + write(s.io, Int32(0)) else - serialize(s, t.parameters) + write(s.io, Int32(length(t.parameters))) + for p in t.parameters + serialize(s, p) + end end end end @@ -513,22 +544,35 @@ function serialize(s::AbstractSerializer, t::DataType) # only type with this property. issue #15849 return write_as_tag(s.io, TUPLE_TAG) end - serialize_type_data(s, t, true) + serialize_type_data(s, t) end -function serialize_type(s::AbstractSerializer, t::DataType) +function serialize_type(s::AbstractSerializer, t::DataType, ref::Bool = false) tag = sertag(t) tag > 0 && return writetag(s.io, tag) - serialize_type_data(s, t, false) + writetag(s.io, ref ? REF_OBJECT_TAG : OBJECT_TAG) + serialize_type_data(s, t) end -function serialize(s::AbstractSerializer, n::Int) - if 0 <= n <= 32 - write(s.io, UInt8(ZERO_TAG+n)) - return +function serialize(s::AbstractSerializer, n::Int32) + if 0 <= n <= (n_int_literals-1) + write(s.io, UInt8(ZERO32_TAG+n)) + else + writetag(s.io, INT32_TAG) + write(s.io, n) + end +end + +function serialize(s::AbstractSerializer, n::Int64) + if 0 <= n <= (n_int_literals-1) + write(s.io, UInt8(ZERO64_TAG+n)) + elseif typemin(Int32) <= n <= typemax(Int32) + writetag(s.io, SHORTINT64_TAG) + write(s.io, Int32(n)) + else + writetag(s.io, INT64_TAG) + write(s.io, n) end - writetag(s.io, INT_TAG) - write(s.io, n) end serialize(s::AbstractSerializer, ::Type{Bottom}) = write_as_tag(s.io, BOTTOM_TAG) @@ -564,7 +608,12 @@ function serialize_any(s::AbstractSerializer, x::ANY) serialize_type(s, t) write(s.io, x) else - serialize_cycle_header(s, x) && return + if t.mutable && nf > 0 + serialize_cycle(s, x) && return + serialize_type(s, t, true) + else + serialize_type(s, t, false) + end for i in 1:nf if isdefined(x, i) serialize(s, getfield(x, i)) @@ -586,10 +635,19 @@ function deserialize(s::AbstractSerializer) end function deserialize_cycle(s::AbstractSerializer, x::ANY) - if !isimmutable(x) && !datatype_pointerfree(typeof(x)) - s.table[s.counter] = x - s.counter += 1 - end + slot = pop!(s.pending_refs) + s.table[slot] = x + nothing +end + +# optimized version of: +# slot = s.counter; s.counter += 1 +# push!(s.pending_refs, slot) +# slot = pop!(s.pending_refs) +# s.table[slot] = x +function resolve_ref_immediately(s::AbstractSerializer, x::ANY) + s.table[s.counter] = x + s.counter += 1 nothing end @@ -604,35 +662,84 @@ function handle_deserialize(s::AbstractSerializer, b::Int32) return desertag(b) elseif b == TUPLE_TAG return deserialize_tuple(s, Int(read(s.io, UInt8)::UInt8)) - elseif b == LONGTUPLE_TAG - return deserialize_tuple(s, Int(read(s.io, Int32)::Int32)) + elseif b == SHORTBACKREF_TAG + id = read(s.io, UInt16)::UInt16 + return s.table[Int(id)] elseif b == BACKREF_TAG - id = read(s.io, Int)::Int - return s.table[id] + id = read(s.io, Int32)::Int32 + return s.table[Int(id)] elseif b == ARRAY_TAG return deserialize_array(s) elseif b == DATATYPE_TAG - return deserialize_datatype(s) + return deserialize_datatype(s, false) + elseif b == FULL_DATATYPE_TAG + return deserialize_datatype(s, true) + elseif b == WRAPPER_DATATYPE_TAG + tname = deserialize(s)::TypeName + return unwrap_unionall(tname.wrapper) + elseif b == OBJECT_TAG + t = deserialize(s) + return deserialize(s, t) + elseif b == REF_OBJECT_TAG + slot = s.counter; s.counter += 1 + push!(s.pending_refs, slot) + t = deserialize(s) + return deserialize(s, t) elseif b == SYMBOL_TAG - return Symbol(read(s.io, UInt8, Int(read(s.io, UInt8)::UInt8))) - elseif b == LONGSYMBOL_TAG - return Symbol(read(s.io, UInt8, Int(read(s.io, Int32)::Int32))) + return deserialize_symbol(s, Int(read(s.io, UInt8)::UInt8)) + elseif b == SHORTINT64_TAG + return Int64(read(s.io, Int32)::Int32) elseif b == EXPR_TAG return deserialize_expr(s, Int(read(s.io, UInt8)::UInt8)) + elseif b == MODULE_TAG + return deserialize_module(s) + elseif b == STRING_TAG + return deserialize_string(s, Int(read(s.io, UInt8)::UInt8)) + elseif b == LONGSTRING_TAG + return deserialize_string(s, Int(read(s.io, Int64)::Int64)) + elseif b == SIMPLEVECTOR_TAG + return deserialize_svec(s) + elseif b == GLOBALREF_TAG + return GlobalRef(deserialize(s)::Module, deserialize(s)::Symbol) + elseif b == FULL_GLOBALREF_TAG + ty = deserialize(s) + return GlobalRef(ty.name.module, ty.name.name) + elseif b == LONGTUPLE_TAG + return deserialize_tuple(s, Int(read(s.io, Int32)::Int32)) elseif b == LONGEXPR_TAG return deserialize_expr(s, Int(read(s.io, Int32)::Int32)) + elseif b == LONGBACKREF_TAG + id = read(s.io, Int64)::Int64 + return s.table[Int(id)] + elseif b == LONGSYMBOL_TAG + return deserialize_symbol(s, Int(read(s.io, Int32)::Int32)) end - return deserialize(s, desertag(b)) + t = desertag(b) + if t.mutable && nfields(t) > 0 + slot = s.counter; s.counter += 1 + push!(s.pending_refs, slot) + end + return deserialize(s, t) +end + +function deserialize_symbol(s::AbstractSerializer, len::Int) + str = Base._string_n(len) + unsafe_read(s.io, pointer(str), len) + sym = Symbol(str) + if len > 7 + resolve_ref_immediately(s, sym) + end + return sym end deserialize_tuple(s::AbstractSerializer, len) = ntuple(i->deserialize(s), len) -function deserialize(s::AbstractSerializer, ::Type{SimpleVector}) +function deserialize_svec(s::AbstractSerializer) n = read(s.io, Int32) svec(Any[ deserialize(s) for i=1:n ]...) end -function deserialize(s::AbstractSerializer, ::Type{Module}) +function deserialize_module(s::AbstractSerializer) path = deserialize(s) m = Main if isa(path,Tuple) && path !== () @@ -716,6 +823,7 @@ function deserialize(s::AbstractSerializer, ::Type{Core.MethodInstance}) end function deserialize_array(s::AbstractSerializer) + slot = s.counter; s.counter += 1 d1 = deserialize(s) if isa(d1, Type) elty = d1 @@ -726,6 +834,7 @@ function deserialize_array(s::AbstractSerializer) if isa(d1, Integer) if elty !== Bool && isbits(elty) a = Array{elty, 1}(d1) + s.table[slot] = a return read!(s.io, a) end dims = (Int(d1),) @@ -750,10 +859,11 @@ function deserialize_array(s::AbstractSerializer) else A = read(s.io, elty, dims) end + s.table[slot] = A return A end A = Array{elty, length(dims)}(dims) - deserialize_cycle(s, A) + s.table[slot] = A for i = eachindex(A) tag = Int32(read(s.io, UInt8)::UInt8) if tag != UNDEFREF_TAG @@ -764,30 +874,18 @@ function deserialize_array(s::AbstractSerializer) end function deserialize_expr(s::AbstractSerializer, len) - hd = deserialize(s)::Symbol - e = Expr(hd) - deserialize_cycle(s, e) + e = Expr(:temp) + resolve_ref_immediately(s, e) + e.head = deserialize(s)::Symbol ty = deserialize(s) e.args = Any[ deserialize(s) for i=1:len ] e.typ = ty e end -function deserialize(s::AbstractSerializer, ::Type{GlobalRef}) - kind = read(s.io, UInt8) - if kind == 0 - return GlobalRef(deserialize(s)::Module, deserialize(s)::Symbol) - else - ty = deserialize(s) - return GlobalRef(ty.name.module, ty.name.name) - end -end - module __deserialized_types__ end function deserialize(s::AbstractSerializer, ::Type{TypeName}) - # the deserialize_cycle call can be delayed, since neither - # Symbol nor Module will use the backref table number = read(s.io, UInt64) return deserialize_typename(s, number) end @@ -859,9 +957,9 @@ function deserialize_typename(s::AbstractSerializer, number) return tn::TypeName end -function deserialize_datatype(s::AbstractSerializer) - form = read(s.io, UInt8)::UInt8 - if (form&2) != 0 +function deserialize_datatype(s::AbstractSerializer, full::Bool) + slot = s.counter; s.counter += 1 + if full tname = deserialize(s)::TypeName ty = tname.wrapper else @@ -872,17 +970,31 @@ function deserialize_datatype(s::AbstractSerializer) if isa(ty,DataType) && isempty(ty.parameters) t = ty else - params = deserialize(s) - if isempty(params) - @assert (form&1) == 0 - return unwrap_unionall(ty) + np = Int(read(s.io, Int32)::Int32) + if np == 0 + t = unwrap_unionall(ty) + elseif ty === Tuple + # note np==0 has its own tag + if np == 1 + t = Tuple{deserialize(s)} + elseif np == 2 + t = Tuple{deserialize(s), deserialize(s)} + elseif np == 3 + t = Tuple{deserialize(s), deserialize(s), deserialize(s)} + elseif np == 4 + t = Tuple{deserialize(s), deserialize(s), deserialize(s), deserialize(s)} + else + t = Tuple{Any[ deserialize(s) for i=1:np ]...} + end + else + t = ty + for i = 1:np + t = t{deserialize(s)} + end end - t = ty{params...} - end - if (form&1) == 0 - return t end - deserialize(s, t) + s.table[slot] = t + return t end function deserialize(s::AbstractSerializer, ::Type{UnionAll}) @@ -921,10 +1033,9 @@ function deserialize(s::AbstractSerializer, ::Type{Task}) t end -function deserialize(s::AbstractSerializer, ::Type{String}) - n = read(s.io, Int) - out = ccall(:jl_alloc_string, Ref{String}, (Csize_t,), n) - unsafe_read(s.io, pointer(out), n) +function deserialize_string(s::AbstractSerializer, len::Int) + out = ccall(:jl_alloc_string, Ref{String}, (Csize_t,), len) + unsafe_read(s.io, pointer(out), len) return out end diff --git a/test/serialize.jl b/test/serialize.jl index d66f448874658..8be0c8f0d0a35 100644 --- a/test/serialize.jl +++ b/test/serialize.jl @@ -3,9 +3,9 @@ using Base.Test # Check that serializer hasn't gone out-of-frame -@test Serializer.sertag(Symbol) == 2 -@test Serializer.sertag(()) == 45 -@test Serializer.sertag(false) == 121 +@test Serializer.sertag(Symbol) == 1 +@test Serializer.sertag(()) == 55 +@test Serializer.sertag(false) == 63 function create_serialization_stream(f::Function) s = IOBuffer() @@ -370,6 +370,17 @@ create_serialization_stream() do s @test isa(b,Vector{Any}) end +# shared references +create_serialization_stream() do s + A = [1,2] + B = [A,A] + serialize(s, B) + seekstart(s) + C = deserialize(s) + @test C == B + @test C[1] === C[2] +end + # Regex create_serialization_stream() do s r1 = r"a?b.*" From e62a7db7504e554c0ea440cb3d7113e076361eaa Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 24 Apr 2017 23:01:42 -0400 Subject: [PATCH 0580/1534] simpler and faster message (de)serialize also separate `serialize_msg` from `serialize` --- base/associative.jl | 7 +++- base/distributed/Distributed.jl | 2 +- base/distributed/messages.jl | 55 +++++++++++++--------------- base/distributed/process_messages.jl | 2 +- base/distributed/remotecall.jl | 2 +- base/precompile.jl | 3 -- base/serialize.jl | 2 +- base/stream.jl | 10 ++++- 8 files changed, 44 insertions(+), 39 deletions(-) diff --git a/base/associative.jl b/base/associative.jl index f46378b56d266..8c276ee8dc078 100644 --- a/base/associative.jl +++ b/base/associative.jl @@ -441,7 +441,12 @@ function delete!(t::ObjectIdDict, key::ANY) t end -empty!(t::ObjectIdDict) = (t.ht = Vector{Any}(length(t.ht)); t.ndel = 0; t) +function empty!(t::ObjectIdDict) + resize!(t.ht, 32) + ccall(:memset, Ptr{Void}, (Ptr{Void}, Cint, Csize_t), t.ht, 0, sizeof(t.ht)) + t.ndel = 0 + return t +end _oidd_nextind(a, i) = reinterpret(Int,ccall(:jl_eqtable_nextind, Csize_t, (Any, Csize_t), a, i)) diff --git a/base/distributed/Distributed.jl b/base/distributed/Distributed.jl index 36e4bcba53fc9..73270b0672b3b 100644 --- a/base/distributed/Distributed.jl +++ b/base/distributed/Distributed.jl @@ -10,7 +10,7 @@ import Base: getindex, wait, put!, take!, fetch, isready, push!, length, using Base: Process, Semaphore, JLOptions, AnyDict, buffer_writes, wait_connected, VERSION_STRING, sync_begin, sync_add, sync_end, async_run_thunk, binding_module, notify_error, atexit, julia_exename, julia_cmd, - AsyncGenerator, display_error, acquire, release + AsyncGenerator, display_error, acquire, release, invokelatest # NOTE: clusterserialize.jl imports additional symbols from Base.Serializer for use diff --git a/base/distributed/messages.jl b/base/distributed/messages.jl index aee31cec8bf50..17a447a154d1f 100644 --- a/base/distributed/messages.jl +++ b/base/distributed/messages.jl @@ -2,10 +2,8 @@ abstract type AbstractMsg end -let REF_ID::Int = 1 - global next_ref_id - next_ref_id() = (id = REF_ID; REF_ID += 1; id) -end +const REF_ID = Ref(1) +next_ref_id() = (id = REF_ID[]; REF_ID[] = id+1; id) struct RRID whence::Int @@ -80,34 +78,32 @@ end # of approximately 10%. Can be removed once module Serializer # has been suitably improved. -# replace CallMsg{Mode} with specific invocations -const msgtypes = filter!(x->x!=CallMsg, subtypes(AbstractMsg)) -push!(msgtypes, CallMsg{:call}, CallMsg{:call_fetch}) +const msgtypes = Any[CallWaitMsg, IdentifySocketAckMsg, IdentifySocketMsg, + JoinCompleteMsg, JoinPGRPMsg, RemoteDoMsg, ResultMsg, + CallMsg{:call}, CallMsg{:call_fetch}] for (idx, tname) in enumerate(msgtypes) - nflds = length(fieldnames(tname)) - @eval begin - function serialize(s::AbstractSerializer, o::$tname) - write(s.io, UInt8($idx)) - for fld in fieldnames($tname) - serialize(s, getfield(o, fld)) - end - end - - function deserialize_msg(s::AbstractSerializer, ::Type{$tname}) - data=Array{Any,1}($nflds) - for i in 1:$nflds - data[i] = deserialize(s) - end - return $tname(data...) - end + exprs = Any[ :(serialize(s, o.$fld)) for fld in fieldnames(tname) ] + @eval function serialize_msg(s::AbstractSerializer, o::$tname) + write(s.io, UInt8($idx)) + $(exprs...) + return nothing end end -function deserialize_msg(s::AbstractSerializer) - idx = read(s.io, UInt8) - t = msgtypes[idx] - return eval(current_module(), Expr(:body, Expr(:return, Expr(:call, deserialize_msg, QuoteNode(s), QuoteNode(t))))) +let msg_cases = :(assert(false)) + for i = length(msgtypes):-1:1 + mti = msgtypes[i] + msg_cases = :(if idx == $i + return $(Expr(:call, QuoteNode(mti), fill(:(deserialize(s)), nfields(mti))...)) + else + $msg_cases + end) + end + @eval function deserialize_msg(s::AbstractSerializer) + idx = read(s.io, UInt8) + $msg_cases + end end function send_msg_unknown(s::IO, header, msg) @@ -171,8 +167,7 @@ function serialize_hdr_raw(io, hdr) end function deserialize_hdr_raw(io) - data = Array{Int,1}(4) - read!(io, data) + data = read(io, Ref{NTuple{4,Int}}())[] return MsgHeader(RRID(data[1], data[2]), RRID(data[3], data[4])) end @@ -183,7 +178,7 @@ function send_msg_(w::Worker, header, msg, now::Bool) try reset_state(w.w_serializer) serialize_hdr_raw(io, header) - eval(current_module(), Expr(:body, Expr(:return, Expr(:call, serialize, QuoteNode(w.w_serializer), QuoteNode(msg))))) # io is wrapped in w_serializer + invokelatest(serialize_msg, w.w_serializer, msg) # io is wrapped in w_serializer write(io, MSG_BOUNDARY) if !now && w.gcflag diff --git a/base/distributed/process_messages.jl b/base/distributed/process_messages.jl index 121467676a64f..1eba6eafd496d 100644 --- a/base/distributed/process_messages.jl +++ b/base/distributed/process_messages.jl @@ -158,7 +158,7 @@ function message_handler_loop(r_stream::IO, w_stream::IO, incoming::Bool) # println("header: ", header) try - msg = deserialize_msg(serializer) + msg = invokelatest(deserialize_msg, serializer) catch e # Deserialization error; discard bytes in stream until boundary found boundary_idx = 1 diff --git a/base/distributed/remotecall.jl b/base/distributed/remotecall.jl index 67d4476d0cc18..e03f1d19a8d9d 100644 --- a/base/distributed/remotecall.jl +++ b/base/distributed/remotecall.jl @@ -152,7 +152,7 @@ function lookup_ref(pg, rrid, f) rv = get(pg.refs, rrid, false) if rv === false # first we've heard of this ref - rv = RemoteValue(eval(Main, Expr(:body, Expr(:return, Expr(:call, f))))) + rv = RemoteValue(invokelatest(f)) pg.refs[rrid] = rv push!(rv.clientset, rrid.whence) end diff --git a/base/precompile.jl b/base/precompile.jl index 2342279959196..8bc84db37f499 100644 --- a/base/precompile.jl +++ b/base/precompile.jl @@ -1405,7 +1405,6 @@ precompile(Tuple{typeof(Base.close), Base.TCPSocket}) precompile(Tuple{typeof(Base.write), Base.TCPSocket, Array{UInt8, 1}}) precompile(Tuple{typeof(Base.wait_readnb), Base.PipeEndpoint, Int64}) precompile(Tuple{typeof(Base.eof), Base.PipeEndpoint}) -precompile(Tuple{typeof(Base.Distributed.deserialize_msg), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Type{Base.Distributed.JoinPGRPMsg}}) precompile(Tuple{typeof(Base.unsafe_read), Base.TCPSocket, Base.RefValue{Int32}, Int64}) precompile(Tuple{typeof(Base.unsafe_read), Base.TCPSocket, Base.RefValue{Int64}, Int64}) precompile(Tuple{typeof(Base.read!), Base.TCPSocket, Array{UInt8, 1}}) @@ -1479,7 +1478,6 @@ precompile(Tuple{typeof(Base.notify), Base.Condition, Base.Distributed.ProcessEx precompile(Tuple{typeof(Base.pop!), Base.Dict{Int64, Union{Base.Distributed.Worker, Base.Distributed.LocalProcess}}, Int64, Void}) precompile(Tuple{typeof(Base.Distributed.deregister_worker), Base.Distributed.ProcessGroup, Int64}) precompile(Tuple{typeof(Base.Distributed.process_hdr), Base.TCPSocket, Bool}) -precompile(Tuple{typeof(Base.Distributed.deserialize_msg), Base.Distributed.ClusterSerializer{Base.TCPSocket}}) precompile(Tuple{typeof(Base.Distributed.null_id), Base.Distributed.RRID}) precompile(Tuple{typeof(Base.Distributed.deliver_result), Base.TCPSocket, Symbol, Base.Distributed.RRID, Base.Distributed.RemoteException}) precompile(Tuple{typeof(Base.Distributed.disable_nagle), Base.TCPSocket}) @@ -1535,7 +1533,6 @@ precompile(Tuple{typeof(Base.Serializer.serialize), Base.Distributed.ClusterSeri precompile(Tuple{typeof(Base.unsafe_write), Base.TCPSocket, Base.RefValue{UInt8}, Int64}) precompile(Tuple{typeof(Base.Serializer.serialize), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Int64}) precompile(Tuple{typeof(Base.write), Base.TCPSocket, Array{UInt8, 1}}) -precompile(Tuple{typeof(Base.Distributed.deserialize_msg), Base.Distributed.ClusterSerializer{Base.TCPSocket}, Type{Base.Distributed.JoinCompleteMsg}}) precompile(Tuple{typeof(Base.unsafe_read), Base.TCPSocket, Base.RefValue{Int32}, Int64}) precompile(Tuple{typeof(Base.unsafe_read), Base.TCPSocket, Base.RefValue{Int64}, Int64}) precompile(Tuple{typeof(Base.read!), Base.TCPSocket, Array{UInt8, 1}}) diff --git a/base/serialize.jl b/base/serialize.jl index 55df21d7c201e..4b309489226c9 100644 --- a/base/serialize.jl +++ b/base/serialize.jl @@ -157,7 +157,7 @@ end function reset_state(s::AbstractSerializer) s.counter = 0 - s.table = ObjectIdDict() + empty!(s.table) empty!(s.pending_refs) s end diff --git a/base/stream.jl b/base/stream.jl index 4c0d931e72282..4bd1f4c070d88 100644 --- a/base/stream.jl +++ b/base/stream.jl @@ -863,7 +863,15 @@ buffer_writes(s::LibuvStream, bufsize) = (s.sendbuf=PipeBuffer(bufsize); s) ## low-level calls to libuv ## -write(s::LibuvStream, b::UInt8) = write(s, Ref{UInt8}(b)) +function write(s::LibuvStream, b::UInt8) + if !isnull(s.sendbuf) + buf = get(s.sendbuf) + if nb_available(buf) + 1 < buf.maxsize + return write(buf, b) + end + end + return write(s, Ref{UInt8}(b)) +end function uv_writecb_task(req::Ptr{Void}, status::Cint) d = uv_req_data(req) From 670c09ff17b33a8a879e0911cf19bbdcf2bfed22 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Thu, 27 Apr 2017 08:45:00 -0700 Subject: [PATCH 0581/1534] Add a test for branch ref name merge (#21573) * Add a test for branch ref name merge * add a note about branch string formatting --- base/libgit2/libgit2.jl | 6 ++++++ test/libgit2.jl | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/base/libgit2/libgit2.jl b/base/libgit2/libgit2.jl index 85f5e6cc76a37..460639d9a4872 100644 --- a/base/libgit2/libgit2.jl +++ b/base/libgit2/libgit2.jl @@ -559,6 +559,12 @@ The keyword arguments are: options for the checkout step. Equivalent to `git merge [--ff-only] [ | ]`. + +!!! note + If you specify a `branch`, this must be done in reference format, since + the string will be turned into a `GitReference`. For example, if you + wanted to merge branch `branch_a`, you would call + `merge!(repo, branch="refs/heads/branch_a")`. """ function merge!(repo::GitRepo; committish::AbstractString = "", diff --git a/test/libgit2.jl b/test/libgit2.jl index a9ca74ce8e1b5..bcc6a64cd6085 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -705,6 +705,26 @@ mktempdir() do dir # from branch/a using committish @test LibGit2.merge!(repo, committish=string(branchhead)) @test LibGit2.is_ancestor_of(string(oldhead), string(LibGit2.head_oid(repo)), repo) + + oldhead = LibGit2.head_oid(repo) + LibGit2.branch!(repo, "branch/ff_c") + open(joinpath(LibGit2.path(repo),"ff_file5"),"w") do f + write(f, "555\n") + end + LibGit2.add!(repo, "ff_file5") + LibGit2.commit(repo, "add ff_file5") + + open(joinpath(LibGit2.path(repo),"ff_file6"),"w") do f + write(f, "666\n") + end + LibGit2.add!(repo, "ff_file6") + LibGit2.commit(repo, "add ff_file6") + branchhead = LibGit2.head_oid(repo) + LibGit2.branch!(repo, "master") + # switch back, now try to ff-merge the changes + # from branch/ff_c using branch name + @test LibGit2.merge!(repo, branch="refs/heads/branch/ff_c") + @test LibGit2.is_ancestor_of(string(oldhead), string(LibGit2.head_oid(repo)), repo) finally close(repo) end From 86bf95fe0a76e4750d41f569bfcb6fa1fb1805e4 Mon Sep 17 00:00:00 2001 From: Mus M Date: Thu, 27 Apr 2017 11:59:20 -0400 Subject: [PATCH 0582/1534] Change to where syntax in misc places (#21558) * Change to where syntax --- base/grisu/float.jl | 4 +-- base/linalg/arnoldi.jl | 13 ++++--- base/linalg/bunchkaufman.jl | 8 ++--- base/linalg/cholesky.jl | 2 +- base/linalg/conjarray.jl | 34 +++++++++--------- base/linalg/factorization.jl | 2 +- base/linalg/generic.jl | 24 ++++++------- base/linalg/givens.jl | 8 ++--- base/linalg/ldlt.jl | 6 ++-- base/linalg/lu.jl | 58 +++++++++++++++--------------- base/linalg/qr.jl | 24 ++++++------- base/linalg/rowvector.jl | 2 +- base/linalg/schur.jl | 2 +- base/linalg/svd.jl | 22 ++++++------ base/linalg/symmetric.jl | 68 +++++++++++++++++++++-------------- base/linalg/transpose.jl | 4 +-- base/linalg/triangular.jl | 2 +- base/linalg/tridiag.jl | 28 +++++++-------- base/linalg/uniformscaling.jl | 10 +++--- base/sharedarray.jl | 22 ++++++------ base/sparse/abstractsparse.jl | 6 ++-- base/sparse/cholmod.jl | 10 +++--- base/tuple.jl | 26 +++++++------- 23 files changed, 199 insertions(+), 186 deletions(-) diff --git a/base/grisu/float.jl b/base/grisu/float.jl index 4581b8bb2ccea..2adec178d2fd6 100644 --- a/base/grisu/float.jl +++ b/base/grisu/float.jl @@ -109,7 +109,7 @@ function _exponent(d::T) where T<:AbstractFloat biased_e::Int32 = Int32((uint_t(d) & ExponentMask(T)) >> PhysicalSignificandSize(T)) return Int32(biased_e - ExponentBias(T)) end -function _significand{T<:AbstractFloat}(d::T) +function _significand(d::T) where T<:AbstractFloat s = uint_t(d) & SignificandMask(T) return !isdenormal(d) ? s + HiddenBit(T) : s end @@ -125,7 +125,7 @@ function normalizedbound(f::AbstractFloat) end return Float(m_minus.s << (m_minus.e - m_plus.e), m_plus.e), m_plus end -function lowerboundaryiscloser{T<:AbstractFloat}(f::T) +function lowerboundaryiscloser(f::T) where T<:AbstractFloat physical_significand_is_zero = (uint_t(f) & SignificandMask(T)) == 0 return physical_significand_is_zero && (_exponent(f) != DenormalExponent(T)) end diff --git a/base/linalg/arnoldi.jl b/base/linalg/arnoldi.jl index fc78d98affaf5..3805bdb2fb529 100644 --- a/base/linalg/arnoldi.jl +++ b/base/linalg/arnoldi.jl @@ -90,10 +90,10 @@ julia> λ eigs(A; kwargs...) = eigs(A, I; kwargs...) eigs(A::AbstractMatrix{<:BlasFloat}, ::UniformScaling; kwargs...) = _eigs(A, I; kwargs...) -eigs{T<:BlasFloat}(A::AbstractMatrix{T}, B::AbstractMatrix{T}; kwargs...) = _eigs(A, B; kwargs...) +eigs(A::AbstractMatrix{T}, B::AbstractMatrix{T}; kwargs...) where {T<:BlasFloat} = _eigs(A, B; kwargs...) eigs(A::AbstractMatrix{BigFloat}, B::AbstractMatrix...; kwargs...) = throw(MethodError(eigs, Any[A,B,kwargs...])) eigs(A::AbstractMatrix{BigFloat}, B::UniformScaling; kwargs...) = throw(MethodError(eigs, Any[A,B,kwargs...])) -function eigs{T}(A::AbstractMatrix{T}, ::UniformScaling; kwargs...) +function eigs(A::AbstractMatrix{T}, ::UniformScaling; kwargs...) where T Tnew = typeof(zero(T)/sqrt(one(T))) eigs(convert(AbstractMatrix{Tnew}, A), I; kwargs...) end @@ -169,10 +169,9 @@ julia> λ """ eigs(A, B; kwargs...) = _eigs(A, B; kwargs...) function _eigs(A, B; - nev::Integer=6, ncv::Integer=max(20,2*nev+1), which=:LM, - tol=0.0, maxiter::Integer=300, sigma=nothing, v0::Vector=zeros(eltype(A),(0,)), - ritzvec::Bool=true) - + nev::Integer=6, ncv::Integer=max(20,2*nev+1), which=:LM, + tol=0.0, maxiter::Integer=300, sigma=nothing, v0::Vector=zeros(eltype(A),(0,)), + ritzvec::Bool=true) n = checksquare(A) T = eltype(A) @@ -326,7 +325,7 @@ issymmetric(s::SVDOperator) = true svds(A::AbstractMatrix{<:BlasFloat}; kwargs...) = _svds(A; kwargs...) svds(A::AbstractMatrix{BigFloat}; kwargs...) = throw(MethodError(svds, Any[A, kwargs...])) -function svds{T}(A::AbstractMatrix{T}; kwargs...) +function svds(A::AbstractMatrix{T}; kwargs...) where T Tnew = typeof(zero(T)/sqrt(one(T))) svds(convert(AbstractMatrix{Tnew}, A); kwargs...) end diff --git a/base/linalg/bunchkaufman.jl b/base/linalg/bunchkaufman.jl index 8d0e55856f58e..af75be31adf1b 100644 --- a/base/linalg/bunchkaufman.jl +++ b/base/linalg/bunchkaufman.jl @@ -72,8 +72,8 @@ The following functions are available for bkfact(A::StridedMatrix{<:BlasFloat}, uplo::Symbol=:U, symmetric::Bool=issymmetric(A), rook::Bool=false) = bkfact!(copy(A), uplo, symmetric, rook) -bkfact{T}(A::StridedMatrix{T}, uplo::Symbol=:U, symmetric::Bool=issymmetric(A), - rook::Bool=false) = +bkfact(A::StridedMatrix{T}, uplo::Symbol=:U, symmetric::Bool=issymmetric(A), + rook::Bool=false) where {T} = bkfact!(convert(Matrix{promote_type(Float32, typeof(sqrt(one(T))))}, A), uplo, symmetric, rook) @@ -120,7 +120,7 @@ function inv(B::BunchKaufman{<:BlasComplex}) end end -function A_ldiv_B!{T<:BlasReal}(B::BunchKaufman{T}, R::StridedVecOrMat{T}) +function A_ldiv_B!(B::BunchKaufman{T}, R::StridedVecOrMat{T}) where T<:BlasReal if B.info > 0 throw(SingularException(B.info)) end @@ -131,7 +131,7 @@ function A_ldiv_B!{T<:BlasReal}(B::BunchKaufman{T}, R::StridedVecOrMat{T}) LAPACK.sytrs!(B.uplo, B.LD, B.ipiv, R) end end -function A_ldiv_B!{T<:BlasComplex}(B::BunchKaufman{T}, R::StridedVecOrMat{T}) +function A_ldiv_B!(B::BunchKaufman{T}, R::StridedVecOrMat{T}) where T<:BlasComplex if B.info > 0 throw(SingularException(B.info)) end diff --git a/base/linalg/cholesky.jl b/base/linalg/cholesky.jl index f43e9364db459..5ba08622ded9c 100644 --- a/base/linalg/cholesky.jl +++ b/base/linalg/cholesky.jl @@ -260,7 +260,7 @@ end ## With pivoting ### BLAS/LAPACK element types function cholfact!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}, - ::Type{Val{true}}; tol = 0.0) + ::Type{Val{true}}; tol = 0.0) AA, piv, rank, info = LAPACK.pstrf!(A.uplo, A.data, tol) return CholeskyPivoted{eltype(AA),typeof(AA)}(AA, A.uplo, piv, rank, tol, info) end diff --git a/base/linalg/conjarray.jl b/base/linalg/conjarray.jl index a1afac5a054f1..e7dc4b49f04a1 100644 --- a/base/linalg/conjarray.jl +++ b/base/linalg/conjarray.jl @@ -21,42 +21,42 @@ julia> ConjArray([1+im 0; 0 1-im]) 0+0im 1+1im ``` """ -struct ConjArray{T, N, A <: AbstractArray} <: AbstractArray{T, N} +struct ConjArray{T,N,A<:AbstractArray} <: AbstractArray{T,N} parent::A end -@inline ConjArray{T,N}(a::AbstractArray{T,N}) = ConjArray{conj_type(T), N, typeof(a)}(a) +@inline ConjArray(a::AbstractArray{T,N}) where {T,N} = ConjArray{conj_type(T),N,typeof(a)}(a) -ConjVector{T, V <: AbstractVector} = ConjArray{T, 1, V} -@inline ConjVector{T}(v::AbstractVector{T}) = ConjArray{conj_type(T), 1, typeof(v)}(v) +const ConjVector{T,V<:AbstractVector} = ConjArray{T,1,V} +@inline ConjVector(v::AbstractVector{T}) where {T} = ConjArray{conj_type(T),1,typeof(v)}(v) -ConjMatrix{T, M <: AbstractMatrix} = ConjArray{T, 2, M} -@inline ConjMatrix{T}(m::AbstractMatrix{T}) = ConjArray{conj_type(T), 2, typeof(m)}(m) +const ConjMatrix{T,M<:AbstractMatrix} = ConjArray{T,2,M} +@inline ConjMatrix(m::AbstractMatrix{T}) where {T} = ConjArray{conj_type(T),2,typeof(m)}(m) # This type can cause the element type to change under conjugation - e.g. an array of complex arrays. @inline conj_type(x) = conj_type(typeof(x)) -@inline conj_type{T}(::Type{T}) = promote_op(conj, T) +@inline conj_type(::Type{T}) where {T} = promote_op(conj, T) @inline parent(c::ConjArray) = c.parent @inline parent_type(c::ConjArray) = parent_type(typeof(c)) -@inline parent_type{T,N,A}(::Type{ConjArray{T,N,A}}) = A +@inline parent_type(::Type{ConjArray{T,N,A}}) where {T,N,A} = A @inline size(a::ConjArray) = size(a.parent) -IndexStyle{CA <: ConjArray}(::CA) = IndexStyle(parent_type(CA)) -IndexStyle{CA <: ConjArray}(::Type{CA}) = IndexStyle(parent_type(CA)) +IndexStyle(::CA) where {CA<:ConjArray} = IndexStyle(parent_type(CA)) +IndexStyle(::Type{CA}) where {CA<:ConjArray} = IndexStyle(parent_type(CA)) -@propagate_inbounds getindex{T,N}(a::ConjArray{T,N}, i::Int) = conj(getindex(a.parent, i)) -@propagate_inbounds getindex{T,N}(a::ConjArray{T,N}, i::Vararg{Int,N}) = conj(getindex(a.parent, i...)) -@propagate_inbounds setindex!{T,N}(a::ConjArray{T,N}, v, i::Int) = setindex!(a.parent, conj(v), i) -@propagate_inbounds setindex!{T,N}(a::ConjArray{T,N}, v, i::Vararg{Int,N}) = setindex!(a.parent, conj(v), i...) +@propagate_inbounds getindex(a::ConjArray{T,N}, i::Int) where {T,N} = conj(getindex(a.parent, i)) +@propagate_inbounds getindex(a::ConjArray{T,N}, i::Vararg{Int,N}) where {T,N} = conj(getindex(a.parent, i...)) +@propagate_inbounds setindex!(a::ConjArray{T,N}, v, i::Int) where {T,N} = setindex!(a.parent, conj(v), i) +@propagate_inbounds setindex!(a::ConjArray{T,N}, v, i::Vararg{Int,N}) where {T,N} = setindex!(a.parent, conj(v), i...) -@inline similar{T,N}(a::ConjArray, ::Type{T}, dims::Dims{N}) = similar(parent(a), T, dims) +@inline similar(a::ConjArray, ::Type{T}, dims::Dims{N}) where {T,N} = similar(parent(a), T, dims) # Currently, this is default behavior for RowVector only @inline conj(a::ConjArray) = parent(a) # Helper functions, currently used by RowVector @inline _conj(a::AbstractArray) = ConjArray(a) -@inline _conj{T<:Real}(a::AbstractArray{T}) = a +@inline _conj(a::AbstractArray{T}) where {T<:Real} = a @inline _conj(a::ConjArray) = parent(a) -@inline _conj{T<:Real}(a::ConjArray{T}) = parent(a) +@inline _conj(a::ConjArray{T}) where {T<:Real} = parent(a) diff --git a/base/linalg/factorization.jl b/base/linalg/factorization.jl index df4066f3b495b..ac795b33167e9 100644 --- a/base/linalg/factorization.jl +++ b/base/linalg/factorization.jl @@ -28,7 +28,7 @@ end ### General promotion rules convert(::Type{Factorization{T}}, F::Factorization{T}) where {T} = F -inv{T}(F::Factorization{T}) = A_ldiv_B!(F, eye(T, size(F,1))) +inv(F::Factorization{T}) where {T} = A_ldiv_B!(F, eye(T, size(F,1))) # With a real lhs and complex rhs with the same precision, we can reinterpret # the complex rhs as a real rhs with twice the number of columns diff --git a/base/linalg/generic.jl b/base/linalg/generic.jl index 8892b5d9e0a44..733f5779c1c9d 100644 --- a/base/linalg/generic.jl +++ b/base/linalg/generic.jl @@ -350,7 +350,7 @@ end # faster computation of norm(x)^2, avoiding overflow for integers norm_sqr(x) = norm(x)^2 norm_sqr(x::Number) = abs2(x) -norm_sqr{T<:Integer}(x::Union{T,Complex{T},Rational{T}}) = abs2(float(x)) +norm_sqr(x::Union{T,Complex{T},Rational{T}}) where {T<:Integer} = abs2(float(x)) function generic_vecnorm2(x) maxabs = vecnormInf(x) @@ -451,10 +451,10 @@ end norm(x::AbstractVector, p::Real=2) = vecnorm(x, p) -function norm1{T}(A::AbstractMatrix{T}) +function norm1(A::AbstractMatrix{T}) where T m, n = size(A) Tnorm = typeof(float(real(zero(T)))) - Tsum = promote_type(Float64,Tnorm) + Tsum = promote_type(Float64, Tnorm) nrm::Tsum = 0 @inbounds begin for j = 1:n @@ -467,16 +467,16 @@ function norm1{T}(A::AbstractMatrix{T}) end return convert(Tnorm, nrm) end -function norm2{T}(A::AbstractMatrix{T}) +function norm2(A::AbstractMatrix{T}) where T m,n = size(A) if m == 1 || n == 1 return vecnorm2(A) end Tnorm = typeof(float(real(zero(T)))) (m == 0 || n == 0) ? zero(Tnorm) : convert(Tnorm, svdvals(A)[1]) end -function normInf{T}(A::AbstractMatrix{T}) +function normInf(A::AbstractMatrix{T}) where T m,n = size(A) Tnorm = typeof(float(real(zero(T)))) - Tsum = promote_type(Float64,Tnorm) + Tsum = promote_type(Float64, Tnorm) nrm::Tsum = 0 @inbounds begin for i = 1:m @@ -718,7 +718,7 @@ julia> M*N == N*M == eye(2) true ``` """ -function inv{T}(A::AbstractMatrix{T}) +function inv(A::AbstractMatrix{T}) where T S = typeof(zero(T)/one(T)) # dimensionful S0 = typeof(zero(T)/oneunit(T)) # dimensionless A_ldiv_B!(factorize(convert(AbstractMatrix{S}, A)), eye(S0, checksquare(A))) @@ -1154,7 +1154,7 @@ julia> det(M) 2.0 ``` """ -function det{T}(A::AbstractMatrix{T}) +function det(A::AbstractMatrix{T}) where T if istriu(A) || istril(A) S = typeof((one(T)*zero(T) + zero(T))/one(T)) return convert(S, det(UpperTriangular(A))) @@ -1197,7 +1197,7 @@ function logdet(A::AbstractMatrix) return d + log(s) end -NumberArray{T<:Number} = AbstractArray{T} +const NumberArray{T<:Number} = AbstractArray{T} """ promote_leaf_eltypes(itr) @@ -1219,9 +1219,9 @@ julia> promote_leaf_eltypes(a) Complex{Float64} ``` """ -promote_leaf_eltypes{T<:Number}(x::Union{AbstractArray{T},Tuple{Vararg{T}}}) = T -promote_leaf_eltypes{T<:NumberArray}(x::Union{AbstractArray{T},Tuple{Vararg{T}}}) = eltype(T) -promote_leaf_eltypes{T}(x::T) = T +promote_leaf_eltypes(x::Union{AbstractArray{T},Tuple{Vararg{T}}}) where {T<:Number} = T +promote_leaf_eltypes(x::Union{AbstractArray{T},Tuple{Vararg{T}}}) where {T<:NumberArray} = eltype(T) +promote_leaf_eltypes(x::T) where {T} = T promote_leaf_eltypes(x::Union{AbstractArray,Tuple}) = mapreduce(promote_leaf_eltypes, promote_type, Bool, x) # isapprox: approximate equality of arrays [like isapprox(Number,Number)] diff --git a/base/linalg/givens.jl b/base/linalg/givens.jl index a6b312db12e35..ed1c967ca5212 100644 --- a/base/linalg/givens.jl +++ b/base/linalg/givens.jl @@ -46,7 +46,7 @@ ctranspose(R::Rotation{T}) where {T} = Rotation{T}(reverse!([ctranspose(r) for r realmin2(::Type{Float32}) = reinterpret(Float32, 0x26000000) realmin2(::Type{Float64}) = reinterpret(Float64, 0x21a0000000000000) -realmin2{T}(::Type{T}) = (twopar = 2one(T); twopar^trunc(Integer,log(realmin(T)/eps(T))/log(twopar)/twopar)) +realmin2(::Type{T}) where {T} = (twopar = 2one(T); twopar^trunc(Integer,log(realmin(T)/eps(T))/log(twopar)/twopar)) # derived from LAPACK's dlartg # Copyright: @@ -54,7 +54,7 @@ realmin2{T}(::Type{T}) = (twopar = 2one(T); twopar^trunc(Integer,log(realmin(T)/ # Univ. of California Berkeley # Univ. of Colorado Denver # NAG Ltd. -function givensAlgorithm{T<:AbstractFloat}(f::T, g::T) +function givensAlgorithm(f::T, g::T) where T<:AbstractFloat onepar = one(T) twopar = 2one(T) T0 = typeof(onepar) # dimensionless @@ -128,7 +128,7 @@ end # Univ. of California Berkeley # Univ. of Colorado Denver # NAG Ltd. -function givensAlgorithm{T<:AbstractFloat}(f::Complex{T}, g::Complex{T}) +function givensAlgorithm(f::Complex{T}, g::Complex{T}) where T<:AbstractFloat twopar, onepar = 2one(T), one(T) T0 = typeof(onepar) # dimensionless zeropar = T0(zero(T)) # must be dimensionless @@ -252,7 +252,7 @@ y[i2] = 0 See also: [`LinAlg.Givens`](@ref) """ -function givens{T}(f::T, g::T, i1::Integer, i2::Integer) +function givens(f::T, g::T, i1::Integer, i2::Integer) where T if i1 == i2 throw(ArgumentError("Indices must be distinct.")) end diff --git a/base/linalg/ldlt.jl b/base/linalg/ldlt.jl index 156ab51bdbf56..53414b08aeee9 100644 --- a/base/linalg/ldlt.jl +++ b/base/linalg/ldlt.jl @@ -21,7 +21,7 @@ convert(::Type{Factorization{T}}, F::LDLt{S,U}) where {T,S,U} = convert(LDLt{T,U Same as [`ldltfact`](@ref), but saves space by overwriting the input `A`, instead of creating a copy. """ -function ldltfact!{T<:Real}(S::SymTridiagonal{T}) +function ldltfact!(S::SymTridiagonal{T}) where T<:Real n = size(S,1) d = S.dv e = S.ev @@ -39,14 +39,14 @@ Compute an `LDLt` factorization of a real symmetric tridiagonal matrix such that where `L` is a unit lower triangular matrix and `d` is a vector. The main use of an `LDLt` factorization `F = ldltfact(A)` is to solve the linear system of equations `Ax = b` with `F\\b`. """ -function ldltfact{T}(M::SymTridiagonal{T}) +function ldltfact(M::SymTridiagonal{T}) where T S = typeof(zero(T)/one(T)) return S == T ? ldltfact!(copy(M)) : ldltfact!(convert(SymTridiagonal{S}, M)) end factorize(S::SymTridiagonal) = ldltfact(S) -function A_ldiv_B!{T}(S::LDLt{T,SymTridiagonal{T}}, B::AbstractVecOrMat{T}) +function A_ldiv_B!(S::LDLt{T,SymTridiagonal{T}}, B::AbstractVecOrMat{T}) where T n, nrhs = size(B, 1), size(B, 2) if size(S,1) != n throw(DimensionMismatch("Matrix has dimensions $(size(S)) but right hand side has first dimension $n")) diff --git a/base/linalg/lu.jl b/base/linalg/lu.jl index 6f715ea76474d..577d1a7e97656 100644 --- a/base/linalg/lu.jl +++ b/base/linalg/lu.jl @@ -12,7 +12,7 @@ end LU(factors::AbstractMatrix{T}, ipiv::Vector{BlasInt}, info::BlasInt) where {T} = LU{T,typeof(factors)}(factors, ipiv, info) # StridedMatrix -function lufact!{T<:BlasFloat}(A::StridedMatrix{T}, pivot::Union{Type{Val{false}}, Type{Val{true}}} = Val{true}) +function lufact!(A::StridedMatrix{T}, pivot::Union{Type{Val{false}}, Type{Val{true}}} = Val{true}) where T<:BlasFloat if pivot === Val{false} return generic_lufact!(A, pivot) end @@ -29,11 +29,11 @@ exception is thrown if the factorization produces a number not representable by element type of `A`, e.g. for integer types. """ lufact!(A::StridedMatrix, pivot::Union{Type{Val{false}}, Type{Val{true}}} = Val{true}) = generic_lufact!(A, pivot) -function generic_lufact!{T,Pivot}(A::StridedMatrix{T}, ::Type{Val{Pivot}} = Val{true}) +function generic_lufact!(A::StridedMatrix{T}, ::Type{Val{Pivot}} = Val{true}) where {T,Pivot} m, n = size(A) minmn = min(m,n) info = 0 - ipiv = Array{BlasInt}(minmn) + ipiv = Vector{BlasInt}(minmn) @inbounds begin for k = 1:minmn # find index max @@ -78,9 +78,9 @@ function generic_lufact!{T,Pivot}(A::StridedMatrix{T}, ::Type{Val{Pivot}} = Val{ end # floating point types doesn't have to be promoted for LU, but should default to pivoting -lufact{T<:AbstractFloat}(A::Union{AbstractMatrix{T}, AbstractMatrix{Complex{T}}}, - pivot::Union{Type{Val{false}}, Type{Val{true}}} = Val{true}) = - lufact!(copy(A), pivot) +lufact(A::Union{AbstractMatrix{T}, AbstractMatrix{Complex{T}}}, + pivot::Union{Type{Val{false}}, Type{Val{true}}} = Val{true}) where {T<:AbstractFloat} = + lufact!(copy(A), pivot) # for all other types we must promote to a type which is stable under division """ @@ -135,14 +135,14 @@ julia> F[:L] * F[:U] == A[F[:p], :] true ``` """ -function lufact{T}(A::AbstractMatrix{T}, pivot::Union{Type{Val{false}}, Type{Val{true}}}) +function lufact(A::AbstractMatrix{T}, pivot::Union{Type{Val{false}}, Type{Val{true}}}) where T S = typeof(zero(T)/one(T)) AA = similar(A, S, size(A)) copy!(AA, A) lufact!(AA, pivot) end # We can't assume an ordered field so we first try without pivoting -function lufact{T}(A::AbstractMatrix{T}) +function lufact(A::AbstractMatrix{T}) where T S = typeof(zero(T)/one(T)) AA = similar(A, S, size(A)) copy!(AA, A) @@ -202,7 +202,7 @@ convert(::Type{Factorization{T}}, F::LU) where {T} = convert(LU{T}, F) size(A::LU) = size(A.factors) size(A::LU,n) = size(A.factors,n) -function ipiv2perm{T}(v::AbstractVector{T}, maxi::Integer) +function ipiv2perm(v::AbstractVector{T}, maxi::Integer) where T p = T[1:maxi;] @inbounds for i in 1:length(v) p[i], p[v[i]] = p[v[i]], p[i] @@ -210,7 +210,7 @@ function ipiv2perm{T}(v::AbstractVector{T}, maxi::Integer) return p end -function getindex{T}(F::LU{T,<:StridedMatrix}, d::Symbol) +function getindex(F::LU{T,<:StridedMatrix}, d::Symbol) where T m, n = size(F) if d == :L L = tril!(F.factors[1:m, 1:min(m,n)]) @@ -234,7 +234,7 @@ function show(io::IO, C::LU) show(io, C[:U]) end -A_ldiv_B!{T<:BlasFloat}(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) = +A_ldiv_B!(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = @assertnonsingular LAPACK.getrs!('N', A.factors, A.ipiv, B) A.info A_ldiv_B!(A::LU{<:Any,<:StridedMatrix}, b::StridedVector) = A_ldiv_B!(UpperTriangular(A.factors), @@ -243,7 +243,7 @@ A_ldiv_B!(A::LU{<:Any,<:StridedMatrix}, B::StridedMatrix) = A_ldiv_B!(UpperTriangular(A.factors), A_ldiv_B!(UnitLowerTriangular(A.factors), B[ipiv2perm(A.ipiv, size(B, 1)),:])) -At_ldiv_B!{T<:BlasFloat}(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) = +At_ldiv_B!(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = @assertnonsingular LAPACK.getrs!('T', A.factors, A.ipiv, B) A.info At_ldiv_B!(A::LU{<:Any,<:StridedMatrix}, b::StridedVector) = At_ldiv_B!(UnitLowerTriangular(A.factors), @@ -252,9 +252,9 @@ At_ldiv_B!(A::LU{<:Any,<:StridedMatrix}, B::StridedMatrix) = At_ldiv_B!(UnitLowerTriangular(A.factors), At_ldiv_B!(UpperTriangular(A.factors), B))[invperm(ipiv2perm(A.ipiv, size(B,1))),:] -Ac_ldiv_B!{T<:Real}(F::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) = +Ac_ldiv_B!(F::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:Real} = At_ldiv_B!(F, B) -Ac_ldiv_B!{T<:BlasComplex}(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) = +Ac_ldiv_B!(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:BlasComplex} = @assertnonsingular LAPACK.getrs!('C', A.factors, A.ipiv, B) A.info Ac_ldiv_B!(A::LU{<:Any,<:StridedMatrix}, b::StridedVector) = Ac_ldiv_B!(UnitLowerTriangular(A.factors), @@ -263,15 +263,15 @@ Ac_ldiv_B!(A::LU{<:Any,<:StridedMatrix}, B::StridedMatrix) = Ac_ldiv_B!(UnitLowerTriangular(A.factors), Ac_ldiv_B!(UpperTriangular(A.factors), B))[invperm(ipiv2perm(A.ipiv, size(B,1))),:] -At_ldiv_Bt{T<:BlasFloat}(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) = +At_ldiv_Bt(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = @assertnonsingular LAPACK.getrs!('T', A.factors, A.ipiv, transpose(B)) A.info At_ldiv_Bt(A::LU, B::StridedVecOrMat) = At_ldiv_B(A, transpose(B)) -Ac_ldiv_Bc{T<:BlasComplex}(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) = +Ac_ldiv_Bc(A::LU{T,<:StridedMatrix}, B::StridedVecOrMat{T}) where {T<:BlasComplex} = @assertnonsingular LAPACK.getrs!('C', A.factors, A.ipiv, ctranspose(B)) A.info Ac_ldiv_Bc(A::LU, B::StridedVecOrMat) = Ac_ldiv_B(A, ctranspose(B)) -function det{T}(A::LU{T}) +function det(A::LU{T}) where T n = checksquare(A) A.info > 0 && return zero(T) P = one(T) @@ -286,7 +286,7 @@ function det{T}(A::LU{T}) return P * s end -function logabsdet{T}(A::LU{T}) # return log(abs(det)) and sign(det) +function logabsdet(A::LU{T}) where T # return log(abs(det)) and sign(det) n = checksquare(A) A.info > 0 && return log(zero(real(T))), log(one(T)) c = 0 @@ -316,10 +316,10 @@ cond(A::LU, p::Number) = norm(A[:L]*A[:U],p)*norm(inv(A),p) # Tridiagonal # See dgttrf.f -function lufact!{T}(A::Tridiagonal{T}, pivot::Union{Type{Val{false}}, Type{Val{true}}} = Val{true}) +function lufact!(A::Tridiagonal{T}, pivot::Union{Type{Val{false}}, Type{Val{true}}} = Val{true}) where T n = size(A, 1) info = 0 - ipiv = Array{BlasInt}(n) + ipiv = Vector{BlasInt}(n) dl = A.dl d = A.d du = A.du @@ -408,7 +408,7 @@ function getindex(F::Base.LinAlg.LU{T,Tridiagonal{T}}, d::Symbol) where T end # See dgtts2.f -function A_ldiv_B!{T}(A::LU{T,Tridiagonal{T}}, B::AbstractVecOrMat) +function A_ldiv_B!(A::LU{T,Tridiagonal{T}}, B::AbstractVecOrMat) where T n = size(A,1) if n != size(B,1) throw(DimensionMismatch("matrix has dimensions ($n,$n) but right hand side has $(size(B,1)) rows")) @@ -439,7 +439,7 @@ function A_ldiv_B!{T}(A::LU{T,Tridiagonal{T}}, B::AbstractVecOrMat) return B end -function At_ldiv_B!{T}(A::LU{T,Tridiagonal{T}}, B::AbstractVecOrMat) +function At_ldiv_B!(A::LU{T,Tridiagonal{T}}, B::AbstractVecOrMat) where T n = size(A,1) if n != size(B,1) throw(DimensionMismatch("matrix has dimensions ($n,$n) but right hand side has $(size(B,1)) rows")) @@ -473,8 +473,8 @@ function At_ldiv_B!{T}(A::LU{T,Tridiagonal{T}}, B::AbstractVecOrMat) return B end -# Ac_ldiv_B!{T<:Real}(A::LU{T,Tridiagonal{T}}, B::AbstractVecOrMat) = At_ldiv_B!(A,B) -function Ac_ldiv_B!{T}(A::LU{T,Tridiagonal{T}}, B::AbstractVecOrMat) +# Ac_ldiv_B!(A::LU{T,Tridiagonal{T}}, B::AbstractVecOrMat) where {T<:Real} = At_ldiv_B!(A,B) +function Ac_ldiv_B!(A::LU{T,Tridiagonal{T}}, B::AbstractVecOrMat) where T n = size(A,1) if n != size(B,1) throw(DimensionMismatch("matrix has dimensions ($n,$n) but right hand side has $(size(B,1)) rows")) @@ -520,10 +520,10 @@ full(F::LU) = convert(AbstractArray, F) function convert(::Type{Tridiagonal}, F::Base.LinAlg.LU{T,Tridiagonal{T}}) where T n = size(F, 1) - dl = copy(F.factors.dl) - d = copy(F.factors.d) - du = copy(F.factors.du) - du2 = copy(F.factors.du2) + dl = copy(F.factors.dl) + d = copy(F.factors.d) + du = copy(F.factors.du) + du2 = copy(F.factors.du2) for i = n - 1:-1:1 li = dl[i] @@ -559,4 +559,4 @@ convert(::Type{Matrix}, F::Base.LinAlg.LU{T,Tridiagonal{T}}) where {T} = convert(Array, convert(AbstractArray, F)) convert(::Type{Array}, F::Base.LinAlg.LU{T,Tridiagonal{T}}) where {T} = convert(Matrix, F) -full{T}(F::Base.LinAlg.LU{T,Tridiagonal{T}}) = convert(AbstractArray, F) +full(F::Base.LinAlg.LU{T,Tridiagonal{T}}) where {T} = convert(AbstractArray, F) diff --git a/base/linalg/qr.jl b/base/linalg/qr.jl index 51d40690f6e05..b879ed801b780 100644 --- a/base/linalg/qr.jl +++ b/base/linalg/qr.jl @@ -133,7 +133,7 @@ end QRPivoted(factors::AbstractMatrix{T}, τ::Vector{T}, jpvt::Vector{BlasInt}) where {T} = QRPivoted{T,typeof(factors)}(factors, τ, jpvt) -function qrfactUnblocked!{T}(A::AbstractMatrix{T}) +function qrfactUnblocked!(A::AbstractMatrix{T}) where {T} m, n = size(A) τ = zeros(T, min(m,n)) for k = 1:min(m - 1 + !(T<:Real), n) @@ -162,7 +162,7 @@ end function qrfactPivotedUnblocked!(A::StridedMatrix) m, n = size(A) piv = collect(UnitRange{BlasInt}(1,n)) - τ = Array{eltype(A)}(min(m,n)) + τ = Vector{eltype(A)}(min(m,n)) for j = 1:min(m,n) # Find column with maximum norm in trailing submatrix @@ -270,12 +270,12 @@ true elementary reflectors, so that the `Q` and `R` matrices can be stored compactly rather as two separate dense matrices. """ -function qrfact{T}(A::AbstractMatrix{T}, arg) +function qrfact(A::AbstractMatrix{T}, arg) where T AA = similar(A, typeof(zero(T)/norm(one(T))), size(A)) copy!(AA, A) return qrfact!(AA, arg) end -function qrfact{T}(A::AbstractMatrix{T}) +function qrfact(A::AbstractMatrix{T}) where T AA = similar(A, typeof(zero(T)/norm(one(T))), size(A)) copy!(AA, A) return qrfact!(AA) @@ -686,11 +686,11 @@ for (f1, f2) in ((:Ac_mul_B, :A_mul_B!), end end -A_ldiv_B!{T<:BlasFloat}(A::QRCompactWY{T}, b::StridedVector{T}) = (A_ldiv_B!(UpperTriangular(A[:R]), view(Ac_mul_B!(A[:Q], b), 1:size(A, 2))); b) -A_ldiv_B!{T<:BlasFloat}(A::QRCompactWY{T}, B::StridedMatrix{T}) = (A_ldiv_B!(UpperTriangular(A[:R]), view(Ac_mul_B!(A[:Q], B), 1:size(A, 2), 1:size(B, 2))); B) +A_ldiv_B!(A::QRCompactWY{T}, b::StridedVector{T}) where {T<:BlasFloat} = (A_ldiv_B!(UpperTriangular(A[:R]), view(Ac_mul_B!(A[:Q], b), 1:size(A, 2))); b) +A_ldiv_B!(A::QRCompactWY{T}, B::StridedMatrix{T}) where {T<:BlasFloat} = (A_ldiv_B!(UpperTriangular(A[:R]), view(Ac_mul_B!(A[:Q], B), 1:size(A, 2), 1:size(B, 2))); B) # Julia implementation similarly to xgelsy -function A_ldiv_B!{T<:BlasFloat}(A::QRPivoted{T}, B::StridedMatrix{T}, rcond::Real) +function A_ldiv_B!(A::QRPivoted{T}, B::StridedMatrix{T}, rcond::Real) where T<:BlasFloat mA, nA = size(A.factors) nr = min(mA,nA) nrhs = size(B, 2) @@ -720,9 +720,9 @@ function A_ldiv_B!{T<:BlasFloat}(A::QRPivoted{T}, B::StridedMatrix{T}, rcond::Re B[1:nA,:] = view(B, 1:nA, :)[invperm(A[:p]::Vector{BlasInt}),:] return B, rnk end -A_ldiv_B!{T<:BlasFloat}(A::QRPivoted{T}, B::StridedVector{T}) = vec(A_ldiv_B!(A,reshape(B,length(B),1))) -A_ldiv_B!{T<:BlasFloat}(A::QRPivoted{T}, B::StridedVecOrMat{T}) = A_ldiv_B!(A, B, maximum(size(A))*eps(real(float(one(eltype(B))))))[1] -function A_ldiv_B!{T}(A::QR{T}, B::StridedMatrix{T}) +A_ldiv_B!(A::QRPivoted{T}, B::StridedVector{T}) where {T<:BlasFloat} = vec(A_ldiv_B!(A,reshape(B,length(B),1))) +A_ldiv_B!(A::QRPivoted{T}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = A_ldiv_B!(A, B, maximum(size(A))*eps(real(float(one(eltype(B))))))[1] +function A_ldiv_B!(A::QR{T}, B::StridedMatrix{T}) where T m, n = size(A) minmn = min(m,n) mB, nB = size(B) @@ -805,7 +805,7 @@ function _append_zeros(B::AbstractMatrix, T::Type, n) end end -function (\){TA,TB}(A::Union{QR{TA},QRCompactWY{TA},QRPivoted{TA}}, B::AbstractVecOrMat{TB}) +function (\)(A::Union{QR{TA},QRCompactWY{TA},QRPivoted{TA}}, B::AbstractVecOrMat{TB}) where {TA,TB} S = promote_type(TA,TB) m, n = size(A) m == size(B,1) || throw(DimensionMismatch("left hand side has $m rows, but right hand side has $(size(B,1)) rows")) @@ -824,7 +824,7 @@ end _ret_size(A::Factorization, b::AbstractVector) = (max(size(A, 2), length(b)),) _ret_size(A::Factorization, B::AbstractMatrix) = (max(size(A, 2), size(B, 1)), size(B, 2)) -function (\){T<:BlasReal}(A::Union{QR{T},QRCompactWY{T},QRPivoted{T}}, BIn::VecOrMat{Complex{T}}) +function (\)(A::Union{QR{T},QRCompactWY{T},QRPivoted{T}}, BIn::VecOrMat{Complex{T}}) where T<:BlasReal m, n = size(A) m == size(BIn, 1) || throw(DimensionMismatch("left hand side has $m rows, but right hand side has $(size(BIn,1)) rows")) diff --git a/base/linalg/rowvector.jl b/base/linalg/rowvector.jl index 513e379ad3c2b..e38111fd7e1d7 100644 --- a/base/linalg/rowvector.jl +++ b/base/linalg/rowvector.jl @@ -25,7 +25,7 @@ end @pure check_types(::Type{T1}, ::Type{T2}) where {T1,T2} = T1 === transpose_type(T2) ? nothing : error("Element type mismatch. Tried to create a `RowVector{$T1}` from an `AbstractVector{$T2}`") -ConjRowVector{T, CV <: ConjVector} = RowVector{T, CV} +const ConjRowVector{T,CV<:ConjVector} = RowVector{T,CV} # The element type may be transformed as transpose is recursive @inline transpose_type{T}(::Type{T}) = promote_op(transpose, T) diff --git a/base/linalg/schur.jl b/base/linalg/schur.jl index 5f4378cc9710e..be0cc0188bfc4 100644 --- a/base/linalg/schur.jl +++ b/base/linalg/schur.jl @@ -7,7 +7,7 @@ struct Schur{Ty,S<:AbstractMatrix} <: Factorization{Ty} values::Vector Schur{Ty,S}(T::AbstractMatrix{Ty}, Z::AbstractMatrix{Ty}, values::Vector) where {Ty,S} = new(T, Z, values) end -Schur(T::AbstractMatrix{Ty}, Z::AbstractMatrix{Ty}, values::Vector) where Ty = Schur{Ty, typeof(T)}(T, Z, values) +Schur(T::AbstractMatrix{Ty}, Z::AbstractMatrix{Ty}, values::Vector) where {Ty} = Schur{Ty, typeof(T)}(T, Z, values) """ schurfact!(A::StridedMatrix) -> F::Schur diff --git a/base/linalg/svd.jl b/base/linalg/svd.jl index db80313605e99..4ea9291873a89 100644 --- a/base/linalg/svd.jl +++ b/base/linalg/svd.jl @@ -20,7 +20,7 @@ If `thin=true` (default), a thin SVD is returned. For a ``M \\times N`` matrix `A`, `U` is ``M \\times M`` for a full SVD (`thin=false`) and ``M \\times \\min(M, N)`` for a thin SVD. """ -function svdfact!{T<:BlasFloat}(A::StridedMatrix{T}; thin::Bool=true) +function svdfact!(A::StridedMatrix{T}; thin::Bool=true) where T<:BlasFloat m,n = size(A) if m == 0 || n == 0 u,s,vt = (eye(T, m, thin ? n : m), real(zeros(T,0)), eye(T,n,n)) @@ -63,7 +63,7 @@ julia> F[:U] * diagm(F[:S]) * F[:Vt] 0.0 2.0 0.0 0.0 0.0 ``` """ -function svdfact{T}(A::StridedVecOrMat{T}; thin::Bool = true) +function svdfact(A::StridedVecOrMat{T}; thin::Bool = true) where T S = promote_type(Float32, typeof(one(T)/norm(one(T)))) svdfact!(copy_oftype(A, S), thin = thin) end @@ -130,7 +130,7 @@ end Returns the singular values of `A`, saving space by overwriting the input. See also [`svdvals`](@ref). """ -svdvals!{T<:BlasFloat}(A::StridedMatrix{T}) = findfirst(size(A), 0) > 0 ? zeros(T, 0) : LAPACK.gesdd!('N', A)[2] +svdvals!(A::StridedMatrix{T}) where {T<:BlasFloat} = findfirst(size(A), 0) > 0 ? zeros(T, 0) : LAPACK.gesdd!('N', A)[2] svdvals(A::AbstractMatrix{<:BlasFloat}) = svdvals!(copy(A)) """ @@ -156,12 +156,12 @@ julia> svdvals(A) 0.0 ``` """ -function svdvals{T}(A::AbstractMatrix{T}) +function svdvals(A::AbstractMatrix{T}) where T S = promote_type(Float32, typeof(one(T)/norm(one(T)))) svdvals!(copy_oftype(A, S)) end svdvals(x::Number) = abs(x) -svdvals{T}(S::SVD{<:Any,T}) = (S[:S])::Vector{T} +svdvals(S::SVD{<:Any,T}) where {T} = (S[:S])::Vector{T} # SVD least squares function A_ldiv_B!{T}(A::SVD{T}, B::StridedVecOrMat) @@ -195,7 +195,7 @@ end `svdfact!` is the same as [`svdfact`](@ref), but modifies the arguments `A` and `B` in-place, instead of making copies. """ -function svdfact!{T<:BlasFloat}(A::StridedMatrix{T}, B::StridedMatrix{T}) +function svdfact!(A::StridedMatrix{T}, B::StridedMatrix{T}) where T<:BlasFloat # xggsvd3 replaced xggsvd in LAPACK 3.6.0 if LAPACK.laver() < (3, 6, 0) U, V, Q, a, b, k, l, R = LAPACK.ggsvd!('U', 'V', 'Q', A, B) @@ -204,7 +204,7 @@ function svdfact!{T<:BlasFloat}(A::StridedMatrix{T}, B::StridedMatrix{T}) end GeneralizedSVD(U, V, Q, a, b, Int(k), Int(l), R) end -svdfact{T<:BlasFloat}(A::StridedMatrix{T}, B::StridedMatrix{T}) = svdfact!(copy(A),copy(B)) +svdfact(A::StridedMatrix{T}, B::StridedMatrix{T}) where {T<:BlasFloat} = svdfact!(copy(A),copy(B)) """ svdfact(A, B) -> GeneralizedSVD @@ -230,7 +230,7 @@ documentation for the [xGGSVD3](http://www.netlib.org/lapack/explore-html/d6/db3/dggsvd3_8f.html) routine which is called underneath (in LAPACK 3.6.0 and newer). """ -function svdfact{TA,TB}(A::StridedMatrix{TA}, B::StridedMatrix{TB}) +function svdfact(A::StridedMatrix{TA}, B::StridedMatrix{TB}) where {TA,TB} S = promote_type(Float32, typeof(one(TA)/norm(one(TA))),TB) return svdfact!(copy_oftype(A, S), copy_oftype(B, S)) end @@ -287,7 +287,7 @@ function getindex(obj::GeneralizedSVD{T}, d::Symbol) where T end end -function svdvals!{T<:BlasFloat}(A::StridedMatrix{T}, B::StridedMatrix{T}) +function svdvals!(A::StridedMatrix{T}, B::StridedMatrix{T}) where T<:BlasFloat # xggsvd3 replaced xggsvd in LAPACK 3.6.0 if LAPACK.laver() < (3, 6, 0) _, _, _, a, b, k, l, _ = LAPACK.ggsvd!('N', 'N', 'N', A, B) @@ -296,7 +296,7 @@ function svdvals!{T<:BlasFloat}(A::StridedMatrix{T}, B::StridedMatrix{T}) end a[1:k + l] ./ b[1:k + l] end -svdvals{T<:BlasFloat}(A::StridedMatrix{T},B::StridedMatrix{T}) = svdvals!(copy(A),copy(B)) +svdvals(A::StridedMatrix{T},B::StridedMatrix{T}) where {T<:BlasFloat} = svdvals!(copy(A),copy(B)) """ svdvals(A, B) @@ -304,7 +304,7 @@ svdvals{T<:BlasFloat}(A::StridedMatrix{T},B::StridedMatrix{T}) = svdvals!(copy(A Return the generalized singular values from the generalized singular value decomposition of `A` and `B`. See also [`svdfact`](@ref). """ -function svdvals{TA,TB}(A::StridedMatrix{TA}, B::StridedMatrix{TB}) +function svdvals(A::StridedMatrix{TA}, B::StridedMatrix{TB}) where {TA,TB} S = promote_type(Float32, typeof(one(TA)/norm(one(TA))), TB) return svdvals!(copy_oftype(A, S), copy_oftype(B, S)) end diff --git a/base/linalg/symmetric.jl b/base/linalg/symmetric.jl index 83485d2701469..1d2e6eecdd5a0 100644 --- a/base/linalg/symmetric.jl +++ b/base/linalg/symmetric.jl @@ -40,7 +40,7 @@ julia> Slower = Symmetric(A, :L) Note that `Supper` will not be equal to `Slower` unless `A` is itself symmetric (e.g. if `A == A.'`). """ -Symmetric(A::AbstractMatrix, uplo::Symbol=:U) = (checksquare(A);Symmetric{eltype(A),typeof(A)}(A, char_uplo(uplo))) +Symmetric(A::AbstractMatrix, uplo::Symbol=:U) = (checksquare(A); Symmetric{eltype(A),typeof(A)}(A, char_uplo(uplo))) struct Hermitian{T,S<:AbstractMatrix} <: AbstractMatrix{T} data::S uplo::Char @@ -83,8 +83,8 @@ function Hermitian(A::AbstractMatrix, uplo::Symbol=:U) Hermitian{eltype(A),typeof(A)}(A, char_uplo(uplo)) end -HermOrSym{T,S} = Union{Hermitian{T,S}, Symmetric{T,S}} -RealHermSymComplexHerm{T<:Real,S} = Union{Hermitian{T,S}, Symmetric{T,S}, Hermitian{Complex{T},S}} +const HermOrSym{T,S} = Union{Hermitian{T,S}, Symmetric{T,S}} +const RealHermSymComplexHerm{T<:Real,S} = Union{Hermitian{T,S}, Symmetric{T,S}, Hermitian{Complex{T},S}} size(A::HermOrSym, d) = size(A.data, d) size(A::HermOrSym) = size(A.data) @@ -233,13 +233,19 @@ end (-)(A::Symmetric{Tv,S}) where {Tv,S<:AbstractMatrix} = Symmetric{Tv,S}(-A.data, A.uplo) ## Matvec -A_mul_B!{T<:BlasFloat}(y::StridedVector{T}, A::Symmetric{T,<:StridedMatrix}, x::StridedVector{T}) = BLAS.symv!(A.uplo, one(T), A.data, x, zero(T), y) -A_mul_B!{T<:BlasComplex}(y::StridedVector{T}, A::Hermitian{T,<:StridedMatrix}, x::StridedVector{T}) = BLAS.hemv!(A.uplo, one(T), A.data, x, zero(T), y) +A_mul_B!(y::StridedVector{T}, A::Symmetric{T,<:StridedMatrix}, x::StridedVector{T}) where {T<:BlasFloat} = + BLAS.symv!(A.uplo, one(T), A.data, x, zero(T), y) +A_mul_B!(y::StridedVector{T}, A::Hermitian{T,<:StridedMatrix}, x::StridedVector{T}) where {T<:BlasComplex} = + BLAS.hemv!(A.uplo, one(T), A.data, x, zero(T), y) ## Matmat -A_mul_B!{T<:BlasFloat}(C::StridedMatrix{T}, A::Symmetric{T,<:StridedMatrix}, B::StridedMatrix{T}) = BLAS.symm!('L', A.uplo, one(T), A.data, B, zero(T), C) -A_mul_B!{T<:BlasFloat}(C::StridedMatrix{T}, A::StridedMatrix{T}, B::Symmetric{T,<:StridedMatrix}) = BLAS.symm!('R', B.uplo, one(T), B.data, A, zero(T), C) -A_mul_B!{T<:BlasComplex}(C::StridedMatrix{T}, A::Hermitian{T,<:StridedMatrix}, B::StridedMatrix{T}) = BLAS.hemm!('L', A.uplo, one(T), A.data, B, zero(T), C) -A_mul_B!{T<:BlasComplex}(C::StridedMatrix{T}, A::StridedMatrix{T}, B::Hermitian{T,<:StridedMatrix}) = BLAS.hemm!('R', B.uplo, one(T), B.data, A, zero(T), C) +A_mul_B!(C::StridedMatrix{T}, A::Symmetric{T,<:StridedMatrix}, B::StridedMatrix{T}) where {T<:BlasFloat} = + BLAS.symm!('L', A.uplo, one(T), A.data, B, zero(T), C) +A_mul_B!(C::StridedMatrix{T}, A::StridedMatrix{T}, B::Symmetric{T,<:StridedMatrix}) where {T<:BlasFloat} = + BLAS.symm!('R', B.uplo, one(T), B.data, A, zero(T), C) +A_mul_B!(C::StridedMatrix{T}, A::Hermitian{T,<:StridedMatrix}, B::StridedMatrix{T}) where {T<:BlasComplex} = + BLAS.hemm!('L', A.uplo, one(T), A.data, B, zero(T), C) +A_mul_B!(C::StridedMatrix{T}, A::StridedMatrix{T}, B::Hermitian{T,<:StridedMatrix}) where {T<:BlasComplex} = + BLAS.hemm!('R', B.uplo, one(T), B.data, A, zero(T), C) *(A::HermOrSym, B::HermOrSym) = full(A)*full(B) *(A::StridedMatrix, B::HermOrSym) = A*full(B) @@ -254,15 +260,14 @@ end bkfact(A::HermOrSym) = bkfact(A.data, Symbol(A.uplo), issymmetric(A)) factorize(A::HermOrSym) = bkfact(A) -# Is just RealHermSymComplexHerm, but type alias seems to be broken -det{T<:Real,S}(A::Union{Hermitian{T,S}, Symmetric{T,S}, Hermitian{Complex{T},S}}) = real(det(bkfact(A))) +det(A::RealHermSymComplexHerm) = real(det(bkfact(A))) det(A::Symmetric{<:Real}) = det(bkfact(A)) det(A::Symmetric) = det(bkfact(A)) \(A::HermOrSym{<:Any,<:StridedMatrix}, B::StridedVecOrMat) = \(bkfact(A.data, Symbol(A.uplo), issymmetric(A)), B) -inv{T<:BlasFloat,S<:StridedMatrix}(A::Hermitian{T,S}) = Hermitian{T,S}(inv(bkfact(A)), A.uplo) -inv{T<:BlasFloat,S<:StridedMatrix}(A::Symmetric{T,S}) = Symmetric{T,S}(inv(bkfact(A)), A.uplo) +inv(A::Hermitian{T,S}) where {T<:BlasFloat,S<:StridedMatrix} = Hermitian{T,S}(inv(bkfact(A)), A.uplo) +inv(A::Symmetric{T,S}) where {T<:BlasFloat,S<:StridedMatrix} = Symmetric{T,S}(inv(bkfact(A)), A.uplo) eigfact!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}) = Eigen(LAPACK.syevr!('V', 'A', A.uplo, A.data, 0.0, 0.0, 0, 0, -1.0)...) # Because of #6721 it is necessary to specify the parameters explicitly here. @@ -288,7 +293,8 @@ The `UnitRange` `irange` specifies indices of the sorted eigenvalues to search f """ eigfact(A::RealHermSymComplexHerm{<:Real}, irange::UnitRange) = (T = eltype(A); S = promote_type(Float32, typeof(zero(T)/norm(one(T)))); eigfact!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), irange)) -eigfact!{T<:BlasReal}(A::RealHermSymComplexHerm{T,<:StridedMatrix}, vl::Real, vh::Real) = Eigen(LAPACK.syevr!('V', 'V', A.uplo, A.data, convert(T, vl), convert(T, vh), 0, 0, -1.0)...) +eigfact!(A::RealHermSymComplexHerm{T,<:StridedMatrix}, vl::Real, vh::Real) where {T<:BlasReal} = + Eigen(LAPACK.syevr!('V', 'V', A.uplo, A.data, convert(T, vl), convert(T, vh), 0, 0, -1.0)...) # Because of #6721 it is necessary to specify the parameters explicitly here. """ eigfact(A::Union{SymTridiagonal, Hermitian, Symmetric}, vl::Real, vu::Real) -> Eigen @@ -307,7 +313,8 @@ The following functions are available for `Eigen` objects: [`inv`](@ref), [`det` """ eigfact(A::RealHermSymComplexHerm{<:Real}, vl::Real, vh::Real) = (T = eltype(A); S = promote_type(Float32, typeof(zero(T)/norm(one(T)))); eigfact!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), vl, vh)) -eigvals!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}) = LAPACK.syevr!('N', 'A', A.uplo, A.data, 0.0, 0.0, 0, 0, -1.0)[1] +eigvals!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}) = + LAPACK.syevr!('N', 'A', A.uplo, A.data, 0.0, 0.0, 0, 0, -1.0)[1] # Because of #6721 it is necessary to specify the parameters explicitly here. eigvals(A::RealHermSymComplexHerm{<:Real}) = (T = eltype(A); S = promote_type(Float32, typeof(zero(T)/norm(one(T)))); eigvals!(S != T ? convert(AbstractMatrix{S}, A) : copy(A))) @@ -352,7 +359,8 @@ eigvals(A::RealHermSymComplexHerm{<:Real}, irange::UnitRange) = (T = eltype(A); Same as [`eigvals`](@ref), but saves space by overwriting the input `A`, instead of creating a copy. `vl` is the lower bound of the interval to search for eigenvalues, and `vu` is the upper bound. """ -eigvals!{T<:BlasReal}(A::RealHermSymComplexHerm{T,<:StridedMatrix}, vl::Real, vh::Real) = LAPACK.syevr!('N', 'V', A.uplo, A.data, convert(T, vl), convert(T, vh), 0, 0, -1.0)[1] +eigvals!(A::RealHermSymComplexHerm{T,<:StridedMatrix}, vl::Real, vh::Real) where {T<:BlasReal} = + LAPACK.syevr!('N', 'V', A.uplo, A.data, convert(T, vl), convert(T, vh), 0, 0, -1.0)[1] # Because of #6721 it is necessary to specify the parameters explicitly here. """ eigvals(A::Union{SymTridiagonal, Hermitian, Symmetric}, vl::Real, vu::Real) -> values @@ -378,24 +386,30 @@ julia> eigvals(A) 5.14005 ``` """ -eigvals(A::RealHermSymComplexHerm{<:Real}, vl::Real, vh::Real) = (T = eltype(A); S = promote_type(Float32, typeof(zero(T)/norm(one(T)))); eigvals!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), vl, vh)) +function eigvals(A::RealHermSymComplexHerm{<:Real}, vl::Real, vh::Real) + T = eltype(A) + S = promote_type(Float32, typeof(zero(T)/norm(one(T)))) + eigvals!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), vl, vh) +end eigmax(A::RealHermSymComplexHerm{<:Real,<:StridedMatrix}) = eigvals(A, size(A, 1):size(A, 1))[1] eigmin(A::RealHermSymComplexHerm{<:Real,<:StridedMatrix}) = eigvals(A, 1:1)[1] -function eigfact!{T<:BlasReal,S<:StridedMatrix}(A::HermOrSym{T,S}, B::HermOrSym{T,S}) +function eigfact!(A::HermOrSym{T,S}, B::HermOrSym{T,S}) where {T<:BlasReal,S<:StridedMatrix} vals, vecs, _ = LAPACK.sygvd!(1, 'V', A.uplo, A.data, B.uplo == A.uplo ? B.data : B.data') GeneralizedEigen(vals, vecs) end -function eigfact!{T<:BlasComplex,S<:StridedMatrix}(A::Hermitian{T,S}, B::Hermitian{T,S}) +function eigfact!(A::Hermitian{T,S}, B::Hermitian{T,S}) where {T<:BlasComplex,S<:StridedMatrix} vals, vecs, _ = LAPACK.sygvd!(1, 'V', A.uplo, A.data, B.uplo == A.uplo ? B.data : B.data') GeneralizedEigen(vals, vecs) end -eigvals!{T<:BlasReal,S<:StridedMatrix}(A::HermOrSym{T,S}, B::HermOrSym{T,S}) = LAPACK.sygvd!(1, 'N', A.uplo, A.data, B.uplo == A.uplo ? B.data : B.data')[1] -eigvals!{T<:BlasComplex,S<:StridedMatrix}(A::Hermitian{T,S}, B::Hermitian{T,S}) = LAPACK.sygvd!(1, 'N', A.uplo, A.data, B.uplo == A.uplo ? B.data : B.data')[1] +eigvals!(A::HermOrSym{T,S}, B::HermOrSym{T,S}) where {T<:BlasReal,S<:StridedMatrix} = + LAPACK.sygvd!(1, 'N', A.uplo, A.data, B.uplo == A.uplo ? B.data : B.data')[1] +eigvals!(A::Hermitian{T,S}, B::Hermitian{T,S}) where {T<:BlasComplex,S<:StridedMatrix} = + LAPACK.sygvd!(1, 'N', A.uplo, A.data, B.uplo == A.uplo ? B.data : B.data')[1] -function svdvals!{T<:Real,S}(A::Union{Hermitian{T,S}, Symmetric{T,S}, Hermitian{Complex{T},S}}) # the union is the same as RealHermSymComplexHerm, but right now parametric typealiases are broken +function svdvals!(A::RealHermSymComplexHerm) vals = eigvals!(A) for i = 1:length(vals) vals[i] = abs(vals[i]) @@ -404,14 +418,14 @@ function svdvals!{T<:Real,S}(A::Union{Hermitian{T,S}, Symmetric{T,S}, Hermitian{ end # Matrix functions -function ^{T<:Real}(A::Symmetric{T}, p::Integer) +function ^(A::Symmetric{T}, p::Integer) where T<:Real if p < 0 return Symmetric(Base.power_by_squaring(inv(A), -p)) else return Symmetric(Base.power_by_squaring(A, p)) end end -function ^{T<:Real}(A::Symmetric{T}, p::Real) +function ^(A::Symmetric{T}, p::Real) where T<:Real F = eigfact(A) if all(λ -> λ ≥ 0, F.values) retmat = (F.vectors * Diagonal((F.values).^p)) * F.vectors' @@ -432,7 +446,7 @@ function ^(A::Hermitian, p::Integer) end return Hermitian(retmat) end -function ^{T}(A::Hermitian{T}, p::Real) +function ^(A::Hermitian{T}, p::Real) where T n = checksquare(A) F = eigfact(A) if all(λ -> λ ≥ 0, F.values) @@ -471,7 +485,7 @@ end for (funm, func) in ([:logm,:log], [:sqrtm,:sqrt]) @eval begin - function ($funm){T<:Real}(A::Symmetric{T}) + function ($funm)(A::Symmetric{T}) where T<:Real F = eigfact(A) if isposdef(F) retmat = (F.vectors * Diagonal(($func).(F.values))) * F.vectors' @@ -481,7 +495,7 @@ for (funm, func) in ([:logm,:log], [:sqrtm,:sqrt]) return Symmetric(retmat) end - function ($funm){T}(A::Hermitian{T}) + function ($funm)(A::Hermitian{T}) where T n = checksquare(A) F = eigfact(A) if isposdef(F) diff --git a/base/linalg/transpose.jl b/base/linalg/transpose.jl index 4bafa9e4e6c7b..d2b51e798e4cc 100644 --- a/base/linalg/transpose.jl +++ b/base/linalg/transpose.jl @@ -42,7 +42,7 @@ function ctranspose!(B::AbstractMatrix, A::AbstractVector) end const transposebaselength=64 -function transpose_f!(f,B::AbstractMatrix,A::AbstractMatrix) +function transpose_f!(f, B::AbstractMatrix, A::AbstractMatrix) inds = indices(A) indices(B,1) == inds[2] && indices(B,2) == inds[1] || throw(DimensionMismatch(string(f))) @@ -60,7 +60,7 @@ function transpose_f!(f,B::AbstractMatrix,A::AbstractMatrix) end return B end -function transposeblock!(f,B::AbstractMatrix,A::AbstractMatrix,m::Int,n::Int,offseti::Int,offsetj::Int) +function transposeblock!(f, B::AbstractMatrix, A::AbstractMatrix, m::Int, n::Int, offseti::Int, offsetj::Int) if m*n<=transposebaselength @inbounds begin for j = offsetj+(1:n) diff --git a/base/linalg/triangular.jl b/base/linalg/triangular.jl index 097a20441e41a..7e1f0944fb1a8 100644 --- a/base/linalg/triangular.jl +++ b/base/linalg/triangular.jl @@ -207,7 +207,7 @@ function tril!(A::UpperTriangular, k::Integer=0) end triu!(A::UpperTriangular, k::Integer=0) = UpperTriangular(triu!(A.data,k)) -function tril!{T}(A::UnitUpperTriangular{T}, k::Integer=0) +function tril!(A::UnitUpperTriangular{T}, k::Integer=0) where T n = size(A,1) if abs(k) > n throw(ArgumentError("requested diagonal, $k, out of bounds in matrix of size ($n,$n)")) diff --git a/base/linalg/tridiag.jl b/base/linalg/tridiag.jl index a749ff94338ef..68c76706a7f2f 100644 --- a/base/linalg/tridiag.jl +++ b/base/linalg/tridiag.jl @@ -112,7 +112,7 @@ broadcast(::typeof(ceil), ::Type{T}, M::SymTridiagonal) where {T<:Integer} = Sym transpose(M::SymTridiagonal) = M #Identity operation ctranspose(M::SymTridiagonal) = conj(M) -function diag{T}(M::SymTridiagonal{T}, n::Integer=0) +function diag(M::SymTridiagonal{T}, n::Integer=0) where T absn = abs(n) if absn == 0 return M.dv @@ -163,41 +163,41 @@ end (\)(T::SymTridiagonal, B::StridedVecOrMat) = ldltfact(T)\B eigfact!(A::SymTridiagonal{<:BlasReal}) = Eigen(LAPACK.stegr!('V', A.dv, A.ev)...) -function eigfact{T}(A::SymTridiagonal{T}) +function eigfact(A::SymTridiagonal{T}) where T S = promote_type(Float32, typeof(zero(T)/norm(one(T)))) eigfact!(copy_oftype(A, S)) end eigfact!(A::SymTridiagonal{<:BlasReal}, irange::UnitRange) = Eigen(LAPACK.stegr!('V', 'I', A.dv, A.ev, 0.0, 0.0, irange.start, irange.stop)...) -function eigfact{T}(A::SymTridiagonal{T}, irange::UnitRange) +function eigfact(A::SymTridiagonal{T}, irange::UnitRange) where T S = promote_type(Float32, typeof(zero(T)/norm(one(T)))) return eigfact!(copy_oftype(A, S), irange) end eigfact!(A::SymTridiagonal{<:BlasReal}, vl::Real, vu::Real) = Eigen(LAPACK.stegr!('V', 'V', A.dv, A.ev, vl, vu, 0, 0)...) -function eigfact{T}(A::SymTridiagonal{T}, vl::Real, vu::Real) +function eigfact(A::SymTridiagonal{T}, vl::Real, vu::Real) where T S = promote_type(Float32, typeof(zero(T)/norm(one(T)))) return eigfact!(copy_oftype(A, S), vl, vu) end eigvals!(A::SymTridiagonal{<:BlasReal}) = LAPACK.stev!('N', A.dv, A.ev)[1] -function eigvals{T}(A::SymTridiagonal{T}) +function eigvals(A::SymTridiagonal{T}) where T S = promote_type(Float32, typeof(zero(T)/norm(one(T)))) return eigvals!(copy_oftype(A, S)) end eigvals!(A::SymTridiagonal{<:BlasReal}, irange::UnitRange) = LAPACK.stegr!('N', 'I', A.dv, A.ev, 0.0, 0.0, irange.start, irange.stop)[1] -function eigvals{T}(A::SymTridiagonal{T}, irange::UnitRange) +function eigvals(A::SymTridiagonal{T}, irange::UnitRange) where T S = promote_type(Float32, typeof(zero(T)/norm(one(T)))) return eigvals!(copy_oftype(A, S), irange) end eigvals!(A::SymTridiagonal{<:BlasReal}, vl::Real, vu::Real) = LAPACK.stegr!('N', 'V', A.dv, A.ev, vl, vu, 0, 0)[1] -function eigvals{T}(A::SymTridiagonal{T}, vl::Real, vu::Real) +function eigvals(A::SymTridiagonal{T}, vl::Real, vu::Real) where T S = promote_type(Float32, typeof(zero(T)/norm(one(T)))) return eigvals!(copy_oftype(A, S), vl, vu) end @@ -297,12 +297,12 @@ end mutable struct ZeroOffsetVector data::Vector end -getindex( a::ZeroOffsetVector, i) = a.data[i+1] +getindex(a::ZeroOffsetVector, i) = a.data[i+1] setindex!(a::ZeroOffsetVector, x, i) = a.data[i+1]=x ## structured matrix methods ## -function Base.replace_in_print_matrix(A::SymTridiagonal,i::Integer,j::Integer,s::AbstractString) +function Base.replace_in_print_matrix(A::SymTridiagonal, i::Integer, j::Integer, s::AbstractString) i==j-1||i==j||i==j+1 ? s : Base.replace_with_centered_mark(s) end @@ -313,7 +313,7 @@ end # R. Usmani, "Inversion of a tridiagonal Jacobi matrix", # Linear Algebra and its Applications 212-213 (1994), pp.413-414 # doi:10.1016/0024-3795(94)90414-6 -function inv_usmani{T}(a::Vector{T}, b::Vector{T}, c::Vector{T}) +function inv_usmani(a::Vector{T}, b::Vector{T}, c::Vector{T}) where T n = length(b) θ = ZeroOffsetVector(zeros(T, n+1)) #principal minors of A θ[0] = 1 @@ -343,7 +343,7 @@ end #Implements the determinant using principal minors #Inputs and reference are as above for inv_usmani() -function det_usmani{T}(a::Vector{T}, b::Vector{T}, c::Vector{T}) +function det_usmani(a::Vector{T}, b::Vector{T}, c::Vector{T}) where T n = length(b) θa = one(T) if n == 0 @@ -432,7 +432,7 @@ julia> Tridiagonal(dl, d, du) ``` """ # Basic constructor takes in three dense vectors of same type -function Tridiagonal{T}(dl::Vector{T}, d::Vector{T}, du::Vector{T}) +function Tridiagonal(dl::Vector{T}, d::Vector{T}, du::Vector{T}) where T n = length(d) if (length(dl) != n-1 || length(du) != n-1) throw(ArgumentError("cannot make Tridiagonal from incompatible lengths of subdiagonal, diagonal and superdiagonal: ($(length(dl)), $(length(d)), $(length(du))")) @@ -441,7 +441,7 @@ function Tridiagonal{T}(dl::Vector{T}, d::Vector{T}, du::Vector{T}) end # Construct from diagonals of any abstract vector, any eltype -function Tridiagonal{Tl, Td, Tu}(dl::AbstractVector{Tl}, d::AbstractVector{Td}, du::AbstractVector{Tu}) +function Tridiagonal(dl::AbstractVector{Tl}, d::AbstractVector{Td}, du::AbstractVector{Tu}) where {Tl,Td,Tu} Tridiagonal(map(v->convert(Vector{promote_type(Tl,Td,Tu)}, v), (dl, d, du))...) end @@ -529,7 +529,7 @@ broadcast(::typeof(ceil), ::Type{T}, M::Tridiagonal) where {T<:Integer} = transpose(M::Tridiagonal) = Tridiagonal(M.du, M.d, M.dl) ctranspose(M::Tridiagonal) = conj(transpose(M)) -function diag{T}(M::Tridiagonal{T}, n::Integer=0) +function diag(M::Tridiagonal{T}, n::Integer=0) where T if n == 0 return M.d elseif n == -1 diff --git a/base/linalg/uniformscaling.jl b/base/linalg/uniformscaling.jl index efedb0f345d59..92f1c81434d58 100644 --- a/base/linalg/uniformscaling.jl +++ b/base/linalg/uniformscaling.jl @@ -191,15 +191,15 @@ end # in A to matrices of type T and sizes given by n[k:end]. n is an array # so that the same promotion code can be used for hvcat. We pass the type T # so that we can re-use this code for sparse-matrix hcat etcetera. -promote_to_arrays_{T}(n::Int, ::Type{Matrix}, J::UniformScaling{T}) = copy!(Matrix{T}(n,n), J) +promote_to_arrays_(n::Int, ::Type{Matrix}, J::UniformScaling{T}) where {T} = copy!(Matrix{T}(n,n), J) promote_to_arrays_(n::Int, ::Type, A::AbstractVecOrMat) = A promote_to_arrays(n,k, ::Type) = () -promote_to_arrays{T}(n,k, ::Type{T}, A) = (promote_to_arrays_(n[k], T, A),) -promote_to_arrays{T}(n,k, ::Type{T}, A, B) = +promote_to_arrays(n,k, ::Type{T}, A) where {T} = (promote_to_arrays_(n[k], T, A),) +promote_to_arrays(n,k, ::Type{T}, A, B) where {T} = (promote_to_arrays_(n[k], T, A), promote_to_arrays_(n[k+1], T, B)) -promote_to_arrays{T}(n,k, ::Type{T}, A, B, C) = +promote_to_arrays(n,k, ::Type{T}, A, B, C) where {T} = (promote_to_arrays_(n[k], T, A), promote_to_arrays_(n[k+1], T, B), promote_to_arrays_(n[k+2], T, C)) -promote_to_arrays{T}(n,k, ::Type{T}, A, B, Cs...) = +promote_to_arrays(n,k, ::Type{T}, A, B, Cs...) where {T} = (promote_to_arrays_(n[k], T, A), promote_to_arrays_(n[k+1], T, B), promote_to_arrays(n,k+2, T, Cs...)...) promote_to_array_type(A::Tuple{Vararg{Union{AbstractVecOrMat,UniformScaling}}}) = (@_pure_meta; Matrix) diff --git a/base/sharedarray.jl b/base/sharedarray.jl index ea4c4b3a0a1b9..bcb78ec050728 100644 --- a/base/sharedarray.jl +++ b/base/sharedarray.jl @@ -77,7 +77,7 @@ beginning of the file. """ SharedArray -function (::Type{SharedArray{T,N}})(dims::Dims{N}; init=false, pids=Int[]) where T where N +function SharedArray{T,N}(dims::Dims{N}; init=false, pids=Int[]) where T where N isbits(T) || throw(ArgumentError("type of SharedArray elements must be bits types, got $(T)")) pids, onlocalhost = shared_pids(pids) @@ -134,17 +134,17 @@ function (::Type{SharedArray{T,N}})(dims::Dims{N}; init=false, pids=Int[]) where S end -(::Type{SharedArray{T,N}})(I::Integer...; kwargs...) where {T,N} = +SharedArray{T,N}(I::Integer...; kwargs...) where {T,N} = SharedArray{T,N}(I; kwargs...) -(::Type{SharedArray{T}})(d::NTuple; kwargs...) where {T} = +SharedArray{T}(d::NTuple; kwargs...) where {T} = SharedArray{T,length(d)}(d; kwargs...) -(::Type{SharedArray{T}})(I::Integer...; kwargs...) where {T} = +SharedArray{T}(I::Integer...; kwargs...) where {T} = SharedArray{T,length(I)}(I; kwargs...) -(::Type{SharedArray{T}})(m::Integer; kwargs...) where {T} = +SharedArray{T}(m::Integer; kwargs...) where {T} = SharedArray{T,1}(m; kwargs...) -(::Type{SharedArray{T}})(m::Integer, n::Integer; kwargs...) where {T} = +SharedArray{T}(m::Integer, n::Integer; kwargs...) where {T} = SharedArray{T,2}(m, n; kwargs...) -(::Type{SharedArray{T}})(m::Integer, n::Integer, o::Integer; kwargs...) where {T} = +SharedArray{T}(m::Integer, n::Integer, o::Integer; kwargs...) where {T} = SharedArray{T,3}(m, n, o; kwargs...) function (::Type{SharedArray{T,N}})(filename::AbstractString, dims::NTuple{N,Int}, offset::Integer=0; @@ -213,8 +213,8 @@ function (::Type{SharedArray{T,N}})(filename::AbstractString, dims::NTuple{N,Int S end -(::Type{SharedArray{T}})(filename::AbstractString, dims::NTuple{N,Int}, offset::Integer=0; - mode=nothing, init=false, pids::Vector{Int}=Int[]) where {T,N} = +SharedArray{T}(filename::AbstractString, dims::NTuple{N,Int}, offset::Integer=0; + mode=nothing, init=false, pids::Vector{Int}=Int[]) where {T,N} = SharedArray{T,N}(filename, dims, offset; mode=mode, init=init, pids=pids) function initialize_shared_array(S, onlocalhost, init, pids) @@ -250,8 +250,8 @@ function finalize_refs(S::SharedArray{T,N}) where T where N S end -SharedVector{T} = SharedArray{T,1} -SharedMatrix{T} = SharedArray{T,2} +const SharedVector{T} = SharedArray{T,1} +const SharedMatrix{T} = SharedArray{T,2} length(S::SharedArray) = prod(S.dims) size(S::SharedArray) = S.dims diff --git a/base/sparse/abstractsparse.jl b/base/sparse/abstractsparse.jl index e2f0cd9000f63..6de3403b5d6de 100644 --- a/base/sparse/abstractsparse.jl +++ b/base/sparse/abstractsparse.jl @@ -2,8 +2,8 @@ abstract type AbstractSparseArray{Tv,Ti,N} <: AbstractArray{Tv,N} end -AbstractSparseVector{Tv,Ti} = AbstractSparseArray{Tv,Ti,1} -AbstractSparseMatrix{Tv,Ti} = AbstractSparseArray{Tv,Ti,2} +const AbstractSparseVector{Tv,Ti} = AbstractSparseArray{Tv,Ti,1} +const AbstractSparseMatrix{Tv,Ti} = AbstractSparseArray{Tv,Ti,2} """ issparse(S) @@ -20,4 +20,4 @@ issparse(S::LinAlg.UnitLowerTriangular{<:Any,<:AbstractSparseMatrix}) = true issparse(S::UpperTriangular{<:Any,<:AbstractSparseMatrix}) = true issparse(S::LinAlg.UnitUpperTriangular{<:Any,<:AbstractSparseMatrix}) = true -indtype{Tv,Ti}(S::AbstractSparseArray{Tv,Ti}) = (Base.@_pure_meta; Ti) +indtype(S::AbstractSparseArray{<:Any,Ti}) where {Ti} = (Base.@_pure_meta; Ti) diff --git a/base/sparse/cholmod.jl b/base/sparse/cholmod.jl index 85cdb5cd4743c..a8688986ed90a 100644 --- a/base/sparse/cholmod.jl +++ b/base/sparse/cholmod.jl @@ -392,7 +392,7 @@ end free_dense!(p::Ptr{C_Dense{T}}) where {T} = ccall((:cholmod_l_free_dense, :libcholmod), Cint, (Ref{Ptr{C_Dense{T}}}, Ptr{Void}), p, common()) -function zeros{T<:VTypes}(m::Integer, n::Integer, ::Type{T}) +function zeros(m::Integer, n::Integer, ::Type{T}) where T<:VTypes d = Dense(ccall((:cholmod_l_zeros, :libcholmod), Ptr{C_Dense{T}}, (Csize_t, Csize_t, Cint, Ptr{UInt8}), m, n, xtyp(T), common())) @@ -401,7 +401,7 @@ function zeros{T<:VTypes}(m::Integer, n::Integer, ::Type{T}) end zeros(m::Integer, n::Integer) = zeros(m, n, Float64) -function ones{T<:VTypes}(m::Integer, n::Integer, ::Type{T}) +function ones(m::Integer, n::Integer, ::Type{T}) where T<:VTypes d = Dense(ccall((:cholmod_l_ones, :libcholmod), Ptr{C_Dense{T}}, (Csize_t, Csize_t, Cint, Ptr{UInt8}), m, n, xtyp(T), common())) @@ -857,7 +857,7 @@ end convert(::Type{Dense}, A::Sparse) = sparse_to_dense(A) # This constructior assumes zero based colptr and rowval -function (::Type{Sparse})(m::Integer, n::Integer, +function Sparse(m::Integer, n::Integer, colptr0::Vector{SuiteSparse_long}, rowval0::Vector{SuiteSparse_long}, nzval::Vector{Tv}, stype) where Tv<:VTypes # checks @@ -892,7 +892,7 @@ function (::Type{Sparse})(m::Integer, n::Integer, return o end -function (::Type{Sparse})(m::Integer, n::Integer, +function Sparse(m::Integer, n::Integer, colptr0::Vector{SuiteSparse_long}, rowval0::Vector{SuiteSparse_long}, nzval::Vector{<:VTypes}) @@ -908,7 +908,7 @@ function (::Type{Sparse})(m::Integer, n::Integer, o end -function (::Type{Sparse})(A::SparseMatrixCSC{Tv,SuiteSparse_long}, stype::Integer) where Tv<:VTypes +function Sparse(A::SparseMatrixCSC{Tv,SuiteSparse_long}, stype::Integer) where Tv<:VTypes ## Check length of input. This should never fail but see #20024 if length(A.colptr) <= A.n throw(ArgumentError("length of colptr must be at least size(A,2) + 1 = $(A.n + 1) but was $(length(A.colptr))")) diff --git a/base/tuple.jl b/base/tuple.jl index e0d9ffed7cf8c..7e243d0fa3728 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -104,7 +104,7 @@ julia> ntuple(i -> 2*i, 4) (2, 4, 6, 8) ``` """ -function ntuple{F}(f::F, n::Integer) +function ntuple(f::F, n::Integer) where F t = n <= 0 ? () : n == 1 ? (f(1),) : n == 2 ? (f(1), f(2)) : @@ -140,14 +140,14 @@ ntuple(f, ::Type{Val{13}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6) ntuple(f, ::Type{Val{14}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10), f(11), f(12), f(13), f(14))) ntuple(f, ::Type{Val{15}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10), f(11), f(12), f(13), f(14), f(15))) -function ntuple{F,N}(f::F, ::Type{Val{N}}) +function ntuple(f::F, ::Type{Val{N}}) where {F,N} Core.typeassert(N, Int) _ntuple((), f, Val{N}) end # Build up the output until it has length N -_ntuple{F,N}(out::NTuple{N,Any}, f::F, ::Type{Val{N}}) = out -function _ntuple{F,N,M}(out::NTuple{M,Any}, f::F, ::Type{Val{N}}) +_ntuple(out::NTuple{N,Any}, f::F, ::Type{Val{N}}) where {F,N} = out +function _ntuple(out::NTuple{M,Any}, f::F, ::Type{Val{N}}) where {F,N,M} @_inline_meta _ntuple((out..., f(M+1)), f, Val{N}) end @@ -159,10 +159,10 @@ map(f, t::Tuple{Any, Any}) = (f(t[1]), f(t[2])) map(f, t::Tuple{Any, Any, Any}) = (f(t[1]), f(t[2]), f(t[3])) map(f, t::Tuple) = (@_inline_meta; (f(t[1]), map(f,tail(t))...)) # stop inlining after some number of arguments to avoid code blowup -Any16{N} = Tuple{Any,Any,Any,Any,Any,Any,Any,Any, - Any,Any,Any,Any,Any,Any,Any,Any,Vararg{Any,N}} -All16{T,N} = Tuple{T,T,T,T,T,T,T,T, - T,T,T,T,T,T,T,T,Vararg{T,N}} +const Any16{N} = Tuple{Any,Any,Any,Any,Any,Any,Any,Any, + Any,Any,Any,Any,Any,Any,Any,Any,Vararg{Any,N}} +const All16{T,N} = Tuple{T,T,T,T,T,T,T,T, + T,T,T,T,T,T,T,T,Vararg{T,N}} function map(f, t::Any16) n = length(t) A = Array{Any,1}(n) @@ -207,16 +207,16 @@ end # type-stable padding fill_to_length{N}(t::Tuple, val, ::Type{Val{N}}) = _ftl((), val, Val{N}, t...) -_ftl{N}(out::NTuple{N,Any}, val, ::Type{Val{N}}) = out +_ftl(out::NTuple{N,Any}, val, ::Type{Val{N}}) where {N} = out function _ftl{N}(out::NTuple{N,Any}, val, ::Type{Val{N}}, t...) @_inline_meta throw(ArgumentError("input tuple of length $(N+length(t)), requested $N")) end -function _ftl{N}(out, val, ::Type{Val{N}}, t1, t...) +function _ftl(out, val, ::Type{Val{N}}, t1, t...) where N @_inline_meta _ftl((out..., t1), val, Val{N}, t...) end -function _ftl{N}(out, val, ::Type{Val{N}}) +function _ftl(out, val, ::Type{Val{N}}) where N @_inline_meta _ftl((out..., val), val, Val{N}) end @@ -229,9 +229,9 @@ if isdefined(Main, :Base) (::Type{T})(x::Tuple) where {T<:Tuple} = convert(T, x) # still use `convert` for tuples # resolve ambiguity between preceding and following methods -(::Type{All16{E,N}})(x::Tuple) where {E,N} = convert(All16{E,N}, x) +All16{E,N}(x::Tuple) where {E,N} = convert(All16{E,N}, x) -function (T::Type{All16{E,N}}){E,N}(itr) +function (T::All16{E,N})(itr) where {E,N} len = N+16 elts = collect(E, Iterators.take(itr,len)) if length(elts) != len From 8e501ee90a314e903c08687319acfe15aa35c69f Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Thu, 27 Apr 2017 09:03:16 -0700 Subject: [PATCH 0583/1534] Fix line numbers in doctests (#21569) * Fix line numbers in doctests and run contrib/add_license_to_files.jl keeping `make release-candidate` passing locally, so [ci skip] * Remove space after comma in 1-element tuples and a few similar occurrences of ', )' * remove another extraneous ', ' --- base/channels.jl | 4 ++-- base/distributed/managers.jl | 2 +- base/file.jl | 6 +++--- base/iterators.jl | 6 +++--- base/libc.jl | 2 +- base/libdl.jl | 2 +- base/libgit2/config.jl | 2 +- base/libgit2/remote.jl | 4 ++-- base/libgit2/status.jl | 2 +- base/libgit2/tag.jl | 6 +++--- base/linalg/eigen.jl | 4 ++-- base/show.jl | 8 ++++---- base/socket.jl | 2 +- base/sparse/cholmod_h.jl | 2 +- test/core.jl | 4 ++-- test/iterators.jl | 2 +- test/misc.jl | 2 +- test/resolvedata1.jl | 2 ++ test/sparse/sparsevector.jl | 2 +- 19 files changed, 33 insertions(+), 31 deletions(-) diff --git a/base/channels.jl b/base/channels.jl index 17eaf443fdc87..9291dd324622b 100644 --- a/base/channels.jl +++ b/base/channels.jl @@ -189,8 +189,8 @@ julia> take!(c) julia> put!(c,1); ERROR: foo Stacktrace: - [1] check_channel_state(::Channel{Any}) at ./channels.jl:127 - [2] put!(::Channel{Any}, ::Int64) at ./channels.jl:258 + [1] check_channel_state(::Channel{Any}) at ./channels.jl:126 + [2] put!(::Channel{Any}, ::Int64) at ./channels.jl:256 ``` """ function bind(c::Channel, task::Task) diff --git a/base/distributed/managers.jl b/base/distributed/managers.jl index aa0104f16218c..69672478c72dc 100644 --- a/base/distributed/managers.jl +++ b/base/distributed/managers.jl @@ -468,7 +468,7 @@ function socket_reuse_port() @static if is_linux() try - rc = ccall(:jl_tcp_reuseport, Int32, (Ptr{Void}, ), s.handle) + rc = ccall(:jl_tcp_reuseport, Int32, (Ptr{Void},), s.handle) if rc > 0 # SO_REUSEPORT is unsupported, just return the ephemerally bound socket return s elseif rc < 0 diff --git a/base/file.jl b/base/file.jl index 0180ff28de8f9..b344e264b79ec 100644 --- a/base/file.jl +++ b/base/file.jl @@ -581,12 +581,12 @@ function readlink(path::AbstractString) (Ptr{Void}, Ptr{Void}, Cstring, Ptr{Void}), eventloop(), req, path, C_NULL) if ret < 0 - ccall(:uv_fs_req_cleanup, Void, (Ptr{Void}, ), req) + ccall(:uv_fs_req_cleanup, Void, (Ptr{Void},), req) uv_error("readlink", ret) assert(false) end - tgt = unsafe_string(ccall(:jl_uv_fs_t_ptr, Ptr{Cchar}, (Ptr{Void}, ), req)) - ccall(:uv_fs_req_cleanup, Void, (Ptr{Void}, ), req) + tgt = unsafe_string(ccall(:jl_uv_fs_t_ptr, Ptr{Cchar}, (Ptr{Void},), req)) + ccall(:uv_fs_req_cleanup, Void, (Ptr{Void},), req) return tgt finally Libc.free(req) diff --git a/base/iterators.jl b/base/iterators.jl index e193a865c62ae..1c2ab13f8e113 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -540,7 +540,7 @@ ndims(p::AbstractProdIterator) = length(indices(p)) # generic methods to handle size of Prod* types _prod_size(a, ::HasShape) = size(a) -_prod_size(a, ::HasLength) = (length(a), ) +_prod_size(a, ::HasLength) = (length(a),) _prod_size(a, A) = throw(ArgumentError("Cannot compute size for object of type $(typeof(a))")) _prod_size(a, b, ::HasLength, ::HasLength) = (length(a), length(b)) @@ -551,7 +551,7 @@ _prod_size(a, b, A, B) = throw(ArgumentError("Cannot construct size for objects of types $(typeof(a)) and $(typeof(b))")) _prod_indices(a, ::HasShape) = indices(a) -_prod_indices(a, ::HasLength) = (OneTo(length(a)), ) +_prod_indices(a, ::HasLength) = (OneTo(length(a)),) _prod_indices(a, A) = throw(ArgumentError("Cannot compute indices for object of type $(typeof(a))")) _prod_indices(a, b, ::HasLength, ::HasLength) = (OneTo(length(a)), OneTo(length(b))) @@ -574,7 +574,7 @@ indices(p::Prod1) = _prod_indices(p.a, iteratorsize(p.a)) @inline start(p::Prod1) = start(p.a) @inline function next(p::Prod1, st) n, st = next(p.a, st) - (n, ), st + (n,), st end @inline done(p::Prod1, st) = done(p.a, st) diff --git a/base/libc.jl b/base/libc.jl index 50da588f3665f..bfce78f823896 100644 --- a/base/libc.jl +++ b/base/libc.jl @@ -34,7 +34,7 @@ if is_windows() handle::Ptr{Void} # On Windows file descriptors are HANDLE's and 64-bit on 64-bit Windows end Base.cconvert(::Type{Ptr{Void}}, fd::WindowsRawSocket) = fd.handle - _get_osfhandle(fd::RawFD) = WindowsRawSocket(ccall(:_get_osfhandle, Ptr{Void}, (Cint, ), fd.fd)) + _get_osfhandle(fd::RawFD) = WindowsRawSocket(ccall(:_get_osfhandle, Ptr{Void}, (Cint,), fd.fd)) _get_osfhandle(fd::WindowsRawSocket) = fd function dup(src::WindowsRawSocket) new_handle = Ref{Ptr{Void}}(-1) diff --git a/base/libdl.jl b/base/libdl.jl index 88846f0cd7f34..439b10bb40410 100644 --- a/base/libdl.jl +++ b/base/libdl.jl @@ -240,7 +240,7 @@ function dllist() end @static if is_apple() - numImages = ccall(:_dyld_image_count, Cint, (), ) + numImages = ccall(:_dyld_image_count, Cint, ()) # start at 1 instead of 0 to skip self for i in 1:numImages-1 diff --git a/base/libgit2/config.jl b/base/libgit2/config.jl index 6296648d26c04..0abfa28244d0b 100644 --- a/base/libgit2/config.jl +++ b/base/libgit2/config.jl @@ -26,7 +26,7 @@ end function GitConfig(level::Consts.GIT_CONFIG = Consts.CONFIG_LEVEL_DEFAULT) cfg_ptr_ptr = Ref{Ptr{Void}}(C_NULL) @check ccall((:git_config_open_default, :libgit2), Cint, - (Ptr{Ptr{Void}}, ), cfg_ptr_ptr) + (Ptr{Ptr{Void}},), cfg_ptr_ptr) cfg = GitConfig(cfg_ptr_ptr[]) if level != Consts.CONFIG_LEVEL_DEFAULT glb_cfg_ptr_ptr = Ref{Ptr{Void}}(C_NULL) diff --git a/base/libgit2/remote.jl b/base/libgit2/remote.jl index 85062caced0bd..508e8bf7b4775 100644 --- a/base/libgit2/remote.jl +++ b/base/libgit2/remote.jl @@ -55,7 +55,7 @@ end Get the URL of a remote git repository. """ function url(rmt::GitRemote) - url_ptr = ccall((:git_remote_url, :libgit2), Cstring, (Ptr{Void}, ), rmt.ptr) + url_ptr = ccall((:git_remote_url, :libgit2), Cstring, (Ptr{Void},), rmt.ptr) url_ptr == C_NULL && return "" return unsafe_string(url_ptr) end @@ -68,7 +68,7 @@ If the remote is anonymous (see [`GitRemoteAnon`](@ref)) the name will be an empty string `""`. """ function name(rmt::GitRemote) - name_ptr = ccall((:git_remote_name, :libgit2), Cstring, (Ptr{Void}, ), rmt.ptr) + name_ptr = ccall((:git_remote_name, :libgit2), Cstring, (Ptr{Void},), rmt.ptr) name_ptr == C_NULL && return "" return unsafe_string(name_ptr) end diff --git a/base/libgit2/status.jl b/base/libgit2/status.jl index a006770cd55fb..ccfb4c8e19985 100644 --- a/base/libgit2/status.jl +++ b/base/libgit2/status.jl @@ -19,7 +19,7 @@ end function Base.length(status::GitStatus) return Int(ccall((:git_status_list_entrycount, :libgit2), Csize_t, - (Ptr{Ptr{Void}}, ), status.ptr)) + (Ptr{Ptr{Void}},), status.ptr)) end function Base.getindex(status::GitStatus, i::Integer) diff --git a/base/libgit2/tag.jl b/base/libgit2/tag.jl index b76a5db932204..cde38e326f66f 100644 --- a/base/libgit2/tag.jl +++ b/base/libgit2/tag.jl @@ -21,7 +21,7 @@ Remove the git tag `tag` from the repository `repo`. """ function tag_delete(repo::GitRepo, tag::AbstractString) @check ccall((:git_tag_delete, :libgit2), Cint, - (Ptr{Void}, Cstring, ), repo.ptr, tag) + (Ptr{Void}, Cstring), repo.ptr, tag) end """ @@ -57,7 +57,7 @@ end The name of `tag` (e.g. `"v0.5"`). """ function name(tag::GitTag) - str_ptr = ccall((:git_tag_name, :libgit2), Cstring, (Ptr{Void}, ), tag.ptr) + str_ptr = ccall((:git_tag_name, :libgit2), Cstring, (Ptr{Void},), tag.ptr) str_ptr == C_NULL && throw(Error.GitError(Error.ERROR)) return unsafe_string(str_ptr) end @@ -69,7 +69,7 @@ end The `GitHash` of the target object of `tag`. """ function target(tag::GitTag) - oid_ptr = ccall((:git_tag_target_id, :libgit2), Ptr{GitHash}, (Ptr{Void}, ), tag.ptr) + oid_ptr = ccall((:git_tag_target_id, :libgit2), Ptr{GitHash}, (Ptr{Void},), tag.ptr) oid_ptr == C_NULL && throw(Error.GitError(Error.ERROR)) return unsafe_load(oid_ptr) end diff --git a/base/linalg/eigen.jl b/base/linalg/eigen.jl index e342101321066..f579f16f1690d 100644 --- a/base/linalg/eigen.jl +++ b/base/linalg/eigen.jl @@ -228,7 +228,7 @@ julia> A = [0 im; -1 0] julia> eigmax(A) ERROR: DomainError: Stacktrace: - [1] #eigmax#40(::Bool, ::Bool, ::Function, ::Array{Complex{Int64},2}) at ./linalg/eigen.jl:238 + [1] #eigmax#38(::Bool, ::Bool, ::Function, ::Array{Complex{Int64},2}) at ./linalg/eigen.jl:238 [2] eigmax(::Array{Complex{Int64},2}) at ./linalg/eigen.jl:236 ``` """ @@ -270,7 +270,7 @@ julia> A = [0 im; -1 0] julia> eigmin(A) ERROR: DomainError: Stacktrace: - [1] #eigmin#41(::Bool, ::Bool, ::Function, ::Array{Complex{Int64},2}) at ./linalg/eigen.jl:280 + [1] #eigmin#39(::Bool, ::Bool, ::Function, ::Array{Complex{Int64},2}) at ./linalg/eigen.jl:280 [2] eigmin(::Array{Complex{Int64},2}) at ./linalg/eigen.jl:278 ``` """ diff --git a/base/show.jl b/base/show.jl index fa9277feab17b..2ad3a079b3734 100644 --- a/base/show.jl +++ b/base/show.jl @@ -1492,7 +1492,7 @@ function print_matrix(io::IO, X::AbstractVecOrMat, print(io, i == first(rowsA) ? pre : presp) print_matrix_row(io, X,A,i,colsA,sep) print(io, i == last(rowsA) ? post : postsp) - if i != last(rowsA); println(io, ); end + if i != last(rowsA); println(io); end end else # rows fit down screen but cols don't, so need horizontal ellipsis c = div(screenwidth-length(hdots)+1,2)+1 # what goes to right of ellipsis @@ -1505,7 +1505,7 @@ function print_matrix(io::IO, X::AbstractVecOrMat, print(io, (i - first(rowsA)) % hmod == 0 ? hdots : repeat(" ", length(hdots))) print_matrix_row(io, X,Ralign,i,n-length(Ralign)+colsA,sep) print(io, i == last(rowsA) ? post : postsp) - if i != last(rowsA); println(io, ); end + if i != last(rowsA); println(io); end end end else # rows don't fit so will need vertical ellipsis @@ -1514,7 +1514,7 @@ function print_matrix(io::IO, X::AbstractVecOrMat, print(io, i == first(rowsA) ? pre : presp) print_matrix_row(io, X,A,i,colsA,sep) print(io, i == last(rowsA) ? post : postsp) - if i != rowsA[end]; println(io, ); end + if i != rowsA[end]; println(io); end if i == rowsA[halfheight] print(io, i == first(rowsA) ? pre : presp) print_matrix_vdots(io, vdots,A,sep,vmod,1) @@ -1533,7 +1533,7 @@ function print_matrix(io::IO, X::AbstractVecOrMat, print(io, (i - first(rowsA)) % hmod == 0 ? hdots : repeat(" ", length(hdots))) print_matrix_row(io, X,Ralign,i,n-length(Ralign)+colsA,sep) print(io, i == last(rowsA) ? post : postsp) - if i != rowsA[end]; println(io, ); end + if i != rowsA[end]; println(io); end if i == rowsA[halfheight] print(io, i == first(rowsA) ? pre : presp) print_matrix_vdots(io, vdots,Lalign,sep,vmod,1) diff --git a/base/socket.jl b/base/socket.jl index 14bb412a94406..5ad8207cdda8a 100644 --- a/base/socket.jl +++ b/base/socket.jl @@ -325,7 +325,7 @@ iswritable(io::TCPSocket) = isopen(io) && io.status != StatusClosing _jl_connect_raw(sock::TCPSocket, sockaddr::Ptr{Void}) = ccall(:jl_connect_raw, Int32, (Ptr{Void}, Ptr{Void}, Ptr{Void}), sock.handle, sockaddr, uv_jl_connectcb::Ptr{Void}) _jl_sockaddr_from_addrinfo(addrinfo::Ptr{Void}) = - ccall(:jl_sockaddr_from_addrinfo, Ptr{Void}, (Ptr{Void}, ), addrinfo) + ccall(:jl_sockaddr_from_addrinfo, Ptr{Void}, (Ptr{Void},), addrinfo) _jl_sockaddr_set_port(ptr::Ptr{Void}, port::UInt16) = ccall(:jl_sockaddr_set_port, Void, (Ptr{Void}, UInt16), ptr, port) diff --git a/base/sparse/cholmod_h.jl b/base/sparse/cholmod_h.jl index 477ab4d07e3f3..7b7b11035c6e5 100644 --- a/base/sparse/cholmod_h.jl +++ b/base/sparse/cholmod_h.jl @@ -59,7 +59,7 @@ const MM_HERMITIAN_POSDIAG = 7 # check the size of SuiteSparse_long if Int(ccall((:jl_cholmod_sizeof_long, :libsuitesparse_wrapper),Csize_t,())) == 4 const SuiteSparse_long = Int32 - const IndexTypes = (:Int32, ) + const IndexTypes = (:Int32,) const ITypes = Union{Int32} else const SuiteSparse_long = Int64 diff --git a/test/core.jl b/test/core.jl index f1b4867abb50d..7474c947e380e 100644 --- a/test/core.jl +++ b/test/core.jl @@ -4689,11 +4689,11 @@ end # module SOE @test_nowarn begin local p15240 p15240 = ccall(:jl_realloc, Ptr{Void}, (Ptr{Void}, Csize_t), C_NULL, 10) - ccall(:jl_free, Void, (Ptr{Void}, ), p15240) + ccall(:jl_free, Void, (Ptr{Void},), p15240) end # issue #19963 -@test_nowarn ccall(:jl_free, Void, (Ptr{Void}, ), C_NULL) +@test_nowarn ccall(:jl_free, Void, (Ptr{Void},), C_NULL) # Wrong string size on 64bits for large string. if Sys.WORD_SIZE == 64 diff --git a/test/iterators.jl b/test/iterators.jl index fd0ec31499827..5e8e368c33269 100644 --- a/test/iterators.jl +++ b/test/iterators.jl @@ -217,7 +217,7 @@ let (a, b, c) = (1:2, 1.0:10.0, Int32(1):Int32(0)) @test length(product(a, b, c)) == 0 # size - @test size(product(a)) == (2, ) + @test size(product(a)) == (2,) @test size(product(a, b)) == (2, 10) @test size(product(a, b, c)) == (2, 10, 0) diff --git a/test/misc.jl b/test/misc.jl index 197cd00f0fa86..ab1166df3be10 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -638,7 +638,7 @@ end @testset "test this does not segfault #19281" begin @test Foo_19281().f[1] == () - @test Foo_19281().f[2] == (1, ) + @test Foo_19281().f[2] == (1,) end let diff --git a/test/resolvedata1.jl b/test/resolvedata1.jl index 19346bc08200a..26d6c649f29e8 100644 --- a/test/resolvedata1.jl +++ b/test/resolvedata1.jl @@ -1,3 +1,5 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + deps_data = Any[ ["ASTInterpreter", v"0.0.1", "AbstractTrees", v"0.0.1", v"0.1.0"], ["ASTInterpreter", v"0.0.1", "JuliaParser", v"0.7.1"], diff --git a/test/sparse/sparsevector.jl b/test/sparse/sparsevector.jl index ca2f1217ceb29..6b8f20eaf0afa 100644 --- a/test/sparse/sparsevector.jl +++ b/test/sparse/sparsevector.jl @@ -162,7 +162,7 @@ end let r1 = MersenneTwister(0), r2 = MersenneTwister(0) @test sprand(r1, 100, .9) == sprand(r2, 100, .9) @test sprandn(r1, 100, .9) == sprandn(r2, 100, .9) - @test sprand(r1, Bool, 100, .9, ) == sprand(r2, Bool, 100, .9) + @test sprand(r1, Bool, 100, .9) == sprand(r2, Bool, 100, .9) end ### Element access From 29806d59662bf9e653ec3d3ebb32b16362264d93 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Thu, 27 Apr 2017 12:25:25 -0400 Subject: [PATCH 0584/1534] allow mkl_rt name in fftw_vendor on non windows --- base/util.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/util.jl b/base/util.jl index 51615f1f343ba..b2167ca36b168 100644 --- a/base/util.jl +++ b/base/util.jl @@ -383,7 +383,7 @@ macro timed(ex) end function fftw_vendor() - if Base.libfftw_name == "libmkl_rt" || (is_windows() && Base.libfftw_name == "mkl_rt") + if Base.libfftw_name in ("libmkl_rt", "mkl_rt") return :mkl else return :fftw From 275efe4b420adbd5ee68565fa1bfd55d3ed84cd7 Mon Sep 17 00:00:00 2001 From: Mus M Date: Thu, 27 Apr 2017 12:27:12 -0400 Subject: [PATCH 0585/1534] Conversion to new syntax in refpointer.jl (#21584) --- base/refpointer.jl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/base/refpointer.jl b/base/refpointer.jl index 03dff1180270f..087a6e0786490 100644 --- a/base/refpointer.jl +++ b/base/refpointer.jl @@ -41,15 +41,15 @@ mutable struct RefValue{T} <: Ref{T} RefValue{T}() where {T} = new() RefValue{T}(x) where {T} = new(x) end -RefValue{T}(x::T) = RefValue{T}(x) +RefValue(x::T) where {T} = RefValue{T}(x) isassigned(x::RefValue) = isdefined(x, :x) Ref(x::Ref) = x Ref(x::Any) = RefValue(x) -Ref{T}(x::Ptr{T}, i::Integer=1) = x + (i-1)*Core.sizeof(T) +Ref(x::Ptr{T}, i::Integer=1) where {T} = x + (i-1)*Core.sizeof(T) Ref(x, i::Integer) = (i != 1 && error("Object only has one element"); Ref(x)) -(::Type{Ref{T}})() where {T} = RefValue{T}() # Ref{T}() -(::Type{Ref{T}})(x) where {T} = RefValue{T}(x) # Ref{T}(x) +Ref{T}() where {T} = RefValue{T}() # Ref{T}() +Ref{T}(x) where {T} = RefValue{T}(x) # Ref{T}(x) convert(::Type{Ref{T}}, x) where {T} = RefValue{T}(x) function unsafe_convert(P::Type{Ptr{T}}, b::RefValue{T}) where T @@ -65,14 +65,14 @@ end unsafe_convert(::Type{Ptr{Void}}, b::RefValue{T}) where {T} = convert(Ptr{Void}, unsafe_convert(Ptr{T}, b)) ### Methods for a Ref object that is backed by an array at index i -struct RefArray{T, A<:AbstractArray{T}, R} <: Ref{T} +struct RefArray{T,A<:AbstractArray{T},R} <: Ref{T} x::A i::Int roots::R # should be either ::Void or ::Any RefArray{T,A,R}(x,i,roots=nothing) where {T,A<:AbstractArray{T},R} = new(x,i,roots) end -RefArray{T}(x::AbstractArray{T},i::Int,roots::Any) = RefArray{T,typeof(x),Any}(x, i, roots) -RefArray{T}(x::AbstractArray{T},i::Int=1,roots::Void=nothing) = RefArray{T,typeof(x),Void}(x, i, nothing) +RefArray(x::AbstractArray{T}, i::Int, roots::Any) where {T} = RefArray{T,typeof(x),Any}(x, i, roots) +RefArray(x::AbstractArray{T}, i::Int=1, roots::Void=nothing) where {T} = RefArray{T,typeof(x),Void}(x, i, nothing) convert(::Type{Ref{T}}, x::AbstractArray{T}) where {T} = RefArray(x, 1) Ref(x::AbstractArray, i::Integer=1) = RefArray(x, i) @@ -89,10 +89,10 @@ end unsafe_convert(::Type{Ptr{Void}}, b::RefArray{T}) where {T} = convert(Ptr{Void}, unsafe_convert(Ptr{T}, b)) # convert Arrays to pointer arrays for ccall -function (::Type{Ref{<:Union{Ptr,Cwstring,Cstring}}})(a::Array{<:Union{Ptr,Cwstring,Cstring}}) # Ref{P<:Ptr}(a::Array{T<:Ptr}) +function Ref{P}(a::Array{<:Union{Ptr,Cwstring,Cstring}}) where P<:Union{Ptr,Cwstring,Cstring} return RefArray(a) # effectively a no-op end -function (::Type{Ref{P}}){P<:Union{Ptr,Cwstring,Cstring},T}(a::Array{T}) # Ref{P<:Ptr}(a::Array) +function Ref{P}(a::Array{T}) where P<:Union{Ptr,Cwstring,Cstring} where T if (!isbits(T) && T <: eltype(P)) # this Array already has the right memory layout for the requested Ref return RefArray(a,1,false) # root something, so that this function is type-stable From 45373a5f791e9307ad1b2ffc8bfeac1ce015a903 Mon Sep 17 00:00:00 2001 From: Mus M Date: Thu, 27 Apr 2017 13:36:26 -0400 Subject: [PATCH 0586/1534] Syntax to using where --- base/array.jl | 2 +- base/c.jl | 6 +++--- base/complex.jl | 8 ++++---- base/dates/ranges.jl | 4 ++-- base/dates/types.jl | 4 ++-- base/generator.jl | 2 +- base/libgit2/repository.jl | 2 +- base/mpfr.jl | 34 +++++++++++++++++----------------- base/multidimensional.jl | 4 ++-- base/strings/types.jl | 2 +- base/strings/util.jl | 8 ++++---- base/traits.jl | 14 +++++++------- 12 files changed, 45 insertions(+), 45 deletions(-) diff --git a/base/array.jl b/base/array.jl index ec727a6998238..c384ee3db721a 100644 --- a/base/array.jl +++ b/base/array.jl @@ -61,7 +61,7 @@ match the length or number of `dims`. Array vect() = Array{Any,1}(0) -vect{T}(X::T...) = T[ X[i] for i=1:length(X) ] +vect(X::T...) where {T} = T[ X[i] for i = 1:length(X) ] function vect(X...) T = promote_typeof(X...) diff --git a/base/c.jl b/base/c.jl index 46ea2fa3af2ef..410bb1e2f153e 100644 --- a/base/c.jl +++ b/base/c.jl @@ -158,9 +158,9 @@ Only conversion to/from UTF-8 is currently supported. """ function transcode end -transcode{T<:Union{UInt8,UInt16,UInt32,Int32}}(::Type{T}, src::Vector{T}) = src -transcode{T<:Union{Int32,UInt32}}(::Type{T}, src::String) = T[T(c) for c in src] -transcode{T<:Union{Int32,UInt32}}(::Type{T}, src::Vector{UInt8}) = transcode(T, String(src)) +transcode(::Type{T}, src::Vector{T}) where {T<:Union{UInt8,UInt16,UInt32,Int32}} = src +transcode(::Type{T}, src::String) where {T<:Union{Int32,UInt32}} = T[T(c) for c in src] +transcode(::Type{T}, src::Vector{UInt8}) where {T<:Union{Int32,UInt32}} = transcode(T, String(src)) function transcode(::Type{UInt8}, src::Vector{<:Union{Int32,UInt32}}) buf = IOBuffer() for c in src; print(buf, Char(c)); end diff --git a/base/complex.jl b/base/complex.jl index 71b8e8c001d1b..617b20d20c487 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -87,8 +87,8 @@ Float64 ``` """ real(T::Type) = typeof(real(zero(T))) -real{T<:Real}(::Type{T}) = T -real{T<:Real}(::Type{Complex{T}}) = T +real(::Type{T}) where {T<:Real} = T +real(::Type{Complex{T}}) where {T<:Real} = T """ isreal(x) -> Bool @@ -366,7 +366,7 @@ function inv(w::Complex128) return Complex128(p*s,q*s) # undo scaling end -function ssqs{T<:AbstractFloat}(x::T, y::T) +function ssqs(x::T, y::T) where T<:AbstractFloat k::Int = 0 ρ = x*x + y*y if !isfinite(ρ) && (isinf(x) || isinf(y)) @@ -536,7 +536,7 @@ function expm1(z::Complex) end end -function log1p{T}(z::Complex{T}) +function log1p(z::Complex{T}) where T zr,zi = reim(z) if isfinite(zr) isinf(zi) && return log(z) diff --git a/base/dates/ranges.jl b/base/dates/ranges.jl index 0004d84d85bec..21b646bd062fe 100644 --- a/base/dates/ranges.jl +++ b/base/dates/ranges.jl @@ -31,10 +31,10 @@ Base.length(r::StepRange{<:Period}) = length(StepRange(value(r.start), value(r.s # Used to calculate the last valid date in the range given the start, stop, and step # last = stop - steprem(start, stop, step) -Base.steprem{T<:TimeType}(a::T, b::T, c) = b - (a + c * len(a, b, c)) +Base.steprem(a::T, b::T, c) where {T<:TimeType} = b - (a + c * len(a, b, c)) import Base.in -function in{T<:TimeType}(x::T, r::StepRange{T}) +function in(x::T, r::StepRange{T}) where T<:TimeType n = len(first(r), x, step(r)) + 1 n >= 1 && n <= length(r) && r[n] == x end diff --git a/base/dates/types.jl b/base/dates/types.jl index 587e7b1be6042..7f2f93d9273f7 100644 --- a/base/dates/types.jl +++ b/base/dates/types.jl @@ -311,5 +311,5 @@ sleep(time::Period) = sleep(toms(time) / 1000) Timer(time::Period, repeat::Period=Second(0)) = Timer(toms(time) / 1000, toms(repeat) / 1000) timedwait(testcb::Function, time::Period) = timedwait(testcb, toms(time) / 1000) -(::Type{Base.TypeOrder})(::Type{<:AbstractTime}) = Base.HasOrder() -(::Type{Base.TypeArithmetic})(::Type{<:AbstractTime}) = Base.ArithmeticOverflows() +Base.TypeOrder(::Type{<:AbstractTime}) = Base.HasOrder() +Base.TypeArithmetic(::Type{<:AbstractTime}) = Base.ArithmeticOverflows() diff --git a/base/generator.jl b/base/generator.jl index 87f3d02fc18b4..d49ed635ff3f1 100644 --- a/base/generator.jl +++ b/base/generator.jl @@ -35,7 +35,7 @@ end Generator(f, I1, I2, Is...) = Generator(a->f(a...), zip(I1, I2, Is...)) -Generator{T,I}(::Type{T}, iter::I) = Generator{I,Type{T}}(T, iter) +Generator(::Type{T}, iter::I) where {T,I} = Generator{I,Type{T}}(T, iter) start(g::Generator) = (@_inline_meta; start(g.iter)) done(g::Generator, s) = (@_inline_meta; done(g.iter, s)) diff --git a/base/libgit2/repository.jl b/base/libgit2/repository.jl index 5f1f938c475b3..9ea6e2a8be3bb 100644 --- a/base/libgit2/repository.jl +++ b/base/libgit2/repository.jl @@ -217,7 +217,7 @@ then `obj` will be peeled until the type changes. - A `GitTag` will be peeled to the object it references. - A `GitCommit` will be peeled to a `GitTree`. """ -function peel{T<:GitObject}(::Type{T}, obj::GitObject) +function peel(::Type{T}, obj::GitObject) where T<:GitObject new_ptr_ptr = Ref{Ptr{Void}}(C_NULL) @check ccall((:git_object_peel, :libgit2), Cint, diff --git a/base/mpfr.jl b/base/mpfr.jl index 4dd53e1d6af96..ff459cf0738f4 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -168,10 +168,10 @@ function unsafe_cast(::Type{UInt64}, x::BigFloat, ri::Cint) (Ptr{BigFloat}, Cint), &x, ri) end -function unsafe_cast{T<:Signed}(::Type{T}, x::BigFloat, ri::Cint) +function unsafe_cast(::Type{T}, x::BigFloat, ri::Cint) where T<:Signed unsafe_cast(Int64, x, ri) % T end -function unsafe_cast{T<:Unsigned}(::Type{T}, x::BigFloat, ri::Cint) +function unsafe_cast(::Type{T}, x::BigFloat, ri::Cint) where T<:Unsigned unsafe_cast(UInt64, x, ri) % T end @@ -184,19 +184,19 @@ function unsafe_cast(::Type{BigInt}, x::BigFloat, ri::Cint) end unsafe_cast(::Type{Int128}, x::BigFloat, ri::Cint) = Int128(unsafe_cast(BigInt,x,ri)) unsafe_cast(::Type{UInt128}, x::BigFloat, ri::Cint) = UInt128(unsafe_cast(BigInt,x,ri)) -unsafe_cast{T<:Integer}(::Type{T}, x::BigFloat, r::RoundingMode) = unsafe_cast(T,x,to_mpfr(r)) +unsafe_cast(::Type{T}, x::BigFloat, r::RoundingMode) where {T<:Integer} = unsafe_cast(T,x,to_mpfr(r)) -unsafe_trunc{T<:Integer}(::Type{T}, x::BigFloat) = unsafe_cast(T,x,RoundToZero) +unsafe_trunc(::Type{T}, x::BigFloat) where {T<:Integer} = unsafe_cast(T,x,RoundToZero) function trunc{T<:Union{Signed,Unsigned}}(::Type{T}, x::BigFloat) (typemin(T) <= x <= typemax(T)) || throw(InexactError()) unsafe_cast(T,x,RoundToZero) end -function floor{T<:Union{Signed,Unsigned}}(::Type{T}, x::BigFloat) +function floor(::Type{T}, x::BigFloat) where T<:Union{Signed,Unsigned} (typemin(T) <= x <= typemax(T)) || throw(InexactError()) unsafe_cast(T,x,RoundDown) end -function ceil{T<:Union{Signed,Unsigned}}(::Type{T}, x::BigFloat) +function ceil(::Type{T}, x::BigFloat) where T<:Union{Signed,Unsigned} (typemin(T) <= x <= typemax(T)) || throw(InexactError()) unsafe_cast(T,x,RoundUp) end @@ -223,7 +223,7 @@ function convert(::Type{BigInt},x::BigFloat) trunc(BigInt,x) end -function convert(::Type{Integer},x::BigFloat) +function convert(::Type{Integer}, x::BigFloat) isinteger(x) || throw(InexactError()) trunc(Integer,x) end @@ -234,23 +234,23 @@ end ## BigFloat -> AbstractFloat convert(::Type{Float64}, x::BigFloat) = - ccall((:mpfr_get_d,:libmpfr), Float64, (Ptr{BigFloat},Int32), &x, ROUNDING_MODE[]) + ccall((:mpfr_get_d,:libmpfr), Float64, (Ptr{BigFloat}, Int32), &x, ROUNDING_MODE[]) convert(::Type{Float32}, x::BigFloat) = - ccall((:mpfr_get_flt,:libmpfr), Float32, (Ptr{BigFloat},Int32), &x, ROUNDING_MODE[]) + ccall((:mpfr_get_flt,:libmpfr), Float32, (Ptr{BigFloat}, Int32), &x, ROUNDING_MODE[]) # TODO: avoid double rounding convert(::Type{Float16}, x::BigFloat) = convert(Float16, convert(Float32, x)) -(::Type{Float64})(x::BigFloat, r::RoundingMode) = - ccall((:mpfr_get_d,:libmpfr), Float64, (Ptr{BigFloat},Int32), &x, to_mpfr(r)) -(::Type{Float32})(x::BigFloat, r::RoundingMode) = - ccall((:mpfr_get_flt,:libmpfr), Float32, (Ptr{BigFloat},Int32), &x, to_mpfr(r)) +Float64(x::BigFloat, r::RoundingMode) = + ccall((:mpfr_get_d,:libmpfr), Float64, (Ptr{BigFloat}, Int32), &x, to_mpfr(r)) +Float32(x::BigFloat, r::RoundingMode) = + ccall((:mpfr_get_flt,:libmpfr), Float32, (Ptr{BigFloat}, Int32), &x, to_mpfr(r)) # TODO: avoid double rounding -(::Type{Float16})(x::BigFloat, r::RoundingMode) = +Float16(x::BigFloat, r::RoundingMode) = convert(Float16, Float32(x, r)) promote_rule(::Type{BigFloat}, ::Type{<:Real}) = BigFloat -promote_rule(::Type{BigInt},::Type{<:AbstractFloat}) = BigFloat -promote_rule(::Type{BigFloat},::Type{<:AbstractFloat}) = BigFloat +promote_rule(::Type{BigInt}, ::Type{<:AbstractFloat}) = BigFloat +promote_rule(::Type{BigFloat}, ::Type{<:AbstractFloat}) = BigFloat function convert(::Type{Rational{BigInt}}, x::AbstractFloat) if isnan(x); return zero(BigInt)//zero(BigInt); end @@ -860,7 +860,7 @@ It is logically equivalent to: Often used as `setprecision(T, precision) do ... end` """ -function setprecision{T}(f::Function, ::Type{T}, prec::Integer) +function setprecision(f::Function, ::Type{T}, prec::Integer) where T old_prec = precision(T) setprecision(T, prec) try diff --git a/base/multidimensional.jl b/base/multidimensional.jl index f29b49fe31efd..9fbb1b294ec0a 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -446,8 +446,8 @@ end _maybe_reshape(::IndexLinear, A::AbstractArray, I...) = A _maybe_reshape(::IndexCartesian, A::AbstractVector, I...) = A @inline _maybe_reshape(::IndexCartesian, A::AbstractArray, I...) = __maybe_reshape(A, index_ndims(I...)) -@inline __maybe_reshape{T,N}(A::AbstractArray{T,N}, ::NTuple{N,Any}) = A -@inline __maybe_reshape{N}(A::AbstractArray, ::NTuple{N,Any}) = reshape(A, Val{N}) +@inline __maybe_reshape(A::AbstractArray{T,N}, ::NTuple{N,Any}) where {T,N} = A +@inline __maybe_reshape(A::AbstractArray, ::NTuple{N,Any}) where {N} = reshape(A, Val{N}) @generated function _unsafe_getindex(::IndexStyle, A::AbstractArray, I::Union{Real, AbstractArray}...) N = length(I) diff --git a/base/strings/types.jl b/base/strings/types.jl index a49d40d9d17f4..587af56c4015d 100644 --- a/base/strings/types.jl +++ b/base/strings/types.jl @@ -26,7 +26,7 @@ struct SubString{T<:AbstractString} <: AbstractString end end end -SubString(s::T, i::Int, j::Int) where T<:AbstractString = SubString{T}(s, i, j) +SubString(s::T, i::Int, j::Int) where {T<:AbstractString} = SubString{T}(s, i, j) SubString(s::SubString, i::Int, j::Int) = SubString(s.string, s.offset+i, s.offset+j) SubString(s::AbstractString, i::Integer, j::Integer) = SubString(s, Int(i), Int(j)) SubString(s::AbstractString, i::Integer) = SubString(s, i, endof(s)) diff --git a/base/strings/util.jl b/base/strings/util.jl index 9d24e0da0667e..82b9b340ca55d 100644 --- a/base/strings/util.jl +++ b/base/strings/util.jl @@ -250,7 +250,7 @@ cpad(s, n::Integer, p=" ") = rpad(lpad(s,div(n+strwidth(s),2),p),n,p) # splitter can be a Char, Vector{Char}, AbstractString, Regex, ... # any splitter that provides search(s::AbstractString, splitter) -split{T<:SubString}(str::T, splitter; limit::Integer=0, keep::Bool=true) = _split(str, splitter, limit, keep, T[]) +split(str::T, splitter; limit::Integer=0, keep::Bool=true) where {T<:SubString} = _split(str, splitter, limit, keep, T[]) """ split(s::AbstractString, [chars]; limit::Integer=0, keep::Bool=true) @@ -273,7 +273,7 @@ julia> split(a,".") "rch" ``` """ -split{T<:AbstractString}(str::T, splitter; limit::Integer=0, keep::Bool=true) = _split(str, splitter, limit, keep, SubString{T}[]) +split(str::T, splitter; limit::Integer=0, keep::Bool=true) where {T<:AbstractString} = _split(str, splitter, limit, keep, SubString{T}[]) function _split(str::AbstractString, splitter, limit::Integer, keep_empty::Bool, strs::Array) i = start(str) n = endof(str) @@ -299,7 +299,7 @@ end # a bit oddball, but standard behavior in Perl, Ruby & Python: split(str::AbstractString) = split(str, _default_delims; limit=0, keep=false) -rsplit{T<:SubString}(str::T, splitter; limit::Integer=0, keep::Bool=true) = _rsplit(str, splitter, limit, keep, T[]) +rsplit(str::T, splitter; limit::Integer=0, keep::Bool=true) where {T<:SubString} = _rsplit(str, splitter, limit, keep, T[]) """ rsplit(s::AbstractString, [chars]; limit::Integer=0, keep::Bool=true) @@ -328,7 +328,7 @@ julia> rsplit(a,".";limit=2) "h" ``` """ -rsplit{T<:AbstractString}(str::T, splitter ; limit::Integer=0, keep::Bool=true) = _rsplit(str, splitter, limit, keep, SubString{T}[]) +rsplit(str::T, splitter ; limit::Integer=0, keep::Bool=true) where {T<:AbstractString} = _rsplit(str, splitter, limit, keep, SubString{T}[]) function _rsplit(str::AbstractString, splitter, limit::Integer, keep_empty::Bool, strs::Array) i = start(str) n = endof(str) diff --git a/base/traits.jl b/base/traits.jl index b9643f7ba6742..3efad150e1ff8 100644 --- a/base/traits.jl +++ b/base/traits.jl @@ -6,9 +6,9 @@ abstract type TypeOrder end struct HasOrder <: TypeOrder end struct Unordered <: TypeOrder end -(::Type{TypeOrder})(instance) = TypeOrder(typeof(instance)) -(::Type{TypeOrder})(::Type{<:Real}) = HasOrder() -(::Type{TypeOrder})(::Type{<:Any}) = Unordered() +TypeOrder(instance) = TypeOrder(typeof(instance)) +TypeOrder(::Type{<:Real}) = HasOrder() +TypeOrder(::Type{<:Any}) = Unordered() # trait for objects that support arithmetic abstract type TypeArithmetic end @@ -16,7 +16,7 @@ struct ArithmeticRounds <: TypeArithmetic end # least significant bits can b struct ArithmeticOverflows <: TypeArithmetic end # most significant bits can be lost struct ArithmeticUnknown <: TypeArithmetic end -(::Type{TypeArithmetic})(instance) = TypeArithmetic(typeof(instance)) -(::Type{TypeArithmetic})(::Type{<:AbstractFloat}) = ArithmeticRounds() -(::Type{TypeArithmetic})(::Type{<:Integer}) = ArithmeticOverflows() -(::Type{TypeArithmetic})(::Type{<:Any}) = ArithmeticUnknown() +TypeArithmetic(instance) = TypeArithmetic(typeof(instance)) +TypeArithmetic(::Type{<:AbstractFloat}) = ArithmeticRounds() +TypeArithmetic(::Type{<:Integer}) = ArithmeticOverflows() +TypeArithmetic(::Type{<:Any}) = ArithmeticUnknown() From 4ddd9fa1eb850d53d47f977a4e07ed0fc48329d7 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Thu, 27 Apr 2017 14:25:17 -0700 Subject: [PATCH 0587/1534] Add a test for profile deserialization (#21575) xref #21025 which is fixed on master, and a one-character fix on release-0.5, but should be tested on both branches --- base/stacktraces.jl | 2 +- test/profile.jl | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/base/stacktraces.jl b/base/stacktraces.jl index 6189c127f2742..7ed559e6034d9 100644 --- a/base/stacktraces.jl +++ b/base/stacktraces.jl @@ -37,7 +37,7 @@ Stack information representing execution context, with the following fields: True if the code is from an inlined frame. -- `pointer::Int64` +- `pointer::UInt64` Representation of the pointer to the execution context as returned by `backtrace`. diff --git a/test/profile.jl b/test/profile.jl index b4d53a6cbd8cd..92e3076fc9481 100644 --- a/test/profile.jl +++ b/test/profile.jl @@ -11,6 +11,17 @@ end Profile.clear() @profile busywait(1, 20) + +let r = Profile.retrieve() + mktemp() do path, io + serialize(io, r) + close(io) + open(path) do io + @test isa(deserialize(io), Tuple{Vector{UInt},Dict{UInt64,Vector{StackFrame}}}) + end + end +end + let iobuf = IOBuffer() Profile.print(iobuf, format=:tree, C=true) str = String(take!(iobuf)) From 9f5b4ada09df7e83b59f15ef8e00915f2c8d462a Mon Sep 17 00:00:00 2001 From: kshyatt Date: Thu, 27 Apr 2017 17:52:58 -0700 Subject: [PATCH 0588/1534] Add test for creating GitAnnotated from FetchHead --- test/libgit2.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/libgit2.jl b/test/libgit2.jl index c3e416d84f3ea..be0973852ff5d 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -806,6 +806,10 @@ mktempdir() do dir @test isfile(joinpath(test_repo, test_file)) @test new_head == head_oid + # GitAnnotated for a fetchhead + fh_ann = LibGit2.GitAnnotated(repo, LibGit2.Consts.FETCH_HEAD) + @test LibGit2.GitHash(fh_ann) == head_oid + # Detach HEAD - no merge LibGit2.checkout!(repo, string(commit_oid3)) @test_throws LibGit2.Error.GitError LibGit2.merge!(repo, fastforward=true) From 8df8c307e213699025359def07439b855138df2a Mon Sep 17 00:00:00 2001 From: Mus M Date: Thu, 27 Apr 2017 17:56:38 -0400 Subject: [PATCH 0589/1534] M --- base/broadcast.jl | 2 +- base/deprecated.jl | 6 ++--- base/linalg/diagonal.jl | 6 ++--- base/markdown/parse/parse.jl | 2 +- base/markdown/render/plain.jl | 2 +- base/multidimensional.jl | 2 +- base/ordering.jl | 2 +- base/range.jl | 49 +++++++++++++++++++++-------------- base/reducedim.jl | 18 ++++++------- base/sparse/sparsematrix.jl | 8 +++--- 10 files changed, 54 insertions(+), 43 deletions(-) diff --git a/base/broadcast.jl b/base/broadcast.jl index 84df411f7c32e..2d98b4031b0d9 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -40,7 +40,7 @@ promote_containertype(::Type{Tuple}, ::ScalarType) = Tuple promote_containertype(::ScalarType, ::Type{Tuple}) = Tuple promote_containertype(::Type{Any}, ::Type{Nullable}) = Nullable promote_containertype(::Type{Nullable}, ::Type{Any}) = Nullable -promote_containertype{T}(::Type{T}, ::Type{T}) = T +promote_containertype(::Type{T}, ::Type{T}) where {T} = T ## Calculate the broadcast indices of the arguments, or error if incompatible # array inputs diff --git a/base/deprecated.jl b/base/deprecated.jl index d9f3282e4f317..442a01cac7bd9 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -633,11 +633,11 @@ _broadcast_zpreserving!(args...) = broadcast!(args...) # note: promote_eltype_op also deprecated, defined later in this file _broadcast_zpreserving(f, As...) = broadcast!(f, similar(Array{_promote_eltype_op(f, As...)}, Base.Broadcast.broadcast_indices(As...)), As...) -_broadcast_zpreserving{Tv1,Ti1,Tv2,Ti2}(f::Function, A_1::SparseMatrixCSC{Tv1,Ti1}, A_2::SparseMatrixCSC{Tv2,Ti2}) = +_broadcast_zpreserving(f::Function, A_1::SparseMatrixCSC{Tv1,Ti1}, A_2::SparseMatrixCSC{Tv2,Ti2}) where {Tv1,Ti1,Tv2,Ti2} = _broadcast_zpreserving!(f, spzeros(promote_type(Tv1, Tv2), promote_type(Ti1, Ti2), Base.to_shape(Base.Broadcast.broadcast_indices(A_1, A_2))), A_1, A_2) -_broadcast_zpreserving{Ti}(f::Function, A_1::SparseMatrixCSC{<:Any,Ti}, A_2::Union{Array,BitArray,Number}) = +_broadcast_zpreserving(f::Function, A_1::SparseMatrixCSC{<:Any,Ti}, A_2::Union{Array,BitArray,Number}) where {Ti} = _broadcast_zpreserving!(f, spzeros(promote_eltype(A_1, A_2), Ti, Base.to_shape(Base.Broadcast.broadcast_indices(A_1, A_2))), A_1, A_2) -_broadcast_zpreserving{Ti}(f::Function, A_1::Union{Array,BitArray,Number}, A_2::SparseMatrixCSC{<:Any,Ti}) = +_broadcast_zpreserving(f::Function, A_1::Union{Array,BitArray,Number}, A_2::SparseMatrixCSC{<:Any,Ti}) where {Ti} = _broadcast_zpreserving!(f, spzeros(promote_eltype(A_1, A_2), Ti, Base.to_shape(Base.Broadcast.broadcast_indices(A_1, A_2))), A_1, A_2) function _depstring_bczpres() diff --git a/base/linalg/diagonal.jl b/base/linalg/diagonal.jl index a5308cd8dcdf2..a94414d2c3ddb 100644 --- a/base/linalg/diagonal.jl +++ b/base/linalg/diagonal.jl @@ -318,7 +318,7 @@ end (\)(D::Diagonal, b::AbstractVector) = D.diag .\ b (\)(Da::Diagonal, Db::Diagonal) = Diagonal(Da.diag .\ Db.diag) -function inv{T}(D::Diagonal{T}) +function inv(D::Diagonal{T}) where T Di = similar(D.diag, typeof(inv(zero(T)))) for i = 1:length(D.diag) if D.diag[i] == zero(T) @@ -329,14 +329,14 @@ function inv{T}(D::Diagonal{T}) Diagonal(Di) end -function pinv{T}(D::Diagonal{T}) +function pinv(D::Diagonal{T}) where T Di = similar(D.diag, typeof(inv(zero(T)))) for i = 1:length(D.diag) isfinite(inv(D.diag[i])) ? Di[i]=inv(D.diag[i]) : Di[i]=zero(T) end Diagonal(Di) end -function pinv{T}(D::Diagonal{T}, tol::Real) +function pinv(D::Diagonal{T}, tol::Real) where T Di = similar(D.diag, typeof(inv(zero(T)))) if( !isempty(D.diag) ) maxabsD = maximum(abs.(D.diag)) end for i = 1:length(D.diag) diff --git a/base/markdown/parse/parse.jl b/base/markdown/parse/parse.jl index 052fda3642ce5..45a7bb62d8fa5 100644 --- a/base/markdown/parse/parse.jl +++ b/base/markdown/parse/parse.jl @@ -73,7 +73,7 @@ parseinline(s::AbstractString, md::MD, c::Config) = parseinline(IOBuffer(s), md, c) # TODO remove once GH #9888 is fixed -parseinline{T}(s::SubString{T}, md::MD, c::Config) = +parseinline(s::SubString{T}, md::MD, c::Config) where {T} = parseinline(convert(T, s), md, c) parseinline(s, md::MD) = parseinline(s, md, config(md)) diff --git a/base/markdown/render/plain.jl b/base/markdown/render/plain.jl index f6a4247cffe18..5d50b5c2080f1 100644 --- a/base/markdown/render/plain.jl +++ b/base/markdown/render/plain.jl @@ -13,7 +13,7 @@ end plain(io::IO, md::MD) = plain(io, md.content) -function plain{l}(io::IO, header::Header{l}) +function plain(io::IO, header::Header{l}) where l print(io, "#"^l*" ") plaininline(io, header.text) println(io) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 9fbb1b294ec0a..95b537e4460ad 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -293,7 +293,7 @@ index_ndims() = () @inline index_dimsum(i1, I...) = (index_dimsum(I...)...) @inline index_dimsum(::Colon, I...) = (true, index_dimsum(I...)...) @inline index_dimsum(::AbstractArray{Bool}, I...) = (true, index_dimsum(I...)...) -@inline function index_dimsum{_,N}(::AbstractArray{_,N}, I...) +@inline function index_dimsum(::AbstractArray{<:Any,N}, I...) where N (ntuple(x->true, Val{N})..., index_dimsum(I...)...) end index_dimsum() = () diff --git a/base/ordering.jl b/base/ordering.jl index a2e772500896d..95b86f4be57f0 100644 --- a/base/ordering.jl +++ b/base/ordering.jl @@ -19,7 +19,7 @@ struct ReverseOrdering{Fwd<:Ordering} <: Ordering end ReverseOrdering(rev::ReverseOrdering) = rev.fwd -ReverseOrdering{Fwd}(fwd::Fwd) = ReverseOrdering{Fwd}(fwd) +ReverseOrdering(fwd::Fwd) where {Fwd} = ReverseOrdering{Fwd}(fwd) const DirectOrdering = Union{ForwardOrdering,ReverseOrdering{ForwardOrdering}} diff --git a/base/range.jl b/base/range.jl index 3736f721bf597..d09d9153733a7 100644 --- a/base/range.jl +++ b/base/range.jl @@ -11,7 +11,8 @@ colon(start::T, stop::T) where {T} = colon(start, oftype(stop-start, 1), stop) range(a, len::Integer) = range(a, oftype(a-a, 1), len) # first promote start and stop, leaving step alone -colon(start::A, step, stop::C) where {A<:Real,C<:Real} = colon(convert(promote_type(A,C),start), step, convert(promote_type(A,C),stop)) +colon(start::A, step, stop::C) where {A<:Real,C<:Real} = + colon(convert(promote_type(A,C),start), step, convert(promote_type(A,C),stop)) colon(start::T, step::Real, stop::T) where {T<:Real} = colon(promote(start, step, stop)...) """ @@ -24,12 +25,16 @@ julia> colon(1, 2, 5) 1:2:5 ``` """ -colon(start::T, step::T, stop::T) where {T<:AbstractFloat} = _colon(TypeOrder(T), TypeArithmetic(T), start, step, stop) -colon(start::T, step::T, stop::T) where {T<:Real} = _colon(TypeOrder(T), TypeArithmetic(T), start, step, stop) -_colon{T}(::HasOrder, ::Any, start::T, step, stop::T) = StepRange(start, step, stop) +colon(start::T, step::T, stop::T) where {T<:AbstractFloat} = + _colon(TypeOrder(T), TypeArithmetic(T), start, step, stop) +colon(start::T, step::T, stop::T) where {T<:Real} = + _colon(TypeOrder(T), TypeArithmetic(T), start, step, stop) +_colon(::HasOrder, ::Any, start::T, step, stop::T) where {T} = StepRange(start, step, stop) # for T<:Union{Float16,Float32,Float64} see twiceprecision.jl -_colon{T}(::HasOrder, ::ArithmeticRounds, start::T, step, stop::T) = StepRangeLen(start, step, floor(Int, (stop-start)/step)+1) -_colon{T}(::Any, ::Any, start::T, step, stop::T) = StepRangeLen(start, step, floor(Int, (stop-start)/step)+1) +_colon(::HasOrder, ::ArithmeticRounds, start::T, step, stop::T) where {T} = + StepRangeLen(start, step, floor(Int, (stop-start)/step)+1) +_colon(::Any, ::Any, start::T, step, stop::T) where {T} = + StepRangeLen(start, step, floor(Int, (stop-start)/step)+1) """ :(start, [step], stop) @@ -42,7 +47,7 @@ colon(start::T, step, stop::T) where {T} = _colon(start, step, stop) colon(start::T, step, stop::T) where {T<:Real} = _colon(start, step, stop) # without the second method above, the first method above is ambiguous with # colon{A<:Real,C<:Real}(start::A, step, stop::C) -function _colon{T}(start::T, step, stop::T) +function _colon(start::T, step, stop::T) where T T′ = typeof(start+step) StepRange(convert(T′,start), step, convert(T′,stop)) end @@ -52,9 +57,11 @@ end Construct a range by length, given a starting value and optional step (defaults to 1). """ -range{T}(a::T, step, len::Integer) = _range(TypeOrder(T), TypeArithmetic(T), a, step, len) -_range{T,S}(::HasOrder, ::ArithmeticOverflows, a::T, step::S, len::Integer) = StepRange{T,S}(a, step, convert(T, a+step*(len-1))) -_range{T,S}(::Any, ::Any, a::T, step::S, len::Integer) = StepRangeLen{typeof(a+0*step),T,S}(a, step, len) +range(a::T, step, len::Integer) where {T} = _range(TypeOrder(T), TypeArithmetic(T), a, step, len) +_range(::HasOrder, ::ArithmeticOverflows, a::T, step::S, len::Integer) where {T,S} = + StepRange{T,S}(a, step, convert(T, a+step*(len-1))) +_range(::Any, ::Any, a::T, step::S, len::Integer) where {T,S} = + StepRangeLen{typeof(a+0*step),T,S}(a, step, len) # AbstractFloat specializations colon(a::T, b::T) where {T<:AbstractFloat} = colon(a, T(1), b) @@ -88,7 +95,7 @@ struct StepRange{T,S} <: OrdinalRange{T,S} end # to make StepRange constructor inlineable, so optimizer can see `step` value -function steprange_last{T}(start::T, step, stop) +function steprange_last(start::T, step, stop) where T if isa(start,AbstractFloat) || isa(step,AbstractFloat) throw(ArgumentError("StepRange should not be used with floating point")) end @@ -145,9 +152,9 @@ end UnitRange(start::T, stop::T) where {T<:Real} = UnitRange{T}(start, stop) unitrange_last(::Bool, stop::Bool) = stop -unitrange_last{T<:Integer}(start::T, stop::T) = +unitrange_last(start::T, stop::T) where {T<:Integer} = ifelse(stop >= start, stop, convert(T,start-oneunit(stop-start))) -unitrange_last{T}(start::T, stop::T) = +unitrange_last(start::T, stop::T) where {T} = ifelse(stop >= start, convert(T,start+floor(stop-start)), convert(T,start-oneunit(stop-start))) @@ -404,12 +411,12 @@ let smallint = (Int === Int64 ? length(r::OneTo{<:smallint}) = Int(r.stop) end -first{T}(r::OrdinalRange{T}) = convert(T, r.start) -first{T}(r::OneTo{T}) = oneunit(T) +first(r::OrdinalRange{T}) where {T} = convert(T, r.start) +first(r::OneTo{T}) where {T} = oneunit(T) first(r::StepRangeLen) = unsafe_getindex(r, 1) first(r::LinSpace) = r.start -last{T}(r::OrdinalRange{T}) = convert(T, r.stop) +last(r::OrdinalRange{T}) where {T} = convert(T, r.stop) last(r::StepRangeLen) = unsafe_getindex(r, length(r)) last(r::LinSpace) = r.stop @@ -859,8 +866,12 @@ function in(x, r::Range) end in(x::Integer, r::AbstractUnitRange{<:Integer}) = (first(r) <= x) & (x <= last(r)) -in{T<:Integer}(x, r::Range{T}) = isinteger(x) && !isempty(r) && x>=minimum(r) && x<=maximum(r) && (mod(convert(T,x),step(r))-mod(first(r),step(r)) == 0) -in(x::Char, r::Range{Char}) = !isempty(r) && x >= minimum(r) && x <= maximum(r) && (mod(Int(x) - Int(first(r)), step(r)) == 0) +in(x, r::Range{T}) where {T<:Integer} = + isinteger(x) && !isempty(r) && x >= minimum(r) && x <= maximum(r) && + (mod(convert(T,x),step(r))-mod(first(r),step(r)) == 0) +in(x::Char, r::Range{Char}) = + !isempty(r) && x >= minimum(r) && x <= maximum(r) && + (mod(Int(x) - Int(first(r)), step(r)) == 0) # Addition/subtraction of ranges @@ -873,7 +884,7 @@ function _define_range_op(f::ANY) range($f(first(r1),first(r2)), $f(step(r1),step(r2)), r1l) end - function $f{T}(r1::LinSpace{T}, r2::LinSpace{T}) + function $f(r1::LinSpace{T}, r2::LinSpace{T}) where T len = r1.len (len == r2.len || throw(DimensionMismatch("argument dimensions must match"))) diff --git a/base/reducedim.jl b/base/reducedim.jl index 5385a8c2c5fed..7b1ad0f493730 100644 --- a/base/reducedim.jl +++ b/base/reducedim.jl @@ -20,7 +20,7 @@ function reduced_indices(inds::Indices{N}, d::Int, rd::AbstractUnitRange) where end reduced_indices(inds::Indices, d::Int) = reduced_indices(inds, d, OneTo(1)) -function reduced_indices0{N}(inds::Indices{N}, d::Int) +function reduced_indices0(inds::Indices{N}, d::Int) where N d < 1 && throw(ArgumentError("dimension must be ≥ 1, got $d")) if d <= N return reduced_indices(inds, d, (inds[d] == OneTo(0) ? OneTo(0) : OneTo(1))) @@ -43,7 +43,7 @@ function reduced_indices(inds::Indices{N}, region) where N tuple(rinds...)::typeof(inds) end -function reduced_indices0{N}(inds::Indices{N}, region) +function reduced_indices0(inds::Indices{N}, region) where N rinds = [inds...] for i in region isa(i, Integer) || throw(ArgumentError("reduced dimension(s) must be integers")) @@ -70,11 +70,11 @@ for (Op, initval) in ((:(typeof(&)), true), (:(typeof(|)), false)) @eval initarray!(a::AbstractArray, ::$(Op), init::Bool) = (init && fill!(a, $initval); a) end -reducedim_initarray{R}(A::AbstractArray, region, v0, ::Type{R}) = fill!(similar(A,R,reduced_indices(A,region)), v0) -reducedim_initarray{T}(A::AbstractArray, region, v0::T) = reducedim_initarray(A, region, v0, T) +reducedim_initarray(A::AbstractArray, region, v0, ::Type{R}) where {R} = fill!(similar(A,R,reduced_indices(A,region)), v0) +reducedim_initarray(A::AbstractArray, region, v0::T) where {T} = reducedim_initarray(A, region, v0, T) -reducedim_initarray0{R}(A::AbstractArray, region, v0, ::Type{R}) = fill!(similar(A,R,reduced_indices0(A,region)), v0) -reducedim_initarray0{T}(A::AbstractArray, region, v0::T) = reducedim_initarray0(A, region, v0, T) +reducedim_initarray0(A::AbstractArray, region, v0, ::Type{R}) where {R} = fill!(similar(A,R,reduced_indices0(A,region)), v0) +reducedim_initarray0(A::AbstractArray, region, v0::T) where {T} = reducedim_initarray0(A, region, v0, T) # TODO: better way to handle reducedim initialization # @@ -106,9 +106,9 @@ reducedim_init(f, op::typeof(max), A::AbstractArray, region) = reducedim_init(f, reducedim_init(f, op::typeof(min), A::AbstractArray, region) = reducedim_init(f, scalarmin, A, region) reducedim_init(f::Union{typeof(abs),typeof(abs2)}, op::typeof(max), A::AbstractArray, region) = reducedim_init(f, scalarmax, A, region) -reducedim_init{T}(f, op::typeof(scalarmax), A::AbstractArray{T}, region) = reducedim_initarray0(A, region, typemin(f(zero(T)))) -reducedim_init{T}(f, op::typeof(scalarmin), A::AbstractArray{T}, region) = reducedim_initarray0(A, region, typemax(f(zero(T)))) -reducedim_init{T}(f::Union{typeof(abs),typeof(abs2)}, op::typeof(scalarmax), A::AbstractArray{T}, region) = +reducedim_init(f, op::typeof(scalarmax), A::AbstractArray{T}, region) where {T} = reducedim_initarray0(A, region, typemin(f(zero(T)))) +reducedim_init(f, op::typeof(scalarmin), A::AbstractArray{T}, region) where {T} = reducedim_initarray0(A, region, typemax(f(zero(T)))) +reducedim_init(f::Union{typeof(abs),typeof(abs2)}, op::typeof(scalarmax), A::AbstractArray{T}, region) where {T} = reducedim_initarray(A, region, zero(f(zero(T)))) reducedim_init(f, op::typeof(&), A::AbstractArray, region) = reducedim_initarray(A, region, true) diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl index 8f7661c98a139..a782a8cf912db 100644 --- a/base/sparse/sparsematrix.jl +++ b/base/sparse/sparsematrix.jl @@ -1162,7 +1162,7 @@ function find(S::SparseMatrixCSC) return sub2ind(sz, I, J) end -function findn{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}) +function findn(S::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} numnz = nnz(S) I = Vector{Ti}(numnz) J = Vector{Ti}(numnz) @@ -1185,7 +1185,7 @@ function findn{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}) return (I, J) end -function findnz{Tv,Ti}(S::SparseMatrixCSC{Tv,Ti}) +function findnz(S::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} numnz = nnz(S) I = Vector{Ti}(numnz) J = Vector{Ti}(numnz) @@ -1768,7 +1768,7 @@ macro _findr(op, A, region, Tv, Ti) end) #quote end -findmin{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, region) = @_findr(<, A, region, Tv, Ti) +findmin(A::SparseMatrixCSC{Tv,Ti}, region) where {Tv,Ti} = @_findr(<, A, region, Tv, Ti) findmax(A::SparseMatrixCSC{Tv,Ti}, region) where {Tv,Ti} = @_findr(>, A, region, Tv, Ti) findmin(A::SparseMatrixCSC) = (r=findmin(A,(1,2)); (r[1][1], r[2][1])) findmax(A::SparseMatrixCSC) = (r=findmax(A,(1,2)); (r[1][1], r[2][1])) @@ -1803,7 +1803,7 @@ getindex(A::SparseMatrixCSC, ::Colon, ::Colon) = copy(A) getindex(A::SparseMatrixCSC, i, ::Colon) = getindex(A, i, 1:size(A, 2)) getindex(A::SparseMatrixCSC, ::Colon, i) = getindex(A, 1:size(A, 1), i) -function getindex_cols{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, J::AbstractVector) +function getindex_cols(A::SparseMatrixCSC{Tv,Ti}, J::AbstractVector) where {Tv,Ti} # for indexing whole columns (m, n) = size(A) nJ = length(J) From 341a41070be48efe364d67b0b6aaa71c3f174ee5 Mon Sep 17 00:00:00 2001 From: Fengyang Wang Date: Thu, 27 Apr 2017 23:12:57 -0400 Subject: [PATCH 0590/1534] Fix #21604, check Any fields at runtime --- src/julia-syntax.scm | 18 ++++++++++++------ test/parse.jl | 9 +++++++++ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 1adb8c862e3b4..492ca2e05f537 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -677,14 +677,20 @@ (block ,@locs (call new ,@field-names))))) - (if (and (null? params) (any (lambda (t) (not (eq? t 'Any))) field-types)) + (if (and (null? params) (pair? field-types)) (list ;; definition with field types for all arguments - `(function (call ,name - ,@(map make-decl field-names field-types)) - (block - ,@locs - (call new ,@field-names))) + ;; only if any field type is not Any, checked at runtime + `(if ,(foldl (lambda (t u) + `(&& ,u (call (core ===) (core Any) ,t))) + `(call (core ===) (core Any) ,(car field-types)) + (cdr field-types)) + (block) + (function (call ,name + ,@(map make-decl field-names field-types)) + (block + ,@locs + (call new ,@field-names)))) any-ctor) (list any-ctor)))) diff --git a/test/parse.jl b/test/parse.jl index 4570ba7248f62..538329d180294 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -1135,3 +1135,12 @@ end f21586(; @m21586(a), @m21586(b)) = a + b @test f21586(a=10) == 52 + +# issue #21604 +@test_nowarn @eval module Test21604 + const Foo = Any + struct X + x::Foo + end +end +@test Test21604.X(1.0) === Test21604.X(1.0) From 0b6be2752783c341442d01ee48bf447849e25c19 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Fri, 28 Apr 2017 01:36:21 -0700 Subject: [PATCH 0591/1534] Replace Array with Vector in various locations. (#21572) (Instances matching another search expression.) --- base/linalg/lapack.jl | 48 +++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/base/linalg/lapack.jl b/base/linalg/lapack.jl index e9b23bdb9443f..529b048593aee 100644 --- a/base/linalg/lapack.jl +++ b/base/linalg/lapack.jl @@ -385,7 +385,7 @@ for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt, geqrt3, gerqf, getrf, elty, relty lwork = BlasInt(-1) cmplx = eltype(A)<:Complex if cmplx - rwork = Array{$relty}(2n) + rwork = Vector{$relty}(2n) end info = Ref{BlasInt}() for i = 1:2 @@ -1043,7 +1043,7 @@ for (gesvx, elty) in rcond = Vector{$elty}(1) ferr = similar(A, $elty, nrhs) berr = similar(A, $elty, nrhs) - work = Array{$elty}(4n) + work = Vector{$elty}(4n) iwork = Array{BlasInt}(n) info = Ref{BlasInt}() X = similar(A, $elty, n, nrhs) @@ -1112,8 +1112,8 @@ for (gesvx, elty, relty) in rcond = Vector{$relty}(1) ferr = similar(A, $relty, nrhs) berr = similar(A, $relty, nrhs) - work = Array{$elty}(2n) - rwork = Array{$relty}(2n) + work = Vector{$elty}(2n) + rwork = Vector{$relty}(2n) info = Ref{BlasInt}() X = similar(A, $elty, n, nrhs) ccall((@blasfunc($gesvx), liblapack), Void, @@ -1549,7 +1549,7 @@ for (geev, gesvd, gesdd, ggsvd, elty, relty) in rwork = Array{$relty}(job == 'N' ? 7*minmn : minmn*max(5*minmn+7, 2*max(m,n)+2*minmn+1)) end - iwork = Array{BlasInt}(8*minmn) + iwork = Vector{BlasInt}(8*minmn) info = Ref{BlasInt}() for i = 1:2 if cmplx @@ -1615,7 +1615,7 @@ for (geev, gesvd, gesdd, ggsvd, elty, relty) in work = Vector{$elty}(1) cmplx = eltype(A) <: Complex if cmplx - rwork = Array{$relty}(5minmn) + rwork = Vector{$relty}(5minmn) end lwork = BlasInt(-1) info = Ref{BlasInt}() @@ -2126,7 +2126,7 @@ for (geevx, ggev, elty, relty) in rcondv = similar(A, $relty, n) work = Vector{$elty}(1) lwork = BlasInt(-1) - rwork = Array{$relty}(2n) + rwork = Vector{$relty}(2n) info = Ref{BlasInt}() for i = 1:2 ccall((@blasfunc($geevx), liblapack), Void, @@ -2192,7 +2192,7 @@ for (geevx, ggev, elty, relty) in vr = similar(A, $elty, ldvr, n) work = Vector{$elty}(1) lwork = BlasInt(-1) - rwork = Array{$relty}(8n) + rwork = Vector{$relty}(8n) info = Ref{BlasInt}() for i = 1:2 ccall((@blasfunc($ggev), liblapack), Void, @@ -3030,7 +3030,7 @@ for (posv, potrf, potri, potrs, pstrf, elty, rtyp) in chkuplo(uplo) piv = similar(A, BlasInt, n) rank = Vector{BlasInt}(1) - work = Array{$rtyp}(2n) + work = Vector{$rtyp}(2n) info = Ref{BlasInt}() ccall((@blasfunc($pstrf), liblapack), Void, (Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, @@ -3335,7 +3335,7 @@ for (trcon, trevc, trrfs, elty) in n = checksquare(A) chkuplo(uplo) rcond = Vector{$elty}(1) - work = Array{$elty}(3n) + work = Vector{$elty}(3n) iwork = Array{BlasInt}(n) info = Ref{BlasInt}() ccall((@blasfunc($trcon), liblapack), Void, @@ -3373,7 +3373,7 @@ for (trcon, trevc, trrfs, elty) in # Allocate m = Ref{BlasInt}() - work = Array{$elty}(3n) + work = Vector{$elty}(3n) info = Ref{BlasInt}() ccall((@blasfunc($trevc), liblapack), Void, @@ -3428,7 +3428,7 @@ for (trcon, trevc, trrfs, elty) in if nrhs != size(X,2) throw(DimensionMismatch("second dimensions of B, $nrhs, and X, $(size(X,2)), must match")) end - work = Array{$elty}(3n) + work = Vector{$elty}(3n) iwork = Array{BlasInt}(n) info = Ref{BlasInt}() ccall((@blasfunc($trrfs), liblapack), Void, @@ -3463,7 +3463,7 @@ for (trcon, trevc, trrfs, elty, relty) in chkuplo(uplo) chkdiag(diag) rcond = Vector{$relty}(1) - work = Array{$elty}(2n) + work = Vector{$elty}(2n) rwork = Array{$relty}(n) info = Ref{BlasInt}() ccall((@blasfunc($trcon), liblapack), Void, @@ -3502,7 +3502,7 @@ for (trcon, trevc, trrfs, elty, relty) in # Allocate m = Ref{BlasInt}() - work = Array{$elty}(2n) + work = Vector{$elty}(2n) rwork = Array{$relty}(n) info = Ref{BlasInt}() ccall((@blasfunc($trevc), liblapack), Void, @@ -3557,7 +3557,7 @@ for (trcon, trevc, trrfs, elty, relty) in if nrhs != size(X,2) throw(DimensionMismatch("second dimensions of B, $nrhs, and X, $(size(X,2)), must match")) end - work = Array{$elty}(2n) + work = Vector{$elty}(2n) rwork = Array{$relty}(n) info = Ref{BlasInt}() ccall((@blasfunc($trrfs), liblapack), Void, @@ -3654,8 +3654,8 @@ for (stev, stebz, stegr, stein, elty) in tmp = 0.0 iblock = similar(dv, BlasInt,n) isplit = similar(dv, BlasInt,n) - work = Array{$elty}(4*n) - iwork = Array{BlasInt}(3*n) + work = Vector{$elty}(4*n) + iwork = Vector{BlasInt}(3*n) info = Ref{BlasInt}() ccall((@blasfunc($stebz), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, @@ -3744,7 +3744,7 @@ for (stev, stebz, stegr, stein, elty) in isplit[1:length(isplit_in)] = isplit_in end z = similar(dv, $elty,(n,m)) - work = Array{$elty}(5*n) + work = Vector{$elty}(5*n) iwork = Array{BlasInt}(n) ifail = Array{BlasInt}(m) info = Ref{BlasInt}() @@ -5140,7 +5140,7 @@ for (bdsqr, relty, elty) in throw(DimensionMismatch("leading dimension of C, $ldc, must be at least $n")) end # Allocate - work = Array{$relty}(4n) + work = Vector{$relty}(4n) info = Ref{BlasInt}() ccall((@blasfunc($bdsqr), liblapack), Void, (Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, @@ -5210,7 +5210,7 @@ for (bdsdc, elty) in q = similar(d, $elty, ldq) iq = similar(d, BlasInt, ldiq) work = Array{$elty}(lwork) - iwork = Array{BlasInt}(8n) + iwork = Vector{BlasInt}(8n) info = Ref{BlasInt}() ccall((@blasfunc($bdsdc), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, @@ -5259,7 +5259,7 @@ for (gecon, elty) in n = checksquare(A) lda = max(1, stride(A, 2)) rcond = Vector{$elty}(1) - work = Array{$elty}(4n) + work = Vector{$elty}(4n) iwork = Array{BlasInt}(n) info = Ref{BlasInt}() ccall((@blasfunc($gecon), liblapack), Void, @@ -5293,8 +5293,8 @@ for (gecon, elty, relty) in n = checksquare(A) lda = max(1, stride(A, 2)) rcond = Vector{$relty}(1) - work = Array{$elty}(2n) - rwork = Array{$relty}(2n) + work = Vector{$elty}(2n) + rwork = Vector{$relty}(2n) info = Ref{BlasInt}() ccall((@blasfunc($gecon), liblapack), Void, (Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, @@ -5626,7 +5626,7 @@ for (gees, gges, elty, relty) in vsr = similar(A, $elty, ldvsr, n) work = Vector{$elty}(1) lwork = BlasInt(-1) - rwork = Array{$relty}(8n) + rwork = Vector{$relty}(8n) info = Ref{BlasInt}() for i = 1:2 ccall((@blasfunc($gges), liblapack), Void, From 3f20d80fa2694dedfc80488ffe7480da838b1a67 Mon Sep 17 00:00:00 2001 From: Mus M Date: Fri, 28 Apr 2017 04:38:24 -0400 Subject: [PATCH 0592/1534] Remove hacks for 6721 for typealias in symmetric.jl (#21565) --- base/linalg/symmetric.jl | 46 ++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/base/linalg/symmetric.jl b/base/linalg/symmetric.jl index 0db662793f448..8704f94eb09f0 100644 --- a/base/linalg/symmetric.jl +++ b/base/linalg/symmetric.jl @@ -272,11 +272,14 @@ inv(A::Symmetric{T,S}) where {T<:BlasFloat,S<:StridedMatrix} = Symmetric{T,S}(in isposdef!(A::HermOrSym{<:BlasFloat,<:StridedMatrix}) = ishermitian(A) && LAPACK.potrf!(A.uplo, A.data)[2] == 0 eigfact!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}) = Eigen(LAPACK.syevr!('V', 'A', A.uplo, A.data, 0.0, 0.0, 0, 0, -1.0)...) -# Because of #6721 it is necessary to specify the parameters explicitly here. -eigfact(A::RealHermSymComplexHerm{<:Real}) = (T = eltype(A); S = promote_type(Float32, typeof(zero(T)/norm(one(T)))); eigfact!(S != T ? convert(AbstractMatrix{S}, A) : copy(A))) + +function eigfact(A::RealHermSymComplexHerm) + T = eltype(A) + S = promote_type(Float32, typeof(zero(T)/norm(one(T)))) + eigfact!(S != T ? convert(AbstractMatrix{S}, A) : copy(A)) +end eigfact!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}, irange::UnitRange) = Eigen(LAPACK.syevr!('V', 'I', A.uplo, A.data, 0.0, 0.0, irange.start, irange.stop, -1.0)...) -# Because of #6721 it is necessary to specify the parameters explicitly here. """ eigfact(A::Union{SymTridiagonal, Hermitian, Symmetric}, irange::UnitRange) -> Eigen @@ -293,11 +296,15 @@ The `UnitRange` `irange` specifies indices of the sorted eigenvalues to search f If `irange` is not `1:n`, where `n` is the dimension of `A`, then the returned factorization will be a *truncated* factorization. """ -eigfact(A::RealHermSymComplexHerm{<:Real}, irange::UnitRange) = (T = eltype(A); S = promote_type(Float32, typeof(zero(T)/norm(one(T)))); eigfact!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), irange)) +function eigfact(A::RealHermSymComplexHerm, irange::UnitRange) + T = eltype(A) + S = promote_type(Float32, typeof(zero(T)/norm(one(T)))) + eigfact!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), irange) +end eigfact!(A::RealHermSymComplexHerm{T,<:StridedMatrix}, vl::Real, vh::Real) where {T<:BlasReal} = Eigen(LAPACK.syevr!('V', 'V', A.uplo, A.data, convert(T, vl), convert(T, vh), 0, 0, -1.0)...) -# Because of #6721 it is necessary to specify the parameters explicitly here. + """ eigfact(A::Union{SymTridiagonal, Hermitian, Symmetric}, vl::Real, vu::Real) -> Eigen @@ -313,12 +320,20 @@ The following functions are available for `Eigen` objects: [`inv`](@ref), [`det` If [`vl`, `vu`] does not contain all eigenvalues of `A`, then the returned factorization will be a *truncated* factorization. """ -eigfact(A::RealHermSymComplexHerm{<:Real}, vl::Real, vh::Real) = (T = eltype(A); S = promote_type(Float32, typeof(zero(T)/norm(one(T)))); eigfact!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), vl, vh)) +function eigfact(A::RealHermSymComplexHerm, vl::Real, vh::Real) + T = eltype(A) + S = promote_type(Float32, typeof(zero(T)/norm(one(T)))) + eigfact!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), vl, vh) +end eigvals!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}) = LAPACK.syevr!('N', 'A', A.uplo, A.data, 0.0, 0.0, 0, 0, -1.0)[1] -# Because of #6721 it is necessary to specify the parameters explicitly here. -eigvals(A::RealHermSymComplexHerm{<:Real}) = (T = eltype(A); S = promote_type(Float32, typeof(zero(T)/norm(one(T)))); eigvals!(S != T ? convert(AbstractMatrix{S}, A) : copy(A))) + +function eigvals(A::RealHermSymComplexHerm) + T = eltype(A) + S = promote_type(Float32, typeof(zero(T)/norm(one(T)))) + eigvals!(S != T ? convert(AbstractMatrix{S}, A) : copy(A)) +end """ eigvals!(A::Union{SymTridiagonal, Hermitian, Symmetric}, irange::UnitRange) -> values @@ -326,8 +341,9 @@ eigvals(A::RealHermSymComplexHerm{<:Real}) = (T = eltype(A); S = promote_type(Fl Same as [`eigvals`](@ref), but saves space by overwriting the input `A`, instead of creating a copy. `irange` is a range of eigenvalue *indices* to search for - for instance, the 2nd to 8th eigenvalues. """ -eigvals!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}, irange::UnitRange) = LAPACK.syevr!('N', 'I', A.uplo, A.data, 0.0, 0.0, irange.start, irange.stop, -1.0)[1] -# Because of #6721 it is necessary to specify the parameters explicitly here. +eigvals!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}, irange::UnitRange) = + LAPACK.syevr!('N', 'I', A.uplo, A.data, 0.0, 0.0, irange.start, irange.stop, -1.0)[1] + """ eigvals(A::Union{SymTridiagonal, Hermitian, Symmetric}, irange::UnitRange) -> values @@ -353,7 +369,11 @@ julia> eigvals(A) 5.14005 ``` """ -eigvals(A::RealHermSymComplexHerm{<:Real}, irange::UnitRange) = (T = eltype(A); S = promote_type(Float32, typeof(zero(T)/norm(one(T)))); eigvals!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), irange)) +function eigvals(A::RealHermSymComplexHerm, irange::UnitRange) + T = eltype(A) + S = promote_type(Float32, typeof(zero(T)/norm(one(T)))) + eigvals!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), irange) +end """ eigvals!(A::Union{SymTridiagonal, Hermitian, Symmetric}, vl::Real, vu::Real) -> values @@ -363,7 +383,7 @@ Same as [`eigvals`](@ref), but saves space by overwriting the input `A`, instead """ eigvals!(A::RealHermSymComplexHerm{T,<:StridedMatrix}, vl::Real, vh::Real) where {T<:BlasReal} = LAPACK.syevr!('N', 'V', A.uplo, A.data, convert(T, vl), convert(T, vh), 0, 0, -1.0)[1] -# Because of #6721 it is necessary to specify the parameters explicitly here. + """ eigvals(A::Union{SymTridiagonal, Hermitian, Symmetric}, vl::Real, vu::Real) -> values @@ -388,7 +408,7 @@ julia> eigvals(A) 5.14005 ``` """ -function eigvals(A::RealHermSymComplexHerm{<:Real}, vl::Real, vh::Real) +function eigvals(A::RealHermSymComplexHerm, vl::Real, vh::Real) T = eltype(A) S = promote_type(Float32, typeof(zero(T)/norm(one(T)))) eigvals!(S != T ? convert(AbstractMatrix{S}, A) : copy(A), vl, vh) From e2f81b7e2756ec50bd9da090ab4a0b556a721c69 Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Fri, 28 Apr 2017 01:39:28 -0700 Subject: [PATCH 0593/1534] Ensure tryparse for dates returns null instead of throwing (#21509) Fixes #21504 In implementing this, the constructors for subtypes of TimeType have been refactored to use a helper function that checks the validity of the arguments passed to the constructor. This function returns a Nullable that's null when the arguments are valid and contains an ArgumentError object otherwise. --- base/dates/parse.jl | 5 +++- base/dates/types.jl | 71 ++++++++++++++++++++++++++++++++++++--------- test/dates/io.jl | 3 ++ 3 files changed, 64 insertions(+), 15 deletions(-) diff --git a/base/dates/parse.jl b/base/dates/parse.jl index 1d036a5a92ab9..07a04ac2257d6 100644 --- a/base/dates/parse.jl +++ b/base/dates/parse.jl @@ -276,8 +276,11 @@ function Base.tryparse(::Type{T}, str::AbstractString, df::DateFormat=default_fo values, pos = tryparsenext_internal(T, str, pos, len, df, false) if isnull(values) Nullable{T}() - else + elseif isnull(validargs(T, unsafe_get(values)...)) + # TODO: validargs gets called twice, since it's called again in the T constructor Nullable{T}(T(unsafe_get(values)...)) + else + Nullable{T}() end end diff --git a/base/dates/types.jl b/base/dates/types.jl index 587e7b1be6042..649ac8c9bfe0f 100644 --- a/base/dates/types.jl +++ b/base/dates/types.jl @@ -144,6 +144,30 @@ isleapyear(y) = ((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0) const DAYSINMONTH = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) daysinmonth(y,m) = DAYSINMONTH[m] + (m == 2 && isleapyear(y)) +### UTILITIES ### + +# These are necessary because the type constructors for TimeType subtypes can +# throw, and we want to be able to use tryparse without requiring a try/catch. +# This is made easier by providing a helper function that checks arguments, so +# we can validate arguments in tryparse. + +""" + validargs(::Type{<:TimeType}, args...) -> Nullable{ArgumentError} + +Determine whether the given arguments consitute valid inputs for the given type. +Returns a `Nullable{ArgumentError}` where null signifies success. +""" +function validargs end + +""" + argerror([msg]) -> Nullable{ArgumentError} + +Construct a `Nullable{ArgumentError}` with the given message, or null if no message +is provided. For use by `validargs`. +""" +argerror(msg::String) = Nullable(ArgumentError(msg)) +argerror() = Nullable{ArgumentError}() + ### CONSTRUCTORS ### # Core constructors """ @@ -153,42 +177,61 @@ Construct a `DateTime` type by parts. Arguments must be convertible to `Int64`. """ function DateTime(y::Int64, m::Int64=1, d::Int64=1, h::Int64=0, mi::Int64=0, s::Int64=0, ms::Int64=0) - 0 < m < 13 || throw(ArgumentError("Month: $m out of range (1:12)")) - 0 < d < daysinmonth(y, m) + 1 || throw(ArgumentError("Day: $d out of range (1:$(daysinmonth(y, m)))")) - -1 < h < 24 || throw(ArgumentError("Hour: $h out of range (0:23)")) - -1 < mi < 60 || throw(ArgumentError("Minute: $mi out of range (0:59)")) - -1 < s < 60 || throw(ArgumentError("Second: $s out of range (0:59)")) - -1 < ms < 1000 || throw(ArgumentError("Millisecond: $ms out of range (0:999)")) + err = validargs(DateTime, y, m, d, h, mi, s, ms) + isnull(err) || throw(unsafe_get(err)) rata = ms + 1000 * (s + 60mi + 3600h + 86400 * totaldays(y, m, d)) return DateTime(UTM(rata)) end +function validargs(::Type{DateTime}, y::Int64, m::Int64, d::Int64, + h::Int64, mi::Int64, s::Int64, ms::Int64) + 0 < m < 13 || return argerror("Month: $m out of range (1:12)") + 0 < d < daysinmonth(y, m) + 1 || return argerror("Day: $d out of range (1:$(daysinmonth(y, m)))") + -1 < h < 24 || return argerror("Hour: $h out of range (0:23)") + -1 < mi < 60 || return argerror("Minute: $mi out of range (0:59)") + -1 < s < 60 || return argerror("Second: $s out of range (0:59)") + -1 < ms < 1000 || return argerror("Millisecond: $ms out of range (0:999)") + return argerror() +end + """ Date(y, [m, d]) -> Date Construct a `Date` type by parts. Arguments must be convertible to `Int64`. """ function Date(y::Int64, m::Int64=1, d::Int64=1) - 0 < m < 13 || throw(ArgumentError("Month: $m out of range (1:12)")) - 0 < d < daysinmonth(y, m) + 1 || throw(ArgumentError("Day: $d out of range (1:$(daysinmonth(y, m)))")) + err = validargs(Date, y, m, d) + isnull(err) || throw(unsafe_get(err)) return Date(UTD(totaldays(y, m, d))) end +function validargs(::Type{Date}, y::Int64, m::Int64, d::Int64) + 0 < m < 13 || return argerror("Month: $m out of range (1:12)") + 0 < d < daysinmonth(y, m) + 1 || return argerror("Day: $d out of range (1:$(daysinmonth(y, m)))") + return argerror() +end + """ Time(h, [mi, s, ms, us, ns]) -> Time Construct a `Time` type by parts. Arguments must be convertible to `Int64`. """ function Time(h::Int64, mi::Int64=0, s::Int64=0, ms::Int64=0, us::Int64=0, ns::Int64=0) - -1 < h < 24 || throw(ArgumentError("Hour: $h out of range (0:23)")) - -1 < mi < 60 || throw(ArgumentError("Minute: $mi out of range (0:59)")) - -1 < s < 60 || throw(ArgumentError("Second: $s out of range (0:59)")) - -1 < ms < 1000 || throw(ArgumentError("Millisecond: $ms out of range (0:999)")) - -1 < us < 1000 || throw(ArgumentError("Microsecond: $us out of range (0:999)")) - -1 < ns < 1000 || throw(ArgumentError("Nanosecond: $ns out of range (0:999)")) + err = validargs(Time, h, mi, s, ms, us, ns) + isnull(err) || throw(unsafe_get(err)) return Time(Nanosecond(ns + 1000us + 1000000ms + 1000000000s + 60000000000mi + 3600000000000h)) end +function validargs(::Type{Time}, h::Int64, mi::Int64, s::Int64, ms::Int64, us::Int64, ns::Int64) + -1 < h < 24 || return argerror("Hour: $h out of range (0:23)") + -1 < mi < 60 || return argerror("Minute: $mi out of range (0:59)") + -1 < s < 60 || return argerror("Second: $s out of range (0:59)") + -1 < ms < 1000 || return argerror("Millisecond: $ms out of range (0:999)") + -1 < us < 1000 || return argerror("Microsecond: $us out of range (0:999)") + -1 < ns < 1000 || return argerror("Nanosecond: $ns out of range (0:999)") + return argerror() +end + # Convenience constructors from Periods function DateTime(y::Year, m::Month=Month(1), d::Day=Day(1), h::Hour=Hour(0), mi::Minute=Minute(0), diff --git a/test/dates/io.jl b/test/dates/io.jl index e7494f94ec7e0..79961249dd844 100644 --- a/test/dates/io.jl +++ b/test/dates/io.jl @@ -429,3 +429,6 @@ for (ms, str) in zip([0, 1, 20, 300, 450, 678], ["0", "001", "02", "3", "45", "6 @test Dates.format(dt, "sss") == rpad(str, 3, '0') @test Dates.format(dt, "ssss") == rpad(str, 4, '0') end + +# Issue #21504 +@test isnull(tryparse(Dates.Date, "0-1000")) From b164848e7200b6a897862675384b053e62f0916f Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Fri, 28 Apr 2017 01:47:52 -0700 Subject: [PATCH 0594/1534] break long rsplit lines --- base/strings/util.jl | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/base/strings/util.jl b/base/strings/util.jl index 82b9b340ca55d..fca9ca1406cb0 100644 --- a/base/strings/util.jl +++ b/base/strings/util.jl @@ -250,7 +250,8 @@ cpad(s, n::Integer, p=" ") = rpad(lpad(s,div(n+strwidth(s),2),p),n,p) # splitter can be a Char, Vector{Char}, AbstractString, Regex, ... # any splitter that provides search(s::AbstractString, splitter) -split(str::T, splitter; limit::Integer=0, keep::Bool=true) where {T<:SubString} = _split(str, splitter, limit, keep, T[]) +split(str::T, splitter; limit::Integer=0, keep::Bool=true) where {T<:SubString} = + _split(str, splitter, limit, keep, T[]) """ split(s::AbstractString, [chars]; limit::Integer=0, keep::Bool=true) @@ -273,7 +274,8 @@ julia> split(a,".") "rch" ``` """ -split(str::T, splitter; limit::Integer=0, keep::Bool=true) where {T<:AbstractString} = _split(str, splitter, limit, keep, SubString{T}[]) +split(str::T, splitter; limit::Integer=0, keep::Bool=true) where {T<:AbstractString} = + _split(str, splitter, limit, keep, SubString{T}[]) function _split(str::AbstractString, splitter, limit::Integer, keep_empty::Bool, strs::Array) i = start(str) n = endof(str) @@ -299,7 +301,8 @@ end # a bit oddball, but standard behavior in Perl, Ruby & Python: split(str::AbstractString) = split(str, _default_delims; limit=0, keep=false) -rsplit(str::T, splitter; limit::Integer=0, keep::Bool=true) where {T<:SubString} = _rsplit(str, splitter, limit, keep, T[]) +rsplit(str::T, splitter; limit::Integer=0, keep::Bool=true) where {T<:SubString} = + _rsplit(str, splitter, limit, keep, T[]) """ rsplit(s::AbstractString, [chars]; limit::Integer=0, keep::Bool=true) @@ -328,7 +331,8 @@ julia> rsplit(a,".";limit=2) "h" ``` """ -rsplit(str::T, splitter ; limit::Integer=0, keep::Bool=true) where {T<:AbstractString} = _rsplit(str, splitter, limit, keep, SubString{T}[]) +rsplit(str::T, splitter; limit::Integer=0, keep::Bool=true) where {T<:AbstractString} = + _rsplit(str, splitter, limit, keep, SubString{T}[]) function _rsplit(str::AbstractString, splitter, limit::Integer, keep_empty::Bool, strs::Array) i = start(str) n = endof(str) From 7de4596f00a827313bd917da25f0ca3e68f0bb62 Mon Sep 17 00:00:00 2001 From: Mus M Date: Fri, 28 Apr 2017 04:51:28 -0400 Subject: [PATCH 0595/1534] New syntax conversion for Array in boot.jl (#21583) * New syntax conversion * Tuple too * Update boot.jl --- base/boot.jl | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/base/boot.jl b/base/boot.jl index bb791d5f2aaca..55721469c6867 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -264,7 +264,7 @@ UnionAll(v::TypeVar, t::ANY) = ccall(:jl_type_unionall, Any, (Any, Any), v, t) Void() = nothing -(::Type{Tuple{}})() = () +(::Type{Tuple{}})() = () # Tuple{}() struct VecElement{T} value::T @@ -298,29 +298,28 @@ convert(::Type{T}, x::T) where {T} = x cconvert(::Type{T}, x) where {T} = convert(T, x) unsafe_convert(::Type{T}, x::T) where {T} = x -NTuple{N,T} = Tuple{Vararg{T,N}} +const NTuple{N,T} = Tuple{Vararg{T,N}} # primitive array constructors -(::Type{Array{T,N}})(d::NTuple{N,Int}) where {T,N} = - ccall(:jl_new_array, Array{T,N}, (Any,Any), Array{T,N}, d) -(::Type{Array{T,1}})(d::NTuple{1,Int}) where {T} = Array{T,1}(getfield(d,1)) -(::Type{Array{T,2}})(d::NTuple{2,Int}) where {T} = Array{T,2}(getfield(d,1), getfield(d,2)) -(::Type{Array{T,3}})(d::NTuple{3,Int}) where {T} = Array{T,3}(getfield(d,1), getfield(d,2), getfield(d,3)) -(::Type{Array{T,N}})(d::Vararg{Int, N}) where {T,N} = ccall(:jl_new_array, Array{T,N}, (Any,Any), Array{T,N}, d) -(::Type{Array{T,1}})(m::Int) where {T} = - ccall(:jl_alloc_array_1d, Array{T,1}, (Any,Int), Array{T,1}, m) -(::Type{Array{T,2}})(m::Int, n::Int) where {T} = - ccall(:jl_alloc_array_2d, Array{T,2}, (Any,Int,Int), Array{T,2}, m, n) -(::Type{Array{T,3}})(m::Int, n::Int, o::Int) where {T} = - ccall(:jl_alloc_array_3d, Array{T,3}, (Any,Int,Int,Int), Array{T,3}, m, n, o) - -(::Type{Array{T}})(d::NTuple{N,Int}) where {T,N} = Array{T,N}(d) -(::Type{Array{T}})(m::Int) where {T} = Array{T,1}(m) -(::Type{Array{T}})(m::Int, n::Int) where {T} = Array{T,2}(m, n) -(::Type{Array{T}})(m::Int, n::Int, o::Int) where {T} = Array{T,3}(m, n, o) - -(::Type{Array{T,1}})() where {T} = Array{T,1}(0) +Array{T,N}(d::NTuple{N,Int}) where {T,N} = + ccall(:jl_new_array, Array{T,N}, (Any, Any), Array{T,N}, d) +Array{T,1}(d::NTuple{1,Int}) where {T} = Array{T,1}(getfield(d,1)) +Array{T,2}(d::NTuple{2,Int}) where {T} = Array{T,2}(getfield(d,1), getfield(d,2)) +Array{T,3}(d::NTuple{3,Int}) where {T} = Array{T,3}(getfield(d,1), getfield(d,2), getfield(d,3)) +Array{T,N}(d::Vararg{Int,N}) where {T,N} = ccall(:jl_new_array, Array{T,N}, (Any, Any), Array{T,N}, d) +Array{T,1}(m::Int) where {T} = ccall(:jl_alloc_array_1d, Array{T,1}, (Any, Int), Array{T,1}, m) +Array{T,2}(m::Int, n::Int) where {T} = + ccall(:jl_alloc_array_2d, Array{T,2}, (Any, Int, Int), Array{T,2}, m, n) +Array{T,3}(m::Int, n::Int, o::Int) where {T} = + ccall(:jl_alloc_array_3d, Array{T,3}, (Any, Int, Int, Int), Array{T,3}, m, n, o) + +Array{T}(d::NTuple{N,Int}) where {T,N} = Array{T,N}(d) +Array{T}(m::Int) where {T} = Array{T,1}(m) +Array{T}(m::Int, n::Int) where {T} = Array{T,2}(m, n) +Array{T}(m::Int, n::Int, o::Int) where {T} = Array{T,3}(m, n, o) + +Array{T,1}() where {T} = Array{T,1}(0) # primitive Symbol constructors function Symbol(s::String) From 991b581c2723c57fc0d5005c1c7b61a1b0458308 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Fri, 28 Apr 2017 01:52:33 -0700 Subject: [PATCH 0596/1534] Make building against MKL on Windows a bit easier (#21588) account for mkl_rt.dll naming, and tweak blas linking flags to work around an issue with libtool in arpack where it says *** Warning: linker path does not have real file for library -lmkl_rt. *** I have the capability to make that library automatically link in when *** you link to this library. But I can only do this if you have a *** shared version of the library, which you do not appear to have *** because I did check the linker path looking for a file starting *** with libmkl_rt but no candidates were found. (...for file magic test) *** The inter-library dependencies that have been dropped here will be *** automatically added whenever a program is linked with this library *** or is declared to -dlopen it. *** Since this library must not contain undefined symbols, *** because either the platform does not support them or *** it was explicitly requested with -no-undefined, *** libtool will only create a static version of it. then refuses to build the shared library we want --- Make.inc | 7 +++++++ base/dft.jl | 1 + 2 files changed, 8 insertions(+) diff --git a/Make.inc b/Make.inc index 0f185de08b67d..024d4f63cda91 100644 --- a/Make.inc +++ b/Make.inc @@ -1002,9 +1002,16 @@ MKLLIB := $(MKLROOT)/lib/ia32 endif USE_SYSTEM_BLAS:=1 USE_SYSTEM_LAPACK:=1 +ifeq ($(OS), WINNT) +LIBBLASNAME := mkl_rt +LIBLAPACKNAME := mkl_rt +# work around libtool issue with arpack +MKL_LDFLAGS := -L$(MKLLIB) -Wl,-lmkl_rt +else LIBBLASNAME := libmkl_rt LIBLAPACKNAME := libmkl_rt MKL_LDFLAGS := -L$(MKLLIB) -lmkl_rt +endif ifneq ($(strip $(MKLLIB)),) ifeq ($(OS), Linux) RPATH_MKL := -Wl,-rpath,$(MKLLIB) diff --git a/base/dft.jl b/base/dft.jl index 49024b36bd04b..ab4e7e0269409 100644 --- a/base/dft.jl +++ b/base/dft.jl @@ -579,6 +579,7 @@ module FFTW correspond to [`r2r`](@ref) and [`r2r!`](@ref), respectively. """ function plan_r2r end + (Base.USE_GPL_LIBS || Base.fftw_vendor() == :mkl) && include(joinpath("fft", "FFTW.jl")) end From bc96f764388704dc9295edfe3a8bad6f21f57008 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Fri, 28 Apr 2017 03:38:09 -0700 Subject: [PATCH 0597/1534] Fix unsis download link for make win-extras (#21608) google code moved all the archived downloads around --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f2eff432666a5..0a14b11101aa6 100644 --- a/Makefile +++ b/Makefile @@ -607,7 +607,7 @@ else endif cd $(JULIAHOME)/dist-extras && \ $(JLDOWNLOAD) http://downloads.sourceforge.net/sevenzip/7z920_extra.7z && \ - $(JLDOWNLOAD) https://unsis.googlecode.com/files/nsis-2.46.5-Unicode-setup.exe && \ + $(JLDOWNLOAD) https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/unsis/nsis-2.46.5-Unicode-setup.exe && \ chmod a+x 7z.exe && \ chmod a+x 7z.dll && \ $(call spawn,./7z.exe) x -y -onsis nsis-2.46.5-Unicode-setup.exe && \ From 44a011b14f43445945d0f2b6731b3d3e4a82fd04 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Fri, 28 Apr 2017 03:38:59 -0700 Subject: [PATCH 0598/1534] Mention sparse/structured broadcast in NEWS.md. (#21602) --- NEWS.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/NEWS.md b/NEWS.md index 886602c3c6845..9029abc7acc99 100644 --- a/NEWS.md +++ b/NEWS.md @@ -343,6 +343,13 @@ Library improvements Currently, it is used by default for the new `RowVector` type only, and enforces that both `transpose(vec)` and `ctranspose(vec)` are views not copies ([#20047]). + * `map[!]` and `broadcast[!]` now have dedicated methods for sparse/structured + vectors/matrices. Specifically, `map[!]` and `broadcast[!]` over combinations including + one or more `SparseVector`, `SparseMatrixCSC`, `Diagonal`, `Bidiagonal`, `Tridiagonal`, + or `SymTridiagonal`, and any number of `broadcast` scalars, `Vector`s, or `Matrix`s, + now efficiently yield `SparseVector`s or `SparseMatrix`s as appropriate ([#19239], + [#19371], [#19518], [#19438], [#19690], [#19724], [#19926], [#19934], [#20009]). + Compiler/Runtime improvements ----------------------------- @@ -447,12 +454,16 @@ Deprecated or removed [#19018]: https://github.com/JuliaLang/julia/issues/19018 [#19157]: https://github.com/JuliaLang/julia/issues/19157 [#19233]: https://github.com/JuliaLang/julia/issues/19233 +[#19239]: https://github.com/JuliaLang/julia/issues/19239 [#19288]: https://github.com/JuliaLang/julia/issues/19288 [#19305]: https://github.com/JuliaLang/julia/issues/19305 [#19331]: https://github.com/JuliaLang/julia/issues/19331 +[#19371]: https://github.com/JuliaLang/julia/issues/19371 +[#19438]: https://github.com/JuliaLang/julia/issues/19438 [#19449]: https://github.com/JuliaLang/julia/issues/19449 [#19464]: https://github.com/JuliaLang/julia/issues/19464 [#19469]: https://github.com/JuliaLang/julia/issues/19469 +[#19518]: https://github.com/JuliaLang/julia/issues/19518 [#19533]: https://github.com/JuliaLang/julia/issues/19533 [#19543]: https://github.com/JuliaLang/julia/issues/19543 [#19594]: https://github.com/JuliaLang/julia/issues/19594 @@ -461,13 +472,16 @@ Deprecated or removed [#19670]: https://github.com/JuliaLang/julia/issues/19670 [#19677]: https://github.com/JuliaLang/julia/issues/19677 [#19680]: https://github.com/JuliaLang/julia/issues/19680 +[#19690]: https://github.com/JuliaLang/julia/issues/19690 [#19692]: https://github.com/JuliaLang/julia/issues/19692 [#19711]: https://github.com/JuliaLang/julia/issues/19711 [#19712]: https://github.com/JuliaLang/julia/issues/19712 [#19720]: https://github.com/JuliaLang/julia/issues/19720 [#19721]: https://github.com/JuliaLang/julia/issues/19721 [#19722]: https://github.com/JuliaLang/julia/issues/19722 +[#19724]: https://github.com/JuliaLang/julia/issues/19724 [#19741]: https://github.com/JuliaLang/julia/issues/19741 +[#19784]: https://github.com/JuliaLang/julia/issues/19784 [#19787]: https://github.com/JuliaLang/julia/issues/19787 [#19791]: https://github.com/JuliaLang/julia/issues/19791 [#19800]: https://github.com/JuliaLang/julia/issues/19800 @@ -476,10 +490,13 @@ Deprecated or removed [#19900]: https://github.com/JuliaLang/julia/issues/19900 [#19903]: https://github.com/JuliaLang/julia/issues/19903 [#19919]: https://github.com/JuliaLang/julia/issues/19919 +[#19926]: https://github.com/JuliaLang/julia/issues/19926 [#19931]: https://github.com/JuliaLang/julia/issues/19931 +[#19934]: https://github.com/JuliaLang/julia/issues/19934 [#19944]: https://github.com/JuliaLang/julia/issues/19944 [#19949]: https://github.com/JuliaLang/julia/issues/19949 [#19950]: https://github.com/JuliaLang/julia/issues/19950 +[#20009]: https://github.com/JuliaLang/julia/issues/20009 [#20047]: https://github.com/JuliaLang/julia/issues/20047 [#20079]: https://github.com/JuliaLang/julia/issues/20079 [#20164]: https://github.com/JuliaLang/julia/issues/20164 From e6ab126f0fe4554e09f41c9167e8d44bbadbc1d2 Mon Sep 17 00:00:00 2001 From: crobarcro Date: Fri, 28 Apr 2017 11:39:23 +0100 Subject: [PATCH 0599/1534] perf.m: missing semi-colon in pisumvec causes matrix of 10000 els to be printed to command line, taking non negligible time. (#21609) --- test/perf/micro/perf.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/perf/micro/perf.m b/test/perf/micro/perf.m index 398711f104ea9..515cf9ba72924 100644 --- a/test/perf/micro/perf.m +++ b/test/perf/micro/perf.m @@ -177,7 +177,7 @@ function timeit(name, func, varargin) %% slow pi series, vectorized %% function s = pisumvec(ignore) - a = [1:10000] + a = [1:10000]; for j=1:500 s = sum( 1./(a.^2)); end From 70c855fea48c8606d8491414f4c84768fb0d81b8 Mon Sep 17 00:00:00 2001 From: Martin Holters Date: Fri, 28 Apr 2017 17:06:33 +0200 Subject: [PATCH 0600/1534] Catch more substituition failures in finish_unionall (closes #21613) --- src/subtype.c | 20 ++++++++++++++++---- test/subtype.jl | 9 +++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/subtype.c b/src/subtype.c index ab5b83f806802..ce4dcb68e82a0 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -1402,8 +1402,14 @@ static jl_value_t *finish_unionall(jl_value_t *res, jl_varbinding_t *vb, jl_sten JL_GC_POP(); return jl_bottom_type; } - if (varval) - btemp->lb = jl_substitute_var(btemp->lb, vb->var, varval); + if (varval) { + JL_TRY { + btemp->lb = jl_substitute_var(btemp->lb, vb->var, varval); + } + JL_CATCH { + res = jl_bottom_type; + } + } else if (btemp->lb == (jl_value_t*)vb->var) btemp->lb = vb->lb; else if (btemp->depth0 == vb->depth0 && !jl_has_typevar(vb->lb, btemp->var) && @@ -1430,8 +1436,14 @@ static jl_value_t *finish_unionall(jl_value_t *res, jl_varbinding_t *vb, jl_sten JL_GC_POP(); return jl_bottom_type; } - if (varval) - btemp->ub = jl_substitute_var(btemp->ub, vb->var, varval); + if (varval) { + JL_TRY { + btemp->ub = jl_substitute_var(btemp->ub, vb->var, varval); + } + JL_CATCH { + res = jl_bottom_type; + } + } else if (btemp->ub == (jl_value_t*)vb->var) btemp->ub = vb->ub; else diff --git a/test/subtype.jl b/test/subtype.jl index c8cfe8668f78f..7233b9054e05f 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -1099,3 +1099,12 @@ let T1 = Val{Val{Val{Union{Int8,Int16,Int32,Int64,UInt8,UInt16}}}}, T2 = Val{Val{Val{Union{Int8,Int16,Int32,Int64,UInt8, S}}}} where S @test T1 <: T2 end + +# issue #21613 +abstract type A21613{S <: Tuple} end +immutable B21613{S <: Tuple, L} <: A21613{S} + data::NTuple{L,Float64} +end +@testintersect(Tuple{Type{B21613{Tuple{L},L}} where L, Any}, + Tuple{Type{SA}, Tuple} where SA<:(A21613{S} where S<:Tuple), + Tuple{Type{B21613{Tuple{L},L}} where L, Tuple}) From 46c991cccead38564131d12d45f0e8d3225b3a5f Mon Sep 17 00:00:00 2001 From: kshyatt Date: Thu, 27 Apr 2017 14:02:59 -0700 Subject: [PATCH 0601/1534] Test that push doesn't work for local non-bare repos --- test/libgit2.jl | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/libgit2.jl b/test/libgit2.jl index c3e416d84f3ea..7ba7a5dde799c 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -790,6 +790,32 @@ mktempdir() do dir end end + @testset "push" begin + up_path = joinpath(dir, "Example.PushUp") + up_repo = LibGit2.clone(cache_repo, up_path) + our_path = joinpath(dir, "Example.Push") + our_repo = LibGit2.clone(cache_repo, our_path) + # need to set this for merges to succeed + our_cfg = LibGit2.GitConfig(our_repo) + LibGit2.set!(our_cfg, "user.name", "AAAA") + LibGit2.set!(our_cfg, "user.email", "BBBB@BBBB.COM") + up_cfg = LibGit2.GitConfig(up_repo) + LibGit2.set!(up_cfg, "user.name", "AAAA") + LibGit2.set!(up_cfg, "user.email", "BBBB@BBBB.COM") + try + open(joinpath(LibGit2.path(our_repo),"file1"),"w") do f + write(f, "111\n") + end + LibGit2.add!(our_repo, "file1") + LibGit2.commit(our_repo, "add file1") + # we cannot yet locally push to non-bare repos + @test_throws LibGit2.GitError LibGit2.push(our_repo, remoteurl=up_path) + finally + close(our_repo) + close(up_repo) + end + end + @testset "Fetch from cache repository" begin repo = LibGit2.GitRepo(test_repo) try From 521550deb3b8da81c937d97b375f5d3c8f7e5be8 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Wed, 26 Apr 2017 18:44:56 -0700 Subject: [PATCH 0602/1534] Replace instances of Array with Vector in linalg/lapack.jl. --- base/linalg/lapack.jl | 186 +++++++++++++++++++++--------------------- 1 file changed, 93 insertions(+), 93 deletions(-) diff --git a/base/linalg/lapack.jl b/base/linalg/lapack.jl index 529b048593aee..96b04e5e68bd0 100644 --- a/base/linalg/lapack.jl +++ b/base/linalg/lapack.jl @@ -296,7 +296,7 @@ for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt, geqrt3, gerqf, getrf, elty, relty chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end A, d, e, tauq, taup @@ -326,7 +326,7 @@ for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt, geqrt3, gerqf, getrf, elty, relty chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end A, tau @@ -356,7 +356,7 @@ for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt, geqrt3, gerqf, getrf, elty, relty chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end A, tau @@ -409,7 +409,7 @@ for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt, geqrt3, gerqf, getrf, elty, relty chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end return A, tau, jpvt @@ -424,7 +424,7 @@ for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt, geqrt3, gerqf, getrf, elty, relty throw(ArgumentError("block size $nb > $minmn too large")) end lda = max(1, stride(A,2)) - work = Array{$elty}(nb*n) + work = Vector{$elty}(nb*n) if n > 0 info = Ref{BlasInt}() ccall((@blasfunc($geqrt), liblapack), Void, @@ -485,7 +485,7 @@ for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt, geqrt3, gerqf, getrf, elty, relty chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end A, tau @@ -513,7 +513,7 @@ for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt, geqrt3, gerqf, getrf, elty, relty chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end A, tau @@ -770,7 +770,7 @@ for (tzrzf, ormrz, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end A, tau @@ -811,7 +811,7 @@ for (tzrzf, ormrz, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end C @@ -872,12 +872,12 @@ for (gels, gesv, getrs, getri, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end k = min(m, n) F = m < n ? tril(A[1:k, 1:k]) : triu(A[1:k, 1:k]) - ssr = Array{$elty}(size(B,2)) + ssr = Vector{$elty}(size(B, 2)) for i = 1:size(B,2) x = zero($elty) for j = k+1:size(B,1) @@ -959,7 +959,7 @@ for (gels, gesv, getrs, getri, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end A @@ -1044,7 +1044,7 @@ for (gesvx, elty) in ferr = similar(A, $elty, nrhs) berr = similar(A, $elty, nrhs) work = Vector{$elty}(4n) - iwork = Array{BlasInt}(n) + iwork = Vector{BlasInt}(n) info = Ref{BlasInt}() X = similar(A, $elty, n, nrhs) ccall((@blasfunc($gesvx), liblapack), Void, @@ -1222,8 +1222,8 @@ for (gelsd, gelsy, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) - iwork = Array{BlasInt}(iwork[1]) + work = Vector{$elty}(lwork) + iwork = Vector{BlasInt}(iwork[1]) end end subsetrows(B, newB, n), rnk[1] @@ -1268,7 +1268,7 @@ for (gelsd, gelsy, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(work[1]) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end subsetrows(B, newB, n), rnk[1] @@ -1316,9 +1316,9 @@ for (gelsd, gelsy, elty, relty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) - rwork = Array{$relty}(BlasInt(rwork[1])) - iwork = Array{BlasInt}(iwork[1]) + work = Vector{$elty}(lwork) + rwork = Vector{$relty}(BlasInt(rwork[1])) + iwork = Vector{BlasInt}(iwork[1]) end end subsetrows(B, newB, n), rnk[1] @@ -1436,7 +1436,7 @@ for (gglse, elty) in ((:dgglse_, :Float64), chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end X, dot(view(c, n - p + 1:m), view(c, n - p + 1:m)) @@ -1508,7 +1508,7 @@ for (geev, gesvd, gesdd, ggsvd, elty, relty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end cmplx ? (W, VL, VR) : (WR, WI, VL, VR) @@ -1577,7 +1577,7 @@ for (geev, gesvd, gesdd, ggsvd, elty, relty) in # and # https://github.com/scipy/scipy/issues/5401 lwork = round(BlasInt, nextfloat(real(work[1]))) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end if job == 'O' @@ -1640,7 +1640,7 @@ for (geev, gesvd, gesdd, ggsvd, elty, relty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end if jobu == 'O' @@ -1816,7 +1816,7 @@ for (f, elty) in ((:dggsvd3_, :Float64), Q = jobq == 'Q' ? similar(A, $elty, ldq, n) : similar(A, $elty, 0) work = Vector{$elty}(1) lwork = BlasInt(-1) - iwork = Array{BlasInt}(n) + iwork = Vector{BlasInt}(n) info = Ref{BlasInt}() for i = 1:2 ccall((@blasfunc($f), liblapack), Void, @@ -1981,7 +1981,7 @@ for (geevx, ggev, elty) in else throw(ArgumentError("sense must be 'N', 'E', 'V' or 'B', but $sense was passed")) end - iwork = Array{BlasInt}(iworksize) + iwork = Vector{BlasInt}(iworksize) info = Ref{BlasInt}() for i = 1:2 ccall((@blasfunc($geevx), liblapack), Void, @@ -2000,7 +2000,7 @@ for (geevx, ggev, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(work[1]) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end A, wr, wi, VL, VR, ilo[], ihi[], scale, abnrm[], rconde, rcondv @@ -2063,7 +2063,7 @@ for (geevx, ggev, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(work[1]) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end alphar, alphai, beta, vl, vr @@ -2145,7 +2145,7 @@ for (geevx, ggev, elty, relty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(work[1]) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end A, w, VL, VR, ilo[], ihi[], scale, abnrm[], rconde, rcondv @@ -2209,7 +2209,7 @@ for (geevx, ggev, elty, relty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(work[1]) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end alpha, beta, vl, vr @@ -2472,7 +2472,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end if m < size(A,1) @@ -2507,7 +2507,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end if n < size(A,2) @@ -2542,7 +2542,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end if n < size(A,2) @@ -2577,7 +2577,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end if n < size(A,2) @@ -2627,7 +2627,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end C @@ -2676,7 +2676,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end C @@ -2725,7 +2725,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end C @@ -2771,7 +2771,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end C @@ -2815,7 +2815,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in throw(DimensionMismatch("wrong value for nb = $nb, which must be between 1 and $k")) end ldc = stride(C, 2) - work = Array{$elty}(wss) + work = Vector{$elty}(wss) info = Ref{BlasInt}() ccall((@blasfunc($gemqrt), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, @@ -3336,7 +3336,7 @@ for (trcon, trevc, trrfs, elty) in chkuplo(uplo) rcond = Vector{$elty}(1) work = Vector{$elty}(3n) - iwork = Array{BlasInt}(n) + iwork = Vector{BlasInt}(n) info = Ref{BlasInt}() ccall((@blasfunc($trcon), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, @@ -3429,7 +3429,7 @@ for (trcon, trevc, trrfs, elty) in throw(DimensionMismatch("second dimensions of B, $nrhs, and X, $(size(X,2)), must match")) end work = Vector{$elty}(3n) - iwork = Array{BlasInt}(n) + iwork = Vector{BlasInt}(n) info = Ref{BlasInt}() ccall((@blasfunc($trrfs), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, @@ -3464,7 +3464,7 @@ for (trcon, trevc, trrfs, elty, relty) in chkdiag(diag) rcond = Vector{$relty}(1) work = Vector{$elty}(2n) - rwork = Array{$relty}(n) + rwork = Vector{$relty}(n) info = Ref{BlasInt}() ccall((@blasfunc($trcon), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, @@ -3503,7 +3503,7 @@ for (trcon, trevc, trrfs, elty, relty) in # Allocate m = Ref{BlasInt}() work = Vector{$elty}(2n) - rwork = Array{$relty}(n) + rwork = Vector{$relty}(n) info = Ref{BlasInt}() ccall((@blasfunc($trevc), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, @@ -3558,7 +3558,7 @@ for (trcon, trevc, trrfs, elty, relty) in throw(DimensionMismatch("second dimensions of B, $nrhs, and X, $(size(X,2)), must match")) end work = Vector{$elty}(2n) - rwork = Array{$relty}(n) + rwork = Vector{$relty}(n) info = Ref{BlasInt}() ccall((@blasfunc($trrfs), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, @@ -3628,7 +3628,7 @@ for (stev, stebz, stegr, stein, elty) in throw(DimensionMismatch("ev has length $(length(ev)) but needs one less than dv's length, $n)")) end Zmat = similar(dv, $elty, (n, job != 'N' ? n : 0)) - work = Array{$elty}(max(1, 2n-2)) + work = Vector{$elty}(max(1, 2n-2)) info = Ref{BlasInt}() ccall((@blasfunc($stev), liblapack), Void, (Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{$elty}, @@ -3745,8 +3745,8 @@ for (stev, stebz, stegr, stein, elty) in end z = similar(dv, $elty,(n,m)) work = Vector{$elty}(5*n) - iwork = Array{BlasInt}(n) - ifail = Array{BlasInt}(m) + iwork = Vector{BlasInt}(n) + ifail = Vector{BlasInt}(m) info = Ref{BlasInt}() ccall((@blasfunc($stein), liblapack), Void, (Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, @@ -3834,7 +3834,7 @@ for (syconv, sysv, sytrf, sytri, sytrs, elty) in chkstride1(A, ipiv) n = checksquare(A) chkuplo(uplo) - work = Array{$elty}(n) + work = Vector{$elty}(n) info = Ref{BlasInt}() ccall((@blasfunc($syconv), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, @@ -3873,7 +3873,7 @@ for (syconv, sysv, sytrf, sytri, sytrs, elty) in chknonsingular(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end B, A, ipiv @@ -3905,7 +3905,7 @@ for (syconv, sysv, sytrf, sytri, sytrs, elty) in chkargsok(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end return A, ipiv, info[] @@ -3934,7 +3934,7 @@ for (syconv, sysv, sytrf, sytri, sytrs, elty) in # chknonsingular(info[]) # if lwork < 0 # lwork = BlasInt(real(work[1])) -# work = Array{$elty}(lwork) +# work = Vector{$elty}(lwork) # end # end # A @@ -3951,7 +3951,7 @@ for (syconv, sysv, sytrf, sytri, sytrs, elty) in chkstride1(A, ipiv) n = checksquare(A) chkuplo(uplo) - work = Array{$elty}(n) + work = Vector{$elty}(n) info = Ref{BlasInt}() ccall((@blasfunc($sytri), liblapack), Void, (Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, @@ -4023,7 +4023,7 @@ for (sysv, sytrf, sytri, sytrs, elty) in chknonsingular(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end B, A, ipiv @@ -4055,7 +4055,7 @@ for (sysv, sytrf, sytri, sytrs, elty) in chkargsok(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end return A, ipiv, info[] @@ -4072,7 +4072,7 @@ for (sysv, sytrf, sytri, sytrs, elty) in chkstride1(A, ipiv) n = checksquare(A) chkuplo(uplo) - work = Array{$elty}(n) + work = Vector{$elty}(n) info = Ref{BlasInt}() ccall((@blasfunc($sytri), liblapack), Void, (Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, @@ -4129,7 +4129,7 @@ for (syconv, hesv, hetrf, hetri, hetrs, elty, relty) in chkstride1(A,ipiv) n = checksquare(A) chkuplo(uplo) - work = Array{$elty}(n) + work = Vector{$elty}(n) info = Ref{BlasInt}() ccall((@blasfunc($syconv), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, @@ -4167,7 +4167,7 @@ for (syconv, hesv, hetrf, hetri, hetrs, elty, relty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end B, A, ipiv @@ -4197,7 +4197,7 @@ for (syconv, hesv, hetrf, hetri, hetrs, elty, relty) in chkargsok(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end A, ipiv, info[] @@ -4226,7 +4226,7 @@ for (syconv, hesv, hetrf, hetri, hetrs, elty, relty) in # chklapackerror(info[]) # if lwork < 0 # lwork = BlasInt(real(work[1])) -# work = Array{$elty}(lwork) +# work = Vector{$elty}(lwork) # end # end # A @@ -4245,7 +4245,7 @@ for (syconv, hesv, hetrf, hetri, hetrs, elty, relty) in chkstride1(A, ipiv) n = checksquare(A) chkuplo(uplo) - work = Array{$elty}(n) + work = Vector{$elty}(n) info = Ref{BlasInt}() ccall((@blasfunc($hetri), liblapack), Void, (Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, @@ -4313,7 +4313,7 @@ for (hesv, hetrf, hetri, hetrs, elty, relty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end B, A, ipiv @@ -4343,7 +4343,7 @@ for (hesv, hetrf, hetri, hetrs, elty, relty) in chkargsok(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end A, ipiv, info[] @@ -4361,7 +4361,7 @@ for (hesv, hetrf, hetri, hetrs, elty, relty) in chkstride1(A,ipiv) n = checksquare(A) chkuplo(uplo) - work = Array{$elty}(n) + work = Vector{$elty}(n) info = Ref{BlasInt}() ccall((@blasfunc($hetri), liblapack), Void, (Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, @@ -4431,7 +4431,7 @@ for (sysv, sytrf, sytri, sytrs, elty, relty) in chknonsingular(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end B, A, ipiv @@ -4464,7 +4464,7 @@ for (sysv, sytrf, sytri, sytrs, elty, relty) in chkargsok(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end A, ipiv, info[] @@ -4493,7 +4493,7 @@ for (sysv, sytrf, sytri, sytrs, elty, relty) in # chklapackerror(info[]) # if lwork < 0 # lwork = BlasInt(real(work[1])) -# work = Array{$elty}(lwork) +# work = Vector{$elty}(lwork) # end # end # A @@ -4511,7 +4511,7 @@ for (sysv, sytrf, sytri, sytrs, elty, relty) in chkstride1(A, ipiv) n = checksquare(A) chkuplo(uplo) - work = Array{$elty}(n) + work = Vector{$elty}(n) info = Ref{BlasInt}() ccall((@blasfunc($sytri), liblapack), Void, (Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, @@ -4582,7 +4582,7 @@ for (sysv, sytrf, sytri, sytrs, elty, relty) in chknonsingular(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end B, A, ipiv @@ -4615,7 +4615,7 @@ for (sysv, sytrf, sytri, sytrs, elty, relty) in chkargsok(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end A, ipiv, info[] @@ -4633,7 +4633,7 @@ for (sysv, sytrf, sytri, sytrs, elty, relty) in chkstride1(A, ipiv) n = checksquare(A) chkuplo(uplo) - work = Array{$elty}(n) + work = Vector{$elty}(n) info = Ref{BlasInt}() ccall((@blasfunc($sytri), liblapack), Void, (Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, @@ -4796,7 +4796,7 @@ for (syev, syevr, sygvd, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end jobz == 'V' ? (W, A) : W @@ -4855,9 +4855,9 @@ for (syev, syevr, sygvd, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) liwork = iwork[1] - iwork = Array{BlasInt}(liwork) + iwork = Vector{BlasInt}(liwork) end end w[1:m[]], Z[:,1:(jobz == 'V' ? m[] : 0)] @@ -4931,7 +4931,7 @@ for (syev, syevr, sygvd, elty, relty) in W = similar(A, $relty, n) work = Vector{$elty}(1) lwork = BlasInt(-1) - rwork = Array{$relty}(max(1, 3n-2)) + rwork = Vector{$relty}(max(1, 3n-2)) info = Ref{BlasInt}() for i = 1:2 ccall((@blasfunc($syev), liblapack), Void, @@ -4941,7 +4941,7 @@ for (syev, syevr, sygvd, elty, relty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end jobz == 'V' ? (W, A) : W @@ -5005,11 +5005,11 @@ for (syev, syevr, sygvd, elty, relty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) lrwork = BlasInt(rwork[1]) - rwork = Array{$relty}(lrwork) + rwork = Vector{$relty}(lrwork) liwork = iwork[1] - iwork = Array{BlasInt}(liwork) + iwork = Vector{BlasInt}(liwork) end end w[1:m[]], Z[:,1:(jobz == 'V' ? m[] : 0)] @@ -5040,7 +5040,7 @@ for (syev, syevr, sygvd, elty, relty) in lwork = BlasInt(-1) iwork = Vector{BlasInt}(1) liwork = BlasInt(-1) - rwork = Array{$relty}() + rwork = Array{$relty,0}() lrwork = BlasInt(-1) info = Ref{BlasInt}() for i = 1:2 @@ -5056,11 +5056,11 @@ for (syev, syevr, sygvd, elty, relty) in chkargsok(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) liwork = iwork[1] - iwork = Array{BlasInt}(liwork) + iwork = Vector{BlasInt}(liwork) lrwork = BlasInt(rwork[1]) - rwork = Array{$relty}(lrwork) + rwork = Vector{$relty}(lrwork) end end chkposdef(info[]) @@ -5209,7 +5209,7 @@ for (bdsdc, elty) in vt = similar(d, $elty, (ldvt, n)) q = similar(d, $elty, ldq) iq = similar(d, BlasInt, ldiq) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) iwork = Vector{BlasInt}(8n) info = Ref{BlasInt}() ccall((@blasfunc($bdsdc), liblapack), Void, @@ -5260,7 +5260,7 @@ for (gecon, elty) in lda = max(1, stride(A, 2)) rcond = Vector{$elty}(1) work = Vector{$elty}(4n) - iwork = Array{BlasInt}(n) + iwork = Vector{BlasInt}(n) info = Ref{BlasInt}() ccall((@blasfunc($gecon), liblapack), Void, (Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, @@ -5349,7 +5349,7 @@ for (gehrd, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end A, tau @@ -5399,7 +5399,7 @@ for (orghr, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end A @@ -5457,7 +5457,7 @@ for (ormhr, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end C @@ -5501,7 +5501,7 @@ for (gees, gges, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end A, vs, iszero(wi) ? wr : complex.(wr, wi) @@ -5550,7 +5550,7 @@ for (gees, gges, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end A, B, complex.(alphar, alphai), beta, vsl[1:(jobvsl == 'V' ? n : 0),:], vsr[1:(jobvsr == 'V' ? n : 0),:] @@ -5580,7 +5580,7 @@ for (gees, gges, elty, relty) in vs = similar(A, $elty, ldvs, n) work = Vector{$elty}(1) lwork = BlasInt(-1) - rwork = Array{$relty}(n) + rwork = Vector{$relty}(n) info = Ref{BlasInt}() for i = 1:2 ccall((@blasfunc($gees), liblapack), Void, @@ -5595,7 +5595,7 @@ for (gees, gges, elty, relty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end A, vs, w @@ -5645,7 +5645,7 @@ for (gees, gges, elty, relty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end A, B, alpha, beta, vsl[1:(jobvsl == 'V' ? n : 0),:], vsr[1:(jobvsr == 'V' ? n : 0),:] @@ -5692,7 +5692,7 @@ for (trexc, trsen, tgsen, elty) in n = checksquare(T) ldt = max(1, stride(T, 2)) ldq = max(1, stride(Q, 2)) - work = Array{$elty}(n) + work = Vector{$elty}(n) info = Ref{BlasInt}() ccall((@blasfunc($trexc), liblapack), Void, (Ptr{UInt8}, Ptr{BlasInt}, @@ -5893,7 +5893,7 @@ for (trexc, trsen, tgsen, elty) in chklapackerror(info[]) if i == 1 # only estimated optimal lwork, liwork lwork = BlasInt(real(work[1])) - work = Array{$elty}(lwork) + work = Vector{$elty}(lwork) end end T, Q, w From fb22520a661eb6901ef7752f024ba5ab2b5aa389 Mon Sep 17 00:00:00 2001 From: kshyatt Date: Fri, 28 Apr 2017 12:34:02 -0700 Subject: [PATCH 0603/1534] Add coverage flag passthrough to addprocs --- test/distributed_exec.jl | 31 ++++++++++++++++--------------- test/topology.jl | 12 ++++++++++-- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/test/distributed_exec.jl b/test/distributed_exec.jl index 42e8f2ce23fd1..92156132ad875 100644 --- a/test/distributed_exec.jl +++ b/test/distributed_exec.jl @@ -17,7 +17,8 @@ end 1 end -addprocs(4; exeflags=`$cov_flag $inline_flag --check-bounds=yes --startup-file=no --depwarn=error`) +cov_in_exeflags = `$cov_flag $inline_flag --check-bounds=yes --startup-file=no --depwarn=error` +addprocs(4; exeflags=cov_in_exeflags) # Test remote() let @@ -963,28 +964,28 @@ if is_unix() # aka have ssh print("\nTesting SSH addprocs with $(length(hosts)) workers...\n") new_pids = remotecall_fetch(1, hosts, sshflags) do h, sf - addprocs(h; sshflags=sf) + addprocs(h; exeflags=cov_in_exeflags, sshflags=sf) end @test length(new_pids) == length(hosts) test_n_remove_pids(new_pids) print("\nMixed ssh addprocs with :auto\n") new_pids = sort(remotecall_fetch(1, ["localhost", ("127.0.0.1", :auto), "localhost"], sshflags) do h, sf - addprocs(h; sshflags=sf) + addprocs(h; exeflags=cov_in_exeflags, sshflags=sf) end) @test length(new_pids) == (2 + Sys.CPU_CORES) test_n_remove_pids(new_pids) print("\nMixed ssh addprocs with numeric counts\n") new_pids = sort(remotecall_fetch(1, [("localhost", 2), ("127.0.0.1", 2), "localhost"], sshflags) do h, sf - addprocs(h; sshflags=sf) + addprocs(h; exeflags=cov_in_exeflags, sshflags=sf) end) @test length(new_pids) == 5 test_n_remove_pids(new_pids) print("\nssh addprocs with tunnel\n") new_pids = sort(remotecall_fetch(1, [("localhost", num_workers)], sshflags) do h, sf - addprocs(h; tunnel=true, sshflags=sf) + addprocs(h; tunnel=true, sshflags=sf, exeflags=cov_in_exeflags) end) @test length(new_pids) == num_workers test_n_remove_pids(new_pids) @@ -1211,7 +1212,7 @@ function test_add_procs_threaded_blas() master_blas_thread_count = get_num_threads() # Test with default enable_threaded_blas false - processes_added = addprocs(2) + processes_added = addprocs(2; exeflags=cov_in_exeflags) for proc_id in processes_added test_blas_config(proc_id, false) end @@ -1226,7 +1227,7 @@ function test_add_procs_threaded_blas() end rmprocs(processes_added) - processes_added = addprocs(2, enable_threaded_blas=true) + processes_added = addprocs(2, enable_threaded_blas=true, exeflags=cov_in_exeflags) for proc_id in processes_added test_blas_config(proc_id, true) end @@ -1247,7 +1248,7 @@ test_add_procs_threaded_blas() #19687 # ensure no race conditions between rmprocs and addprocs for i in 1:5 - p = addprocs(1)[1] + p = addprocs(1; exeflags=cov_in_exeflags)[1] @spawnat p sleep(5) rmprocs(p; waitfor=0) end @@ -1255,7 +1256,7 @@ end # Test if a wait has been called on rmprocs(...;waitfor=0), further remotecalls # don't throw errors. for i in 1:5 - p = addprocs(1)[1] + p = addprocs(1; exeflags=cov_in_exeflags)[1] np = nprocs() @spawnat p sleep(5) wait(rmprocs(p; waitfor=0)) @@ -1267,7 +1268,7 @@ end # Test that an exception is thrown if workers are unable to be removed within requested time. if DoFullTest - pids=addprocs(4); + pids=addprocs(4; exeflags=cov_in_exeflags); @test_throws ErrorException rmprocs(pids; waitfor=0.001); # wait for workers to be removed while any(x -> (x in procs()), pids) @@ -1276,7 +1277,7 @@ if DoFullTest end # Test addprocs/rmprocs from master node only -for f in [ ()->addprocs(1), ()->rmprocs(workers()) ] +for f in [ ()->addprocs(1; exeflags=cov_in_exeflags), ()->rmprocs(workers()) ] try remotecall_fetch(f, id_other) error("Unexpected") @@ -1322,13 +1323,13 @@ end testruns = Any[] if DoFullTest - append!(testruns, [(()->addprocs(["errorhost20372"]), "Unable to read host:port string from worker. Launch command exited with error?", ())]) + append!(testruns, [(()->addprocs(["errorhost20372"]; exeflags=cov_in_exeflags), "Unable to read host:port string from worker. Launch command exited with error?", ())]) end append!(testruns, [ - (()->addprocs(ErrorSimulator(:exit)), "Unable to read host:port string from worker. Launch command exited with error?", ()), - (()->addprocs(ErrorSimulator(:ntries)), "Unexpected output from worker launch command. Host:port string not found.", ()), - (()->addprocs(ErrorSimulator(:timeout)), "Timed out waiting to read host:port string from worker.", ("JULIA_WORKER_TIMEOUT"=>"1",)) + (()->addprocs(ErrorSimulator(:exit); exeflags=cov_in_exeflags), "Unable to read host:port string from worker. Launch command exited with error?", ()), + (()->addprocs(ErrorSimulator(:ntries); exeflags=cov_in_exeflags), "Unexpected output from worker launch command. Host:port string not found.", ()), + (()->addprocs(ErrorSimulator(:timeout); exeflags=cov_in_exeflags), "Timed out waiting to read host:port string from worker.", ("JULIA_WORKER_TIMEOUT"=>"1",)) ]) for (addp_testf, expected_errstr, env) in testruns diff --git a/test/topology.jl b/test/topology.jl index 00a53daa9ea51..46c9f39251c63 100644 --- a/test/topology.jl +++ b/test/topology.jl @@ -1,7 +1,15 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license include("testdefs.jl") -addprocs(4; topology="master_slave") +inline_flag = Base.JLOptions().can_inline == 1 ? `` : `--inline=no` +cov_flag = `` +if Base.JLOptions().code_coverage == 1 + cov_flag = `--code-coverage=user` +elseif Base.JLOptions().code_coverage == 2 + cov_flag = `--code-coverage=all` +end +cov_in_exeflags = `$cov_flag $inline_flag --check-bounds=yes --startup-file=no --depwarn=error` +addprocs(4; exeflags=cov_in_exeflags, topology="master_slave") using Base.Test @test_throws RemoteException remotecall_fetch(()->remotecall_fetch(myid, 3), 2) @@ -64,7 +72,7 @@ function Base.manage(manager::TopoTestManager, id::Integer, config::WorkerConfig end end -addprocs(TopoTestManager(8); topology="custom") +addprocs(TopoTestManager(8); exeflags=cov_in_exeflags, topology="custom") while true if any(x->get(map_pid_ident, x, 0)==0, workers()) From 228a3136fff5917b11fb99f188beec7e70e9449e Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Fri, 28 Apr 2017 15:45:22 -0400 Subject: [PATCH 0604/1534] Make structure of Cmd more obvious in printing Cmds behave as an array of strings, but for most new users the mental model they start with is that Cmds are essentially strings. As a result, people can get easily confused by the interpolation rules around Cmds. They are quite intuitive when one thinks of them as arrays of strings (e.g. arrays get expanded, strings get inserted as is), but less so when thinking of a Cmd as a single string. It seems possible to make it clearer in printing that there is an underlying structure to the Cmd by adjusting the way it prints. This one attempt at doing so by underlining each separate part of the array. Some advantages: - The underlining makes it clear that there is something going on beyong being a regular string - The underlining gets dropped when copying out from a terminal, so there's no trouble with pasting it back into a REPL. - The underlying structure of clearly visible (each contiguous underline is one of the elements of the array of strings). --- base/client.jl | 2 ++ base/process.jl | 14 +++++++------- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/base/client.jl b/base/client.jl index 268a24d692373..8202b42ddaef0 100644 --- a/base/client.jl +++ b/base/client.jl @@ -22,6 +22,7 @@ const text_colors = AnyDict( :normal => "\033[0m", :default => "\033[39m", :bold => "\033[1m", + :underline => "\033[4m", :nothing => "", ) @@ -31,6 +32,7 @@ end const disable_text_style = AnyDict( :bold => "\033[22m", + :underline => "\033[24m", :normal => "", :default => "", ) diff --git a/base/process.jl b/base/process.jl index cd15390ca42d6..161095ebe5eb1 100644 --- a/base/process.jl +++ b/base/process.jl @@ -104,14 +104,14 @@ function show(io::IO, cmd::Cmd) print_env = cmd.env !== nothing print_dir = !isempty(cmd.dir) (print_env || print_dir) && print(io, "setenv(") - esc = shell_escape(cmd, special=shell_special) print(io, '`') - for c in esc - if c == '`' - print(io, '\\') - end - print(io, c) - end + print(io, join(map(cmd.exec) do arg + replace(sprint() do io + with_output_color(:underline, io) do io + print_shell_word(io, arg, shell_special) + end + end, '`', "\\`") + end, ' ')) print(io, '`') print_env && (print(io, ","); show(io, cmd.env)) print_dir && (print(io, "; dir="); show(io, cmd.dir)) From 7af579d095a7362a72947c001482d61588c17c7c Mon Sep 17 00:00:00 2001 From: Fengyang Wang Date: Fri, 28 Apr 2017 16:48:16 -0400 Subject: [PATCH 0605/1534] Implement Jeff suggestion --- src/ast.scm | 2 +- src/julia-syntax.scm | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ast.scm b/src/ast.scm index 29408af897439..ebcd9a118b8c5 100644 --- a/src/ast.scm +++ b/src/ast.scm @@ -207,7 +207,7 @@ (if (decl? v) (cadr v) v)) (define (decl-type v) - (if (decl? v) (caddr v) 'Any)) + (if (decl? v) (caddr v) '(core Any))) (define (sym-dot? e) (and (length= e 3) (eq? (car e) '|.|) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 492ca2e05f537..7511d4854c758 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -677,7 +677,8 @@ (block ,@locs (call new ,@field-names))))) - (if (and (null? params) (pair? field-types)) + (if (and (null? params) (any (lambda (t) (not (equal? t '(core Any)))) + field-types)) (list ;; definition with field types for all arguments ;; only if any field type is not Any, checked at runtime From 7230edfe5156ba9ff9d35ee90378e68a9bf566e5 Mon Sep 17 00:00:00 2001 From: Fengyang Wang Date: Fri, 28 Apr 2017 17:47:00 -0400 Subject: [PATCH 0606/1534] Improve 'Any to '(core Any) in various places --- src/ast.scm | 4 ++-- src/julia-syntax.scm | 26 +++++++++++++------------- test/parse.jl | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 15 deletions(-) diff --git a/src/ast.scm b/src/ast.scm index ebcd9a118b8c5..40321654ee798 100644 --- a/src/ast.scm +++ b/src/ast.scm @@ -154,7 +154,7 @@ (else (bad-formal-argument v)))))) (define (arg-type v) - (cond ((symbol? v) 'Any) + (cond ((symbol? v) '(core Any)) ((not (pair? v)) (bad-formal-argument v)) (else @@ -273,7 +273,7 @@ (define (eq-sym? a b) (or (eq? a b) (and (ssavalue? a) (ssavalue? b) (eqv? (cdr a) (cdr b))))) -(define (make-var-info name) (list name 'Any 0)) +(define (make-var-info name) (list name '(core Any) 0)) (define vinfo:name car) (define vinfo:type cadr) (define (vinfo:set-type! v t) (set-car! (cdr v) t)) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 7511d4854c758..50a0a67e9a1de 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -164,7 +164,7 @@ `(block ,body)))) `(lambda ,argl () (scope-block - ,(if (eq? rett 'Any) + ,(if (equal? rett '(core Any)) body (let ((meta (take-while (lambda (x) (and (pair? x) (memq (car x) '(line meta)))) @@ -300,7 +300,7 @@ ;; construct the (method ...) expression for one primitive method definition, ;; assuming optional and keyword args are already handled -(define (method-def-expr- name sparams argl body isstaged (rett 'Any)) +(define (method-def-expr- name sparams argl body isstaged (rett '(core Any))) (if (any kwarg? argl) ;; has optional positional args @@ -940,9 +940,9 @@ ;; take apart a type signature, e.g. T{X} <: S{Y} (define (analyze-type-sig ex) (or ((pattern-lambda (-- name (-s)) - (values name '() 'Any)) ex) + (values name '() '(core Any))) ex) ((pattern-lambda (curly (-- name (-s)) . params) - (values name params 'Any)) ex) + (values name params '(core Any))) ex) ((pattern-lambda (|<:| (-- name (-s)) super) (values name '() super)) ex) ((pattern-lambda (|<:| (curly (-- name (-s)) . params) super) @@ -1004,7 +1004,7 @@ (set! name (cadr w)))) #f)) (dcl (and (pair? name) (eq? (car name) '|::|))) - (rett (if dcl (caddr name) 'Any)) + (rett (if dcl (caddr name) '(core Any))) (name (if dcl (cadr name) name))) (cond ((and (length= e 2) (symbol? name)) (if (or (eq? name 'true) (eq? name 'false)) @@ -2686,7 +2686,7 @@ ;; record. for non-symbols or globals, emit a type assertion. (let ((vi (var-info-for (cadr e) env))) (if vi - (begin (if (not (eq? (vinfo:type vi) 'Any)) + (begin (if (not (equal? (vinfo:type vi) '(core Any))) (error (string "multiple type declarations for \"" (cadr e) "\""))) (if (assq (cadr e) captvars) @@ -2753,7 +2753,7 @@ f(x) = yt(x) (composite_type ,name (call (core svec)) (call (core svec) ,@(map (lambda (v) `',v) fields)) ,super - (call (core svec) ,@(map (lambda (v) 'Any) fields)) + (call (core svec) ,@(map (lambda (v) '(core Any)) fields)) false ,(length fields)) (return (null))))))) @@ -2800,7 +2800,7 @@ f(x) = yt(x) (cl-convert (cadddr lam) fname lam (table) #f interp)))) (define (convert-for-type-decl rhs t) - (if (eq? t 'Any) + (if (equal? t '(core Any)) rhs `(call (core typeassert) (call (top convert) ,t ,rhs) @@ -2816,16 +2816,16 @@ f(x) = yt(x) (cv (assq var (cadr (lam:vinfo lam)))) (vt (or (and vi (vinfo:type vi)) (and cv (vinfo:type cv)) - 'Any)) + '(core Any))) (closed (and cv (vinfo:asgn cv) (vinfo:capt cv))) (capt (and vi (vinfo:asgn vi) (vinfo:capt vi)))) - (if (and (not closed) (not capt) (eq? vt 'Any)) + (if (and (not closed) (not capt) (equal? vt '(core Any))) `(= ,var ,rhs0) (let* ((rhs1 (if (or (ssavalue? rhs0) (simple-atom? rhs0) (equal? rhs0 '(the_exception))) rhs0 (make-ssavalue))) - (rhs (if (eq? vt 'Any) + (rhs (if (equal? vt '(core Any)) rhs1 (convert-for-type-decl rhs1 (cl-convert vt fname lam #f #f interp)))) (ex (cond (closed `(call (core setfield!) @@ -3004,7 +3004,7 @@ f(x) = yt(x) `(call (core getfield) ,fname (inert ,e))))) (if (and (vinfo:asgn cv) (vinfo:capt cv)) (let ((val `(call (core getfield) ,access (inert contents)))) - (if (eq? (vinfo:type cv) 'Any) + (if (equal? (vinfo:type cv) '(core Any)) val `(call (core typeassert) ,val ,(cl-convert (vinfo:type cv) fname lam namemap toplevel interp)))) @@ -3012,7 +3012,7 @@ f(x) = yt(x) (vi (if (and (vinfo:asgn vi) (vinfo:capt vi)) (let ((val `(call (core getfield) ,e (inert contents)))) - (if (eq? (vinfo:type vi) 'Any) + (if (equal? (vinfo:type vi) '(core Any)) val `(call (core typeassert) ,val ,(cl-convert (vinfo:type vi) fname lam namemap toplevel interp)))) diff --git a/test/parse.jl b/test/parse.jl index 538329d180294..5716c17491687 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -1144,3 +1144,42 @@ f21586(; @m21586(a), @m21586(b)) = a + b end end @test Test21604.X(1.0) === Test21604.X(1.0) + +# comment 298107224 on pull #21607 +module Test21607 + using Base.Test + + @test_warn( + "WARNING: imported binding for Any overwritten in module Test21607", + @eval const Any = Integer) + + # check that X <: Core.Any, not Integer + mutable struct X; end + @test supertype(X) === Core.Any + + # check that return type is Integer + f()::Any = 1.0 + @test f() === 1 + + # check that constructor accepts Any + struct Y + x + end + @test Y(1.0) !== Y(1) + + # check that function default argument type is Any + g(x) = x + @test g(1.0) === 1.0 + + # check that asserted variable type is Integer + @test let + x::Any = 1.0 + x + end === 1 + + # check that unasserted variable type is not Integer + @test let + x = 1.0 + x + end === 1.0 +end From b49b8a47b6a571f14ece9061d908e18e41ff1ca5 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Fri, 28 Apr 2017 18:48:41 -0700 Subject: [PATCH 0607/1534] Fix Windows LLVM build for addition of LLVM_LINK_LLVM_DYLIB flag fixes #21621, since this flag was enabled in #21498 the llvm tools have been linking against the LLVM shared library, which means on windows the dll has to be copied to build_depsbindir in order for llvm-config to run --- deps/llvm.mk | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/deps/llvm.mk b/deps/llvm.mk index 411d07954add5..ab7d85d936d8e 100644 --- a/deps/llvm.mk +++ b/deps/llvm.mk @@ -553,8 +553,14 @@ endif $(build_prefix)/manifest/llvm: | $(llvm_python_workaround) ifeq ($(LLVM_USE_CMAKE),1) +ifeq ($(OS), WINNT) +LLVM_INSTALL = \ + cd $1 && $$(CMAKE) -DCMAKE_INSTALL_PREFIX="$2$$(build_prefix)" -P cmake_install.cmake && \ + cp $2$$(build_shlibdir)/LLVM.dll $2$$(build_depsbindir) +else LLVM_INSTALL = \ cd $1 && $$(CMAKE) -DCMAKE_INSTALL_PREFIX="$2$$(build_prefix)" -P cmake_install.cmake +endif else LLVM_INSTALL = \ $(call MAKE_INSTALL,$1,$2,$3 $$(LLVM_MFLAGS) PATH="$$(llvm_python_workaround):$$$$PATH" DestSharedLibDir="$2$$(build_shlibdir)") From 6d518bc437effeb3a5d43d8c305d574182d7c90b Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Fri, 28 Apr 2017 19:22:05 -0700 Subject: [PATCH 0608/1534] make a bit more concise --- deps/llvm.mk | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/deps/llvm.mk b/deps/llvm.mk index ab7d85d936d8e..5ac5ab438f51a 100644 --- a/deps/llvm.mk +++ b/deps/llvm.mk @@ -553,13 +553,10 @@ endif $(build_prefix)/manifest/llvm: | $(llvm_python_workaround) ifeq ($(LLVM_USE_CMAKE),1) -ifeq ($(OS), WINNT) -LLVM_INSTALL = \ - cd $1 && $$(CMAKE) -DCMAKE_INSTALL_PREFIX="$2$$(build_prefix)" -P cmake_install.cmake && \ - cp $2$$(build_shlibdir)/LLVM.dll $2$$(build_depsbindir) -else LLVM_INSTALL = \ cd $1 && $$(CMAKE) -DCMAKE_INSTALL_PREFIX="$2$$(build_prefix)" -P cmake_install.cmake +ifeq ($(OS), WINNT) +LLVM_INSTALL += && cp $2$$(build_shlibdir)/LLVM.dll $2$$(build_depsbindir) endif else LLVM_INSTALL = \ From 1ae1b793e94afc37ec7ba32a3775d66b7194ff15 Mon Sep 17 00:00:00 2001 From: Mus M Date: Sat, 29 Apr 2017 06:18:32 -0400 Subject: [PATCH 0609/1534] Remove parseline method since 9888 is fixed (#21605) --- base/markdown/parse/parse.jl | 4 ---- 1 file changed, 4 deletions(-) diff --git a/base/markdown/parse/parse.jl b/base/markdown/parse/parse.jl index 45a7bb62d8fa5..b9a2f9c1f36c2 100644 --- a/base/markdown/parse/parse.jl +++ b/base/markdown/parse/parse.jl @@ -72,10 +72,6 @@ end parseinline(s::AbstractString, md::MD, c::Config) = parseinline(IOBuffer(s), md, c) -# TODO remove once GH #9888 is fixed -parseinline(s::SubString{T}, md::MD, c::Config) where {T} = - parseinline(convert(T, s), md, c) - parseinline(s, md::MD) = parseinline(s, md, config(md)) # Block parsing From 41376e2564b6bb8428dbfce95f110a65eb77d35b Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Sat, 29 Apr 2017 19:21:49 +0900 Subject: [PATCH 0610/1534] test/compile test warning from subprocess (#21585) --- test/compile.jl | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/test/compile.jl b/test/compile.jl index 3814cc8e5c678..740cf5beca532 100644 --- a/test/compile.jl +++ b/test/compile.jl @@ -437,8 +437,26 @@ let dir = mktempdir() """ exename = `$(Base.julia_cmd()) --startup-file=no` - @test readchomp(`$exename -E $(testcode)`) == "nothing" - @test readchomp(`$exename -E $(testcode)`) == "nothing" + let fname = tempname() + try + @test readchomp(pipeline(`$exename -E $(testcode)`, stderr=fname)) == "nothing" + @test Test.ismatch_warn("WARNING: replacing module $Test_module.\n", readstring(fname)) + finally + rm(fname, force=true) + end + end + # Loading $Test_module from the cache should not bring `Base.Iterators` + # into `Main`, since that would lead to a namespace conflict with + # the module `Iterators` defined above. + let fname = tempname() + try + @test readchomp(pipeline(`$exename -E $(testcode)`, stderr=fname)) == "nothing" + # e.g `@test_nowarn` + @test Test.ismatch_warn(r"^(?!.)"s, readstring(fname)) + finally + rm(fname, force=true) + end + end finally rm(dir, recursive=true) end From a0c142950562bf81e048944b9c9714a9f6af7a89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Sat, 29 Apr 2017 12:48:54 +0200 Subject: [PATCH 0611/1534] Make exp(::Complex{Irrational}) work (#21596) Addresses #21204. --- base/complex.jl | 2 +- test/complex.jl | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/base/complex.jl b/base/complex.jl index 617b20d20c487..ae9a191b181d4 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -504,7 +504,7 @@ function exp(z::Complex) end else er = exp(zr) - if zi == zero(zi) + if iszero(zi) Complex(er, zi) else Complex(er*cos(zi), er*sin(zi)) diff --git a/test/complex.jl b/test/complex.jl index fa4d31a63cd57..ccf71b3c1528f 100644 --- a/test/complex.jl +++ b/test/complex.jl @@ -943,3 +943,10 @@ end # issue #19240 @test big(1)/(10+10im) ≈ (5-5im)/big(100) ≈ big"0.05" - big"0.05"*im + +@testset "Complex Irrationals, issue #21204" begin + for x in (pi, e, catalan) # No need to test all of them + @test typeof(Complex(x, x)) == Complex{typeof(x)} + @test exp(complex(x, x)) ≈ exp(x) * cis(x) + end +end From 9f48ca0a2d768c4706d85f80710b22063f2a8f44 Mon Sep 17 00:00:00 2001 From: Nathan Smith Date: Fri, 28 Apr 2017 23:37:14 -0400 Subject: [PATCH 0612/1534] document >>, << and >>> for BitVector --- base/bitarray.jl | 79 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/base/bitarray.jl b/base/bitarray.jl index e3e81bba2c0a0..105d590c55f3a 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -1375,10 +1375,89 @@ function (>>>)(B::BitVector, i::UInt) return A end +""" + >>(B::BitVector, n) -> BitVector + +Right bit shift operator, `B >> n`. For `n >= 0`, the result is `B` +with elements shifted `n` positions forward, filling with `false` +values. If `n < 0`, elements are shifted backwards. Equivalent to +`B << -n`. + +## Example + +```jldoctest +julia> B = BitVector([true, false, true, false, false]) +5-element BitArray{1}: + true + false + true + false + false + +julia> B >> 1 +5-element BitArray{1}: + false + true + false + true + false + +julia> B >> -1 +5-element BitArray{1}: + false + true + false + false + false +``` +""" (>>)(B::BitVector, i::Union{Int, UInt}) = B >>> i # signed integer version of shift operators with handling of negative values +""" + <<(B::BitVector, n) -> BitVector + +Left bit shift operator, `B << n`. For `n >= 0`, the result is `B` +with elements shifted `n` positions backwards, filling with `false` +values. If `n < 0`, elements are shifted forwards. Equivalent to +`B >> -n`. + +## Examples + +```jldoctest +julia> B = BitVector([true, false, true, false, false]) +5-element BitArray{1}: + true + false + true + false + false + +julia> B << 1 +5-element BitArray{1}: + false + true + false + false + false + +julia> B << -1 +5-element BitArray{1}: + false + true + false + true + false +``` +""" (<<)(B::BitVector, i::Int) = (i >=0 ? B << unsigned(i) : B >> unsigned(-i)) + +""" + >>>(B::BitVector, n) -> BitVector + +Unsigned right bitshift operator, `B >>> n`. Equivalent to `B >> n`. See [`>>`](@ref) for +details and examples. +""" (>>>)(B::BitVector, i::Int) = (i >=0 ? B >> unsigned(i) : B << unsigned(-i)) """ From 4767110a435427f73e95b32842dffa0c066692f5 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Sat, 29 Apr 2017 11:07:48 -0400 Subject: [PATCH 0613/1534] Fix config write with symlink Ref https://github.com/libgit2/libgit2/pull/4169 * Test this on unix * Do not write to user's global gitconfig --- deps/libgit2.mk | 8 ++- deps/patches/libgit2-gitconfig-symlink.patch | 27 ++++++++++ test/libgit2.jl | 56 ++++++++++++++++++-- 3 files changed, 85 insertions(+), 6 deletions(-) create mode 100644 deps/patches/libgit2-gitconfig-symlink.patch diff --git a/deps/libgit2.mk b/deps/libgit2.mk index 7ff18f7093d36..4363676c0a5a8 100644 --- a/deps/libgit2.mk +++ b/deps/libgit2.mk @@ -89,6 +89,11 @@ $(LIBGIT2_SRC_PATH)/libgit2-mbedtls-verify.patch-applied: $(LIBGIT2_SRC_PATH)/so patch -p1 -f < $(SRCDIR)/patches/libgit2-mbedtls-verify.patch echo 1 > $@ +$(LIBGIT2_SRC_PATH)/libgit2-gitconfig-symlink.patch-applied: $(LIBGIT2_SRC_PATH)/source-extracted | $(LIBGIT2_SRC_PATH)/libgit2-mbedtls-verify.patch-applied + cd $(LIBGIT2_SRC_PATH) && \ + patch -p1 -f < $(SRCDIR)/patches/libgit2-gitconfig-symlink.patch + echo 1 > $@ + $(build_datarootdir)/julia/cert.pem: $(CERTFILE) mkdir -p $(build_datarootdir)/julia -cp $(CERTFILE) $@ @@ -98,7 +103,8 @@ $(BUILDDIR)/$(LIBGIT2_SRC_DIR)/build-configured: \ $(LIBGIT2_SRC_PATH)/libgit2-ssh.patch-applied \ $(LIBGIT2_SRC_PATH)/libgit2-agent-nonfatal.patch-applied \ $(LIBGIT2_SRC_PATH)/libgit2-mbedtls-writer-fix.patch-applied \ - $(LIBGIT2_SRC_PATH)/libgit2-mbedtls-verify.patch-applied + $(LIBGIT2_SRC_PATH)/libgit2-mbedtls-verify.patch-applied \ + $(LIBGIT2_SRC_PATH)/libgit2-gitconfig-symlink.patch-applied ifneq ($(CERTFILE),) $(BUILDDIR)/$(LIBGIT2_SRC_DIR)/build-configured: $(build_datarootdir)/julia/cert.pem diff --git a/deps/patches/libgit2-gitconfig-symlink.patch b/deps/patches/libgit2-gitconfig-symlink.patch new file mode 100644 index 0000000000000..bd4e983045be4 --- /dev/null +++ b/deps/patches/libgit2-gitconfig-symlink.patch @@ -0,0 +1,27 @@ +From 86a8cd9f6a039889801b5bec865a4bc3deb30f47 Mon Sep 17 00:00:00 2001 +From: Sven Strickroth2 +Date: Mon, 20 Mar 2017 11:21:00 +0100 +Subject: [PATCH] filebuf: fix resolving absolute symlinks + +The symlink destination is always concatenated to the original path. Fix +this by using `git_buf_sets` instead of `git_buf_puts`. +--- + src/filebuf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/filebuf.c b/src/filebuf.c +index ef68b16f4..825b9c04c 100644 +--- a/src/filebuf.c ++++ b/src/filebuf.c +@@ -246,7 +246,7 @@ static int resolve_symlink(git_buf *out, const char *path) + + root = git_path_root(target.ptr); + if (root >= 0) { +- if ((error = git_buf_puts(&curpath, target.ptr)) < 0) ++ if ((error = git_buf_sets(&curpath, target.ptr)) < 0) + goto cleanup; + } else { + git_buf dir = GIT_BUF_INIT; +-- +2.12.2 + diff --git a/test/libgit2.jl b/test/libgit2.jl index 375aa1e909c8c..26e899c72bea8 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -6,6 +6,37 @@ import TestHelpers: challenge_prompt const LIBGIT2_MIN_VER = v"0.23.0" const LIBGIT2_HELPER_PATH = joinpath(dirname(@__FILE__), "libgit2-helpers.jl") +function get_global_dir() + buf = Ref(LibGit2.Buffer()) + LibGit2.@check ccall((:git_libgit2_opts, :libgit2), Cint, + (Cint, Cint, Ptr{LibGit2.Buffer}), + LibGit2.Consts.GET_SEARCH_PATH, LibGit2.Consts.CONFIG_LEVEL_GLOBAL, buf) + path = unsafe_string(buf[].ptr) + LibGit2.free(buf) + return path +end + +function set_global_dir(dir) + LibGit2.@check ccall((:git_libgit2_opts, :libgit2), Cint, + (Cint, Cint, Cstring), + LibGit2.Consts.SET_SEARCH_PATH, LibGit2.Consts.CONFIG_LEVEL_GLOBAL, dir) + return +end + +function with_libgit2_temp_home(f) + mktempdir() do tmphome + oldpath = get_global_dir() + set_global_dir(tmphome) + try + @test get_global_dir() == tmphome + f(tmphome) + finally + set_global_dir(oldpath) + end + return + end +end + ######### # TESTS # ######### @@ -59,11 +90,26 @@ end end @testset "Default config" begin - #for now just see that this works - cfg = LibGit2.GitConfig() - @test isa(cfg, LibGit2.GitConfig) - LibGit2.set!(cfg, "fake.property", "AAAA") - LibGit2.getconfig("fake.property", "") == "AAAA" + with_libgit2_temp_home() do tmphome + cfg = LibGit2.GitConfig() + @test isa(cfg, LibGit2.GitConfig) + @test LibGit2.getconfig("fake.property", "") == "" + LibGit2.set!(cfg, "fake.property", "AAAA") + @test LibGit2.getconfig("fake.property", "") == "AAAA" + end +end + +is_unix() && @testset "Default config with symlink" begin + with_libgit2_temp_home() do tmphome + write(joinpath(tmphome, "real_gitconfig"), "[fake]\n\tproperty = BBB") + symlink(joinpath(tmphome, "real_gitconfig"), + joinpath(tmphome, ".gitconfig")) + cfg = LibGit2.GitConfig() + @test isa(cfg, LibGit2.GitConfig) + LibGit2.getconfig("fake.property", "") == "BBB" + LibGit2.set!(cfg, "fake.property", "AAAA") + LibGit2.getconfig("fake.property", "") == "AAAA" + end end @testset "Git URL parsing" begin From 94352ed3bf9f89425484a115c0ffe3881fc608d9 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Sat, 29 Apr 2017 12:48:47 -0400 Subject: [PATCH 0614/1534] Add libgit2 patch to fix double free of GitConfig Fix #21635 Ref libgit2/libgit2#4224 --- deps/libgit2.mk | 8 +++++++- deps/patches/libgit2-free-config.patch | 25 +++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 deps/patches/libgit2-free-config.patch diff --git a/deps/libgit2.mk b/deps/libgit2.mk index 4363676c0a5a8..fe6d5e18cd15c 100644 --- a/deps/libgit2.mk +++ b/deps/libgit2.mk @@ -94,6 +94,11 @@ $(LIBGIT2_SRC_PATH)/libgit2-gitconfig-symlink.patch-applied: $(LIBGIT2_SRC_PATH) patch -p1 -f < $(SRCDIR)/patches/libgit2-gitconfig-symlink.patch echo 1 > $@ +$(LIBGIT2_SRC_PATH)/libgit2-free-config.patch-applied: $(LIBGIT2_SRC_PATH)/source-extracted | $(LIBGIT2_SRC_PATH)/libgit2-gitconfig-symlink.patch-applied + cd $(LIBGIT2_SRC_PATH) && \ + patch -p1 -f < $(SRCDIR)/patches/libgit2-free-config.patch + echo 1 > $@ + $(build_datarootdir)/julia/cert.pem: $(CERTFILE) mkdir -p $(build_datarootdir)/julia -cp $(CERTFILE) $@ @@ -104,7 +109,8 @@ $(BUILDDIR)/$(LIBGIT2_SRC_DIR)/build-configured: \ $(LIBGIT2_SRC_PATH)/libgit2-agent-nonfatal.patch-applied \ $(LIBGIT2_SRC_PATH)/libgit2-mbedtls-writer-fix.patch-applied \ $(LIBGIT2_SRC_PATH)/libgit2-mbedtls-verify.patch-applied \ - $(LIBGIT2_SRC_PATH)/libgit2-gitconfig-symlink.patch-applied + $(LIBGIT2_SRC_PATH)/libgit2-gitconfig-symlink.patch-applied \ + $(LIBGIT2_SRC_PATH)/libgit2-free-config.patch-applied ifneq ($(CERTFILE),) $(BUILDDIR)/$(LIBGIT2_SRC_DIR)/build-configured: $(build_datarootdir)/julia/cert.pem diff --git a/deps/patches/libgit2-free-config.patch b/deps/patches/libgit2-free-config.patch new file mode 100644 index 0000000000000..767aa816c3c10 --- /dev/null +++ b/deps/patches/libgit2-free-config.patch @@ -0,0 +1,25 @@ +From 5552237686dae90fb9c22f0088de488b48654828 Mon Sep 17 00:00:00 2001 +From: Yichao Yu +Date: Sat, 29 Apr 2017 12:28:35 -0400 +Subject: [PATCH] Do not free config when creating remote + +The regression was introduced in 22261344de18b3cc60ee6937468d66a6a6a28875 +--- + src/remote.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/remote.c b/src/remote.c +index d3132f75c..15752ab27 100644 +--- a/src/remote.c ++++ b/src/remote.c +@@ -260,7 +260,6 @@ on_error: + if (error) + git_remote_free(remote); + +- git_config_free(config); + git_buf_free(&canonical_url); + git_buf_free(&var); + return error; +-- +2.12.2 + From 66de6eb4322ec5007ccdc5f1687b7c41708e1585 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Sat, 29 Apr 2017 18:58:20 +0200 Subject: [PATCH 0615/1534] fix constructors of Symmetric and Hermitian (#21622) --- base/linalg/symmetric.jl | 17 +++++++++++++++++ test/linalg/symmetric.jl | 9 ++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/base/linalg/symmetric.jl b/base/linalg/symmetric.jl index 8704f94eb09f0..d828bf83e532c 100644 --- a/base/linalg/symmetric.jl +++ b/base/linalg/symmetric.jl @@ -41,6 +41,15 @@ julia> Slower = Symmetric(A, :L) Note that `Supper` will not be equal to `Slower` unless `A` is itself symmetric (e.g. if `A == A.'`). """ Symmetric(A::AbstractMatrix, uplo::Symbol=:U) = (checksquare(A); Symmetric{eltype(A),typeof(A)}(A, char_uplo(uplo))) +Symmetric(A::Symmetric) = A +function Symmetric(A::Symmetric, uplo::Symbol) + if A.uplo == char_uplo(uplo) + return A + else + throw(ArgumentError("Cannot construct Symmetric; uplo doesn't match")) + end +end + struct Hermitian{T,S<:AbstractMatrix} <: AbstractMatrix{T} data::S uplo::Char @@ -82,6 +91,14 @@ function Hermitian(A::AbstractMatrix, uplo::Symbol=:U) end Hermitian{eltype(A),typeof(A)}(A, char_uplo(uplo)) end +Hermitian(A::Hermitian) = A +function Hermitian(A::Hermitian, uplo::Symbol) + if A.uplo == char_uplo(uplo) + return A + else + throw(ArgumentError("Cannot construct Hermitian; uplo doesn't match")) + end +end const HermOrSym{T,S} = Union{Hermitian{T,S}, Symmetric{T,S}} const RealHermSymComplexHerm{T<:Real,S} = Union{Hermitian{T,S}, Symmetric{T,S}, Hermitian{Complex{T},S}} diff --git a/test/linalg/symmetric.jl b/test/linalg/symmetric.jl index bf2a045ba7b06..ac43ea7a5420b 100644 --- a/test/linalg/symmetric.jl +++ b/test/linalg/symmetric.jl @@ -46,6 +46,14 @@ let n=10 debug && println("\ntype of a: ", eltya, "\n") + # constructor + @test Symmetric(Symmetric(asym, :U)) === Symmetric(asym, :U) + @test Hermitian(Hermitian(asym, :U)) === Hermitian(asym, :U) + @test Symmetric(Symmetric(asym, :U), :U) === Symmetric(asym, :U) + @test Hermitian(Hermitian(asym, :U), :U) === Hermitian(asym, :U) + @test_throws ArgumentError Symmetric(Symmetric(asym, :U), :L) + @test_throws ArgumentError Hermitian(Hermitian(asym, :U), :L) + # similar @test isa(similar(Symmetric(asym)), Symmetric{eltya}) @test isa(similar(Hermitian(asym)), Hermitian{eltya}) @@ -60,7 +68,6 @@ let n=10 @test asym == full(Hermitian(asym)) # parent - @test asym == parent(Hermitian(asym)) # getindex From da1a444d7807d4fd3443561d047305233acb7761 Mon Sep 17 00:00:00 2001 From: Nathan Smith Date: Sat, 29 Apr 2017 13:04:38 -0400 Subject: [PATCH 0616/1534] add documentation for abspath(p1, p2...) (#21626) * add documentation for abspath(p1, p2...) * replace tab with spaces and fix spelling mistake --- base/path.jl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/base/path.jl b/base/path.jl index f9b7ab3a233ac..37476674d0f24 100644 --- a/base/path.jl +++ b/base/path.jl @@ -258,6 +258,13 @@ normpath(a::AbstractString, b::AbstractString...) = normpath(joinpath(a,b...)) Convert a path to an absolute path by adding the current directory if necessary. """ abspath(a::String) = normpath(isabspath(a) ? a : joinpath(pwd(),a)) + +""" + abspath(path::AbstractString, paths::AbstractString...) -> AbstractString + +Convert a set of paths to an absolute path by joining them together and adding the +current directory if necessary. Equivalent to `abspath(joinpath(path, paths...))`. +""" abspath(a::AbstractString, b::AbstractString...) = abspath(joinpath(a,b...)) if is_windows() From d53bc64991cca47b239d622025efe1a7a501d13e Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sat, 29 Apr 2017 11:28:26 -0700 Subject: [PATCH 0617/1534] Replace instances of Array with Vector in sparse/umfpack.jl. --- base/sparse/umfpack.jl | 44 +++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/base/sparse/umfpack.jl b/base/sparse/umfpack.jl index e827fd7362b47..58981862d702e 100644 --- a/base/sparse/umfpack.jl +++ b/base/sparse/umfpack.jl @@ -71,9 +71,9 @@ const UMFVTypes = Union{Float64,Complex128} ## UMFPACK # the control and info arrays -const umf_ctrl = Array{Float64}(UMFPACK_CONTROL) +const umf_ctrl = Vector{Float64}(UMFPACK_CONTROL) ccall((:umfpack_dl_defaults,:libumfpack), Void, (Ptr{Float64},), umf_ctrl) -const umf_info = Array{Float64}(UMFPACK_INFO) +const umf_info = Vector{Float64}(UMFPACK_INFO) function show_umf_ctrl(level::Real = 2.0) old_prt::Float64 = umf_ctrl[1] @@ -324,15 +324,15 @@ for itype in UmfpackIndexTypes function umf_extract(lu::UmfpackLU{Float64,$itype}) umfpack_numeric!(lu) # ensure the numeric decomposition exists (lnz, unz, n_row, n_col, nz_diag) = umf_lunz(lu) - Lp = Array{$itype}(n_row + 1) - Lj = Array{$itype}(lnz) # L is returned in CSR (compressed sparse row) format - Lx = Array{Float64}(lnz) - Up = Array{$itype}(n_col + 1) - Ui = Array{$itype}(unz) - Ux = Array{Float64}(unz) - P = Array{$itype}(n_row) - Q = Array{$itype}(n_col) - Rs = Array{Float64}(n_row) + Lp = Vector{$itype}(n_row + 1) + Lj = Vector{$itype}(lnz) # L is returned in CSR (compressed sparse row) format + Lx = Vector{Float64}(lnz) + Up = Vector{$itype}(n_col + 1) + Ui = Vector{$itype}(unz) + Ux = Vector{Float64}(unz) + P = Vector{$itype}(n_row) + Q = Vector{$itype}(n_col) + Rs = Vector{Float64}(n_row) @isok ccall(($get_num_r,:libumfpack), $itype, (Ptr{$itype},Ptr{$itype},Ptr{Float64}, Ptr{$itype},Ptr{$itype},Ptr{Float64}, @@ -349,17 +349,17 @@ for itype in UmfpackIndexTypes function umf_extract(lu::UmfpackLU{Complex128,$itype}) umfpack_numeric!(lu) # ensure the numeric decomposition exists (lnz, unz, n_row, n_col, nz_diag) = umf_lunz(lu) - Lp = Array{$itype}(n_row + 1) - Lj = Array{$itype}(lnz) # L is returned in CSR (compressed sparse row) format - Lx = Array{Float64}(lnz) - Lz = Array{Float64}(lnz) - Up = Array{$itype}(n_col + 1) - Ui = Array{$itype}(unz) - Ux = Array{Float64}(unz) - Uz = Array{Float64}(unz) - P = Array{$itype}(n_row) - Q = Array{$itype}(n_col) - Rs = Array{Float64}(n_row) + Lp = Vector{$itype}(n_row + 1) + Lj = Vector{$itype}(lnz) # L is returned in CSR (compressed sparse row) format + Lx = Vector{Float64}(lnz) + Lz = Vector{Float64}(lnz) + Up = Vector{$itype}(n_col + 1) + Ui = Vector{$itype}(unz) + Ux = Vector{Float64}(unz) + Uz = Vector{Float64}(unz) + P = Vector{$itype}(n_row) + Q = Vector{$itype}(n_col) + Rs = Vector{Float64}(n_row) @isok ccall(($get_num_z,:libumfpack), $itype, (Ptr{$itype},Ptr{$itype},Ptr{Float64},Ptr{Float64}, Ptr{$itype},Ptr{$itype},Ptr{Float64},Ptr{Float64}, From be633c12b66d3149676fded1f943b886631c9c1e Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sat, 29 Apr 2017 13:41:00 -0400 Subject: [PATCH 0618/1534] improve binding deprecation message for functions fixes #21606 --- src/module.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/module.c b/src/module.c index c3cde491b9e30..dc9d7b8f1f601 100644 --- a/src/module.c +++ b/src/module.c @@ -489,10 +489,21 @@ void jl_binding_deprecation_warning(jl_binding_t *b) else jl_printf(JL_STDERR, "%s is deprecated", jl_symbol_name(b->name)); jl_value_t *v = b->value; - if (v && (jl_is_type(v) || jl_is_module(v)/* || (jl_is_function(v) && jl_is_gf(v))*/)) { - jl_printf(JL_STDERR, ", use "); - jl_static_show(JL_STDERR, v); - jl_printf(JL_STDERR, " instead"); + if (v) { + if (jl_is_type(v) || jl_is_module(v)) { + jl_printf(JL_STDERR, ", use "); + jl_static_show(JL_STDERR, v); + jl_printf(JL_STDERR, " instead"); + } + else { + jl_methtable_t *mt = jl_gf_mtable(v); + if (mt != NULL && mt->defs.unknown != jl_nothing) { + jl_printf(JL_STDERR, ", use "); + jl_static_show(JL_STDERR, (jl_value_t*)mt->module); + jl_printf(JL_STDERR, ".%s", jl_symbol_name(mt->name)); + jl_printf(JL_STDERR, " instead"); + } + } } jl_printf(JL_STDERR, ".\n"); From 6d240982bf61b5e3e540c2a3a4da8b5883effc02 Mon Sep 17 00:00:00 2001 From: Roman Poya Date: Sun, 30 Apr 2017 02:01:21 +0100 Subject: [PATCH 0619/1534] Make python benchmark more idiomatic (#21628) --- test/perf/micro/perf.py | 67 +++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 30 deletions(-) diff --git a/test/perf/micro/perf.py b/test/perf/micro/perf.py index 164155a048b69..b1bd40f150be9 100644 --- a/test/perf/micro/perf.py +++ b/test/perf/micro/perf.py @@ -1,9 +1,9 @@ from numpy import * -from numpy.linalg import * +from numpy.random import rand, randn +from numpy.linalg import matrix_power import sys import time import random -import numpy if sys.version_info < (3,): range = xrange @@ -44,22 +44,22 @@ def randmatstat(t): v = zeros(t) w = zeros(t) for i in range(1,t): - a = numpy.random.randn(n, n) - b = numpy.random.randn(n, n) - c = numpy.random.randn(n, n) - d = numpy.random.randn(n, n) - P = matrix(hstack((a, b, c, d))) - Q = matrix(vstack((hstack((a, b)), hstack((c, d))))) - v[i] = trace(matrix_power(transpose(P)*P, 4)) - w[i] = trace(matrix_power(transpose(Q)*Q, 4)) + a = randn(n, n) + b = randn(n, n) + c = randn(n, n) + d = randn(n, n) + P = concatenate((a, b, c, d)) + Q = concatenate((concatenate((a, b)), concatenate((c, d))),axis=1) + v[i] = trace(matrix_power(dot(P.T,P), 4)) + w[i] = trace(matrix_power(dot(Q.T,Q), 4)) return (std(v)/mean(v), std(w)/mean(w)) ## randmatmul ## def randmatmul(n): - A = numpy.random.rand(n,n) - B = numpy.random.rand(n,n) - return numpy.dot(A,B) + A = rand(n,n) + B = rand(n,n) + return dot(A,B) ## mandelbrot ## @@ -73,8 +73,8 @@ def mandel(z): return maxiter def mandelperf(): - r1 = numpy.linspace(-2.0, 0.5, 26) - r2 = numpy.linspace(-1.0, 1.0, 21) + r1 = [-2. + 0.1*i for i in range(26)] + r2 = [-1. + 0.1*i for i in range(21)] return [mandel(complex(r, i)) for r in r1 for i in r2] def pisum(): @@ -89,15 +89,28 @@ def pisum(): # def pisumvec(): # return numpy.sum(1./(numpy.arange(1,10000)**2)) +def parse_int(t): + for i in range(1,t): + n = random.randint(0,2**32-1) + s = hex(n) + if s[-1]=='L': + s = s[0:-1] + m = int(s,16) + assert m == n + return n + def print_perf(name, time): print("python," + name + "," + str(time*1000)) ## run tests ## if __name__=="__main__": + + mintrials = 5 + assert fib(20) == 6765 tmin = float('inf') - for i in range(5): + for i in range(mintrials): t = time.time() f = fib(20) t = time.time()-t @@ -105,22 +118,16 @@ def print_perf(name, time): print_perf("fib", tmin) tmin = float('inf') - for i in range(5): + for i in range(mintrials): t = time.time() - for i in range(1,1000): - n = random.randint(0,2**32-1) - s = hex(n) - if s[-1]=='L': - s = s[0:-1] - m = int(s,16) - assert m == n + n = parse_int(1000) t = time.time()-t if t < tmin: tmin = t print_perf ("parse_int", tmin) assert sum(mandelperf()) == 14791 tmin = float('inf') - for i in range(5): + for i in range(mintrials): t = time.time() mandelperf() t = time.time()-t @@ -128,7 +135,7 @@ def print_perf(name, time): print_perf ("mandel", tmin) tmin = float('inf') - for i in range(5): + for i in range(mintrials): lst = [ random.random() for i in range(1,5000) ] t = time.time() qsort_kernel(lst, 0, len(lst)-1) @@ -138,7 +145,7 @@ def print_perf(name, time): assert abs(pisum()-1.644834071848065) < 1e-6 tmin = float('inf') - for i in range(5): + for i in range(mintrials): t = time.time() pisum() t = time.time()-t @@ -147,7 +154,7 @@ def print_perf(name, time): # assert abs(pisumvec()-1.644834071848065) < 1e-6 # tmin = float('inf') - # for i in range(5): + # for i in range(mintrials): # t = time.time() # pisumvec() # t = time.time()-t @@ -157,7 +164,7 @@ def print_perf(name, time): (s1, s2) = randmatstat(1000) assert s1 > 0.5 and s1 < 1.0 tmin = float('inf') - for i in range(5): + for i in range(mintrials): t = time.time() randmatstat(1000) t = time.time()-t @@ -165,7 +172,7 @@ def print_perf(name, time): print_perf ("rand_mat_stat", tmin) tmin = float('inf') - for i in range(5): + for i in range(mintrials): t = time.time() C = randmatmul(1000) assert C[0,0] >= 0 From da69be277435098c94d1a038df01cbc208fac143 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Sat, 29 Apr 2017 19:06:50 -0700 Subject: [PATCH 0620/1534] fix line number in a doctest (#21633) --- base/strings/util.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/strings/util.jl b/base/strings/util.jl index fca9ca1406cb0..c4c4459545128 100644 --- a/base/strings/util.jl +++ b/base/strings/util.jl @@ -491,7 +491,7 @@ throwing an `ArgumentError` indicating the position of the first non-ASCII byte. julia> ascii("abcdeγfgh") ERROR: ArgumentError: invalid ASCII at index 6 in "abcdeγfgh" Stacktrace: - [1] ascii(::String) at ./strings/util.jl:475 + [1] ascii(::String) at ./strings/util.jl:479 julia> ascii("abcdefgh") "abcdefgh" From 46551cdc408b9af2f21c0308eb71ffb8bef642d3 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sat, 29 Apr 2017 22:01:41 -0700 Subject: [PATCH 0621/1534] Replace various instances of Array with Vector. (#21645) --- base/Enums.jl | 2 +- base/io.jl | 2 +- base/loading.jl | 2 +- base/pkg/resolve.jl | 4 ++-- base/pkg/resolve/interface.jl | 2 +- base/random.jl | 2 +- base/sparse/sparsematrix.jl | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/base/Enums.jl b/base/Enums.jl index e29efb296e087..5d00f78baa1f7 100644 --- a/base/Enums.jl +++ b/base/Enums.jl @@ -63,7 +63,7 @@ macro enum(T,syms...) elseif !isa(T,Symbol) throw(ArgumentError("invalid type expression for enum $T")) end - vals = Array{Tuple{Symbol,Integer}}(0) + vals = Vector{Tuple{Symbol,Integer}}(0) lo = hi = 0 i = zero(basetype) hasexpr = false diff --git a/base/io.jl b/base/io.jl index 6e9e8c87a4267..9ac08e77863b6 100644 --- a/base/io.jl +++ b/base/io.jl @@ -521,7 +521,7 @@ Read at most `nb` bytes from `s`, returning a `Vector{UInt8}` of the bytes read. function read(s::IO, nb=typemax(Int)) # Let readbytes! grow the array progressively by default # instead of taking of risk of over-allocating - b = Array{UInt8}(nb == typemax(Int) ? 1024 : nb) + b = Vector{UInt8}(nb == typemax(Int) ? 1024 : nb) nr = readbytes!(s, b, nb) return resize!(b, nr) end diff --git a/base/loading.jl b/base/loading.jl index 8d0c3b87f2f8a..355ada1fac751 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -47,7 +47,7 @@ elseif is_apple() path_basename = String(basename(path)) local casepreserved_basename const header_size = 12 - buf = Array{UInt8}(length(path_basename) + header_size + 1) + buf = Vector{UInt8}(length(path_basename) + header_size + 1) while true ret = ccall(:getattrlist, Cint, (Cstring, Ptr{Void}, Ptr{Void}, Csize_t, Culong), diff --git a/base/pkg/resolve.jl b/base/pkg/resolve.jl index 8cd453fa20d25..a8481a9aee5c0 100644 --- a/base/pkg/resolve.jl +++ b/base/pkg/resolve.jl @@ -74,7 +74,7 @@ function sanity_check(deps::Dict{String,Dict{VersionNumber,Available}}, end end - vers = Array{Tuple{String,VersionNumber,VersionNumber}}(0) + vers = Vector{Tuple{String,VersionNumber,VersionNumber}}(0) for (p,d) in deps, vn in keys(d) lvns = VersionNumber[Iterators.filter(vn2->(vn2>vn), keys(d))...] nvn = isempty(lvns) ? typemax(VersionNumber) : minimum(lvns) @@ -88,7 +88,7 @@ function sanity_check(deps::Dict{String,Dict{VersionNumber,Available}}, checked = falses(nv) - problematic = Array{Tuple{String,VersionNumber,String}}(0) + problematic = Vector{Tuple{String,VersionNumber,String}}(0) i = 1 psl = 0 for (p,vn,nvn) in vers diff --git a/base/pkg/resolve/interface.jl b/base/pkg/resolve/interface.jl index 0fc14623562c7..9ed3c6d531db5 100644 --- a/base/pkg/resolve/interface.jl +++ b/base/pkg/resolve/interface.jl @@ -240,7 +240,7 @@ function enforce_optimality!(sol::Vector{Int}, interface::Interface) # prepare some useful structures # pdeps[p0][v0] has all dependencies of package p0 version v0 - pdeps = [Array{Requires}(spp[p0]-1) for p0 = 1:np] + pdeps = [Vector{Requires}(spp[p0]-1) for p0 = 1:np] # prevdeps[p1][p0][v0] is the VersionSet of package p1 which package p0 version v0 # depends upon prevdeps = [Dict{Int,Dict{Int,VersionSet}}() for p0 = 1:np] diff --git a/base/random.jl b/base/random.jl index fd4a5765d17a1..471ac6bbd18d2 100644 --- a/base/random.jl +++ b/base/random.jl @@ -576,7 +576,7 @@ else limbs::Vector{Limb} # buffer to be copied into generated BigInt's mask::Limb # applied to the highest limb - RangeGeneratorBigInt(a, m, nlimbs, mask) = new(a, m, Array{Limb}(nlimbs), mask) + RangeGeneratorBigInt(a, m, nlimbs, mask) = new(a, m, Vector{Limb}(nlimbs), mask) end end diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl index a782a8cf912db..f21a2411f17d6 100644 --- a/base/sparse/sparsematrix.jl +++ b/base/sparse/sparsematrix.jl @@ -327,7 +327,7 @@ end # convert'ing from SparseMatrixCSC to other matrix types function convert(::Type{Matrix}, S::SparseMatrixCSC{Tv}) where Tv # Handle cases where zero(Tv) is not defined but the array is dense. - A = length(S) == nnz(S) ? Array{Tv}(S.m, S.n) : zeros(Tv, S.m, S.n) + A = length(S) == nnz(S) ? Matrix{Tv}(S.m, S.n) : zeros(Tv, S.m, S.n) for Sj in 1:S.n for Sk in nzrange(S, Sj) Si = S.rowval[Sk] From 552626cc97e14cf9846e435dc3589110e9352dbb Mon Sep 17 00:00:00 2001 From: Napoleon Oikonomou Date: Sun, 30 Apr 2017 08:06:42 +0300 Subject: [PATCH 0622/1534] Fix matrix logarithm (#21643) Closes #21179 --- base/linalg/dense.jl | 36 +++++++++++++++--------------------- base/linalg/symmetric.jl | 4 ++-- base/linalg/triangular.jl | 32 ++++++++++---------------------- test/linalg/dense.jl | 26 ++++++++++++++++++++++++++ 4 files changed, 53 insertions(+), 45 deletions(-) diff --git a/base/linalg/dense.jl b/base/linalg/dense.jl index cd3422938eaef..11676b92c51f3 100644 --- a/base/linalg/dense.jl +++ b/base/linalg/dense.jl @@ -554,36 +554,30 @@ julia> logm(A) function logm(A::StridedMatrix{T}) where T # If possible, use diagonalization if issymmetric(A) && T <: Real - return full(logm(Symmetric(A))) + return logm(Symmetric(A)) end if ishermitian(A) - return full(logm(Hermitian(A))) + return logm(Hermitian(A)) end # Use Schur decomposition n = checksquare(A) if istriu(A) - retmat = full(logm(UpperTriangular(complex(A)))) - d = diag(A) + return full(logm(UpperTriangular(complex(A)))) else - S,Q,d = schur(complex(A)) - R = logm(UpperTriangular(S)) - retmat = Q * R * Q' - end - - # Check whether the matrix has nonpositive real eigs - np_real_eigs = false - for i = 1:n - if imag(d[i]) < eps() && real(d[i]) <= 0 - np_real_eigs = true - break + if isreal(A) + SchurF = schurfact(real(A)) + else + SchurF = schurfact(A) + end + if !istriu(SchurF.T) + SchurS = schurfact(complex(SchurF.T)) + logT = SchurS.Z * logm(UpperTriangular(SchurS.T)) * SchurS.Z' + return SchurF.Z * logT * SchurF.Z' + else + R = logm(UpperTriangular(complex(SchurF.T))) + return SchurF.Z * R * SchurF.Z' end - end - - if isreal(A) && !np_real_eigs - return real(retmat) - else - return retmat end end function logm(a::Number) diff --git a/base/linalg/symmetric.jl b/base/linalg/symmetric.jl index d828bf83e532c..6d9c865edca32 100644 --- a/base/linalg/symmetric.jl +++ b/base/linalg/symmetric.jl @@ -526,7 +526,7 @@ for (funm, func) in ([:logm,:log], [:sqrtm,:sqrt]) @eval begin function ($funm)(A::Symmetric{T}) where T<:Real F = eigfact(A) - if isposdef(F) + if all(λ -> λ ≥ 0, F.values) retmat = (F.vectors * Diagonal(($func).(F.values))) * F.vectors' else retmat = (F.vectors * Diagonal(($func).(complex.(F.values)))) * F.vectors' @@ -537,7 +537,7 @@ for (funm, func) in ([:logm,:log], [:sqrtm,:sqrt]) function ($funm)(A::Hermitian{T}) where T n = checksquare(A) F = eigfact(A) - if isposdef(F) + if all(λ -> λ ≥ 0, F.values) retmat = (F.vectors * Diagonal(($func).(F.values))) * F.vectors' if T <: Real return Hermitian(retmat) diff --git a/base/linalg/triangular.jl b/base/linalg/triangular.jl index 7e1f0944fb1a8..a9935851177cc 100644 --- a/base/linalg/triangular.jl +++ b/base/linalg/triangular.jl @@ -1757,19 +1757,12 @@ function logm(A0::UpperTriangular{T}) where T<:Union{Float64,Complex{Float64}} m = 0 # Compute repeated roots - d = diag(A) - dm1 = Vector{T}(n) + d = complex(diag(A)) + dm1 = d .- 1 s = 0 - for i = 1:n - dm1[i] = d[i] - 1. - end - while norm(dm1, Inf) > theta[tmax] - for i = 1:n - d[i] = sqrt(d[i]) - end - for i = 1:n - dm1[i] = d[i] - 1 - end + while norm(dm1, Inf) > theta[tmax] && s < maxsqrt + d .= sqrt.(d) + dm1 .= d .- 1 s = s + 1 end s0 = s @@ -1783,7 +1776,7 @@ function logm(A0::UpperTriangular{T}) where T<:Union{Float64,Complex{Float64}} alpha2 = max(d2, d3) foundm = false if alpha2 <= theta[2] - m = alpha2<=theta[1]?1:2 + m = alpha2 <= theta[1] ? 1 : 2 foundm = true end @@ -1964,16 +1957,11 @@ function invsquaring(A0::UpperTriangular, theta) # Compute repeated roots d = complex(diag(A)) - dm1 = similar(d, n) + dm1 = d .- 1 s = 0 - for i = 1:n - dm1[i] = d[i] - 1 - end - while norm(dm1, Inf) > theta[tmax] - for i = 1:n - d[i] = sqrt(d[i]) - dm1[i] = d[i] - 1 - end + while norm(dm1, Inf) > theta[tmax] && s < maxsqrt + d .= sqrt.(d) + dm1 .= d .- 1 s = s + 1 end s0 = s diff --git a/test/linalg/dense.jl b/test/linalg/dense.jl index 29a7659caad0f..3f1b316ba3905 100644 --- a/test/linalg/dense.jl +++ b/test/linalg/dense.jl @@ -481,6 +481,32 @@ end @test expm(A10) ≈ eA10 end +@testset "Additional matrix logarithm tests" for elty in (Float64, Complex{Float64}) + A11 = convert(Matrix{elty}, [3 2; -5 -3]) + @test expm(logm(A11)) ≈ A11 + + A12 = convert(Matrix{elty}, [1 -1; 1 -1]) + @test typeof(logm(A12)) == Array{Complex{Float64}, 2} + + A1 = convert(Matrix{elty}, [4 2 0; 1 4 1; 1 1 4]) + logmA1 = convert(Matrix{elty}, [1.329661349 0.5302876358 -0.06818951543; + 0.2310490602 1.295566591 0.2651438179; + 0.2310490602 0.1969543025 1.363756107]) + @test logm(A1) ≈ logmA1 + @test expm(logm(A1)) ≈ A1 + + A4 = convert(Matrix{elty}, [1/2 1/3 1/4 1/5+eps(); + 1/3 1/4 1/5 1/6; + 1/4 1/5 1/6 1/7; + 1/5 1/6 1/7 1/8]) + logmA4 = convert(Matrix{elty}, [-1.73297159 1.857349738 0.4462766564 0.2414170219; + 1.857349738 -5.335033737 2.994142974 0.5865285289; + 0.4462766564 2.994142974 -7.351095988 3.318413247; + 0.2414170219 0.5865285289 3.318413247 -5.444632124]) + @test logm(A4) ≈ logmA4 + @test expm(logm(A4)) ≈ A4 +end + @testset "issue #7181" begin A = [ 1 5 9 2 6 10 From cb11d806a97d23502a6db5e2e51d2b38b3364d05 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Wed, 19 Apr 2017 15:41:02 +0900 Subject: [PATCH 0623/1534] Add a callback to Base.require Packages such as `Requires.jl` need to be notified when a package is successfully loaded. Currently we have to resolve to a horrible hack that overrides `Base.require`. In a post 265 world this is no longer feasible. --- base/loading.jl | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/base/loading.jl b/base/loading.jl index 355ada1fac751..5601825f94b68 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -246,6 +246,11 @@ const DEBUG_LOADING = Ref(false) # to synchronize multiple tasks trying to import/using something const package_locks = Dict{Symbol,Condition}() +# to notify downstream consumers that a module was successfully loaded +# Callbacks take the form (mod::Symbol) -> nothing. +# WARNING: This is an experimental feature and might change later, without deprecation. +const package_callbacks = Any[] + # used to optionally track dependencies when requiring a module: const _concrete_dependencies = Any[] # these dependency versions are "set in stone", and the process should try to avoid invalidating them const _require_dependencies = Any[] # a list of (path, mtime) tuples that are the file dependencies of the module currently being precompiled @@ -378,6 +383,14 @@ all platforms, including those with case-insensitive filesystems like macOS and Windows. """ function require(mod::Symbol) + _require(mod::Symbol) + # After successfully loading notify downstream consumers + for callback in package_callbacks + invokelatest(callback, mod) + end +end + +function _require(mod::Symbol) # dependency-tracking is only used for one top-level include(path), # and is not applied recursively to imported modules: old_track_dependencies = _track_dependencies[] From c37ce31a00e0cd107d56375836110ab9989f6f3b Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Thu, 27 Apr 2017 16:24:30 +0900 Subject: [PATCH 0624/1534] add tests for package_callbacks --- test/compile.jl | 50 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/test/compile.jl b/test/compile.jl index 740cf5beca532..caf55a6c1592a 100644 --- a/test/compile.jl +++ b/test/compile.jl @@ -462,6 +462,56 @@ let dir = mktempdir() end end +let dir = mktempdir() + try + insert!(LOAD_PATH, 1, dir) + insert!(Base.LOAD_CACHE_PATH, 1, dir) + + loaded_modules = Channel{Symbol}(32) + callback = (mod::Symbol) -> put!(loaded_modules, mod) + push!(Base.package_callbacks, callback) + + Test1_module = :Teste4095a81 + Test2_module = :Teste4095a82 + Test3_module = :Teste4095a83 + + write(joinpath(dir, "$(Test1_module).jl"), + """ + module $(Test1_module) + __precompile__(true) + end + """) + + Base.compilecache("$(Test1_module)") + write(joinpath(dir, "$(Test2_module).jl"), + """ + module $(Test2_module) + __precompile__(true) + using $(Test1_module) + end + """) + Base.compilecache("$(Test2_module)") + @test !Base.isbindingresolved(Main, Test2_module) + Base.require(Test2_module) + @test Base.isbindingresolved(Main, Test2_module) + @test take!(loaded_modules) == Test1_module + @test take!(loaded_modules) == Test2_module + write(joinpath(dir, "$(Test3_module).jl"), + """ + module $(Test3_module) + using $(Test3_module) + end + """) + Base.require(Test3_module) + @test take!(loaded_modules) == Test3_module + finally + pop!(Base.package_callbacks) + splice!(Base.LOAD_CACHE_PATH, 1) + splice!(LOAD_PATH, 1) + rm(dir, recursive=true) + end +end + let module_name = string("a",randstring()) insert!(LOAD_PATH, 1, pwd()) file_name = string(module_name, ".jl") From 29f8959581613cde21014d0f8b4d40329cd2f5b1 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Fri, 28 Apr 2017 10:31:53 +0900 Subject: [PATCH 0625/1534] initial docs for Base.require --- doc/make.jl | 1 + doc/src/devdocs/require.md | 40 ++++++++++++++++++++++++++++++++++++++ doc/src/index.md | 1 + 3 files changed, 42 insertions(+) create mode 100644 doc/src/devdocs/require.md diff --git a/doc/make.jl b/doc/make.jl index 39f4b34b14d0d..dc931c98ca9bb 100644 --- a/doc/make.jl +++ b/doc/make.jl @@ -105,6 +105,7 @@ const PAGES = [ "devdocs/locks.md", "devdocs/offset-arrays.md", "devdocs/libgit2.md", + "devdocs/require.md", ], "Developing/debugging Julia's C code" => [ "devdocs/backtraces.md", diff --git a/doc/src/devdocs/require.md b/doc/src/devdocs/require.md new file mode 100644 index 0000000000000..65b72f6cf7db5 --- /dev/null +++ b/doc/src/devdocs/require.md @@ -0,0 +1,40 @@ +# Module loading + +`Base.require`[@ref] is responsible for loading modules and it also manages the +precompilation cache. It is the implementation of the `import` statement. + +## Experimental features +The features below are experimental and not part of the stable Julia API. +Before building upon them inform yourself about the current thinking and whether they might change soon. + +### Module loading callbacks + +It is possible to listen to the modules loaded by `Base.require`, by registering a callback. + +```julia +loaded_packages = Channel{Symbol}() +callback = (mod::Symbol) -> put!(loaded_packages, mod) +push!(Base.package_callbacks, callback) +``` + +Please note that the symbol given to the callback is a non-unique identifier and +it is the responsibility of the callback provider to walk the module chain to +determine the fully qualified name of the loaded binding. + +The callback below is an example of how to do that: + +```julia +# Get the fully-qualified name of a module. +function module_fqn(name::Symbol) + fqn = Symbol[name] + mod = getfield(Main, name) + parent = Base.module_parent(mod) + while parent !== Main + push!(fqn, Base.module_name(parent)) + parent = Base.module_parent(parent) + end + fqn = reverse!(fqn) + return join(fqn, '.') +end +``` + diff --git a/doc/src/index.md b/doc/src/index.md index deca430af0046..7434a4d78cfbc 100644 --- a/doc/src/index.md +++ b/doc/src/index.md @@ -89,6 +89,7 @@ * [Proper maintenance and care of multi-threading locks](@ref) * [Arrays with custom indices](@ref) * [Base.LibGit2](@ref) + * [Module loading](@ref) * Developing/debugging Julia's C code * [Reporting and analyzing crashes (segfaults)](@ref) * [gdb debugging tips](@ref) From 10140fa3d50a515afbeb24a8abfd330f1f896d11 Mon Sep 17 00:00:00 2001 From: Amit Murthy Date: Sun, 30 Apr 2017 22:46:58 +0530 Subject: [PATCH 0626/1534] Fix bug in parsing port number from host spec. Added tests. --- base/distributed/managers.jl | 2 +- test/distributed_exec.jl | 35 +++++++++++++++++++++-------------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/base/distributed/managers.jl b/base/distributed/managers.jl index 69672478c72dc..3bc643d720d8f 100644 --- a/base/distributed/managers.jl +++ b/base/distributed/managers.jl @@ -167,7 +167,7 @@ function launch_on_machine(manager::SSHManager, machine, cnt, params, launched, portopt = `` if length(machine_def) == 2 portstr = machine_def[2] - if !isinteger(portstr) || (p = parse(Int,portstr); p < 1 || p > 65535) + if !all(isdigit, portstr) || (p = parse(Int,portstr); p < 1 || p > 65535) msg = "invalid machine definition format string: invalid port format \"$machine_def\"" throw(ArgumentError(msg)) end diff --git a/test/distributed_exec.jl b/test/distributed_exec.jl index 92156132ad875..9774fe094df06 100644 --- a/test/distributed_exec.jl +++ b/test/distributed_exec.jl @@ -887,7 +887,6 @@ wp = CachingPool(workers()) clear!(wp) @test length(wp.map_obj2ref) == 0 - # The below block of tests are usually run only on local development systems, since: # - tests which print errors # - addprocs tests are memory intensive @@ -950,7 +949,10 @@ if is_unix() # aka have ssh end print("\n\nTesting SSHManager. A minimum of 4GB of RAM is recommended.\n") - print("Please ensure sshd is running locally with passwordless login enabled.\n") + print("Please ensure: \n") + print("1) sshd is running locally with passwordless login enabled.\n") + print("2) Env variable USER is defined and is the ssh user.\n") + print("3) Port 9300 is not in use.\n") sshflags = `-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=ERROR ` #Issue #9951 @@ -963,32 +965,37 @@ if is_unix() # aka have ssh end print("\nTesting SSH addprocs with $(length(hosts)) workers...\n") - new_pids = remotecall_fetch(1, hosts, sshflags) do h, sf - addprocs(h; exeflags=cov_in_exeflags, sshflags=sf) - end + new_pids = addprocs(hosts; exeflags=cov_in_exeflags, sshflags=sshflags) @test length(new_pids) == length(hosts) test_n_remove_pids(new_pids) print("\nMixed ssh addprocs with :auto\n") - new_pids = sort(remotecall_fetch(1, ["localhost", ("127.0.0.1", :auto), "localhost"], sshflags) do h, sf - addprocs(h; exeflags=cov_in_exeflags, sshflags=sf) - end) + new_pids = addprocs(["localhost", ("127.0.0.1", :auto), "localhost"]; sshflags=sshflags) @test length(new_pids) == (2 + Sys.CPU_CORES) test_n_remove_pids(new_pids) print("\nMixed ssh addprocs with numeric counts\n") - new_pids = sort(remotecall_fetch(1, [("localhost", 2), ("127.0.0.1", 2), "localhost"], sshflags) do h, sf - addprocs(h; exeflags=cov_in_exeflags, sshflags=sf) - end) + new_pids = addprocs([("localhost", 2), ("127.0.0.1", 2), "localhost"]; exeflags=cov_in_exeflags, sshflags=sshflags) @test length(new_pids) == 5 test_n_remove_pids(new_pids) print("\nssh addprocs with tunnel\n") - new_pids = sort(remotecall_fetch(1, [("localhost", num_workers)], sshflags) do h, sf - addprocs(h; tunnel=true, sshflags=sf, exeflags=cov_in_exeflags) - end) + new_pids = addprocs([("localhost", num_workers)]; tunnel=true, exeflags=cov_in_exeflags, sshflags=sshflags) @test length(new_pids) == num_workers test_n_remove_pids(new_pids) + + print("\nAll supported formats for hostname\n") + h1 = "localhost" + user = ENV["USER"] + h2 = "$user@$h1" + h3 = "$h2:22" + h4 = "$h3 $(string(getipaddr()))" + h5 = "$h4:9300" + + new_pids = addprocs([h1, h2, h3, h4, h5]; exeflags=cov_in_exeflags, sshflags=sshflags) + @test length(new_pids) == 5 + test_n_remove_pids(new_pids) + end # unix-only end # full-test From 37c7fe069394477d9ce813da73d60f3a3b394bd5 Mon Sep 17 00:00:00 2001 From: Amit Murthy Date: Sun, 30 Apr 2017 22:59:07 +0530 Subject: [PATCH 0627/1534] fix wrong error message with ssh addprocs tunnel option --- base/distributed/managers.jl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/base/distributed/managers.jl b/base/distributed/managers.jl index 3bc643d720d8f..7591f51292cf2 100644 --- a/base/distributed/managers.jl +++ b/base/distributed/managers.jl @@ -259,8 +259,7 @@ Returns a port number `localport` such that `localhost:localport` connects to `h """ function ssh_tunnel(user, host, bind_addr, port, sshflags) port = Int(port) - cnt = 100 - localport = next_tunnel_port() + cnt = ntries = 100 # if we cannot do port forwarding, bail immediately # the connection is forwarded to `port` on the remote server over the local port `localport` # the -f option backgrounds the ssh session @@ -269,15 +268,16 @@ function ssh_tunnel(user, host, bind_addr, port, sshflags) # If no connections are made within 60 seconds, ssh will exit and an error will be printed on the # process that launched the remote process. ssh = `ssh -T -a -x -o ExitOnForwardFailure=yes` - while !success(detach(`$ssh -f $sshflags $user@$host -L $localport:$bind_addr:$port sleep 60`)) && cnt > 0 + while cnt > 0 localport = next_tunnel_port() + if success(detach(`$ssh -f $sshflags $user@$host -L $localport:$bind_addr:$port sleep 60`)) + return localport + end cnt -= 1 end - if cnt == 0 - throw(ErrorException( - "unable to create SSH tunnel after $cnt tries. No free port?")) - end - return localport + + throw(ErrorException( + string("unable to create SSH tunnel after ", ntries, " tries. No free port?"))) end From 057fa2aa9f9a3d6e41e14ab08e70fa995eff3122 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 27 Apr 2017 19:09:25 -0400 Subject: [PATCH 0628/1534] small optimization to `f(...; kw...)` when `kw` is empty --- base/essentials.jl | 20 +++++++ base/task.jl | 2 +- base/test.jl | 3 + src/julia-syntax.scm | 135 ++++++++++++++++++++++++------------------- test/test.jl | 2 + 5 files changed, 100 insertions(+), 62 deletions(-) diff --git a/base/essentials.jl b/base/essentials.jl index 145ea6bb50486..c5322273ba4a5 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -336,6 +336,26 @@ function vector_any(xs::ANY...) a end +function as_kwargs(xs::Union{AbstractArray,Associative}) + n = length(xs) + to = Vector{Any}(n*2) + i = 1 + for (k, v) in xs + to[i] = k::Symbol + to[i+1] = v + i += 2 + end + return to +end + +function as_kwargs(xs) + to = Vector{Any}(0) + for (k, v) in xs + ccall(:jl_array_ptr_1d_push2, Void, (Any, Any, Any), to, k::Symbol, v) + end + return to +end + isempty(itr) = done(itr, start(itr)) """ diff --git a/base/task.jl b/base/task.jl index c2172c4ce7d53..5639bb444a739 100644 --- a/base/task.jl +++ b/base/task.jl @@ -209,7 +209,7 @@ function task_done_hook(t::Task) if isa(t.donenotify, Condition) && !isempty(t.donenotify.waitq) handled = true - notify(t.donenotify, result, error=err) + notify(t.donenotify, result, true, err) end # Execute any other hooks registered in the TLS diff --git a/base/test.jl b/base/test.jl index e7c6e5afe75ce..a64c9679b0264 100644 --- a/base/test.jl +++ b/base/test.jl @@ -848,6 +848,9 @@ function testset_beginend(args, tests) # action (such as reporting the results) quote ts = $(testsettype)($desc; $options...) + # this empty loop is here to force the block to be compiled, + # which is needed for backtrace scrubbing to work correctly. + while false; end push_testset(ts) try $(esc(tests)) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 50a0a67e9a1de..842327fe740d7 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -493,7 +493,7 @@ (= ,ii (call (top -) (call (top *) ,i 2) 1)) (= ,elt (call (core arrayref) ,kw ,ii)) ,(foldl (lambda (kvf else) - (let* ((k (car kvf)) + (let* ((k (car kvf)) (rval0 `(call (core arrayref) ,kw (call (top +) ,ii 1))) ;; note: if the "declared" type of a KW arg @@ -536,9 +536,9 @@ (list `(... ,(arg-name (car vararg)))))) ;; otherwise add to rest keywords `(foreigncall 'jl_array_ptr_1d_push (core Void) (call (core svec) Any Any) - ,rkw 0 (tuple ,elt - (call (core arrayref) ,kw - (call (top +) ,ii 1))) 0)) + ,rkw 0 (tuple ,elt + (call (core arrayref) ,kw + (call (top +) ,ii 1))) 0)) (map list vars vals flags)))) ;; set keywords that weren't present to their default values ,@(apply append @@ -1437,64 +1437,77 @@ (reverse a)))))) ;; lower function call containing keyword arguments -(define (lower-kw-call fexpr kw pa) - (let ((container (make-ssavalue))) - (let loop ((kw kw) - (initial-kw '()) ;; keyword args before any splats - (stmts '()) - (has-kw #f)) ;; whether there are definitely >0 kwargs - (if (null? kw) - (let ((f (if (sym-ref? fexpr) fexpr (make-ssavalue)))) +(define (lower-kw-call fexpr kw0 pa) + + (define (kwcall-unless-empty f pa kw-container-test kw-container) + (let* ((expr_stmts (remove-argument-side-effects `(call ,f ,@pa))) + (pa (cddr (car expr_stmts))) + (stmts (cdr expr_stmts))) + `(block + ,@stmts + (if (call (top isempty) ,kw-container-test) + (call ,f ,@pa) + (call (call (core kwfunc) ,f) ,kw-container ,f ,@pa))))) + + (let ((f (if (sym-ref? fexpr) fexpr (make-ssavalue)))) + `(block + ,@(if (eq? f fexpr) '() `((= ,f, fexpr))) + ,(if ;; optimize splatting one existing container, `f(...; kw...)` + (and (length= kw0 1) (vararg? (car kw0))) + (let* ((container (cadr (car kw0))) + (expr_stmts (remove-argument-side-effects `(call _ ,container))) + (container (caddr (car expr_stmts))) + (stmts (cdr expr_stmts))) `(block - ,@(if (eq? f fexpr) '() `((= ,f, fexpr))) - ,(if (null? stmts) - `(call (call (core kwfunc) ,f) (call (top vector_any) ,@(reverse initial-kw)) ,f ,@pa) - `(block - (= ,container (call (top vector_any) ,@(reverse initial-kw))) - ,@(reverse stmts) - ,(if has-kw - `(call (call (core kwfunc) ,f) ,container ,f ,@pa) - (let* ((expr_stmts (remove-argument-side-effects `(call ,f ,@pa))) - (pa (cddr (car expr_stmts))) - (stmts (cdr expr_stmts))) - `(block - ,@stmts - (if (call (top isempty) ,container) - (call ,f ,@pa) - (call (call (core kwfunc) ,f) ,container ,f ,@pa))))))))) - (let ((arg (car kw))) - (cond ((and (pair? arg) (eq? (car arg) 'parameters)) - (error "more than one semicolon in argument list")) - ((kwarg? arg) - (if (not (symbol? (cadr arg))) - (error (string "keyword argument is not a symbol: \"" - (deparse (cadr arg)) "\""))) - (if (vararg? (caddr arg)) - (error "splicing with \"...\" cannot be used for a keyword argument value")) - (if (null? stmts) - (loop (cdr kw) (list* (caddr arg) `(quote ,(cadr arg)) initial-kw) stmts #t) - (loop (cdr kw) initial-kw - (cons `(foreigncall 'jl_array_ptr_1d_push2 (core Void) (call (core svec) Any Any Any) - ,container 0 - (|::| (quote ,(cadr arg)) (core Symbol)) 0 - ,(caddr arg) 0) - stmts) - #t))) - (else - (loop (cdr kw) initial-kw - (cons (let* ((k (make-ssavalue)) - (v (make-ssavalue)) - (push-expr `(foreigncall 'jl_array_ptr_1d_push2 (core Void) (call (core svec) Any Any Any) - ,container 0 - (|::| ,k (core Symbol)) 0 - ,v 0))) - (if (vararg? arg) - `(for (= (tuple ,k ,v) ,(cadr arg)) - ,push-expr) - `(block (= (tuple ,k ,v) ,arg) - ,push-expr))) - stmts) - (or has-kw (not (vararg? arg))))))))))) + ,@stmts + ,(kwcall-unless-empty f pa container `(call (top as_kwargs) ,container)))) + (let ((container (make-ssavalue))) + (let loop ((kw kw0) + (initial-kw '()) ;; keyword args before any splats + (stmts '()) + (has-kw #f)) ;; whether there are definitely >0 kwargs + (if (null? kw) + (if (null? stmts) + `(call (call (core kwfunc) ,f) (call (top vector_any) ,@(reverse initial-kw)) ,f ,@pa) + `(block + (= ,container (call (top vector_any) ,@(reverse initial-kw))) + ,@(reverse stmts) + ,(if has-kw + `(call (call (core kwfunc) ,f) ,container ,f ,@pa) + (kwcall-unless-empty f pa container container)))) + (let ((arg (car kw))) + (cond ((and (pair? arg) (eq? (car arg) 'parameters)) + (error "more than one semicolon in argument list")) + ((kwarg? arg) + (if (not (symbol? (cadr arg))) + (error (string "keyword argument is not a symbol: \"" + (deparse (cadr arg)) "\""))) + (if (vararg? (caddr arg)) + (error "splicing with \"...\" cannot be used for a keyword argument value")) + (if (null? stmts) + (loop (cdr kw) (list* (caddr arg) `(quote ,(cadr arg)) initial-kw) stmts #t) + (loop (cdr kw) initial-kw + (cons `(foreigncall 'jl_array_ptr_1d_push2 (core Void) (call (core svec) Any Any Any) + ,container 0 + (|::| (quote ,(cadr arg)) (core Symbol)) 0 + ,(caddr arg) 0) + stmts) + #t))) + (else + (loop (cdr kw) initial-kw + (cons (let* ((k (make-ssavalue)) + (v (make-ssavalue)) + (push-expr `(foreigncall 'jl_array_ptr_1d_push2 (core Void) (call (core svec) Any Any Any) + ,container 0 + (|::| ,k (core Symbol)) 0 + ,v 0))) + (if (vararg? arg) + `(for (= (tuple ,k ,v) ,(cadr arg)) + ,push-expr) + `(block (= (tuple ,k ,v) ,arg) + ,push-expr))) + stmts) + (or has-kw (not (vararg? arg)))))))))))))) ;; convert e.g. A'*B to Ac_mul_B(A,B) (define (expand-transposed-op e ops) diff --git a/test/test.jl b/test/test.jl index 3fbc5f9a96ed3..01898c234e93c 100644 --- a/test/test.jl +++ b/test/test.jl @@ -416,6 +416,8 @@ end io = IOBuffer() @test (print(io, Base.Test.Error(:test_error, "woot", 5, backtrace())); 1) == 1 str = String(take!(io)) +# NOTE: This test depends on the code generated by @testset getting compiled, +# to get good backtraces. If it fails, check the implementation of `testset_beginend`. @test contains(str, "test.jl") @test !contains(str, "boot.jl") From dfc60631ce13b2ecda3069b7f08310e378509594 Mon Sep 17 00:00:00 2001 From: Amit Murthy Date: Sun, 30 Apr 2017 23:25:20 +0530 Subject: [PATCH 0629/1534] SSHManager now supports keyword arg exename as a Cmd type --- base/distributed/cluster.jl | 2 +- test/distributed_exec.jl | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/base/distributed/cluster.jl b/base/distributed/cluster.jl index 03e9173d5c5a8..f420bb502c0f8 100644 --- a/base/distributed/cluster.jl +++ b/base/distributed/cluster.jl @@ -10,7 +10,7 @@ mutable struct WorkerConfig # Used when launching additional workers at a host count::Nullable{Union{Int, Symbol}} - exename::Nullable{AbstractString} + exename::Nullable{Union{AbstractString, Cmd}} exeflags::Nullable{Cmd} # External cluster managers can use this to store information at a per-worker level diff --git a/test/distributed_exec.jl b/test/distributed_exec.jl index 9774fe094df06..23da6dfb88924 100644 --- a/test/distributed_exec.jl +++ b/test/distributed_exec.jl @@ -996,6 +996,18 @@ if is_unix() # aka have ssh @test length(new_pids) == 5 test_n_remove_pids(new_pids) + print("\nkeyword arg exename\n") + + for exename in [`$(joinpath(JULIA_HOME, Base.julia_exename()))`, "$(joinpath(JULIA_HOME, Base.julia_exename()))"] + for addp_func in [()->addprocs(["localhost"]; exename=exename, exeflags=cov_in_exeflags, sshflags=sshflags), + ()->addprocs(1; exename=exename, exeflags=cov_in_exeflags)] + + new_pids = addp_func() + @test length(new_pids) == 1 + test_n_remove_pids(new_pids) + end + end + end # unix-only end # full-test From 1732bb34c5569dab75d3846ae96e11fda288bcd2 Mon Sep 17 00:00:00 2001 From: Amit Murthy Date: Mon, 1 May 2017 09:28:22 +0530 Subject: [PATCH 0630/1534] Fix bug in nprocs()/nworkers()/procs() in non :all_to_all topology case. (#21651) * Fix bug in nprocs()/nworkers()/procs() in non :all_to_all topology case. --- base/distributed/cluster.jl | 24 ++++++++++++++++++------ test/distributed_exec.jl | 26 +++++++++++++------------- 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/base/distributed/cluster.jl b/base/distributed/cluster.jl index f420bb502c0f8..a2ca068a7161e 100644 --- a/base/distributed/cluster.jl +++ b/base/distributed/cluster.jl @@ -652,13 +652,18 @@ myid() = LPROC.id Get the number of available processes. """ function nprocs() - n = length(PGRP.workers) - for jw in PGRP.workers - if !isa(jw, LocalProcess) && (jw.state != W_CONNECTED) - n = n - 1 + if myid() == 1 || PGRP.topology == :all_to_all + n = length(PGRP.workers) + # filter out workers in the process of being setup/shutdown. + for jw in PGRP.workers + if !isa(jw, LocalProcess) && (jw.state != W_CONNECTED) + n = n - 1 + end end + return n + else + return length(PGRP.workers) end - n end """ @@ -677,7 +682,14 @@ end Returns a list of all process identifiers. """ -procs() = Int[x.id for x in PGRP.workers if isa(x, LocalProcess) || (x.state == W_CONNECTED)] +function procs() + if myid() == 1 || PGRP.topology == :all_to_all + # filter out workers in the process of being setup/shutdown. + return Int[x.id for x in PGRP.workers if isa(x, LocalProcess) || (x.state == W_CONNECTED)] + else + return Int[x.id for x in PGRP.workers] + end +end """ procs(pid::Integer) diff --git a/test/distributed_exec.jl b/test/distributed_exec.jl index 23da6dfb88924..7742059ea3f73 100644 --- a/test/distributed_exec.jl +++ b/test/distributed_exec.jl @@ -896,19 +896,6 @@ clear!(wp) DoFullTest = Bool(parse(Int,(get(ENV, "JULIA_TESTFULL", "0")))) if DoFullTest - # Topology tests need to run externally since a given cluster at any - # time can only support a single topology and the current session - # is already running in parallel under the default topology. - script = joinpath(dirname(@__FILE__), "topology.jl") - cmd = `$(Base.julia_cmd()) $script` - - (strm, proc) = open(pipeline(cmd, stderr=STDERR)) - wait(proc) - if !success(proc) && ccall(:jl_running_on_valgrind,Cint,()) == 0 - println(readstring(strm)) - error("Topology tests failed : $cmd") - end - println("Testing exception printing on remote worker from a `remote_do` call") println("Please ensure the remote error and backtrace is displayed on screen") @@ -1572,3 +1559,16 @@ catch ex @test contains(ex.captured.ex.exceptions[1].ex.msg, "BoundsError") @test ex.captured.ex.exceptions[2].ex == UndefVarError(:DontExistOn1) end + +# Topology tests need to run externally since a given cluster at any +# time can only support a single topology and the current session +# is already running in parallel under the default topology. +script = joinpath(dirname(@__FILE__), "topology.jl") +cmd = `$(Base.julia_cmd()) $cov_in_exeflags $script` + +(strm, proc) = open(pipeline(cmd, stderr=STDERR)) +wait(proc) +if !success(proc) && ccall(:jl_running_on_valgrind,Cint,()) == 0 + println(readstring(strm)) + error("Topology tests failed : $cmd") +end From e1e7442011a0ef32b6cfbd71b3d39b61dc9f4f11 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 28 Apr 2017 18:12:25 -0400 Subject: [PATCH 0631/1534] more performance improvements to `Distributed` --- base/channels.jl | 15 +++++++++++---- base/distributed/cluster.jl | 24 +++++++++++++++++++++--- base/distributed/remotecall.jl | 4 ++-- base/distributed/workerpool.jl | 2 +- 4 files changed, 35 insertions(+), 10 deletions(-) diff --git a/base/channels.jl b/base/channels.jl index 9291dd324622b..646917b603b3c 100644 --- a/base/channels.jl +++ b/base/channels.jl @@ -27,9 +27,9 @@ mutable struct Channel{T} <: AbstractChannel sz_max::Int # maximum size of channel # Used when sz_max == 0, i.e., an unbuffered channel. + waiters::Int takers::Vector{Task} putters::Vector{Task} - waiters::Int function Channel{T}(sz::Float64) where T if sz == Inf @@ -42,7 +42,12 @@ mutable struct Channel{T} <: AbstractChannel if sz < 0 throw(ArgumentError("Channel size must be either 0, a positive integer or Inf")) end - new(Condition(), Condition(), :open, Nullable{Exception}(), Vector{T}(0), sz, Vector{Task}(0), Vector{Task}(0), 0) + ch = new(Condition(), Condition(), :open, Nullable{Exception}(), Vector{T}(0), sz, 0) + if sz == 0 + ch.takers = Vector{Task}(0) + ch.putters = Vector{Task}(0) + end + return ch end # deprecated empty constructor @@ -376,8 +381,10 @@ function notify_error(c::Channel, err) notify_error(c.cond_put, err) # release tasks on a `wait()/yieldto()` call (on unbuffered channels) - waiters = filter!(t->(t.state == :runnable), vcat(c.takers, c.putters)) - foreach(t->schedule(t, err; error=true), waiters) + if !isbuffered(c) + waiters = filter!(t->(t.state == :runnable), vcat(c.takers, c.putters)) + foreach(t->schedule(t, err; error=true), waiters) + end end notify_error(c::Channel) = notify_error(c, get(c.excp)) diff --git a/base/distributed/cluster.jl b/base/distributed/cluster.jl index a2ca068a7161e..77bc037c126ba 100644 --- a/base/distributed/cluster.jl +++ b/base/distributed/cluster.jl @@ -691,6 +691,23 @@ function procs() end end +function id_in_procs(id) # faster version of `id in procs()` + if myid() == 1 || PGRP.topology == :all_to_all + for x in PGRP.workers + if (x.id::Int) == id && (isa(x, LocalProcess) || (x::Worker).state == W_CONNECTED) + return true + end + end + else + for x in PGRP.workers + if (x.id::Int) == id + return true + end + end + end + return false +end + """ procs(pid::Integer) @@ -806,17 +823,18 @@ mutable struct ProcessExitedException <: Exception end worker_from_id(i) = worker_from_id(PGRP, i) function worker_from_id(pg::ProcessGroup, i) - if in(i, map_del_wrkr) + if !isempty(map_del_wrkr) && in(i, map_del_wrkr) throw(ProcessExitedException()) end - if !haskey(map_pid_wrkr,i) + w = get(map_pid_wrkr, i, nothing) + if w === nothing if myid() == 1 error("no process with id $i exists") end w = Worker(i) map_pid_wrkr[i] = w else - w = map_pid_wrkr[i] + w = w::Union{Worker, LocalProcess} end w end diff --git a/base/distributed/remotecall.jl b/base/distributed/remotecall.jl index e03f1d19a8d9d..ff1de61be8222 100644 --- a/base/distributed/remotecall.jl +++ b/base/distributed/remotecall.jl @@ -235,7 +235,7 @@ end function send_del_client(rr) if rr.where == myid() del_client(rr) - elseif rr.where in procs() # process only if a valid worker + elseif id_in_procs(rr.where) # process only if a valid worker w = worker_from_id(rr.where) push!(w.del_msgs, (remoteref_id(rr), myid())) w.gcflag = true @@ -260,7 +260,7 @@ end function send_add_client(rr::AbstractRemoteRef, i) if rr.where == myid() add_client(remoteref_id(rr), i) - elseif (i != rr.where) && (rr.where in procs()) + elseif (i != rr.where) && id_in_procs(rr.where) # don't need to send add_client if the message is already going # to the processor that owns the remote ref. it will add_client # itself inside deserialize(). diff --git a/base/distributed/workerpool.jl b/base/distributed/workerpool.jl index ba43ef788bf67..72a4d52ab5f4b 100644 --- a/base/distributed/workerpool.jl +++ b/base/distributed/workerpool.jl @@ -97,7 +97,7 @@ function wp_local_take!(pool::AbstractWorkerPool) end worker = take!(pool.channel) - if worker in procs() + if id_in_procs(worker) break else delete!(pool.workers, worker) # Remove invalid worker from pool From 91ec5bd739c21697c977b6b4e3d4dd77c49bc893 Mon Sep 17 00:00:00 2001 From: Mus M Date: Mon, 1 May 2017 02:43:53 -0400 Subject: [PATCH 0632/1534] Use where syntax in types.md for show method --- doc/src/manual/types.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/src/manual/types.md b/doc/src/manual/types.md index dda0cb71bd540..d1fbf2c5dea15 100644 --- a/doc/src/manual/types.md +++ b/doc/src/manual/types.md @@ -1198,7 +1198,7 @@ format for displaying an object by overloading a three-argument form of `show` t `text/plain` MIME type as its second argument (see [Multimedia I/O](@ref)), for example: ```jldoctest polartype -julia> Base.show{T}(io::IO, ::MIME"text/plain", z::Polar{T}) = +julia> Base.show(io::IO, ::MIME"text/plain", z::Polar{T}) where{T} = print(io, "Polar{$T} complex number:\n ", z) ``` @@ -1225,7 +1225,7 @@ Moreover, you can also define `show` methods for other MIME types in order to en we can define formatted HTML display of `Polar` objects, with superscripts and italics, via: ```jldoctest polartype -julia> Base.show{T}(io::IO, ::MIME"text/html", z::Polar{T}) = +julia> Base.show(io::IO, ::MIME"text/html", z::Polar{T}) where {T} = println(io, "Polar{$T} complex number: ", z.r, " e", z.Θ, " i") ``` From f11dc1588efcf215f1d988ef28d62652eda2ddb1 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 28 Apr 2017 16:01:12 -0400 Subject: [PATCH 0633/1534] optimize field access when field types don't depend on parameters also computes layout and shares it for all instantiations for such types --- src/codegen.cpp | 35 +++++++++++++++++++---------------- src/datatype.c | 45 ++++++++++++++++++++++++++++++++------------- src/interpreter.c | 5 +---- 3 files changed, 52 insertions(+), 33 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index e55424d47170e..cefa88a579fc0 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -2455,8 +2455,8 @@ static jl_cgval_t emit_getfield(jl_value_t *expr, jl_sym_t *name, jl_codectx_t * JL_GC_PUSH1(&sty); if (jl_is_type_type((jl_value_t*)sty) && jl_is_leaf_type(jl_tparam0(sty))) sty = (jl_datatype_t*)jl_typeof(jl_tparam0(sty)); - if (jl_is_structtype(sty) && sty != jl_module_type && sty->uid != 0 && - jl_is_leaf_type((jl_value_t*)sty)) { + sty = (jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)sty); + if (jl_is_structtype(sty) && sty != jl_module_type && sty->layout) { unsigned idx = jl_field_index(sty, name, 0); if (idx != (unsigned)-1) { jl_cgval_t strct = emit_expr(expr, ctx); @@ -2971,8 +2971,7 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, JL_GC_POP(); return true; } - jl_datatype_t *stt = (jl_datatype_t*)expr_type(args[1], ctx); - jl_value_t *fldt = expr_type(args[2], ctx); + jl_value_t *fldt = expr_type(args[2], ctx); // VA tuple if (ctx->vaStack && slot_eq(args[1], ctx->vaSlot)) { @@ -2989,22 +2988,25 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, return true; } - if (fldt == (jl_value_t*)jl_long_type && jl_is_leaf_type((jl_value_t*)stt)) { - if ((jl_is_structtype(stt) || jl_is_tuple_type(stt)) && !jl_subtype((jl_value_t*)jl_module_type, (jl_value_t*)stt)) { - size_t nfields = jl_datatype_nfields(stt); + jl_datatype_t *stt = (jl_datatype_t*)expr_type(args[1], ctx); + jl_value_t *utt = jl_unwrap_unionall((jl_value_t*)stt); + + if (fldt == (jl_value_t*)jl_long_type && jl_is_datatype(utt) && ((jl_datatype_t*)utt)->layout) { + if ((jl_is_structtype(utt) || jl_is_tuple_type(utt)) && !jl_subtype((jl_value_t*)jl_module_type, (jl_value_t*)stt)) { + size_t nfields = jl_datatype_nfields(utt); jl_cgval_t strct = emit_expr(args[1], ctx); // integer index size_t idx; if (jl_is_long(args[2]) && (idx=jl_unbox_long(args[2])-1) < nfields) { // known index - *ret = emit_getfield_knownidx(strct, idx, stt, ctx); + *ret = emit_getfield_knownidx(strct, idx, (jl_datatype_t*)utt, ctx); JL_GC_POP(); return true; } else { // unknown index Value *vidx = emit_unbox(T_size, emit_expr(args[2], ctx), (jl_value_t*)jl_long_type); - if (emit_getfield_unknownidx(ret, strct, vidx, stt, ctx)) { + if (emit_getfield_unknownidx(ret, strct, vidx, (jl_datatype_t*)utt, ctx)) { if (ret->typ == (jl_value_t*)jl_any_type) // improve the type, if known from the expr ret->typ = expr_type(expr, ctx); JL_GC_POP(); @@ -3012,8 +3014,8 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, } } } - } else { - jl_value_t *utt = jl_unwrap_unionall((jl_value_t*)stt); + } + else { if (jl_is_tuple_type(utt) && is_tupletype_homogeneous(((jl_datatype_t*)utt)->types, true)) { // For tuples, we can emit code even if we don't know the exact // type (e.g. because we don't know the length). This is possible @@ -3045,10 +3047,11 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, else if (f==jl_builtin_setfield && nargs==3) { jl_datatype_t *sty = (jl_datatype_t*)expr_type(args[1], ctx); rt1 = (jl_value_t*)sty; - if (jl_is_structtype(sty) && sty != jl_module_type) { + jl_datatype_t *uty = (jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)sty); + if (jl_is_structtype(uty) && uty != jl_module_type) { size_t idx = (size_t)-1; if (jl_is_quotenode(args[2]) && jl_is_symbol(jl_fieldref(args[2],0))) { - idx = jl_field_index(sty, (jl_sym_t*)jl_fieldref(args[2],0), 0); + idx = jl_field_index(uty, (jl_sym_t*)jl_fieldref(args[2],0), 0); } else if (jl_is_long(args[2]) || (jl_is_quotenode(args[2]) && jl_is_long(jl_fieldref(args[2],0)))) { ssize_t i; @@ -3056,14 +3059,14 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, i = jl_unbox_long(args[2]); else i = jl_unbox_long(jl_fieldref(args[2],0)); - if (i > 0 && i <= jl_datatype_nfields(sty)) + if (i > 0 && i <= jl_datatype_nfields(uty)) idx = i-1; } if (idx != (size_t)-1) { - jl_value_t *ft = jl_svecref(sty->types, idx); + jl_value_t *ft = jl_svecref(uty->types, idx); jl_value_t *rhst = expr_type(args[3], ctx); rt2 = rhst; - if (jl_is_leaf_type((jl_value_t*)sty) && jl_subtype(rhst, ft)) { + if (uty->layout && jl_subtype(rhst, ft)) { // TODO: attempt better codegen for approximate types jl_cgval_t strct = emit_expr(args[1], ctx); // emit lhs *ret = emit_expr(args[3], ctx); diff --git a/src/datatype.c b/src/datatype.c index 1d8005fe462e7..6bf0388894004 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -227,11 +227,37 @@ void jl_compute_field_offsets(jl_datatype_t *st) size_t sz = 0, alignm = 1; int homogeneous = 1; jl_value_t *lastty = NULL; - uint64_t max_offset = (((uint64_t)1) << 32) - 1; uint64_t max_size = max_offset >> 1; + if (st->name->wrapper) { + // If layout doesn't depend on type parameters, it's stored in st->name->wrapper + // and reused by all subtypes. + jl_datatype_t *w = (jl_datatype_t*)jl_unwrap_unionall(st->name->wrapper); + if (st != w && // this check allows us to re-compute layout for some types during init + w->layout) { + st->layout = w->layout; + st->size = w->size; + return; + } + } + if (st->types == NULL) + return; uint32_t nfields = jl_svec_len(st->types); + if (nfields == 0 && st != jl_sym_type && st != jl_simplevector_type) { + // reuse the same layout for all singletons + static const jl_datatype_layout_t singleton_layout = {0, 1, 0, 0, 0}; + st->layout = &singleton_layout; + return; + } + if (!jl_is_leaf_type((jl_value_t*)st)) { + // compute layout whenever field types have no free variables + for (size_t i = 0; i < nfields; i++) { + if (jl_has_free_typevars(jl_field_type(st, i))) + return; + } + } + size_t descsz = nfields * sizeof(jl_fielddesc32_t); jl_fielddesc32_t *desc; if (descsz < jl_page_size) @@ -372,18 +398,11 @@ JL_DLLEXPORT jl_datatype_t *jl_new_datatype(jl_sym_t *name, jl_datatype_t *super } jl_precompute_memoized_dt(t); - if (abstract || jl_svec_len(parameters) > 0) { - t->uid = 0; - } - else { - t->uid = jl_assign_type_uid(); - if (t->types != NULL && t->isleaftype) { - static const jl_datatype_layout_t singleton_layout = {0, 1, 0, 0, 0}; - if (fnames == jl_emptysvec) - t->layout = &singleton_layout; - else - jl_compute_field_offsets(t); - } + t->uid = 0; + if (!abstract) { + if (jl_svec_len(parameters) == 0) + t->uid = jl_assign_type_uid(); + jl_compute_field_offsets(t); } JL_GC_POP(); return t; diff --git a/src/interpreter.c b/src/interpreter.c index a4743edcec4b4..4e78fea57383a 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -470,10 +470,7 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s) b->value = temp; jl_rethrow(); } - if (dt->name->names == jl_emptysvec) - dt->layout = jl_void_type->layout; // reuse the same layout for all singletons - else if (jl_is_leaf_type((jl_value_t*)dt)) - jl_compute_field_offsets(dt); + jl_compute_field_offsets(dt); if (para == (jl_value_t*)jl_emptysvec && jl_is_datatype_make_singleton(dt)) { dt->instance = jl_gc_alloc(ptls, 0, dt); jl_gc_wb(dt, dt->instance); From 0be9996cf4f438c7d0247499c9479abb61c332f7 Mon Sep 17 00:00:00 2001 From: Nathan Smith Date: Mon, 1 May 2017 10:35:18 -0400 Subject: [PATCH 0634/1534] add documentation for Function type (#21649) --- base/docs/basedocs.jl | 18 ++++++++++++++++++ doc/src/stdlib/base.md | 1 + 2 files changed, 19 insertions(+) diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index 5938cd2d18205..9134bbc3925f7 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -693,4 +693,22 @@ run(pipeline(`cat test.txt`, DevNull)) """ DevNull +""" + Function + +Abstract type of all functions. + +```jldoctest +julia> isa(+, Function) +true + +julia> typeof(sin) +Base.#sin + +julia> ans <: Function +true +``` +""" +Function + end diff --git a/doc/src/stdlib/base.md b/doc/src/stdlib/base.md index c19859b07cf98..9af89439bcc8f 100644 --- a/doc/src/stdlib/base.md +++ b/doc/src/stdlib/base.md @@ -118,6 +118,7 @@ Base.instances ## Generic Functions ```@docs +Core.Function Base.method_exists Core.applicable Core.invoke From c984203b3c8171b2ff6e6b3a6296952490729c09 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Mon, 1 May 2017 11:46:44 -0400 Subject: [PATCH 0635/1534] Add libgit2 patch to allow NULL refspec in git_remote_push Ref libgit2/libgit2#4225 Fix #21639 --- deps/libgit2.mk | 8 ++++++- deps/patches/libgit2-remote-push-NULL.patch | 26 +++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 deps/patches/libgit2-remote-push-NULL.patch diff --git a/deps/libgit2.mk b/deps/libgit2.mk index fe6d5e18cd15c..129fbe610fa17 100644 --- a/deps/libgit2.mk +++ b/deps/libgit2.mk @@ -99,6 +99,11 @@ $(LIBGIT2_SRC_PATH)/libgit2-free-config.patch-applied: $(LIBGIT2_SRC_PATH)/sourc patch -p1 -f < $(SRCDIR)/patches/libgit2-free-config.patch echo 1 > $@ +$(LIBGIT2_SRC_PATH)/libgit2-remote-push-NULL.patch-applied: $(LIBGIT2_SRC_PATH)/source-extracted | $(LIBGIT2_SRC_PATH)/libgit2-free-config.patch-applied + cd $(LIBGIT2_SRC_PATH) && \ + patch -p1 -f < $(SRCDIR)/patches/libgit2-remote-push-NULL.patch + echo 1 > $@ + $(build_datarootdir)/julia/cert.pem: $(CERTFILE) mkdir -p $(build_datarootdir)/julia -cp $(CERTFILE) $@ @@ -110,7 +115,8 @@ $(BUILDDIR)/$(LIBGIT2_SRC_DIR)/build-configured: \ $(LIBGIT2_SRC_PATH)/libgit2-mbedtls-writer-fix.patch-applied \ $(LIBGIT2_SRC_PATH)/libgit2-mbedtls-verify.patch-applied \ $(LIBGIT2_SRC_PATH)/libgit2-gitconfig-symlink.patch-applied \ - $(LIBGIT2_SRC_PATH)/libgit2-free-config.patch-applied + $(LIBGIT2_SRC_PATH)/libgit2-free-config.patch-applied \ + $(LIBGIT2_SRC_PATH)/libgit2-remote-push-NULL.patch-applied ifneq ($(CERTFILE),) $(BUILDDIR)/$(LIBGIT2_SRC_DIR)/build-configured: $(build_datarootdir)/julia/cert.pem diff --git a/deps/patches/libgit2-remote-push-NULL.patch b/deps/patches/libgit2-remote-push-NULL.patch new file mode 100644 index 0000000000000..ac84d6d1bacb2 --- /dev/null +++ b/deps/patches/libgit2-remote-push-NULL.patch @@ -0,0 +1,26 @@ +From 90cdf44ffb7c78cb9d36709f8a07a216e06bd919 Mon Sep 17 00:00:00 2001 +From: Yichao Yu +Date: Sat, 29 Apr 2017 13:00:07 -0400 +Subject: [PATCH] Allow NULL refspec in git_remote_push + +Since this is allowed in `git_remote_upload` +--- + src/remote.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/remote.c b/src/remote.c +index d3132f75c..4cbc45eda 100644 +--- a/src/remote.c ++++ b/src/remote.c +@@ -2412,7 +2412,7 @@ int git_remote_push(git_remote *remote, const git_strarray *refspecs, const git_ + proxy = &opts->proxy_opts; + } + +- assert(remote && refspecs); ++ assert(remote); + + if ((error = git_remote_connect(remote, GIT_DIRECTION_PUSH, cbs, proxy, custom_headers)) < 0) + return error; +-- +2.12.2 + From 9fc78aeb763156c9041dc141054d57d9f2ae79aa Mon Sep 17 00:00:00 2001 From: Mus M Date: Mon, 1 May 2017 13:01:11 -0400 Subject: [PATCH 0636/1534] Update to where syntax in misc files (#21641) * Update to where syntax in misc files --- base/abstractarray.jl | 2 +- base/linalg/hessenberg.jl | 2 +- base/random.jl | 36 ++++++++++++++++++------------------ base/reducedim.jl | 2 +- base/reshapedarray.jl | 4 ++-- base/show.jl | 2 +- base/tuple.jl | 4 ++-- base/twiceprecision.jl | 14 +++++++------- 8 files changed, 33 insertions(+), 33 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index bb5dfa258feaf..22aaa08db840e 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -88,7 +88,7 @@ julia> extrema(b) (1, 210) ``` """ -linearindices(A) = (@_inline_meta; OneTo(_length(A))) +linearindices(A) = (@_inline_meta; OneTo(_length(A))) linearindices(A::AbstractVector) = (@_inline_meta; indices1(A)) eltype(::Type{<:AbstractArray{E}}) where {E} = E elsize(::AbstractArray{T}) where {T} = sizeof(T) diff --git a/base/linalg/hessenberg.jl b/base/linalg/hessenberg.jl index 326bfbd2f7ea0..22aaf5b1d09fe 100644 --- a/base/linalg/hessenberg.jl +++ b/base/linalg/hessenberg.jl @@ -58,7 +58,7 @@ struct HessenbergQ{T,S<:AbstractMatrix} <: AbstractMatrix{T} τ::Vector{T} HessenbergQ{T,S}(factors::AbstractMatrix{T}, τ::Vector{T}) where {T,S<:AbstractMatrix} = new(factors, τ) end -HessenbergQ{T}(factors::AbstractMatrix{T}, τ::Vector{T}) = HessenbergQ{T,typeof(factors)}(factors, τ) +HessenbergQ(factors::AbstractMatrix{T}, τ::Vector{T}) where {T} = HessenbergQ{T,typeof(factors)}(factors, τ) HessenbergQ(A::Hessenberg) = HessenbergQ(A.factors, A.τ) size(A::HessenbergQ, d) = size(A.factors, d) size(A::HessenbergQ) = size(A.factors) diff --git a/base/random.jl b/base/random.jl index 471ac6bbd18d2..d1c99e953c8be 100644 --- a/base/random.jl +++ b/base/random.jl @@ -519,29 +519,29 @@ end # remainder function according to Knuth, where rem_knuth(a, 0) = a rem_knuth(a::UInt, b::UInt) = a % (b + (b == 0)) + a * (b == 0) -rem_knuth{T<:Unsigned}(a::T, b::T) = b != 0 ? a % b : a +rem_knuth(a::T, b::T) where {T<:Unsigned} = b != 0 ? a % b : a # maximum multiple of k <= 2^bits(T) decremented by one, # that is 0xFFFF...FFFF if k = typemax(T) - typemin(T) with intentional underflow # see http://stackoverflow.com/questions/29182036/integer-arithmetic-add-1-to-uint-max-and-divide-by-n-without-overflow -maxmultiple{T<:Unsigned}(k::T) = (div(typemax(T) - k + oneunit(k), k + (k == 0))*k + k - oneunit(k))::T +maxmultiple(k::T) where {T<:Unsigned} = (div(typemax(T) - k + oneunit(k), k + (k == 0))*k + k - oneunit(k))::T # maximum multiple of k within 1:2^32 or 1:2^64 decremented by one, depending on size maxmultiplemix(k::UInt64) = if k >> 32 != 0; maxmultiple(k); else (div(0x0000000100000000, k + (k == 0))*k - oneunit(k))::UInt64; end abstract type RangeGenerator end -struct RangeGeneratorInt{T<:Integer, U<:Unsigned} <: RangeGenerator +struct RangeGeneratorInt{T<:Integer,U<:Unsigned} <: RangeGenerator a::T # first element of the range k::U # range length or zero for full range u::U # rejection threshold end # generators with 32, 128 bits entropy -RangeGeneratorInt{T, U<:Union{UInt32, UInt128}}(a::T, k::U) = RangeGeneratorInt{T, U}(a, k, maxmultiple(k)) +RangeGeneratorInt(a::T, k::U) where {T,U<:Union{UInt32,UInt128}} = RangeGeneratorInt{T,U}(a, k, maxmultiple(k)) # mixed 32/64 bits entropy generator -RangeGeneratorInt{T}(a::T, k::UInt64) = RangeGeneratorInt{T,UInt64}(a, k, maxmultiplemix(k)) +RangeGeneratorInt(a::T, k::UInt64) where {T} = RangeGeneratorInt{T,UInt64}(a, k, maxmultiplemix(k)) # generator for ranges -RangeGenerator{T<:Unsigned}(r::UnitRange{T}) = begin +function RangeGenerator(r::UnitRange{T}) where T<:Unsigned if isempty(r) throw(ArgumentError("range must be non-empty")) end @@ -1274,11 +1274,11 @@ let Floats = Union{Float16,Float32,Float64} randfun! = Symbol(randfun, :!) @eval begin # scalars - $randfun{T<:$Floats}(rng::AbstractRNG, ::Type{T}) = convert(T, $randfun(rng)) - $randfun{T}(::Type{T}) = $randfun(GLOBAL_RNG, T) + $randfun(rng::AbstractRNG, ::Type{T}) where {T<:$Floats} = convert(T, $randfun(rng)) + $randfun(::Type{T}) where {T} = $randfun(GLOBAL_RNG, T) # filling arrays - function $randfun!{T}(rng::AbstractRNG, A::AbstractArray{T}) + function $randfun!(rng::AbstractRNG, A::AbstractArray{T}) where T for i in eachindex(A) @inbounds A[i] = $randfun(rng, T) end @@ -1288,15 +1288,15 @@ let Floats = Union{Float16,Float32,Float64} $randfun!(A::AbstractArray) = $randfun!(GLOBAL_RNG, A) # generating arrays - $randfun{T}(rng::AbstractRNG, ::Type{T}, dims::Dims ) = $randfun!(rng, Array{T}(dims)) + $randfun(rng::AbstractRNG, ::Type{T}, dims::Dims ) where {T} = $randfun!(rng, Array{T}(dims)) # Note that this method explicitly does not define $randfun(rng, T), in order to prevent an infinite recursion. - $randfun{T}(rng::AbstractRNG, ::Type{T}, dim1::Integer, dims::Integer...) = $randfun!(rng, Array{T}(dim1, dims...)) - $randfun{T}( ::Type{T}, dims::Dims ) = $randfun(GLOBAL_RNG, T, dims) - $randfun{T}( ::Type{T}, dims::Integer... ) = $randfun(GLOBAL_RNG, T, dims...) - $randfun( rng::AbstractRNG, dims::Dims ) = $randfun(rng, Float64, dims) - $randfun( rng::AbstractRNG, dims::Integer... ) = $randfun(rng, Float64, dims...) - $randfun( dims::Dims ) = $randfun(GLOBAL_RNG, Float64, dims) - $randfun( dims::Integer... ) = $randfun(GLOBAL_RNG, Float64, dims...) + $randfun(rng::AbstractRNG, ::Type{T}, dim1::Integer, dims::Integer...) where {T} = $randfun!(rng, Array{T}(dim1, dims...)) + $randfun( ::Type{T}, dims::Dims ) where {T} = $randfun(GLOBAL_RNG, T, dims) + $randfun( ::Type{T}, dims::Integer... ) where {T} = $randfun(GLOBAL_RNG, T, dims...) + $randfun(rng::AbstractRNG, dims::Dims ) = $randfun(rng, Float64, dims) + $randfun(rng::AbstractRNG, dims::Integer... ) = $randfun(rng, Float64, dims...) + $randfun( dims::Dims ) = $randfun(GLOBAL_RNG, Float64, dims) + $randfun( dims::Integer... ) = $randfun(GLOBAL_RNG, Float64, dims...) end end end @@ -1444,7 +1444,7 @@ function randsubseq!(r::AbstractRNG, S::AbstractArray, A::AbstractArray, p::Real end randsubseq!(S::AbstractArray, A::AbstractArray, p::Real) = randsubseq!(GLOBAL_RNG, S, A, p) -randsubseq{T}(r::AbstractRNG, A::AbstractArray{T}, p::Real) = randsubseq!(r, T[], A, p) +randsubseq(r::AbstractRNG, A::AbstractArray{T}, p::Real) where {T} = randsubseq!(r, T[], A, p) """ randsubseq(A, p) -> Vector diff --git a/base/reducedim.jl b/base/reducedim.jl index 7b1ad0f493730..a2ba674ee6d64 100644 --- a/base/reducedim.jl +++ b/base/reducedim.jl @@ -210,7 +210,7 @@ end mapreducedim!(f, op, R::AbstractArray, A::AbstractArray) = (_mapreducedim!(f, op, R, A); R) -reducedim!{RT}(op, R::AbstractArray{RT}, A::AbstractArray) = +reducedim!(op, R::AbstractArray{RT}, A::AbstractArray) where {RT} = mapreducedim!(identity, op, R, A, zero(RT)) """ diff --git a/base/reshapedarray.jl b/base/reshapedarray.jl index ac9f4468d2738..5109359421402 100644 --- a/base/reshapedarray.jl +++ b/base/reshapedarray.jl @@ -10,7 +10,7 @@ end ReshapedArray{T,N}(parent::AbstractArray{T}, dims::NTuple{N,Int}, mi) = ReshapedArray{T,N,typeof(parent),typeof(mi)}(parent, dims, mi) # IndexLinear ReshapedArray -ReshapedArrayLF{T,N,P<:AbstractArray} = ReshapedArray{T,N,P,Tuple{}} +const ReshapedArrayLF{T,N,P<:AbstractArray} = ReshapedArray{T,N,P,Tuple{}} # Fast iteration on ReshapedArrays: use the parent iterator struct ReshapedArrayIterator{I,M} @@ -227,7 +227,7 @@ end end # helpful error message for a common failure case -ReshapedRange{T,N,A<:Range} = ReshapedArray{T,N,A,Tuple{}} +const ReshapedRange{T,N,A<:Range} = ReshapedArray{T,N,A,Tuple{}} setindex!(A::ReshapedRange, val, index::Int) = _rs_setindex!_err() setindex!(A::ReshapedRange, val, indexes::Int...) = _rs_setindex!_err() setindex!(A::ReshapedRange, val, index::ReshapedIndex) = _rs_setindex!_err() diff --git a/base/show.jl b/base/show.jl index 2ad3a079b3734..00e941ecba5a9 100644 --- a/base/show.jl +++ b/base/show.jl @@ -1673,7 +1673,7 @@ end show(io::IO, X::AbstractArray) = showarray(io, X, true) -repremptyarray{T}(io::IO, X::Array{T}) = print(io, "Array{$T}(", join(size(X),','), ')') +repremptyarray(io::IO, X::Array{T}) where {T} = print(io, "Array{$T}(", join(size(X),','), ')') repremptyarray(io, X) = nothing # by default, we don't know this constructor function showarray(io::IO, X::AbstractArray, repr::Bool = true; header = true) diff --git a/base/tuple.jl b/base/tuple.jl index 7e243d0fa3728..4103b9111edf9 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -206,9 +206,9 @@ end # type-stable padding -fill_to_length{N}(t::Tuple, val, ::Type{Val{N}}) = _ftl((), val, Val{N}, t...) +fill_to_length(t::Tuple, val, ::Type{Val{N}}) where {N} = _ftl((), val, Val{N}, t...) _ftl(out::NTuple{N,Any}, val, ::Type{Val{N}}) where {N} = out -function _ftl{N}(out::NTuple{N,Any}, val, ::Type{Val{N}}, t...) +function _ftl(out::NTuple{N,Any}, val, ::Type{Val{N}}, t...) where N @_inline_meta throw(ArgumentError("input tuple of length $(N+length(t)), requested $N")) end diff --git a/base/twiceprecision.jl b/base/twiceprecision.jl index 30ace134c09fa..38f027013e3da 100644 --- a/base/twiceprecision.jl +++ b/base/twiceprecision.jl @@ -35,21 +35,21 @@ struct TwicePrecision{T} lo::T # least significant bits end -function (::Type{TwicePrecision{T}}){T,I}(nd::Tuple{I,I}) +function TwicePrecision{T}(nd::Tuple{I,I}) where {T,I} n, d = nd TwicePrecision{T}(n, zero(T)) / d end -function (::Type{TwicePrecision{T}}){T,I}(nd::Tuple{I,I}, nb::Integer) +function TwicePrecision{T}(nd::Tuple{I,I}, nb::Integer) where {T,I} twiceprecision(TwicePrecision{T}(nd), nb) end -function twiceprecision{T<:Number}(val::T, nb::Integer) +function twiceprecision(val::T, nb::Integer) where T<:Number hi = truncbits(val, nb) TwicePrecision{T}(hi, val - hi) end -function twiceprecision{T<:Number}(val::TwicePrecision{T}, nb::Integer) +function twiceprecision(val::TwicePrecision{T}, nb::Integer) where T<:Number hi = truncbits(val.hi, nb) TwicePrecision{T}(hi, (val.hi - hi) + val.lo) end @@ -86,7 +86,7 @@ zero(::Type{TwicePrecision{T}}) where {T} = TwicePrecision{T}(0, 0) ## StepRangeLen # If using TwicePrecision numbers, deliberately force user to specify offset -StepRangeLen{T}(ref::TwicePrecision{T}, step::TwicePrecision{T}, len::Integer, offset::Integer) = +StepRangeLen(ref::TwicePrecision{T}, step::TwicePrecision{T}, len::Integer, offset::Integer) where {T} = StepRangeLen{T,TwicePrecision{T},TwicePrecision{T}}(ref, step, len, offset) # Construct range for rational start=start_n/den, step=step_n/den @@ -439,7 +439,7 @@ narrow(::Type{Float64}) = Float32 narrow(::Type{Float32}) = Float16 narrow(::Type{Float16}) = Float16 -function add2{T<:Number}(u::T, v::T) +function add2(u::T, v::T) where T<:Number @_inline_meta u, v = ifelse(abs(v) > abs(u), (v, u), (u, v)) w = u + v @@ -473,7 +473,7 @@ function *(x::TwicePrecision, v::Integer) TwicePrecision(y_hi, y_lo) end -function _mul2{T<:Union{Float16,Float32,Float64}}(x::TwicePrecision{T}, v::T) +function _mul2(x::TwicePrecision{T}, v::T) where T<:Union{Float16,Float32,Float64} v == 0 && return TwicePrecision(T(0), T(0)) xhh, xhl = splitprec(x.hi) vh, vl = splitprec(v) From 45dc18d0bc75c9b74d7934cbbb3311b4d0a54ca2 Mon Sep 17 00:00:00 2001 From: Napoleon Oikonomou Date: Mon, 1 May 2017 04:35:55 +0300 Subject: [PATCH 0637/1534] fixed zero insertion when concatenate sparse matrices with 0*I --- base/sparse/sparsematrix.jl | 3 +++ test/sparse/sparse.jl | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl index f21a2411f17d6..cee5b35516408 100644 --- a/base/sparse/sparsematrix.jl +++ b/base/sparse/sparsematrix.jl @@ -1430,6 +1430,9 @@ speye_scaled(diag, m::Integer, n::Integer) = speye_scaled(typeof(diag), diag, m, function speye_scaled(T, diag, m::Integer, n::Integer) ((m < 0) || (n < 0)) && throw(ArgumentError("invalid array dimensions")) + if iszero(diag) + return SparseMatrixCSC(m, n, ones(Int, n+1), Vector{Int}(0), Vector{T}(0)) + end nnz = min(m,n) colptr = Vector{Int}(1+n) colptr[1:nnz+1] = 1:nnz+1 diff --git a/test/sparse/sparse.jl b/test/sparse/sparse.jl index f0ae30b96c99c..43a0c4c346577 100644 --- a/test/sparse/sparse.jl +++ b/test/sparse/sparse.jl @@ -45,14 +45,18 @@ do33 = ones(3) end @testset "concatenation tests" begin + sp33 = speye(3, 3) + @testset "horizontal concatenation" begin @test all([se33 se33] == sparse([1, 2, 3, 1, 2, 3], [1, 2, 3, 4, 5, 6], ones(6))) + @test length(([sp33 0I]).nzval) == 3 end @testset "vertical concatenation" begin @test all([se33; se33] == sparse([1, 4, 2, 5, 3, 6], [1, 1, 2, 2, 3, 3], ones(6))) se33_32bit = convert(SparseMatrixCSC{Float32,Int32}, se33) @test all([se33; se33_32bit] == sparse([1, 4, 2, 5, 3, 6], [1, 1, 2, 2, 3, 3], ones(6))) + @test length(([sp33; 0I]).nzval) == 3 end se44 = speye(4) @@ -62,6 +66,7 @@ end se77 = speye(7) @testset "h+v concatenation" begin @test all([se44 sz42 sz41; sz34 se33] == se77) + @test length(([sp33 0I; 1I 0I]).nzval) == 6 end @testset "blkdiag concatenation" begin From ef02bc6a781c849ef04ae99071d939cc1a177d93 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Mon, 1 May 2017 21:48:54 -0500 Subject: [PATCH 0638/1534] Support isless and == between all Period subtypes (#21378) --- base/dates/periods.jl | 16 ++++++++++------ test/dates/periods.jl | 20 ++++++++++++++++++++ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/base/dates/periods.jl b/base/dates/periods.jl index 1c08edfdaf385..7682164506a73 100644 --- a/base/dates/periods.jl +++ b/base/dates/periods.jl @@ -59,8 +59,10 @@ default(p::Union{T,Type{T}}) where {T<:DatePeriod} = T(1) default(p::Union{T,Type{T}}) where {T<:TimePeriod} = T(0) (-)(x::P) where {P<:Period} = P(-value(x)) +==(x::P, y::P) where {P<:Period} = value(x) == value(y) +==(x::Period, y::Period) = (==)(promote(x, y)...) Base.isless(x::P, y::P) where {P<:Period} = isless(value(x), value(y)) -(==)(x::P, y::P) where {P<:Period} = value(x) == value(y) +Base.isless(x::Period, y::Period) = isless(promote(x, y)...) # Period Arithmetic, grouped by dimensionality: import Base: div, fld, mod, rem, gcd, lcm, +, -, *, /, % @@ -425,9 +427,6 @@ for i = 1:length(fixedperiod_conversions) N *= nc end end -# have to declare thusly so that diagonal dispatch above takes precedence: -(==)(x::T, y::S) where {T<:FixedPeriod,S<:FixedPeriod} = (==)(promote(x, y)...) -Base.isless(x::T, y::S) where {T<:FixedPeriod,S<:FixedPeriod} = isless(promote(x, y)...) # other periods with fixed conversions but which aren't fixed time periods const OtherPeriod = Union{Month, Year} @@ -439,8 +438,13 @@ let vmax = typemax(Int64) ÷ 12, vmin = typemin(Int64) ÷ 12 end Base.convert(::Type{Year}, x::Month) = Year(divexact(value(x), 12)) Base.promote_rule(::Type{Year}, ::Type{Month}) = Month -(==)(x::T, y::S) where {T<:OtherPeriod,S<:OtherPeriod} = (==)(promote(x, y)...) -Base.isless(x::T, y::S) where {T<:OtherPeriod,S<:OtherPeriod} = isless(promote(x, y)...) + +# disallow comparing fixed to other periods +(==)(x::FixedPeriod, y::OtherPeriod) = throw(MethodError(==, (x, y))) +(==)(x::OtherPeriod, y::FixedPeriod) = throw(MethodError(==, (x, y))) + +Base.isless(x::FixedPeriod, y::OtherPeriod) = throw(MethodError(isless, (x, y))) +Base.isless(x::OtherPeriod, y::FixedPeriod) = throw(MethodError(isless, (x, y))) # truncating conversions to milliseconds and days: toms(c::Nanosecond) = div(value(c), 1000000) diff --git a/test/dates/periods.jl b/test/dates/periods.jl index e4bb9d9bb30b2..72ce644003870 100644 --- a/test/dates/periods.jl +++ b/test/dates/periods.jl @@ -234,6 +234,26 @@ test = ((((((((dt + y) - m) + w) - d) + h) - mi) + s) - ms) @test !(Dates.Millisecond(-1) > Dates.Millisecond(1)) @test Dates.Millisecond(1) == Dates.Millisecond(1) @test_throws MethodError Dates.Year(1) < Dates.Millisecond(1) +@test_throws MethodError Dates.Millisecond(1) < Dates.Year(1) +@test_throws MethodError Dates.Year(1) == Dates.Millisecond(1) +@test_throws MethodError Dates.Millisecond(1) == Dates.Year(1) + +# Allow comparisons with new Period subtypes +let + # https://en.wikipedia.org/wiki/Swatch_Internet_Time + struct Beat <: Dates.Period + value::Int64 + end + + Dates.value(b::Beat) = b.value + Dates.toms(b::Beat) = Dates.value(b) * 86400 + Dates._units(b::Beat) = " beat" * (abs(Dates.value(b)) == 1 ? "" : "s") + Base.promote_rule(::Type{Dates.Day}, ::Type{Beat}) = Dates.Millisecond + Base.convert{T<:Dates.Millisecond}(::Type{T}, b::Beat) = T(Dates.toms(b)) + + @test Beat(1000) == Dates.Day(1) + @test Beat(1) < Dates.Day(1) +end @test Dates.Year("1") == y @test Dates.Month("1") == m From 8d93b4d455786aba4624cbe5bd14cf5e4d81472e Mon Sep 17 00:00:00 2001 From: Mus M Date: Mon, 1 May 2017 22:49:59 -0400 Subject: [PATCH 0639/1534] Use where syntax for SharedArray constructor (#21661) Use `where` syntax in sharedarray.jl --- base/sharedarray.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/base/sharedarray.jl b/base/sharedarray.jl index bcb78ec050728..62e1a546764d7 100644 --- a/base/sharedarray.jl +++ b/base/sharedarray.jl @@ -77,7 +77,7 @@ beginning of the file. """ SharedArray -function SharedArray{T,N}(dims::Dims{N}; init=false, pids=Int[]) where T where N +function SharedArray{T,N}(dims::Dims{N}; init=false, pids=Int[]) where {T,N} isbits(T) || throw(ArgumentError("type of SharedArray elements must be bits types, got $(T)")) pids, onlocalhost = shared_pids(pids) @@ -147,8 +147,8 @@ SharedArray{T}(m::Integer, n::Integer; kwargs...) where {T} = SharedArray{T}(m::Integer, n::Integer, o::Integer; kwargs...) where {T} = SharedArray{T,3}(m, n, o; kwargs...) -function (::Type{SharedArray{T,N}})(filename::AbstractString, dims::NTuple{N,Int}, offset::Integer=0; - mode=nothing, init=false, pids::Vector{Int}=Int[]) where T where N +function SharedArray{T,N}(filename::AbstractString, dims::NTuple{N,Int}, offset::Integer=0; + mode=nothing, init=false, pids::Vector{Int}=Int[]) where {T,N} if !isabspath(filename) throw(ArgumentError("$filename is not an absolute path; try abspath(filename)?")) end @@ -258,7 +258,7 @@ size(S::SharedArray) = S.dims ndims(S::SharedArray) = length(S.dims) IndexStyle(::Type{<:SharedArray}) = IndexLinear() -function reshape(a::SharedArray{T}, dims::NTuple{N,Int}) where T where N +function reshape(a::SharedArray{T}, dims::NTuple{N,Int}) where {T,N} if length(a) != prod(dims) throw(DimensionMismatch("dimensions must be consistent with array size")) end @@ -325,7 +325,7 @@ function convert(::Type{SharedArray{T}}, A::Array) where T S = SharedArray{T,ndims(A)}(size(A)) copy!(S, A) end -function convert(::Type{SharedArray{TS,N}}, A::Array{TA,N}) where TS where TA where N +function convert(::Type{SharedArray{TS,N}}, A::Array{TA,N}) where {TS,TA,N} S = SharedArray{TS,ndims(A)}(size(A)) copy!(S, A) end From 609b3d12c75bdf99d98a29ab3db856a307253e74 Mon Sep 17 00:00:00 2001 From: Amit Murthy Date: Tue, 2 May 2017 09:35:12 +0530 Subject: [PATCH 0640/1534] pass exeflags consistently to all julia test processes (#21652) --- test/distributed.jl | 10 +----- test/distributed_exec.jl | 70 +++++++++++++++------------------------- test/runtests.jl | 27 ++++++---------- test/testdefs.jl | 25 +++++++++++++- test/topology.jl | 20 ++++-------- 5 files changed, 67 insertions(+), 85 deletions(-) diff --git a/test/distributed.jl b/test/distributed.jl index 99a02ee6b662a..007f28d4625aa 100644 --- a/test/distributed.jl +++ b/test/distributed.jl @@ -3,15 +3,7 @@ # Run the distributed test outside of the main driver since it needs its own # set of dedicated workers. -inline_flag = Base.JLOptions().can_inline == 1 ? `` : `--inline=no` -cov_flag = `` -if Base.JLOptions().code_coverage == 1 - cov_flag = `--code-coverage=user` -elseif Base.JLOptions().code_coverage == 2 - cov_flag = `--code-coverage=all` -end - -cmd = `$(Base.julia_cmd()) $inline_flag $cov_flag --check-bounds=yes --startup-file=no --depwarn=error distributed_exec.jl` +cmd = `$test_exename $test_exeflags distributed_exec.jl` if !success(pipeline(cmd; stdout=STDOUT, stderr=STDERR)) && ccall(:jl_running_on_valgrind,Cint,()) == 0 error("Distributed test failed, cmd : $cmd") diff --git a/test/distributed_exec.jl b/test/distributed_exec.jl index 7742059ea3f73..64f28c1e379e7 100644 --- a/test/distributed_exec.jl +++ b/test/distributed_exec.jl @@ -1,14 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test - -inline_flag = Base.JLOptions().can_inline == 1 ? `` : `--inline=no` -cov_flag = `` -if Base.JLOptions().code_coverage == 1 - cov_flag = `--code-coverage=user` -elseif Base.JLOptions().code_coverage == 2 - cov_flag = `--code-coverage=all` -end +include("testdefs.jl") # Test a few "remote" invocations when no workers are present @test remote(myid)() == 1 @@ -17,8 +10,10 @@ end 1 end -cov_in_exeflags = `$cov_flag $inline_flag --check-bounds=yes --startup-file=no --depwarn=error` -addprocs(4; exeflags=cov_in_exeflags) +addprocs_with_testenv(4) + +id_me = myid() +id_other = filter(x -> x != id_me, procs())[rand(1:(nprocs()-1))] # Test remote() let @@ -79,10 +74,6 @@ let @test count == 0 end - -id_me = myid() -id_other = filter(x -> x != id_me, procs())[rand(1:(nprocs()-1))] - # Test Futures function testf(id) f=Future(id) @@ -952,22 +943,22 @@ if is_unix() # aka have ssh end print("\nTesting SSH addprocs with $(length(hosts)) workers...\n") - new_pids = addprocs(hosts; exeflags=cov_in_exeflags, sshflags=sshflags) + new_pids = addprocs_with_testenv(hosts; sshflags=sshflags) @test length(new_pids) == length(hosts) test_n_remove_pids(new_pids) print("\nMixed ssh addprocs with :auto\n") - new_pids = addprocs(["localhost", ("127.0.0.1", :auto), "localhost"]; sshflags=sshflags) + new_pids = addprocs_with_testenv(["localhost", ("127.0.0.1", :auto), "localhost"]; sshflags=sshflags) @test length(new_pids) == (2 + Sys.CPU_CORES) test_n_remove_pids(new_pids) print("\nMixed ssh addprocs with numeric counts\n") - new_pids = addprocs([("localhost", 2), ("127.0.0.1", 2), "localhost"]; exeflags=cov_in_exeflags, sshflags=sshflags) + new_pids = addprocs_with_testenv([("localhost", 2), ("127.0.0.1", 2), "localhost"]; sshflags=sshflags) @test length(new_pids) == 5 test_n_remove_pids(new_pids) print("\nssh addprocs with tunnel\n") - new_pids = addprocs([("localhost", num_workers)]; tunnel=true, exeflags=cov_in_exeflags, sshflags=sshflags) + new_pids = addprocs_with_testenv([("localhost", num_workers)]; tunnel=true, sshflags=sshflags) @test length(new_pids) == num_workers test_n_remove_pids(new_pids) @@ -979,15 +970,14 @@ if is_unix() # aka have ssh h4 = "$h3 $(string(getipaddr()))" h5 = "$h4:9300" - new_pids = addprocs([h1, h2, h3, h4, h5]; exeflags=cov_in_exeflags, sshflags=sshflags) + new_pids = addprocs_with_testenv([h1, h2, h3, h4, h5]; sshflags=sshflags) @test length(new_pids) == 5 test_n_remove_pids(new_pids) print("\nkeyword arg exename\n") - for exename in [`$(joinpath(JULIA_HOME, Base.julia_exename()))`, "$(joinpath(JULIA_HOME, Base.julia_exename()))"] - for addp_func in [()->addprocs(["localhost"]; exename=exename, exeflags=cov_in_exeflags, sshflags=sshflags), - ()->addprocs(1; exename=exename, exeflags=cov_in_exeflags)] + for addp_func in [()->addprocs_with_testenv(["localhost"]; exename=exename, exeflags=test_exeflags, sshflags=sshflags), + ()->addprocs_with_testenv(1; exename=exename, exeflags=test_exeflags)] new_pids = addp_func() @test length(new_pids) == 1 @@ -1218,7 +1208,7 @@ function test_add_procs_threaded_blas() master_blas_thread_count = get_num_threads() # Test with default enable_threaded_blas false - processes_added = addprocs(2; exeflags=cov_in_exeflags) + processes_added = addprocs_with_testenv(2) for proc_id in processes_added test_blas_config(proc_id, false) end @@ -1233,7 +1223,7 @@ function test_add_procs_threaded_blas() end rmprocs(processes_added) - processes_added = addprocs(2, enable_threaded_blas=true, exeflags=cov_in_exeflags) + processes_added = addprocs_with_testenv(2, enable_threaded_blas=true) for proc_id in processes_added test_blas_config(proc_id, true) end @@ -1254,7 +1244,7 @@ test_add_procs_threaded_blas() #19687 # ensure no race conditions between rmprocs and addprocs for i in 1:5 - p = addprocs(1; exeflags=cov_in_exeflags)[1] + p = addprocs_with_testenv(1)[1] @spawnat p sleep(5) rmprocs(p; waitfor=0) end @@ -1262,7 +1252,7 @@ end # Test if a wait has been called on rmprocs(...;waitfor=0), further remotecalls # don't throw errors. for i in 1:5 - p = addprocs(1; exeflags=cov_in_exeflags)[1] + p = addprocs_with_testenv(1)[1] np = nprocs() @spawnat p sleep(5) wait(rmprocs(p; waitfor=0)) @@ -1274,7 +1264,7 @@ end # Test that an exception is thrown if workers are unable to be removed within requested time. if DoFullTest - pids=addprocs(4; exeflags=cov_in_exeflags); + pids=addprocs_with_testenv(4); @test_throws ErrorException rmprocs(pids; waitfor=0.001); # wait for workers to be removed while any(x -> (x in procs()), pids) @@ -1283,7 +1273,7 @@ if DoFullTest end # Test addprocs/rmprocs from master node only -for f in [ ()->addprocs(1; exeflags=cov_in_exeflags), ()->rmprocs(workers()) ] +for f in [ ()->addprocs(1; exeflags=test_exeflags), ()->rmprocs(workers()) ] try remotecall_fetch(f, id_other) error("Unexpected") @@ -1329,13 +1319,13 @@ end testruns = Any[] if DoFullTest - append!(testruns, [(()->addprocs(["errorhost20372"]; exeflags=cov_in_exeflags), "Unable to read host:port string from worker. Launch command exited with error?", ())]) + append!(testruns, [(()->addprocs_with_testenv(["errorhost20372"]), "Unable to read host:port string from worker. Launch command exited with error?", ())]) end append!(testruns, [ - (()->addprocs(ErrorSimulator(:exit); exeflags=cov_in_exeflags), "Unable to read host:port string from worker. Launch command exited with error?", ()), - (()->addprocs(ErrorSimulator(:ntries); exeflags=cov_in_exeflags), "Unexpected output from worker launch command. Host:port string not found.", ()), - (()->addprocs(ErrorSimulator(:timeout); exeflags=cov_in_exeflags), "Timed out waiting to read host:port string from worker.", ("JULIA_WORKER_TIMEOUT"=>"1",)) + (()->addprocs_with_testenv(ErrorSimulator(:exit)), "Unable to read host:port string from worker. Launch command exited with error?", ()), + (()->addprocs_with_testenv(ErrorSimulator(:ntries)), "Unexpected output from worker launch command. Host:port string not found.", ()), + (()->addprocs_with_testenv(ErrorSimulator(:timeout)), "Timed out waiting to read host:port string from worker.", ("JULIA_WORKER_TIMEOUT"=>"1",)) ]) for (addp_testf, expected_errstr, env) in testruns @@ -1560,15 +1550,7 @@ catch ex @test ex.captured.ex.exceptions[2].ex == UndefVarError(:DontExistOn1) end -# Topology tests need to run externally since a given cluster at any -# time can only support a single topology and the current session -# is already running in parallel under the default topology. -script = joinpath(dirname(@__FILE__), "topology.jl") -cmd = `$(Base.julia_cmd()) $cov_in_exeflags $script` - -(strm, proc) = open(pipeline(cmd, stderr=STDERR)) -wait(proc) -if !success(proc) && ccall(:jl_running_on_valgrind,Cint,()) == 0 - println(readstring(strm)) - error("Topology tests failed : $cmd") -end +# Run topology tests last after removing all workers, since a given +# cluster at any time only supports a single topology. +rmprocs(workers()) +include("topology.jl") diff --git a/test/runtests.jl b/test/runtests.jl index e481d4f3e7ceb..262684a746496 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -2,6 +2,8 @@ using Base.Test include("choosetests.jl") +include("testdefs.jl") + tests, net_on = choosetests(ARGS) tests = unique(tests) @@ -11,18 +13,6 @@ else typemax(Csize_t) end -if haskey(ENV, "JULIA_TEST_EXEFLAGS") - const test_exeflags = `$(Base.shell_split(ENV["JULIA_TEST_EXEFLAGS"]))` -else - const test_exeflags = `--check-bounds=yes --startup-file=no --depwarn=error` -end - -if haskey(ENV, "JULIA_TEST_EXENAME") - const test_exename = `$(Base.shell_split(ENV["JULIA_TEST_EXENAME"]))` -else - const test_exename = `$(joinpath(JULIA_HOME, Base.julia_exename()))` -end - const node1_tests = String[] function move_to_node1(t) if t in tests @@ -40,12 +30,15 @@ cd(dirname(@__FILE__)) do n = 1 if net_on n = min(Sys.CPU_CORES, length(tests)) - n > 1 && addprocs(n; exename=test_exename, exeflags=test_exeflags) + if n > 1 + addprocs_with_testenv(n) + @sync for p in workers() + @async remotecall_fetch(include, p, "testdefs.jl") + end + end BLAS.set_num_threads(1) end - @everywhere include("testdefs.jl") - #pretty print the information about gc and mem usage name_align = maximum([length("Test (Worker)"); map(x -> length(x) + 3 + ndigits(nworkers()), tests)]) elapsed_align = length("Time (s)") @@ -72,8 +65,8 @@ cd(dirname(@__FILE__)) do if (isa(resp[end], Integer) && (resp[end] > max_worker_rss)) || isa(resp, Exception) if n > 1 rmprocs(wrkr, waitfor=30) - p = addprocs(1; exename=test_exename, exeflags=test_exeflags)[1] - remotecall_fetch(()->include("testdefs.jl"), p) + p = addprocs_with_testenv(1)[1] + remotecall_fetch(include, p, "testdefs.jl") else # single process testing, bail if mem limit reached, or, on an exception. isa(resp, Exception) ? rethrow(resp) : error("Halting tests. Memory limit reached : $resp > $max_worker_rss") diff --git a/test/testdefs.jl b/test/testdefs.jl index e9d7a1bdfadd9..7450c4bcaf7c0 100644 --- a/test/testdefs.jl +++ b/test/testdefs.jl @@ -1,5 +1,26 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license +if haskey(ENV, "JULIA_TEST_EXEFLAGS") + const test_exeflags = `$(Base.shell_split(ENV["JULIA_TEST_EXEFLAGS"]))` +else + inline_flag = Base.JLOptions().can_inline == 1 ? `` : `--inline=no` + cov_flag = `` + if Base.JLOptions().code_coverage == 1 + cov_flag = `--code-coverage=user` + elseif Base.JLOptions().code_coverage == 2 + cov_flag = `--code-coverage=all` + end + const test_exeflags = `$cov_flag $inline_flag --check-bounds=yes --startup-file=no --depwarn=error` +end + +if haskey(ENV, "JULIA_TEST_EXENAME") + const test_exename = `$(Base.shell_split(ENV["JULIA_TEST_EXENAME"]))` +else + const test_exename = `$(joinpath(JULIA_HOME, Base.julia_exename()))` +end + +addprocs_with_testenv(X; kwargs...) = addprocs(X; exename=test_exename, exeflags=test_exeflags, kwargs...) + function runtests(name, isolate=true) old_print_setting = Base.Test.TESTSET_PRINT_ENABLE[] Base.Test.TESTSET_PRINT_ENABLE[] = false @@ -9,6 +30,7 @@ function runtests(name, isolate=true) # code it in the test mod_name = Symbol("Test", rand(1:100), "Main_", replace(name, '/', '_')) m = @eval(Main, module $mod_name end) + eval(m, :(import Main: test_exename, test_exeflags, addprocs_with_testenv)) else m = Main end @@ -38,4 +60,5 @@ end # looking in . messes things up badly filter!(x->x!=".", LOAD_PATH) -nothing + +nothing # File is loaded via a remotecall to "include". Ensure it returns "nothing". diff --git a/test/topology.jl b/test/topology.jl index 46c9f39251c63..c3c92c51a7a1f 100644 --- a/test/topology.jl +++ b/test/topology.jl @@ -1,18 +1,10 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -include("testdefs.jl") -inline_flag = Base.JLOptions().can_inline == 1 ? `` : `--inline=no` -cov_flag = `` -if Base.JLOptions().code_coverage == 1 - cov_flag = `--code-coverage=user` -elseif Base.JLOptions().code_coverage == 2 - cov_flag = `--code-coverage=all` -end -cov_in_exeflags = `$cov_flag $inline_flag --check-bounds=yes --startup-file=no --depwarn=error` -addprocs(4; exeflags=cov_in_exeflags, topology="master_slave") -using Base.Test +pids = addprocs_with_testenv(4; topology="master_slave") +p1 = pids[1] +p2 = pids[2] -@test_throws RemoteException remotecall_fetch(()->remotecall_fetch(myid, 3), 2) +@test_throws RemoteException remotecall_fetch(()->remotecall_fetch(myid, p2), p1) function test_worker_counts() # check if the nprocs/nworkers/workers are the same on the remaining workers @@ -51,7 +43,7 @@ function Base.launch(manager::TopoTestManager, params::Dict, launched::Array, c: for i in 1:manager.np io, pobj = open(pipeline(detach( - setenv(`$(Base.julia_cmd(exename)) $exeflags --bind-to $(Base.Distributed.LPROC.bind_addr) --worker $(Base.cluster_cookie())`, dir=dir)); stderr=STDERR), "r") + setenv(`$exename $exeflags --bind-to $(Base.Distributed.LPROC.bind_addr) --worker $(Base.cluster_cookie())`, dir=dir)); stderr=STDERR), "r") wconfig = WorkerConfig() wconfig.process = pobj wconfig.io = io @@ -72,7 +64,7 @@ function Base.manage(manager::TopoTestManager, id::Integer, config::WorkerConfig end end -addprocs(TopoTestManager(8); exeflags=cov_in_exeflags, topology="custom") +addprocs_with_testenv(TopoTestManager(8); topology="custom") while true if any(x->get(map_pid_ident, x, 0)==0, workers()) From 63c269e8fa04cafb8e38a122df979333cd1c2995 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Tue, 2 May 2017 05:16:30 -0700 Subject: [PATCH 0641/1534] Reopen master for breaking changes (#21610) --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index dda172758e203..9e9aa6f93f9c5 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.6.0-pre.beta +0.7.0-DEV From 8c32d9c124cc32f742435fd2c50ac1da61be0810 Mon Sep 17 00:00:00 2001 From: kshyatt Date: Mon, 1 May 2017 16:45:30 -0700 Subject: [PATCH 0642/1534] Fix a bad link and document DiffDelta type --- base/libgit2/types.jl | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/base/libgit2/types.jl b/base/libgit2/types.jl index 3bfede4b20367..19fdc67f7d720 100644 --- a/base/libgit2/types.jl +++ b/base/libgit2/types.jl @@ -298,7 +298,18 @@ end LibGit2.DiffDelta Description of changes to one entry. -Matches the [`git_diff_file`](https://libgit2.github.com/libgit2/#HEAD/type/git_diff_file) struct. +Matches the [`git_diff_delta`](https://libgit2.github.com/libgit2/#HEAD/type/git_diff_delta) struct. + +The fields represent: + * `status`: One of `Consts.DELTA_STATUS`, indicating whether the file has been added/modified/deleted. + * `flags`: Flags for the delta and the objects on each side. Determines whether to treat the file(s) + as binary/text, whether they exist on each side of the diff, and whether the object ids are known + to be correct. + * `similarity`: Used to indicate if a file has been renamed or copied. + * `nfiles`: The number of files in the delta (for instance, if the delta + was run on a submodule commit id, it may contain more than one file). + * `old_file`: A [`DiffFile`](@ref) containing information about the file(s) before the changes. + * `new_file`: A [`DiffFile`](@ref) containing information about the file(s) after the changes. """ struct DiffDelta status::Cint From 17d882b5ec9c36e7f9db9a301cbc4a432c7991b6 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Tue, 2 May 2017 08:16:58 -0400 Subject: [PATCH 0643/1534] fix existing doctest outputs --- base/linalg/dense.jl | 2 +- base/linalg/eigen.jl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/base/linalg/dense.jl b/base/linalg/dense.jl index 11676b92c51f3..1c4a3f453d4d6 100644 --- a/base/linalg/dense.jl +++ b/base/linalg/dense.jl @@ -546,7 +546,7 @@ julia> A = 2.7182818 * eye(2) 0.0 2.71828 julia> logm(A) -2×2 Array{Float64,2}: +2×2 Symmetric{Float64,Array{Float64,2}}: 1.0 0.0 0.0 1.0 ``` diff --git a/base/linalg/eigen.jl b/base/linalg/eigen.jl index f579f16f1690d..0ef75b84c2246 100644 --- a/base/linalg/eigen.jl +++ b/base/linalg/eigen.jl @@ -228,7 +228,7 @@ julia> A = [0 im; -1 0] julia> eigmax(A) ERROR: DomainError: Stacktrace: - [1] #eigmax#38(::Bool, ::Bool, ::Function, ::Array{Complex{Int64},2}) at ./linalg/eigen.jl:238 + [1] #eigmax#46(::Bool, ::Bool, ::Function, ::Array{Complex{Int64},2}) at ./linalg/eigen.jl:238 [2] eigmax(::Array{Complex{Int64},2}) at ./linalg/eigen.jl:236 ``` """ @@ -270,7 +270,7 @@ julia> A = [0 im; -1 0] julia> eigmin(A) ERROR: DomainError: Stacktrace: - [1] #eigmin#39(::Bool, ::Bool, ::Function, ::Array{Complex{Int64},2}) at ./linalg/eigen.jl:280 + [1] #eigmin#47(::Bool, ::Bool, ::Function, ::Array{Complex{Int64},2}) at ./linalg/eigen.jl:280 [2] eigmin(::Array{Complex{Int64},2}) at ./linalg/eigen.jl:278 ``` """ From fef650ba6fb6166f9765345c9e7986cad8fbe495 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Tue, 2 May 2017 14:55:26 -0400 Subject: [PATCH 0644/1534] change a few example code blocks to doctests and fix quoted output of a Cmd object --- base/dates/periods.jl | 4 ++-- base/shell.jl | 13 ++++++++----- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/base/dates/periods.jl b/base/dates/periods.jl index 7682164506a73..7fbba3d59f86f 100644 --- a/base/dates/periods.jl +++ b/base/dates/periods.jl @@ -199,7 +199,7 @@ Construct a `CompoundPeriod` from a `Vector` of `Period`s. All `Period`s of the will be added together. # Examples -```julia +```jldoctest julia> Dates.CompoundPeriod(Dates.Hour(12), Dates.Hour(13)) 25 hours @@ -232,7 +232,7 @@ Reduces the `CompoundPeriod` into its canonical form by applying the following r (eg. `Hour(1) - Day(1)` becomes `-Hour(23)`) # Examples -```julia +```jldoctest julia> Dates.canonicalize(Dates.CompoundPeriod(Dates.Hour(12), Dates.Hour(13))) 1 day, 1 hour diff --git a/base/shell.jl b/base/shell.jl index a191a1725b826..a6a8d2fddb48a 100644 --- a/base/shell.jl +++ b/base/shell.jl @@ -178,13 +178,16 @@ The unexported `shell_escape` function is the inverse of the unexported `shell_s it takes a string or command object and escapes any special characters in such a way that calling `shell_split` on it would give back the array of words in the original command. The `special` keyword argument controls what characters in addition to whitespace, backslashes, quotes and -dollar signs are considered to be special (default: none). Examples: +dollar signs are considered to be special (default: none). - julia> Base.shell_escape("cat", "/foo/bar baz", "&&", "echo", "done") - "cat '/foo/bar baz' && echo done" +# Examples +```jldoctest +julia> Base.shell_escape("cat", "/foo/bar baz", "&&", "echo", "done") +"cat '/foo/bar baz' && echo done" - julia> Base.shell_escape("echo", "this", "&&", "that") - "echo this '&&' that" +julia> Base.shell_escape("echo", "this", "&&", "that") +"echo this && that" +``` """ shell_escape(args::AbstractString...; special::AbstractString="") = sprint(io->print_shell_escaped(io, args..., special=special)) From 94acb6f47dceeb2d44a4f0952cc9146723f9ec98 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 25 Aug 2015 22:43:07 -0400 Subject: [PATCH 0645/1534] change open(cmd) to return a Process object (without a separate IO value) This reverts commit 8ffdfc274cbe20b9ed5994eaa00f0937e5b4272e, and fixes it a bit too :) fix #9659 --- base/distributed/cluster.jl | 4 +- base/distributed/managers.jl | 13 ++-- base/loading.jl | 34 +++++----- base/process.jl | 63 +++++++++++-------- .../clustermanager/simple/UnixDomainCM.jl | 4 +- test/distributed_exec.jl | 6 +- test/spawn.jl | 16 ++--- test/topology.jl | 9 +-- 8 files changed, 80 insertions(+), 69 deletions(-) diff --git a/base/distributed/cluster.jl b/base/distributed/cluster.jl index a2ca068a7161e..686eb8d2a4fff 100644 --- a/base/distributed/cluster.jl +++ b/base/distributed/cluster.jl @@ -525,8 +525,8 @@ function launch_additional(np::Integer, cmd::Cmd) addresses = Vector{Any}(np) for i in 1:np - io, pobj = open(pipeline(detach(cmd), stderr=STDERR), "r") - io_objs[i] = io + io = open(detach(cmd)) + io_objs[i] = io.out end for (i,io) in enumerate(io_objs) diff --git a/base/distributed/managers.jl b/base/distributed/managers.jl index 7591f51292cf2..cbd8316a75941 100644 --- a/base/distributed/managers.jl +++ b/base/distributed/managers.jl @@ -202,10 +202,10 @@ function launch_on_machine(manager::SSHManager, machine, cnt, params, launched, # detach launches the command in a new process group, allowing it to outlive # the initial julia process (Ctrl-C and teardown methods are handled through messages) # for the launched processes. - io, pobj = open(pipeline(detach(cmd), stderr=STDERR), "r") + io = open(detach(cmd)) wconfig = WorkerConfig() - wconfig.io = io + wconfig.io = io.out wconfig.host = host wconfig.tunnel = params[:tunnel] wconfig.sshflags = sshflags @@ -321,12 +321,11 @@ function launch(manager::LocalManager, params::Dict, launched::Array, c::Conditi bind_to = manager.restrict ? `127.0.0.1` : `$(LPROC.bind_addr)` for i in 1:manager.np - io, pobj = open(pipeline(detach( - setenv(`$(julia_cmd(exename)) $exeflags --bind-to $bind_to --worker $(cluster_cookie())`, dir=dir)), - stderr=STDERR), "r") + cmd = `$(julia_cmd(exename)) $exeflags --bind-to $bind_to --worker $(cluster_cookie())` + io = open(detach(setenv(cmd, dir=dir))) wconfig = WorkerConfig() - wconfig.process = pobj - wconfig.io = io + wconfig.process = io + wconfig.io = io.out wconfig.enable_threaded_blas = params[:enable_threaded_blas] push!(launched, wconfig) end diff --git a/base/loading.jl b/base/loading.jl index 5601825f94b68..5491b120d95e7 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -599,14 +599,15 @@ function create_expr_cache(input::String, output::String, concrete_deps::Vector{ eval(Main, deserialize(STDIN)) end """ - io, pobj = open(pipeline(detach(`$(julia_cmd()) -O0 - --output-ji $output --output-incremental=yes - --startup-file=no --history-file=no - --color=$(have_color ? "yes" : "no") - --eval $code_object`), stderr=STDERR), - "w", STDOUT) + io = open(pipeline(detach(`$(julia_cmd()) -O0 + --output-ji $output --output-incremental=yes + --startup-file=no --history-file=no + --color=$(have_color ? "yes" : "no") + --eval $code_object`), stderr=STDERR), + "w", STDOUT) + in = io.in try - serialize(io, quote + serialize(in, quote empty!(Base.LOAD_PATH) append!(Base.LOAD_PATH, $LOAD_PATH) empty!(Base.LOAD_CACHE_PATH) @@ -619,22 +620,21 @@ function create_expr_cache(input::String, output::String, concrete_deps::Vector{ end) source = source_path(nothing) if source !== nothing - serialize(io, quote + serialize(in, quote task_local_storage()[:SOURCE_PATH] = $(source) end) end - serialize(io, :(Base.include($(abspath(input))))) + serialize(in, :(Base.include($(abspath(input))))) if source !== nothing - serialize(io, :(delete!(task_local_storage(), :SOURCE_PATH))) + serialize(in, :(delete!(task_local_storage(), :SOURCE_PATH))) end - close(io) - wait(pobj) - return pobj - catch - kill(pobj) - close(io) - rethrow() + close(in) + catch ex + close(in) + process_running(io) && Timer(t -> kill(io), 5.0) # wait a short time before killing the process to give it a chance to clean up on its own first + rethrow(ex) end + return io end compilecache(mod::Symbol) = compilecache(string(mod)) diff --git a/base/process.jl b/base/process.jl index fa1cce13f27a9..ac37796026607 100644 --- a/base/process.jl +++ b/base/process.jl @@ -577,38 +577,45 @@ the process's standard input and `stdio` optionally specifies the process's stan stream. """ function open(cmds::AbstractCmd, mode::AbstractString="r", other::Redirectable=DevNull) - if mode == "r" + if mode == "r+" || mode == "w+" + other === DevNull || throw(ArgumentError("no other stream for mode rw+")) + in = Pipe() + out = Pipe() + processes = spawn(cmds, (in,out,STDERR)) + close(in.out) + close(out.in) + elseif mode == "r" in = other - out = io = Pipe() + out = Pipe() processes = spawn(cmds, (in,out,STDERR)) close(out.in) elseif mode == "w" - in = io = Pipe() + in = Pipe() out = other processes = spawn(cmds, (in,out,STDERR)) close(in.out) else throw(ArgumentError("mode must be \"r\" or \"w\", not \"$mode\"")) end - return (io, processes) + return processes end """ open(f::Function, command, mode::AbstractString="r", stdio=DevNull) -Similar to `open(command, mode, stdio)`, but calls `f(stream)` on the resulting read or -write stream, then closes the stream and waits for the process to complete. Returns the -value returned by `f`. +Similar to `open(command, mode, stdio)`, but calls `f(stream)` on the resulting process +stream, then closes the input stream and waits for the process to complete. +Returns the value returned by `f`. """ function open(f::Function, cmds::AbstractCmd, args...) - io, P = open(cmds, args...) + P = open(cmds, args...) ret = try - f(io) - catch + f(P) + catch e kill(P) - rethrow() + rethrow(e) finally - close(io) + close(P.in) end success(P) || pipeline_error(P) return ret @@ -623,15 +630,14 @@ Starts running a command asynchronously, and returns a tuple (stdout,stdin,proce output stream and input stream of the process, and the process object itself. """ function readandwrite(cmds::AbstractCmd) - in = Pipe() - out, processes = open(cmds, "r", in) - (out, in, processes) + processes = open(cmds, "r+") + return (processes.out, processes.in, processes) end function read(cmd::AbstractCmd, stdin::Redirectable=DevNull) - out, procs = open(cmd, "r", stdin) - bytes = read(out) - !success(procs) && pipeline_error(procs) + procs = open(cmd, "r", stdin) + bytes = read(procs.out) + success(procs) || pipeline_error(procs) return bytes end @@ -656,9 +662,17 @@ function run(cmds::AbstractCmd, args...) success(ps) ? nothing : pipeline_error(ps) end -const SIGPIPE = 13 +# some common signal numbers that are usually available on all platforms +# and might be useful as arguments to `kill` or testing against `Process.termsignal` +const SIGHUP = 1 +const SIGINT = 2 +const SIGQUIT = 3 # !windows +const SIGKILL = 9 +const SIGPIPE = 13 # !windows +const SIGTERM = 15 + function test_success(proc::Process) - assert(process_exited(proc)) + @assert process_exited(proc) if proc.exitcode < 0 #TODO: this codepath is not currently tested throw(UVError("could not start process $(string(proc.cmd))", proc.exitcode)) @@ -668,8 +682,7 @@ end function success(x::Process) wait(x) - kill(x) - test_success(x) + return test_success(x) end success(procs::Vector{Process}) = mapreduce(success, &, procs) success(procs::ProcessChain) = success(procs.processes) @@ -705,8 +718,6 @@ function pipeline_error(procs::ProcessChain) error(msg) end -_jl_kill(p::Process, signum::Integer) = ccall(:uv_process_kill, Int32, (Ptr{Void},Int32), p.handle, signum) - """ kill(p::Process, signum=SIGTERM) @@ -715,14 +726,14 @@ Send a signal to a process. The default is to terminate the process. function kill(p::Process, signum::Integer) if process_running(p) @assert p.handle != C_NULL - _jl_kill(p, signum) + ccall(:uv_process_kill, Int32, (Ptr{Void}, Int32), p.handle, signum) else Int32(-1) end end kill(ps::Vector{Process}) = map(kill, ps) kill(ps::ProcessChain) = map(kill, ps.processes) -kill(p::Process) = kill(p, 15) #SIGTERM +kill(p::Process) = kill(p, SIGTERM) function _contains_newline(bufptr::Ptr{Void}, len::Int32) return (ccall(:memchr, Ptr{Void}, (Ptr{Void},Int32,Csize_t), bufptr, '\n', len) != C_NULL) diff --git a/examples/clustermanager/simple/UnixDomainCM.jl b/examples/clustermanager/simple/UnixDomainCM.jl index d1e27e2c6fa2c..e3a1f7f9d350a 100644 --- a/examples/clustermanager/simple/UnixDomainCM.jl +++ b/examples/clustermanager/simple/UnixDomainCM.jl @@ -13,10 +13,10 @@ function launch(manager::UnixDomainCM, params::Dict, launched::Array, c::Conditi sockname = tempname() try cmd = `$(params[:exename]) --startup-file=no $(@__FILE__) udwrkr $sockname $cookie` - io, pobj = open(cmd, "r") + pobj = open(cmd) wconfig = WorkerConfig() - wconfig.userdata = Dict(:sockname=>sockname, :io=>io, :process=>pobj) + wconfig.userdata = Dict(:sockname=>sockname, :io=>pobj.out, :process=>pobj) push!(launched, wconfig) notify(c) catch e diff --git a/test/distributed_exec.jl b/test/distributed_exec.jl index 64f28c1e379e7..87247a89ff6c3 100644 --- a/test/distributed_exec.jl +++ b/test/distributed_exec.jl @@ -1307,11 +1307,11 @@ function Base.launch(manager::ErrorSimulator, params::Dict, launched::Array, c:: else error("Unknown mode") end - io, pobj = open(pipeline(detach(setenv(cmd, dir=dir)); stderr=STDERR), "r") + io = open(detach(setenv(cmd, dir=dir))) wconfig = WorkerConfig() - wconfig.process = pobj - wconfig.io = io + wconfig.process = io + wconfig.io = io.out push!(launched, wconfig) notify(c) end diff --git a/test/spawn.jl b/test/spawn.jl index f6c514c21bc1a..84cccddbce632 100644 --- a/test/spawn.jl +++ b/test/spawn.jl @@ -242,26 +242,26 @@ let fname = tempname() function thrash(handle::Ptr{Void}) # Kill the memory, but write a nice low value in the libuv type field to # trigger the right code path - ccall(:memset,Ptr{Void},(Ptr{Void},Cint,Csize_t),handle,0xee,3*sizeof(Ptr{Void})) - unsafe_store!(convert(Ptr{Cint},handle+2*sizeof(Ptr{Void})),15) + ccall(:memset, Ptr{Void}, (Ptr{Void}, Cint, Csize_t), handle, 0xee, 3 * sizeof(Ptr{Void})) + unsafe_store!(convert(Ptr{Cint}, handle + 2 * sizeof(Ptr{Void})), 15) nothing end OLD_STDERR = STDERR - redirect_stderr(open("$(escape_string(fname))","w")) + redirect_stderr(open("$(escape_string(fname))", "w")) # Usually this would be done by GC. Do it manually, to make the failure # case more reliable. oldhandle = OLD_STDERR.handle OLD_STDERR.status = Base.StatusClosing OLD_STDERR.handle = C_NULL - ccall(:uv_close,Void,(Ptr{Void},Ptr{Void}),oldhandle,cfunction(thrash,Void,(Ptr{Void},))) + ccall(:uv_close, Void, (Ptr{Void}, Ptr{Void}), oldhandle, cfunction(thrash, Void, (Ptr{Void},))) sleep(1) import Base.zzzInvalidIdentifier """ try - (in,p) = open(pipeline(`$exename --startup-file=no`, stderr=STDERR), "w") - write(in,cmd) - close(in) - wait(p) + io = open(pipeline(`$exename --startup-file=no`, stderr=STDERR), "w") + write(io, cmd) + close(io) + wait(io) catch error("IOStream redirect failed. Child stderr was \n$(readstring(fname))\n") finally diff --git a/test/topology.jl b/test/topology.jl index c3c92c51a7a1f..8e5cbcaf93459 100644 --- a/test/topology.jl +++ b/test/topology.jl @@ -41,12 +41,13 @@ function Base.launch(manager::TopoTestManager, params::Dict, launched::Array, c: exename = params[:exename] exeflags = params[:exeflags] + cmd = `$exename $exeflags --bind-to $(Base.Distributed.LPROC.bind_addr) --worker $(Base.cluster_cookie())` + cmd = pipeline(detach(setenv(cmd, dir=dir))) for i in 1:manager.np - io, pobj = open(pipeline(detach( - setenv(`$exename $exeflags --bind-to $(Base.Distributed.LPROC.bind_addr) --worker $(Base.cluster_cookie())`, dir=dir)); stderr=STDERR), "r") + io = open(cmd) wconfig = WorkerConfig() - wconfig.process = pobj - wconfig.io = io + wconfig.process = io + wconfig.io = io.out wconfig.ident = i wconfig.connect_idents = collect(i+2:2:manager.np) push!(launched, wconfig) From 505dec55acf6e3623bbaf38e69aff27ec5cae7d1 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 26 Aug 2015 18:46:17 -0400 Subject: [PATCH 0646/1534] add deprecation mechanism for (io,p) = open(cmd) --- base/deprecated.jl | 13 +++++++++++++ base/process.jl | 13 +++++++++++++ 2 files changed, 26 insertions(+) diff --git a/base/deprecated.jl b/base/deprecated.jl index 442a01cac7bd9..b29917a958919 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1324,5 +1324,18 @@ end # END 0.6 deprecations +# BEGIN 0.7 deprecations + +# 12807 +start(::Union{Process, ProcessChain}) = 1 +done(::Union{Process, ProcessChain}, i::Int) = (i == 3) +next(p::Union{Process, ProcessChain}, i::Int) = (getindex(p, i), i + 1) +@noinline function getindex(p::Union{Process, ProcessChain}, i::Int) + depwarn("open(cmd) now returns only a Process<:IO object", :getindex) + return i == 1 ? getfield(p, p.openstream) : p +end + +# END 0.7 deprecations + # BEGIN 1.0 deprecations # END 1.0 deprecations diff --git a/base/process.jl b/base/process.jl index ac37796026607..d0fefa923df3e 100644 --- a/base/process.jl +++ b/base/process.jl @@ -315,6 +315,7 @@ mutable struct Process <: AbstractPipe termsignal::Int32 exitnotify::Condition closenotify::Condition + openstream::Symbol # for open(cmd) deprecation function Process(cmd::Cmd, handle::Ptr{Void}, in::Union{Redirectable, Ptr{Void}}, out::Union{Redirectable, Ptr{Void}}, @@ -344,7 +345,9 @@ struct ProcessChain <: AbstractPipe in::Redirectable out::Redirectable err::Redirectable + openstream::Symbol # for open(cmd) deprecation ProcessChain(stdios::StdIOSet) = new(Process[], stdios[1], stdios[2], stdios[3]) + ProcessChain(chain::ProcessChain, openstream::Symbol) = new(chain.processes, chain.in, chain.out, chain.err, openstream) # for open(cmd) deprecation end pipe_reader(p::ProcessChain) = p.out pipe_writer(p::ProcessChain) = p.in @@ -589,11 +592,21 @@ function open(cmds::AbstractCmd, mode::AbstractString="r", other::Redirectable=D out = Pipe() processes = spawn(cmds, (in,out,STDERR)) close(out.in) + if isa(processes, ProcessChain) # for open(cmd) deprecation + processes = ProcessChain(processes, :out) + else + processes.openstream = :out + end elseif mode == "w" in = Pipe() out = other processes = spawn(cmds, (in,out,STDERR)) close(in.out) + if isa(processes, ProcessChain) # for open(cmd) deprecation + processes = ProcessChain(processes, :in) + else + processes.openstream = :in + end else throw(ArgumentError("mode must be \"r\" or \"w\", not \"$mode\"")) end From 49c1910d8db06b820c4cb26cc7255c5870bfe070 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 2 May 2017 17:55:11 -0400 Subject: [PATCH 0647/1534] fix bug in inference assuming that iteration always calls into Main.Base most notably in Core.Inference, this may cause the addition of bad edges and suboptimal results --- base/inference.jl | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 22adbe4b00402..a51853631da57 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -328,9 +328,9 @@ _topmod(sv::InferenceState) = _topmod(sv.mod) _topmod(m::Module) = ccall(:jl_base_relative_to, Any, (Any,), m)::Module function istopfunction(topmod, f::ANY, sym) - if isdefined(Main, :Base) && isdefined(Main.Base, sym) && f === getfield(Main.Base, sym) + if isdefined(Main, :Base) && isdefined(Main.Base, sym) && isconst(Main.Base, sym) && f === getfield(Main.Base, sym) return true - elseif isdefined(topmod, sym) && f === getfield(topmod, sym) + elseif isdefined(topmod, sym) && isconst(topmod, sym) && f === getfield(topmod, sym) return true end return false @@ -1451,21 +1451,26 @@ function precise_container_type(arg, typ, vtypes::VarTable, sv) elseif tti0 <: Array return Any[Vararg{eltype(tti0)}] else - return Any[Vararg{abstract_iteration(tti0, vtypes, sv)}] + return Any[abstract_iteration(tti0, vtypes, sv)] end end # simulate iteration protocol on container type up to fixpoint function abstract_iteration(itertype, vtypes::VarTable, sv) - if !isdefined(Main, :Base) || !isdefined(Main.Base, :start) || !isdefined(Main.Base, :next) - return Any + tm = _topmod(sv) + if !isdefined(tm, :start) || !isdefined(tm, :next) || !isconst(tm, :start) || !isconst(tm, :next) + return Vararg{Any} end - statetype = abstract_call(Main.Base.start, (), Any[Const(Main.Base.start), itertype], vtypes, sv) + startf = getfield(tm, :start) + nextf = getfield(tm, :next) + statetype = abstract_call(startf, (), Any[Const(startf), itertype], vtypes, sv) + statetype === Bottom && return Bottom valtype = Bottom while valtype !== Any - nt = abstract_call(Main.Base.next, (), Any[Const(Main.Base.next), itertype, statetype], vtypes, sv) + nt = abstract_call(nextf, (), Any[Const(nextf), itertype, statetype], vtypes, sv) + nt = widenconst(nt) if !isa(nt, DataType) || !(nt <: Tuple) || isvatuple(nt) || length(nt.parameters) != 2 - return Any + return Vararg{Any} end if nt.parameters[1] <: valtype && nt.parameters[2] <: statetype break @@ -1473,7 +1478,7 @@ function abstract_iteration(itertype, vtypes::VarTable, sv) valtype = tmerge(valtype, nt.parameters[1]) statetype = tmerge(statetype, nt.parameters[2]) end - return valtype + return Vararg{valtype} end # do apply(af, fargs...), where af is a function value From 0250e4f791a13331057064668e76c1e135a151cc Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 2 May 2017 18:07:11 -0400 Subject: [PATCH 0648/1534] inference: improve function call signatures ensures that abstract_iteration gets better information, and that specialization can compile these methods ahead-of-time --- base/inference.jl | 43 ++++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index a51853631da57..9dab296025988 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -1404,7 +1404,7 @@ function abstract_call_gf_by_type(f::ANY, atype::ANY, sv::InferenceState) end # determine whether `ex` abstractly evals to constant `c` -function abstract_evals_to_constant(ex, c::ANY, vtypes, sv) +function abstract_evals_to_constant(ex::ANY, c::ANY, vtypes::VarTable, sv::InferenceState) av = abstract_eval(ex, vtypes, sv) return isa(av,Const) && av.val === c end @@ -1413,14 +1413,19 @@ end # if the expression constructs a container (e.g. `svec(x,y,z)`), # refine its type to an array of element types. # Union of Tuples of the same length is converted to Tuple of Unions. -# returns an array of types, or `nothing`. -function precise_container_type(arg, typ, vtypes::VarTable, sv) +# returns an array of types +function precise_container_type(arg::ANY, typ::ANY, vtypes::VarTable, sv::InferenceState) + if isa(typ, Const) + val = typ.val + if isa(val, SimpleVector) || isa(val, Tuple) + return Any[ abstract_eval_constant(x) for x in val ] + end + end + tti0 = widenconst(typ) tti = unwrap_unionall(tti0) - if isa(typ, Const) && (isa(typ.val, SimpleVector) || isa(typ.val, Tuple)) - return Any[ abstract_eval_constant(x) for x in typ.val ] - elseif isa(arg, Expr) && arg.head === :call && (abstract_evals_to_constant(arg.args[1], svec, vtypes, sv) || - abstract_evals_to_constant(arg.args[1], tuple, vtypes, sv)) + if isa(arg, Expr) && arg.head === :call && (abstract_evals_to_constant(arg.args[1], svec, vtypes, sv) || + abstract_evals_to_constant(arg.args[1], tuple, vtypes, sv)) aa = arg.args result = Any[ (isa(aa[j],Expr) ? aa[j].typ : abstract_eval(aa[j],vtypes,sv)) for j=2:length(aa) ] if _any(isvarargtype, result) @@ -1451,12 +1456,12 @@ function precise_container_type(arg, typ, vtypes::VarTable, sv) elseif tti0 <: Array return Any[Vararg{eltype(tti0)}] else - return Any[abstract_iteration(tti0, vtypes, sv)] + return Any[abstract_iteration(typ, vtypes, sv)] end end # simulate iteration protocol on container type up to fixpoint -function abstract_iteration(itertype, vtypes::VarTable, sv) +function abstract_iteration(itertype::ANY, vtypes::VarTable, sv::InferenceState) tm = _topmod(sv) if !isdefined(tm, :start) || !isdefined(tm, :next) || !isconst(tm, :start) || !isconst(tm, :next) return Vararg{Any} @@ -1482,7 +1487,7 @@ function abstract_iteration(itertype, vtypes::VarTable, sv) end # do apply(af, fargs...), where af is a function value -function abstract_apply(af::ANY, fargs, aargtypes::Vector{Any}, vtypes::VarTable, sv) +function abstract_apply(af::ANY, fargs::Vector{Any}, aargtypes::Vector{Any}, vtypes::VarTable, sv::InferenceState) res = Union{} nargs = length(fargs) assert(nargs == length(aargtypes)) @@ -1625,14 +1630,10 @@ function _typename(a::Union) ta === tb ? tb : (ta === Any || tb === Any) ? Any : Union{} end _typename(union::UnionAll) = _typename(union.body) -function typename_static(t) - # N.B.: typename maps type equivalence classes to a single value - if isa(t, Const) || isType(t) - return _typename(isa(t, Const) ? t.val : t.parameters[1]) - else - return Any - end -end + +# N.B.: typename maps type equivalence classes to a single value +typename_static(t::Const) = _typename(t.val) +typename_static(t::ANY) = isType(t) ? _typename(t.parameters[1]) : Any function abstract_call(f::ANY, fargs::Union{Tuple{},Vector{Any}}, argtypes::Vector{Any}, vtypes::VarTable, sv::InferenceState) if f === _apply @@ -1842,11 +1843,7 @@ function abstract_call(f::ANY, fargs::Union{Tuple{},Vector{Any}}, argtypes::Vect if istopfunction(tm, f, :promote_type) || istopfunction(tm, f, :typejoin) return Type elseif length(argtypes) == 2 && istopfunction(tm, f, :typename) - t = argtypes[2] - if isa(t, Const) || isType(t) - return typename_static(t) - end - return Any + return typename_static(argtypes[2]) end if sv.params.inlining From 82eb74c8effa85c7398b42dfa38aa1accb9c56a2 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Tue, 2 May 2017 19:00:45 -0700 Subject: [PATCH 0649/1534] upgrade libssl on travis to hopefully fix curl certificate issues have only seen this on release-0.5 so far, but could hit master or release-0.6 too if they need to build from a clean cache --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 07ca0927c7215..710b2662d7093 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,7 @@ matrix: sources: - ubuntu-toolchain-r-test packages: + - libssl1.0.0 - bar - time - binutils @@ -29,6 +30,7 @@ matrix: sources: - ubuntu-toolchain-r-test packages: + - libssl1.0.0 - bar - time - g++-5 From 0ab5cc0e46a169b43918fdee710f2c91e2368afc Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Wed, 3 May 2017 10:08:46 -0700 Subject: [PATCH 0650/1534] Set RPATH for private libdirs on FreeBSD --- Make.inc | 1 + Makefile | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Make.inc b/Make.inc index 024d4f63cda91..498394a37d95b 100644 --- a/Make.inc +++ b/Make.inc @@ -1,4 +1,5 @@ # -*- mode: makefile-gmake -*- +# vi:syntax=make ## Note: ## It is generally preferable to change these options, for diff --git a/Makefile b/Makefile index 0a14b11101aa6..dda792566108a 100644 --- a/Makefile +++ b/Makefile @@ -405,7 +405,7 @@ ifeq ($(OS), Darwin) install_name_tool -rpath @executable_path/$(build_private_libdir_rel) @executable_path/$(private_libdir_rel) $$julia; \ install_name_tool -add_rpath @executable_path/$(build_libdir_rel) @executable_path/$(libdir_rel) $$julia; \ done -else ifeq ($(OS), Linux) +else ifneq (,$(findstring $(OS),Linux FreeBSD)) for julia in $(DESTDIR)$(bindir)/julia* ; do \ patchelf --set-rpath '$$ORIGIN/$(private_libdir_rel):$$ORIGIN/$(libdir_rel)' $$julia; \ done From 253fa74996c19129dfa326de141e479a9e3150df Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Wed, 3 May 2017 14:36:06 -0500 Subject: [PATCH 0651/1534] Make reshape(::Bitarray,...) type stable (#21670) This works around some of the performance regressions flagged in #20993. The instability itself is not new nor is it the cause of the regression. The trouble is just that there are a few more inlined functions now, each of which needs a dynamic dispatch. It is worth noting that 0.6 (with this patch) is significantly faster than 0.5 (with this patch). I measure an improvement of ~30%. --- base/bitarray.jl | 7 +++++-- test/bitarray.jl | 4 ++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/base/bitarray.jl b/base/bitarray.jl index 105d590c55f3a..265cf65b3614c 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -472,10 +472,13 @@ function copy!(dest::BitArray, src::Array) return unsafe_copy!(dest, 1, src, 1, length(src)) end -function reshape(B::BitArray, dims::NTuple{N,Int}) where N +function reshape(B::BitArray{N}, dims::NTuple{N,Int}) where N + return dims == size(B) ? B : _bitreshape(B, dims) +end +reshape(B::BitArray, dims::Tuple{Vararg{Int}}) = _bitreshape(B, dims) +function _bitreshape(B::BitArray, dims::NTuple{N,Int}) where N prod(dims) == length(B) || throw(DimensionMismatch("new dimensions $(dims) must be consistent with array size $(length(B))")) - dims == size(B) && return B Br = BitArray{N}(ntuple(i->0,Val{N})...) Br.chunks = B.chunks Br.len = prod(dims) diff --git a/test/bitarray.jl b/test/bitarray.jl index 9a0541ef7b92c..3ae22cb0beae3 100644 --- a/test/bitarray.jl +++ b/test/bitarray.jl @@ -143,6 +143,10 @@ timesofar("conversions") @check_bit_operation reshape(b1, (n2,n1)) BitMatrix @test_throws DimensionMismatch reshape(b1, (1,n1)) + @test @inferred(reshape(b1, n1*n2)) == @inferred(reshape(b1, (n1*n2,))) == @inferred(reshape(b1, Val{1})) == @inferred(reshape(b1, :)) + @test @inferred(reshape(b1, n1, n2)) === @inferred(reshape(b1, Val{2})) === b1 + @test @inferred(reshape(b1, n2, :)) == @inferred(reshape(b1, (n2, n1))) != @inferred(reshape(b1, Val{2})) + b1 = bitrand(s1, s2, s3, s4) @check_bit_operation reshape(b1, (s3,s1,s2,s4)) BitArray{4} @test_throws DimensionMismatch reshape(b1, (1,n1)) From a9fd67d21ed1816cfc108390cf3853377f2b915c Mon Sep 17 00:00:00 2001 From: kshyatt Date: Tue, 2 May 2017 16:02:06 -0700 Subject: [PATCH 0652/1534] More examples, clarification for git docs --- base/libgit2/libgit2.jl | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/base/libgit2/libgit2.jl b/base/libgit2/libgit2.jl index 460639d9a4872..5594fb2a8e491 100644 --- a/base/libgit2/libgit2.jl +++ b/base/libgit2/libgit2.jl @@ -204,6 +204,23 @@ end Returns `true` if `a`, a [`GitHash`](@ref) in string form, is an ancestor of `b`, a [`GitHash`](@ref) in string form. + +# Example + +```julia +julia> repo = LibGit2.GitRepo(repo_path); + +julia> LibGit2.add!(repo, test_file1); + +julia> commit_oid1 = LibGit2.commit(repo, "commit1"); + +julia> LibGit2.add!(repo, test_file2); + +julia> commit_oid2 = LibGit2.commit(repo, "commit2"); + +julia> LibGit2.is_ancestor_of(string(commit_oid1), string(commit_oid2), repo) +true +``` """ function is_ancestor_of(a::AbstractString, b::AbstractString, repo::GitRepo) A = revparseid(repo, a) @@ -336,6 +353,7 @@ end Checkout a new git branch in the `repo` repository. `commit` is the [`GitHash`](@ref), in string form, which will be the start of the new branch. +If `commit` is an empty string, the current HEAD will be used. The keyword arguments are: * `track::AbstractString=""`: the name of the @@ -348,6 +366,13 @@ The keyword arguments are: finishes the branch head will be set as the HEAD of `repo`. Equivalent to `git checkout [-b|-B] [] [--track ]`. + +# Example + +```julia +repo = LibGit2.GitRepo(repo_path) +LibGit2.branch!(repo, "new_branch", set_head=false) +``` """ function branch!(repo::GitRepo, branch_name::AbstractString, commit::AbstractString = ""; # start point From 9b7584428b8adce42988d83d6f025975aa05edf4 Mon Sep 17 00:00:00 2001 From: kshyatt Date: Mon, 1 May 2017 18:02:12 -0700 Subject: [PATCH 0653/1534] Examples for set_remote_url, xrefs --- base/libgit2/libgit2.jl | 11 +++++++++++ base/libgit2/repository.jl | 12 ++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/base/libgit2/libgit2.jl b/base/libgit2/libgit2.jl index 460639d9a4872..d400278611f0c 100644 --- a/base/libgit2/libgit2.jl +++ b/base/libgit2/libgit2.jl @@ -215,6 +215,17 @@ end Set the `url` for `remote` for the git repository `repo`. The default name of the remote is `"origin"`. + +# Examples + +```julia +repo_path = joinpath("test_directory", "Example") +repo = LibGit2.init(repo_path) +url1 = "https://github.com/JuliaLang/Example.jl" +LibGit2.set_remote_url(repo, url1, remote="upstream") +url2 = "https://github.com/JuliaLang/Example2.jl" +LibGit2.set_remote_url(repo_path, url2, remote="upstream2") +``` """ function set_remote_url(repo::GitRepo, url::AbstractString; remote::AbstractString="origin") with(GitConfig, repo) do cfg diff --git a/base/libgit2/repository.jl b/base/libgit2/repository.jl index 9ea6e2a8be3bb..020d0ffbeadf2 100644 --- a/base/libgit2/repository.jl +++ b/base/libgit2/repository.jl @@ -92,11 +92,11 @@ end GitObject(repo::GitRepo, hash::AbstractGitHash) GitObject(repo::GitRepo, spec::AbstractString) -Return the specified object (`GitCommit`, `GitBlob`, `GitTree` or `GitTag`) from `repo` +Return the specified object ([`GitCommit`](@ref), [`GitBlob`](@ref), [`GitTree`](@ref) or [`GitTag`](@ref)) from `repo` specified by `hash`/`spec`. - `hash` is a full (`GitHash`) or partial (`GitShortHash`) hash. -- `spec` is a textual specification: see https://git-scm.com/docs/git-rev-parse.html#_specifying_revisions for a full list. +- `spec` is a textual specification: see [the git docs](https://git-scm.com/docs/git-rev-parse.html#_specifying_revisions) for a full list. """ GitObject for T in (:GitCommit, :GitBlob, :GitTree, :GitTag) @@ -107,7 +107,7 @@ for T in (:GitCommit, :GitBlob, :GitTree, :GitTag) Return a `$T` object from `repo` specified by `hash`/`spec`. - `hash` is a full (`GitHash`) or partial (`GitShortHash`) hash. -- `spec` is a textual specification: see https://git-scm.com/docs/git-rev-parse.html#_specifying_revisions for a full list. +- `spec` is a textual specification: see [the git docs](https://git-scm.com/docs/git-rev-parse.html#_specifying_revisions) for a full list. """ $T end @@ -155,7 +155,7 @@ Returns the location of the "git" files of `repo`: - for normal repositories, this is the location of the `.git` folder. - for bare repositories, this is the location of the repository itself. -See also `workdir`, `path` +See also [`workdir`](@ref), [`path`](@ref). """ function gitdir(repo::GitRepo) return unsafe_string(ccall((:git_repository_path, :libgit2), Cstring, @@ -174,7 +174,7 @@ repositories. some cases: e.g. if either the `core.worktree` configuration variable or the `GIT_WORK_TREE` environment variable is set. -See also `gitdir`, `path` +See also [`gitdir`](@ref), [`path`](@ref). """ function workdir(repo::GitRepo) sptr = ccall((:git_repository_workdir, :libgit2), Cstring, @@ -193,7 +193,7 @@ The base file path of the repository `repo`. more details). - for bare repositories, this is the location of the "git" files. -See also `gitdir`, `workdir`. +See also [`gitdir`](@ref), [`workdir`](@ref). """ function path(repo::GitRepo) d = gitdir(repo) From ff73d57f12ec6193cb8e3103e9ee31fa9aeb5269 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Thu, 4 May 2017 10:50:34 -0500 Subject: [PATCH 0654/1534] Switch to dash for list default --- doc/src/manual/documentation.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/src/manual/documentation.md b/doc/src/manual/documentation.md index 85b4fef5a0e41..390c45993432f 100644 --- a/doc/src/manual/documentation.md +++ b/doc/src/manual/documentation.md @@ -69,15 +69,15 @@ As in the example above, we recommend following some simple conventions when wri description of the function's purpose. An argument list would only repeat information already provided elsewhere. However, providing an argument list can be a good idea for complex functions with many arguments (in particular keyword arguments). In that case, insert it after the general - description of the function, under an `# Arguments` header, with one `*` bullet for each argument. + description of the function, under an `# Arguments` header, with one `-` bullet for each argument. The list should mention the types and default values (if any) of the arguments: ```julia """ ... # Arguments - * `n::Integer`: the number of elements to compute. - * `dim::Integer=1`: the dimensions along which to perform the computation. + - `n::Integer`: the number of elements to compute. + - `dim::Integer=1`: the dimensions along which to perform the computation. ... """ ``` From c21e77aa10d1b567150cd6f337e4a5cf91cdfdfd Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Thu, 4 May 2017 15:30:47 -0500 Subject: [PATCH 0655/1534] [ci skip] Replace visually confusing asterisks --- base/statistics.jl | 2 +- base/summarysize.jl | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/base/statistics.jl b/base/statistics.jl index 382f7172fad6e..0eff0d321f4c5 100644 --- a/base/statistics.jl +++ b/base/statistics.jl @@ -733,7 +733,7 @@ for `k = 1:n` where `n = length(v)`. This corresponds to Definition 7 of Hyndman handling of missing data, the `DataArrays.jl` package is recommended. `quantile` will throw an `ArgumentError` in the presence of `NaN` values in the data array. -* Hyndman, R.J and Fan, Y. (1996) "Sample Quantiles in Statistical Packages", +- Hyndman, R.J and Fan, Y. (1996) "Sample Quantiles in Statistical Packages", *The American Statistician*, Vol. 50, No. 4, pp. 361-365 """ quantile(v::AbstractVector, p; sorted::Bool=false) = diff --git a/base/summarysize.jl b/base/summarysize.jl index a7c0e216e19b1..b7e320529527a 100644 --- a/base/summarysize.jl +++ b/base/summarysize.jl @@ -15,9 +15,9 @@ end Compute the amount of memory used by all unique objects reachable from the argument. # Keyword Arguments -* `exclude`: specifies the types of objects to exclude from the traversal. -* `chargeall`: specifies the types of objects to always charge the size of all of their fields, - even if those fields would normally be excluded. +- `exclude`: specifies the types of objects to exclude from the traversal. +- `chargeall`: specifies the types of objects to always charge the size of all of their + fields, even if those fields would normally be excluded. """ function summarysize(obj::ANY; exclude::ANY = Union{DataType, TypeName, Method}, From b1d0897dddd3ecbf19a55958d26cdc260ad707f8 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Thu, 4 May 2017 15:32:08 -0500 Subject: [PATCH 0656/1534] [ci skip] Word wrap at 92-characters --- base/distributed/managers.jl | 47 ++++++++++++++------------- base/docs/helpdb/Base.jl | 13 +++++--- base/linalg/arnoldi.jl | 11 ++++--- base/process.jl | 61 +++++++++++++++++------------------- base/socket.jl | 4 +-- base/strings/utf8proc.jl | 13 ++++---- 6 files changed, 74 insertions(+), 75 deletions(-) diff --git a/base/distributed/managers.jl b/base/distributed/managers.jl index 7591f51292cf2..269a69033f12d 100644 --- a/base/distributed/managers.jl +++ b/base/distributed/managers.jl @@ -58,48 +58,47 @@ location on each node, or to be available via a shared file system. A machine specification is either a string `machine_spec` or a tuple - `(machine_spec, count)`. -`machine_spec` is a string of the form `[user@]host[:port] [bind_addr[:port]]`. `user` defaults -to current user, `port` to the standard ssh port. If `[bind_addr[:port]]` is specified, other -workers will connect to this worker at the specified `bind_addr` and `port`. +`machine_spec` is a string of the form `[user@]host[:port] [bind_addr[:port]]`. `user` +defaults to current user, `port` to the standard ssh port. If `[bind_addr[:port]]` is +specified, other workers will connect to this worker at the specified `bind_addr` and +`port`. -`count` is the number of workers to be launched on the specified host. If specified as `:auto` -it will launch as many workers as the number of cores on the specific host. +`count` is the number of workers to be launched on the specified host. If specified as +`:auto` it will launch as many workers as the number of cores on the specific host. Keyword arguments: * `tunnel`: if `true` then SSH tunneling will be used to connect to the worker from the - master process. Default is `false`. + master process. Default is `false`. -* `sshflags`: specifies additional ssh options, e.g. - ```sshflags=\`-i /home/foo/bar.pem\` ``` +* `sshflags`: specifies additional ssh options, e.g. ```sshflags=\`-i /home/foo/bar.pem\```` -* `max_parallel`: specifies the maximum number of workers connected to in parallel at a host. - Defaults to 10. +* `max_parallel`: specifies the maximum number of workers connected to in parallel at a + host. Defaults to 10. * `dir`: specifies the working directory on the workers. Defaults to the host's current - directory (as found by `pwd()`) + directory (as found by `pwd()`) - * `enable_threaded_blas`: if `true` then BLAS will run on multiple threads in added - processes. Default is `false`. +* `enable_threaded_blas`: if `true` then BLAS will run on multiple threads in added + processes. Default is `false`. * `exename`: name of the `julia` executable. Defaults to `"\$JULIA_HOME/julia"` or - `"\$JULIA_HOME/julia-debug"` as the case may be. + `"\$JULIA_HOME/julia-debug"` as the case may be. * `exeflags`: additional flags passed to the worker processes. -* `topology`: Specifies how the workers connect to each other. Sending a message - between unconnected workers results in an error. +* `topology`: Specifies how the workers connect to each other. Sending a message between + unconnected workers results in an error. - + `topology=:all_to_all` : All processes are connected to each other. - This is the default. + + `topology=:all_to_all`: All processes are connected to each other. The default. - + `topology=:master_slave` : Only the driver process, i.e. `pid` 1 connects to the - workers. The workers do not connect to each other. + + `topology=:master_slave`: Only the driver process, i.e. `pid` 1 connects to the + workers. The workers do not connect to each other. - + `topology=:custom` : The `launch` method of the cluster manager specifies the - connection topology via fields `ident` and `connect_idents` in - `WorkerConfig`. A worker with a cluster manager identity `ident` - will connect to all workers specified in `connect_idents`. + + `topology=:custom`: The `launch` method of the cluster manager specifies the + connection topology via fields `ident` and `connect_idents` in `WorkerConfig`. + A worker with a cluster manager identity `ident` will connect to all workers specified + in `connect_idents`. Environment variables : diff --git a/base/docs/helpdb/Base.jl b/base/docs/helpdb/Base.jl index e0da5a28c17ce..2f71cfdfc57bf 100644 --- a/base/docs/helpdb/Base.jl +++ b/base/docs/helpdb/Base.jl @@ -1300,20 +1300,23 @@ cotd Block the current task until some event occurs, depending on the type of the argument: -* [`RemoteChannel`](@ref) : Wait for a value to become available on the specified remote channel. +* [`RemoteChannel`](@ref) : Wait for a value to become available on the specified remote + channel. * [`Future`](@ref) : Wait for a value to become available for the specified future. * [`Channel`](@ref): Wait for a value to be appended to the channel. * [`Condition`](@ref): Wait for [`notify`](@ref) on a condition. * `Process`: Wait for a process or process chain to exit. The `exitcode` field of a process can be used to determine success or failure. -* [`Task`](@ref): Wait for a `Task` to finish, returning its result value. If the task fails with an - exception, the exception is propagated (re-thrown in the task that called `wait`). -* `RawFD`: Wait for changes on a file descriptor (see [`poll_fd`](@ref) for keyword arguments and return code) +* [`Task`](@ref): Wait for a `Task` to finish, returning its result value. If the task fails + with an exception, the exception is propagated (re-thrown in the task that called `wait`). +* `RawFD`: Wait for changes on a file descriptor (see [`poll_fd`](@ref) for keyword + arguments and return code) If no argument is passed, the task blocks for an undefined period. A task can only be restarted by an explicit call to [`schedule`](@ref) or [`yieldto`](@ref). -Often `wait` is called within a `while` loop to ensure a waited-for condition is met before proceeding. +Often `wait` is called within a `while` loop to ensure a waited-for condition is met before +proceeding. """ wait diff --git a/base/linalg/arnoldi.jl b/base/linalg/arnoldi.jl index 3805bdb2fb529..70e893abf67a8 100644 --- a/base/linalg/arnoldi.jl +++ b/base/linalg/arnoldi.jl @@ -338,10 +338,9 @@ iterations derived from [`eigs`](@ref). **Inputs** -* `A`: Linear operator whose singular values are desired. `A` may be represented - as a subtype of `AbstractArray`, e.g., a sparse matrix, or any other type - supporting the four methods `size(A)`, `eltype(A)`, `A * vector`, and - `A' * vector`. +* `A`: Linear operator whose singular values are desired. `A` may be represented as a + subtype of `AbstractArray`, e.g., a sparse matrix, or any other type supporting the four + methods `size(A)`, `eltype(A)`, `A * vector`, and `A' * vector`. * `nsv`: Number of singular values. Default: 6. * `ritzvec`: If `true`, return the left and right singular vectors `left_sv` and `right_sv`. If `false`, omit the singular vectors. Default: `true`. @@ -353,7 +352,9 @@ iterations derived from [`eigs`](@ref). **Outputs** -* `svd`: An `SVD` object containing the left singular vectors, the requested values, and the right singular vectors. If `ritzvec = false`, the left and right singular vectors will be empty. +* `svd`: An `SVD` object containing the left singular vectors, the requested values, and the + right singular vectors. If `ritzvec = false`, the left and right singular vectors will be + empty. * `nconv`: Number of converged singular values. * `niter`: Number of iterations. * `nmult`: Number of matrix--vector products used. diff --git a/base/process.jl b/base/process.jl index fa1cce13f27a9..b3ac98e28387b 100644 --- a/base/process.jl +++ b/base/process.jl @@ -31,42 +31,37 @@ struct Cmd <: AbstractCmd end """ - Cmd(cmd::Cmd; ignorestatus, detach, windows_verbatim, windows_hide, - env, dir) - -Construct a new `Cmd` object, representing an external program and -arguments, from `cmd`, while changing the settings of the optional -keyword arguments: - -* `ignorestatus::Bool`: If `true` (defaults to `false`), then the `Cmd` - will not throw an error if the return code is nonzero. -* `detach::Bool`: If `true` (defaults to `false`), then the `Cmd` will be - run in a new process group, allowing it to outlive the `julia` process - and not have Ctrl-C passed to it. -* `windows_verbatim::Bool`: If `true` (defaults to `false`), then on Windows - the `Cmd` will send a command-line string to the process with no quoting - or escaping of arguments, even arguments containing spaces. (On Windows, - arguments are sent to a program as a single "command-line" string, and - programs are responsible for parsing it into arguments. By default, - empty arguments and arguments with spaces or tabs are quoted with double - quotes `"` in the command line, and `\\` or `"` are preceded by backslashes. - `windows_verbatim=true` is useful for launching programs that parse their - command line in nonstandard ways.) Has no effect on non-Windows systems. -* `windows_hide::Bool`: If `true` (defaults to `false`), then on Windows no - new console window is displayed when the `Cmd` is executed. This has - no effect if a console is already open or on non-Windows systems. -* `env`: Set environment variables to use when running the `Cmd`. `env` - is either a dictionary mapping strings to strings, an array - of strings of the form `"var=val"`, an array or tuple of `"var"=>val` - pairs, or `nothing`. In order to modify (rather than replace) - the existing environment, create `env` by `copy(ENV)` and then - set `env["var"]=val` as desired. + Cmd(cmd::Cmd; ignorestatus, detach, windows_verbatim, windows_hide, env, dir) + +Construct a new `Cmd` object, representing an external program and arguments, from `cmd`, +while changing the settings of the optional keyword arguments: + +* `ignorestatus::Bool`: If `true` (defaults to `false`), then the `Cmd` will not throw an + error if the return code is nonzero. +* `detach::Bool`: If `true` (defaults to `false`), then the `Cmd` will be run in a new + process group, allowing it to outlive the `julia` process and not have Ctrl-C passed to + it. +* `windows_verbatim::Bool`: If `true` (defaults to `false`), then on Windows the `Cmd` will + send a command-line string to the process with no quoting or escaping of arguments, even + arguments containing spaces. (On Windows, arguments are sent to a program as a single + "command-line" string, and programs are responsible for parsing it into arguments. By + default, empty arguments and arguments with spaces or tabs are quoted with double quotes + `"` in the command line, and `\\` or `"` are preceded by backslashes. + `windows_verbatim=true` is useful for launching programs that parse their command line in + nonstandard ways.) Has no effect on non-Windows systems. +* `windows_hide::Bool`: If `true` (defaults to `false`), then on Windows no new console + window is displayed when the `Cmd` is executed. This has no effect if a console is + already open or on non-Windows systems. +* `env`: Set environment variables to use when running the `Cmd`. `env` is either a + dictionary mapping strings to strings, an array of strings of the form `"var=val"`, an + array or tuple of `"var"=>val` pairs, or `nothing`. In order to modify (rather than + replace) the existing environment, create `env` by `copy(ENV)` and then set + `env["var"]=val` as desired. * `dir::AbstractString`: Specify a working directory for the command (instead of the current directory). -For any keywords that are not specified, the current settings from `cmd` are -used. Normally, to create a `Cmd` object in the first place, one uses -backticks, e.g. +For any keywords that are not specified, the current settings from `cmd` are used. Normally, +to create a `Cmd` object in the first place, one uses backticks, e.g. Cmd(`echo "Hello world"`, ignorestatus=true, detach=false) """ diff --git a/base/socket.jl b/base/socket.jl index 5ad8207cdda8a..7ca828205c46c 100644 --- a/base/socket.jl +++ b/base/socket.jl @@ -451,8 +451,8 @@ Set UDP socket options. * `multicast_loop`: loopback for multicast packets (default: `true`). * `multicast_ttl`: TTL for multicast packets (default: `nothing`). -* `enable_broadcast`: flag must be set to `true` if socket will be used for broadcast messages, - or else the UDP system will return an access error (default: `false`). +* `enable_broadcast`: flag must be set to `true` if socket will be used for broadcast + messages, or else the UDP system will return an access error (default: `false`). * `ttl`: Time-to-live of packets sent on the socket (default: `nothing`). """ function setopt(sock::UDPSocket; multicast_loop = nothing, multicast_ttl=nothing, enable_broadcast=nothing, ttl=nothing) diff --git a/base/strings/utf8proc.jl b/base/strings/utf8proc.jl index b60e9c6d9936d..8b90af4d06c7c 100644 --- a/base/strings/utf8proc.jl +++ b/base/strings/utf8proc.jl @@ -160,18 +160,19 @@ Alternatively, finer control and additional transformations may be be obtained b options (which all default to `false` except for `compose`) are specified: * `compose=false`: do not perform canonical composition -* `decompose=true`: do canonical decomposition instead of canonical composition (`compose=true` - is ignored if present) +* `decompose=true`: do canonical decomposition instead of canonical composition + (`compose=true` is ignored if present) * `compat=true`: compatibility equivalents are canonicalized * `casefold=true`: perform Unicode case folding, e.g. for case-insensitive string comparison -* `newline2lf=true`, `newline2ls=true`, or `newline2ps=true`: convert various newline sequences - (LF, CRLF, CR, NEL) into a linefeed (LF), line-separation (LS), or paragraph-separation (PS) - character, respectively +* `newline2lf=true`, `newline2ls=true`, or `newline2ps=true`: convert various newline + sequences (LF, CRLF, CR, NEL) into a linefeed (LF), line-separation (LS), or + paragraph-separation (PS) character, respectively * `stripmark=true`: strip diacritical marks (e.g. accents) * `stripignore=true`: strip Unicode's "default ignorable" characters (e.g. the soft hyphen or the left-to-right marker) * `stripcc=true`: strip control characters; horizontal tabs and form feeds are converted to - spaces; newlines are also converted to spaces unless a newline-conversion flag was specified + spaces; newlines are also converted to spaces unless a newline-conversion flag was + specified * `rejectna=true`: throw an error if unassigned code points are found * `stable=true`: enforce Unicode Versioning Stability From dfe5a3037c68914c7a6c1c26e9f5caf9c21c3fb8 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Thu, 4 May 2017 15:42:39 -0700 Subject: [PATCH 0657/1534] Add examples to GitRemote docs (#21681) * Add examples to GitRemote docs * Add examples for name and for url --- base/libgit2/remote.jl | 48 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/base/libgit2/remote.jl b/base/libgit2/remote.jl index 508e8bf7b4775..9819f614da9cc 100644 --- a/base/libgit2/remote.jl +++ b/base/libgit2/remote.jl @@ -4,6 +4,13 @@ GitRemote(repo::GitRepo, rmt_name::AbstractString, rmt_url::AbstractString) -> GitRemote Look up a remote git repository using its name and URL. Uses the default fetch refspec. + +# Example + +```julia +repo = LibGit2.init(repo_path) +remote = LibGit2.GitRemote(repo, "upstream", repo_url) +``` """ function GitRemote(repo::GitRepo, rmt_name::AbstractString, rmt_url::AbstractString) rmt_ptr_ptr = Ref{Ptr{Void}}(C_NULL) @@ -19,6 +26,14 @@ end Look up a remote git repository using the repository's name and URL, as well as specifications for how to fetch from the remote (e.g. which remote branch to fetch from). + +# Example + +```julia +repo = LibGit2.init(repo_path) +refspec = "+refs/heads/mybranch:refs/remotes/origin/mybranch" +remote = LibGit2.GitRemote(repo, "upstream", repo_url, refspec) +``` """ function GitRemote(repo::GitRepo, rmt_name::AbstractString, rmt_url::AbstractString, fetch_spec::AbstractString) rmt_ptr_ptr = Ref{Ptr{Void}}(C_NULL) @@ -32,6 +47,13 @@ end GitRemoteAnon(repo::GitRepo, url::AbstractString) -> GitRemote Look up a remote git repository using only its URL, not its name. + +# Example + +```julia +repo = LibGit2.init(repo_path) +remote = LibGit2.GitRemoteAnon(repo, repo_url) +``` """ function GitRemoteAnon(repo::GitRepo, url::AbstractString) rmt_ptr_ptr = Ref{Ptr{Void}}(C_NULL) @@ -53,6 +75,19 @@ end url(rmt::GitRemote) Get the URL of a remote git repository. + +# Example + +```julia +julia> repo_url = "https://github.com/JuliaLang/Example.jl"; + +julia> repo = LibGit2.clone(cache_repo, "test_directory"); + +julia> remote = LibGit2.GitRemote(repo, "origin", repo_url); + +julia> url(remote) +"https://github.com/JuliaLang/Example.jl" +``` """ function url(rmt::GitRemote) url_ptr = ccall((:git_remote_url, :libgit2), Cstring, (Ptr{Void},), rmt.ptr) @@ -66,6 +101,19 @@ end Get the name of a remote repository, for instance `"origin"`. If the remote is anonymous (see [`GitRemoteAnon`](@ref)) the name will be an empty string `""`. + +# Example + +```julia +julia> repo_url = "https://github.com/JuliaLang/Example.jl"; + +julia> repo = LibGit2.clone(cache_repo, "test_directory"); + +julia> remote = LibGit2.GitRemote(repo, "origin", repo_url); + +julia> name(remote) +"origin" +``` """ function name(rmt::GitRemote) name_ptr = ccall((:git_remote_name, :libgit2), Cstring, (Ptr{Void},), rmt.ptr) From 0af901f5390088821fce6cfa6e98666589ebdee1 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Fri, 5 May 2017 00:42:58 +0200 Subject: [PATCH 0658/1534] fix finalizer's doc (#21691) [ci skip] --- base/docs/helpdb/Base.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/base/docs/helpdb/Base.jl b/base/docs/helpdb/Base.jl index e0da5a28c17ce..f9ca7514353eb 100644 --- a/base/docs/helpdb/Base.jl +++ b/base/docs/helpdb/Base.jl @@ -1637,10 +1637,11 @@ true issubtype(type1, type2) """ - finalizer(x, function) + finalizer(x, f) Register a function `f(x)` to be called when there are no program-accessible references to -`x`. The behavior of this function is unpredictable if `x` is of a bits type. +`x`. The type of `x` must be a `mutable struct`, otherwise the behavior of this function is +unpredictable. """ finalizer From 9beece6e999fd7e3f7ffd13df43146fad4c9ffe3 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Fri, 5 May 2017 00:45:50 +0200 Subject: [PATCH 0659/1534] recover some lost build flags for openblas (#21688) --- deps/blas.mk | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/deps/blas.mk b/deps/blas.mk index d473dd4825bc2..55216c84ee112 100644 --- a/deps/blas.mk +++ b/deps/blas.mk @@ -4,7 +4,7 @@ OPENBLAS_GIT_URL := git://github.com/xianyi/OpenBLAS.git OPENBLAS_TAR_URL = https://api.github.com/repos/xianyi/OpenBLAS/tarball/$1 $(eval $(call git-external,openblas,OPENBLAS,,,$(BUILDDIR))) -OPENBLAS_BUILD_OPTS := CC="$(CC)" FC="$(FC)" RANLIB="$(RANLIB)" FFLAGS="$(FFLAGS) $(JFFLAGS)" TARGET=$(OPENBLAS_TARGET_ARCH) BINARY=$(BINARY) +OPENBLAS_BUILD_OPTS := CC="$(CC)" FC="$(FC)" RANLIB="$(RANLIB)" TARGET=$(OPENBLAS_TARGET_ARCH) BINARY=$(BINARY) # Thread support ifeq ($(OPENBLAS_USE_THREAD), 1) @@ -46,8 +46,8 @@ $(BUILDDIR)/$(OPENBLAS_SRC_DIR)/build-compiled: | $(BUILDDIR)/objconv/build-comp endif endif -OPENBLAS_FFLAGS := -OPENBLAS_CFLAGS := +OPENBLAS_FFLAGS := $(JFFLAGS) +OPENBLAS_CFLAGS := -O2 # Decide whether to build for 32-bit or 64-bit arch ifneq ($(BUILD_OS),$(OS)) @@ -56,14 +56,14 @@ endif ifeq ($(OS),WINNT) ifneq ($(ARCH),x86_64) ifneq ($(USECLANG),1) -OPENBLAS_CFLAGS += $(CFLAGS) -mincoming-stack-boundary=2 +OPENBLAS_CFLAGS += -mincoming-stack-boundary=2 endif -OPENBLAS_FFLAGS += $(FFLAGS) -mincoming-stack-boundary=2 +OPENBLAS_FFLAGS += -mincoming-stack-boundary=2 endif endif -OPENBLAS_BUILD_OPTS += CFLAGS="$(OPENBLAS_CFLAGS)" -OPENBLAS_BUILD_OPTS += FFLAGS="$(OPENBLAS_FFLAGS)" +OPENBLAS_BUILD_OPTS += CFLAGS="$(CFLAGS) $(OPENBLAS_CFLAGS)" +OPENBLAS_BUILD_OPTS += FFLAGS="$(FFLAGS) $(OPENBLAS_FFLAGS)" # Debug OpenBLAS ifeq ($(OPENBLAS_DEBUG), 1) From f3e425650a2476f0b905c15b0b01807cb128a681 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Thu, 4 May 2017 19:30:08 -0400 Subject: [PATCH 0660/1534] Do not hard code temp file path in the test. --- test/sparse/cholmod.jl | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/test/sparse/cholmod.jl b/test/sparse/cholmod.jl index 3f782fa63c18f..233472d287680 100644 --- a/test/sparse/cholmod.jl +++ b/test/sparse/cholmod.jl @@ -191,30 +191,21 @@ ACSC = sprandn(10, 10, 0.3) + I @test ishermitian(Sparse(Hermitian(complex(ACSC), :U))) # test Sparse constructor for c_SparseVoid (and read_sparse) -let testfile = joinpath(tempdir(), "tmp.mtx") - try - writedlm(testfile, ["%%MatrixMarket matrix coordinate real symmetric","3 3 4","1 1 1","2 2 1","3 2 0.5","3 3 1"]) - @test sparse(CHOLMOD.Sparse(testfile)) == [1 0 0;0 1 0.5;0 0.5 1] - finally - rm(testfile) - end -end -let testfile = joinpath(tempdir(), "tmp.mtx") - try - writedlm(testfile, ["%%MatrixMarket matrix coordinate complex Hermitian", - "3 3 4","1 1 1.0 0.0","2 2 1.0 0.0","3 2 0.5 0.5","3 3 1.0 0.0"]) - @test sparse(CHOLMOD.Sparse(testfile)) == [1 0 0;0 1 0.5-0.5im;0 0.5+0.5im 1] - finally - rm(testfile) - end -end -let testfile = joinpath(tempdir(), "tmp.mtx") - try - writedlm(testfile, ["%%MatrixMarket matrix coordinate real symmetric","%3 3 4","1 1 1","2 2 1","3 2 0.5","3 3 1"]) - @test_throws ArgumentError sparse(CHOLMOD.Sparse(testfile)) - finally - rm(testfile) - end +mktempdir() do temp_dir + testfile = joinpath(temp_dir, "tmp.mtx") + + writedlm(testfile, ["%%MatrixMarket matrix coordinate real symmetric","3 3 4","1 1 1","2 2 1","3 2 0.5","3 3 1"]) + @test sparse(CHOLMOD.Sparse(testfile)) == [1 0 0;0 1 0.5;0 0.5 1] + rm(testfile) + + writedlm(testfile, ["%%MatrixMarket matrix coordinate complex Hermitian", + "3 3 4","1 1 1.0 0.0","2 2 1.0 0.0","3 2 0.5 0.5","3 3 1.0 0.0"]) + @test sparse(CHOLMOD.Sparse(testfile)) == [1 0 0;0 1 0.5-0.5im;0 0.5+0.5im 1] + rm(testfile) + + writedlm(testfile, ["%%MatrixMarket matrix coordinate real symmetric","%3 3 4","1 1 1","2 2 1","3 2 0.5","3 3 1"]) + @test_throws ArgumentError sparse(CHOLMOD.Sparse(testfile)) + rm(testfile) end # test that Sparse(Ptr) constructor throws the right places From 3cfb989a5d26a58b68f095e468a181965f445a50 Mon Sep 17 00:00:00 2001 From: kshyatt Date: Thu, 4 May 2017 20:46:17 -0700 Subject: [PATCH 0661/1534] Add example for authors --- base/libgit2/libgit2.jl | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/base/libgit2/libgit2.jl b/base/libgit2/libgit2.jl index ac7dfa7a1683b..200ddea137d27 100644 --- a/base/libgit2/libgit2.jl +++ b/base/libgit2/libgit2.jl @@ -749,6 +749,26 @@ end authors(repo::GitRepo) -> Vector{Signature} Returns all authors of commits to the `repo` repository. + +# Example + +```julia +repo = LibGit2.GitRepo(repo_path) +repo_file = open(joinpath(repo_path, test_file), "a") + +println(repo_file, commit_msg) +flush(repo_file) +LibGit2.add!(repo, test_file) +sig = LibGit2.Signature("TEST", "TEST@TEST.COM", round(time(), 0), 0) +commit_oid1 = LibGit2.commit(repo, "commit1"; author=sig, committer=sig) +println(repo_file, randstring(10)) +flush(repo_file) +LibGit2.add!(repo, test_file) +commit_oid2 = LibGit2.commit(repo, "commit2"; author=sig, committer=sig) + +# will be a Vector of [sig, sig] +auths = LibGit2.authors(repo) +``` """ function authors(repo::GitRepo) return with(GitRevWalker(repo)) do walker From 4bcb1bf5205d1fc677a5f62c00ea350dec1991e1 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 5 May 2017 10:35:33 -0400 Subject: [PATCH 0662/1534] better static printing of typemap entries --- base/boot.jl | 4 ++-- src/rtutils.c | 16 +++++++++++----- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/base/boot.jl b/base/boot.jl index 55721469c6867..d0a686e761bf5 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -370,10 +370,10 @@ end show(io::IO, x::ANY) = ccall(:jl_static_show, Void, (Ptr{Void}, Any), io_pointer(io), x) print(io::IO, x::Char) = ccall(:jl_uv_putc, Void, (Ptr{Void}, Char), io_pointer(io), x) -print(io::IO, x::String) = write(io, x) +print(io::IO, x::String) = (write(io, x); nothing) print(io::IO, x::ANY) = show(io, x) print(io::IO, x::ANY, a::ANY...) = (print(io, x); print(io, a...)) -println(io::IO) = write(io, 0x0a) # 0x0a = '\n' +println(io::IO) = (write(io, 0x0a); nothing) # 0x0a = '\n' println(io::IO, x::ANY...) = (print(io, x...); println(io)) show(a::ANY) = show(STDOUT, a) diff --git a/src/rtutils.c b/src/rtutils.c index 954c352186e52..e5b2c8d8f11f8 100644 --- a/src/rtutils.c +++ b/src/rtutils.c @@ -841,14 +841,16 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt if (nb > 0 && tlen == 0) { uint8_t *data = (uint8_t*)v; n += jl_printf(out, "0x"); - for(int i=nb-1; i >= 0; --i) + for(int i = nb - 1; i >= 0; --i) n += jl_printf(out, "%02" PRIx8, data[i]); } else { - for (size_t i = 0; i < tlen; i++) { + size_t i = 0; + if (vt == jl_typemap_entry_type) + i = 1; + for (; i < tlen; i++) { if (!istuple) { n += jl_printf(out, "%s", jl_symbol_name((jl_sym_t*)jl_svecref(vt->name->names, i))); - //jl_fielddesc_t f = t->fields[i]; n += jl_printf(out, "="); } size_t offs = jl_field_offset(vt, i); @@ -861,11 +863,15 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt (jl_datatype_t*)jl_field_type(vt, i), depth); } - if (istuple && tlen==1) + if (istuple && tlen == 1) n += jl_printf(out, ","); - else if (i != tlen-1) + else if (i != tlen - 1) n += jl_printf(out, ", "); } + if (vt == jl_typemap_entry_type) { + n += jl_printf(out, ", next=↩︎\n "); + n += jl_static_show_x(out, jl_fieldref(v, 0), depth); + } } n += jl_printf(out, ")"); } From 3930eef75acaad350e635b8c2759d6200b9bb014 Mon Sep 17 00:00:00 2001 From: Amit Murthy Date: Fri, 5 May 2017 21:26:04 +0530 Subject: [PATCH 0663/1534] fix serialization of multiple global bindings to the same object in a closure (#21700) * fix serialization of multiple global bindings to the same object in a closure --- base/distributed/clusterserialize.jl | 4 ++-- test/distributed_exec.jl | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/base/distributed/clusterserialize.jl b/base/distributed/clusterserialize.jl index 6dca89ec15365..0454e1e668bf5 100644 --- a/base/distributed/clusterserialize.jl +++ b/base/distributed/clusterserialize.jl @@ -114,7 +114,7 @@ function syms_2b_sent(s::ClusterSerializer, identifier) oid = object_id(v) if haskey(s.glbs_sent, oid) # We have sent this object before, see if it has changed. - s.glbs_sent[oid] != hash(v) && push!(lst, sym) + s.glbs_sent[oid] != hash(sym, hash(v)) && push!(lst, sym) else push!(lst, sym) end @@ -143,7 +143,7 @@ function serialize_global_from_main(s::ClusterSerializer, sym) end end end - record_v && (s.glbs_sent[oid] = hash(v)) + record_v && (s.glbs_sent[oid] = hash(sym, hash(v))) serialize(s, isconst(Main, sym)) serialize(s, v) diff --git a/test/distributed_exec.jl b/test/distributed_exec.jl index 64f28c1e379e7..3275ba90fd4e3 100644 --- a/test/distributed_exec.jl +++ b/test/distributed_exec.jl @@ -1358,6 +1358,13 @@ for i in 1:5 @test remotecall_fetch(()->v2, id_other) == v2 end +# Different global bindings to the same object +global v3 = ones(10) +global v4 = v3 +@test remotecall_fetch(()->v3, id_other) == remotecall_fetch(()->v4, id_other) +@test remotecall_fetch(()->isdefined(Main, :v3), id_other) +@test remotecall_fetch(()->isdefined(Main, :v4), id_other) + # Test that a global is not being repeatedly serialized when # a) referenced multiple times in the closure # b) hash value has not changed. From 700bc5f0b0419be896a473fefb6f352834df6245 Mon Sep 17 00:00:00 2001 From: Alexander Morley Date: Fri, 5 May 2017 19:32:10 +0100 Subject: [PATCH 0664/1534] Add a word missing from the README (#21711) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d5533a3992263..6cf204e48a403 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ For builds of julia starting with 0.5.0-dev, you can create out-of-tree builds o If you need to build Julia in an environment that does not allow access to the outside world, use `make -C deps getall` to download all the necessary files. Then, copy the `julia` directory over to the target environment and build with `make`. -**Note:** the build process fail badly if any of the build directory's parent directories have spaces or other shell meta-characters such as `$` or `:` in their names (this is due to a limitation in GNU make). +**Note:** the build process will fail badly if any of the build directory's parent directories have spaces or other shell meta-characters such as `$` or `:` in their names (this is due to a limitation in GNU make). Once it is built, you can run the `julia` executable using its full path in the directory created above (the `julia` directory), or, to run it from anywhere, either - add an alias (in `bash`: `echo "alias julia='/path/to/install/folder/bin/julia'" >> ~/.bashrc && source ~/.bashrc`), or From c4ed32e81f22ea0f5c531a3b62c2104a1fc4f484 Mon Sep 17 00:00:00 2001 From: kshyatt Date: Fri, 5 May 2017 15:54:18 -0700 Subject: [PATCH 0665/1534] Add examples for clone --- base/libgit2/libgit2.jl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/base/libgit2/libgit2.jl b/base/libgit2/libgit2.jl index ac7dfa7a1683b..789473a4a8101 100644 --- a/base/libgit2/libgit2.jl +++ b/base/libgit2/libgit2.jl @@ -510,6 +510,16 @@ The keyword arguments are: repository. Equivalent to `git clone [-b ] [--bare] `. + +# Examples + +```julia +repo_url = "https://github.com/JuliaLang/Example.jl" +repo1 = LibGit2.clone(repo_url, "test_path") +repo2 = LibGit2.clone(repo_url, "test_path", isbare=true) +julia_url = "https://github.com/JuliaLang/julia" +julia_repo = LibGit2.clone(julia_url, "julia_path", branch="release-0.6") +``` """ function clone(repo_url::AbstractString, repo_path::AbstractString; branch::AbstractString="", From e566cea1ad907abbd91d019edc64978330cfbbd6 Mon Sep 17 00:00:00 2001 From: Samuel Powell Date: Sat, 6 May 2017 12:19:49 +0000 Subject: [PATCH 0666/1534] Provide build instructions for nVidia TX2 (ARM) (#21727) --- README.arm.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/README.arm.md b/README.arm.md index f31eed9d51ef3..f8df20ad78538 100644 --- a/README.arm.md +++ b/README.arm.md @@ -129,3 +129,43 @@ finding appropriate `crouton` help. On the current [Scaleway](http://scaleway.com) ARM servers, the Julia build works out of the box. + +## nVidia Jetson TX2 + +Julia builds and runs on the [nVidia Jetson TX2](http://www.nvidia.com/object/embedded-systems-dev-kits-modules.html) platform with minimal configuration changes. A full multi-threaded build, including LLVM, will complete in around two hours. All tests pass and CUDA functionality is available through, e.g., [CUDAdrv](https://github.com/JuliaGPU/CUDAdrv.jl). + +Starting from the default configuration flashed by [Jetpack 3.0](https://developer.nvidia.com/embedded/jetpack): + +``` +sudo apt-get install libssl-dev +``` + +### Julia 0.5.1 + +The easiest method to build Julia 0.5.1 is to use system provided versions of BLAS and LAPACK: + +``` +sudo apt-get install libopenblas-dev liblapack-dev +``` + +Configure Make.user as follows: + +``` +MARCH=armv8-a +JULIA_CPU_TARGET=cortex-a57 +override USE_SYSTEM_BLAS=1 +override USE_SYSTEM_LAPACK=1 +``` + +Note that package manager functions fail with an error regarding SSL certificates. This can be overcome by following the instructions in [this comment](https://github.com/JuliaLang/julia/issues/13399#issuecomment-182018321). + +### Julia 0.6 beta + +Configure Make.user as follows: + +``` +MARCH=armv8-a +JULIA_CPU_TARGET=cortex-a57 +``` + +No further changes are required. From 89541f5a013d94be99ad135dd125a3eeb77d336c Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Sat, 6 May 2017 16:12:43 +0200 Subject: [PATCH 0667/1534] Remove trailing whitespace in README.arm.md --- README.arm.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.arm.md b/README.arm.md index f8df20ad78538..326e761fa52a1 100644 --- a/README.arm.md +++ b/README.arm.md @@ -132,7 +132,7 @@ build works out of the box. ## nVidia Jetson TX2 -Julia builds and runs on the [nVidia Jetson TX2](http://www.nvidia.com/object/embedded-systems-dev-kits-modules.html) platform with minimal configuration changes. A full multi-threaded build, including LLVM, will complete in around two hours. All tests pass and CUDA functionality is available through, e.g., [CUDAdrv](https://github.com/JuliaGPU/CUDAdrv.jl). +Julia builds and runs on the [nVidia Jetson TX2](http://www.nvidia.com/object/embedded-systems-dev-kits-modules.html) platform with minimal configuration changes. A full multi-threaded build, including LLVM, will complete in around two hours. All tests pass and CUDA functionality is available through, e.g., [CUDAdrv](https://github.com/JuliaGPU/CUDAdrv.jl). Starting from the default configuration flashed by [Jetpack 3.0](https://developer.nvidia.com/embedded/jetpack): From a581292947a758ce7957f3f9caaeebe14c9d284a Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sat, 6 May 2017 14:59:51 -0400 Subject: [PATCH 0668/1534] fix #21719, incorrect MethodError This was caused by incorrectly using a TypeVar as the value of a static parameter in the case of a compiled specialization whose signature is not a leaf type. In this case, one slot was specialized on `Function`, but the slot with the static parameter had a leaf type. --- src/subtype.c | 10 ++++++---- test/core.jl | 9 +++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/subtype.c b/src/subtype.c index ce4dcb68e82a0..45a7e2f89559f 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -2157,11 +2157,13 @@ jl_value_t *jl_type_intersection_env_s(jl_value_t *a, jl_value_t *b, jl_svec_t * // we assume that if the intersection is a leaf type, we have // full information in `env`. however the intersection algorithm // does not yet provide that in all cases so use subtype. - if (szb > 0 && jl_is_leaf_type(*ans) && !jl_types_equal(b, (jl_value_t*)jl_type_type)) { + if (szb > 0 && !jl_types_equal(b, (jl_value_t*)jl_type_type)) { if (jl_subtype_env(*ans, b, env, szb)) { - for(i=0; i < sz; i++) { - if (jl_is_typevar(env[i])) { - *ans = jl_bottom_type; goto bot; + if (jl_is_leaf_type(*ans)) { + for(i=0; i < sz; i++) { + if (jl_is_typevar(env[i])) { + *ans = jl_bottom_type; goto bot; + } } } } diff --git a/test/core.jl b/test/core.jl index 7474c947e380e..2c60c21dc196a 100644 --- a/test/core.jl +++ b/test/core.jl @@ -4881,3 +4881,12 @@ function foo21568() end foo21568() @test f21568([0]) == 1 + +# issue #21719 +type T21719{V} + f + tol::Float64 + goal::V +end +g21719(f, goal; tol = 1e-6) = T21719(f, tol, goal) +@test isa(g21719(identity, 1.0; tol=0.1), T21719) From d10666260a0dc69aaa14e4c0d1bc429d6a53fa2b Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sat, 6 May 2017 15:07:44 -0400 Subject: [PATCH 0669/1534] fix #21710, specificity of `Array` vs. `AbstractVector` --- src/subtype.c | 10 ++++++---- test/core.jl | 4 ++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/subtype.c b/src/subtype.c index ce4dcb68e82a0..ddb3a8aaea1a8 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -275,6 +275,10 @@ static int obviously_disjoint(jl_value_t *a, jl_value_t *b, int specificity) else { ad = temp; } + if (specificity) { + // account for declared subtypes taking priority (issue #21710) + return 0; + } } int istuple = (ad->name == jl_tuple_typename); size_t np; @@ -2543,10 +2547,8 @@ static int type_morespecific_(jl_value_t *a, jl_value_t *b, int invariant, jl_ty int super=0; while (tta != (jl_datatype_t*)jl_any_type) { if (tta->name == ttb->name) { - if (super) { - if (tta->name != jl_type_typename) - return 1; - } + if (super && tta->name != jl_type_typename) + return 1; if (super && ttb->name == jl_type_typename && jl_is_typevar(jl_tparam0(b))) { if (type_morespecific_(a, jl_tparam0(b), 1, env)) return 1; diff --git a/test/core.jl b/test/core.jl index 7474c947e380e..22e375024fb07 100644 --- a/test/core.jl +++ b/test/core.jl @@ -85,6 +85,10 @@ _bound_vararg_specificity_1{T}(::Type{Array{T,1}}, d::Int) = 1 @test _bound_vararg_specificity_1(Array{Int,1}, 1) == 1 @test _bound_vararg_specificity_1(Array{Int,2}, 1, 1) == 0 +# issue #21710 +@test args_morespecific(Tuple{Array}, Tuple{AbstractVector}) +@test args_morespecific(Tuple{Matrix}, Tuple{AbstractVector}) + # issue #12939 module Issue12939 abstract type Abs; end From 79605e8fc9e51317b2a4395977f145684a69de01 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sat, 6 May 2017 15:08:20 -0400 Subject: [PATCH 0670/1534] clarify some quasi-ambiguous or unnecessary method signatures Without the fix to issue #21710, these are likely sources of ambiguities. --- base/abstractarray.jl | 6 +++--- base/abstractarraymath.jl | 7 ++----- base/bitarray.jl | 2 +- base/linalg/bitarray.jl | 2 +- base/linalg/blas.jl | 12 ++++++------ base/sparse/sparsevector.jl | 1 + 6 files changed, 14 insertions(+), 16 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 22aaa08db840e..6b97d97c2327a 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -190,7 +190,6 @@ function stride(a::AbstractArray, i::Integer) return s end -strides(A::AbstractArray{<:Any,0}) = () """ strides(A) @@ -204,8 +203,9 @@ julia> strides(A) ``` """ strides(A::AbstractArray) = _strides((1,), A) -_strides(out::NTuple{N,Any}, A::AbstractArray{T,N}) where {T,N} = out -function _strides(out::NTuple{M,Any}, A::AbstractArray) where M +_strides(out::Tuple{Int}, A::AbstractArray{<:Any,0}) = () +_strides(out::NTuple{N,Int}, A::AbstractArray{<:Any,N}) where {N} = out +function _strides(out::NTuple{M,Int}, A::AbstractArray) where M @_inline_meta _strides((out..., out[M]*size(A, M)), A) end diff --git a/base/abstractarraymath.jl b/base/abstractarraymath.jl index 847ddc03c4f8c..058170e3d5041 100644 --- a/base/abstractarraymath.jl +++ b/base/abstractarraymath.jl @@ -120,11 +120,6 @@ function slicedim(A::AbstractArray, d::Integer, i) A[setindex(indices(A), i, d)...] end -function flipdim(A::AbstractVector, d::Integer) - d == 1 || throw(ArgumentError("dimension to flip must be 1")) - reverse(A) -end - """ flipdim(A, d::Integer) @@ -147,6 +142,8 @@ function flipdim(A::AbstractArray, d::Integer) 1 ≤ d ≤ nd || throw(ArgumentError("dimension $d is not 1 ≤ $d ≤ $nd")) if isempty(A) return copy(A) + elseif nd == 1 + return reverse(A) end inds = indices(A) B = similar(A) diff --git a/base/bitarray.jl b/base/bitarray.jl index 265cf65b3614c..012f413ee4ca9 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -1188,7 +1188,7 @@ end for f in (:/, :\) @eval begin - ($f)(A::BitArray, B::BitArray) = ($f)(Array(A), Array(B)) + ($f)(A::Union{BitMatrix,BitVector}, B::Union{BitMatrix,BitVector}) = ($f)(Array(A), Array(B)) end end (/)(B::BitArray, x::Number) = (/)(Array(B), x) diff --git a/base/linalg/bitarray.jl b/base/linalg/bitarray.jl index bb0eb96579438..375f7ad67ce7a 100644 --- a/base/linalg/bitarray.jl +++ b/base/linalg/bitarray.jl @@ -295,4 +295,4 @@ function transpose(B::BitMatrix) return Bt end -ctranspose(B::BitArray) = transpose(B) +ctranspose(B::Union{BitMatrix,BitVector}) = transpose(B) diff --git a/base/linalg/blas.jl b/base/linalg/blas.jl index 87db924d4ffb3..9e1ab6f53d46c 100644 --- a/base/linalg/blas.jl +++ b/base/linalg/blas.jl @@ -329,6 +329,9 @@ end ## nrm2 +stride1(x) = stride(x,1) +stride1(x::Array) = 1 + """ nrm2(n, X, incx) @@ -358,8 +361,7 @@ for (fname, elty, ret_type) in ((:dnrm2_,:Float64,:Float64), end end end -nrm2(x::StridedVector) = nrm2(length(x), pointer(x), stride(x,1)) -nrm2(x::Array) = nrm2(length(x), pointer(x), 1) +nrm2(x::Union{StridedVector,Array}) = nrm2(length(x), pointer(x), stride1(x)) ## asum @@ -392,8 +394,7 @@ for (fname, elty, ret_type) in ((:dasum_,:Float64,:Float64), end end end -asum(x::StridedVector) = asum(length(x), pointer(x), stride(x,1)) -asum(x::Array) = asum(length(x), pointer(x), 1) +asum(x::Union{StridedVector,Array}) = asum(length(x), pointer(x), stride1(x)) ## axpy @@ -473,8 +474,7 @@ for (fname, elty) in ((:idamax_,:Float64), end end end -iamax(dx::StridedVector) = iamax(length(dx), pointer(dx), stride(dx,1)) -iamax(dx::Array) = iamax(length(dx), pointer(dx), 1) +iamax(dx::Union{StridedVector,Array}) = iamax(length(dx), pointer(dx), stride1(dx)) # Level 2 ## mv diff --git a/base/sparse/sparsevector.jl b/base/sparse/sparsevector.jl index 2c870762b1dc4..7f915492a2fd3 100644 --- a/base/sparse/sparsevector.jl +++ b/base/sparse/sparsevector.jl @@ -316,6 +316,7 @@ julia> sparsevec([1.0, 2.0, 0.0, 0.0, 3.0, 0.0]) sparsevec(a::AbstractVector{T}) where {T} = convert(SparseVector{T, Int}, a) sparsevec(a::AbstractArray) = sparsevec(vec(a)) sparsevec(a::AbstractSparseArray) = vec(a) +sparsevec(a::AbstractSparseVector) = vec(a) sparse(a::AbstractVector) = sparsevec(a) function _dense2sparsevec(s::AbstractArray{Tv}, initcap::Ti) where {Tv,Ti} From 14da9d3e45fa6958343e9199ecf700892ba4a0c8 Mon Sep 17 00:00:00 2001 From: kshyatt Date: Thu, 4 May 2017 21:06:55 -0700 Subject: [PATCH 0671/1534] Add example for checkout --- base/libgit2/libgit2.jl | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/base/libgit2/libgit2.jl b/base/libgit2/libgit2.jl index ac7dfa7a1683b..d875be7ec288e 100644 --- a/base/libgit2/libgit2.jl +++ b/base/libgit2/libgit2.jl @@ -458,6 +458,23 @@ Equivalent to `git checkout [-f] --detach `. Checkout the git commit `commit` (a [`GitHash`](@ref) in string form) in `repo`. If `force` is `true`, force the checkout and discard any current changes. Note that this detaches the current HEAD. + +# Example + +```julia +repo = LibGit2.init(repo_path) +open(joinpath(LibGit2.path(repo), "file1"), "w") do f + write(f, "111\n") +end +LibGit2.add!(repo, "file1") +commit_oid = LibGit2.commit(repo, "add file1") +open(joinpath(LibGit2.path(repo), "file1"), "w") do f + write(f, "112\n") +end +# would fail without the force=true +# since there are modifications to the file +LibGit2.checkout!(repo, string(commit_oid), force=true) +``` """ function checkout!(repo::GitRepo, commit::AbstractString = ""; force::Bool = true) From 4d08b54e538f973d7572f8488c9a0a66bb678dee Mon Sep 17 00:00:00 2001 From: Amit Murthy Date: Sun, 7 May 2017 07:06:03 +0530 Subject: [PATCH 0672/1534] Move testenv specific consts and addprocs to a separate file. (#21713) --- test/distributed.jl | 1 + test/distributed_exec.jl | 2 +- test/runtests.jl | 11 ++++------- test/testdefs.jl | 22 ---------------------- test/testenv.jl | 22 ++++++++++++++++++++++ 5 files changed, 28 insertions(+), 30 deletions(-) create mode 100644 test/testenv.jl diff --git a/test/distributed.jl b/test/distributed.jl index 007f28d4625aa..fc3bac479dab5 100644 --- a/test/distributed.jl +++ b/test/distributed.jl @@ -3,6 +3,7 @@ # Run the distributed test outside of the main driver since it needs its own # set of dedicated workers. +include("testenv.jl") cmd = `$test_exename $test_exeflags distributed_exec.jl` if !success(pipeline(cmd; stdout=STDOUT, stderr=STDERR)) && ccall(:jl_running_on_valgrind,Cint,()) == 0 diff --git a/test/distributed_exec.jl b/test/distributed_exec.jl index 3275ba90fd4e3..ea179f827a347 100644 --- a/test/distributed_exec.jl +++ b/test/distributed_exec.jl @@ -1,7 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test -include("testdefs.jl") +include("testenv.jl") # Test a few "remote" invocations when no workers are present @test remote(myid)() == 1 diff --git a/test/runtests.jl b/test/runtests.jl index 262684a746496..262ca6a46ecca 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -2,7 +2,7 @@ using Base.Test include("choosetests.jl") -include("testdefs.jl") +include("testenv.jl") tests, net_on = choosetests(ARGS) tests = unique(tests) @@ -30,15 +30,12 @@ cd(dirname(@__FILE__)) do n = 1 if net_on n = min(Sys.CPU_CORES, length(tests)) - if n > 1 - addprocs_with_testenv(n) - @sync for p in workers() - @async remotecall_fetch(include, p, "testdefs.jl") - end - end + n > 1 && addprocs_with_testenv(n) BLAS.set_num_threads(1) end + @everywhere include("testdefs.jl") + #pretty print the information about gc and mem usage name_align = maximum([length("Test (Worker)"); map(x -> length(x) + 3 + ndigits(nworkers()), tests)]) elapsed_align = length("Time (s)") diff --git a/test/testdefs.jl b/test/testdefs.jl index 7450c4bcaf7c0..bc214dab6fcf4 100644 --- a/test/testdefs.jl +++ b/test/testdefs.jl @@ -1,26 +1,5 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -if haskey(ENV, "JULIA_TEST_EXEFLAGS") - const test_exeflags = `$(Base.shell_split(ENV["JULIA_TEST_EXEFLAGS"]))` -else - inline_flag = Base.JLOptions().can_inline == 1 ? `` : `--inline=no` - cov_flag = `` - if Base.JLOptions().code_coverage == 1 - cov_flag = `--code-coverage=user` - elseif Base.JLOptions().code_coverage == 2 - cov_flag = `--code-coverage=all` - end - const test_exeflags = `$cov_flag $inline_flag --check-bounds=yes --startup-file=no --depwarn=error` -end - -if haskey(ENV, "JULIA_TEST_EXENAME") - const test_exename = `$(Base.shell_split(ENV["JULIA_TEST_EXENAME"]))` -else - const test_exename = `$(joinpath(JULIA_HOME, Base.julia_exename()))` -end - -addprocs_with_testenv(X; kwargs...) = addprocs(X; exename=test_exename, exeflags=test_exeflags, kwargs...) - function runtests(name, isolate=true) old_print_setting = Base.Test.TESTSET_PRINT_ENABLE[] Base.Test.TESTSET_PRINT_ENABLE[] = false @@ -30,7 +9,6 @@ function runtests(name, isolate=true) # code it in the test mod_name = Symbol("Test", rand(1:100), "Main_", replace(name, '/', '_')) m = @eval(Main, module $mod_name end) - eval(m, :(import Main: test_exename, test_exeflags, addprocs_with_testenv)) else m = Main end diff --git a/test/testenv.jl b/test/testenv.jl new file mode 100644 index 0000000000000..22ef4aada9353 --- /dev/null +++ b/test/testenv.jl @@ -0,0 +1,22 @@ +# This file is a part of Julia. License is MIT: https://julialang.org/license + +if haskey(ENV, "JULIA_TEST_EXEFLAGS") + const test_exeflags = `$(Base.shell_split(ENV["JULIA_TEST_EXEFLAGS"]))` +else + inline_flag = Base.JLOptions().can_inline == 1 ? `` : `--inline=no` + cov_flag = `` + if Base.JLOptions().code_coverage == 1 + cov_flag = `--code-coverage=user` + elseif Base.JLOptions().code_coverage == 2 + cov_flag = `--code-coverage=all` + end + const test_exeflags = `$cov_flag $inline_flag --check-bounds=yes --startup-file=no --depwarn=error` +end + +if haskey(ENV, "JULIA_TEST_EXENAME") + const test_exename = `$(Base.shell_split(ENV["JULIA_TEST_EXENAME"]))` +else + const test_exename = `$(joinpath(JULIA_HOME, Base.julia_exename()))` +end + +addprocs_with_testenv(X; kwargs...) = addprocs(X; exename=test_exename, exeflags=test_exeflags, kwargs...) From 677142166cfa66559b4eab3d80c662d21175886a Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Sat, 6 May 2017 23:07:38 -0400 Subject: [PATCH 0673/1534] Clean up testenv and old test isolation code --- test/ambiguous.jl | 5 ++--- test/bitarray.jl | 5 ----- test/core.jl | 6 +++--- test/docs.jl | 7 +++---- test/enums.jl | 5 ++--- test/intrinsics.jl | 6 +++--- test/linalg/tridiag.jl | 3 --- test/meta.jl | 12 ----------- test/nullable.jl | 5 ++--- test/reflection.jl | 4 ++-- test/repl.jl | 5 ++--- test/replutil.jl | 6 ++---- test/show.jl | 5 ++--- test/testenv.jl | 47 +++++++++++++++++++++++++++--------------- 14 files changed, 53 insertions(+), 68 deletions(-) diff --git a/test/ambiguous.jl b/test/ambiguous.jl index e799da798e3d5..32139c496a44f 100644 --- a/test/ambiguous.jl +++ b/test/ambiguous.jl @@ -9,9 +9,8 @@ ambig(x::Int, y::Int) = 4 ambig(x::Number, y) = 5 # END OF LINE NUMBER SENSITIVITY -const curmod = current_module() -const curmod_name = fullname(curmod) -const curmod_str = curmod === Main ? "Main" : join(curmod_name, ".") +# For curmod_* +include("testenv.jl") ambigs = Any[[], [3], [2,5], [], [3]] diff --git a/test/bitarray.jl b/test/bitarray.jl index 3ae22cb0beae3..4babea7771545 100644 --- a/test/bitarray.jl +++ b/test/bitarray.jl @@ -1,8 +1,5 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -module BitArrayTests - -using Base.Test using Base: findprevnot, findnextnot tc{N}(r1::NTuple{N,Any}, r2::NTuple{N,Any}) = all(x->tc(x...), [zip(r1,r2)...]) @@ -1467,5 +1464,3 @@ end end timesofar("I/O") - -end # module diff --git a/test/core.jl b/test/core.jl index 4404791034409..20a48c58ca875 100644 --- a/test/core.jl +++ b/test/core.jl @@ -2,9 +2,9 @@ # test core language features const Bottom = Union{} -const curmod = current_module() -const curmod_name = fullname(curmod) -const curmod_prefix = "$(["$m." for m in curmod_name]...)" + +# For curmod_* +include("testenv.jl") f47{T}(x::Vector{Vector{T}}) = 0 @test_throws MethodError f47(Array{Vector}(0)) diff --git a/test/docs.jl b/test/docs.jl index 82e550490521b..17ba396b79deb 100644 --- a/test/docs.jl +++ b/test/docs.jl @@ -2,9 +2,8 @@ import Base.Docs: meta, @var, DocStr, parsedoc -const curmod = current_module() -const curmod_name = fullname(curmod) -const curmod_prefix = "$(["$m." for m in curmod_name]...)" +# For curmod_* +include("testenv.jl") # Test helpers. function docstrings_equal(d1, d2) @@ -875,7 +874,7 @@ let x = Binding(Base, :bindingdoesnotexist) @test @var(Base.bindingdoesnotexist) == x end -let x = Binding(current_module(), :bindingdoesnotexist) +let x = Binding(curmod, :bindingdoesnotexist) @test defined(x) == false @test @var(bindingdoesnotexist) == x end diff --git a/test/enums.jl b/test/enums.jl index cdd64fa3928e9..243650b27c643 100644 --- a/test/enums.jl +++ b/test/enums.jl @@ -1,8 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -const curmod = current_module() -const curmod_name = fullname(curmod) -const curmod_prefix = "$(["$m." for m in curmod_name]...)" +# For curmod_* +include("testenv.jl") using Base.Test diff --git a/test/intrinsics.jl b/test/intrinsics.jl index c1bf0525c87cc..7e4dbfa46f99f 100644 --- a/test/intrinsics.jl +++ b/test/intrinsics.jl @@ -1,9 +1,9 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license # intrinsic functions -const curmod = current_module() -const curmod_name = fullname(curmod) -const curmod_prefix = "$(["$m." for m in curmod_name]...)" + +# For curmod_* +include("testenv.jl") # bits types @test isa((() -> Core.Intrinsics.bitcast(Ptr{Int8}, 0))(), Ptr{Int8}) diff --git a/test/linalg/tridiag.jl b/test/linalg/tridiag.jl index 4ffdd3f38a561..1fd499b675841 100644 --- a/test/linalg/tridiag.jl +++ b/test/linalg/tridiag.jl @@ -1,7 +1,5 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -module TridiagTest -using Base.Test debug = false # basic tridiagonal operations @@ -483,4 +481,3 @@ SymTridiagonal([1, 2], [0])^3 == [1 0; 0 8] # Test constructors with range and other abstract vectors @test SymTridiagonal(1:3, 1:2) == [1 1 0; 1 2 2; 0 2 3] @test Tridiagonal(4:5, 1:3, 1:2) == [1 1 0; 4 2 2; 0 5 3] -end diff --git a/test/meta.jl b/test/meta.jl index 0efa06566e959..a1c562d2fdd3e 100644 --- a/test/meta.jl +++ b/test/meta.jl @@ -2,10 +2,6 @@ # test meta-expressions that annotate blocks of code -module MetaTest - -using Base.Test - const inlining_on = Base.JLOptions().can_inline != 0 function f(x) @@ -121,13 +117,7 @@ body.args = ast.code @test popmeta!(body, :test) == (true, [42]) @test popmeta!(body, :nonexistent) == (false, []) -end - - # tests to fully cover functions in base/meta.jl -module MetaJLtest - -using Base.Test using Base.Meta @test isexpr(:(1+1),Set([:call])) @@ -139,8 +129,6 @@ show_sexpr(ioB,:(1+1)) show_sexpr(ioB,QuoteNode(1),1) -end - # test base/expr.jl baremodule B eval = 0 diff --git a/test/nullable.jl b/test/nullable.jl index 6c118ec9620e8..15bcb9e1b5ecd 100644 --- a/test/nullable.jl +++ b/test/nullable.jl @@ -115,9 +115,8 @@ for (i, T) in enumerate(types) end module NullableTestEnum -const curmod = current_module() -const curmod_name = fullname(curmod) -const curmod_prefix = "$(["$m." for m in curmod_name]...)" +# For curmod_* +include("testenv.jl") io = IOBuffer() @enum TestEnum a b show(io, Nullable(a)) diff --git a/test/reflection.jl b/test/reflection.jl index 57f2a93534503..d66098e3fde77 100644 --- a/test/reflection.jl +++ b/test/reflection.jl @@ -163,8 +163,8 @@ not_const = 1 ## find bindings tests @test ccall(:jl_get_module_of_binding, Any, (Any, Any), Base, :sin)==Base -const curmod = current_module() -const curmod_name = fullname(curmod) +# For curmod_* +include("testenv.jl") module TestMod7648 using Base.Test diff --git a/test/repl.jl b/test/repl.jl index 2b9eaa9932b62..65b27398db249 100644 --- a/test/repl.jl +++ b/test/repl.jl @@ -1,8 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -const curmod = current_module() -const curmod_name = fullname(curmod) -const curmod_prefix = "$(["$m." for m in curmod_name]...)" +# For curmod_* +include("testenv.jl") # REPL tests isdefined(Main, :TestHelpers) || @eval Main include(joinpath(dirname(@__FILE__), "TestHelpers.jl")) diff --git a/test/replutil.jl b/test/replutil.jl index 1a403ed17d6cf..63e3091c9b7a7 100644 --- a/test/replutil.jl +++ b/test/replutil.jl @@ -1,9 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -const curmod = current_module() -const curmod_name = fullname(curmod) -const curmod_str = curmod === Main ? "Main" : join(curmod_name, ".") -const curmod_prefix = "$(["$m." for m in curmod_name]...)" +# For curmod_* +include("testenv.jl") function test_have_color(buf, color, no_color) if Base.have_color diff --git a/test/show.jl b/test/show.jl index d9960abdd184b..a0f9fa3bd32c9 100644 --- a/test/show.jl +++ b/test/show.jl @@ -1,8 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -const curmod = current_module() -const curmod_name = fullname(curmod) -const curmod_prefix = "$(["$m." for m in curmod_name]...)" +# For curmod_* +include("testenv.jl") replstr(x) = sprint((io,x) -> show(IOContext(io, :limit => true), MIME("text/plain"), x), x) diff --git a/test/testenv.jl b/test/testenv.jl index 22ef4aada9353..871999c759536 100644 --- a/test/testenv.jl +++ b/test/testenv.jl @@ -1,22 +1,35 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -if haskey(ENV, "JULIA_TEST_EXEFLAGS") - const test_exeflags = `$(Base.shell_split(ENV["JULIA_TEST_EXEFLAGS"]))` -else - inline_flag = Base.JLOptions().can_inline == 1 ? `` : `--inline=no` - cov_flag = `` - if Base.JLOptions().code_coverage == 1 - cov_flag = `--code-coverage=user` - elseif Base.JLOptions().code_coverage == 2 - cov_flag = `--code-coverage=all` +# This includes a few helper variables and functions that provide information about the +# test environment (command line flags, current module, etc). +# This file can be included multiple times in the same module if necessary, +# which can happen with unisolated test runs. + +if !isdefined(:testenv_defined) + const testenv_defined = true + if haskey(ENV, "JULIA_TEST_EXEFLAGS") + const test_exeflags = `$(Base.shell_split(ENV["JULIA_TEST_EXEFLAGS"]))` + else + inline_flag = Base.JLOptions().can_inline == 1 ? `` : `--inline=no` + cov_flag = `` + if Base.JLOptions().code_coverage == 1 + cov_flag = `--code-coverage=user` + elseif Base.JLOptions().code_coverage == 2 + cov_flag = `--code-coverage=all` + end + const test_exeflags = `$cov_flag $inline_flag --check-bounds=yes --startup-file=no --depwarn=error` end - const test_exeflags = `$cov_flag $inline_flag --check-bounds=yes --startup-file=no --depwarn=error` -end -if haskey(ENV, "JULIA_TEST_EXENAME") - const test_exename = `$(Base.shell_split(ENV["JULIA_TEST_EXENAME"]))` -else - const test_exename = `$(joinpath(JULIA_HOME, Base.julia_exename()))` -end + if haskey(ENV, "JULIA_TEST_EXENAME") + const test_exename = `$(Base.shell_split(ENV["JULIA_TEST_EXENAME"]))` + else + const test_exename = `$(joinpath(JULIA_HOME, Base.julia_exename()))` + end + + addprocs_with_testenv(X; kwargs...) = addprocs(X; exename=test_exename, exeflags=test_exeflags, kwargs...) -addprocs_with_testenv(X; kwargs...) = addprocs(X; exename=test_exename, exeflags=test_exeflags, kwargs...) + const curmod = current_module() + const curmod_name = fullname(curmod) + const curmod_str = curmod === Main ? "Main" : join(curmod_name, ".") + const curmod_prefix = "$(["$m." for m in curmod_name]...)" +end From 15c86f8fa5fa33467616e99f04e977506b50b16b Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Sat, 22 Apr 2017 00:13:13 -0400 Subject: [PATCH 0674/1534] A few GC clean up/tweak * Rename and clean up thread heap initialization * More reliable inlining of `gc_setmark_buf` in `gc.c` * Move assertion part of `gc_datatype_assert` outline. --- src/gc.c | 44 +++++++++++++++++++++++++------------------- src/julia_internal.h | 2 +- src/julia_threads.h | 12 ++++++------ src/threading.c | 5 +---- 4 files changed, 33 insertions(+), 30 deletions(-) diff --git a/src/gc.c b/src/gc.c index bfa5c9485e0e3..55ba458ffa517 100644 --- a/src/gc.c +++ b/src/gc.c @@ -616,10 +616,7 @@ STATIC_INLINE void gc_setmark(jl_ptls_t ptls, jl_taggedvalue_t *o, } } -#ifndef __cplusplus -inline -#endif -void gc_setmark_buf(jl_ptls_t ptls, void *o, uint8_t mark_mode, size_t minsz) +STATIC_INLINE void gc_setmark_buf_(jl_ptls_t ptls, void *o, uint8_t mark_mode, size_t minsz) { jl_taggedvalue_t *buf = jl_astaggedvalue(o); uintptr_t tag = buf->header; @@ -642,6 +639,11 @@ void gc_setmark_buf(jl_ptls_t ptls, void *o, uint8_t mark_mode, size_t minsz) } } +void gc_setmark_buf(jl_ptls_t ptls, void *o, uint8_t mark_mode, size_t minsz) +{ + gc_setmark_buf_(ptls, o, mark_mode, minsz); +} + #define should_collect() (__unlikely(gc_num.allocd>0)) static inline int maybe_collect(jl_ptls_t ptls) @@ -1357,7 +1359,7 @@ NOINLINE static int gc_mark_module(jl_ptls_t ptls, jl_module_t *m, for(i=1; i < m->bindings.size; i+=2) { if (table[i] != HT_NOTFOUND) { jl_binding_t *b = (jl_binding_t*)table[i]; - gc_setmark_buf(ptls, b, bits, sizeof(jl_binding_t)); + gc_setmark_buf_(ptls, b, bits, sizeof(jl_binding_t)); void *vb = jl_astaggedvalue(b); verify_parent1("module", m, &vb, "binding_buff"); (void)vb; @@ -1438,11 +1440,11 @@ static void gc_mark_task_stack(jl_ptls_t ptls, jl_task_t *ta, int d, int8_t bits jl_ptls_t ptls2 = jl_all_tls_states[tid]; if (stkbuf) { #ifdef COPY_STACKS - gc_setmark_buf(ptls, ta->stkbuf, bits, ta->bufsz); + gc_setmark_buf_(ptls, ta->stkbuf, bits, ta->bufsz); #else // stkbuf isn't owned by julia for the root task if (ta != ptls2->root_task) { - gc_setmark_buf(ptls, ta->stkbuf, bits, ta->ssize); + gc_setmark_buf_(ptls, ta->stkbuf, bits, ta->ssize); } #endif } @@ -1493,10 +1495,8 @@ void gc_mark_object_list(jl_ptls_t ptls, arraylist_t *list, size_t start) } } -STATIC_INLINE void gc_assert_datatype(jl_datatype_t *vt) +JL_NORETURN NOINLINE void gc_assert_datatype_fail(jl_datatype_t *vt) { - if (__likely(jl_is_datatype(vt))) - return; jl_printf(JL_STDOUT, "GC error (probable corruption) :\n"); gc_debug_print_status(); jl_(vt); @@ -1504,11 +1504,12 @@ STATIC_INLINE void gc_assert_datatype(jl_datatype_t *vt) abort(); } -// for chasing down unwanted references -/* -static jl_value_t *lookforme = NULL; -JL_DLLEXPORT void jl_gc_lookfor(jl_value_t *v) { lookforme = v; } -*/ +STATIC_INLINE void gc_assert_datatype(jl_datatype_t *vt) +{ + if (__likely(jl_is_datatype(vt))) + return; + gc_assert_datatype_fail(vt); +} #define MAX_MARK_DEPTH 400 // Scan a marked object `v` and recursively mark its children. @@ -1567,8 +1568,8 @@ static void gc_scan_obj_(jl_ptls_t ptls, jl_value_t *v, int d, verify_parent1("array", v, &val_buf, "buffer ('loc' addr is meaningless)"); (void)val_buf; - gc_setmark_buf(ptls, (char*)a->data - a->offset * a->elsize, - bits, array_nbytes(a)); + gc_setmark_buf_(ptls, (char*)a->data - a->offset * a->elsize, + bits, array_nbytes(a)); } if (flags.ptrarray && a->data != NULL) { size_t l = jl_array_len(a); @@ -2128,8 +2129,8 @@ JL_DLLEXPORT jl_value_t *(jl_gc_alloc)(jl_ptls_t ptls, size_t sz, void *ty) return jl_gc_alloc_(ptls, sz, ty); } -// Per-thread initialization (when threading is fully implemented) -void jl_mk_thread_heap(jl_ptls_t ptls) +// Per-thread initialization +void jl_init_thread_heap(jl_ptls_t ptls) { jl_thread_heap_t *heap = &ptls->heap; jl_gc_pool_t *p = heap->norm_pools; @@ -2151,6 +2152,11 @@ void jl_mk_thread_heap(jl_ptls_t ptls) arraylist_new(heap->remset, 0); arraylist_new(heap->last_remset, 0); arraylist_new(&ptls->finalizers, 0); + + jl_gc_mark_cache_t *gc_cache = &ptls->gc_cache; + gc_cache->perm_scanned_bytes = 0; + gc_cache->scanned_bytes = 0; + gc_cache->nbig_obj = 0; } // System-wide initializations diff --git a/src/julia_internal.h b/src/julia_internal.h index 00cb0f60c955f..216d0833846ed 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -512,7 +512,7 @@ void jl_gc_init(void); void jl_init_signal_async(void); void jl_init_debuginfo(void); void jl_init_runtime_ccall(void); -void jl_mk_thread_heap(jl_ptls_t ptls); +void jl_init_thread_heap(jl_ptls_t ptls); void _julia_init(JL_IMAGE_SEARCH rel); diff --git a/src/julia_threads.h b/src/julia_threads.h index bbb11d3e23137..7d7c127588007 100644 --- a/src/julia_threads.h +++ b/src/julia_threads.h @@ -34,6 +34,12 @@ typedef struct { uint16_t osize; // size of objects in this pool } jl_gc_pool_t; +// Recursive spin lock +typedef struct { + volatile unsigned long owner; + uint32_t count; +} jl_mutex_t; + typedef struct { // variable for tracking weak references arraylist_t weak_refs; @@ -503,12 +509,6 @@ JL_DLLEXPORT void (jl_gc_safepoint)(void); } \ } while (0) -// Recursive spin lock -typedef struct { - volatile unsigned long owner; - uint32_t count; -} jl_mutex_t; - JL_DLLEXPORT void jl_gc_enable_finalizers(jl_ptls_t ptls, int on); static inline void jl_lock_frame_push(jl_mutex_t *lock); static inline void jl_lock_frame_pop(void); diff --git a/src/threading.c b/src/threading.c index baf4c2f808a4b..4d45433932a5d 100644 --- a/src/threading.c +++ b/src/threading.c @@ -266,9 +266,6 @@ static void ti_initthread(int16_t tid) ptls->tid = tid; ptls->pgcstack = NULL; ptls->gc_state = 0; // GC unsafe - ptls->gc_cache.perm_scanned_bytes = 0; - ptls->gc_cache.scanned_bytes = 0; - ptls->gc_cache.nbig_obj = 0; // Conditionally initialize the safepoint address. See comment in // `safepoint.c` if (tid == 0) { @@ -287,7 +284,7 @@ static void ti_initthread(int16_t tid) abort(); } ptls->bt_data = (uintptr_t*)bt_data; - jl_mk_thread_heap(ptls); + jl_init_thread_heap(ptls); jl_install_thread_signal_handler(ptls); jl_all_tls_states[tid] = ptls; From c967e68edbeed87bf28281947dc1b93712fc7645 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Mon, 24 Apr 2017 19:51:10 -0400 Subject: [PATCH 0675/1534] Implement GC mark loop * Uses an iterative (mostly) Depth-first search (DFS) to mark all the objects. * Use two manually managed stacks instead of the native stack for better performance and compatibility with incremental/parallel scanning. --- src/gc-debug.c | 171 +++++++++ src/gc.c | 837 ++++++++++++++++++++++++++++++++++++++++++++ src/gc.h | 155 +++++++- src/julia_threads.h | 4 + 4 files changed, 1165 insertions(+), 2 deletions(-) diff --git a/src/gc-debug.c b/src/gc-debug.c index 7e77d7b6e9c2d..4767750b92814 100644 --- a/src/gc-debug.c +++ b/src/gc-debug.c @@ -1186,6 +1186,177 @@ void gc_count_pool(void) jl_safe_printf("************************\n"); } +int gc_slot_to_fieldidx(void *obj, void *slot) +{ + jl_datatype_t *vt = (jl_datatype_t*)jl_typeof(obj); + int nf = (int)jl_datatype_nfields(vt); + for (int i = 0; i < nf; i++) { + void *fieldaddr = (char*)obj + jl_field_offset(vt, i); + if (fieldaddr >= slot) { + return i; + } + } + return -1; +} + +int gc_slot_to_arrayidx(void *obj, void *_slot) +{ + char *slot = (char*)_slot; + jl_datatype_t *vt = (jl_datatype_t*)jl_typeof(obj); + char *start = NULL; + size_t len = 0; + if (vt == jl_module_type) { + jl_module_t *m = (jl_module_t*)obj; + start = (char*)m->usings.items; + len = m->usings.len; + } + else if (vt == jl_simplevector_type) { + start = (char*)jl_svec_data(obj); + len = jl_svec_len(obj); + } + else if (vt->name == jl_array_typename) { + jl_array_t *a = (jl_array_t*)obj; + if (!a->flags.ptrarray) + return -1; + start = (char*)a->data; + len = jl_array_len(a); + } + if (slot < start || slot >= start + sizeof(void*) * len) + return -1; + return (slot - start) / sizeof(void*); +} + +// Print a backtrace from the bottom (start) of the mark stack up to `sp` +// `pc_offset` will be added to `sp` for convenience in the debugger. +NOINLINE void gc_mark_loop_unwind(jl_ptls_t ptls, gc_mark_sp_t sp, int pc_offset) +{ + jl_jmp_buf *old_buf = ptls->safe_restore; + jl_jmp_buf buf; + ptls->safe_restore = &buf; + if (jl_setjmp(buf, 0) != 0) { + jl_printf((JL_STREAM*)STDERR_FILENO, + "\n!!! ERROR when unwinding gc mark loop -- ABORTING !!!\n"); + ptls->safe_restore = old_buf; + return; + } + void **top = sp.pc + pc_offset; + char *data_top = sp.data; + sp.data = ptls->gc_cache.data_stack; + sp.pc = ptls->gc_cache.pc_stack; + int isroot = 1; + while (sp.pc < top) { + void *pc = *sp.pc; + const char *prefix = isroot ? "r--" : " `-"; + isroot = 0; + if (pc == gc_mark_label_addrs[GC_MARK_L_marked_obj]) { + gc_mark_marked_obj_t *data = gc_repush_markdata(&sp, gc_mark_marked_obj_t); + if ((char*)data > data_top) { + jl_safe_printf("Mark stack unwind overflow -- ABORTING !!!\n"); + break; + } + jl_safe_printf("%p: Root object: %p :: %p (bits: %d)\n of type ", + data, data->obj, (void*)data->tag, (int)data->bits); + jl_((void*)data->tag); + isroot = 1; + } + else if (pc == gc_mark_label_addrs[GC_MARK_L_scan_only]) { + gc_mark_marked_obj_t *data = gc_repush_markdata(&sp, gc_mark_marked_obj_t); + if ((char*)data > data_top) { + jl_safe_printf("Mark stack unwind overflow -- ABORTING !!!\n"); + break; + } + jl_safe_printf("%p: Queued root: %p :: %p (bits: %d)\n of type ", + data, data->obj, (void*)data->tag, (int)data->bits); + jl_((void*)data->tag); + isroot = 1; + } + else if (pc == gc_mark_label_addrs[GC_MARK_L_finlist]) { + gc_mark_finlist_t *data = gc_repush_markdata(&sp, gc_mark_finlist_t); + if ((char*)data > data_top) { + jl_safe_printf("Mark stack unwind overflow -- ABORTING !!!\n"); + break; + } + jl_safe_printf("%p: Finalizer list from %p to %p\n", data, data->begin, data->end); + isroot = 1; + } + else if (pc == gc_mark_label_addrs[GC_MARK_L_objarray]) { + gc_mark_objarray_t *data = gc_repush_markdata(&sp, gc_mark_objarray_t); + if ((char*)data > data_top) { + jl_safe_printf("Mark stack unwind overflow -- ABORTING !!!\n"); + break; + } + jl_safe_printf("%p: %s Array in object %p :: %p -- [%p, %p)\n of type ", + data, prefix, data->parent, ((void**)data->parent)[-1], + data->begin, data->end); + jl_(jl_typeof(data->parent)); + } + else if (pc == gc_mark_label_addrs[GC_MARK_L_obj8]) { + gc_mark_obj8_t *data = gc_repush_markdata(&sp, gc_mark_obj8_t); + if ((char*)data > data_top) { + jl_safe_printf("Mark stack unwind overflow -- ABORTING !!!\n"); + break; + } + jl_datatype_t *vt = (jl_datatype_t*)jl_typeof(data->parent); + jl_fielddesc8_t *desc = (jl_fielddesc8_t*)jl_dt_layout_fields(vt->layout); + jl_safe_printf("%p: %s Object (8bit) %p :: %p -- [%d, %d)\n of type ", + data, prefix, data->parent, ((void**)data->parent)[-1], + (int)(data->begin - desc), (int)(data->end - desc)); + jl_(jl_typeof(data->parent)); + } + else if (pc == gc_mark_label_addrs[GC_MARK_L_obj16]) { + gc_mark_obj16_t *data = gc_repush_markdata(&sp, gc_mark_obj16_t); + if ((char*)data > data_top) { + jl_safe_printf("Mark stack unwind overflow -- ABORTING !!!\n"); + break; + } + jl_datatype_t *vt = (jl_datatype_t*)jl_typeof(data->parent); + jl_fielddesc16_t *desc = (jl_fielddesc16_t*)jl_dt_layout_fields(vt->layout); + jl_safe_printf("%p: %s Object (16bit) %p :: %p -- [%d, %d)\n of type ", + data, prefix, data->parent, ((void**)data->parent)[-1], + (int)(data->begin - desc), (int)(data->end - desc)); + jl_(jl_typeof(data->parent)); + } + else if (pc == gc_mark_label_addrs[GC_MARK_L_obj32]) { + gc_mark_obj32_t *data = gc_repush_markdata(&sp, gc_mark_obj32_t); + if ((char*)data > data_top) { + jl_safe_printf("Mark stack unwind overflow -- ABORTING !!!\n"); + break; + } + jl_datatype_t *vt = (jl_datatype_t*)jl_typeof(data->parent); + jl_fielddesc32_t *desc = (jl_fielddesc32_t*)jl_dt_layout_fields(vt->layout); + jl_safe_printf("%p: %s Object (32bit) %p :: %p -- [%d, %d)\n of type ", + data, prefix, data->parent, ((void**)data->parent)[-1], + (int)(data->begin - desc), (int)(data->end - desc)); + jl_(jl_typeof(data->parent)); + } + else if (pc == gc_mark_label_addrs[GC_MARK_L_stack]) { + gc_mark_stackframe_t *data = gc_repush_markdata(&sp, gc_mark_stackframe_t); + if ((char*)data > data_top) { + jl_safe_printf("Mark stack unwind overflow -- ABORTING !!!\n"); + break; + } + jl_safe_printf("%p: %s Stack frame %p -- %d of %d (%s)\n", + data, prefix, data->s, (int)data->i, (int)data->nroots >> 1, + (data->nroots & 1) ? "indirect" : "direct"); + } + else if (pc == gc_mark_label_addrs[GC_MARK_L_module_binding]) { + // module_binding + gc_mark_binding_t *data = gc_repush_markdata(&sp, gc_mark_binding_t); + if ((char*)data > data_top) { + jl_safe_printf("Mark stack unwind overflow -- ABORTING !!!\n"); + break; + } + jl_safe_printf("%p: %s Module (bindings) %p (bits %d) -- [%p, %p)\n", + data, prefix, data->parent, (int)data->bits, data->begin, data->end); + } + else { + jl_safe_printf("Unknown pc %p --- ABORTING !!!\n", pc); + break; + } + } + ptls->safe_restore = old_buf; +} + #ifdef __cplusplus } #endif diff --git a/src/gc.c b/src/gc.c index 55ba458ffa517..c40234f99709c 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1511,6 +1511,836 @@ STATIC_INLINE void gc_assert_datatype(jl_datatype_t *vt) gc_assert_datatype_fail(vt); } +// This stores the label address in the mark loop function. +// We can't directly store that to a global array so we need some hack to get that. +// See the call to `gc_mark_loop` in init with a `NULL` `ptls`. +void *gc_mark_label_addrs[_GC_MARK_L_MAX]; + +// Double the mark stack (both pc and data) with the lock held. +static void NOINLINE gc_mark_stack_resize(jl_gc_mark_cache_t *gc_cache, gc_mark_sp_t *sp) +{ + char *old_data = gc_cache->data_stack; + void **pc_stack = sp->pc_start; + size_t stack_size = (char*)sp->pc_end - (char*)pc_stack; + JL_LOCK_NOGC(&gc_cache->stack_lock); + gc_cache->data_stack = (char*)realloc(old_data, stack_size * 2 * sizeof(gc_mark_data_t)); + sp->data += gc_cache->data_stack - old_data; + + sp->pc_start = gc_cache->pc_stack = (void**)realloc(pc_stack, stack_size * 2 * sizeof(void*)); + gc_cache->pc_stack_end = sp->pc_end = sp->pc_start + stack_size * 2; + sp->pc += sp->pc_start - pc_stack; + JL_UNLOCK_NOGC(&gc_cache->stack_lock); +} + +// Push a work item to the stack. The type of the work item is marked with `pc`. +// The data needed is in `data` and is of size `data_size`. +// If there isn't enough space on the stack, the stack will be resized with the stack +// lock held. The caller should invalidate any local cache of the stack addresses that's not +// in `gc_cache` or `sp` +// The `sp` will be updated on return if `inc` is true. +STATIC_INLINE void gc_mark_stack_push(jl_gc_mark_cache_t *gc_cache, gc_mark_sp_t *sp, + void *pc, void *data, size_t data_size, int inc) +{ + assert(data_size <= sizeof(gc_mark_data_t)); + if (__unlikely(sp->pc == sp->pc_end)) + gc_mark_stack_resize(gc_cache, sp); + *sp->pc = pc; + memcpy(sp->data, data, data_size); + if (inc) { + sp->data += data_size; + sp->pc++; + } +} + +// Check if the reference is non-NULL and atomically set the mark bit. +// Update `*nptr`, which is the `nptr` field of the parent item, if the object is young. +// Return the tag (with GC bits cleared) and the GC bits in `*ptag` and `*pbits`. +// Return whether the object needs to be scanned / have metadata updated. +STATIC_INLINE int gc_try_setmark(jl_value_t *obj, uintptr_t *nptr, + uintptr_t *ptag, uint8_t *pbits) +{ + if (!obj) + return 0; + jl_taggedvalue_t *o = jl_astaggedvalue(obj); + uintptr_t tag = o->header; + if (!gc_marked(tag)) { + uint8_t bits; + int res = gc_setmark_tag(o, GC_MARKED, tag, &bits); + if (!gc_old(bits)) + *nptr = *nptr | 1; + *ptag = tag & ~(uintptr_t)0xf; + *pbits = bits; + return __likely(res); + } + else if (!gc_old(tag)) { + *nptr = *nptr | 1; + } + return 0; +} + +// Queue a finalizer list to be scanned in the mark loop. Start marking from index `start`. +void gc_mark_queue_finlist(jl_gc_mark_cache_t *gc_cache, gc_mark_sp_t *sp, + arraylist_t *list, size_t start) +{ + size_t len = list->len; + if (len <= start) + return; + jl_value_t **items = (jl_value_t**)list->items; + gc_mark_finlist_t markdata = {items + start, items + len}; + gc_mark_stack_push(gc_cache, sp, gc_mark_label_addrs[GC_MARK_L_finlist], + &markdata, sizeof(markdata), 1); +} + +// Queue a object to be scanned. The object should already be marked and the GC metadata +// should already be updated for it. Only scanning of the object should be performed. +STATIC_INLINE void gc_mark_queue_scan_obj(jl_gc_mark_cache_t *gc_cache, gc_mark_sp_t *sp, + jl_value_t *obj) +{ + jl_taggedvalue_t *o = jl_astaggedvalue(obj); + uintptr_t tag = o->header; + uint8_t bits = tag & 0xf; + tag = tag & ~(uintptr_t)0xf; + gc_mark_marked_obj_t data = {obj, tag, bits}; + gc_mark_stack_push(gc_cache, sp, gc_mark_label_addrs[GC_MARK_L_scan_only], + &data, sizeof(data), 1); +} + +// Mark and queue a object to be scanned. +// The object will be marked atomically which can also happen concurrently. +// It will be queued if the object wasn't marked already (or concurrently by another thread) +// Returns whether the object is young. +STATIC_INLINE int gc_mark_queue_obj(jl_gc_mark_cache_t *gc_cache, gc_mark_sp_t *sp, void *_obj) +{ + jl_value_t *obj = (jl_value_t*)jl_assume(_obj); + uintptr_t nptr = 0; + uintptr_t tag = 0; + uint8_t bits = 0; + if (!gc_try_setmark(obj, &nptr, &tag, &bits)) + return (int)nptr; + gc_mark_marked_obj_t data = {obj, tag, bits}; + gc_mark_stack_push(gc_cache, sp, gc_mark_label_addrs[GC_MARK_L_marked_obj], + &data, sizeof(data), 1); + return (int)nptr; +} + +// Check if `nptr` is tagged for `old + refyoung`, +// Push the object to the remset and update the `nptr` counter if necessary. +STATIC_INLINE void gc_mark_push_remset(jl_ptls_t ptls, jl_value_t *obj, uintptr_t nptr) +{ + if (__unlikely((nptr & 0x3) == 0x3)) { + ptls->heap.remset_nptr += nptr >> 2; + arraylist_t *remset = ptls->heap.remset; + size_t len = remset->len; + if (__unlikely(len >= remset->max)) { + arraylist_push(remset, obj); + } + else { + remset->len = len + 1; + remset->items[len] = obj; + } + } +} + +// Scan a dense array of object references, see `gc_mark_objarray_t` +STATIC_INLINE int gc_mark_scan_objarray(jl_ptls_t ptls, gc_mark_sp_t *sp, + gc_mark_objarray_t *objary, + jl_value_t **begin, jl_value_t **end, + jl_value_t **pnew_obj, uintptr_t *ptag, uint8_t *pbits) +{ + (void)jl_assume(objary == (gc_mark_objarray_t*)sp->data); + for (; begin < end; begin++) { + *pnew_obj = *begin; + if (*pnew_obj) + verify_parent2("obj array", objary->parent, begin, "elem(%d)", + gc_slot_to_arrayidx(objary->parent, begin)); + if (!gc_try_setmark(*pnew_obj, &objary->nptr, ptag, pbits)) + continue; + begin++; + // Found an object to mark + if (begin < end) { + // Haven't done with this one yet. Update the content and push it back + objary->begin = begin; + gc_repush_markdata(sp, gc_mark_objarray_t); + } + else { + // Finished scaning this one, finish up by checking the GC invariance + // and let the next item replacing the current one directly. + gc_mark_push_remset(ptls, objary->parent, objary->nptr); + } + return 1; + } + gc_mark_push_remset(ptls, objary->parent, objary->nptr); + return 0; +} + +// Scan an object with 8bits field descriptors. see `gc_mark_obj8_t` +STATIC_INLINE int gc_mark_scan_obj8(jl_ptls_t ptls, gc_mark_sp_t *sp, gc_mark_obj8_t *obj8, + char *parent, jl_fielddesc8_t *begin, jl_fielddesc8_t *end, + jl_value_t **pnew_obj, uintptr_t *ptag, uint8_t *pbits) +{ + (void)jl_assume(obj8 == (gc_mark_obj8_t*)sp->data); + (void)jl_assume(begin < end); + for (; begin < end; begin++) { + if (!begin->isptr) + continue; + jl_value_t **slot = (jl_value_t**)(parent + begin->offset); + *pnew_obj = *slot; + if (*pnew_obj) + verify_parent2("object", parent, slot, "field(%d)", + gc_slot_to_fieldidx(parent, slot)); + if (!gc_try_setmark(*pnew_obj, &obj8->nptr, ptag, pbits)) + continue; + begin++; + // Found an object to mark + if (begin < end) { + // Haven't done with this one yet. Update the content and push it back + obj8->begin = begin; + gc_repush_markdata(sp, gc_mark_obj8_t); + } + else { + // Finished scaning this one, finish up by checking the GC invariance + // and let the next item replacing the current one directly. + gc_mark_push_remset(ptls, obj8->parent, obj8->nptr); + } + return 1; + } + gc_mark_push_remset(ptls, obj8->parent, obj8->nptr); + return 0; +} + +// Scan an object with 16bits field descriptors. see `gc_mark_obj16_t` +STATIC_INLINE int gc_mark_scan_obj16(jl_ptls_t ptls, gc_mark_sp_t *sp, gc_mark_obj16_t *obj16, + char *parent, jl_fielddesc16_t *begin, jl_fielddesc16_t *end, + jl_value_t **pnew_obj, uintptr_t *ptag, uint8_t *pbits) +{ + (void)jl_assume(obj16 == (gc_mark_obj16_t*)sp->data); + (void)jl_assume(begin < end); + for (; begin < end; begin++) { + if (!begin->isptr) + continue; + jl_value_t **slot = (jl_value_t**)(parent + begin->offset); + *pnew_obj = *slot; + if (*pnew_obj) + verify_parent2("object", parent, slot, "field(%d)", + gc_slot_to_fieldidx(parent, slot)); + if (!gc_try_setmark(*pnew_obj, &obj16->nptr, ptag, pbits)) + continue; + begin++; + // Found an object to mark + if (begin < end) { + // Haven't done with this one yet. Update the content and push it back + obj16->begin = begin; + gc_repush_markdata(sp, gc_mark_obj16_t); + } + else { + // Finished scaning this one, finish up by checking the GC invariance + // and let the next item replacing the current one directly. + gc_mark_push_remset(ptls, obj16->parent, obj16->nptr); + } + return 1; + } + gc_mark_push_remset(ptls, obj16->parent, obj16->nptr); + return 0; +} + +// Scan an object with 32bits field descriptors. see `gc_mark_obj32_t` +STATIC_INLINE int gc_mark_scan_obj32(jl_ptls_t ptls, gc_mark_sp_t *sp, gc_mark_obj32_t *obj32, + char *parent, jl_fielddesc32_t *begin, jl_fielddesc32_t *end, + jl_value_t **pnew_obj, uintptr_t *ptag, uint8_t *pbits) +{ + (void)jl_assume(obj32 == (gc_mark_obj32_t*)sp->data); + (void)jl_assume(begin < end); + for (; begin < end; begin++) { + if (!begin->isptr) + continue; + jl_value_t **slot = (jl_value_t**)(parent + begin->offset); + *pnew_obj = *slot; + if (*pnew_obj) + verify_parent2("object", parent, slot, "field(%d)", + gc_slot_to_fieldidx(parent, slot)); + if (!gc_try_setmark(*pnew_obj, &obj32->nptr, ptag, pbits)) + continue; + begin++; + // Found an object to mark + if (begin < end) { + // Haven't done with this one yet. Update the content and push it back + obj32->begin = begin; + gc_repush_markdata(sp, gc_mark_obj32_t); + } + else { + // Finished scaning this one, finish up by checking the GC invariance + // and let the next item replacing the current one directly. + gc_mark_push_remset(ptls, obj32->parent, obj32->nptr); + } + return 1; + } + gc_mark_push_remset(ptls, obj32->parent, obj32->nptr); + return 0; +} + +#ifdef __GNUC__ +# define gc_mark_laddr(name) (&&name) +# define gc_mark_jmp(ptr) goto *(ptr) +#else +#define gc_mark_laddr(name) ((void*)(uintptr_t)GC_MARK_L_##name) +#define gc_mark_jmp(ptr) do { \ + switch ((int)(uintptr_t)ptr) { \ + case GC_MARK_L_marked_obj: \ + goto marked_obj; \ + case GC_MARK_L_scan_only: \ + goto scan_only; \ + case GC_MARK_L_finlist: \ + goto finlist; \ + case GC_MARK_L_objarray: \ + goto objarray; \ + case GC_MARK_L_obj8: \ + goto obj8; \ + case GC_MARK_L_obj16: \ + goto obj16; \ + case GC_MARK_L_obj32: \ + goto obj32; \ + case GC_MARK_L_stack: \ + goto stack; \ + case GC_MARK_L_module_binding: \ + goto module_binding; \ + default: \ + abort(); \ + } \ + } while (0) +#endif + +// This is the main marking loop. +// It uses an iterative (mostly) Depth-first search (DFS) to mark all the objects. +// Instead of using the native stack, two stacks are manually maintained, +// one (fixed-size) pc stack which stores the return address and one (variable-size) +// data stack which stores the local variables needed by the scanning code. +// Using a manually maintained stack has a few advantages +// +// 1. We can resize the stack as we go and never worry about stack overflow +// This is especitally useful when enters the GC in a deep call stack. +// It also removes the very deep GC call stack in a profile. +// 2. We can minimize the number of local variables to save on the stack. +// This includes minimizing the sizes of the stack frames and only saving variables +// that have been changed before making "function calls" (i.e. `goto mark;`) +// 3. We can perform end-of-loop tail-call optimization for common cases. +// 4. The marking can be interrupted more easily since all the states are maintained +// in a well-defined format already. +// This will be useful if we want to have incremental marking again. +// 5. The frames can be stolen by another thread more easily and it is not necessary +// to copy works to be stolen to another queue. Useful for parallel marking. +// (Will still require synchronization in stack popping of course.) +// 6. A flat function (i.e. no or very few function calls) also give the compiler +// opportunity to keep more states in registers that doesn't have to be spilled as often. +// +// We use two stacks so that the thief on another thread can steal the fixed sized pc stack +// and use that to figure out the size of the struct on the variable size data stack. +// +// The main disadvantages are that we bypass some stack-based CPU optimizations including the +// stack engine and return address prediction. +// Using two stacks also double the number of operations on the stack pointer +// though we still only need to use one of them (the pc stack pointer) for bounds check. +// In general, it seems that the reduction of stack memory ops and instructions count +// have a larger possitive effect on the performance. =) + +// As a general guide we do not want to make non-inlined function calls in this function +// if possible since a large number of registers has to be spilled when that happens. +// This is especially true on on X86 which doesn't have many (any?) +// callee saved general purpose registers. +// (OTOH, the spill will likely make use of the stack engine which is otherwise idle so +// the performance impact is minimum as long as it's not in the hottest path) + +// There are three external entry points to the loop, corresponding to label +// `marked_obj`, `scan_only` and `finlist` (see the corresponding functions +// `gc_mark_queue_obj`, `gc_mark_queue_scan_obj` and `gc_mark_queue_finlist` above). +// The scanning of the object starts with `goto mark`, which updates the metadata and scans +// the object whose information is stored in `new_obj`, `tag` and `bits`. +// The branches in `mark` will dispatch the object to one of the scan "loop"s to be scanned +// as either a normal julia object or one of the special objects with specific storage format. +// Each of the scan "loop" will preform a DFS of the object in the following way +// +// 1. When encountering an pointer (julia object reference) slots, load, preform NULL check +// and atomically set the mark bits to determine if the object needs to be scanned. +// 2. If yes, it'll push itself back onto the mark stack (after updating fields that are changed) +// using `gc_repush_markdata` to increment the stack pointers. +// This step can also be replaced by a tail call by finishing up the marking of the current +// object when the end of the current object is reached. +// 3. Jump to `mark`. The marking of the current object will be resumed after the child is +// scanned by popping the stack frame back. +// +// Some of the special object scannings use BFS to simplify the code (Task and Module). + +// The jumps from the dispatch to the scan "loop"s are done by first pushing a frame +// to the stacks while only increment the data stack pointer before jumping to the loop +// This way the scan "loop" gets exactly what it expects after a stack pop. +// Additional optimizations are done for some of the common cases by skipping +// the unnecessary data stack pointer increment and the load from the stack +// (i.e. store to load forwaring). See `objary_loaded`, `obj8_loaded` and `obj16_loaded`. +NOINLINE void gc_mark_loop(jl_ptls_t ptls, gc_mark_sp_t sp) +{ + if (__unlikely(ptls == NULL)) { + gc_mark_label_addrs[GC_MARK_L_marked_obj] = gc_mark_laddr(marked_obj); + gc_mark_label_addrs[GC_MARK_L_scan_only] = gc_mark_laddr(scan_only); + gc_mark_label_addrs[GC_MARK_L_finlist] = gc_mark_laddr(finlist); + gc_mark_label_addrs[GC_MARK_L_objarray] = gc_mark_laddr(objarray); + gc_mark_label_addrs[GC_MARK_L_obj8] = gc_mark_laddr(obj8); + gc_mark_label_addrs[GC_MARK_L_obj16] = gc_mark_laddr(obj16); + gc_mark_label_addrs[GC_MARK_L_obj32] = gc_mark_laddr(obj32); + gc_mark_label_addrs[GC_MARK_L_stack] = gc_mark_laddr(stack); + gc_mark_label_addrs[GC_MARK_L_module_binding] = gc_mark_laddr(module_binding); + return; + } + + jl_value_t *new_obj = NULL; + uintptr_t tag = 0; + uint8_t bits = 0; + int meta_updated = 0; + + gc_mark_objarray_t *objary; + jl_value_t **objary_begin; + jl_value_t **objary_end; + + gc_mark_obj8_t *obj8; + char *obj8_parent; + jl_fielddesc8_t *obj8_begin; + jl_fielddesc8_t *obj8_end; + + gc_mark_obj16_t *obj16; + char *obj16_parent; + jl_fielddesc16_t *obj16_begin; + jl_fielddesc16_t *obj16_end; + +pop: + if (sp.pc == sp.pc_start) { + // TODO: stealing form another thread + return; + } + sp.pc--; + gc_mark_jmp(*sp.pc); // computed goto + +marked_obj: { + // An object that has been marked and needs have metadata updated and scanned. + gc_mark_marked_obj_t *obj = gc_pop_markdata(&sp, gc_mark_marked_obj_t); + new_obj = obj->obj; + tag = obj->tag; + bits = obj->bits; + goto mark; + } + +scan_only: { + // An object that has been marked and needs to be scanned. + gc_mark_marked_obj_t *obj = gc_pop_markdata(&sp, gc_mark_marked_obj_t); + new_obj = obj->obj; + tag = obj->tag; + bits = obj->bits; + meta_updated = 1; + goto mark; + } + +objarray: + objary = gc_pop_markdata(&sp, gc_mark_objarray_t); + objary_begin = objary->begin; + objary_end = objary->end; +objarray_loaded: + if (gc_mark_scan_objarray(ptls, &sp, objary, objary_begin, objary_end, + &new_obj, &tag, &bits)) + goto mark; + goto pop; + +obj8: + obj8 = gc_pop_markdata(&sp, gc_mark_obj8_t); + obj8_parent = (char*)obj8->parent; + obj8_begin = obj8->begin; + obj8_end = obj8->end; +obj8_loaded: + if (gc_mark_scan_obj8(ptls, &sp, obj8, obj8_parent, obj8_begin, obj8_end, + &new_obj, &tag, &bits)) + goto mark; + goto pop; + +obj16: + obj16 = gc_pop_markdata(&sp, gc_mark_obj16_t); + obj16_parent = (char*)obj16->parent; + obj16_begin = obj16->begin; + obj16_end = obj16->end; +obj16_loaded: + if (gc_mark_scan_obj16(ptls, &sp, obj16, obj16_parent, obj16_begin, obj16_end, + &new_obj, &tag, &bits)) + goto mark; + goto pop; + +obj32: { + gc_mark_obj32_t *obj32 = gc_pop_markdata(&sp, gc_mark_obj32_t); + char *parent = (char*)obj32->parent; + jl_fielddesc32_t *begin = obj32->begin; + jl_fielddesc32_t *end = obj32->end; + if (gc_mark_scan_obj32(ptls, &sp, obj32, parent, begin, end, &new_obj, &tag, &bits)) + goto mark; + goto pop; + } + +stack: { + // Scan the stack. see `gc_mark_stackframe_t` + // The task object this stack belongs to is being scanned separately as a normal + // 8bit field descriptor object. + gc_mark_stackframe_t *stack = gc_pop_markdata(&sp, gc_mark_stackframe_t); + jl_gcframe_t *s = stack->s; + uint32_t i = stack->i; + uint32_t nroots = stack->nroots; + uintptr_t offset = stack->offset; + uintptr_t lb = stack->lb; + uintptr_t ub = stack->ub; + uint32_t nr = nroots >> 1; + uintptr_t nptr = 0; + while (1) { + jl_value_t ***rts = (jl_value_t***)(((void**)s) + 2); + for (; i < nr; i++) { + if (nroots & 1) { + void **slot = (void**)gc_read_stack(&rts[i], offset, lb, ub); + new_obj = (jl_value_t*)gc_read_stack(slot, offset, lb, ub); + } + else { + new_obj = (jl_value_t*)gc_read_stack(&rts[i], offset, lb, ub); + } + if (!gc_try_setmark(new_obj, &nptr, &tag, &bits)) + continue; + i++; + if (i < nr) { + // Haven't done with this one yet. Update the content and push it back + stack->i = i; + gc_repush_markdata(&sp, gc_mark_stackframe_t); + } + else if ((s = (jl_gcframe_t*)gc_read_stack(&s->prev, offset, lb, ub))) { + stack->s = s; + stack->i = 0; + uintptr_t new_nroots = gc_read_stack(&s->nroots, offset, lb, ub); + assert(new_nroots <= UINT32_MAX); + stack->nroots = (uint32_t)new_nroots; + gc_repush_markdata(&sp, gc_mark_stackframe_t); + } + goto mark; + } + s = (jl_gcframe_t*)gc_read_stack(&s->prev, offset, lb, ub); + if (s != 0) { + stack->s = s; + i = 0; + uintptr_t new_nroots = gc_read_stack(&s->nroots, offset, lb, ub); + assert(new_nroots <= UINT32_MAX); + nroots = stack->nroots = (uint32_t)new_nroots; + nr = nroots >> 1; + continue; + } + goto pop; + } + } + +module_binding: { + // Scan a module. see `gc_mark_binding_t` + // Other fields of the module will be scanned after the bindings are scanned + gc_mark_binding_t *binding = gc_pop_markdata(&sp, gc_mark_binding_t); + jl_binding_t **begin = binding->begin; + jl_binding_t **end = binding->end; + uint8_t mbits = binding->bits; + for (; begin < end; begin += 2) { + jl_binding_t *b = *begin; + if (b == (jl_binding_t*)HT_NOTFOUND) + continue; + gc_setmark_buf_(ptls, b, mbits, sizeof(jl_binding_t)); + void *vb = jl_astaggedvalue(b); + verify_parent1("module", binding->parent, &vb, "binding_buff"); + (void)vb; + jl_value_t *value = b->value; + jl_value_t *globalref = b->globalref; + if (value) { + verify_parent2("module", binding->parent, + &b->value, "binding(%s)", jl_symbol_name(b->name)); + if (gc_try_setmark(value, &binding->nptr, &tag, &bits)) { + new_obj = value; + begin += 2; + binding->begin = begin; + gc_repush_markdata(&sp, gc_mark_binding_t); + uintptr_t gr_tag; + uint8_t gr_bits; + if (gc_try_setmark(globalref, &binding->nptr, &gr_tag, &gr_bits)) { + gc_mark_marked_obj_t data = {globalref, gr_tag, gr_bits}; + gc_mark_stack_push(&ptls->gc_cache, &sp, gc_mark_laddr(marked_obj), + &data, sizeof(data), 1); + } + goto mark; + } + } + if (gc_try_setmark(globalref, &binding->nptr, &tag, &bits)) { + begin += 2; + binding->begin = begin; + gc_repush_markdata(&sp, gc_mark_binding_t); + new_obj = globalref; + goto mark; + } + } + jl_module_t *m = binding->parent; + int scanparent = gc_try_setmark((jl_value_t*)m->parent, &binding->nptr, &tag, &bits); + size_t nusings = m->usings.len; + if (nusings) { + // this is only necessary because bindings for "using" modules + // are added only when accessed. therefore if a module is replaced + // after "using" it but before accessing it, this array might + // contain the only reference. + objary_begin = (jl_value_t**)m->usings.items; + objary_end = objary_begin + nusings; + gc_mark_objarray_t data = {(jl_value_t*)m, objary_begin, objary_end, binding->nptr}; + gc_mark_stack_push(&ptls->gc_cache, &sp, gc_mark_laddr(objarray), + &data, sizeof(data), 0); + if (!scanparent) { + objary = (gc_mark_objarray_t*)sp.data; + goto objarray_loaded; + } + sp.data += sizeof(data); + sp.pc++; + } + else { + gc_mark_push_remset(ptls, (jl_value_t*)m, binding->nptr); + } + if (scanparent) { + new_obj = (jl_value_t*)m->parent; + goto mark; + } + goto pop; + } + +finlist: { + // Scan a finalizer list. see `gc_mark_finlist_t` + gc_mark_finlist_t *finlist = gc_pop_markdata(&sp, gc_mark_finlist_t); + jl_value_t **begin = finlist->begin; + jl_value_t **end = finlist->end; + for (; begin < end; begin++) { + new_obj = *begin; + if (__unlikely(!new_obj)) + continue; + if (gc_ptr_tag(new_obj, 1)) { + new_obj = (jl_value_t*)gc_ptr_clear_tag(new_obj, 1); + begin++; + assert(begin < end); + } + uintptr_t nptr = 0; + if (!gc_try_setmark(new_obj, &nptr, &tag, &bits)) + continue; + begin++; + // Found an object to mark + if (begin < end) { + // Haven't done with this one yet. Update the content and push it back + finlist->begin = begin; + gc_repush_markdata(&sp, gc_mark_finlist_t); + } + goto mark; + } + goto pop; + } + +mark: { + // Generic scanning entry point. + // Expects `new_obj`, `tag` and `bits` to be set correctly. +#ifdef JL_DEBUG_BUILD + if (new_obj == gc_findval) + jl_raise_debugger(); +#endif + jl_taggedvalue_t *o = jl_astaggedvalue(new_obj); + jl_datatype_t *vt = (jl_datatype_t*)tag; + int update_meta = __likely(!meta_updated && !gc_verifying); + meta_updated = 0; + // Symbols are always marked + assert(vt != jl_symbol_type); + if (vt == jl_simplevector_type) { + size_t l = jl_svec_len(new_obj); + jl_value_t **data = jl_svec_data(new_obj); + if (update_meta) + gc_setmark(ptls, o, bits, l * sizeof(void*) + sizeof(jl_svec_t)); + uintptr_t nptr = (l << 2) | (bits & GC_OLD); + objary_begin = data; + objary_end = data + l; + gc_mark_objarray_t markdata = {new_obj, objary_begin, objary_end, nptr}; + gc_mark_stack_push(&ptls->gc_cache, &sp, gc_mark_laddr(objarray), + &markdata, sizeof(markdata), 0); + objary = (gc_mark_objarray_t*)sp.data; + goto objarray_loaded; + } + else if (vt->name == jl_array_typename) { + jl_array_t *a = (jl_array_t*)new_obj; + jl_array_flags_t flags = a->flags; + if (update_meta) { + if (flags.pooled) + gc_setmark_pool(ptls, o, bits); + else + gc_setmark_big(ptls, o, bits); + } + if (flags.how == 1) { + void *val_buf = jl_astaggedvalue((char*)a->data - a->offset * a->elsize); + verify_parent1("array", new_obj, &val_buf, "buffer ('loc' addr is meaningless)"); + (void)val_buf; + gc_setmark_buf_(ptls, (char*)a->data - a->offset * a->elsize, + bits, array_nbytes(a)); + } + else if (flags.how == 2) { + if (update_meta) { + objprofile_count(jl_malloc_tag, bits == GC_OLD_MARKED, + array_nbytes(a)); + if (bits == GC_OLD_MARKED) { + ptls->gc_cache.perm_scanned_bytes += array_nbytes(a); + } + else { + ptls->gc_cache.scanned_bytes += array_nbytes(a); + } + } + } + else if (flags.how == 3) { + jl_value_t *owner = jl_array_data_owner(a); + uintptr_t nptr = (1 << 2) | (bits & GC_OLD); + int markowner = gc_try_setmark(owner, &nptr, &tag, &bits); + gc_mark_push_remset(ptls, new_obj, nptr); + if (markowner) { + new_obj = owner; + goto mark; + } + goto pop; + } + if (!flags.ptrarray || a->data == NULL) + goto pop; + size_t l = jl_array_len(a); + uintptr_t nptr = (l << 2) | (bits & GC_OLD); + objary_begin = (jl_value_t**)a->data; + objary_end = objary_begin + l; + gc_mark_objarray_t markdata = {new_obj, objary_begin, objary_end, nptr}; + gc_mark_stack_push(&ptls->gc_cache, &sp, gc_mark_laddr(objarray), + &markdata, sizeof(markdata), 0); + objary = (gc_mark_objarray_t*)sp.data; + goto objarray_loaded; + } + else if (vt == jl_module_type) { + if (update_meta) + gc_setmark(ptls, o, bits, sizeof(jl_module_t)); + jl_module_t *m = (jl_module_t*)new_obj; + jl_binding_t **table = (jl_binding_t**)m->bindings.table; + size_t bsize = m->bindings.size; + uintptr_t nptr = ((bsize + m->usings.len + 1) << 2) | (bits & GC_OLD); + gc_mark_binding_t markdata = {m, table + 1, table + bsize, nptr, bits}; + gc_mark_stack_push(&ptls->gc_cache, &sp, gc_mark_laddr(module_binding), + &markdata, sizeof(markdata), 0); + sp.data += sizeof(markdata); + goto module_binding; + } + else if (vt == jl_task_type) { + if (update_meta) + gc_setmark(ptls, o, bits, sizeof(jl_task_t)); + jl_task_t *ta = (jl_task_t*)new_obj; + gc_scrub_record_task(ta); + int stkbuf = (ta->stkbuf != (void*)(intptr_t)-1 && ta->stkbuf != NULL); + int16_t tid = ta->tid; + jl_ptls_t ptls2 = jl_all_tls_states[tid]; + if (stkbuf) { +#ifdef COPY_STACKS + gc_setmark_buf_(ptls, ta->stkbuf, bits, ta->bufsz); +#else + // stkbuf isn't owned by julia for the root task + if (ta != ptls2->root_task) { + gc_setmark_buf_(ptls, ta->stkbuf, bits, ta->ssize); + } +#endif + } + jl_gcframe_t *s = NULL; + size_t nroots; + uintptr_t offset = 0; + uintptr_t lb = 0; + uintptr_t ub = (uintptr_t)-1; + if (ta == ptls2->current_task) { + s = ptls2->pgcstack; + } + else if (stkbuf) { + s = ta->gcstack; +#ifdef COPY_STACKS + ub = (uintptr_t)ptls2->stackbase; + lb = ub - ta->ssize; + offset = (uintptr_t)ta->stkbuf - lb; +#endif + } + if (s) { + nroots = gc_read_stack(&s->nroots, offset, lb, ub); + assert(nroots <= UINT32_MAX); + gc_mark_stackframe_t stackdata = {s, 0, (uint32_t)nroots, offset, lb, ub}; + gc_mark_stack_push(&ptls->gc_cache, &sp, gc_mark_laddr(stack), + &stackdata, sizeof(stackdata), 1); + } + const jl_datatype_layout_t *layout = jl_task_type->layout; + assert(layout->fielddesc_type == 0); + size_t nfields = layout->nfields; + assert(nfields > 0); + obj8_begin = (jl_fielddesc8_t*)jl_dt_layout_fields(layout); + obj8_end = obj8_begin + nfields; + gc_mark_obj8_t markdata = {new_obj, obj8_begin, obj8_end, (9 << 2) | 1 | bits}; + gc_mark_stack_push(&ptls->gc_cache, &sp, gc_mark_laddr(obj8), + &markdata, sizeof(markdata), 0); + obj8 = (gc_mark_obj8_t*)sp.data; + obj8_parent = (char*)ta; + goto obj8_loaded; + } + else if (vt == jl_string_type) { + if (update_meta) + gc_setmark(ptls, o, bits, jl_string_len(new_obj) + sizeof(size_t) + 1); + goto pop; + } + else { + gc_assert_datatype(vt); + if (update_meta) + gc_setmark(ptls, o, bits, jl_datatype_size(vt)); + if (vt == jl_weakref_type) + goto pop; + const jl_datatype_layout_t *layout = vt->layout; + uint32_t npointers = layout->npointers; + if (npointers == 0) + goto pop; + uintptr_t nptr = ((npointers & 0xff) << (npointers & 0x300)) << 2; + nptr = nptr | (bits & GC_OLD); + uint32_t offsets = jl_datatype_layout_n_nonptr(layout); + size_t nfields = layout->nfields; + nfields -= offsets & 0xffff; + size_t first = offsets >> 16; + if (layout->fielddesc_type == 0) { + jl_fielddesc8_t *desc = (jl_fielddesc8_t*)jl_dt_layout_fields(layout); + obj8_parent = (char*)new_obj; + obj8_begin = desc + first; + obj8_end = desc + nfields; + assert(obj8_begin < obj8_end); + gc_mark_obj8_t markdata = {new_obj, obj8_begin, obj8_end, nptr}; + gc_mark_stack_push(&ptls->gc_cache, &sp, gc_mark_laddr(obj8), + &markdata, sizeof(markdata), 0); + obj8 = (gc_mark_obj8_t*)sp.data; + goto obj8_loaded; + } + else if (layout->fielddesc_type == 1) { + jl_fielddesc16_t *desc = (jl_fielddesc16_t*)jl_dt_layout_fields(layout); + obj16_parent = (char*)new_obj; + obj16_begin = desc + first; + obj16_end = desc + nfields; + assert(obj16_begin < obj16_end); + gc_mark_obj16_t markdata = {new_obj, obj16_begin, obj16_end, nptr}; + gc_mark_stack_push(&ptls->gc_cache, &sp, gc_mark_laddr(obj16), + &markdata, sizeof(markdata), 0); + obj16 = (gc_mark_obj16_t*)sp.data; + goto obj16_loaded; + } + else { + // This is very uncommon + // Do not do store to load forwarding to save some code size + assert(layout->fielddesc_type == 2); + jl_fielddesc32_t *desc = (jl_fielddesc32_t*)jl_dt_layout_fields(layout); + assert(first < nfields); + gc_mark_obj32_t markdata = {new_obj, desc + first, desc + nfields, nptr}; + gc_mark_stack_push(&ptls->gc_cache, &sp, gc_mark_laddr(obj32), + &markdata, sizeof(markdata), 0); + sp.data += sizeof(markdata); + goto obj32; + } + } + } +} + #define MAX_MARK_DEPTH 400 // Scan a marked object `v` and recursively mark its children. // The object will be queued on the mark stack when recursion depth @@ -2157,6 +2987,11 @@ void jl_init_thread_heap(jl_ptls_t ptls) gc_cache->perm_scanned_bytes = 0; gc_cache->scanned_bytes = 0; gc_cache->nbig_obj = 0; + JL_MUTEX_INIT(&gc_cache->stack_lock); + size_t init_size = 1024; + gc_cache->pc_stack = (void**)malloc(init_size * sizeof(void*)); + gc_cache->pc_stack_end = gc_cache->pc_stack + init_size; + gc_cache->data_stack = (char*)malloc(init_size * sizeof(gc_mark_data_t)); } // System-wide initializations @@ -2178,6 +3013,8 @@ void jl_gc_init(void) if (maxmem > max_collect_interval) max_collect_interval = maxmem; #endif + gc_mark_sp_t sp = {NULL, NULL, NULL, NULL}; + gc_mark_loop(NULL, sp); } JL_DLLEXPORT void *jl_gc_counted_malloc(size_t sz) diff --git a/src/gc.h b/src/gc.h index 48cc90547f229..0026ae47d64b1 100644 --- a/src/gc.h +++ b/src/gc.h @@ -74,6 +74,141 @@ typedef struct { int full_sweep; } jl_gc_num_t; +typedef struct { + void **pc; // Current stack address for the pc (up growing) + char *data; // Current stack address for the data (up growing) + void **pc_start; // Cached value of `gc_cache->pc_stack` + void **pc_end; // Cached value of `gc_cache->pc_stack_end` +} gc_mark_sp_t; + +enum { + GC_MARK_L_marked_obj, + GC_MARK_L_scan_only, + GC_MARK_L_finlist, + GC_MARK_L_objarray, + GC_MARK_L_obj8, + GC_MARK_L_obj16, + GC_MARK_L_obj32, + GC_MARK_L_stack, + GC_MARK_L_module_binding, + _GC_MARK_L_MAX +}; + +// Pop a data struct from the mark data stack (i.e. decrease the stack pointer) +// This should be used after dispatch and therefore the pc stack pointer is already popped from +// the stack. +STATIC_INLINE void *gc_pop_markdata_(gc_mark_sp_t *sp, size_t size) +{ + char *data = sp->data - size; + sp->data = data; + return data; +} +#define gc_pop_markdata(sp, type) ((type*)gc_pop_markdata_(sp, sizeof(type))) + +// Re-push a frame to the mark stack (both data and pc) +// The data and pc are expected to be on the stack (or updated in place) already. +// Mainly useful to pause the current scanning in order to scan an new object. +STATIC_INLINE void *gc_repush_markdata_(gc_mark_sp_t *sp, size_t size) +{ + char *data = sp->data; + sp->pc++; + sp->data = data + size; + return data; +} +#define gc_repush_markdata(sp, type) ((type*)gc_repush_markdata_(sp, sizeof(type))) + +/** + * The `nptr` member of marking data records the number of pointers slots referenced by + * an object to be used in the full collection heuristics as well as whether the object + * references young objects. + * `nptr >> 2` is the number of pointers fields referenced by the object. + * The lowest bit of `nptr` is set if the object references young object. + * The 2nd lowest bit of `nptr` is the GC old bits of the object after marking. + * A `0x3` in the low bits means that the object needs to be in the remset. + */ + +// An generic object that's marked and needs to be scanned +// The metadata might need update too (depend on the PC) +typedef struct { + jl_value_t *obj; // The object + uintptr_t tag; // The tag with the GC bits masked out + uint8_t bits; // The GC bits after tagging (`bits & 1 == 1`) +} gc_mark_marked_obj_t; + +// An object array. This can come from an array, svec, or the using array or a module +typedef struct { + jl_value_t *parent; // The parent object to trigger write barrier on. + jl_value_t **begin; // The first slot to be scanned. + jl_value_t **end; // The end address (after the last slot to be scanned) + uintptr_t nptr; // See notes about `nptr` above. +} gc_mark_objarray_t; + +// A normal object with 8bits field descriptors +typedef struct { + jl_value_t *parent; // The parent object to trigger write barrier on. + jl_fielddesc8_t *begin; // Current field descriptor. + jl_fielddesc8_t *end; // End of field descriptor. + uintptr_t nptr; // See notes about `nptr` above. +} gc_mark_obj8_t; + +// A normal object with 16bits field descriptors +typedef struct { + jl_value_t *parent; // The parent object to trigger write barrier on. + jl_fielddesc16_t *begin; // Current field descriptor. + jl_fielddesc16_t *end; // End of field descriptor. + uintptr_t nptr; // See notes about `nptr` above. +} gc_mark_obj16_t; + +// A normal object with 32bits field descriptors +typedef struct { + jl_value_t *parent; // The parent object to trigger write barrier on. + jl_fielddesc32_t *begin; // Current field descriptor. + jl_fielddesc32_t *end; // End of field descriptor. + uintptr_t nptr; // See notes about `nptr` above. +} gc_mark_obj32_t; + +// Stack frame +typedef struct { + jl_gcframe_t *s; // The current stack frame + uint32_t i; // The current slot index in the frame + uint32_t nroots; // `nroots` fields in the frame + // Parameters to mark the copy_stack range. + uintptr_t offset; + uintptr_t lb; + uintptr_t ub; +} gc_mark_stackframe_t; + +// Module bindings. This is also the beginning of module scanning. +// The loop will start marking other references in a module after the bindings are marked +typedef struct { + jl_module_t *parent; // The parent module to trigger write barrier on. + jl_binding_t **begin; // The first slot to be scanned. + jl_binding_t **end; // The end address (after the last slot to be scanned) + uintptr_t nptr; // See notes about `nptr` above. + uint8_t bits; // GC bits of the module (the bits to mark the binding buffer with) +} gc_mark_binding_t; + +// Finalizer list +typedef struct { + jl_value_t **begin; + jl_value_t **end; +} gc_mark_finlist_t; + +// This is used to determine the max size of the data objects on the data stack. +// We'll use this size to determine the size of the data stack corresponding to a +// PC stack size. Since the data objects are not all of the same size, we'll waste +// some memory on the data stack this way but that size is unlikely going to be significant. +typedef union { + gc_mark_marked_obj_t marked; + gc_mark_objarray_t objarray; + gc_mark_obj8_t obj8; + gc_mark_obj16_t obj16; + gc_mark_obj32_t obj32; + gc_mark_stackframe_t stackframe; + gc_mark_binding_t binding; + gc_mark_finlist_t finlist; +} gc_mark_data_t; + // layout for big (>2k) objects typedef struct _bigval_t { @@ -343,12 +478,25 @@ STATIC_INLINE void gc_big_object_link(bigval_t *hdr, bigval_t **list) *list = hdr; } +STATIC_INLINE void gc_mark_sp_init(jl_gc_mark_cache_t *gc_cache, gc_mark_sp_t *sp) +{ + sp->pc = gc_cache->pc_stack; + sp->data = gc_cache->data_stack; + sp->pc_start = gc_cache->pc_stack; + sp->pc_end = gc_cache->pc_stack_end; +} + void mark_all_roots(jl_ptls_t ptls); void gc_mark_object_list(jl_ptls_t ptls, arraylist_t *list, size_t start); void visit_mark_stack(jl_ptls_t ptls); +void gc_mark_queue_finlist(jl_gc_mark_cache_t *gc_cache, gc_mark_sp_t *sp, + arraylist_t *list, size_t start); +void gc_mark_loop(jl_ptls_t ptls, gc_mark_sp_t sp); void gc_debug_init(void); void jl_mark_box_caches(jl_ptls_t ptls); +extern void *gc_mark_label_addrs[_GC_MARK_L_MAX]; + // GC pages void jl_gc_init_page(void); @@ -461,10 +609,13 @@ extern int gc_verifying; #else #define gc_verify(ptls) #define verify_val(v) -#define verify_parent1(ty,obj,slot,arg1) -#define verify_parent2(ty,obj,slot,arg1,arg2) +#define verify_parent1(ty,obj,slot,arg1) do {} while (0) +#define verify_parent2(ty,obj,slot,arg1,arg2) do {} while (0) #define gc_verifying (0) #endif +int gc_slot_to_fieldidx(void *_obj, void *slot); +int gc_slot_to_arrayidx(void *_obj, void *begin); +NOINLINE void gc_mark_loop_unwind(jl_ptls_t ptls, gc_mark_sp_t sp, int pc_offset); #ifdef GC_DEBUG_ENV JL_DLLEXPORT extern jl_gc_debug_env_t jl_gc_debug_env; diff --git a/src/julia_threads.h b/src/julia_threads.h index 7d7c127588007..1051d740c8b85 100644 --- a/src/julia_threads.h +++ b/src/julia_threads.h @@ -88,6 +88,10 @@ typedef struct { // this makes sure that a single objects can only appear once in // the lists (the mark bit cannot be flipped to `0` without sweeping) void *big_obj[1024]; + jl_mutex_t stack_lock; + void **pc_stack; + void **pc_stack_end; + char *data_stack; } jl_gc_mark_cache_t; // This includes all the thread local states we care about for a thread. From 96d23d9f0ea7a3e291aeb480377ef6b5b3ecd336 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Sun, 23 Apr 2017 13:31:36 -0400 Subject: [PATCH 0676/1534] Use mark loop in GC --- src/gc-debug.c | 26 +-- src/gc.c | 454 +++++-------------------------------------------- src/gc.h | 4 +- 3 files changed, 64 insertions(+), 420 deletions(-) diff --git a/src/gc-debug.c b/src/gc-debug.c index 4767750b92814..69f02b0dab3ab 100644 --- a/src/gc-debug.c +++ b/src/gc-debug.c @@ -198,18 +198,21 @@ static void restore(void) static void gc_verify_track(jl_ptls_t ptls) { + jl_gc_mark_cache_t *gc_cache = &ptls->gc_cache; do { + gc_mark_sp_t sp; + gc_mark_sp_init(gc_cache, &sp); arraylist_push(&lostval_parents_done, lostval); jl_printf(JL_STDERR, "Now looking for %p =======\n", lostval); clear_mark(GC_CLEAN); - mark_all_roots(ptls); - gc_mark_object_list(ptls, &to_finalize, 0); + gc_mark_queue_all_roots(ptls, &sp); + gc_mark_queue_finlist(gc_cache, &sp, &to_finalize, 0); for (int i = 0;i < jl_n_threads;i++) { jl_ptls_t ptls2 = jl_all_tls_states[i]; - gc_mark_object_list(ptls, &ptls2->finalizers, 0); + gc_mark_queue_finlist(gc_cache, &sp, &ptls2->finalizers, 0); } - gc_mark_object_list(ptls, &finalizer_list_marked, 0); - visit_mark_stack(ptls); + gc_mark_queue_finlist(gc_cache, &sp, &finalizer_list_marked, 0); + gc_mark_loop(ptls, sp); if (lostval_parents.len == 0) { jl_printf(JL_STDERR, "Could not find the missing link. We missed a toplevel root. This is odd.\n"); break; @@ -243,19 +246,22 @@ static void gc_verify_track(jl_ptls_t ptls) void gc_verify(jl_ptls_t ptls) { + jl_gc_mark_cache_t *gc_cache = &ptls->gc_cache; + gc_mark_sp_t sp; + gc_mark_sp_init(gc_cache, &sp); lostval = NULL; lostval_parents.len = 0; lostval_parents_done.len = 0; clear_mark(GC_CLEAN); gc_verifying = 1; - mark_all_roots(ptls); - gc_mark_object_list(ptls, &to_finalize, 0); + gc_mark_queue_all_roots(ptls, &sp); + gc_mark_queue_finlist(gc_cache, &sp, &to_finalize, 0); for (int i = 0;i < jl_n_threads;i++) { jl_ptls_t ptls2 = jl_all_tls_states[i]; - gc_mark_object_list(ptls, &ptls2->finalizers, 0); + gc_mark_queue_finlist(gc_cache, &sp, &ptls2->finalizers, 0); } - gc_mark_object_list(ptls, &finalizer_list_marked, 0); - visit_mark_stack(ptls); + gc_mark_queue_finlist(gc_cache, &sp, &finalizer_list_marked, 0); + gc_mark_loop(ptls, sp); int clean_len = bits_save[GC_CLEAN].len; for(int i = 0; i < clean_len + bits_save[GC_OLD].len; i++) { jl_taggedvalue_t *v = (jl_taggedvalue_t*)bits_save[i >= clean_len ? GC_OLD : GC_CLEAN].items[i >= clean_len ? i - clean_len : i]; diff --git a/src/gc.c b/src/gc.c index c40234f99709c..497e76d612740 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1256,25 +1256,6 @@ static void gc_sweep_pool(int sweep_full) // mark phase -static jl_value_t **mark_stack = NULL; -static jl_value_t **mark_stack_base = NULL; -static size_t mark_stack_size = 0; -static size_t mark_sp = 0; - -static void grow_mark_stack(void) -{ - size_t newsz = mark_stack_size>0 ? mark_stack_size*2 : 32000; - size_t offset = mark_stack - mark_stack_base; - mark_stack_base = (jl_value_t**)realloc(mark_stack_base, newsz*sizeof(void*)); - if (mark_stack_base == NULL) { - jl_printf(JL_STDERR, "Couldn't grow mark stack to : %" PRIuPTR "\n", - (uintptr_t)newsz); - exit(1); - } - mark_stack = mark_stack_base + offset; - mark_stack_size = newsz; -} - JL_DLLEXPORT void jl_gc_queue_root(jl_value_t *ptr) { jl_ptls_t ptls = jl_get_ptls_states(); @@ -1306,36 +1287,9 @@ void gc_queue_binding(jl_binding_t *bnd) arraylist_push(&ptls->heap.rem_bindings, bnd); } -static void gc_scan_obj_(jl_ptls_t ptls, jl_value_t *v, int d, - uintptr_t tag, uint8_t bits); -static void gc_mark_obj(jl_ptls_t ptls, jl_value_t *v, - uintptr_t tag, uint8_t bits); #ifdef JL_DEBUG_BUILD static void *volatile gc_findval; // for usage from gdb, for finding the gc-root for a value #endif -// Returns whether the object is young -STATIC_INLINE int gc_push_root(jl_ptls_t ptls, void *v, int d) // v isa jl_value_t* -{ -#ifdef JL_DEBUG_BUILD - if (v == gc_findval) - jl_raise_debugger(); -#endif - assert(v != NULL); - jl_taggedvalue_t *o = jl_astaggedvalue(v); - verify_val(v); - uintptr_t tag = o->header; - if (!gc_marked(tag)) { - uint8_t bits; - if (__likely(gc_setmark_tag(o, GC_MARKED, tag, &bits))) { - tag = tag & ~(uintptr_t)15; - if (!gc_verifying) - gc_mark_obj(ptls, (jl_value_t*)v, tag, bits); - gc_scan_obj_(ptls, (jl_value_t*)v, d, tag, bits); - } - return !gc_old(bits); - } - return !gc_old(tag); -} // TODO rename this as it is misleading now void jl_gc_setmark(jl_ptls_t ptls, jl_value_t *v) @@ -1350,43 +1304,6 @@ void jl_gc_setmark(jl_ptls_t ptls, jl_value_t *v) } } -NOINLINE static int gc_mark_module(jl_ptls_t ptls, jl_module_t *m, - int d, int8_t bits) -{ - size_t i; - int refyoung = 0; - void **table = m->bindings.table; - for(i=1; i < m->bindings.size; i+=2) { - if (table[i] != HT_NOTFOUND) { - jl_binding_t *b = (jl_binding_t*)table[i]; - gc_setmark_buf_(ptls, b, bits, sizeof(jl_binding_t)); - void *vb = jl_astaggedvalue(b); - verify_parent1("module", m, &vb, "binding_buff"); - (void)vb; - if (b->value != NULL) { - verify_parent2("module", m, &b->value, "binding(%s)", - jl_symbol_name(b->name)); - refyoung |= gc_push_root(ptls, b->value, d); - } - if (b->globalref != NULL) - refyoung |= gc_push_root(ptls, b->globalref, d); - } - } - // this is only necessary because bindings for "using" modules - // are added only when accessed. therefore if a module is replaced - // after "using" it but before accessing it, this array might - // contain the only reference. - for(i=0; i < m->usings.len; i++) { - refyoung |= gc_push_root(ptls, m->usings.items[i], d); - } - - if (m->parent) { - refyoung |= gc_push_root(ptls, m->parent, d); - } - - return refyoung; -} - // Handle the case where the stack is only partially copied. STATIC_INLINE uintptr_t gc_get_stack_addr(void *_addr, uintptr_t offset, uintptr_t lb, uintptr_t ub) @@ -1404,113 +1321,17 @@ STATIC_INLINE uintptr_t gc_read_stack(void *_addr, uintptr_t offset, return *(uintptr_t*)real_addr; } -static void gc_mark_stack(jl_ptls_t ptls, jl_gcframe_t *s, uintptr_t offset, - uintptr_t lb, uintptr_t ub, int d) -{ - while (s != NULL) { - jl_value_t ***rts = (jl_value_t***)(((void**)s) + 2); - size_t nroots = gc_read_stack(&s->nroots, offset, lb, ub); - size_t nr = nroots >> 1; - if (nroots & 1) { - for (size_t i = 0; i < nr; i++) { - void **slot = (void**)gc_read_stack(&rts[i], offset, lb, ub); - void *obj = (void*)gc_read_stack(slot, offset, lb, ub); - if (obj != NULL) { - gc_push_root(ptls, obj, d); - } - } - } - else { - for (size_t i=0; i < nr; i++) { - void *obj = (void*)gc_read_stack(&rts[i], offset, lb, ub); - if (obj) { - gc_push_root(ptls, obj, d); - } - } - } - s = (jl_gcframe_t*)gc_read_stack(&s->prev, offset, lb, ub); - } -} - -static void gc_mark_task_stack(jl_ptls_t ptls, jl_task_t *ta, int d, int8_t bits) -{ - gc_scrub_record_task(ta); - int stkbuf = (ta->stkbuf != (void*)(intptr_t)-1 && ta->stkbuf != NULL); - int16_t tid = ta->tid; - jl_ptls_t ptls2 = jl_all_tls_states[tid]; - if (stkbuf) { -#ifdef COPY_STACKS - gc_setmark_buf_(ptls, ta->stkbuf, bits, ta->bufsz); -#else - // stkbuf isn't owned by julia for the root task - if (ta != ptls2->root_task) { - gc_setmark_buf_(ptls, ta->stkbuf, bits, ta->ssize); - } -#endif - } - if (ta == ptls2->current_task) { - gc_mark_stack(ptls, ptls2->pgcstack, 0, 0, (uintptr_t)-1, d); - } - else if (stkbuf) { - uintptr_t offset = 0; - uintptr_t lb = 0; - uintptr_t ub = (uintptr_t)-1; -#ifdef COPY_STACKS - ub = (uintptr_t)ptls2->stackbase; - lb = ub - ta->ssize; - offset = (uintptr_t)ta->stkbuf - lb; -#endif - gc_mark_stack(ptls, ta->gcstack, offset, lb, ub, d); - } -} - -NOINLINE static void gc_mark_task(jl_ptls_t ptls, jl_task_t *ta, - int d, int8_t bits) -{ - if (ta->parent) gc_push_root(ptls, ta->parent, d); - gc_push_root(ptls, ta->tls, d); - gc_push_root(ptls, ta->consumers, d); - gc_push_root(ptls, ta->donenotify, d); - gc_push_root(ptls, ta->exception, d); - if (ta->backtrace) gc_push_root(ptls, ta->backtrace, d); - if (ta->start) gc_push_root(ptls, ta->start, d); - if (ta->result) gc_push_root(ptls, ta->result, d); - gc_mark_task_stack(ptls, ta, d, bits); -} - -void gc_mark_object_list(jl_ptls_t ptls, arraylist_t *list, size_t start) -{ - void **items = list->items; - size_t len = list->len; - for (size_t i = start;i < len;i++) { - void *v = items[i]; - if (__unlikely(!v)) - continue; - if (gc_ptr_tag(v, 1)) { - v = gc_ptr_clear_tag(v, 1); - i++; - assert(i < len); - } - gc_push_root(ptls, v, 0); - } -} - -JL_NORETURN NOINLINE void gc_assert_datatype_fail(jl_datatype_t *vt) +JL_NORETURN NOINLINE void gc_assert_datatype_fail(jl_ptls_t ptls, jl_datatype_t *vt, + gc_mark_sp_t sp) { jl_printf(JL_STDOUT, "GC error (probable corruption) :\n"); gc_debug_print_status(); jl_(vt); gc_debug_critical_error(); + gc_mark_loop_unwind(ptls, sp, 0); abort(); } -STATIC_INLINE void gc_assert_datatype(jl_datatype_t *vt) -{ - if (__likely(jl_is_datatype(vt))) - return; - gc_assert_datatype_fail(vt); -} - // This stores the label address in the mark loop function. // We can't directly store that to a global array so we need some hack to get that. // See the call to `gc_mark_loop` in init with a `NULL` `ptls`. @@ -2286,7 +2107,8 @@ mark: { goto pop; } else { - gc_assert_datatype(vt); + if (__unlikely(!jl_is_datatype(vt))) + gc_assert_datatype_fail(ptls, vt, sp); if (update_meta) gc_setmark(ptls, o, bits, jl_datatype_size(vt)); if (vt == jl_weakref_type) @@ -2341,236 +2163,50 @@ mark: { } } -#define MAX_MARK_DEPTH 400 -// Scan a marked object `v` and recursively mark its children. -// The object will be queued on the mark stack when recursion depth -// becomes too high. -// It does so assuming that the tag of the (marked) object is `tag`. -// If `v` is `GC_OLD_MARKED` and some of its children are `GC_MARKED` (young), -// `v` is added to the remset -static void gc_scan_obj_(jl_ptls_t ptls, jl_value_t *v, int d, - uintptr_t tag, uint8_t bits) -{ - assert(v != NULL); - assert(gc_marked(bits)); - jl_datatype_t *vt = (jl_datatype_t*)tag; -#ifdef JL_DEBUG_BUILD - gc_assert_datatype(vt); // should have checked in `gc_mark_obj` -#endif - int refyoung = 0, nptr = 0; - - assert(vt != jl_symbol_type); - // weakref should not be marked - if (vt == jl_weakref_type) - return; - // fast path - uint32_t npointers = vt->layout->npointers; - if (npointers == 0) - return; - d++; - if (d >= MAX_MARK_DEPTH) - goto queue_the_root; - - // some values have special representations - if (vt == jl_simplevector_type) { - size_t l = jl_svec_len(v); - jl_value_t **data = jl_svec_data(v); - nptr += l; - for(size_t i=0; i < l; i++) { - jl_value_t *elt = data[i]; - if (elt != NULL) { - verify_parent2("svec", v, &data[i], "elem(%d)", (int)i); - refyoung |= gc_push_root(ptls, elt, d); - } - } - } - else if (vt->name == jl_array_typename) { - jl_array_t *a = (jl_array_t*)v; - jl_array_flags_t flags = a->flags; - if (flags.how == 3) { - jl_value_t *owner = jl_array_data_owner(a); - refyoung |= gc_push_root(ptls, owner, d); - goto ret; - } - else if (flags.how == 1) { - void *val_buf = jl_astaggedvalue((char*)a->data - - a->offset * a->elsize); - verify_parent1("array", v, &val_buf, - "buffer ('loc' addr is meaningless)"); - (void)val_buf; - gc_setmark_buf_(ptls, (char*)a->data - a->offset * a->elsize, - bits, array_nbytes(a)); - } - if (flags.ptrarray && a->data != NULL) { - size_t l = jl_array_len(a); - if (l > 100000 && d > MAX_MARK_DEPTH-10) { - // don't mark long arrays at high depth, to try to avoid - // copying the whole array into the mark queue - goto queue_the_root; - } - else { - nptr += l; - void *data = a->data; - for (size_t i=0; i < l; i++) { - jl_value_t *elt = ((jl_value_t**)data)[i]; - if (elt != NULL) { - verify_parent2("array", v, &((jl_value_t**)data)[i], "elem(%d)", (int)i); - refyoung |= gc_push_root(ptls, elt, d); - } - } - } - } - } - else if (vt == jl_module_type) { - // should increase nptr here - refyoung |= gc_mark_module(ptls, (jl_module_t*)v, d, bits); - } - else if (vt == jl_task_type) { - // ditto nptr - gc_mark_task(ptls, (jl_task_t*)v, d, bits); - // tasks should always be remarked since we do not trigger the write barrier - // for stores to stack slots - refyoung = 1; - } - else { - int nf = (int)jl_datatype_nfields(vt); - nptr += (npointers & 0xff) << (npointers & 0x300); - uint32_t offsets = jl_datatype_layout_n_nonptr(vt->layout); - nf -= offsets & 0xffff; - for (int i = (offsets >> 16); i < nf; i++) { - if (jl_field_isptr(vt, i)) { - jl_value_t **slot = (jl_value_t**)((char*)v + jl_field_offset(vt, i)); - jl_value_t *fld = *slot; - if (fld) { - verify_parent2("object", v, slot, "field(%d)", i); - refyoung |= gc_push_root(ptls, fld, d); - } - } - } - } - -ret: - if ((bits == GC_OLD_MARKED) && refyoung && !gc_verifying) { - ptls->heap.remset_nptr += nptr; - // v is an old object referencing young objects - arraylist_push(ptls->heap.remset, v); - } - return; - -queue_the_root: - if (mark_sp >= mark_stack_size) - grow_mark_stack(); - mark_stack[mark_sp++] = (jl_value_t*)v; -} - -STATIC_INLINE void gc_scan_obj(jl_ptls_t ptls, jl_value_t *v, int d, - uintptr_t tag) -{ - gc_scan_obj_(ptls, v, d, tag & ~(uintptr_t)15, tag & 0xf); -} - -// Update the metadata of a marked object (without scanning it). -static void gc_mark_obj(jl_ptls_t ptls, jl_value_t *v, - uintptr_t tag, uint8_t bits) -{ - assert(v != NULL); - assert(gc_marked(bits)); - jl_taggedvalue_t *o = jl_astaggedvalue(v); - jl_datatype_t *vt = (jl_datatype_t*)(tag & ~(uintptr_t)15); - gc_assert_datatype(vt); - // Symbols are always marked - assert(vt != jl_symbol_type); - - // some values have special representations - if (vt == jl_simplevector_type) { - size_t l = jl_svec_len(v); - gc_setmark(ptls, o, bits, l * sizeof(void*) + sizeof(jl_svec_t)); - } - else if (vt->name == jl_array_typename) { - jl_array_t *a = (jl_array_t*)v; - jl_array_flags_t flags = a->flags; - if (flags.pooled) - gc_setmark_pool(ptls, o, bits); - else - gc_setmark_big(ptls, o, bits); - if (flags.how == 2) { - objprofile_count(jl_malloc_tag, bits == GC_OLD_MARKED, - array_nbytes(a)); - if (bits == GC_OLD_MARKED) { - ptls->gc_cache.perm_scanned_bytes += array_nbytes(a); - } - else { - ptls->gc_cache.scanned_bytes += array_nbytes(a); - } - } - } - else if (vt == jl_module_type) { - gc_setmark(ptls, o, bits, sizeof(jl_module_t)); - } - else if (vt == jl_task_type) { - gc_setmark(ptls, o, bits, sizeof(jl_task_t)); - } - else if (vt == jl_string_type) { - gc_setmark(ptls, o, bits, jl_string_len(v) + sizeof(size_t) + 1); - } - else { - gc_setmark(ptls, o, bits, jl_datatype_size(vt)); - } -} - -void visit_mark_stack(jl_ptls_t ptls) -{ - while (mark_sp > 0 && !should_timeout()) { - jl_value_t *v = mark_stack[--mark_sp]; - assert(jl_astaggedvalue(v)->bits.gc); - gc_scan_obj(ptls, v, 0, jl_astaggedvalue(v)->header); - } - assert(!mark_sp); -} - extern jl_array_t *jl_module_init_order; extern jl_typemap_entry_t *call_cache[N_CALL_CACHE]; extern jl_array_t *jl_all_methods; -static void jl_gc_mark_thread_local(jl_ptls_t ptls, jl_ptls_t ptls2) +static void jl_gc_queue_thread_local(jl_gc_mark_cache_t *gc_cache, gc_mark_sp_t *sp, + jl_ptls_t ptls2) { // `current_module` might not have a value when the thread is not // running. if (ptls2->current_module) - gc_push_root(ptls, ptls2->current_module, 0); - gc_push_root(ptls, ptls2->current_task, 0); - gc_push_root(ptls, ptls2->root_task, 0); - gc_push_root(ptls, ptls2->exception_in_transit, 0); + gc_mark_queue_obj(gc_cache, sp, ptls2->current_module); + gc_mark_queue_obj(gc_cache, sp, ptls2->current_task); + gc_mark_queue_obj(gc_cache, sp, ptls2->root_task); + gc_mark_queue_obj(gc_cache, sp, ptls2->exception_in_transit); } // mark the initial root set -static void mark_roots(jl_ptls_t ptls) +static void mark_roots(jl_gc_mark_cache_t *gc_cache, gc_mark_sp_t *sp) { // modules - gc_push_root(ptls, jl_main_module, 0); - gc_push_root(ptls, jl_internal_main_module, 0); + gc_mark_queue_obj(gc_cache, sp, jl_main_module); + gc_mark_queue_obj(gc_cache, sp, jl_internal_main_module); // invisible builtin values if (jl_an_empty_vec_any != NULL) - gc_push_root(ptls, jl_an_empty_vec_any, 0); + gc_mark_queue_obj(gc_cache, sp, jl_an_empty_vec_any); if (jl_module_init_order != NULL) - gc_push_root(ptls, jl_module_init_order, 0); - gc_push_root(ptls, jl_cfunction_list.unknown, 0); - gc_push_root(ptls, jl_anytuple_type_type, 0); - gc_push_root(ptls, jl_ANY_flag, 0); + gc_mark_queue_obj(gc_cache, sp, jl_module_init_order); + gc_mark_queue_obj(gc_cache, sp, jl_cfunction_list.unknown); + gc_mark_queue_obj(gc_cache, sp, jl_anytuple_type_type); + gc_mark_queue_obj(gc_cache, sp, jl_ANY_flag); for (size_t i = 0; i < N_CALL_CACHE; i++) if (call_cache[i]) - gc_push_root(ptls, call_cache[i], 0); + gc_mark_queue_obj(gc_cache, sp, call_cache[i]); if (jl_all_methods != NULL) - gc_push_root(ptls, jl_all_methods, 0); + gc_mark_queue_obj(gc_cache, sp, jl_all_methods); #ifndef COPY_STACKS - gc_push_root(ptls, jl_unprotect_stack_func, 0); + gc_mark_queue_obj(gc_cache, sp, jl_unprotect_stack_func); #endif // constants - gc_push_root(ptls, jl_typetype_type, 0); - gc_push_root(ptls, jl_emptytuple_type, 0); + gc_mark_queue_obj(gc_cache, sp, jl_typetype_type); + gc_mark_queue_obj(gc_cache, sp, jl_emptytuple_type); } // find unmarked objects that need to be finalized from the finalizer list "list". @@ -2704,14 +2340,12 @@ static void jl_gc_premark(jl_ptls_t ptls2) } } -static void jl_gc_mark_remset(jl_ptls_t ptls, jl_ptls_t ptls2) +static void jl_gc_queue_remset(jl_gc_mark_cache_t *gc_cache, gc_mark_sp_t *sp, jl_ptls_t ptls2) { size_t len = ptls2->heap.last_remset->len; void **items = ptls2->heap.last_remset->items; - for (size_t i = 0; i < len; i++) { - jl_value_t *item = (jl_value_t*)items[i]; - gc_scan_obj(ptls, item, 0, jl_astaggedvalue(item)->header); - } + for (size_t i = 0; i < len; i++) + gc_mark_queue_scan_obj(gc_cache, sp, (jl_value_t*)items[i]); int n_bnd_refyoung = 0; len = ptls2->heap.rem_bindings.len; items = ptls2->heap.rem_bindings.items; @@ -2720,7 +2354,7 @@ static void jl_gc_mark_remset(jl_ptls_t ptls, jl_ptls_t ptls2) // A null pointer can happen here when the binding is cleaned up // as an exception is thrown after it was already queued (#10221) if (!ptr->value) continue; - if (gc_push_root(ptls, ptr->value, 0)) { + if (gc_mark_queue_obj(gc_cache, sp, ptr->value)) { items[n_bnd_refyoung] = ptr; n_bnd_refyoung++; } @@ -2741,9 +2375,12 @@ static void jl_gc_mark_ptrfree(jl_ptls_t ptls) // Only one thread should be running in this function static int _jl_gc_collect(jl_ptls_t ptls, int full) { + jl_gc_mark_cache_t *gc_cache = &ptls->gc_cache; + gc_mark_sp_t sp; + gc_mark_sp_init(gc_cache, &sp); + uint64_t t0 = jl_hrtime(); int64_t last_perm_scanned_bytes = perm_scanned_bytes; - assert(mark_sp == 0); // 1. fix GC bits of objects in the remset. for (int t_i = 0; t_i < jl_n_threads; t_i++) @@ -2752,14 +2389,15 @@ static int _jl_gc_collect(jl_ptls_t ptls, int full) for (int t_i = 0; t_i < jl_n_threads; t_i++) { jl_ptls_t ptls2 = jl_all_tls_states[t_i]; // 2.1. mark every object in the `last_remsets` and `rem_binding` - jl_gc_mark_remset(ptls, ptls2); + jl_gc_queue_remset(gc_cache, &sp, ptls2); // 2.2. mark every thread local root - jl_gc_mark_thread_local(ptls, ptls2); + jl_gc_queue_thread_local(gc_cache, &sp, ptls2); } // 3. walk roots - mark_roots(ptls); - visit_mark_stack(ptls); + mark_roots(gc_cache, &sp); + gc_mark_loop(ptls, sp); + gc_mark_sp_init(gc_cache, &sp); gc_num.since_sweep += gc_num.allocd + (int64_t)gc_num.interval; gc_settime_premark_end(); gc_time_mark_pause(t0, scanned_bytes, perm_scanned_bytes); @@ -2781,19 +2419,20 @@ static int _jl_gc_collect(jl_ptls_t ptls, int full) } for (int i = 0;i < jl_n_threads;i++) { jl_ptls_t ptls2 = jl_all_tls_states[i]; - gc_mark_object_list(ptls, &ptls2->finalizers, 0); + gc_mark_queue_finlist(gc_cache, &sp, &ptls2->finalizers, 0); } - gc_mark_object_list(ptls, &finalizer_list_marked, orig_marked_len); + gc_mark_queue_finlist(gc_cache, &sp, &finalizer_list_marked, orig_marked_len); // "Flush" the mark stack before flipping the reset_age bit // so that the objects are not incorrectly resetted. - visit_mark_stack(ptls); + gc_mark_loop(ptls, sp); + gc_mark_sp_init(gc_cache, &sp); mark_reset_age = 1; // Reset the age and old bit for any unmarked objects referenced by the // `to_finalize` list. These objects are only reachable from this list // and should not be referenced by any old objects so this won't break // the GC invariant. - gc_mark_object_list(ptls, &to_finalize, 0); - visit_mark_stack(ptls); + gc_mark_queue_finlist(gc_cache, &sp, &to_finalize, 0); + gc_mark_loop(ptls, sp); mark_reset_age = 0; gc_settime_postmark_end(); @@ -2944,11 +2583,12 @@ JL_DLLEXPORT void jl_gc_collect(int full) } } -void mark_all_roots(jl_ptls_t ptls) +void gc_mark_queue_all_roots(jl_ptls_t ptls, gc_mark_sp_t *sp) { + jl_gc_mark_cache_t *gc_cache = &ptls->gc_cache; for (size_t i = 0; i < jl_n_threads; i++) - jl_gc_mark_thread_local(ptls, jl_all_tls_states[i]); - mark_roots(ptls); + jl_gc_queue_thread_local(gc_cache, sp, jl_all_tls_states[i]); + mark_roots(gc_cache, sp); jl_gc_mark_ptrfree(ptls); } diff --git a/src/gc.h b/src/gc.h index 0026ae47d64b1..44785fda43298 100644 --- a/src/gc.h +++ b/src/gc.h @@ -486,9 +486,7 @@ STATIC_INLINE void gc_mark_sp_init(jl_gc_mark_cache_t *gc_cache, gc_mark_sp_t *s sp->pc_end = gc_cache->pc_stack_end; } -void mark_all_roots(jl_ptls_t ptls); -void gc_mark_object_list(jl_ptls_t ptls, arraylist_t *list, size_t start); -void visit_mark_stack(jl_ptls_t ptls); +void gc_mark_queue_all_roots(jl_ptls_t ptls, gc_mark_sp_t *sp); void gc_mark_queue_finlist(jl_gc_mark_cache_t *gc_cache, gc_mark_sp_t *sp, arraylist_t *list, size_t start); void gc_mark_loop(jl_ptls_t ptls, gc_mark_sp_t sp); From 1aa85c4447c84b2290336eaf44831d373b3718ea Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Sat, 6 May 2017 23:52:06 -0400 Subject: [PATCH 0677/1534] Clean up of jl_assume * Make sure the unused result of `jl_assume` is explicitly discarded to suppress compiler warnings * Enable it on other GCC compatible compilers (like mingw) too --- src/julia_internal.h | 35 ++++++++++++++++------------------- src/threading.c | 2 +- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/src/julia_internal.h b/src/julia_internal.h index 216d0833846ed..7ae0d3391c195 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -47,16 +47,26 @@ #endif #if jl_has_builtin(__builtin_assume) -static inline void jl_assume_(int cond) +#define jl_assume(cond) (__extension__ ({ \ + __typeof__(cond) cond_ = (cond); \ + __builtin_assume(!!(cond_)); \ + cond_; \ + })) +#elif defined(_COMPILER_MICROSOFT_) && defined(__cplusplus) +template +static inline T +jl_assume(T v) { - __builtin_assume(cond); + __assume(!!v); + return v; } +#elif defined(_COMPILER_INTEL_) #define jl_assume(cond) (__extension__ ({ \ __typeof__(cond) cond_ = (cond); \ - jl_assume_(!!(cond_)); \ - cond; \ + __assume(!!(cond_)); \ + cond_; \ })) -#elif defined(_COMPILER_GCC_) +#elif defined(__GNUC__) static inline void jl_assume_(int cond) { if (!cond) { @@ -68,19 +78,6 @@ static inline void jl_assume_(int cond) jl_assume_(!!(cond_)); \ cond_; \ })) -#elif defined(_COMPILER_INTEL_) -#define jl_assume(cond) (__extension__ ({ \ - __assume(!!(cond)); \ - cond; \ - })) -#elif defined(_COMPILER_MICROSOFT_) && defined(__cplusplus) -template -static inline T -jl_assume(T v) -{ - __assume(!!v); - return v; -} #else #define jl_assume(cond) (cond) #endif @@ -352,7 +349,7 @@ STATIC_INLINE jl_value_t *jl_call_method_internal(jl_method_instance_t *meth, jl jl_value_t *v = jl_compile_method_internal(&fptr, meth); if (v) return v; - jl_assume(fptr.jlcall_api != 2); + (void)jl_assume(fptr.jlcall_api != 2); return jl_call_fptr_internal(&fptr, meth, args, nargs); } diff --git a/src/threading.c b/src/threading.c index 4d45433932a5d..6792c10acf0b5 100644 --- a/src/threading.c +++ b/src/threading.c @@ -309,7 +309,7 @@ static jl_value_t *ti_run_fun(const jl_generic_fptr_t *fptr, jl_method_instance_ { jl_ptls_t ptls = jl_get_ptls_states(); JL_TRY { - jl_assume(fptr->jlcall_api != 2); + (void)jl_assume(fptr->jlcall_api != 2); jl_call_fptr_internal(fptr, mfunc, args, nargs); } JL_CATCH { From e257ef4c1b010c8117dd27d3d9b8ab0c00f6712d Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Sun, 7 May 2017 18:41:51 +0200 Subject: [PATCH 0678/1534] Improve docstrings for norm, vecnorm, normalize and normalize! (#21611) * Improve docstrings for norm, vecnorm, normalize and normalize! Add equations defining the norms, reorganize the docstrings by argument type, and mention what "normalizing" means. [av skip] * Remove docstring for the norm() function --- base/linalg/generic.jl | 89 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 72 insertions(+), 17 deletions(-) diff --git a/base/linalg/generic.jl b/base/linalg/generic.jl index 733f5779c1c9d..6f44208621bd4 100644 --- a/base/linalg/generic.jl +++ b/base/linalg/generic.jl @@ -412,13 +412,22 @@ vecnorm2(x) = generic_vecnorm2(x) vecnormp(x, p) = generic_vecnormp(x, p) """ - vecnorm(A, [p::Real=2]) + vecnorm(A, p::Real=2) For any iterable container `A` (including arrays of any dimension) of numbers (or any element type for which `norm` is defined), compute the `p`-norm (defaulting to `p=2`) as if `A` were a vector of the corresponding length. -For example, if `A` is a matrix and `p=2`, then this is equivalent to the Frobenius norm. +The `p`-norm is defined as: +```math +\\|A\\|_p = \\left( \\sum_{i=1}^n | a_i | ^p \\right)^{1/p} +``` +with ``a_i`` the entries of ``A`` and ``n`` its length. + +`p` can assume any numeric value (even though not all values produce a +mathematically valid vector norm). In particular, `vecnorm(A, Inf)` returns the largest value +in `abs(A)`, whereas `vecnorm(A, -Inf)` returns the smallest. If `A` is a matrix and `p=2`, +then this is equivalent to the Frobenius norm. # Example @@ -447,9 +456,13 @@ function vecnorm(itr, p::Real=2) vecnormp(itr,p) end end -@inline vecnorm(x::Number, p::Real=2) = p == 0 ? (x==0 ? zero(abs(x)) : oneunit(abs(x))) : abs(x) -norm(x::AbstractVector, p::Real=2) = vecnorm(x, p) +""" + vecnorm(x::Number, p::Real=2) + +For numbers, return ``\\left( |x|^p \\right) ^{1/p}``. +""" +@inline vecnorm(x::Number, p::Real=2) = p == 0 ? (x==0 ? zero(abs(x)) : oneunit(abs(x))) : abs(x) function norm1(A::AbstractMatrix{T}) where T m, n = size(A) @@ -491,18 +504,27 @@ function normInf(A::AbstractMatrix{T}) where T end """ - norm(A, [p::Real=2]) + norm(A::AbstractArray, p::Real=2) + +Compute the `p`-norm of a vector or the operator norm of a matrix `A`, +defaulting to the 2-norm. -Compute the `p`-norm of a vector or the operator norm of a matrix `A`, defaulting to the `p=2`-norm. + norm(A::AbstractVector, p::Real=2) -For vectors, `p` can assume any numeric value (even though not all values produce a +For vectors, this is equivalent to [`vecnorm`](@ref) and equal to: +```math +\\|A\\|_p = \\left( \\sum_{i=1}^n | a_i | ^p \\right)^{1/p} +``` +with ``a_i`` the entries of ``A`` and ``n`` its length. + +`p` can assume any numeric value (even though not all values produce a mathematically valid vector norm). In particular, `norm(A, Inf)` returns the largest value in `abs(A)`, whereas `norm(A, -Inf)` returns the smallest. # Example ```jldoctest -julia> v = [3;-2;6] +julia> v = [3, -2, 6] 3-element Array{Int64,1}: 3 -2 @@ -514,11 +536,30 @@ julia> norm(v) julia> norm(v, Inf) 6.0 ``` +""" +norm(x::AbstractVector, p::Real=2) = vecnorm(x, p) + +""" + norm(A::AbstractMatrix, p::Real=2) For matrices, the matrix norm induced by the vector `p`-norm is used, where valid values of `p` are `1`, `2`, or `Inf`. (Note that for sparse matrices, `p=2` is currently not implemented.) Use [`vecnorm`](@ref) to compute the Frobenius norm. +When `p=1`, the matrix norm is the maximum absolute column sum of `A`: +```math +\\|A\\|_1 = \\max_{1 ≤ j ≤ n} \\sum_{i=1}^m | a_{ij} | +``` +with ``a_{ij}`` the entries of ``A``, and ``m`` and ``n`` its dimensions. + +When `p=2`, the matrix norm is the spectral norm, equal to the largest +singular value of `A`. + +When `p=Inf`, the matrix norm is the maximum absolute row sum of `A`: +```math +\\|A\\|_\\infty = \\max_{1 ≤ i ≤ m} \\sum _{j=1}^n | a_{ij} | +``` + # Example ```jldoctest @@ -543,14 +584,20 @@ function norm(A::AbstractMatrix, p::Real=2) end end +""" + norm(x::Number, p::Real=2) + +For numbers, return ``\\left( |x|^p \\right)^{1/p}``. +This is equivalent to [`vecnorm`](@ref). +""" @inline norm(x::Number, p::Real=2) = vecnorm(x, p) @inline norm(tv::RowVector) = norm(transpose(tv)) """ - norm(rowvector, [q = 2]) + norm(A::RowVector, q::Real=2) -Takes the q-norm of a `RowVector`, which is equivalent to the p-norm with +For row vectors, return the ``q``-norm of `A`, which is equivalent to the p-norm with value `p = q/(q-1)`. They coincide at `p = q = 2`. The difference in norm between a vector space and its dual arises to preserve @@ -1240,10 +1287,11 @@ function isapprox(x::AbstractArray, y::AbstractArray; end """ - normalize!(v, [p::Real=2]) + normalize!(v::AbstractVector, p::Real=2) -Normalize the vector `v` in-place with respect to the `p`-norm. -See also [`vecnorm`](@ref) and [`normalize`](@ref). +Normalize the vector `v` in-place so that its `p`-norm equals unity, +i.e. `norm(v, p) == 1`. +See also [`normalize`](@ref) and [`vecnorm`](@ref). """ function normalize!(v::AbstractVector, p::Real=2) nrm = norm(v, p) @@ -1268,9 +1316,10 @@ end end """ - normalize(v, [p::Real=2]) + normalize(v::AbstractVector, p::Real=2) -Normalize the vector `v` with respect to the `p`-norm. +Normalize the vector `v` so that its `p`-norm equals unity, +i.e. `norm(v, p) == vecnorm(v, p) == 1`. See also [`normalize!`](@ref) and [`vecnorm`](@ref). # Example @@ -1278,17 +1327,23 @@ See also [`normalize!`](@ref) and [`vecnorm`](@ref). ```jldoctest julia> a = [1,2,4]; -julia> normalize(a) +julia> b = normalize(a) 3-element Array{Float64,1}: 0.218218 0.436436 0.872872 -julia> normalize(a,1) +julia> norm(b) +1.0 + +julia> c = normalize(a, 1) 3-element Array{Float64,1}: 0.142857 0.285714 0.571429 + +julia> norm(c, 1) +1.0 ``` """ function normalize(v::AbstractVector, p::Real = 2) From a6f1e96feae1e37365543b9f5de378d79a24ddd2 Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Sun, 7 May 2017 15:00:10 -0400 Subject: [PATCH 0679/1534] Use A'A instead of [0 A;A' 0] in svds. The former can be much faster. The latter (#21701) is only relevant when computing the small values and we don't support that. This also fixes #16608. --- base/linalg/arnoldi.jl | 106 +++++++++------- base/linalg/arpack.jl | 2 +- base/linalg/generic.jl | 2 + test/linalg/arnoldi.jl | 275 +++++++++++++++++++++-------------------- 4 files changed, 206 insertions(+), 179 deletions(-) diff --git a/base/linalg/arnoldi.jl b/base/linalg/arnoldi.jl index 70e893abf67a8..73b25f8d892dc 100644 --- a/base/linalg/arnoldi.jl +++ b/base/linalg/arnoldi.jl @@ -177,8 +177,8 @@ function _eigs(A, B; T = eltype(A) iscmplx = T <: Complex isgeneral = B !== I - sym = issymmetric(A) && issymmetric(B) && !iscmplx - nevmax=sym ? n-1 : n-2 + sym = !iscmplx && issymmetric(A) && issymmetric(B) + nevmax = sym ? n-1 : n-2 if nevmax <= 0 throw(ArgumentError("input matrix A is too small. Use eigfact instead.")) end @@ -299,29 +299,49 @@ end ## svds -### Restrict operator to BlasFloat because ARPACK only supports that. Loosen restriction -### when we switch to our own implementation -mutable struct SVDOperator{T<:BlasFloat,S} <: AbstractArray{T, 2} +struct SVDAugmented{T,S} <: AbstractArray{T, 2} X::S - m::Int - n::Int - SVDOperator{T,S}(X::AbstractMatrix) where {T<:BlasFloat,S} = new(X, size(X, 1), size(X, 2)) + SVDAugmented{T,S}(X::AbstractMatrix) where {T,S} = new(X) end -function SVDOperator(A::AbstractMatrix{T}) where T +function SVDAugmented(A::AbstractMatrix{T}) where T Tnew = typeof(zero(T)/sqrt(one(T))) Anew = convert(AbstractMatrix{Tnew}, A) - SVDOperator{Tnew,typeof(Anew)}(Anew) + SVDAugmented{Tnew,typeof(Anew)}(Anew) end -function A_mul_B!(u::StridedVector{T}, s::SVDOperator{T}, v::StridedVector{T}) where T - a, b = s.m, length(v) - A_mul_B!(view(u,1:a), s.X, view(v,a+1:b)) # left singular vector - Ac_mul_B!(view(u,a+1:b), s.X, view(v,1:a)) # right singular vector - u +function A_mul_B!(y::StridedVector{T}, A::SVDAugmented{T}, x::StridedVector{T}) where T + m, mn = size(A.X, 1), length(x) + A_mul_B!( view(y, 1:m), A.X, view(x, m + 1:mn)) # left singular vector + Ac_mul_B!(view(y, m + 1:mn), A.X, view(x, 1:m)) # right singular vector + return y end -size(s::SVDOperator) = s.m + s.n, s.m + s.n -issymmetric(s::SVDOperator) = true +size(A::SVDAugmented) = ((+)(size(A.X)...), (+)(size(A.X)...)) +ishermitian(A::SVDAugmented) = true + +struct AtA_or_AAt{T,S} <: AbstractArray{T, 2} + A::S + buffer::Vector{T} +end + +function AtA_or_AAt(A::AbstractMatrix{T}) where T + Tnew = typeof(zero(T)/sqrt(one(T))) + Anew = convert(AbstractMatrix{Tnew}, A) + AtA_or_AAt{Tnew,typeof(Anew)}(Anew, Vector{Tnew}(max(size(A)...))) +end + +function A_mul_B!(y::StridedVector{T}, A::AtA_or_AAt{T}, x::StridedVector{T}) where T + if size(A.A, 1) >= size(A.A, 2) + A_mul_B!(A.buffer, A.A, x) + return Ac_mul_B!(y, A.A, A.buffer) + else + Ac_mul_B!(A.buffer, A.A, x) + return A_mul_B!(y, A.A, A.buffer) + end +end +size(A::AtA_or_AAt) = ntuple(i -> min(size(A.A)...), Val{2}) +ishermitian(s::AtA_or_AAt) = true + svds(A::AbstractMatrix{<:BlasFloat}; kwargs...) = _svds(A; kwargs...) svds(A::AbstractMatrix{BigFloat}; kwargs...) = throw(MethodError(svds, Any[A, kwargs...])) @@ -331,7 +351,7 @@ function svds(A::AbstractMatrix{T}; kwargs...) where T end """ - svds(A; nsv=6, ritzvec=true, tol=0.0, maxiter=1000, ncv=2*nsv, u0=zeros((0,)), v0=zeros((0,))) -> (SVD([left_sv,] s, [right_sv,]), nconv, niter, nmult, resid) + svds(A; nsv=6, ritzvec=true, tol=0.0, maxiter=1000, ncv=2*nsv, v0=zeros((0,))) -> (SVD([left_sv,] s, [right_sv,]), nconv, niter, nmult, resid) Computes the largest singular values `s` of `A` using implicitly restarted Lanczos iterations derived from [`eigs`](@ref). @@ -347,8 +367,7 @@ iterations derived from [`eigs`](@ref). * `tol`: tolerance, see [`eigs`](@ref). * `maxiter`: Maximum number of iterations, see [`eigs`](@ref). Default: 1000. * `ncv`: Maximum size of the Krylov subspace, see [`eigs`](@ref) (there called `nev`). Default: `2*nsv`. -* `u0`: Initial guess for the first left Krylov vector. It may have length `m` (the first dimension of `A`), or 0. -* `v0`: Initial guess for the first right Krylov vector. It may have length `n` (the second dimension of `A`), or 0. +* `v0`: Initial guess for the first Krylov vector. It may have length `min(size(A)...)`, or 0. **Outputs** @@ -375,48 +394,45 @@ julia> s[:S] !!! note "Implementation" `svds(A)` is formally equivalent to calling [`eigs`](@ref) to perform implicitly restarted - Lanczos tridiagonalization on the Hermitian matrix - ``\\begin{pmatrix} 0 & A^\\prime \\\\ A & 0 \\end{pmatrix}``, whose eigenvalues are - plus and minus the singular values of ``A``. + Lanczos tridiagonalization on the Hermitian matrix ``A^\\prime A`` or ``AA^\\prime`` such + that the size is smallest. """ svds(A; kwargs...) = _svds(A; kwargs...) -function _svds(X; nsv::Int = 6, ritzvec::Bool = true, tol::Float64 = 0.0, maxiter::Int = 1000, ncv::Int = 2*nsv, u0::Vector=zeros(eltype(X),(0,)), v0::Vector=zeros(eltype(X),(0,))) +function _svds(X; nsv::Int = 6, ritzvec::Bool = true, tol::Float64 = 0.0, maxiter::Int = 1000, ncv::Int = 2*nsv, v0::Vector=zeros(eltype(X),(0,))) if nsv < 1 throw(ArgumentError("number of singular values (nsv) must be ≥ 1, got $nsv")) end if nsv > minimum(size(X)) throw(ArgumentError("number of singular values (nsv) must be ≤ $(minimum(size(X))), got $nsv")) end - m,n = size(X) + m, n = size(X) otype = eltype(X) - padv0 = zeros(eltype(X),(0,)) if length(v0) ∉ [0,n] throw(DimensionMismatch("length of v0, the guess for the starting right Krylov vector, must be 0, or $n, got $(length(v0))")) end - if length(u0) ∉ [0,m] - throw(DimensionMismatch("length of u0, the guess for the starting left Krylov vector, must be 0, or $m, got $(length(u0))")) - end - if length(v0) == n && length(u0) == m - padv0 = [u0; v0] - elseif length(v0) == n && length(u0) == 0 - padv0 = [zeros(otype,m); v0] - elseif length(v0) == 0 && length(u0) == m - padv0 = [u0; zeros(otype,n) ] - end - ex = eigs(SVDOperator(X), I; ritzvec = ritzvec, nev = ncv, tol = tol, maxiter = maxiter, v0=padv0) - ind = [1:2:ncv;] - sval = abs.(ex[1][ind]) + ex = eigs(AtA_or_AAt(X), I; which = :LM, ritzvec = ritzvec, nev = nsv, tol = tol, maxiter = maxiter, v0=v0) + # ind = [1:2:ncv;] + # sval = abs.(ex[1][ind]) + svals = sqrt.(real.(ex[1])) if ritzvec # calculating singular vectors - left_sv = sqrt(2) * ex[2][ 1:size(X,1), ind ] .* sign.(ex[1][ind]') - right_sv = sqrt(2) * ex[2][ size(X,1)+1:end, ind ] - return (SVD(left_sv, sval, right_sv'), ex[3], ex[4], ex[5], ex[6]) + # left_sv = sqrt(2) * ex[2][ 1:size(X,1), ind ] .* sign.(ex[1][ind]') + if size(X, 1) >= size(X, 2) + V = ex[2] + U = qr(scale!(X*V, inv.(svals)))[1] + else + U = ex[2] + V = qr(scale!(X'U, inv.(svals)))[1] + end + + # right_sv = sqrt(2) * ex[2][ size(X,1)+1:end, ind ] + return (SVD(U, svals, V'), ex[3], ex[4], ex[5], ex[6]) else #The sort is necessary to work around #10329 - return (SVD(zeros(eltype(sval), n, 0), - sort!(sval, by=real, rev=true), - zeros(eltype(sval), 0, m)), + return (SVD(zeros(eltype(svals), n, 0), + svals, + zeros(eltype(svals), 0, m)), ex[2], ex[3], ex[4], ex[5]) end end diff --git a/base/linalg/arpack.jl b/base/linalg/arpack.jl index be6db8779fdef..c268920fc3a91 100644 --- a/base/linalg/arpack.jl +++ b/base/linalg/arpack.jl @@ -149,7 +149,7 @@ function eupd_wrapper(T, n::Integer, sym::Bool, cmplx::Bool, bmat::String, end p = sortperm(dmap(d), rev=true) - return ritzvec ? (d[p], v[1:n, p],iparam[5],iparam[3],iparam[9],resid) : (d,iparam[5],iparam[3],iparam[9],resid) + return ritzvec ? (d[p], v[1:n, p],iparam[5],iparam[3],iparam[9],resid) : (d[p],iparam[5],iparam[3],iparam[9],resid) else dr = Vector{T}(nev+1) di = Vector{T}(nev+1) diff --git a/base/linalg/generic.jl b/base/linalg/generic.jl index 6f44208621bd4..b1da7e74b24e2 100644 --- a/base/linalg/generic.jl +++ b/base/linalg/generic.jl @@ -847,6 +847,8 @@ condition number, or componentwise relative condition number. """ condskeel(A::AbstractMatrix, x::AbstractVector, p::Real=Inf) = norm(abs.(inv(A))*(abs.(A)*abs.(x)), p) +issymmetric(A::AbstractMatrix{<:Real}) = ishermitian(A) + """ issymmetric(A) -> Bool diff --git a/test/linalg/arnoldi.jl b/test/linalg/arnoldi.jl index 6f895a1d130a5..d1518327592cb 100644 --- a/test/linalg/arnoldi.jl +++ b/test/linalg/arnoldi.jl @@ -3,78 +3,83 @@ using Base.Test @testset "eigs" begin - let - srand(1234) - local n,a,asym,b,bsym,d,v - n = 10 - areal = sprandn(n,n,0.4) - breal = sprandn(n,n,0.4) - acmplx = complex.(sprandn(n,n,0.4), sprandn(n,n,0.4)) - bcmplx = complex.(sprandn(n,n,0.4), sprandn(n,n,0.4)) - - testtol = 1e-6 - - @testset for elty in (Float64, Complex128) - if elty == Complex64 || elty == Complex128 - a = acmplx - b = bcmplx - else - a = areal - b = breal - end - a = convert(SparseMatrixCSC{elty}, a) - asym = a' + a # symmetric indefinite - apd = a'*a # symmetric positive-definite + srand(1234) + n = 10 + areal = sprandn(n,n,0.4) + breal = sprandn(n,n,0.4) + acmplx = complex.(sprandn(n,n,0.4), sprandn(n,n,0.4)) + bcmplx = complex.(sprandn(n,n,0.4), sprandn(n,n,0.4)) - b = convert(SparseMatrixCSC{elty}, b) - bsym = b' + b - bpd = b'*b + testtol = 1e-6 - (d,v) = eigs(a, nev=3) - @test a*v[:,2] ≈ d[2]*v[:,2] - @test norm(v) > testtol # eigenvectors cannot be null vectors - # (d,v) = eigs(a, b, nev=3, tol=1e-8) # not handled yet - # @test a*v[:,2] ≈ d[2]*b*v[:,2] atol=testtol - # @test norm(v) > testtol # eigenvectors cannot be null vectors + @testset for elty in (Float64, Complex128) + if elty == Complex64 || elty == Complex128 + a = acmplx + b = bcmplx + else + a = areal + b = breal + end + a = convert(SparseMatrixCSC{elty}, a) + asym = a' + a # symmetric indefinite + apd = a'*a # symmetric positive-definite - (d,v) = eigs(asym, nev=3) - @test asym*v[:,1] ≈ d[1]*v[:,1] - @test eigs(asym; nev=1, sigma=d[3])[1][1] ≈ d[3] - @test norm(v) > testtol # eigenvectors cannot be null vectors + b = convert(SparseMatrixCSC{elty}, b) + bsym = b' + b + bpd = b'*b - (d,v) = eigs(apd, nev=3) - @test apd*v[:,3] ≈ d[3]*v[:,3] - @test eigs(apd; nev=1, sigma=d[3])[1][1] ≈ d[3] + (d,v) = eigs(a, nev=3) + @test a*v[:,2] ≈ d[2]*v[:,2] + @test norm(v) > testtol # eigenvectors cannot be null vectors + # (d,v) = eigs(a, b, nev=3, tol=1e-8) # not handled yet + # @test a*v[:,2] ≈ d[2]*b*v[:,2] atol=testtol + # @test norm(v) > testtol # eigenvectors cannot be null vectors - (d,v) = eigs(apd, bpd, nev=3, tol=1e-8) - @test apd*v[:,2] ≈ d[2]*bpd*v[:,2] atol=testtol - @test norm(v) > testtol # eigenvectors cannot be null vectors + (d,v) = eigs(asym, nev=3) + @test asym*v[:,1] ≈ d[1]*v[:,1] + @test eigs(asym; nev=1, sigma=d[3])[1][1] ≈ d[3] + @test norm(v) > testtol # eigenvectors cannot be null vectors - @testset "(shift-and-)invert mode" begin - (d,v) = eigs(apd, nev=3, sigma=0) - @test apd*v[:,3] ≈ d[3]*v[:,3] - @test norm(v) > testtol # eigenvectors cannot be null vectors + (d,v) = eigs(apd, nev=3) + @test apd*v[:,3] ≈ d[3]*v[:,3] + @test eigs(apd; nev=1, sigma=d[3])[1][1] ≈ d[3] - (d,v) = eigs(apd, bpd, nev=3, sigma=0, tol=1e-8) - @test apd*v[:,1] ≈ d[1]*bpd*v[:,1] atol=testtol - @test norm(v) > testtol # eigenvectors cannot be null vectors - end + (d,v) = eigs(apd, bpd, nev=3, tol=1e-8) + @test apd*v[:,2] ≈ d[2]*bpd*v[:,2] atol=testtol + @test norm(v) > testtol # eigenvectors cannot be null vectors - @testset "ArgumentErrors" begin - @test_throws ArgumentError eigs(rand(elty,2,2)) - @test_throws ArgumentError eigs(a, nev=-1) - @test_throws ArgumentError eigs(a, which=:Z) - @test_throws ArgumentError eigs(a, which=:BE) - @test_throws DimensionMismatch eigs(a, v0=zeros(elty,n+2)) - @test_throws ArgumentError eigs(a, v0=zeros(Int,n)) - if elty == Float64 - @test_throws ArgumentError eigs(a+a.',which=:SI) - @test_throws ArgumentError eigs(a+a.',which=:LI) - @test_throws ArgumentError eigs(a,sigma=rand(Complex64)) - end + @testset "(shift-and-)invert mode" begin + (d,v) = eigs(apd, nev=3, sigma=0) + @test apd*v[:,3] ≈ d[3]*v[:,3] + @test norm(v) > testtol # eigenvectors cannot be null vectors + + (d,v) = eigs(apd, bpd, nev=3, sigma=0, tol=1e-8) + @test apd*v[:,1] ≈ d[1]*bpd*v[:,1] atol=testtol + @test norm(v) > testtol # eigenvectors cannot be null vectors + end + + @testset "ArgumentErrors" begin + @test_throws ArgumentError eigs(rand(elty,2,2)) + @test_throws ArgumentError eigs(a, nev=-1) + @test_throws ArgumentError eigs(a, which=:Z) + @test_throws ArgumentError eigs(a, which=:BE) + @test_throws DimensionMismatch eigs(a, v0=zeros(elty,n+2)) + @test_throws ArgumentError eigs(a, v0=zeros(Int,n)) + if elty == Float64 + @test_throws ArgumentError eigs(a+a.',which=:SI) + @test_throws ArgumentError eigs(a+a.',which=:LI) + @test_throws ArgumentError eigs(a,sigma=rand(Complex64)) end end end + + @testset "Symmetric generalized with singular B" begin + n = 10 + k = 3 + A = randn(n,n); A = A'A + B = randn(n,k); B = B*B' + @test sort(eigs(A, B, nev = k, sigma = 1.0)[1]) ≈ sort(eigvals(A, B)[1:k]) + end end # Problematic example from #6965 @@ -152,81 +157,93 @@ let end @testset "real svds" begin - let A = sparse([1, 1, 2, 3, 4], [2, 1, 1, 3, 1], [2.0, -1.0, 6.1, 7.0, 1.5]) - S1 = svds(A, nsv = 2) - S2 = svd(Array(A)) + A = sparse([1, 1, 2, 3, 4], [2, 1, 1, 3, 1], [2.0, -1.0, 6.1, 7.0, 1.5]) + S1 = svds(A, nsv = 2) + S2 = svd(Array(A)) - ## singular values match: + ## singular values match: + @test S1[1][:S] ≈ S2[2][1:2] + @testset "singular vectors" begin + ## 1st left singular vector + s1_left = sign(S1[1][:U][3,1]) * S1[1][:U][:,1] + s2_left = sign(S2[1][3,1]) * S2[1][:,1] + @test s1_left ≈ s2_left + + ## 1st right singular vector + s1_right = sign(S1[1][:V][3,1]) * S1[1][:V][:,1] + s2_right = sign(S2[3][3,1]) * S2[3][:,1] + @test s1_right ≈ s2_right + end + # Issue number 10329 + # Ensure singular values from svds are in + # the correct order + @testset "singular values ordered correctly" begin + B = sparse(diagm([1.0, 2.0, 34.0, 5.0, 6.0])) + S3 = svds(B, ritzvec=false, nsv=2) + @test S3[1][:S] ≈ [34.0, 6.0] + S4 = svds(B, nsv=2) + @test S4[1][:S] ≈ [34.0, 6.0] + end + @testset "passing guess for Krylov vectors" begin + S1 = svds(A, nsv = 2, v0=rand(eltype(A),size(A,2))) @test S1[1][:S] ≈ S2[2][1:2] - @testset "singular vectors" begin - ## 1st left singular vector - s1_left = sign(S1[1][:U][3,1]) * S1[1][:U][:,1] - s2_left = sign(S2[1][3,1]) * S2[1][:,1] - @test s1_left ≈ s2_left - - ## 1st right singular vector - s1_right = sign(S1[1][:V][3,1]) * S1[1][:V][:,1] - s2_right = sign(S2[3][3,1]) * S2[3][:,1] - @test s1_right ≈ s2_right - end - # Issue number 10329 - # Ensure singular values from svds are in - # the correct order - @testset "singular values ordered correctly" begin - B = sparse(diagm([1.0, 2.0, 34.0, 5.0, 6.0])) - S3 = svds(B, ritzvec=false, nsv=2) - @test S3[1][:S] ≈ [34.0, 6.0] - S4 = svds(B, nsv=2) - @test S4[1][:S] ≈ [34.0, 6.0] + end + + @test_throws ArgumentError svds(A,nsv=0) + @test_throws ArgumentError svds(A,nsv=20) + @test_throws DimensionMismatch svds(A,nsv=2,v0=rand(size(A,2)+1)) + + @testset "Orthogonal vectors with repeated singular values $i times. Issue 16608" for i in 2:3 + rng = MersenneTwister(126) # Fragile to compute repeated values without blocking so we set the seed + v0 = randn(rng, 20) + d = sort(rand(rng, 20), rev = true) + for j in 2:i + d[j] = d[1] end - @testset "passing guess for Krylov vectors" begin - S1 = svds(A, nsv = 2, u0=rand(eltype(A),size(A,1))) - @test S1[1][:S] ≈ S2[2][1:2] - S1 = svds(A, nsv = 2, v0=rand(eltype(A),size(A,2))) - @test S1[1][:S] ≈ S2[2][1:2] - S1 = svds(A, nsv = 2, u0=rand(eltype(A),size(A,1)), v0=rand(eltype(A),size(A,2))) - @test S1[1][:S] ≈ S2[2][1:2] + A = qr(randn(rng, 20, 20))[1]*Diagonal(d)*qr(randn(rng, 20, 20))[1] + @testset "Number of singular values: $j" for j in 2:6 + # Default size of subspace + F = svds(A, nsv = j, v0 = v0) + @test F[1][:U]'F[1][:U] ≈ eye(j) + @test F[1][:V]'F[1][:V] ≈ eye(j) + @test F[1][:S] ≈ d[1:j] + for k in 3j:2:5j + # Custom size of subspace + F = svds(A, nsv = j, ncv = k, v0 = v0) + @test F[1][:U]'F[1][:U] ≈ eye(j) + @test F[1][:V]'F[1][:V] ≈ eye(j) + @test F[1][:S] ≈ d[1:j] + end end - - @test_throws ArgumentError svds(A,nsv=0) - @test_throws ArgumentError svds(A,nsv=20) - @test_throws DimensionMismatch svds(A,nsv=2,u0=rand(size(A,1)+1)) - @test_throws DimensionMismatch svds(A,nsv=2,v0=rand(size(A,2)+1)) end end @testset "complex svds" begin - let A = sparse([1, 1, 2, 3, 4], [2, 1, 1, 3, 1], exp.(im*[2.0:2:10;])) - S1 = svds(A, nsv = 2) - S2 = svd(Array(A)) + A = sparse([1, 1, 2, 3, 4], [2, 1, 1, 3, 1], exp.(im*[2.0:2:10;]), 5, 4) + S1 = svds(A, nsv = 2) + S2 = svd(Array(A)) - ## singular values match: - @test S1[1][:S] ≈ S2[2][1:2] - @testset "singular vectors" begin - ## left singular vectors - s1_left = abs.(S1[1][:U][:,1:2]) - s2_left = abs.(S2[1][:,1:2]) - @test s1_left ≈ s2_left - - ## right singular vectors - s1_right = abs.(S1[1][:V][:,1:2]) - s2_right = abs.(S2[3][:,1:2]) - @test s1_right ≈ s2_right - end - @testset "passing guess for Krylov vectors" begin - S1 = svds(A, nsv = 2, u0=rand(eltype(A),size(A,1))) - @test S1[1][:S] ≈ S2[2][1:2] - S1 = svds(A, nsv = 2, v0=rand(eltype(A),size(A,2))) - @test S1[1][:S] ≈ S2[2][1:2] - S1 = svds(A, nsv = 2, u0=rand(eltype(A),size(A,1)), v0=rand(eltype(A),size(A,2))) - @test S1[1][:S] ≈ S2[2][1:2] - end + ## singular values match: + @test S1[1][:S] ≈ S2[2][1:2] + @testset "singular vectors" begin + ## left singular vectors + s1_left = abs.(S1[1][:U][:,1:2]) + s2_left = abs.(S2[1][:,1:2]) + @test s1_left ≈ s2_left - @test_throws ArgumentError svds(A,nsv=0) - @test_throws ArgumentError svds(A,nsv=20) - @test_throws DimensionMismatch svds(A,nsv=2,u0=complex(rand(size(A,1)+1))) - @test_throws DimensionMismatch svds(A,nsv=2,v0=complex(rand(size(A,2)+1))) + ## right singular vectors + s1_right = abs.(S1[1][:V][:,1:2]) + s2_right = abs.(S2[3][:,1:2]) + @test s1_right ≈ s2_right + end + @testset "passing guess for Krylov vectors" begin + S1 = svds(A, nsv = 2, v0=rand(eltype(A),size(A,2))) + @test S1[1][:S] ≈ S2[2][1:2] end + + @test_throws ArgumentError svds(A,nsv=0) + @test_throws ArgumentError svds(A,nsv=20) + @test_throws DimensionMismatch svds(A,nsv=2,v0=complex(rand(size(A,2)+1))) end @testset "promotion" begin @@ -237,11 +254,3 @@ end @test_throws MethodError eigs(big.(rand(1:10, 10, 10)), rand(1:10, 10, 10)) @test_throws MethodError svds(big.(rand(1:10, 10, 8))) end - -# Symmetric generalized with singular B -let n = 10 - k = 3 - A = randn(n,n); A = A'A - B = randn(n,k); B = B*B' - @test sort(eigs(A, B, nev = k, sigma = 1.0)[1]) ≈ sort(eigvals(A, B)[1:k]) -end From 310b6ddbdceab9c0d7bf3c8a8790d6dabc8c23ba Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Mon, 8 May 2017 10:10:37 -0700 Subject: [PATCH 0680/1534] Add example for iscommit and reset! (#21734) --- base/libgit2/libgit2.jl | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/base/libgit2/libgit2.jl b/base/libgit2/libgit2.jl index 6b704768be3f2..c8ba346ec52f1 100644 --- a/base/libgit2/libgit2.jl +++ b/base/libgit2/libgit2.jl @@ -72,6 +72,19 @@ end Checks if commit `id` (which is a [`GitHash`](@ref) in string form) is in the repository. + +# Example + +```julia +julia> repo = LibGit2.GitRepo(repo_path); + +julia> LibGit2.add!(repo, test_file); + +julia> commit_oid = LibGit2.commit(repo, "add test_file"); + +julia> LibGit2.iscommit(string(commit_oid), repo) +true +``` """ function iscommit(id::AbstractString, repo::GitRepo) res = true @@ -573,6 +586,21 @@ set by `mode`: 3. `Consts.RESET_HARD` - move HEAD to `id`, reset the index to `id`, and discard all working changes. Equivalent to `git reset [--soft | --mixed | --hard] `. + +# Example + +```julia +repo = LibGit2.GitRepo(repo_path) +head_oid = LibGit2.head_oid(repo) +open(joinpath(repo_path, "file1"), "w") do f + write(f, "111\n") +end +LibGit2.add!(repo, "file1") +mode = LibGit2.Consts.RESET_HARD +# will discard the changes to file1 +# and unstage it +new_head = LibGit2.reset!(repo, head_oid, mode) +``` """ reset!(repo::GitRepo, id::GitHash, mode::Cint = Consts.RESET_MIXED) = reset!(repo, GitObject(repo, id), mode) From 25f241ccf84f200be5cadc3af35b6c9eeef9504f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Mon, 8 May 2017 19:16:36 +0200 Subject: [PATCH 0681/1534] Define methods for big(T) (#21218) --- base/complex.jl | 4 ++-- base/gmp.jl | 5 ++++- base/irrationals.jl | 1 + base/mpfr.jl | 4 +++- base/number.jl | 19 +++++++++++++++++++ test/bigfloat.jl | 5 +++++ test/bigint.jl | 4 ++++ 7 files changed, 38 insertions(+), 4 deletions(-) diff --git a/base/complex.jl b/base/complex.jl index ae9a191b181d4..606f47488ce00 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -880,8 +880,8 @@ end float(z::Complex{<:AbstractFloat}) = z float(z::Complex) = Complex(float(real(z)), float(imag(z))) -big(z::Complex{<:AbstractFloat}) = Complex{BigFloat}(z) -big(z::Complex{<:Integer}) = Complex{BigInt}(z) +big(::Type{Complex{T}}) where {T<:Real} = Complex{big(T)} +big(z::Complex{T}) where {T<:Real} = Complex{big(T)}(z) ## Array operations on complex numbers ## diff --git a/base/gmp.jl b/base/gmp.jl index 365de9154fd51..67e4aa70b2b37 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -9,7 +9,7 @@ import Base: *, +, -, /, <, <<, >>, >>>, <=, ==, >, >=, ^, (~), (&), (|), xor, ndigits, promote_rule, rem, show, isqrt, string, powermod, sum, trailing_zeros, trailing_ones, count_ones, base, tryparse_internal, bin, oct, dec, hex, isequal, invmod, prevpow2, nextpow2, ndigits0z, widen, signed, unsafe_trunc, trunc, - iszero + iszero, big if Clong == Int32 const ClongMax = Union{Int8, Int16, Int32} @@ -248,6 +248,9 @@ convert(::Type{Float16}, n::BigInt) = Float16(n,RoundNearest) promote_rule(::Type{BigInt}, ::Type{<:Integer}) = BigInt +big(::Type{<:Integer}) = BigInt +big(::Type{<:Rational}) = Rational{BigInt} + # Binary ops for (fJ, fC) in ((:+, :add), (:-,:sub), (:*, :mul), (:fld, :fdiv_q), (:div, :tdiv_q), (:mod, :fdiv_r), (:rem, :tdiv_r), diff --git a/base/irrationals.jl b/base/irrationals.jl index 1e3ca1be649e4..366e0564c0bd1 100644 --- a/base/irrationals.jl +++ b/base/irrationals.jl @@ -131,6 +131,7 @@ macro irrational(sym, val, def) end big(x::Irrational) = convert(BigFloat,x) +big(::Type{<:Irrational}) = BigFloat ## specific irrational mathematical constants diff --git a/base/mpfr.jl b/base/mpfr.jl index ff459cf0738f4..a05585a2a37a5 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -16,7 +16,7 @@ import eps, signbit, sin, cos, tan, sec, csc, cot, acos, asin, atan, cosh, sinh, tanh, sech, csch, coth, acosh, asinh, atanh, atan2, cbrt, typemax, typemin, unsafe_trunc, realmin, realmax, rounding, - setrounding, maxintfloat, widen, significand, frexp, tryparse, iszero + setrounding, maxintfloat, widen, significand, frexp, tryparse, iszero, big import Base.Rounding: rounding_raw, setrounding_raw @@ -252,6 +252,8 @@ promote_rule(::Type{BigFloat}, ::Type{<:Real}) = BigFloat promote_rule(::Type{BigInt}, ::Type{<:AbstractFloat}) = BigFloat promote_rule(::Type{BigFloat}, ::Type{<:AbstractFloat}) = BigFloat +big(::Type{<:AbstractFloat}) = BigFloat + function convert(::Type{Rational{BigInt}}, x::AbstractFloat) if isnan(x); return zero(BigInt)//zero(BigInt); end if isinf(x); return copysign(one(BigInt),x)//zero(BigInt); end diff --git a/base/number.jl b/base/number.jl index bf695e0718024..704bf42fc0070 100644 --- a/base/number.jl +++ b/base/number.jl @@ -211,3 +211,22 @@ julia> factorial(big(21)) ``` """ factorial(x::Number) = gamma(x + 1) # fallback for x not Integer + +""" + big(T::Type) + +Compute the type that represents the numeric type `T` with arbitrary precision. +Equivalent to `typeof(big(zero(T)))`. + +```jldoctest +julia> big(Rational) +Rational{BigInt} + +julia> big(Float64) +BigFloat + +julia> big(Complex{Int}) +Complex{BigInt} +``` +""" +big(::Type{T}) where {T<:Number} = typeof(big(zero(T))) diff --git a/test/bigfloat.jl b/test/bigfloat.jl index bef4c0ce63fa8..4966c1b7a1c6e 100644 --- a/test/bigfloat.jl +++ b/test/bigfloat.jl @@ -7,5 +7,10 @@ for T in [Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt @test big(2.0)^T(3) == 8 end +for x in (2f0, pi, 7.8, big(e)) + @test big(typeof(x)) == typeof(big(x)) + @test big(typeof(complex(x, x))) == typeof(big(complex(x, x))) +end + # issue 15659 @test (setprecision(53) do; big(1/3); end) < 1//3 diff --git a/test/bigint.jl b/test/bigint.jl index 4bf485ccb8e29..5a74ae37b4f90 100644 --- a/test/bigint.jl +++ b/test/bigint.jl @@ -57,6 +57,10 @@ end @test typeof(BigInt(BigInt(1))) == BigInt +for x in (Int16(0), 1, 3//4, big(5//6), big(9)) + @test big(typeof(x)) == typeof(big(x)) + @test big(typeof(complex(x, x))) == typeof(big(complex(x, x))) +end # Signed addition @test a+Int8(1) == b From 66b8036c4dfe790874371d5a76348f82f826f594 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Fri, 5 May 2017 15:41:47 -0400 Subject: [PATCH 0682/1534] make at-everywhere import modules first on node 1 before doing remote calls --- base/distributed/macros.jl | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/base/distributed/macros.jl b/base/distributed/macros.jl index 0720172bcc101..afacac1a00c82 100644 --- a/base/distributed/macros.jl +++ b/base/distributed/macros.jl @@ -48,6 +48,24 @@ macro fetchfrom(p, expr) :(remotecall_fetch($thunk, $(esc(p)))) end +# extract a list of modules to import from an expression +extract_imports(x) = Symbol[] +function extract_imports(ex::Expr) + if Meta.isexpr(ex, [:import, :using]) + return Symbol[ex.args[1]] + elseif Meta.isexpr(ex, :let) + return extract_imports(ex.args[1]) + elseif Meta.isexpr(ex, [:toplevel, :block]) + imports = Symbol[] + for i in eachindex(ex.args) + append!(imports, extract_imports(ex.args[i])) + end + return imports + else + return Symbol[] + end +end + """ @everywhere expr @@ -79,6 +97,7 @@ will result in `Main.bar` being defined on all processes and not `FooBar.bar`. """ macro everywhere(ex) quote + $(Expr(:toplevel, [Expr(:import, m) for m in extract_imports(ex)]...)) sync_begin() for pid in workers() async_run_thunk(()->remotecall_fetch(eval_ew_expr, pid, $(Expr(:quote,ex)))) From 18291b052b166fec588154c32fbc8cabaec128ff Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Sat, 6 May 2017 00:05:14 -0400 Subject: [PATCH 0683/1534] don't insert toplevel expression unless there are imports --- base/distributed/macros.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/base/distributed/macros.jl b/base/distributed/macros.jl index afacac1a00c82..32ed901f1504b 100644 --- a/base/distributed/macros.jl +++ b/base/distributed/macros.jl @@ -96,8 +96,9 @@ For example : will result in `Main.bar` being defined on all processes and not `FooBar.bar`. """ macro everywhere(ex) + imps = [Expr(:import, m) for m in extract_imports(ex)] quote - $(Expr(:toplevel, [Expr(:import, m) for m in extract_imports(ex)]...)) + $(isempty(imps) ? nothing : Expr(:toplevel, imps...)) sync_begin() for pid in workers() async_run_thunk(()->remotecall_fetch(eval_ew_expr, pid, $(Expr(:quote,ex)))) From 305037afbcf7f7bf4b877697670ca6f8060c9551 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Mon, 8 May 2017 17:04:54 -0400 Subject: [PATCH 0684/1534] eliminate unnecessary array allocations from isexpr and extract_imports functions --- base/distributed/macros.jl | 20 +++++++++----------- base/docs/Docs.jl | 6 +++--- base/meta.jl | 3 +-- test/meta.jl | 4 ++++ 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/base/distributed/macros.jl b/base/distributed/macros.jl index 32ed901f1504b..b3fefa24eec97 100644 --- a/base/distributed/macros.jl +++ b/base/distributed/macros.jl @@ -49,22 +49,20 @@ macro fetchfrom(p, expr) end # extract a list of modules to import from an expression -extract_imports(x) = Symbol[] -function extract_imports(ex::Expr) - if Meta.isexpr(ex, [:import, :using]) - return Symbol[ex.args[1]] +extract_imports!(imports, x) = imports +function extract_imports!(imports, ex::Expr) + if Meta.isexpr(ex, (:import, :using)) + return push!(imports, ex.args[1]) elseif Meta.isexpr(ex, :let) - return extract_imports(ex.args[1]) - elseif Meta.isexpr(ex, [:toplevel, :block]) - imports = Symbol[] + return extract_imports!(imports, ex.args[1]) + elseif Meta.isexpr(ex, (:toplevel, :block)) for i in eachindex(ex.args) - append!(imports, extract_imports(ex.args[i])) + extract_imports!(imports, ex.args[i]) end - return imports - else - return Symbol[] end + return imports end +extract_imports(x) = extract_imports!(Symbol[], x) """ @everywhere expr diff --git a/base/docs/Docs.jl b/base/docs/Docs.jl index d1cf074440804..23753f86f2625 100644 --- a/base/docs/Docs.jl +++ b/base/docs/Docs.jl @@ -83,7 +83,7 @@ function initmeta(m::Module = current_module()) end function signature!(tv, expr::Expr) - if isexpr(expr, [:call, :macrocall]) + if isexpr(expr, (:call, :macrocall)) sig = :(Union{Tuple{}}) for arg in expr.args[2:end] isexpr(arg, :parameters) && continue @@ -454,7 +454,7 @@ function nameof(x::Expr, ismacro) if isexpr(x, :.) ismacro ? macroname(x) : x else - n = isexpr(x, [:module, :type, :bitstype]) ? 2 : 1 + n = isexpr(x, (:module, :type, :bitstype)) ? 2 : 1 nameof(x.args[n], ismacro) end end @@ -531,7 +531,7 @@ function calldoc(str, def) docerror(def) end end -validcall(x) = isa(x, Symbol) || isexpr(x, [:(::), :..., :kw, :parameters]) +validcall(x) = isa(x, Symbol) || isexpr(x, (:(::), :..., :kw, :parameters)) function moduledoc(meta, def, def′) name = namify(def′) diff --git a/base/meta.jl b/base/meta.jl index 6daaa8330c0e4..bbe4c3f49bde6 100644 --- a/base/meta.jl +++ b/base/meta.jl @@ -12,8 +12,7 @@ export quot, quot(ex) = Expr(:quote, ex) isexpr(ex::Expr, head) = ex.head === head -isexpr(ex::Expr, heads::Set) = in(ex.head, heads) -isexpr(ex::Expr, heads::Vector) = in(ex.head, heads) +isexpr(ex::Expr, heads::Union{Set,Vector,Tuple}) = in(ex.head, heads) isexpr(ex, head) = false isexpr(ex, head, n::Int) = isexpr(ex, head) && length(ex.args) == n diff --git a/test/meta.jl b/test/meta.jl index a1c562d2fdd3e..c3db48351d201 100644 --- a/test/meta.jl +++ b/test/meta.jl @@ -122,6 +122,7 @@ using Base.Meta @test isexpr(:(1+1),Set([:call])) @test isexpr(:(1+1),Vector([:call])) +@test isexpr(:(1+1),(:call)) @test isexpr(1,:call)==false @test isexpr(:(1+1),:call,3) ioB = IOBuffer() @@ -129,6 +130,9 @@ show_sexpr(ioB,:(1+1)) show_sexpr(ioB,QuoteNode(1),1) +@test Base.Meta.extract_imports(:(begin; import Foo, Bar; let; using Baz; end; end)) == + [:Foo, :Bar, :Baz] + # test base/expr.jl baremodule B eval = 0 From d214d578f553fa801fb229104bf671365b06c01a Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Tue, 9 May 2017 17:12:48 +0200 Subject: [PATCH 0685/1534] use TypeArithmetic trait in cumsum! implementation (#21666) * use TypeArithmetic trait in cumsum! implementation --- base/multidimensional.jl | 15 ++++++++++----- test/arrayops.jl | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 95b537e4460ad..e85400ebd355a 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -574,13 +574,18 @@ function accumulate_pairwise(op, v::AbstractVector{T}) where T end function cumsum!(out, v::AbstractVector, axis::Integer=1) - # for types prone to numerical stability issues, we want - # accumulate_pairwise. - axis == 1 ? accumulate_pairwise!(+, out, v) : copy!(out,v) + # we dispatch on the possibility of numerical stability issues + _cumsum!(out, v, axis, TypeArithmetic(eltype(out))) end -function cumsum!(out, v::AbstractVector{<:Integer}, axis::Integer=1) - axis == 1 ? accumulate!(+, out, v) : copy!(out,v) +function _cumsum!(out, v, axis, ::ArithmeticRounds) + axis == 1 ? accumulate_pairwise!(+, out, v) : copy!(out, v) +end +function _cumsum!(out, v, axis, ::ArithmeticUnknown) + _cumsum!(out, v, axis, ArithmeticRounds()) +end +function _cumsum!(out, v, axis, ::TypeArithmetic) + axis == 1 ? accumulate!(+, out, v) : copy!(out, v) end """ diff --git a/test/arrayops.jl b/test/arrayops.jl index ae92e9ba1401b..c6851c018f04d 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -2055,6 +2055,28 @@ end @test accumulate(op, [10 20 30], 2) == [10 op(10, 20) op(op(10, 20), 30)] == [10 40 110] end +struct F21666{T <: Base.TypeArithmetic} + x::Float32 +end + +@testset "Exactness of cumsum # 21666" begin + # test that cumsum uses more stable algorithm + # for types with unknown/rounding arithmetic + Base.TypeArithmetic(::Type{F21666{T}}) where {T} = T + Base.:+(x::F, y::F) where {F <: F21666} = F(x.x + y.x) + Base.convert(::Type{Float64}, x::F21666) = Float64(x.x) + # we make v pretty large, because stable algorithm may have a large base case + v = zeros(300); v[1] = 2; v[200:end] = eps(Float32) + + f_rounds = Float64.(cumsum(F21666{Base.ArithmeticRounds}.(v))) + f_unknown = Float64.(cumsum(F21666{Base.ArithmeticUnknown}.(v))) + f_truth = cumsum(v) + f_inexact = Float64.(accumulate(+, Float32.(v))) + @test f_rounds == f_unknown + @test f_rounds != f_inexact + @test norm(f_truth - f_rounds) < norm(f_truth - f_inexact) +end + @testset "zeros and ones" begin @test ones([1,2], Float64, (2,3)) == ones(2,3) @test ones(2) == ones(Int, 2) == ones([2,3], Float32, 2) == [1,1] From d34c596c7e49e7983ca45a5d15a1fbddd24b6f81 Mon Sep 17 00:00:00 2001 From: kshyatt Date: Mon, 8 May 2017 15:39:45 -0700 Subject: [PATCH 0686/1534] Docs for blob content and example for addblob --- base/libgit2/blob.jl | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/base/libgit2/blob.jl b/base/libgit2/blob.jl index 999a58da63f86..0676deceddd85 100644 --- a/base/libgit2/blob.jl +++ b/base/libgit2/blob.jl @@ -9,6 +9,14 @@ function rawcontent(blob::GitBlob) copy(unsafe_wrap(Array, ptr, (length(blob),), false)) end +""" + content(blob::GitBlob) + +Fetch the contents of the `GitBlob` `blob`. If the `blob` contains +binary data (which can be determined using [`isbinary`](@ref)), +throw an error. Otherwise, return a `String` containing the contents +of the `blob`. +""" function content(blob::GitBlob) s = String(rawcontent(blob)) isvalid(s) || error("Blob does not contain valid UTF-8 data") @@ -30,6 +38,14 @@ end Reads the file at `path` and adds it to the object database of `repo` as a loose blob. Returns the `GitHash` of the resulting blob. + +# Example + +```julia +hash_str = hex(commit_oid) +blob_file = joinpath(repo_path, ".git", "objects", hash_str[1:2], hash_str[3:end]) +id = LibGit2.addblob!(repo, blob_file) +``` """ function addblob!(repo::GitRepo, path::AbstractString) id_ref = Ref{GitHash}() From d63f72dbb60c1e9fd1bbcd4e9bddb29ef07bc5e8 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sun, 7 May 2017 13:34:30 -0400 Subject: [PATCH 0687/1534] improve error reporting for invalid type arguments to `ccall` --- src/method.c | 27 +++++++++++++++++++-------- test/ccall.jl | 2 ++ 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/method.c b/src/method.c index 723750cd8ce96..5a4f9f8100f92 100644 --- a/src/method.c +++ b/src/method.c @@ -72,18 +72,29 @@ jl_value_t *jl_resolve_globals(jl_value_t *expr, jl_module_t *module, jl_svec_t JL_NARGSV(ccall method definition, 3); // (fptr, rt, at) jl_value_t *rt = jl_exprarg(e, 1); jl_value_t *at = jl_exprarg(e, 2); - JL_TRY { - if (!jl_is_type(rt)) { + if (!jl_is_type(rt)) { + JL_TRY { rt = jl_interpret_toplevel_expr_in(module, rt, NULL, sparam_vals); - jl_exprargset(e, 1, rt); } - if (!jl_is_svec(at)) { - at = jl_interpret_toplevel_expr_in(module, at, NULL, sparam_vals); - jl_exprargset(e, 2, at); + JL_CATCH { + if (jl_typeis(jl_exception_in_transit, jl_errorexception_type)) + jl_error("could not evaluate ccall return type (it might depend on a local variable)"); + else + jl_rethrow(); } + jl_exprargset(e, 1, rt); } - JL_CATCH { - jl_error("invalid return type or argument type in ccall"); + if (!jl_is_svec(at)) { + JL_TRY { + at = jl_interpret_toplevel_expr_in(module, at, NULL, sparam_vals); + } + JL_CATCH { + if (jl_typeis(jl_exception_in_transit, jl_errorexception_type)) + jl_error("could not evaluate ccall argument type (it might depend on a local variable)"); + else + jl_rethrow(); + } + jl_exprargset(e, 2, at); } if (jl_is_svec(rt)) jl_error("ccall: missing return type"); diff --git a/test/ccall.jl b/test/ccall.jl index 38b4cd15f91f6..ad97132813279 100644 --- a/test/ccall.jl +++ b/test/ccall.jl @@ -1239,6 +1239,8 @@ end # issue #20835 @test_throws ErrorException eval(:(f20835(x) = ccall(:fn, Void, (Ptr{typeof(x)},), x))) +@test_throws UndefVarError eval(:(f20835(x) = ccall(:fn, Something_not_defined_20835, (Ptr{typeof(x)},), x))) + @noinline f21104at(::Type{T}) where {T} = ccall(:fn, Void, (Nullable{T},), 0) @noinline f21104rt(::Type{T}) where {T} = ccall(:fn, Nullable{T}, ()) @test code_llvm(DevNull, f21104at, (Type{Float64},)) === nothing From 24a74a5cf2c83f5c55b8ebeb76c1c42d9a958294 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Tue, 9 May 2017 16:51:33 -0400 Subject: [PATCH 0688/1534] test fixes --- test/meta.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/meta.jl b/test/meta.jl index c3db48351d201..6e12549ab10ee 100644 --- a/test/meta.jl +++ b/test/meta.jl @@ -122,7 +122,7 @@ using Base.Meta @test isexpr(:(1+1),Set([:call])) @test isexpr(:(1+1),Vector([:call])) -@test isexpr(:(1+1),(:call)) +@test isexpr(:(1+1),(:call,)) @test isexpr(1,:call)==false @test isexpr(:(1+1),:call,3) ioB = IOBuffer() @@ -130,7 +130,7 @@ show_sexpr(ioB,:(1+1)) show_sexpr(ioB,QuoteNode(1),1) -@test Base.Meta.extract_imports(:(begin; import Foo, Bar; let; using Baz; end; end)) == +@test Base.Distributed.extract_imports(:(begin; import Foo, Bar; let; using Baz; end; end)) == [:Foo, :Bar, :Baz] # test base/expr.jl From 15fd96596728dced5ef57496f4f29f62cadb427d Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Tue, 9 May 2017 16:30:30 -0500 Subject: [PATCH 0689/1534] Fix a promotion failure with linspace --- base/range.jl | 1 + test/ranges.jl | 1 + 2 files changed, 2 insertions(+) diff --git a/base/range.jl b/base/range.jl index d09d9153733a7..eded200e7ce2b 100644 --- a/base/range.jl +++ b/base/range.jl @@ -238,6 +238,7 @@ julia> linspace(1.3,2.9,9) ``` """ linspace(start, stop, len::Real=50) = linspace(promote_noncircular(start, stop)..., Int(len)) +linspace(start::T, stop::T, len::Real=50) where {T} = linspace(start, stop, Int(len)) linspace(start::Real, stop::Real, len::Integer) = linspace(promote(start, stop)..., len) linspace(start::T, stop::T, len::Integer) where {T<:Integer} = linspace(Float64, start, stop, len, 1) diff --git a/test/ranges.jl b/test/ranges.jl index 895ee4d873299..a45018f44bbba 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -25,6 +25,7 @@ L64 = @inferred(linspace(Int64(1), Int64(4), 4)) @test L32[2] == 2 && L64[2] == 2 @test L32[3] == 3 && L64[3] == 3 @test L32[4] == 4 && L64[4] == 4 +@test @inferred(linspace(1.0, 2.0, 2.0f0)) === linspace(1.0, 2.0, 2) r = 5:-1:1 @test r[1]==5 From 37f20f1ae8cb243aa9db46b3c488e44f2651503e Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 9 May 2017 17:43:34 -0400 Subject: [PATCH 0690/1534] fix method specificity issue causing problems for pr #21750 --- src/subtype.c | 2 ++ test/core.jl | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/src/subtype.c b/src/subtype.c index 6cf43828b3d4a..2cf56492a6d56 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -2320,6 +2320,8 @@ static int tuple_morespecific(jl_datatype_t *cdt, jl_datatype_t *pdt, int invari if (ci >= clenf && !cseq) { if (pseq && plenr <= clenr+1) return 1; + // shorter tuples are more specific, to ensure transitivity with varargs + if (!pseq && clenr < plenr) return 1; break; } if (pi >= plenf && !pseq) { diff --git a/test/core.jl b/test/core.jl index 20a48c58ca875..5b391e02eedad 100644 --- a/test/core.jl +++ b/test/core.jl @@ -78,6 +78,15 @@ _z_z_z_(::Int, c...) = 3 @test args_morespecific(Tuple{Type{Pair{A,B} where B}} where A, Tuple{DataType}) @test args_morespecific(Tuple{Union{Int,String},Type{Pair{A,B} where B}} where A, Tuple{Integer,UnionAll}) +# PR #21750 +let A = Tuple{Any, Tuple{Vararg{Integer,N} where N}}, + B = Tuple{Any, Tuple{Any}}, + C = Tuple{Any, Tuple{}} + @test args_morespecific(A, B) + @test args_morespecific(C, A) + @test args_morespecific(C, B) +end + # with bound varargs _bound_vararg_specificity_1{T,N}(::Type{Array{T,N}}, d::Vararg{Int, N}) = 0 From 6774ec6535d9fdc6a3ee560e6a58beb6c29c7c14 Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Tue, 9 May 2017 15:34:54 -0700 Subject: [PATCH 0691/1534] Allow building patchelf on FreeBSD --- deps/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/Makefile b/deps/Makefile index 53953d2c4cfbb..12183252513cf 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -58,7 +58,7 @@ DEP_LIBS += osxunwind endif endif -ifeq ($(OS), Linux) +ifneq (,$(findstring $(OS),Linux FreeBSD)) ifeq ($(USE_SYSTEM_PATCHELF), 0) DEP_LIBS += patchelf PATCHELF:=$(build_depsbindir)/patchelf From 57a8f0a80779b9076e6251c754bf0845ea937a10 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 9 May 2017 19:17:32 -0400 Subject: [PATCH 0692/1534] add typeof_tfunc for UnionAll types fix #21763 --- base/inference.jl | 2 ++ test/inference.jl | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/base/inference.jl b/base/inference.jl index 9dab296025988..9a4768bd38b19 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -598,6 +598,8 @@ function typeof_tfunc(t::ANY) return Union{a, b} elseif isa(t, TypeVar) && !(Any <: t.ub) return typeof_tfunc(t.ub) + elseif isa(t, UnionAll) + return rewrap_unionall(widenconst(typeof_tfunc(unwrap_unionall(t))), t) else return DataType # typeof(anything)::DataType end diff --git a/test/inference.jl b/test/inference.jl index bdcabb2ff7a72..318e33c4e552b 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -291,8 +291,9 @@ let g() = Int <: Real ? 1 : "" @test Base.return_types(g, Tuple{}) == [Int] end -NInt{N} = Tuple{Vararg{Int, N}} +const NInt{N} = Tuple{Vararg{Int, N}} @test Base.eltype(NInt) === Int +@test Base.return_types(eltype, (NInt,)) == Any[Union{Type{Int}, Type{Union{}}}] # issue 21763 fNInt(x::NInt) = (x...) gNInt() = fNInt(x) @test Base.return_types(gNInt, ()) == Any[NInt] From ab29eb31d33c97ed96b2e614301b7ec8f05cd8eb Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Tue, 9 May 2017 23:02:39 -0400 Subject: [PATCH 0693/1534] Rename cond(LU) to the helper function _cond1Inf and allow for a norm (#21577) argument. The old version was broken and inefficient. While it would be possible to fix just the bug, the performance problem is a consequence of how condition number estimation works, i.e. a norm estimate is required and that is not natural to produce from the factorized matrix. Hence, the change to a helper function. Fixes #21453 --- base/deprecated.jl | 1 + base/linalg/dense.jl | 4 +++- base/linalg/lu.jl | 10 ++++++---- test/linalg/lu.jl | 3 +++ 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index b29917a958919..d8da299e17eed 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1335,6 +1335,7 @@ next(p::Union{Process, ProcessChain}, i::Int) = (getindex(p, i), i + 1) return i == 1 ? getfield(p, p.openstream) : p end +@deprecate cond(F::LinAlg.LU, p::Integer) cond(full(F), p) # END 0.7 deprecations # BEGIN 1.0 deprecations diff --git a/base/linalg/dense.jl b/base/linalg/dense.jl index 1c4a3f453d4d6..0f96ffc3ab5dd 100644 --- a/base/linalg/dense.jl +++ b/base/linalg/dense.jl @@ -914,10 +914,12 @@ function cond(A::AbstractMatrix, p::Real=2) return maxv == 0.0 ? oftype(real(A[1,1]),Inf) : maxv / minimum(v) elseif p == 1 || p == Inf checksquare(A) - return cond(lufact(A), p) + return _cond1Inf(A, p) end throw(ArgumentError("p-norm must be 1, 2 or Inf, got $p")) end +_cond1Inf(A::StridedMatrix{<:BlasFloat}, p::Real) = _cond1Inf(lufact(A), p, norm(A, p)) +_cond1Inf(A::AbstractMatrix, p::Real) = norm(A, p)*norm(inv(A), p) ## Lyapunov and Sylvester equation diff --git a/base/linalg/lu.jl b/base/linalg/lu.jl index 577d1a7e97656..67cc4dd81dbdb 100644 --- a/base/linalg/lu.jl +++ b/base/linalg/lu.jl @@ -112,7 +112,6 @@ The relationship between `F` and `A` is |:---------------------------------|:-----|:-----------------------| | [`/`](@ref) | ✓ | | | [`\\`](@ref) | ✓ | ✓ | -| [`cond`](@ref) | ✓ | | | [`det`](@ref) | ✓ | ✓ | | [`logdet`](@ref) | ✓ | ✓ | | [`logabsdet`](@ref) | ✓ | ✓ | @@ -309,9 +308,12 @@ inv!(A::LU{<:BlasFloat,<:StridedMatrix}) = inv(A::LU{<:BlasFloat,<:StridedMatrix}) = inv!(LU(copy(A.factors), copy(A.ipiv), copy(A.info))) -cond(A::LU{<:BlasFloat,<:StridedMatrix}, p::Number) = - inv(LAPACK.gecon!(p == 1 ? '1' : 'I', A.factors, norm((A[:L]*A[:U])[A[:p],:], p))) -cond(A::LU, p::Number) = norm(A[:L]*A[:U],p)*norm(inv(A),p) +function _cond1Inf(A::LU{<:BlasFloat,<:StridedMatrix}, p::Number, normA::Real) + if p != 1 && p != Inf + throw(ArgumentError("p must be either 1 or Inf")) + end + return inv(LAPACK.gecon!(p == 1 ? '1' : 'I', A.factors, normA)) +end # Tridiagonal diff --git a/test/linalg/lu.jl b/test/linalg/lu.jl index 674a5e71cf636..fd6a59621a9c0 100644 --- a/test/linalg/lu.jl +++ b/test/linalg/lu.jl @@ -208,3 +208,6 @@ end @test @inferred(logdet(Complex64[1.0f0 0.5f0; 0.5f0 -1.0f0])) === 0.22314355f0 + 3.1415927f0im @test_throws DomainError logdet([1 1; 1 -1]) + +# Issue 21453. +@test_throws ArgumentError LinAlg._cond1Inf(lufact(randn(5,5)), 2, 2.0) From 424f8aab44996583857a69ca0a3c5d95dac11676 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Wed, 10 May 2017 01:03:43 -0400 Subject: [PATCH 0694/1534] Allocate some permanent objects in permgen and skip marking them in GC. --- src/datatype.c | 54 ++++------- src/gc.c | 27 +----- src/gc.h | 1 - src/jltypes.c | 226 +++++++++++++++++++++---------------------- src/julia_internal.h | 15 ++- src/simplevector.c | 13 +++ src/task.c | 20 ++-- 7 files changed, 170 insertions(+), 186 deletions(-) diff --git a/src/datatype.c b/src/datatype.c index 6bf0388894004..0bf85c8af246a 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -488,6 +488,14 @@ void jl_assign_bits(void *dest, jl_value_t *bits) jl_value_t *v = jl_gc_alloc(ptls, nw * sizeof(void*), t); \ *(int##nb##_t*)jl_data_ptr(v) = x; \ return v; \ + } \ + jl_value_t *jl_permbox##nb(jl_datatype_t *t, int##nb##_t x) \ + { \ + assert(jl_isbits(t)); \ + assert(jl_datatype_size(t) == sizeof(x)); \ + jl_value_t *v = jl_gc_permobj(nw * sizeof(void*), t); \ + *(int##nb##_t*)jl_data_ptr(v) = x; \ + return v; \ } BOXN_FUNC(8, 1) BOXN_FUNC(16, 1) @@ -592,18 +600,18 @@ void jl_init_int32_int64_cache(void) { int64_t i; for(i=0; i < NBOX_C; i++) { - boxed_int32_cache[i] = jl_box32(jl_int32_type, i-NBOX_C/2); - boxed_int64_cache[i] = jl_box64(jl_int64_type, i-NBOX_C/2); + boxed_int32_cache[i] = jl_permbox32(jl_int32_type, i-NBOX_C/2); + boxed_int64_cache[i] = jl_permbox64(jl_int64_type, i-NBOX_C/2); #ifdef _P64 - boxed_ssavalue_cache[i] = jl_box64(jl_ssavalue_type, i); - boxed_slotnumber_cache[i] = jl_box64(jl_slotnumber_type, i); + boxed_ssavalue_cache[i] = jl_permbox64(jl_ssavalue_type, i); + boxed_slotnumber_cache[i] = jl_permbox64(jl_slotnumber_type, i); #else - boxed_ssavalue_cache[i] = jl_box32(jl_ssavalue_type, i); - boxed_slotnumber_cache[i] = jl_box32(jl_slotnumber_type, i); + boxed_ssavalue_cache[i] = jl_permbox32(jl_ssavalue_type, i); + boxed_slotnumber_cache[i] = jl_permbox32(jl_slotnumber_type, i); #endif } for(i=0; i < 256; i++) { - boxed_uint8_cache[i] = jl_box8(jl_uint8_type, i); + boxed_uint8_cache[i] = jl_permbox8(jl_uint8_type, i); } } @@ -611,34 +619,14 @@ void jl_init_box_caches(void) { int64_t i; for(i=0; i < 256; i++) { - boxed_int8_cache[i] = jl_box8(jl_int8_type, i); - } - for(i=0; i < NBOX_C; i++) { - boxed_int16_cache[i] = jl_box16(jl_int16_type, i-NBOX_C/2); - boxed_uint16_cache[i] = jl_box16(jl_uint16_type, i); - boxed_uint32_cache[i] = jl_box32(jl_uint32_type, i); - boxed_char_cache[i] = jl_box32(jl_char_type, i); - boxed_uint64_cache[i] = jl_box64(jl_uint64_type, i); - } -} - -void jl_mark_box_caches(jl_ptls_t ptls) -{ - int64_t i; - for(i=0; i < 256; i++) { - jl_gc_setmark(ptls, boxed_int8_cache[i]); - jl_gc_setmark(ptls, boxed_uint8_cache[i]); + boxed_int8_cache[i] = jl_permbox8(jl_int8_type, i); } for(i=0; i < NBOX_C; i++) { - jl_gc_setmark(ptls, boxed_int16_cache[i]); - jl_gc_setmark(ptls, boxed_int32_cache[i]); - jl_gc_setmark(ptls, boxed_int64_cache[i]); - jl_gc_setmark(ptls, boxed_uint16_cache[i]); - jl_gc_setmark(ptls, boxed_uint32_cache[i]); - jl_gc_setmark(ptls, boxed_char_cache[i]); - jl_gc_setmark(ptls, boxed_uint64_cache[i]); - jl_gc_setmark(ptls, boxed_ssavalue_cache[i]); - jl_gc_setmark(ptls, boxed_slotnumber_cache[i]); + boxed_int16_cache[i] = jl_permbox16(jl_int16_type, i-NBOX_C/2); + boxed_uint16_cache[i] = jl_permbox16(jl_uint16_type, i); + boxed_uint32_cache[i] = jl_permbox32(jl_uint32_type, i); + boxed_char_cache[i] = jl_permbox32(jl_char_type, i); + boxed_uint64_cache[i] = jl_permbox64(jl_uint64_type, i); } } diff --git a/src/gc.c b/src/gc.c index 497e76d612740..371919569bfbb 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1291,19 +1291,6 @@ void gc_queue_binding(jl_binding_t *bnd) static void *volatile gc_findval; // for usage from gdb, for finding the gc-root for a value #endif -// TODO rename this as it is misleading now -void jl_gc_setmark(jl_ptls_t ptls, jl_value_t *v) -{ - jl_taggedvalue_t *o = jl_astaggedvalue(v); - uintptr_t tag = o->header; - if (!gc_marked(tag)) { - uint8_t bits; - if (__likely(gc_setmark_tag(o, GC_MARKED, tag, &bits)) && !gc_verifying) { - gc_setmark_pool(ptls, o, bits); - } - } -} - // Handle the case where the stack is only partially copied. STATIC_INLINE uintptr_t gc_get_stack_addr(void *_addr, uintptr_t offset, uintptr_t lb, uintptr_t ub) @@ -2362,16 +2349,6 @@ static void jl_gc_queue_remset(jl_gc_mark_cache_t *gc_cache, gc_mark_sp_t *sp, j ptls2->heap.rem_bindings.len = n_bnd_refyoung; } -static void jl_gc_mark_ptrfree(jl_ptls_t ptls) -{ - // Pointer-free objects, can be marked concurrently - jl_mark_box_caches(ptls); - jl_gc_setmark(ptls, (jl_value_t*)jl_emptysvec); - jl_gc_setmark(ptls, jl_emptytuple); - jl_gc_setmark(ptls, jl_true); - jl_gc_setmark(ptls, jl_false); -} - // Only one thread should be running in this function static int _jl_gc_collect(jl_ptls_t ptls, int full) { @@ -2553,14 +2530,13 @@ JL_DLLEXPORT void jl_gc_collect(int full) JL_TIMING(GC); // Now we are ready to wait for other threads to hit the safepoint, // we can do a few things that doesn't require synchronization. - jl_gc_mark_ptrfree(ptls); + // TODO (concurrently queue objects) // no-op for non-threading jl_gc_wait_for_the_world(); if (!jl_gc_disable_counter) { JL_LOCK_NOGC(&finalizers_lock); if (_jl_gc_collect(ptls, full)) { - jl_gc_mark_ptrfree(ptls); int ret = _jl_gc_collect(ptls, 0); (void)ret; assert(!ret); @@ -2589,7 +2565,6 @@ void gc_mark_queue_all_roots(jl_ptls_t ptls, gc_mark_sp_t *sp) for (size_t i = 0; i < jl_n_threads; i++) jl_gc_queue_thread_local(gc_cache, sp, jl_all_tls_states[i]); mark_roots(gc_cache, sp); - jl_gc_mark_ptrfree(ptls); } // allocator entry points diff --git a/src/gc.h b/src/gc.h index 44785fda43298..9b6ea7d1c1ab0 100644 --- a/src/gc.h +++ b/src/gc.h @@ -491,7 +491,6 @@ void gc_mark_queue_finlist(jl_gc_mark_cache_t *gc_cache, gc_mark_sp_t *sp, arraylist_t *list, size_t start); void gc_mark_loop(jl_ptls_t ptls, gc_mark_sp_t sp); void gc_debug_init(void); -void jl_mark_box_caches(jl_ptls_t ptls); extern void *gc_mark_label_addrs[_GC_MARK_L_MAX]; diff --git a/src/jltypes.c b/src/jltypes.c index 01724a722571e..3edfd5296a687 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -1547,14 +1547,13 @@ void jl_init_types(void) jl_symbol_type = jl_sym_type; jl_simplevector_type = jl_new_uninitialized_datatype(); jl_methtable_type = jl_new_uninitialized_datatype(); - jl_nothing = jl_gc_alloc(ptls, 0, NULL); + jl_nothing = jl_gc_permobj(0, NULL); jl_default_cgparams.hooks.module_setup = jl_nothing; jl_default_cgparams.hooks.module_activation = jl_nothing; jl_default_cgparams.hooks.raise_exception = jl_nothing; - jl_emptysvec = (jl_svec_t*)jl_gc_alloc(ptls, sizeof(void*), - jl_simplevector_type); + jl_emptysvec = (jl_svec_t*)jl_gc_permobj(sizeof(void*), jl_simplevector_type); jl_svec_set_len_unsafe(jl_emptysvec, 0); jl_any_type = (jl_datatype_t*)jl_new_abstracttype((jl_value_t*)jl_symbol("Any"), NULL, jl_emptysvec); @@ -1569,23 +1568,23 @@ void jl_init_types(void) jl_datatype_type->name->wrapper = (jl_value_t*)jl_datatype_type; jl_datatype_type->super = (jl_datatype_t*)jl_type_type; jl_datatype_type->parameters = jl_emptysvec; - jl_datatype_type->name->names = jl_svec(16, - jl_symbol("name"), - jl_symbol("super"), - jl_symbol("parameters"), - jl_symbol("types"), - jl_symbol("instance"), - jl_symbol("layout"), - jl_symbol("size"), - jl_symbol("ninitialized"), - jl_symbol("uid"), - jl_symbol("abstract"), - jl_symbol("mutable"), - jl_symbol("llvm::StructType"), - jl_symbol("llvm::DIType"), - jl_symbol("depth"), - jl_symbol("hasfreetypevars"), - jl_symbol("isleaftype")); + jl_datatype_type->name->names = jl_perm_symsvec(16, + "name", + "super", + "parameters", + "types", + "instance", + "layout", + "size", + "ninitialized", + "uid", + "abstract", + "mutable", + "llvm::StructType", + "llvm::DIType", + "depth", + "hasfreetypevars", + "isleaftype"); jl_datatype_type->types = jl_svec(16, jl_typename_type, jl_datatype_type, @@ -1610,10 +1609,10 @@ void jl_init_types(void) jl_typename_type->name->mt = jl_new_method_table(jl_typename_type->name->name, ptls->current_module); jl_typename_type->super = jl_any_type; jl_typename_type->parameters = jl_emptysvec; - jl_typename_type->name->names = jl_svec(8, jl_symbol("name"), jl_symbol("module"), - jl_symbol("names"), jl_symbol("wrapper"), - jl_symbol("cache"), jl_symbol("linearcache"), - jl_symbol("hash"), jl_symbol("mt")); + jl_typename_type->name->names = jl_perm_symsvec(8, "name", "module", + "names", "wrapper", + "cache", "linearcache", + "hash", "mt"); jl_typename_type->types = jl_svec(8, jl_sym_type, jl_any_type, jl_simplevector_type, jl_type_type, jl_simplevector_type, jl_simplevector_type, jl_any_type, jl_any_type); @@ -1630,10 +1629,10 @@ void jl_init_types(void) jl_methtable_type->name->mt = jl_new_method_table(jl_methtable_type->name->name, ptls->current_module); jl_methtable_type->super = jl_any_type; jl_methtable_type->parameters = jl_emptysvec; - jl_methtable_type->name->names = jl_svec(9, jl_symbol("name"), jl_symbol("defs"), - jl_symbol("cache"), jl_symbol("max_args"), - jl_symbol("kwsorter"), jl_symbol("module"), - jl_symbol("backedges"), jl_symbol(""), jl_symbol("")); + jl_methtable_type->name->names = jl_perm_symsvec(9, "name", "defs", + "cache", "max_args", + "kwsorter", "module", + "backedges", "", ""); jl_methtable_type->types = jl_svec(9, jl_sym_type, jl_any_type, jl_any_type, jl_any_type/*jl_long*/, jl_any_type, jl_any_type/*module*/, jl_any_type/*any vector*/, jl_any_type/*long*/, jl_any_type/*int32*/); @@ -1666,7 +1665,7 @@ void jl_init_types(void) jl_simplevector_type->name->mt = jl_new_method_table(jl_simplevector_type->name->name, ptls->current_module); jl_simplevector_type->super = jl_any_type; jl_simplevector_type->parameters = jl_emptysvec; - jl_simplevector_type->name->names = jl_svec(1, jl_symbol("length")); + jl_simplevector_type->name->names = jl_perm_symsvec(1, "length"); jl_simplevector_type->types = jl_svec(1, jl_any_type); jl_simplevector_type->uid = jl_assign_type_uid(); jl_simplevector_type->instance = NULL; @@ -1679,7 +1678,7 @@ void jl_init_types(void) // now they can be used to create the remaining base kinds and types jl_void_type = jl_new_datatype(jl_symbol("Void"), jl_any_type, jl_emptysvec, jl_emptysvec, jl_emptysvec, 0, 0, 0); - jl_set_typeof(jl_nothing, jl_void_type); + jl_astaggedvalue(jl_nothing)->header = ((uintptr_t)jl_void_type) | GC_OLD_MARKED; jl_void_type->instance = jl_nothing; jl_datatype_t *type_type = (jl_datatype_t*)jl_type_type; @@ -1689,19 +1688,18 @@ void jl_init_types(void) jl_typeofbottom_type->instance = jl_bottom_type; jl_uniontype_type = jl_new_datatype(jl_symbol("Union"), type_type, jl_emptysvec, - jl_svec(2, jl_symbol("a"), jl_symbol("b")), + jl_perm_symsvec(2, "a", "b"), jl_svec(2, jl_any_type, jl_any_type), 0, 0, 2); jl_tvar_type = jl_new_datatype(jl_symbol("TypeVar"), jl_any_type, jl_emptysvec, - jl_svec(3, jl_symbol("name"), - jl_symbol("lb"), jl_symbol("ub")), + jl_perm_symsvec(3, "name", "lb", "ub"), jl_svec(3, jl_sym_type, jl_any_type, jl_any_type), 0, 1, 3); jl_unionall_type = jl_new_datatype(jl_symbol("UnionAll"), type_type, jl_emptysvec, - jl_svec(2, jl_symbol("var"), jl_symbol("body")), + jl_perm_symsvec(2, "var", "body"), jl_svec(2, jl_tvar_type, jl_any_type), 0, 0, 2); @@ -1731,7 +1729,7 @@ void jl_init_types(void) jl_emptytuple_type = jl_apply_tuple_type(jl_emptysvec); jl_emptytuple_type->uid = jl_assign_type_uid(); - jl_emptytuple = jl_gc_alloc(ptls, 0, jl_emptytuple_type); + jl_emptytuple = jl_gc_permobj(0, jl_emptytuple_type); jl_emptytuple_type->instance = jl_emptytuple; // non-primitive definitions follow @@ -1747,18 +1745,18 @@ void jl_init_types(void) jl_any_type, jl_emptysvec, 8); jl_ssavalue_type = jl_new_datatype(jl_symbol("SSAValue"), jl_any_type, jl_emptysvec, - jl_svec1(jl_symbol("id")), + jl_perm_symsvec(1, "id"), jl_svec1(jl_long_type), 0, 0, 1); jl_abstractslot_type = jl_new_abstracttype((jl_value_t*)jl_symbol("Slot"), jl_any_type, jl_emptysvec); jl_slotnumber_type = jl_new_datatype(jl_symbol("SlotNumber"), jl_abstractslot_type, jl_emptysvec, - jl_svec1(jl_symbol("id")), + jl_perm_symsvec(1, "id"), jl_svec1(jl_long_type), 0, 0, 1); jl_typedslot_type = jl_new_datatype(jl_symbol("TypedSlot"), jl_abstractslot_type, jl_emptysvec, - jl_svec(2, jl_symbol("id"), jl_symbol("typ")), + jl_perm_symsvec(2, "id", "typ"), jl_svec(2, jl_long_type, jl_any_type), 0, 0, 2); jl_init_int32_int64_cache(); @@ -1766,19 +1764,18 @@ void jl_init_types(void) jl_bool_type = NULL; jl_bool_type = jl_new_primitivetype((jl_value_t*)jl_symbol("Bool"), jl_any_type, jl_emptysvec, 8); - jl_false = jl_box8(jl_bool_type, 0); - jl_true = jl_box8(jl_bool_type, 1); + jl_false = jl_permbox8(jl_bool_type, 0); + jl_true = jl_permbox8(jl_bool_type, 1); jl_typemap_level_type = jl_new_datatype(jl_symbol("TypeMapLevel"), jl_any_type, jl_emptysvec, - jl_svec(7, - jl_symbol("index_arg1"), - jl_symbol("arg1"), - jl_symbol("index_targ"), - jl_symbol("targ"), - jl_symbol("list"), - jl_symbol("any"), - jl_symbol("key")), + jl_perm_symsvec(7, "index_arg1", + "arg1", + "index_targ", + "targ", + "list", + "any", + "key"), jl_svec(7, jl_any_type, jl_any_type, @@ -1791,17 +1788,17 @@ void jl_init_types(void) jl_typemap_entry_type = jl_new_datatype(jl_symbol("TypeMapEntry"), jl_any_type, jl_emptysvec, - jl_svec(10, - jl_symbol("next"), - jl_symbol("sig"), - jl_symbol("simplesig"), - jl_symbol("guardsigs"), - jl_symbol("min_world"), - jl_symbol("max_world"), - jl_symbol("func"), - jl_symbol("isleafsig"), - jl_symbol("issimplesig"), - jl_symbol("va")), + jl_perm_symsvec(10, + "next", + "sig", + "simplesig", + "guardsigs", + "min_world", + "max_world", + "func", + "isleafsig", + "issimplesig", + "va"), jl_svec(10, jl_any_type, // Union{TypeMapEntry, Void} jl_type_type, // TupleType @@ -1849,60 +1846,59 @@ void jl_init_types(void) jl_expr_type = jl_new_datatype(jl_symbol("Expr"), jl_any_type, jl_emptysvec, - jl_svec(3, jl_symbol("head"), jl_symbol("args"), - jl_symbol("typ")), + jl_perm_symsvec(3, "head", "args", "typ"), jl_svec(3, jl_sym_type, jl_array_any_type, jl_any_type), 0, 1, 3); jl_linenumbernode_type = jl_new_datatype(jl_symbol("LineNumberNode"), jl_any_type, jl_emptysvec, - jl_svec(1, jl_symbol("line")), + jl_perm_symsvec(1, "line"), jl_svec(1, jl_long_type), 0, 0, 1); jl_labelnode_type = jl_new_datatype(jl_symbol("LabelNode"), jl_any_type, jl_emptysvec, - jl_svec(1, jl_symbol("label")), + jl_perm_symsvec(1, "label"), jl_svec(1, jl_long_type), 0, 0, 1); jl_gotonode_type = jl_new_datatype(jl_symbol("GotoNode"), jl_any_type, jl_emptysvec, - jl_svec(1, jl_symbol("label")), + jl_perm_symsvec(1, "label"), jl_svec(1, jl_long_type), 0, 0, 1); jl_quotenode_type = jl_new_datatype(jl_symbol("QuoteNode"), jl_any_type, jl_emptysvec, - jl_svec(1, jl_symbol("value")), + jl_perm_symsvec(1, "value"), jl_svec(1, jl_any_type), 0, 0, 1); jl_newvarnode_type = jl_new_datatype(jl_symbol("NewvarNode"), jl_any_type, jl_emptysvec, - jl_svec(1, jl_symbol("slot")), + jl_perm_symsvec(1, "slot"), jl_svec(1, jl_slotnumber_type), 0, 0, 1); jl_module_type = jl_new_datatype(jl_symbol("Module"), jl_any_type, jl_emptysvec, - jl_svec(2, jl_symbol("name"), jl_symbol("parent")), + jl_perm_symsvec(2, "name", "parent"), jl_svec(2, jl_sym_type, jl_any_type), 0, 1, 2); jl_globalref_type = jl_new_datatype(jl_symbol("GlobalRef"), jl_any_type, jl_emptysvec, - jl_svec(2, jl_symbol("mod"), jl_symbol("name")), + jl_perm_symsvec(2, "mod", "name"), jl_svec(2, jl_module_type, jl_sym_type), 0, 0, 2); jl_code_info_type = jl_new_datatype(jl_symbol("CodeInfo"), jl_any_type, jl_emptysvec, - jl_svec(9, - jl_symbol("code"), - jl_symbol("slottypes"), - jl_symbol("ssavaluetypes"), - jl_symbol("slotflags"), - jl_symbol("slotnames"), - jl_symbol("inferred"), - jl_symbol("inlineable"), - jl_symbol("propagate_inbounds"), - jl_symbol("pure")), + jl_perm_symsvec(9, + "code", + "slottypes", + "ssavaluetypes", + "slotflags", + "slotnames", + "inferred", + "inlineable", + "propagate_inbounds", + "pure"), jl_svec(9, jl_array_any_type, jl_any_type, @@ -1918,26 +1914,26 @@ void jl_init_types(void) jl_method_type = jl_new_datatype(jl_symbol("Method"), jl_any_type, jl_emptysvec, - jl_svec(19, - jl_symbol("name"), - jl_symbol("module"), - jl_symbol("file"), - jl_symbol("line"), - jl_symbol("sig"), - jl_symbol("min_world"), - jl_symbol("ambig"), - jl_symbol("specializations"), - jl_symbol("sparam_syms"), - jl_symbol("source"), - jl_symbol("unspecialized"), - jl_symbol("generator"), - jl_symbol("roots"), - jl_symbol("invokes"), - jl_symbol("nargs"), - jl_symbol("called"), - jl_symbol("isva"), - jl_symbol("isstaged"), - jl_symbol("pure")), + jl_perm_symsvec(19, + "name", + "module", + "file", + "line", + "sig", + "min_world", + "ambig", + "specializations", + "sparam_syms", + "source", + "unspecialized", + "generator", + "roots", + "invokes", + "nargs", + "called", + "isva", + "isstaged", + "pure"), jl_svec(19, jl_sym_type, jl_module_type, @@ -1963,22 +1959,22 @@ void jl_init_types(void) jl_method_instance_type = jl_new_datatype(jl_symbol("MethodInstance"), jl_any_type, jl_emptysvec, - jl_svec(16, - jl_symbol("specTypes"), - jl_symbol("rettype"), - jl_symbol("sparam_vals"), - jl_symbol("backedges"), - jl_symbol("inferred"), - jl_symbol("inferred_const"), - jl_symbol("def"), - jl_symbol("min_world"), - jl_symbol("max_world"), - jl_symbol("inInference"), - jl_symbol("jlcall_api"), - jl_symbol(""), - jl_symbol("fptr"), - jl_symbol("unspecialized_ducttape"), - jl_symbol(""), jl_symbol("")), + jl_perm_symsvec(16, + "specTypes", + "rettype", + "sparam_vals", + "backedges", + "inferred", + "inferred_const", + "def", + "min_world", + "max_world", + "inInference", + "jlcall_api", + "", + "fptr", + "unspecialized_ducttape", + "", ""), jl_svec(16, jl_any_type, jl_any_type, @@ -2032,7 +2028,7 @@ void jl_init_types(void) jl_abstractstring_type = jl_new_abstracttype((jl_value_t*)jl_symbol("AbstractString"), jl_any_type, jl_emptysvec); jl_string_type = jl_new_datatype(jl_symbol("String"), jl_abstractstring_type, jl_emptysvec, - jl_svec1(jl_symbol("len")), jl_svec1(jl_long_type), + jl_perm_symsvec(1, "len"), jl_svec1(jl_long_type), 0, 1, 1); // complete builtin type metadata diff --git a/src/julia_internal.h b/src/julia_internal.h index 7ae0d3391c195..4721f93feec2e 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -265,6 +265,20 @@ STATIC_INLINE void *jl_gc_alloc_buf(jl_ptls_t ptls, size_t sz) return jl_gc_alloc(ptls, sz, (void*)jl_buff_tag); } +STATIC_INLINE jl_value_t *jl_gc_permobj(size_t sz, void *ty) +{ + const size_t allocsz = sz + sizeof(jl_taggedvalue_t); + jl_taggedvalue_t *o = (jl_taggedvalue_t*)jl_gc_perm_alloc(allocsz, 0); + uintptr_t tag = (uintptr_t)ty; + o->header = tag | GC_OLD_MARKED; + return jl_valueof(o); +} +jl_value_t *jl_permbox8(jl_datatype_t *t, int8_t x); +jl_value_t *jl_permbox16(jl_datatype_t *t, int16_t x); +jl_value_t *jl_permbox32(jl_datatype_t *t, int32_t x); +jl_value_t *jl_permbox64(jl_datatype_t *t, int64_t x); +jl_svec_t *jl_perm_symsvec(size_t n, ...); + // Returns a int32 where the high 16 bits are a lower bound of the number of non-pointer fields // at the beginning of the type and the low 16 bits are a lower bound on the number of non-pointer // fields at the end of the type. This field only exists for a layout that has at least one @@ -357,7 +371,6 @@ jl_tupletype_t *jl_argtype_with_function(jl_function_t *f, jl_tupletype_t *types JL_DLLEXPORT jl_value_t *jl_apply_2va(jl_value_t *f, jl_value_t **args, uint32_t nargs); -void jl_gc_setmark(jl_ptls_t ptls, jl_value_t *v); void jl_gc_sync_total_bytes(void); void jl_gc_track_malloced_array(jl_ptls_t ptls, jl_array_t *a); void jl_gc_count_allocd(size_t sz); diff --git a/src/simplevector.c b/src/simplevector.c index 805d8d3aa4163..69247924a6ee9 100644 --- a/src/simplevector.c +++ b/src/simplevector.c @@ -19,6 +19,19 @@ JL_DLLEXPORT jl_svec_t *jl_svec(size_t n, ...) return jv; } +jl_svec_t *jl_perm_symsvec(size_t n, ...) +{ + if (n == 0) return jl_emptysvec; + jl_svec_t *jv = (jl_svec_t*)jl_gc_permobj((n + 1) * sizeof(void*), jl_simplevector_type); + jl_svec_set_len_unsafe(jv, n); + va_list args; + va_start(args, n); + for (size_t i = 0; i < n; i++) + jl_svecset(jv, i, jl_symbol(va_arg(args, const char*))); + va_end(args); + return jv; +} + JL_DLLEXPORT jl_svec_t *jl_svec1(void *a) { jl_ptls_t ptls = jl_get_ptls_states(); diff --git a/src/task.c b/src/task.c index c4e0a465bcfac..37fedf3838eae 100644 --- a/src/task.c +++ b/src/task.c @@ -660,16 +660,16 @@ void jl_init_tasks(void) jl_new_datatype(jl_symbol("Task"), jl_any_type, jl_emptysvec, - jl_svec(9, - jl_symbol("parent"), - jl_symbol("storage"), - jl_symbol("state"), - jl_symbol("consumers"), - jl_symbol("donenotify"), - jl_symbol("result"), - jl_symbol("exception"), - jl_symbol("backtrace"), - jl_symbol("code")), + jl_perm_symsvec(9, + "parent", + "storage", + "state", + "consumers", + "donenotify", + "result", + "exception", + "backtrace", + "code"), jl_svec(9, jl_any_type, jl_any_type, From 6e8006b87c559048a40985dc9325576a1c2c32f9 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Wed, 10 May 2017 01:19:07 -0400 Subject: [PATCH 0695/1534] Do not call mprotect if there is only one thread --- src/safepoint.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/safepoint.c b/src/safepoint.c index b4281af0c966e..43dad38f4fad4 100644 --- a/src/safepoint.c +++ b/src/safepoint.c @@ -110,6 +110,10 @@ void jl_safepoint_init(void) int jl_safepoint_start_gc(void) { #ifdef JULIA_ENABLE_THREADING + if (jl_n_threads == 1) { + jl_gc_running = 1; + return 1; + } // The thread should have set this already assert(jl_get_ptls_states()->gc_state == JL_GC_STATE_WAITING); jl_mutex_lock_nogc(&safepoint_lock); @@ -139,6 +143,10 @@ void jl_safepoint_end_gc(void) { assert(jl_gc_running); #ifdef JULIA_ENABLE_THREADING + if (jl_n_threads == 1) { + jl_gc_running = 0; + return; + } jl_mutex_lock_nogc(&safepoint_lock); // Need to reset the page protection before resetting the flag since // the thread will trigger a segfault immediately after returning from From cd468eecd45230ca3aa7d22cdae244649e260ec7 Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Fri, 5 May 2017 14:34:58 -0400 Subject: [PATCH 0696/1534] Make fixup_libgfortran more resilient against SONAME changes --- contrib/fixup-libgfortran.sh | 110 +++++++++++++++++++++-------------- 1 file changed, 66 insertions(+), 44 deletions(-) diff --git a/contrib/fixup-libgfortran.sh b/contrib/fixup-libgfortran.sh index 4f426e9e7d647..7467b1d39dc52 100755 --- a/contrib/fixup-libgfortran.sh +++ b/contrib/fixup-libgfortran.sh @@ -31,74 +31,96 @@ find_shlib () if [ -f "$private_libdir/lib$1.$SHLIB_EXT" ]; then if [ "$UNAME" = "Linux" ]; then ldd "$private_libdir/lib$1.$SHLIB_EXT" | grep $2 | cut -d' ' -f3 | xargs - elif [ "$UNAME" = "Darwin" ]; then + else # $UNAME is "Darwin", we only have two options, see above otool -L "$private_libdir/lib$1.$SHLIB_EXT" | grep $2 | cut -d' ' -f1 | xargs fi fi } # First, discover all the places where libgfortran/libgcc is, as well as their true SONAMES -for lib in arpack openlibm openspecfun lapack; do +for lib in arpack openspecfun lapack; do if [ -f "$private_libdir/lib$lib.$SHLIB_EXT" ]; then - LIBGFORTRAN_DIRS="$LIBGFORTRAN_DIRS $(dirname $(find_shlib $lib libgfortran) 2>/dev/null)" - LIBGFORTRAN_DIRS="$LIBGFORTRAN_DIRS $(dirname $(find_shlib $lib libgcc_s) 2>/dev/null)" - LIBGFORTRAN_DIRS="$LIBGFORTRAN_DIRS $(dirname $(find_shlib $lib libquadmath) 2>/dev/null)" + # Find the paths to the libraries we're interested in. These are almost + # always within the same directory, but we like to be general. + LIBGFORTRAN_PATH=$(find_shlib $lib libgfortran) + LIBGCC_PATH=$(find_shlib $lib libgcc_s) + LIBQUADMATH_PATH=$(find_shlib $lib libquadmath) + + # Take the directories, add them onto LIBGFORTRAN_DIRS to search for things later + LIBGFORTRAN_DIRS="$LIBGFORTRAN_DIRS $(dirname $LIBGFORTRAN_PATH)" + LIBGFORTRAN_DIRS="$LIBGFORTRAN_DIRS $(dirname $LIBGCC_PATH)" + LIBGFORTRAN_DIRS="$LIBGFORTRAN_DIRS $(dirname $LIBQUADMATH_PATH)" + + # Save the SONAMES + LIBGFORTRAN_SONAMES="$LIBGFORTRAN_SONAMES $(basename "$LIBGFORTRAN_PATH")" + LIBGCC_SONAMES="$LIBGCC_SONAMES $(basename "$LIBGCC_PATH")" + LIBQUADMATH_SONAMES="$LIBQUADMATH_SONAMES $(basename "$LIBQUADMATH_PATH")" fi done -LIBGFORTRAN_DIRS=$(echo "$LIBGFORTRAN_DIRS" | tr " " "\n" | sort | uniq | grep -v '^$' | tr "\n" " ") +# Take in a list of space-separated tokens, return a deduplicated list of the same +uniquify() +{ + echo "$1" | tr " " "\n" | sort | uniq | grep -v '^$' | tr "\n" " " +} -# If only we could agree on something -if [ "$UNAME" = "Linux" ]; then - NAMEXTS="gcc_s.so.1 gfortran.so.3 quadmath.so.0" -elif [ "$UNAME" = "Darwin" ]; then - NAMEXTS="gcc_s.1.dylib gfortran.3.dylib quadmath.0.dylib" -fi +LIBGFORTRAN_DIRS=$(uniquify "$LIBGFORTRAN_DIRS") +SONAMES="$(uniquify "$LIBGFORTRAN_SONAMES $LIBGCC_SONAMES $LIBQUADMATH_SONAMES")" -for namext in $NAMEXTS; do +# Copy the SONAMEs we identified above into our private_libdir +for soname in $SONAMES; do for dir in $LIBGFORTRAN_DIRS; do - if [ ! -f "$private_libdir/lib$namext" ] && [ -f "$dir/lib$namext" ]; then - cp -v "$dir/lib$namext" "$private_libdir" - chmod 755 "$private_libdir/lib$namext" + if [ ! -f "$private_libdir/$soname" ] && [ -f "$dir/$soname" ]; then + cp -v "$dir/$soname" "$private_libdir" + chmod 755 "$private_libdir/$soname" if [ "$UNAME" = "Darwin" ]; then - install_name_tool -id @rpath/lib$namext "$private_libdir/lib$namext" + install_name_tool -id "@rpath/$soname" "$private_libdir/$soname" fi fi done -done -# Add possible internal directories to LIBGFORTRAN_DIRS -for lib in gfortran.3 quadmath.0 gcc_s.1 ; do - if [ -f "$private_libdir/lib$lib.$SHLIB_EXT" ]; then - LIBGFORTRAN_DIRS="$LIBGFORTRAN_DIRS $(dirname $(find_shlib $lib libgfortran) 2>/dev/null)" - LIBGFORTRAN_DIRS="$LIBGFORTRAN_DIRS $(dirname $(find_shlib $lib libgcc_s) 2>/dev/null)" - LIBGFORTRAN_DIRS="$LIBGFORTRAN_DIRS $(dirname $(find_shlib $lib libquadmath) 2>/dev/null)" + # Add possible internal directories to LIBGFORTRAN_DIRS so that we can find all possible ways + # That any of our libraries or these libraries we just copied in link to themselves later. + if [ -f "$private_libdir/$soname" ]; then + LIBGFORTRAN_DIRS="$LIBGFORTRAN_DIRS $(dirname $(find_shlib $lib libgfortran))" + LIBGFORTRAN_DIRS="$LIBGFORTRAN_DIRS $(dirname $(find_shlib $lib libgcc_s))" + LIBGFORTRAN_DIRS="$LIBGFORTRAN_DIRS $(dirname $(find_shlib $lib libquadmath))" fi done -LIBGFORTRAN_DIRS=$(echo "$LIBGFORTRAN_DIRS" | tr " " "\n" | sort | uniq | grep -v '^$' | tr "\n" " ") + +change_linkage() +{ + shlib_path="$1" + old_link="$2" + new_link="$3" + if [ "$UNAME" = "Darwin" ]; then + install_name_tool -change "$old_link" "$new_link" "$shlib_path" + else # $UNAME is "Linux", we only have two options, see above + patchelf --set-rpath \$ORIGIN "$shlib_path" + fi +} + +LIBGFORTRAN_DIRS=$(uniquify "$LIBGFORTRAN_DIRS") echo "Found traces of libgfortran/libgcc in $LIBGFORTRAN_DIRS" +# For every library that remotely touches libgfortran stuff (so the libraries +# we have copied in ourselves as well as arpack, openspecfun, etc...) we must +# update the linkage to point to @rpath (on OSX) or $ORIGIN (on Linux) so +# that direct links to the old libgfortran directories are instead directed +# to the proper location, which is our $private_libdir. +cd $private_libdir -# Do the private_libdir libraries -if [ "$UNAME" = "Darwin" ]; then - cd $private_libdir - for file in openlibm quadmath.0 gfortran.3 openblas arpack lapack openspecfun; do - for dylib in $(ls lib$file*.dylib* 2>/dev/null); do - for dir in $LIBGFORTRAN_DIRS; do - install_name_tool -change "$dir/libgfortran.3.dylib" @rpath/libgfortran.3.dylib $dylib - install_name_tool -change "$dir/libquadmath.0.dylib" @rpath/libquadmath.0.dylib $dylib - install_name_tool -change "$dir/libgcc_s.1.dylib" @rpath/libgcc_s.1.dylib $dylib - done +# Iterate over possible library names +for soname in libopenblas libarpack libcholmod liblapack libopenspecfun $SONAMES; do + # Grab every incarnation of that library that exists within $private_libdir + # (e.g. "libopenspecfun.so", and "libopenspecfun.so.0", etc...) + for lib in $private_libdir/$soname*.$SHLIB_EXT*; do + # Look for links to any of the our three musketeers within ANY of the + # potential LIBGFORTRAN_DIRS we've discovered so far + for dir in $LIBGFORTRAN_DIRS; do + change_linkage "$lib" "$dir/$soname" "@rpath/$soname" done done -fi +done -if [ "$UNAME" = "Linux" ]; then - cd $private_libdir - for file in openlibm quadmath gfortran openblas arpack lapack openspecfun; do - for dylib in $(ls lib$file*.so* 2>/dev/null); do - patchelf --set-rpath \$ORIGIN $dylib - done - done -fi From 05708f8f8296fbecc3302dea6532197297633318 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Wed, 29 Mar 2017 17:40:35 +0700 Subject: [PATCH 0697/1534] make iszero(::BigInt) faster Avoid a library call into GMP. --- base/gmp.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/gmp.jl b/base/gmp.jl index 67e4aa70b2b37..38cb9e46dbdf7 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -508,7 +508,7 @@ binomial(n::BigInt, k::Integer) = k < 0 ? BigInt(0) : binomial(n, UInt(k)) ==(i::Integer, x::BigInt) = cmp(x,i) == 0 ==(x::BigInt, f::CdoubleMax) = isnan(f) ? false : cmp(x,f) == 0 ==(f::CdoubleMax, x::BigInt) = isnan(f) ? false : cmp(x,f) == 0 -iszero(x::BigInt) = x == Clong(0) +iszero(x::BigInt) = x.size == 0 <=(x::BigInt, y::BigInt) = cmp(x,y) <= 0 <=(x::BigInt, i::Integer) = cmp(x,i) <= 0 From 42fd2a7d8acccb8562580873760a05c2a607645a Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Thu, 30 Mar 2017 12:05:55 +0700 Subject: [PATCH 0698/1534] speed-up prevpow2 & nextpow2 for BigInt --- base/gmp.jl | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/base/gmp.jl b/base/gmp.jl index 38cb9e46dbdf7..09605241b2e7c 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -385,6 +385,13 @@ trailing_ones(x::BigInt) = Int(ccall((:__gmpz_scan0, :libgmp), Culong, (Ptr{BigI count_ones(x::BigInt) = Int(ccall((:__gmpz_popcount, :libgmp), Culong, (Ptr{BigInt},), &x)) +""" + count_ones_abs(x::BigInt) + +Number of ones in the binary representation of abs(x). +""" +count_ones_abs(x::BigInt) = iszero(x) ? 0 : ccall((:__gmpn_popcount, :libgmp), Culong, (Ptr{Limb}, Csize_t), x.d, abs(x.size)) % Int + function divrem(x::BigInt, y::BigInt) z1 = BigInt() z2 = BigInt() @@ -521,6 +528,8 @@ iszero(x::BigInt) = x.size == 0 <(i::Integer, x::BigInt) = cmp(x,i) > 0 <(x::BigInt, f::CdoubleMax) = isnan(f) ? false : cmp(x,f) < 0 <(f::CdoubleMax, x::BigInt) = isnan(f) ? false : cmp(x,f) > 0 +isneg(x::BigInt) = x.size < 0 +ispos(x::BigInt) = x.size > 0 string(x::BigInt) = dec(x) show(io::IO, x::BigInt) = print(io, string(x)) @@ -580,8 +589,19 @@ function ndigits0z(x::BigInt, b::Integer=10) end ndigits(x::BigInt, b::Integer=10) = x.size == 0 ? 1 : ndigits0z(x,b) -prevpow2(x::BigInt) = x.size < 0 ? -prevpow2(-x) : (x <= 2 ? x : one(BigInt) << (ndigits(x, 2)-1)) -nextpow2(x::BigInt) = x.size < 0 ? -nextpow2(-x) : (x <= 2 ? x : one(BigInt) << ndigits(x-1, 2)) +function prevpow2(x::BigInt) + -2 <= x <= 2 && return x + r = one(BigInt) << (ndigits(x, 2)-1) + isneg(x) && (r.size = -r.size) + return r +end + +function nextpow2(x::BigInt) + count_ones_abs(x) <= 1 && return x + r = one(BigInt) << ndigits(x, 2) + isneg(x) && (r.size = -r.size) + return r +end Base.checked_abs(x::BigInt) = abs(x) Base.checked_neg(x::BigInt) = -x From f63bdfdaad633bcbca23ea7641a6a12f33d90313 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Thu, 30 Mar 2017 12:32:32 +0700 Subject: [PATCH 0699/1534] GMP: add flipsign[!] functions and use more iszero/isneg/ispos --- base/gmp.jl | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/base/gmp.jl b/base/gmp.jl index 09605241b2e7c..f85656d0836f7 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -9,7 +9,7 @@ import Base: *, +, -, /, <, <<, >>, >>>, <=, ==, >, >=, ^, (~), (&), (|), xor, ndigits, promote_rule, rem, show, isqrt, string, powermod, sum, trailing_zeros, trailing_ones, count_ones, base, tryparse_internal, bin, oct, dec, hex, isequal, invmod, prevpow2, nextpow2, ndigits0z, widen, signed, unsafe_trunc, trunc, - iszero, big + iszero, big, flipsign, signbit if Clong == Int32 const ClongMax = Union{Int8, Int16, Int32} @@ -104,7 +104,7 @@ function tryparse_internal(::Type{BigInt}, s::AbstractString, startpos::Int, end raise && throw(ArgumentError("invalid BigInt: $(repr(bstr))")) return _n end - Nullable(sgn < 0 ? -z : z) + Nullable(flipsign!(z, sgn)) end function convert(::Type{BigInt}, x::Union{Clong,Int32}) @@ -175,7 +175,7 @@ function rem{T<:Union{Unsigned,Signed}}(x::BigInt, ::Type{T}) for l = 1:min(abs(x.size), cld(sizeof(T),sizeof(Limb))) u += (unsafe_load(x.d,l)%T) << ((sizeof(Limb)<<3)*(l-1)) end - x.size < 0 ? -u : u + flipsign(u, x) end rem(x::Integer, ::Type{BigInt}) = convert(BigInt, x) @@ -197,7 +197,7 @@ function convert(::Type{T}, x::BigInt) where T<:Signed else 0 <= n <= cld(sizeof(T),sizeof(Limb)) || throw(InexactError()) y = x % T - (x.size > 0) ⊻ (y > 0) && throw(InexactError()) # catch overflow + ispos(x) ⊻ (y > 0) && throw(InexactError()) # catch overflow y end end @@ -497,7 +497,7 @@ function sum(arr::AbstractArray{BigInt}) end function factorial(x::BigInt) - x.size < 0 && return BigInt(0) + isneg(x) && return BigInt(0) z = BigInt() ccall((:__gmpz_fac_ui, :libgmp), Void, (Ptr{BigInt}, Culong), &z, x) return z @@ -531,6 +531,10 @@ iszero(x::BigInt) = x.size == 0 isneg(x::BigInt) = x.size < 0 ispos(x::BigInt) = x.size > 0 +signbit(x::BigInt) = isneg(x) +flipsign!(x::BigInt, y::Integer) = (signbit(y) && (x.size = -x.size); x) +flipsign( x::BigInt, y::Integer) = signbit(y) ? -x : x + string(x::BigInt) = dec(x) show(io::IO, x::BigInt) = print(io, string(x)) @@ -587,21 +591,10 @@ function ndigits0z(x::BigInt, b::Integer=10) end end end -ndigits(x::BigInt, b::Integer=10) = x.size == 0 ? 1 : ndigits0z(x,b) - -function prevpow2(x::BigInt) - -2 <= x <= 2 && return x - r = one(BigInt) << (ndigits(x, 2)-1) - isneg(x) && (r.size = -r.size) - return r -end +ndigits(x::BigInt, b::Integer=10) = iszero(x) ? 1 : ndigits0z(x,b) -function nextpow2(x::BigInt) - count_ones_abs(x) <= 1 && return x - r = one(BigInt) << ndigits(x, 2) - isneg(x) && (r.size = -r.size) - return r -end +prevpow2(x::BigInt) = -2 <= x <= 2 ? x : flipsign!(one(x) << (ndigits(x, 2)-1), x) +nextpow2(x::BigInt) = count_ones_abs(x) <= 1 ? x : flipsign!(one(x) << ndigits(x, 2), x) Base.checked_abs(x::BigInt) = abs(x) Base.checked_neg(x::BigInt) = -x From b521acd6d48ffef9596d442e7791dcb6fdb66688 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Thu, 30 Mar 2017 15:48:53 +0700 Subject: [PATCH 0700/1534] add ZERO & ONE global BigInt constants for optimization --- base/gmp.jl | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/base/gmp.jl b/base/gmp.jl index f85656d0836f7..ec85233d609ae 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -50,6 +50,10 @@ mutable struct BigInt <: Integer end end +const ZERO = BigInt() +const ONE = BigInt() +const _ONE = Limb[1] + function __init__() try if gmp_version().major != GMP_VERSION.major || gmp_bits_per_limb() != GMP_BITS_PER_LIMB @@ -63,6 +67,9 @@ function __init__() cglobal(:jl_gc_counted_malloc), cglobal(:jl_gc_counted_realloc_with_old_size), cglobal(:jl_gc_counted_free)) + + ZERO.alloc, ZERO.size, ZERO.d = 0, 0, C_NULL + ONE.alloc, ONE.size, ONE.d = 1, 1, pointer(_ONE) catch ex Base.showerror_nostdio(ex, "WARNING: Error during initialization of module GMP") @@ -466,8 +473,10 @@ end powermod(x::Integer, p::Integer, m::BigInt) = powermod(big(x), big(p), m) function gcdx(a::BigInt, b::BigInt) - if b == 0 # shortcut this to ensure consistent results with gcdx(a,b) - return a < 0 ? (-a,-one(BigInt),zero(BigInt)) : (a,one(BigInt),zero(BigInt)) + if iszero(b) # shortcut this to ensure consistent results with gcdx(a,b) + return a < 0 ? (-a,-ONE,b) : (a,one(BigInt),b) + # we don't return the globals ONE and ZERO in case the user wants to + # mutate the result end g = BigInt() s = BigInt() @@ -593,8 +602,10 @@ function ndigits0z(x::BigInt, b::Integer=10) end ndigits(x::BigInt, b::Integer=10) = iszero(x) ? 1 : ndigits0z(x,b) -prevpow2(x::BigInt) = -2 <= x <= 2 ? x : flipsign!(one(x) << (ndigits(x, 2)-1), x) -nextpow2(x::BigInt) = count_ones_abs(x) <= 1 ? x : flipsign!(one(x) << ndigits(x, 2), x) +# below, ONE is always left-shifted by at least one digit, so a new BigInt is +# allocated, which can be safely mutated +prevpow2(x::BigInt) = -2 <= x <= 2 ? x : flipsign!(ONE << (ndigits(x, 2) - 1), x) +nextpow2(x::BigInt) = count_ones_abs(x) <= 1 ? x : flipsign!(ONE << ndigits(x, 2), x) Base.checked_abs(x::BigInt) = abs(x) Base.checked_neg(x::BigInt) = -x From a2a6d182dc27db943c886c4b863540d0f0981bd2 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Wed, 10 May 2017 10:50:51 -0500 Subject: [PATCH 0701/1534] Implement tryparse(Float16, str) via Float32 conversion --- base/parse.jl | 2 ++ test/parse.jl | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/base/parse.jl b/base/parse.jl index 27c00e36dcd07..754d670f9d0b8 100644 --- a/base/parse.jl +++ b/base/parse.jl @@ -195,6 +195,8 @@ tryparse(::Type{Float32}, s::SubString{String}) = ccall(:jl_try_substrtof, Nulla tryparse(::Type{T}, s::AbstractString) where {T<:Union{Float32,Float64}} = tryparse(T, String(s)) +tryparse(::Type{Float16}, s::AbstractString) = convert(Nullable{Float16}, tryparse(Float32, s)) + function parse(::Type{T}, s::AbstractString) where T<:AbstractFloat result = tryparse(T, s) if isnull(result) diff --git a/test/parse.jl b/test/parse.jl index 5716c17491687..df2f38cfbd36f 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -674,6 +674,10 @@ end # error throwing branch from #10560 @test_throws ArgumentError Base.tryparse_internal(Bool, "foo", 1, 2, 10, true) +@test tryparse(Float64, "1.23") === Nullable(1.23) +@test tryparse(Float32, "1.23") === Nullable(1.23f0) +@test tryparse(Float16, "1.23") === Nullable(Float16(1.23)) + # PR #17393 for op in (:.==, :.&, :.|, :.≤) @test parse("a $op b") == Expr(:call, op, :a, :b) From 86cf0db610cf48183cc65a2fd5f002108a251419 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Wed, 10 May 2017 19:55:20 +0200 Subject: [PATCH 0702/1534] Add isintger with Irrational argument (#21770) --- base/irrationals.jl | 1 + test/numbers.jl | 1 + 2 files changed, 2 insertions(+) diff --git a/base/irrationals.jl b/base/irrationals.jl index 366e0564c0bd1..aa5637ff13090 100644 --- a/base/irrationals.jl +++ b/base/irrationals.jl @@ -95,6 +95,7 @@ end <=(x::Rational, y::Irrational) = x < y isfinite(::Irrational) = true +isinteger(::Irrational) = false iszero(::Irrational) = false hash(x::Irrational, h::UInt) = 3*object_id(x) - h diff --git a/test/numbers.jl b/test/numbers.jl index 787fd9c5dc398..24fcb24a1864a 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -2808,6 +2808,7 @@ testmi(typemax(UInt32)-UInt32(1000):typemax(UInt32), map(UInt32, 1:100)) @test indices(1,1) == 1:1 @test_throws BoundsError indices(1,-1) @test isinteger(Integer(2)) == true +@test !isinteger(π) @test size(1) == () @test length(1) == 1 @test endof(1) == 1 From 22d4d84f954171cb687c90089c44b46ea7aca320 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Wed, 10 May 2017 21:08:24 +0200 Subject: [PATCH 0703/1534] More efficient float(T) for rationals and big*, works with Irrational (#21219) --- base/complex.jl | 3 +++ base/float.jl | 1 + base/irrationals.jl | 2 ++ base/mpfr.jl | 4 +++- base/rational.jl | 2 ++ test/floatfuncs.jl | 7 +++++++ 6 files changed, 18 insertions(+), 1 deletion(-) diff --git a/base/complex.jl b/base/complex.jl index 606f47488ce00..f6d4adf2ddd90 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -33,6 +33,9 @@ promote_rule(::Type{Complex{T}}, ::Type{Complex{S}}) where {T<:Real,S<:Real} = widen(::Type{Complex{T}}) where {T} = Complex{widen(T)} +float(::Type{Complex{T}}) where {T<:AbstractFloat} = Complex{T} +float(::Type{Complex{T}}) where {T} = Complex{float(T)} + """ real(z) diff --git a/base/float.jl b/base/float.jl index 16919ea9fe253..68d0d5138f0fe 100644 --- a/base/float.jl +++ b/base/float.jl @@ -272,6 +272,7 @@ Float64 ``` """ float(::Type{T}) where {T<:Number} = typeof(float(zero(T))) +float(::Type{T}) where {T<:AbstractFloat} = T for Ti in (Int8, Int16, Int32, Int64) @eval begin diff --git a/base/irrationals.jl b/base/irrationals.jl index aa5637ff13090..d2d76abbc0df0 100644 --- a/base/irrationals.jl +++ b/base/irrationals.jl @@ -37,6 +37,8 @@ convert(::Type{Rational{BigInt}}, x::Irrational) = throw(ArgumentError("Cannot c end end +float(::Type{<:Irrational}) = Float64 + ==(::Irrational{s}, ::Irrational{s}) where {s} = true ==(::Irrational, ::Irrational) = false diff --git a/base/mpfr.jl b/base/mpfr.jl index a05585a2a37a5..5ff7007370d10 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -10,7 +10,7 @@ import Base: (*), +, -, /, <, <=, ==, >, >=, ^, ceil, cmp, convert, copysign, div, exp, exp2, exponent, factorial, floor, fma, hypot, isinteger, isfinite, isinf, isnan, ldexp, log, log2, log10, max, min, mod, modf, - nextfloat, prevfloat, promote_rule, rem, rem2pi, round, show, + nextfloat, prevfloat, promote_rule, rem, rem2pi, round, show, float, sum, sqrt, string, print, trunc, precision, exp10, expm1, gamma, lgamma, log1p, eps, signbit, sin, cos, tan, sec, csc, cot, acos, asin, atan, @@ -118,6 +118,8 @@ end convert(::Type{Rational}, x::BigFloat) = convert(Rational{BigInt}, x) convert(::Type{AbstractFloat}, x::BigInt) = BigFloat(x) +float(::Type{BigInt}) = BigFloat + # generic constructor with arbitrary precision: """ BigFloat(x, prec::Int) diff --git a/base/rational.jl b/base/rational.jl index 2305c427d7071..a64c26a3aba98 100644 --- a/base/rational.jl +++ b/base/rational.jl @@ -429,3 +429,5 @@ iszero(x::Rational) = iszero(numerator(x)) function lerpi(j::Integer, d::Integer, a::Rational, b::Rational) ((d-j)*a)/d + (j*b)/d end + +float{T<:Integer}(::Type{Rational{T}}) = float(T) diff --git a/test/floatfuncs.jl b/test/floatfuncs.jl index 3fee77d56dbe3..e246e8df5cac6 100644 --- a/test/floatfuncs.jl +++ b/test/floatfuncs.jl @@ -68,3 +68,10 @@ for elty in (Float32,Float64) @test round.(elty2,A) == fill(round(elty2,x),(10,10,10)) end end + +@testset "Types" begin + for x in (Int16(0), 1, 2f0, pi, 3//4, big(5//6), 7.8, big(9), big(e)) + @test float(typeof(x)) == typeof(float(x)) + @test float(typeof(complex(x, x))) == typeof(float(complex(x, x))) + end +end From ba87e9986f8618f11a7013ebc925f4e9b107b02a Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 10 May 2017 14:58:18 -0400 Subject: [PATCH 0704/1534] fix error in `showerror` with backtraces from CapturedExceptions --- base/stacktraces.jl | 4 ++++ test/distributed_exec.jl | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/base/stacktraces.jl b/base/stacktraces.jl index 7ed559e6034d9..82a30cbf12f0c 100644 --- a/base/stacktraces.jl +++ b/base/stacktraces.jl @@ -136,6 +136,10 @@ end lookup(pointer::UInt) = lookup(convert(Ptr{Void}, pointer)) +# allow lookup on already-looked-up data for easier handling of pre-processed frames +lookup(s::StackFrame) = StackFrame[s] +lookup(s::Tuple{StackFrame,Int}) = StackFrame[s[1]] + """ stacktrace([trace::Vector{Ptr{Void}},] [c_funcs::Bool=false]) -> StackTrace diff --git a/test/distributed_exec.jl b/test/distributed_exec.jl index 1f7bdfb1a20f5..818c410505a2c 100644 --- a/test/distributed_exec.jl +++ b/test/distributed_exec.jl @@ -1498,6 +1498,18 @@ if true end @test x == map(_->sin(2), 1:2) +let thrown = false + try + remotecall_fetch(sqrt, 2, -1) + catch e + thrown = true + b = IOBuffer() + showerror(b, e) + @test contains(String(take!(b)), "sqrt will only return") + end + @test thrown +end + # Testing clear! function setup_syms(n, pids) syms = [] From b50fae946fcba35647ad6142039f545cba9edc2b Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Wed, 10 May 2017 17:06:53 -0700 Subject: [PATCH 0705/1534] Remove extra `$SHLIB_EXT` after `$soname` in `fixup-libgfortran` --- contrib/fixup-libgfortran.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/fixup-libgfortran.sh b/contrib/fixup-libgfortran.sh index 7467b1d39dc52..9549d08d6b430 100755 --- a/contrib/fixup-libgfortran.sh +++ b/contrib/fixup-libgfortran.sh @@ -115,7 +115,7 @@ cd $private_libdir for soname in libopenblas libarpack libcholmod liblapack libopenspecfun $SONAMES; do # Grab every incarnation of that library that exists within $private_libdir # (e.g. "libopenspecfun.so", and "libopenspecfun.so.0", etc...) - for lib in $private_libdir/$soname*.$SHLIB_EXT*; do + for lib in $private_libdir/$soname*; do # Look for links to any of the our three musketeers within ANY of the # potential LIBGFORTRAN_DIRS we've discovered so far for dir in $LIBGFORTRAN_DIRS; do From 0c89c16de505262f8216bd16a51416c80d01a8c0 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Sun, 7 May 2017 12:08:33 -0400 Subject: [PATCH 0706/1534] Optimize sysimg TLS access on Linux --- src/codegen.cpp | 12 +-- src/dump.c | 4 + src/jitlayers.cpp | 10 ++- src/jitlayers.h | 3 +- src/julia_internal.h | 1 + src/llvm-ptls.cpp | 192 +++++++++++++++++++++++++++---------------- src/threading.c | 3 + 7 files changed, 146 insertions(+), 79 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index cefa88a579fc0..a3cd82040a16e 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -340,8 +340,8 @@ static Function *jltls_states_func; static GlobalVariable *jltls_states_var; #else // Imaging mode only -static GlobalVariable *jltls_states_func_ptr = NULL; size_t jltls_states_func_idx = 0; +size_t jltls_offset_idx = 0; #endif // important functions @@ -6621,10 +6621,12 @@ static void init_julia_llvm_env(Module *m) add_named_global(jltls_states_func, jl_get_ptls_states_getter()); if (imaging_mode) { PointerType *pfunctype = jltls_states_func->getFunctionType()->getPointerTo(); - jltls_states_func_ptr = - jl_emit_sysimg_slot(m, pfunctype, "jl_get_ptls_states.ptr", - (uintptr_t)jl_get_ptls_states_getter(), - jltls_states_func_idx); + jl_emit_sysimg_slot(m, pfunctype, "jl_get_ptls_states.ptr", + (uintptr_t)jl_get_ptls_states_getter(), + jltls_states_func_idx); + jl_emit_sysimg_slot(m, T_size, "jl_tls_offset.val", + (uintptr_t)(jl_tls_offset == -1 ? 0 : jl_tls_offset), + jltls_offset_idx); } #endif diff --git a/src/dump.c b/src/dump.c index 63fb83a042d91..7e4ca4a9ad75a 100644 --- a/src/dump.c +++ b/src/dump.c @@ -241,6 +241,10 @@ static void jl_load_sysimg_so(void) "jl_ptls_states_getter_idx"); *sysimg_gvars[tls_getter_idx - 1] = (jl_value_t*)jl_get_ptls_states_getter(); + size_t tls_offset_idx = *(size_t*)jl_dlsym(jl_sysimg_handle, + "jl_tls_offset_idx"); + *sysimg_gvars[tls_offset_idx - 1] = + (jl_value_t*)(uintptr_t)(jl_tls_offset == -1 ? 0 : jl_tls_offset); #endif const char *cpu_target = (const char*)jl_dlsym(jl_sysimg_handle, "jl_sysimg_cpu_target"); if (strcmp(cpu_target,jl_options.cpu_target) != 0) diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index b049c5da6db04..bd6a40518bad2 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -1019,7 +1019,7 @@ void* jl_emit_and_add_to_shadow(GlobalVariable *gv, void *gvarinit) // Use as an optimization for runtime constant addresses to have one less // load. (Used only by threading). GlobalVariable *jl_emit_sysimg_slot(Module *m, Type *typ, const char *name, - uintptr_t init, size_t &idx) + uintptr_t init, size_t &idx) { assert(imaging_mode); // This is **NOT** a external variable or a normal global variable @@ -1027,7 +1027,7 @@ GlobalVariable *jl_emit_sysimg_slot(Module *m, Type *typ, const char *name, // in the global variable table. GlobalVariable *gv = new GlobalVariable(*m, typ, false, GlobalVariable::InternalLinkage, - ConstantPointerNull::get((PointerType*)typ), name); + Constant::getNullValue(typ), name); addComdat(gv); // make the pointer valid for this session #if defined(USE_MCJIT) || defined(USE_ORCJIT) @@ -1111,6 +1111,12 @@ static void jl_gen_llvm_globaldata(llvm::Module *mod, ValueToValueMapTy &VMap, GlobalVariable::ExternalLinkage, ConstantInt::get(T_size, jltls_states_func_idx), "jl_ptls_states_getter_idx")); + addComdat(new GlobalVariable(*mod, + T_size, + true, + GlobalVariable::ExternalLinkage, + ConstantInt::get(T_size, jltls_offset_idx), + "jl_tls_offset_idx")); #endif Constant *feature_string = ConstantDataArray::getString(jl_LLVMContext, jl_options.cpu_target); diff --git a/src/jitlayers.h b/src/jitlayers.h index 02a38275d6218..73817ef527f71 100644 --- a/src/jitlayers.h +++ b/src/jitlayers.h @@ -55,6 +55,7 @@ extern Function *juliapersonality_func; #ifdef JULIA_ENABLE_THREADING extern size_t jltls_states_func_idx; +extern size_t jltls_offset_idx; #endif typedef struct {Value *gv; int32_t index;} jl_value_llvm; // uses 1-based indexing @@ -66,7 +67,7 @@ void addOptimizationPasses(PassManager *PM); #endif void* jl_emit_and_add_to_shadow(GlobalVariable *gv, void *gvarinit = NULL); GlobalVariable *jl_emit_sysimg_slot(Module *m, Type *typ, const char *name, - uintptr_t init, size_t &idx); + uintptr_t init, size_t &idx); void* jl_get_global(GlobalVariable *gv); GlobalVariable *jl_get_global_for(const char *cname, void *addr, Module *M); void jl_add_to_shadow(Module *m); diff --git a/src/julia_internal.h b/src/julia_internal.h index 7ae0d3391c195..31a5b1146d4db 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -516,6 +516,7 @@ void _julia_init(JL_IMAGE_SEARCH rel); void jl_set_base_ctx(char *__stk); extern ssize_t jl_tls_offset; +extern const int jl_tls_elf_support; void jl_init_threading(void); void jl_start_threads(void); void jl_shutdown_threading(void); diff --git a/src/llvm-ptls.cpp b/src/llvm-ptls.cpp index 750ed613c707d..d5af0f7505f70 100644 --- a/src/llvm-ptls.cpp +++ b/src/llvm-ptls.cpp @@ -24,6 +24,7 @@ #if JL_LLVM_VERSION >= 30700 && defined(JULIA_ENABLE_THREADING) # include +# include #endif #include "fix_llvm_assert.h" @@ -74,6 +75,84 @@ static void ensure_global(const char *name, Type *t, Module &M, #endif // _OS_WINDOWS_ } +#ifdef JULIA_ENABLE_THREADING +static void setCallPtlsAttrs(CallInst *ptlsStates) +{ +#if JL_LLVM_VERSION >= 50000 + ptlsStates->addAttribute(AttributeList::FunctionIndex, Attribute::ReadNone); + ptlsStates->addAttribute(AttributeList::FunctionIndex, Attribute::NoUnwind); +#else + ptlsStates->addAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone); + ptlsStates->addAttribute(AttributeSet::FunctionIndex, Attribute::NoUnwind); +#endif +} + +#if JL_LLVM_VERSION >= 30700 +static Instruction *emit_ptls_tp(LLVMContext &ctx, Value *offset, Type *T_ppjlvalue, + Instruction *insertBefore) +{ + auto T_int8 = Type::getInt8Ty(ctx); + auto T_pint8 = PointerType::get(T_int8, 0); +# if defined(_CPU_X86_64_) || defined(_CPU_X86_) + // Workaround LLVM bug by hiding the offset computation + // (and therefore the optimization opportunity) from LLVM. + // Ref https://github.com/JuliaLang/julia/issues/17288 + static const std::string const_asm_str = [&] () { + std::stringstream stm; +# if defined(_CPU_X86_64_) + stm << "movq %fs:0, $0;\naddq $$" << jl_tls_offset << ", $0"; +# else + stm << "movl %gs:0, $0;\naddl $$" << jl_tls_offset << ", $0"; +# endif + return stm.str(); + }(); +# if defined(_CPU_X86_64_) + const char *dyn_asm_str = "movq %fs:0, $0;\naddq $1, $0"; +# else + const char *dyn_asm_str = "movl %gs:0, $0;\naddl $1, $0"; +# endif + + // The add instruction clobbers flags + Value *tls; + if (offset) { + std::vector args(0); + args.push_back(offset->getType()); + auto tp = InlineAsm::get(FunctionType::get(T_pint8, args, false), + dyn_asm_str, "=&r,r,~{dirflag},~{fpsr},~{flags}", false); + tls = CallInst::Create(tp, offset, "ptls_i8", insertBefore); + } + else { + auto tp = InlineAsm::get(FunctionType::get(T_pint8, false), + const_asm_str.c_str(), "=r,~{dirflag},~{fpsr},~{flags}", false); + tls = CallInst::Create(tp, "ptls_i8", insertBefore); + } + return new BitCastInst(tls, PointerType::get(T_ppjlvalue, 0), "ptls", insertBefore); +# elif defined(_CPU_AARCH64_) + // AArch64 doesn't seem to have this issue. + // (Possibly because there are many more registers and the offset is + // positive and small) + // It's also harder to emit the offset in a generic way on AArch64 + // (need to generate one or two `add` with shift) so let llvm emit + // the add for now. + const char *asm_str = "mrs $0, tpidr_el0"; + if (!offset) { + auto T_size = (sizeof(size_t) == 8 ? Type::getInt64Ty(ctx) : Type::getInt32Ty(ctx)); + offset = ConstantInt::getSigned(T_size, jl_tls_offset); + } + auto tp = InlineAsm::get(FunctionType::get(T_pint8, false), asm_str, "=r", false); + Value *tls = CallInst::Create(tp, "thread_ptr", insertBefore); + tls = GetElementPtrInst::Create(T_int8, tls, {offset}, "ptls_i8", insertBefore); + return new BitCastInst(tls, PointerType::get(T_ppjlvalue, 0), "ptls", insertBefore); +# else + (void)T_pint8; + assert(0 && "Cannot emit thread pointer for this architecture."); + return nullptr; +# endif +} +#endif + +#endif + void LowerPTLS::runOnFunction(LLVMContext &ctx, Module &M, Function *F, Function *ptls_getter, Type *T_ppjlvalue, MDNode *tbaa_const) { @@ -99,85 +178,53 @@ void LowerPTLS::runOnFunction(LLVMContext &ctx, Module &M, Function *F, if (imaging_mode) { GlobalVariable *GV = cast( M.getNamedValue("jl_get_ptls_states.ptr")); - LoadInst *getter = new LoadInst(GV, "", ptlsStates); +#if JL_LLVM_VERSION >= 30700 + if (jl_tls_elf_support) { + GlobalVariable *OffsetGV = cast( + M.getNamedValue("jl_tls_offset.val")); + // if (offset != 0) + // ptls = tp + offset; + // else + // ptls = getter(); + auto offset = new LoadInst(OffsetGV, "", ptlsStates); + offset->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_const); + auto cmp = new ICmpInst(ptlsStates, CmpInst::ICMP_NE, offset, + Constant::getNullValue(offset->getType())); + MDBuilder MDB(ctx); + SmallVector Weights{9, 1}; + TerminatorInst *fastTerm; + TerminatorInst *slowTerm; + SplitBlockAndInsertIfThenElse(cmp, ptlsStates, &fastTerm, &slowTerm, + MDB.createBranchWeights(Weights)); + + auto fastTLS = emit_ptls_tp(ctx, offset, T_ppjlvalue, fastTerm); + auto phi = PHINode::Create(PointerType::get(T_ppjlvalue, 0), 2, "", ptlsStates); + ptlsStates->replaceAllUsesWith(phi); + ptlsStates->moveBefore(slowTerm); + auto getter = new LoadInst(GV, "", ptlsStates); + getter->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_const); + ptlsStates->setCalledFunction(getter); + setCallPtlsAttrs(ptlsStates); + + phi->addIncoming(fastTLS, fastTLS->getParent()); + phi->addIncoming(ptlsStates, ptlsStates->getParent()); + + return; + } +#endif + auto getter = new LoadInst(GV, "", ptlsStates); getter->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_const); ptlsStates->setCalledFunction(getter); -#if JL_LLVM_VERSION >= 50000 - ptlsStates->addAttribute(AttributeList::FunctionIndex, - Attribute::ReadNone); - ptlsStates->addAttribute(AttributeList::FunctionIndex, - Attribute::NoUnwind); -#else - ptlsStates->addAttribute(AttributeSet::FunctionIndex, - Attribute::ReadNone); - ptlsStates->addAttribute(AttributeSet::FunctionIndex, - Attribute::NoUnwind); -#endif + setCallPtlsAttrs(ptlsStates); } #if JL_LLVM_VERSION >= 30700 else if (jl_tls_offset != -1) { - auto T_int8 = Type::getInt8Ty(ctx); - auto T_pint8 = PointerType::get(T_int8, 0); - // Replace the function call with inline assembly if we know - // how to generate it. -# if defined(_CPU_X86_64_) || defined(_CPU_X86_) - // Workaround LLVM bug by hiding the offset computation - // (and therefore the optimization opportunity) from LLVM. - static const std::string asm_str = [&] () { - std::stringstream stm; -# if defined(_CPU_X86_64_) - stm << "movq %fs:0, $0;\naddq $$" << jl_tls_offset << ", $0"; -# else - stm << "movl %gs:0, $0;\naddl $$" << jl_tls_offset << ", $0"; -# endif - return stm.str(); - }(); - // The add instruction clobbers flags - auto tp = InlineAsm::get(FunctionType::get(T_pint8, false), - asm_str.c_str(), - "=r,~{dirflag},~{fpsr},~{flags}", false); - Value *tls = CallInst::Create(tp, "ptls_i8", ptlsStates); - tls = new BitCastInst(tls, PointerType::get(T_ppjlvalue, 0), - "ptls", ptlsStates); -# elif defined(_CPU_AARCH64_) - // AArch64 doesn't seem to have this issue. - // (Possibly because there are many more registers and the offset is - // positive and small) - // It's also harder to emit the offset in a generic way on AArch64 - // (need to generate one or two `add` with shift) so let llvm emit - // the add for now. - auto T_size = (sizeof(size_t) == 8 ? Type::getInt64Ty(ctx) : - Type::getInt32Ty(ctx)); - const char *asm_str = "mrs $0, tpidr_el0"; - auto offset = ConstantInt::getSigned(T_size, jl_tls_offset); - auto tp = InlineAsm::get(FunctionType::get(T_pint8, false), - asm_str, "=r", false); - Value *tls = CallInst::Create(tp, "thread_ptr", ptlsStates); - tls = GetElementPtrInst::Create(T_int8, tls, {offset}, - "ptls_i8", ptlsStates); - tls = new BitCastInst(tls, PointerType::get(T_ppjlvalue, 0), - "ptls", ptlsStates); -# else - Value *tls = nullptr; - assert(0 && "Cannot emit thread pointer for this architecture."); -# endif - (void)T_pint8; - ptlsStates->replaceAllUsesWith(tls); + ptlsStates->replaceAllUsesWith(emit_ptls_tp(ctx, nullptr, T_ppjlvalue, ptlsStates)); ptlsStates->eraseFromParent(); } #endif else { -#if JL_LLVM_VERSION >= 50000 - ptlsStates->addAttribute(AttributeList::FunctionIndex, - Attribute::ReadNone); - ptlsStates->addAttribute(AttributeList::FunctionIndex, - Attribute::NoUnwind); -#else - ptlsStates->addAttribute(AttributeSet::FunctionIndex, - Attribute::ReadNone); - ptlsStates->addAttribute(AttributeSet::FunctionIndex, - Attribute::NoUnwind); -#endif + setCallPtlsAttrs(ptlsStates); } #else ptlsStates->replaceAllUsesWith(M.getNamedValue("jl_tls_states")); @@ -197,8 +244,11 @@ bool LowerPTLS::runOnModule(Module &M) auto T_ppjlvalue = cast(functype->getReturnType())->getElementType(); #ifdef JULIA_ENABLE_THREADING - if (imaging_mode) + if (imaging_mode) { ensure_global("jl_get_ptls_states.ptr", functype->getPointerTo(), M); + ensure_global("jl_tls_offset.val", + sizeof(size_t) == 8 ? Type::getInt64Ty(ctx) : Type::getInt32Ty(ctx), M); + } #else ensure_global("jl_tls_states", T_ppjlvalue, M, imaging_mode); #endif diff --git a/src/threading.c b/src/threading.c index 6792c10acf0b5..15382e572a02d 100644 --- a/src/threading.c +++ b/src/threading.c @@ -453,6 +453,7 @@ void ti_reset_timings(void); ssize_t jl_tls_offset = -1; #ifdef JL_ELF_TLS_VARIANT +const int jl_tls_elf_support = 1; // Optimize TLS access in codegen if the TLS buffer is using a IE or LE model. // To detect such case, we find the size of the TLS segment in the main // executable and the TIB pointer and then see if the TLS pointer on the @@ -540,6 +541,8 @@ static void jl_check_tls(void) return; jl_tls_offset = offset; } +#else +const int jl_tls_elf_support = 0; #endif // interface to Julia; sets up to make the runtime thread-safe From f4625de2dd52844ee610af8a5faa365bba80b4d7 Mon Sep 17 00:00:00 2001 From: Mus M Date: Wed, 10 May 2017 22:23:08 -0400 Subject: [PATCH 0707/1534] Whitespace and where fix for rational.jl (#21778) --- base/rational.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/base/rational.jl b/base/rational.jl index a64c26a3aba98..611d7ca5e3252 100644 --- a/base/rational.jl +++ b/base/rational.jl @@ -32,9 +32,9 @@ julia> (3 // 5) // (2 // 1) 3//10 ``` """ -//(n::Integer, d::Integer ) = Rational(n,d) +//(n::Integer, d::Integer) = Rational(n,d) -function //(x::Rational, y::Integer ) +function //(x::Rational, y::Integer) xn,yn = divgcd(x.num,y) xn//checked_mul(x.den,yn) end @@ -430,4 +430,4 @@ function lerpi(j::Integer, d::Integer, a::Rational, b::Rational) ((d-j)*a)/d + (j*b)/d end -float{T<:Integer}(::Type{Rational{T}}) = float(T) +float(::Type{Rational{T}}) where {T<:Integer} = float(T) From b0a283140974dbe95f48d40d7b33998a35c35405 Mon Sep 17 00:00:00 2001 From: Mus M Date: Wed, 10 May 2017 23:43:16 -0400 Subject: [PATCH 0708/1534] Use where syntax in Enums.jl --- base/Enums.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/base/Enums.jl b/base/Enums.jl index 5d00f78baa1f7..9e8a144da1e58 100644 --- a/base/Enums.jl +++ b/base/Enums.jl @@ -9,10 +9,10 @@ function basetype end abstract type Enum{T<:Integer} end -Base.convert{T<:Integer}(::Type{Integer}, x::Enum{T}) = bitcast(T, x) -Base.convert{T<:Integer,T2<:Integer}(::Type{T}, x::Enum{T2}) = convert(T, bitcast(T2, x)) -Base.write{T<:Integer}(io::IO, x::Enum{T}) = write(io, T(x)) -Base.read{T<:Enum}(io::IO, ::Type{T}) = T(read(io, Enums.basetype(T))) +Base.convert(::Type{Integer}, x::Enum{T}) where {T<:Integer} = bitcast(T, x) +Base.convert(::Type{T}, x::Enum{T2}) where {T<:Integer,T2<:Integer} = convert(T, bitcast(T2, x)) +Base.write(io::IO, x::Enum{T}) where {T<:Integer} = write(io, T(x)) +Base.read(io::IO, ::Type{T}) where {T<:Enum} = T(read(io, Enums.basetype(T))) # generate code to test whether expr is in the given set of values function membershiptest(expr, values) From 66e494dd465538dfede8e04659b453e6ce23b4d1 Mon Sep 17 00:00:00 2001 From: Mus M Date: Wed, 10 May 2017 23:56:58 -0400 Subject: [PATCH 0709/1534] Use where syntax for associative.jl --- base/associative.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/associative.jl b/base/associative.jl index 8c276ee8dc078..74f3fdd47a9f4 100644 --- a/base/associative.jl +++ b/base/associative.jl @@ -32,7 +32,7 @@ struct ValueIterator{T<:Associative} dict::T end -summary{T<:Union{KeyIterator,ValueIterator}}(iter::T) = +summary(iter::T) where {T<:Union{KeyIterator,ValueIterator}} = string(T.name, " for a ", summary(iter.dict)) show(io::IO, iter::Union{KeyIterator,ValueIterator}) = show(io, collect(iter)) From 9694de7579df0ebcf74de4acaaea61c473fe0e86 Mon Sep 17 00:00:00 2001 From: Amit Murthy Date: Thu, 11 May 2017 17:04:23 +0530 Subject: [PATCH 0710/1534] Optimize remotecall pattern used in distributed loading (#21745) * Optimize remotecall pattern used in distributed loading --- base/loading.jl | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/base/loading.jl b/base/loading.jl index 5491b120d95e7..2674b3dfd27f1 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -172,19 +172,25 @@ function _require_from_serialized(node::Int, mod::Symbol, path_to_try::String, t end restored = _include_from_serialized(content) isa(restored, Exception) && return restored - others = filter(x -> x != myid(), procs()) - refs = Any[ - (p, @spawnat(p, - let m = try - _include_from_serialized(content) - catch ex - isa(ex, Exception) ? ex : ErrorException(string(ex)) + + results = sizehint!(Vector{Tuple{Int,Any}}(), nprocs()) + @sync for p in procs() + if p != myid() + @async begin + result = remotecall_fetch(p) do + let m = try + _include_from_serialized(content) + catch ex + isa(ex, Exception) ? ex : ErrorException(string(ex)) + end + isa(m, Exception) ? m : nothing end - isa(m, Exception) ? m : nothing - end)) - for p in others ] - for (id, ref) in refs - m = fetch(ref) + end + push!(results, (p, result)) + end + end + end + for (id, m) in results if m !== nothing warn("Node state is inconsistent: node $id failed to load cache from $path_to_try. Got:") warn(m, prefix="WARNING: ") @@ -460,8 +466,13 @@ function _require(mod::Symbol) eval(Main, :(Base.include_from_node1($path))) # broadcast top-level import/using from node 1 (only) - refs = Any[ @spawnat p eval(Main, :(Base.include_from_node1($path))) for p in filter(x -> x != 1, procs()) ] - for r in refs; wait(r); end + @sync begin + for p in filter(x -> x != 1, procs()) + @async remotecall_fetch(p) do + eval(Main, :(Base.include_from_node1($path); nothing)) + end + end + end else eval(Main, :(Base.include_from_node1($path))) end From 64daacead00ea7de9374f9092b3d18e27986f2b2 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Wed, 10 May 2017 23:11:50 -0400 Subject: [PATCH 0711/1534] Implement TLS access optimization on ARMv7 --- src/llvm-ptls.cpp | 10 +++++++--- src/threading.c | 15 ++++++++++++--- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/llvm-ptls.cpp b/src/llvm-ptls.cpp index d5af0f7505f70..b8b6584c09a0e 100644 --- a/src/llvm-ptls.cpp +++ b/src/llvm-ptls.cpp @@ -127,14 +127,18 @@ static Instruction *emit_ptls_tp(LLVMContext &ctx, Value *offset, Type *T_ppjlva tls = CallInst::Create(tp, "ptls_i8", insertBefore); } return new BitCastInst(tls, PointerType::get(T_ppjlvalue, 0), "ptls", insertBefore); -# elif defined(_CPU_AARCH64_) - // AArch64 doesn't seem to have this issue. +# elif defined(_CPU_AARCH64_) || (defined(__ARM_ARCH) && __ARM_ARCH >= 7) + // AArch64/ARM doesn't seem to have this issue. // (Possibly because there are many more registers and the offset is // positive and small) - // It's also harder to emit the offset in a generic way on AArch64 + // It's also harder to emit the offset in a generic way on ARM/AArch64 // (need to generate one or two `add` with shift) so let llvm emit // the add for now. +#if defined(_CPU_AARCH64_) const char *asm_str = "mrs $0, tpidr_el0"; +#else + const char *asm_str = "mrc p15, 0, $0, c13, c0, 3"; +#endif if (!offset) { auto T_size = (sizeof(size_t) == 8 ? Type::getInt64Ty(ctx) : Type::getInt32Ty(ctx)); offset = ConstantInt::getSigned(T_size, jl_tls_offset); diff --git a/src/threading.c b/src/threading.c index 15382e572a02d..369f7a45507de 100644 --- a/src/threading.c +++ b/src/threading.c @@ -22,6 +22,9 @@ #include "julia.h" #include "julia_internal.h" +// Ref https://www.uclibc.org/docs/tls.pdf +// For variant 1 JL_ELF_TLS_INIT_SIZE is the size of the thread control block (TCB) +// For variant 2 JL_ELF_TLS_INIT_SIZE is 0 #ifdef _OS_LINUX_ # if defined(_CPU_X86_64_) || defined(_CPU_X86_) # define JL_ELF_TLS_VARIANT 2 @@ -31,6 +34,10 @@ # define JL_ELF_TLS_VARIANT 1 # define JL_ELF_TLS_INIT_SIZE 16 # endif +# if defined(__ARM_ARCH) && __ARM_ARCH >= 7 +# define JL_ELF_TLS_VARIANT 1 +# define JL_ELF_TLS_INIT_SIZE 8 +# endif #endif #ifdef JL_ELF_TLS_VARIANT @@ -456,13 +463,13 @@ ssize_t jl_tls_offset = -1; const int jl_tls_elf_support = 1; // Optimize TLS access in codegen if the TLS buffer is using a IE or LE model. // To detect such case, we find the size of the TLS segment in the main -// executable and the TIB pointer and then see if the TLS pointer on the +// executable and the thread pointer (TP) and then see if the TLS pointer on the // current thread is in the right range. // This can in principle be extended to the case where the TLS buffer is // in the shared library but is part of the static buffer but that seems harder // to detect. # if JL_ELF_TLS_VARIANT == 1 -// In Variant 1, the static TLS buffer comes after a fixed size TIB. +// In Variant 1, the static TLS buffer comes after a fixed size TCB. // The alignment needs to be applied to the original size. static inline size_t jl_add_tls_size(size_t orig_size, size_t size, size_t align) { @@ -477,7 +484,7 @@ static inline ssize_t jl_check_tls_bound(void *tp, void *ptls, size_t tls_size) return offset; } # elif JL_ELF_TLS_VARIANT == 2 -// In Variant 2, the static TLS buffer comes before a unknown size TIB. +// In Variant 2, the static TLS buffer comes before a unknown size TCB. // The alignment needs to be applied to the new size. static inline size_t jl_add_tls_size(size_t orig_size, size_t size, size_t align) { @@ -533,6 +540,8 @@ static void jl_check_tls(void) asm("movl %%gs:0, %0" : "=r"(tp)); #elif defined(_CPU_AARCH64_) asm("mrs %0, tpidr_el0" : "=r"(tp)); +#elif defined(__ARM_ARCH) && __ARM_ARCH >= 7 + asm("mrc p15, 0, %0, c13, c0, 3" : "=r"(tp)); #else # error "Cannot emit thread pointer for this architecture." #endif From 1129de34c72d3fcf5155f3693cfd39ecb5db5870 Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Thu, 11 May 2017 08:07:54 -0700 Subject: [PATCH 0712/1534] Fix stack overflow in SSHCredentials constructor (#21779) --- base/libgit2/types.jl | 2 +- test/libgit2.jl | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/base/libgit2/types.jl b/base/libgit2/types.jl index 19fdc67f7d720..89cb7e16a34ef 100644 --- a/base/libgit2/types.jl +++ b/base/libgit2/types.jl @@ -699,7 +699,7 @@ mutable struct SSHCredentials <: AbstractCredentials finalizer(c, securezero!) return c end - SSHCredentials(u::AbstractString,p::AbstractString,prompt_if_incorrect::Bool=false) = SSHCredentials(u,p,prompt_if_incorrect) + SSHCredentials(u::AbstractString,p::AbstractString,prompt_if_incorrect::Bool=false) = SSHCredentials(u,p,"","",prompt_if_incorrect) SSHCredentials(prompt_if_incorrect::Bool=false) = SSHCredentials("","","","",prompt_if_incorrect) end diff --git a/test/libgit2.jl b/test/libgit2.jl index 26e899c72bea8..bd6c4a8144f41 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -1249,6 +1249,11 @@ mktempdir() do dir @test LibGit2.checkused!(creds) @test creds.user == creds_user @test creds.pass == creds_pass + sshcreds = LibGit2.SSHCredentials(creds_user, creds_pass) + @test sshcreds.user == creds_user + @test sshcreds.pass == creds_pass + @test isempty(sshcreds.prvkey) + @test isempty(sshcreds.pubkey) end # The following tests require that we can fake a TTY so that we can provide passwords From 3675ce15056858aaa18f41acca6c8d8d996c0ecc Mon Sep 17 00:00:00 2001 From: Mus M Date: Thu, 11 May 2017 12:24:27 -0400 Subject: [PATCH 0713/1534] Use where syntax in trig.jl --- base/special/trig.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/base/special/trig.jl b/base/special/trig.jl index e7c342a9e342c..4b6039da0ff69 100644 --- a/base/special/trig.jl +++ b/base/special/trig.jl @@ -292,7 +292,7 @@ Compute ``\\sin(\\pi x) / (\\pi x)`` if ``x \\neq 0``, and ``1`` if ``x = 0``. """ sinc(x::Number) = x==0 ? one(x) : oftype(x,sinpi(x)/(pi*x)) sinc(x::Integer) = x==0 ? one(x) : zero(x) -sinc(x::Complex{T}) where {T<:Integer} = sinc(float(x)) +sinc(x::Complex{<:Integer}) = sinc(float(x)) sinc(x::Real) = x==0 ? one(x) : isinf(x) ? zero(x) : sinpi(x)/(pi*x) """ @@ -303,14 +303,14 @@ Compute ``\\cos(\\pi x) / x - \\sin(\\pi x) / (\\pi x^2)`` if ``x \\neq 0``, and """ cosc(x::Number) = x==0 ? zero(x) : oftype(x,(cospi(x)-sinpi(x)/(pi*x))/x) cosc(x::Integer) = cosc(float(x)) -cosc(x::Complex{T}) where {T<:Integer} = cosc(float(x)) +cosc(x::Complex{<:Integer}) = cosc(float(x)) cosc(x::Real) = x==0 || isinf(x) ? zero(x) : (cospi(x)-sinpi(x)/(pi*x))/x for (finv, f) in ((:sec, :cos), (:csc, :sin), (:cot, :tan), (:sech, :cosh), (:csch, :sinh), (:coth, :tanh), (:secd, :cosd), (:cscd, :sind), (:cotd, :tand)) @eval begin - ($finv){T<:Number}(z::T) = one(T) / (($f)(z)) + ($finv)(z::T) where {T<:Number} = one(T) / (($f)(z)) end end From 116741d68fac3c86699bdb79dbf6ad2b2d2f55ce Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Thu, 11 May 2017 14:24:13 -0700 Subject: [PATCH 0714/1534] Rearchitect this file for the second time, it's much more precise now --- contrib/fixup-libgfortran.sh | 93 +++++++++++++++++++++--------------- 1 file changed, 55 insertions(+), 38 deletions(-) diff --git a/contrib/fixup-libgfortran.sh b/contrib/fixup-libgfortran.sh index 9549d08d6b430..9c7f078031a16 100755 --- a/contrib/fixup-libgfortran.sh +++ b/contrib/fixup-libgfortran.sh @@ -1,7 +1,15 @@ #!/bin/sh # This file is a part of Julia. License is MIT: https://julialang.org/license -# Run as: fixup-libgfortran.sh <$private_libdir> +# Run as: fixup-libgfortran.sh [--verbose] <$private_libdir> + +# If we're invoked with "--verbose", create a `debug` function that prints stuff out +if [ "$1" == "--verbose" ] || [ "$1" == "-v" ]; then +shift 1 +debug() { echo "$*"; } +else +debug() { :; } +fi if [ -z "$1" ]; then echo "Usage: $0 " @@ -14,7 +22,7 @@ if [ "$UNAME" = "Linux" ]; then elif [ "$UNAME" = "Darwin" ]; then SHLIB_EXT="dylib" else - echo "WARNING: Could not autodetect platform type ('uname -s' == $UNAME); assuming Linux" + echo "WARNING: Could not autodetect platform type ('uname -s' == $UNAME); assuming Linux" >&2 UNAME="Linux" SHLIB_EXT="so" fi @@ -26,27 +34,34 @@ if [ ! -f "$private_libdir/libarpack.$SHLIB_EXT" ]; then exit 2 fi -find_shlib () +find_shlib() { - if [ -f "$private_libdir/lib$1.$SHLIB_EXT" ]; then + lib_path="$1" + if [ -f "$lib_path" ]; then if [ "$UNAME" = "Linux" ]; then - ldd "$private_libdir/lib$1.$SHLIB_EXT" | grep $2 | cut -d' ' -f3 | xargs + ldd "$lib_path" | grep $2 | cut -d' ' -f3 | xargs else # $UNAME is "Darwin", we only have two options, see above - otool -L "$private_libdir/lib$1.$SHLIB_EXT" | grep $2 | cut -d' ' -f1 | xargs + otool -L "$lib_path" | grep $2 | cut -d' ' -f1 | xargs fi fi } +private_libname() +{ + echo "$private_libdir/lib$1.$SHLIB_EXT" +} + # First, discover all the places where libgfortran/libgcc is, as well as their true SONAMES for lib in arpack openspecfun lapack; do if [ -f "$private_libdir/lib$lib.$SHLIB_EXT" ]; then # Find the paths to the libraries we're interested in. These are almost # always within the same directory, but we like to be general. - LIBGFORTRAN_PATH=$(find_shlib $lib libgfortran) - LIBGCC_PATH=$(find_shlib $lib libgcc_s) - LIBQUADMATH_PATH=$(find_shlib $lib libquadmath) + LIBGFORTRAN_PATH=$(find_shlib "$(private_libname $lib)" libgfortran) + LIBGCC_PATH=$(find_shlib "$(private_libname $lib)" libgcc_s) + LIBQUADMATH_PATH=$(find_shlib "$(private_libname $lib)" libquadmath) - # Take the directories, add them onto LIBGFORTRAN_DIRS to search for things later + # Take the directories, add them onto LIBGFORTRAN_DIRS, which we use to + # search for these libraries with in the future. LIBGFORTRAN_DIRS="$LIBGFORTRAN_DIRS $(dirname $LIBGFORTRAN_PATH)" LIBGFORTRAN_DIRS="$LIBGFORTRAN_DIRS $(dirname $LIBGCC_PATH)" LIBGFORTRAN_DIRS="$LIBGFORTRAN_DIRS $(dirname $LIBQUADMATH_PATH)" @@ -66,6 +81,8 @@ uniquify() LIBGFORTRAN_DIRS=$(uniquify "$LIBGFORTRAN_DIRS") SONAMES="$(uniquify "$LIBGFORTRAN_SONAMES $LIBGCC_SONAMES $LIBQUADMATH_SONAMES")" +debug "Discovered traces of libgfortran within $LIBGFORTRAN_DIRS" +debug "Got SONAMES of $SONAMES" # Copy the SONAMEs we identified above into our private_libdir for soname in $SONAMES; do @@ -78,48 +95,48 @@ for soname in $SONAMES; do fi fi done - - # Add possible internal directories to LIBGFORTRAN_DIRS so that we can find all possible ways - # That any of our libraries or these libraries we just copied in link to themselves later. - if [ -f "$private_libdir/$soname" ]; then - LIBGFORTRAN_DIRS="$LIBGFORTRAN_DIRS $(dirname $(find_shlib $lib libgfortran))" - LIBGFORTRAN_DIRS="$LIBGFORTRAN_DIRS $(dirname $(find_shlib $lib libgcc_s))" - LIBGFORTRAN_DIRS="$LIBGFORTRAN_DIRS $(dirname $(find_shlib $lib libquadmath))" - fi done - +# On OSX, we need to change the old link (which is usually a full path) +# to point to `@rpath/${soname}` explicitly, so we use `find_shlib()` +# to dynamically find the full path we want to change. On Linux, we +# don't care about full paths, we just set the rpath to `$ORIGIN`. change_linkage() { - shlib_path="$1" - old_link="$2" - new_link="$3" + # This is the path of the library we want to edit + lib_path="$1" + + # If it doesn't exist, exit quietly + if [ ! -f "$lib_path" ]; then + debug " $lib_path doesn't exist, skipping" + return + fi + + # This is the soname of the dependency we want to swap out + soname="$2" + if [ "$UNAME" = "Darwin" ]; then - install_name_tool -change "$old_link" "$new_link" "$shlib_path" + old_link=$(find_shlib "$lib_path" "$soname") + echo " $old_link" + install_name_tool -change "$old_link" "@rpath/$soname" "$lib_path" else # $UNAME is "Linux", we only have two options, see above - patchelf --set-rpath \$ORIGIN "$shlib_path" + patchelf --set-rpath \$ORIGIN "$lib_path" fi } -LIBGFORTRAN_DIRS=$(uniquify "$LIBGFORTRAN_DIRS") -echo "Found traces of libgfortran/libgcc in $LIBGFORTRAN_DIRS" - -# For every library that remotely touches libgfortran stuff (so the libraries -# we have copied in ourselves as well as arpack, openspecfun, etc...) we must +# For every library that remotely touches libgfortran stuff (the libraries we +# have copied in ourselves as well as arpack, openspecfun, etc...) we must # update the linkage to point to @rpath (on OSX) or $ORIGIN (on Linux) so # that direct links to the old libgfortran directories are instead directed # to the proper location, which is our $private_libdir. -cd $private_libdir - -# Iterate over possible library names -for soname in libopenblas libarpack libcholmod liblapack libopenspecfun $SONAMES; do +for lib in libopenblas libarpack libcholmod liblapack libopenspecfun $SONAMES; do # Grab every incarnation of that library that exists within $private_libdir # (e.g. "libopenspecfun.so", and "libopenspecfun.so.0", etc...) - for lib in $private_libdir/$soname*; do - # Look for links to any of the our three musketeers within ANY of the - # potential LIBGFORTRAN_DIRS we've discovered so far - for dir in $LIBGFORTRAN_DIRS; do - change_linkage "$lib" "$dir/$soname" "@rpath/$soname" + for lib_path in $private_libdir/$lib*; do + # Iterate over dependency names that need to be changed + for soname in $SONAMES; do + debug "changing linkage of $lib_path to $soname" + change_linkage "$lib_path" "$soname" done done done From 4c549350df8467a59f49b8e64f82fb34de86c4a6 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 11 May 2017 10:40:59 -0400 Subject: [PATCH 0715/1534] fix #21793, regression in serializing nested closure --- base/serialize.jl | 3 ++- test/serialize.jl | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/base/serialize.jl b/base/serialize.jl index 4b309489226c9..d453e9e0a33f9 100644 --- a/base/serialize.jl +++ b/base/serialize.jl @@ -703,7 +703,8 @@ function handle_deserialize(s::AbstractSerializer, b::Int32) return GlobalRef(deserialize(s)::Module, deserialize(s)::Symbol) elseif b == FULL_GLOBALREF_TAG ty = deserialize(s) - return GlobalRef(ty.name.module, ty.name.name) + tn = unwrap_unionall(ty).name + return GlobalRef(tn.module, tn.name) elseif b == LONGTUPLE_TAG return deserialize_tuple(s, Int(read(s.io, Int32)::Int32)) elseif b == LONGEXPR_TAG diff --git a/test/serialize.jl b/test/serialize.jl index 8be0c8f0d0a35..b136ad7b40425 100644 --- a/test/serialize.jl +++ b/test/serialize.jl @@ -300,6 +300,15 @@ main_ex = quote $Test.@test g2() == :magic_token_anon_fun_test $Test.@test g2() == :magic_token_anon_fun_test $Test.@test deserialize(ds) === g2 + + # issue #21793 + y = x -> (() -> x) + seekstart(s) + serialize(s, y) + seekstart(s) + y2 = deserialize(s) + x2 = y2(2) + $Test.@test x2() == 2 end end # This needs to be run on `Main` since the serializer treats it differently. From 3b4d238f0255dcfa24b1ea31b61b314cd778dd02 Mon Sep 17 00:00:00 2001 From: Mus M Date: Fri, 12 May 2017 12:53:37 -0400 Subject: [PATCH 0716/1534] Use where syntax in bitarray.jl (#21790) * Use where in bitarray.jl * Use sugar form in BitArray constructor --- base/bitarray.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/base/bitarray.jl b/base/bitarray.jl index 012f413ee4ca9..23602c25634fe 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -80,7 +80,7 @@ const _msk64 = ~UInt64(0) @inline _msk_end(B::BitArray) = _msk_end(length(B)) num_bit_chunks(n::Int) = _div64(n+63) -function _check_bitarray_consistency{N}(B::BitArray{N}) +function _check_bitarray_consistency(B::BitArray{N}) where N n = length(B) if N ≠ 1 all(d ≥ 0 for d in B.dims) || (warn("negative d in dims: $(B.dims)"); return false) @@ -542,7 +542,7 @@ reinterpret(B::BitArray, dims::NTuple{N,Int}) where {N} = reshape(B, dims) ## Constructors from generic iterables ## -BitArray{T,N}(A::AbstractArray{T,N}) = convert(BitArray{N}, A) +BitArray(A::AbstractArray{<:Any,N}) where {N} = convert(BitArray{N}, A) """ BitArray(itr) @@ -1880,7 +1880,7 @@ end # If we were able to specialize the function to a known bitwise operation, # map across the chunks. Otherwise, fall-back to the AbstractArray method that # iterates bit-by-bit. -function bit_map!{F}(f::F, dest::BitArray, A::BitArray) +function bit_map!(f::F, dest::BitArray, A::BitArray) where F size(A) == size(dest) || throw(DimensionMismatch("sizes of dest and A must match")) isempty(A) && return dest destc = dest.chunks @@ -1891,7 +1891,7 @@ function bit_map!{F}(f::F, dest::BitArray, A::BitArray) destc[end] = f(Ac[end]) & _msk_end(A) dest end -function bit_map!{F}(f::F, dest::BitArray, A::BitArray, B::BitArray) +function bit_map!(f::F, dest::BitArray, A::BitArray, B::BitArray) where F size(A) == size(B) == size(dest) || throw(DimensionMismatch("sizes of dest, A, and B must all match")) isempty(A) && return dest destc = dest.chunks From 65757ba6d9ecacc95f7f37231af4bc428f52a579 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Wed, 12 Apr 2017 14:58:12 +0700 Subject: [PATCH 0717/1534] deprecate srand(rng, filename::AbstractString) `srand` should accept a seed as second argument; here `filename` is only an indirect seed, preventing the use a string object as a direct seed. --- NEWS.md | 31 +++++++++++++++++++++++++++++++ base/deprecated.jl | 6 ++++++ base/random.jl | 19 ++++--------------- test/random.jl | 3 --- 4 files changed, 41 insertions(+), 18 deletions(-) diff --git a/NEWS.md b/NEWS.md index 9029abc7acc99..21dd1ccb602c3 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,34 @@ +Julia v0.7.0 Release Notes +========================== + +New language features +--------------------- + + +Language changes +---------------- + + +Breaking changes +---------------- + +This section lists changes that do not have deprecation warnings. + + +Library improvements +-------------------- + + +Compiler/Runtime improvements +----------------------------- + + +Deprecated or removed +--------------------- + + * The method `srand(rng, filename, n=4)` has been deprecated ([#21359]). + + Julia v0.6.0 Release Notes ========================== diff --git a/base/deprecated.jl b/base/deprecated.jl index d8da299e17eed..cedc68e0e2a92 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1336,6 +1336,12 @@ next(p::Union{Process, ProcessChain}, i::Int) = (getindex(p, i), i + 1) end @deprecate cond(F::LinAlg.LU, p::Integer) cond(full(F), p) + +# PR #21359 +@deprecate srand(r::MersenneTwister, filename::AbstractString, n::Integer=4) srand(r, read!(filename, Array{UInt32}(Int(n)))) +@deprecate srand(filename::AbstractString, n::Integer=4) srand(read!(filename, Array{UInt32}(Int(n)))) +@deprecate MersenneTwister(filename::AbstractString) srand(MersenneTwister(0), read!(filename, Array{UInt32}(Int(4)))) + # END 0.7 deprecations # BEGIN 1.0 deprecations diff --git a/base/random.jl b/base/random.jl index d1c99e953c8be..6383f2c599269 100644 --- a/base/random.jl +++ b/base/random.jl @@ -213,25 +213,19 @@ function make_seed(n::Integer) end end -function make_seed(filename::AbstractString, n::Integer) - read!(filename, Vector{UInt32}(Int(n))) -end - ## srand() """ - srand([rng=GLOBAL_RNG], [seed]) -> rng - srand([rng=GLOBAL_RNG], filename, n=4) -> rng + srand([rng=GLOBAL_RNG], seed) -> rng + srand([rng=GLOBAL_RNG]) -> rng Reseed the random number generator. If a `seed` is provided, the RNG will give a reproducible sequence of numbers, otherwise Julia will get entropy from the system. For -`MersenneTwister`, the `seed` may be a non-negative integer, a vector of `UInt32` integers -or a filename, in which case the seed is read from a file (`4n` bytes are read from the file, -where `n` is an optional argument). `RandomDevice` does not support seeding. +`MersenneTwister`, the `seed` may be a non-negative integer or a vector of `UInt32` integers. +`RandomDevice` does not support seeding. """ srand(r::MersenneTwister) = srand(r, make_seed()) srand(r::MersenneTwister, n::Integer) = srand(r, make_seed(n)) -srand(r::MersenneTwister, filename::AbstractString, n::Integer=4) = srand(r, make_seed(filename, n)) function dsfmt_gv_srand() @@ -250,11 +244,6 @@ function srand(seed::Union{Integer, Vector{UInt32}}) dsfmt_gv_srand() end -function srand(filename::AbstractString, n::Integer=4) - srand(GLOBAL_RNG, filename, n) - dsfmt_gv_srand() -end - ## Global RNG const GLOBAL_RNG = MersenneTwister(0) diff --git a/test/random.jl b/test/random.jl index 1403af94cfa19..359ecf7d26b26 100644 --- a/test/random.jl +++ b/test/random.jl @@ -485,11 +485,8 @@ let g = Base.Random.GLOBAL_RNG, @test srand() === g @test srand(rand(UInt)) === g @test srand(rand(UInt32, rand(1:10))) === g - @test srand(@__FILE__) === g - @test srand(@__FILE__, rand(1:10)) === g @test srand(m) === m @test srand(m, rand(UInt)) === m @test srand(m, rand(UInt32, rand(1:10))) === m @test srand(m, rand(1:10)) === m - @test srand(m, @__FILE__, rand(1:10)) === m end From 1da3019dc9185d318d98cf5fe22042ef4cf5f27a Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Thu, 9 Jun 2016 16:18:41 +0530 Subject: [PATCH 0718/1534] ndigits: check for invalid bases (fix #16766) --- base/gmp.jl | 6 +++--- base/intfuncs.jl | 28 ++++++++++++++++++---------- test/bigint.jl | 6 +++--- test/intfuncs.jl | 8 +++++++- 4 files changed, 31 insertions(+), 17 deletions(-) diff --git a/base/gmp.jl b/base/gmp.jl index ec85233d609ae..15ec065559de6 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -8,8 +8,8 @@ import Base: *, +, -, /, <, <<, >>, >>>, <=, ==, >, >=, ^, (~), (&), (|), xor, binomial, cmp, convert, div, divrem, factorial, fld, gcd, gcdx, lcm, mod, ndigits, promote_rule, rem, show, isqrt, string, powermod, sum, trailing_zeros, trailing_ones, count_ones, base, tryparse_internal, - bin, oct, dec, hex, isequal, invmod, prevpow2, nextpow2, ndigits0z, widen, signed, unsafe_trunc, trunc, - iszero, big, flipsign, signbit + bin, oct, dec, hex, isequal, invmod, prevpow2, nextpow2, ndigits0z, + ndigits0znb, widen, signed, unsafe_trunc, trunc, iszero, big, flipsign, signbit if Clong == Int32 const ClongMax = Union{Int8, Int16, Int32} @@ -581,6 +581,7 @@ end function ndigits0z(x::BigInt, b::Integer=10) b < 2 && throw(DomainError()) + x.size == 0 && return 0 # for consistency with other ndigits0z methods if ispow2(b) && 2 <= b <= 62 # GMP assumes b is in this range Int(ccall((:__gmpz_sizeinbase,:libgmp), Csize_t, (Ptr{BigInt}, Cint), &x, b)) else @@ -600,7 +601,6 @@ function ndigits0z(x::BigInt, b::Integer=10) end end end -ndigits(x::BigInt, b::Integer=10) = iszero(x) ? 1 : ndigits0z(x,b) # below, ONE is always left-shifted by at least one digit, so a new BigInt is # allocated, which can be safely mutated diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 91191d4048c18..3afbb74685439 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -347,8 +347,11 @@ function ndigits0z(x::UInt128) return n + ndigits0z(UInt64(x)) end ndigits0z(x::Integer) = ndigits0z(unsigned(abs(x))) +ndigits(x::Integer) = x==0 ? 1 : ndigits0z(x) -function ndigits0znb(n::Signed, b::Int) +# The suffix "nb" stands for "negative base" +function ndigits0znb(n::Integer, b::Integer) + # precondition: b < -1 && !(typeof(n) <: Unsigned) d = 0 while n != 0 n = cld(n,b) @@ -357,7 +360,10 @@ function ndigits0znb(n::Signed, b::Int) return d end +ndigits0znb(n::Unsigned, b::Integer) = ndigits0znb(signed(n), b) + function ndigits0z(n::Unsigned, b::Int) + # precondition: b > 1 b < 0 && return ndigits0znb(signed(n), b) b == 2 && return sizeof(n)<<3 - leading_zeros(n) b == 8 && return (sizeof(n)<<3 - leading_zeros(n) + 2) ÷ 3 @@ -379,20 +385,23 @@ function ndigits0z(n::Unsigned, b::Int) end return d end -ndigits0z(x::Integer, b::Integer) = ndigits0z(unsigned(abs(x)),Int(b)) - -ndigitsnb(x::Integer, b::Integer) = x==0 ? 1 : ndigits0znb(x, b) -ndigits(x::Unsigned, b::Integer) = x==0 ? 1 : ndigits0z(x,Int(b)) -ndigits(x::Unsigned) = x==0 ? 1 : ndigits0z(x) +ndigits0z(x::Integer, b::Integer) = ndigits0z(unsigned(abs(x)), Int(b)) """ ndigits(n::Integer, b::Integer=10) Compute the number of digits in integer `n` written in base `b`. """ -ndigits(x::Integer, b::Integer) = b >= 0 ? ndigits(unsigned(abs(x)),Int(b)) : ndigitsnb(x, b) -ndigits(x::Integer) = ndigits(unsigned(abs(x))) +function ndigits(x::Integer, b::Integer) + if b < -1 + x == 0 ? 1 : ndigits0znb(x, b) + elseif b > 1 + x == 0 ? 1 : ndigits0z(x, b) + else + throw(DomainError()) + end +end ## integer to string functions ## @@ -544,8 +553,7 @@ higher indexes, such that `n == sum([digits[k]*base^(k-1) for k=1:length(digits) """ digits(n::Integer, base::T=10, pad::Integer=1) where {T<:Integer} = digits(T, n, base, pad) -function digits(::Type{T}, n::Integer, base::Integer=10, pad::Integer=1) where T<:Integer - 2 <= base || throw(ArgumentError("base must be ≥ 2, got $base")) +function digits(T::Type{<:Integer}, n::Integer, base::Integer=10, pad::Integer=1) digits!(zeros(T, max(pad, ndigits0z(n,base))), n, base) end diff --git a/test/bigint.jl b/test/bigint.jl index 5a74ae37b4f90..5ebc8cfa9ef38 100644 --- a/test/bigint.jl +++ b/test/bigint.jl @@ -278,10 +278,10 @@ ndigits_mismatch(n) = ndigits(n) != ndigits(BigInt(n)) @test !any(ndigits_mismatch, 8192:9999) # The following should not crash (#16579) -ndigits(rand(big.(-999:999)), rand(63:typemax(Int))) -ndigits(rand(big.(-999:999)), big(2)^rand(2:999)) +ndigits(big(rand(Int)), rand(63:typemax(Int))) +ndigits(big(rand(Int)), big(2)^rand(2:999)) -for i in big.([-20:-1;1:20]) +for i in big.([-20:-1;1:20; rand(Int)]) for b in -10:1 @test_throws DomainError ndigits(i, b) end diff --git a/test/intfuncs.jl b/test/intfuncs.jl index 547e826480c52..c5fd6732bba66 100644 --- a/test/intfuncs.jl +++ b/test/intfuncs.jl @@ -85,8 +85,14 @@ end @test ndigits(146, -3) == 5 -let n = rand(Int) +let (n, b) = rand(Int, 2) + -1 <= b <= 1 && (b = 2) # invalid bases @test ndigits(n) == ndigits(big(n)) == ndigits(n, 10) + @test ndigits(n, b) == ndigits(big(n), b) +end + +for b in -1:1 + @test_throws DomainError ndigits(rand(Int), b) end @test ndigits(Int8(5)) == ndigits(5) From 1f969e4d4191ce908d51743c749c9598cc82ed1b Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Fri, 17 Jun 2016 19:29:39 +0530 Subject: [PATCH 0719/1534] rename ndigits0z to ndigits0zpb --- base/gmp.jl | 6 +++--- base/intfuncs.jl | 36 ++++++++++++++++++++++++++++-------- test/bigint.jl | 8 +++++--- test/intfuncs.jl | 4 ++++ 4 files changed, 40 insertions(+), 14 deletions(-) diff --git a/base/gmp.jl b/base/gmp.jl index 15ec065559de6..af0ebdc0d763c 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -8,8 +8,8 @@ import Base: *, +, -, /, <, <<, >>, >>>, <=, ==, >, >=, ^, (~), (&), (|), xor, binomial, cmp, convert, div, divrem, factorial, fld, gcd, gcdx, lcm, mod, ndigits, promote_rule, rem, show, isqrt, string, powermod, sum, trailing_zeros, trailing_ones, count_ones, base, tryparse_internal, - bin, oct, dec, hex, isequal, invmod, prevpow2, nextpow2, ndigits0z, - ndigits0znb, widen, signed, unsafe_trunc, trunc, iszero, big, flipsign, signbit + bin, oct, dec, hex, isequal, invmod, prevpow2, nextpow2, ndigits0zpb, + widen, signed, unsafe_trunc, trunc, iszero, big, flipsign, signbit if Clong == Int32 const ClongMax = Union{Int8, Int16, Int32} @@ -579,7 +579,7 @@ function base(b::Integer, n::BigInt, pad::Integer) String(buf) end -function ndigits0z(x::BigInt, b::Integer=10) +function ndigits0zpb(x::BigInt, b::Integer) b < 2 && throw(DomainError()) x.size == 0 && return 0 # for consistency with other ndigits0z methods if ispow2(b) && 2 <= b <= 62 # GMP assumes b is in this range diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 3afbb74685439..0c43446b4c031 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -333,7 +333,7 @@ const powers_of_ten = [ 0x000000e8d4a51000, 0x000009184e72a000, 0x00005af3107a4000, 0x00038d7ea4c68000, 0x002386f26fc10000, 0x016345785d8a0000, 0x0de0b6b3a7640000, 0x8ac7230489e80000, ] -function ndigits0z(x::Union{UInt8,UInt16,UInt32,UInt64}) +function ndigits0z(x::Base.BitUnsigned64) lz = (sizeof(x)<<3)-leading_zeros(x) nd = (1233*lz)>>12+1 nd -= x < powers_of_ten[nd] @@ -346,8 +346,11 @@ function ndigits0z(x::UInt128) end return n + ndigits0z(UInt64(x)) end -ndigits0z(x::Integer) = ndigits0z(unsigned(abs(x))) -ndigits(x::Integer) = x==0 ? 1 : ndigits0z(x) + +ndigits0z(x::Signed) = ndigits0z(unsigned(abs(x))) + +ndigits0z(x::Integer) = ndigits(x, false) +ndigits(x::Integer, min1::Bool=true) = x==0 ? min1%Int : ndigits0zpb(x, 10) # The suffix "nb" stands for "negative base" function ndigits0znb(n::Integer, b::Integer) @@ -362,7 +365,9 @@ end ndigits0znb(n::Unsigned, b::Integer) = ndigits0znb(signed(n), b) -function ndigits0z(n::Unsigned, b::Int) +# The suffix "pb" stands for "positive base" +# TODO: allow b::Integer +function ndigits0zpb(n::Base.BitUnsigned, b::Int) # precondition: b > 1 b < 0 && return ndigits0znb(signed(n), b) b == 2 && return sizeof(n)<<3 - leading_zeros(n) @@ -386,18 +391,33 @@ function ndigits0z(n::Unsigned, b::Int) return d end -ndigits0z(x::Integer, b::Integer) = ndigits0z(unsigned(abs(x)), Int(b)) +ndigits0zpb(x::Base.BitSigned, b::Integer) = ndigits0zpb(unsigned(abs(x)), Int(b)) +ndigits0zpb(x::Base.BitUnsigned, b::Integer) = ndigits0zpb(x, Int(b)) + +# The suffix "0z" means that the output is 0 on input zero (cf. #16841) +""" + ndigits0z(n::Integer, b::Integer=10) + +Return 0 if `n == 0`, otherwise compute the number of digits in +integer `n` written in base `b` (i.e. equal to `ndigits(n, b)` +in this case). +The base `b` must not be in `[-1, 0, 1]`. +""" +ndigits0z(x::Integer, b::Integer) = ndigits(x, b, false) """ ndigits(n::Integer, b::Integer=10) Compute the number of digits in integer `n` written in base `b`. +The base `b` must not be in `[-1, 0, 1] """ -function ndigits(x::Integer, b::Integer) +function ndigits(x::Integer, b::Integer, min1::Bool=true) + # min1: whether the minimum value of this function should be 1 + # (for the special input value 0), or not (then ndigits(0, b) == 0) if b < -1 - x == 0 ? 1 : ndigits0znb(x, b) + x == 0 ? min1%Int : ndigits0znb(x, b) elseif b > 1 - x == 0 ? 1 : ndigits0z(x, b) + x == 0 ? min1%Int : ndigits0zpb(x, b) else throw(DomainError()) end diff --git a/test/bigint.jl b/test/bigint.jl index 5ebc8cfa9ef38..0e4650d1d7d1a 100644 --- a/test/bigint.jl +++ b/test/bigint.jl @@ -281,12 +281,14 @@ ndigits_mismatch(n) = ndigits(n) != ndigits(BigInt(n)) ndigits(big(rand(Int)), rand(63:typemax(Int))) ndigits(big(rand(Int)), big(2)^rand(2:999)) -for i in big.([-20:-1;1:20; rand(Int)]) - for b in -10:1 - @test_throws DomainError ndigits(i, b) +for x in big.([-20:20; rand(Int)]) + for b in -1:1 + @test_throws DomainError ndigits(x, b) end end +@test Base.ndigits0zpb(big(0), big(rand(2:100))) == 0 + # conversion from float @test BigInt(2.0) == BigInt(2.0f0) == BigInt(big(2.0)) == 2 @test_throws InexactError convert(BigInt, 2.1) diff --git a/test/intfuncs.jl b/test/intfuncs.jl index c5fd6732bba66..7a445307e197d 100644 --- a/test/intfuncs.jl +++ b/test/intfuncs.jl @@ -99,6 +99,10 @@ end # issue #19367 @test ndigits(Int128(2)^64, 256) == 9 +# test unsigned bases +@test ndigits(9, 0x2) == 4 +@test ndigits(0x9, 0x2) == 4 + @test bin('3') == "110011" @test bin('3',7) == "0110011" @test bin(3) == "11" From 775468553b0c8bb6905cf9d8160a956ed6104787 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Fri, 26 Aug 2016 11:16:12 +0200 Subject: [PATCH 0720/1534] ndigits: add a 'pad' argument --- base/intfuncs.jl | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 0c43446b4c031..fca9fc16a1dc8 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -325,6 +325,8 @@ function prevpow(a::Real, x::Real) p <= x ? p : a^n end +## ndigits (number of digits) in base 10 ## + # decimal digits in an unsigned integer const powers_of_ten = [ 0x0000000000000001, 0x000000000000000a, 0x0000000000000064, 0x00000000000003e8, @@ -349,8 +351,13 @@ end ndigits0z(x::Signed) = ndigits0z(unsigned(abs(x))) -ndigits0z(x::Integer) = ndigits(x, false) -ndigits(x::Integer, min1::Bool=true) = x==0 ? min1%Int : ndigits0zpb(x, 10) +ndigits0z(x::Integer) = ndigits0zpb(x, 10) + +# TODO (when keywords args are fast): rename to ndigits and make pad a keyword +ndigits10(x::Integer, pad::Int=1) = max(pad, ndigits0z(x)) +ndigits(x::Integer) = iszero(x) ? 1 : ndigits0z(x) + +## ndigits with specified base ## # The suffix "nb" stands for "negative base" function ndigits0znb(n::Integer, b::Integer) @@ -403,26 +410,24 @@ integer `n` written in base `b` (i.e. equal to `ndigits(n, b)` in this case). The base `b` must not be in `[-1, 0, 1]`. """ -ndigits0z(x::Integer, b::Integer) = ndigits(x, b, false) - -""" - ndigits(n::Integer, b::Integer=10) - -Compute the number of digits in integer `n` written in base `b`. -The base `b` must not be in `[-1, 0, 1] -""" -function ndigits(x::Integer, b::Integer, min1::Bool=true) - # min1: whether the minimum value of this function should be 1 - # (for the special input value 0), or not (then ndigits(0, b) == 0) +function ndigits0z(x::Integer, b::Integer) if b < -1 - x == 0 ? min1%Int : ndigits0znb(x, b) + ndigits0znb(x, b) elseif b > 1 - x == 0 ? min1%Int : ndigits0zpb(x, b) + ndigits0zpb(x, b) else throw(DomainError()) end end +""" + ndigits(n::Integer, b::Integer=10) + +Compute the number of digits in integer `n` written in base `b`. +The base `b` must not be in `[-1, 0, 1]`. +""" +ndigits(x::Integer, b::Integer, pad::Int=1) = max(pad, ndigits0z(x, b)) + ## integer to string functions ## string(x::Union{Int8,Int16,Int32,Int64,Int128}) = dec(x) @@ -452,7 +457,7 @@ function oct(x::Unsigned, pad::Int, neg::Bool) end function dec(x::Unsigned, pad::Int, neg::Bool) - i = neg + max(pad,ndigits0z(x)) + i = neg + ndigits10(x, pad) a = StringVector(i) while i > neg a[i] = '0'+rem(x,10) @@ -484,7 +489,7 @@ const base62digits = ['0':'9';'A':'Z';'a':'z'] function base(b::Int, x::Unsigned, pad::Int, neg::Bool) 2 <= b <= 62 || throw(ArgumentError("base must be 2 ≤ base ≤ 62, got $b")) digits = b <= 36 ? base36digits : base62digits - i = neg + max(pad,ndigits0z(x,b)) + i = neg + ndigits(x, b, pad) a = StringVector(i) while i > neg a[i] = digits[1+rem(x,b)] @@ -574,7 +579,7 @@ higher indexes, such that `n == sum([digits[k]*base^(k-1) for k=1:length(digits) digits(n::Integer, base::T=10, pad::Integer=1) where {T<:Integer} = digits(T, n, base, pad) function digits(T::Type{<:Integer}, n::Integer, base::Integer=10, pad::Integer=1) - digits!(zeros(T, max(pad, ndigits0z(n,base))), n, base) + digits!(zeros(T, ndigits(n, base, pad)), n, base) end """ From 897e666be71e6a281d6df24d954d7434c5a4a434 Mon Sep 17 00:00:00 2001 From: Mus M Date: Fri, 12 May 2017 17:19:17 -0400 Subject: [PATCH 0721/1534] Use uninitialized buffer for get_process_title() --- base/sysinfo.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/sysinfo.jl b/base/sysinfo.jl index fb9119dd668b5..73e7ff33451e6 100644 --- a/base/sysinfo.jl +++ b/base/sysinfo.jl @@ -162,7 +162,7 @@ total_memory() = ccall(:uv_get_total_memory, UInt64, ()) Get the process title. On some systems, will always return empty string. (not exported) """ function get_process_title() - buf = zeros(UInt8, 512) + buf = Vector{UInt8}(512) err = ccall(:uv_get_process_title, Cint, (Ptr{UInt8}, Cint), buf, 512) Base.uv_error("get_process_title", err) return unsafe_string(pointer(buf)) From ba56cbb7bbf7f631178381328092f77a5553a708 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Fri, 12 May 2017 15:58:57 -0700 Subject: [PATCH 0722/1534] Add NEWS.md entry for bitbroadcast deprecation (#19771). (#21804) --- NEWS.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS.md b/NEWS.md index 21dd1ccb602c3..4f6172d368000 100644 --- a/NEWS.md +++ b/NEWS.md @@ -440,6 +440,9 @@ Deprecated or removed * The zero-argument constructor `MersenneTwister()` has been deprecated in favor of the explicit `MersenneTwister(0)` ([#16984]). + * `bitbroadcast` has been deprecated in favor of `broadcast`, which now produces a + `BitArray` instead of `Array{Bool}` for functions yielding a boolean result ([#19771]). + [#265]: https://github.com/JuliaLang/julia/issues/265 [#4615]: https://github.com/JuliaLang/julia/issues/4615 @@ -512,6 +515,7 @@ Deprecated or removed [#19722]: https://github.com/JuliaLang/julia/issues/19722 [#19724]: https://github.com/JuliaLang/julia/issues/19724 [#19741]: https://github.com/JuliaLang/julia/issues/19741 +[#19771]: https://github.com/JuliaLang/julia/issues/19771 [#19784]: https://github.com/JuliaLang/julia/issues/19784 [#19787]: https://github.com/JuliaLang/julia/issues/19787 [#19791]: https://github.com/JuliaLang/julia/issues/19791 From 28675708427c3631bf6dd6601fa0ad26f00f24ca Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Fri, 12 May 2017 15:59:11 -0700 Subject: [PATCH 0723/1534] Add NEWS.md entry for homedir implementation changes (#19636). (#21805) --- NEWS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS.md b/NEWS.md index 4f6172d368000..51da28ea021f7 100644 --- a/NEWS.md +++ b/NEWS.md @@ -262,6 +262,8 @@ This section lists changes that do not have deprecation warnings. serialize globals defined under Main. For details, please refer to the paragraph on "Global variables" under the "Parallel computing" chapter in the manual ([#19594]). + * `homedir` now determines the user's home directory via `libuv`'s `uv_os_homedir`, + rather than from environment variables ([#19636]). Library improvements -------------------- @@ -503,6 +505,7 @@ Deprecated or removed [#19594]: https://github.com/JuliaLang/julia/issues/19594 [#19598]: https://github.com/JuliaLang/julia/issues/19598 [#19635]: https://github.com/JuliaLang/julia/issues/19635 +[#19636]: https://github.com/JuliaLang/julia/issues/19636 [#19670]: https://github.com/JuliaLang/julia/issues/19670 [#19677]: https://github.com/JuliaLang/julia/issues/19677 [#19680]: https://github.com/JuliaLang/julia/issues/19680 From 194b246143b4425e9b18ba985f076cb44b16ba78 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Fri, 12 May 2017 15:59:25 -0700 Subject: [PATCH 0724/1534] Add NEWS.md entry for IPv4 address parsing changes (#19811). (#21807) --- NEWS.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/NEWS.md b/NEWS.md index 51da28ea021f7..75adc6564002a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -258,6 +258,10 @@ This section lists changes that do not have deprecation warnings. localize variables. Previously, the expression would be wrapped in an implicit `let` block ([#19594]). + * `parse` no longer accepts IPv4 addresses including leading zeros, octal, or hexadecimal. + Convert IPv4 addresses including octal or hexadecimal to decimal, and remove leading + zeros in decimal addresses ([#19811]). + * Closures shipped for remote execution via `@spawn` or `remotecall` now automatically serialize globals defined under Main. For details, please refer to the paragraph on "Global variables" under the "Parallel computing" chapter in the manual ([#19594]). @@ -524,6 +528,7 @@ Deprecated or removed [#19791]: https://github.com/JuliaLang/julia/issues/19791 [#19800]: https://github.com/JuliaLang/julia/issues/19800 [#19802]: https://github.com/JuliaLang/julia/issues/19802 +[#19811]: https://github.com/JuliaLang/julia/issues/19811 [#19841]: https://github.com/JuliaLang/julia/issues/19841 [#19900]: https://github.com/JuliaLang/julia/issues/19900 [#19903]: https://github.com/JuliaLang/julia/issues/19903 From 4ecdf950802cc19a28948c8c4878f66cc1fb7de8 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Fri, 12 May 2017 15:59:40 -0700 Subject: [PATCH 0725/1534] Add NEWS.md entry for function composition and negation via operators (#17155). (#21808) --- NEWS.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/NEWS.md b/NEWS.md index 75adc6564002a..eb03244b5518e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -387,6 +387,12 @@ Library improvements now efficiently yield `SparseVector`s or `SparseMatrix`s as appropriate ([#19239], [#19371], [#19518], [#19438], [#19690], [#19724], [#19926], [#19934], [#20009]). + * The operators `!` and `∘` (`\circ` at the REPL and in most code editors) now + respectively perform predicate function negation and function composition. For example, + `map(!iszero, (0, 1))` is now equivalent to `map(x -> !iszero(x), (0, 1))` and + `map(uppercase ∘ hex, 250:255)` is now equivalent to + `map(x -> uppercase(hex(x)), 250:255)` ([#17155]). + Compiler/Runtime improvements ----------------------------- @@ -464,6 +470,7 @@ Deprecated or removed [#16984]: https://github.com/JuliaLang/julia/issues/16984 [#16986]: https://github.com/JuliaLang/julia/issues/16986 [#17057]: https://github.com/JuliaLang/julia/issues/17057 +[#17155]: https://github.com/JuliaLang/julia/issues/17155 [#17261]: https://github.com/JuliaLang/julia/issues/17261 [#17265]: https://github.com/JuliaLang/julia/issues/17265 [#17302]: https://github.com/JuliaLang/julia/issues/17302 From 4ecbe49e41e9bf5a1de1141d325ab62f21ee2bfb Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Fri, 12 May 2017 15:59:54 -0700 Subject: [PATCH 0726/1534] Add NEWS.md entry noting need to quote special characters in Cmds (#19786). (#21809) --- NEWS.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/NEWS.md b/NEWS.md index eb03244b5518e..db9875f72448f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -449,6 +449,10 @@ Deprecated or removed * `convert` methods from `Diagonal` and `Bidiagonal` to subtypes of `AbstractTriangular` have been deprecated ([#17723]). + * Special characters (`#{}()[]<>|&*?~;`) should now be quoted in commands. For example, + ``` `export FOO=1\;` ``` should replace ``` `export FOO=1;` ``` and + ``` `cd $dir '&&' $thingie` ``` should replace ``` `cd $dir && $thingie` ``` ([#19786]). + * The zero-argument constructor `MersenneTwister()` has been deprecated in favor of the explicit `MersenneTwister(0)` ([#16984]). @@ -531,6 +535,7 @@ Deprecated or removed [#19741]: https://github.com/JuliaLang/julia/issues/19741 [#19771]: https://github.com/JuliaLang/julia/issues/19771 [#19784]: https://github.com/JuliaLang/julia/issues/19784 +[#19786]: https://github.com/JuliaLang/julia/issues/19786 [#19787]: https://github.com/JuliaLang/julia/issues/19787 [#19791]: https://github.com/JuliaLang/julia/issues/19791 [#19800]: https://github.com/JuliaLang/julia/issues/19800 From 4c05eb28354756610d24a98905d7ada1311999e1 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Fri, 12 May 2017 16:00:08 -0700 Subject: [PATCH 0727/1534] Add NEWS.md entry for test_approx_eq[_eps] deprecations (#19901). (#21810) --- NEWS.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/NEWS.md b/NEWS.md index db9875f72448f..b763483a1c342 100644 --- a/NEWS.md +++ b/NEWS.md @@ -446,6 +446,14 @@ Deprecated or removed * `broadcast_zpreserving` has been deprecated ([#19533], [#19720]). + * `@test_approx_eq a b` has been deprecated in favor of `@test a ≈ b` (or, + equivalently, `@test ≈(a, b)` or `@test isapprox(a, b)`). + `@test_approx_eq_eps` has been deprecated in favor of new `@test` syntax: + `@test` now supports the syntax `@test f(args...) key=val ...` for + `@test f(args..., key=val...)`. This syntax allows, for example, writing + `@test a ≈ b atol=c` in place of `@test ≈(a, b, atol=c)` (and hence + `@test_approx_eq_eps a b c`) ([#19901]). + * `convert` methods from `Diagonal` and `Bidiagonal` to subtypes of `AbstractTriangular` have been deprecated ([#17723]). @@ -543,6 +551,7 @@ Deprecated or removed [#19811]: https://github.com/JuliaLang/julia/issues/19811 [#19841]: https://github.com/JuliaLang/julia/issues/19841 [#19900]: https://github.com/JuliaLang/julia/issues/19900 +[#19901]: https://github.com/JuliaLang/julia/issues/19901 [#19903]: https://github.com/JuliaLang/julia/issues/19903 [#19919]: https://github.com/JuliaLang/julia/issues/19919 [#19926]: https://github.com/JuliaLang/julia/issues/19926 From d052e88c6b19c63d1dde55ecc9b22e764e62c0b1 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Fri, 12 May 2017 16:03:12 -0700 Subject: [PATCH 0728/1534] Add NEWS.md entry for deprecation of invoke's tuple-of-types form (#18444). (#21817) --- NEWS.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS.md b/NEWS.md index b763483a1c342..32ccc86752a38 100644 --- a/NEWS.md +++ b/NEWS.md @@ -444,6 +444,9 @@ Deprecated or removed * `isimag` has been deprecated ([#19949]). + * The tuple-of-types form of `invoke`, `invoke(f, (types...), ...)`, has been deprecated + in favor of the tuple-type form `invoke(f, Tuple{types...}, ...)` ([#18444]). + * `broadcast_zpreserving` has been deprecated ([#19533], [#19720]). * `@test_approx_eq a b` has been deprecated in favor of `@test a ≈ b` (or, @@ -497,6 +500,7 @@ Deprecated or removed [#18339]: https://github.com/JuliaLang/julia/issues/18339 [#18346]: https://github.com/JuliaLang/julia/issues/18346 [#18442]: https://github.com/JuliaLang/julia/issues/18442 +[#18444]: https://github.com/JuliaLang/julia/issues/18444 [#18453]: https://github.com/JuliaLang/julia/issues/18453 [#18457]: https://github.com/JuliaLang/julia/issues/18457 [#18473]: https://github.com/JuliaLang/julia/issues/18473 From 9ac907163e23f306344c5d9da0adc22d9a85fa93 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Fri, 12 May 2017 16:04:42 -0700 Subject: [PATCH 0729/1534] Add link to libuv's uv_os_homedir documentation to homedir's docstring. (#21806) --- base/path.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/base/path.jl b/base/path.jl index 37476674d0f24..df03c9def77b5 100644 --- a/base/path.jl +++ b/base/path.jl @@ -53,6 +53,11 @@ splitdrive(path::AbstractString) homedir() -> AbstractString Return the current user's home directory. + +!!! note + `homedir` determines the home directory via `libuv`'s `uv_os_homedir`. For details + (for example on how to specify the home directory via environment variables), see the + [`uv_os_homedir` documentation](http://docs.libuv.org/en/v1.x/misc.html#c.uv_os_homedir). """ function homedir() path_max = 1024 From 2b4bb1ad966f1a7b72a5a439c31453e325d968a1 Mon Sep 17 00:00:00 2001 From: Alexey Stukalov Date: Fri, 5 May 2017 11:03:45 +0200 Subject: [PATCH 0730/1534] make ntuple(f, Val{-1}) throw ArgumentError otherwise Julia would stuck in an endless type inference loop --- base/tuple.jl | 1 + test/tuple.jl | 2 ++ 2 files changed, 3 insertions(+) diff --git a/base/tuple.jl b/base/tuple.jl index 4103b9111edf9..4c7687f5a52be 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -142,6 +142,7 @@ ntuple(f, ::Type{Val{15}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6) function ntuple(f::F, ::Type{Val{N}}) where {F,N} Core.typeassert(N, Int) + (N >= 0) || throw(ArgumentError(string("tuple length should be ≥0, got ", N))) _ntuple((), f, Val{N}) end diff --git a/test/tuple.jl b/test/tuple.jl index 451a9f7fea6ce..d59b0497cdc9f 100644 --- a/test/tuple.jl +++ b/test/tuple.jl @@ -168,6 +168,8 @@ end @test @inferred(ntuple(abs2, Val{4})) == (1, 4, 9, 16) @test @inferred(ntuple(abs2, Val{5})) == (1, 4, 9, 16, 25) @test @inferred(ntuple(abs2, Val{6})) == (1, 4, 9, 16, 25, 36) +# issue #21697 +@test_throws ArgumentError ntuple(abs2, Val{-1}) # issue #12854 @test_throws TypeError ntuple(identity, Val{1:2}) From fc90413e4045b2649195328890cd736ff84b6fbe Mon Sep 17 00:00:00 2001 From: Alexey Stukalov Date: Thu, 4 May 2017 21:19:07 +0200 Subject: [PATCH 0731/1534] ntuple(f, -1) throws ArgumentError --- NEWS.md | 2 ++ base/tuple.jl | 8 ++++++-- test/tuple.jl | 2 ++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index 32ccc86752a38..4ec36725798b3 100644 --- a/NEWS.md +++ b/NEWS.md @@ -14,6 +14,8 @@ Breaking changes This section lists changes that do not have deprecation warnings. + * `ntuple(f, n::Integer)` throws `ArgumentError` if `n` is negative. + Previously an empty tuple was returned ([#21697]). Library improvements -------------------- diff --git a/base/tuple.jl b/base/tuple.jl index 4c7687f5a52be..dc041a47937fb 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -105,7 +105,7 @@ julia> ntuple(i -> 2*i, 4) ``` """ function ntuple(f::F, n::Integer) where F - t = n <= 0 ? () : + t = n == 0 ? () : n == 1 ? (f(1),) : n == 2 ? (f(1), f(2)) : n == 3 ? (f(1), f(2), f(3)) : @@ -120,7 +120,11 @@ function ntuple(f::F, n::Integer) where F return t end -_ntuple(f, n) = (@_noinline_meta; ([f(i) for i = 1:n]...)) +function _ntuple(f, n) + @_noinline_meta + (n >= 0) || throw(ArgumentError(string("tuple length should be ≥0, got ", n))) + ([f(i) for i = 1:n]...) +end # inferrable ntuple ntuple(f, ::Type{Val{0}}) = (@_inline_meta; ()) diff --git a/test/tuple.jl b/test/tuple.jl index d59b0497cdc9f..2385e52a9ef4f 100644 --- a/test/tuple.jl +++ b/test/tuple.jl @@ -181,6 +181,8 @@ for n = 0:20 @test t[i] == i end end +# issue #21697 +@test_throws ArgumentError ntuple(identity, -1) # issue #19719 @test_throws BoundsError (1,2,3)[falses(4)] From e26b1e181c21f71b30c1ccb084ec31a6396b8b8f Mon Sep 17 00:00:00 2001 From: Westley Argentum Hennigh-Palermo Date: Fri, 12 May 2017 21:05:04 -0400 Subject: [PATCH 0732/1534] fix links to docs in CONTRIBUTING.md (#21766) --- CONTRIBUTING.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c0a9a7f2d7793..bea8df3c44394 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,10 +1,10 @@ # Notes for Julia Contributors -Hi! If you are new to the Julia community: welcome, and thanks for trying Julia. Please be sure to respect our [community standards](https://julialang.org/community/standards/) in all interactions. +Hi! If you are new to the Julia community: welcome, and thanks for trying Julia. Please be sure to respect our [community standards](https://julialang.org/community/standards) in all interactions. ## Learning Julia -[The learning page](https://julialang.org/learning/) has a great list of resources for new and experienced users alike. [This tutorial video](https://www.youtube.com/watch?v=vWkgEddb4-A) is one recommended starting point, as is the "[Invitation to Julia](https://www.youtube.com/watch?v=gQ1y5NUD_RI)" workshop video from JuliaCon 2015 ([slide materials here](https://github.com/dpsanders/invitation_to_julia)). The [Julia documentation](https://docs.julialang.org/en/latest/) covers the language and core library features, and is searchable. +[The learning page](https://julialang.org/learning) has a great list of resources for new and experienced users alike. [This tutorial video](https://www.youtube.com/watch?v=vWkgEddb4-A) is one recommended starting point, as is the "[Invitation to Julia](https://www.youtube.com/watch?v=gQ1y5NUD_RI)" workshop video from JuliaCon 2015 ([slide materials here](https://github.com/dpsanders/invitation_to_julia)). The [Julia documentation](https://docs.julialang.org/en/latest) covers the language and core library features, and is searchable. ## Before filing an issue @@ -12,7 +12,7 @@ Hi! If you are new to the Julia community: welcome, and thanks for trying Julia. - Contributing code? Be sure to review the [contributor checklist](https://github.com/JuliaLang/julia/blob/master/CONTRIBUTING.md#contributor-checklist) for helpful tips on the tools we use to build Julia. -- Library feature requests are generally not accepted on this issue tracker. New libraries should be developed as [packages](https://docs.julialang.org/en/release-0.4/manual/packages/#package-development). Discuss ideas for libraries at the [Julia Discourse forum](https://discourse.julialang.org/). Doing so will often lead to pointers to existing projects and bring together collaborators with common interests. +- Library feature requests are generally not accepted on this issue tracker. New libraries should be developed as [packages](https://docs.julialang.org/en/latest/manual/packages#Package-Development-1). Discuss ideas for libraries at the [Julia Discourse forum](https://discourse.julialang.org). Doing so will often lead to pointers to existing projects and bring together collaborators with common interests. ## Contributor Checklist @@ -26,7 +26,7 @@ Hi! If you are new to the Julia community: welcome, and thanks for trying Julia. * Learn to use [git](http://git-scm.com), the version control system used by GitHub and the Julia project. Try a tutorial such as the one [provided by GitHub](http://try.GitHub.io/levels/1/challenges/1). -* Review discussions on the [Julia Discourse forum](https://discourse.julialang.org/). +* Review discussions on the [Julia Discourse forum](https://discourse.julialang.org). * For more detailed tips, read the [submission guide](https://github.com/JuliaLang/julia/blob/master/CONTRIBUTING.md#submitting-contributions) below. @@ -37,11 +37,11 @@ Hi! If you are new to the Julia community: welcome, and thanks for trying Julia. A useful bug report filed as a GitHub issue provides information about how to reproduce the error. 1. Before opening a new [GitHub issue](https://github.com/JuliaLang/julia/issues): - - Try searching the existing issues or the [Julia Discourse forum](https://discourse.julialang.org/) to see if someone else has already noticed the same problem. + - Try searching the existing issues or the [Julia Discourse forum](https://discourse.julialang.org) to see if someone else has already noticed the same problem. - Try some simple debugging techniques to help isolate the problem. - Try running the code with the debug build of Julia with `make debug`, which produces the `usr/bin/julia-debug`. - Consider running `julia-debug` with a debugger such as `gdb` or `lldb`. Obtaining even a simple [backtrace](http://www.unknownroad.com/rtfm/gdbtut/gdbsegfault.html) is very useful. - - If Julia segfaults, try following [these debugging tips](http://julia.readthedocs.org/en/latest/devdocs/backtraces/#segfaults-during-bootstrap-sysimg-jl) to help track down the specific origin of the bug. + - If Julia segfaults, try following [these debugging tips](https://docs.julialang.org/en/latest/devdocs/backtraces.html#Reporting-and-analyzing-crashes-(segfaults)-1) to help track down the specific origin of the bug. 2. If the problem is caused by a Julia package rather than core Julia, file a bug report with the relevant package author rather than here. @@ -50,13 +50,13 @@ A useful bug report filed as a GitHub issue provides information about how to re - A minimal working example, i.e. the smallest chunk of code that triggers the error. Ideally, this should be code that can be pasted into a REPL or run from a source file. If the code is larger than (say) 50 lines, consider putting it in a [gist](https://gist.github.com). - The version of Julia as provided by the `versioninfo()` command. Occasionally, the longer output produced by `versioninfo(true)` may be useful also, especially if the issue is related to a specific package. -4. When pasting code blocks or output, put triple backquotes (\`\`\`) around the text so GitHub will format it nicely. Code statements should be surrounded by single backquotes (\`). Be aware that the `@` sign tags users on GitHub, so references to macros should always be in single backquotes. See [GitHub's guide on Markdown](https://guides.github.com/features/mastering-markdown/) for more formatting tricks. +4. When pasting code blocks or output, put triple backquotes (\`\`\`) around the text so GitHub will format it nicely. Code statements should be surrounded by single backquotes (\`). Be aware that the `@` sign tags users on GitHub, so references to macros should always be in single backquotes. See [GitHub's guide on Markdown](https://guides.github.com/features/mastering-markdown) for more formatting tricks. ## Submitting contributions ### Contributing a Julia package -Julia has a built-in [package manager](https://github.com/JuliaLang/METADATA.jl) based on `git`. A number of [packages](http://pkg.julialang.org/) across many domains are already available for Julia. Developers are encouraged to provide their libraries as a Julia package. The Julia manual provides instructions on [creating Julia packages](https://docs.julialang.org/en/latest/manual/packages/). +Julia has a built-in [package manager](https://github.com/JuliaLang/METADATA.jl) based on `git`. A number of [packages](http://pkg.julialang.org) across many domains are already available for Julia. Developers are encouraged to provide their libraries as a Julia package. The Julia manual provides instructions on [creating Julia packages](https://docs.julialang.org/en/latest/manual/packages). For developers who need to wrap C libraries so that they can be called from Julia, the [Clang.jl](https://github.com/ihnorton/Clang.jl) package can help generate the wrappers automatically from the C header files. @@ -71,7 +71,7 @@ to port your package to latest Julia release. However, porting a package to the latest release may cause the package to break on earlier Julia releases. To maintain compatibility across releases, use -[`Compat.jl`](https://github.com/JuliaLang/Compat.jl/). Find the fix for your package +[`Compat.jl`](https://github.com/JuliaLang/Compat.jl). Find the fix for your package from the README, and specify the minimum version of Compat that provides the fix in your REQUIRE file. To find the correct minimum version, refer to [this guide](https://github.com/JuliaLang/Compat.jl/#tagging-the-correct-minimum-version-of-compat). @@ -84,7 +84,7 @@ There are never enough tests. Track [code coverage at Coveralls](https://coveral 2. Browse through the source files and find some untested functionality (highlighted in red) that you think you might be able to write a test for. -3. Write a test that exercises this functionality---you can add your test to one of the existing files, or start a new one, whichever seems most appropriate to you. If you're adding a new test file, make sure you include it in the list of tests in `test/choosetests.jl`. http://julia.readthedocs.org/en/latest/stdlib/test/ may be helpful in explaining how the testing infrastructure works. +3. Write a test that exercises this functionality---you can add your test to one of the existing files, or start a new one, whichever seems most appropriate to you. If you're adding a new test file, make sure you include it in the list of tests in `test/choosetests.jl`. https://docs.julialang.org/en/latest/stdlib/test may be helpful in explaining how the testing infrastructure works. 4. Run `make test-all` to rebuild Julia and run your new test(s). If you had to fix a bug or add functionality in `base`, this will ensure that your test passes and that you have not introduced extraneous whitespace. @@ -112,7 +112,7 @@ from Julia's root directory. This will rebuild the Julia system image, then inst > > When making changes to any of Julia's documentation it is recommended that you run `make docs` to check the your changes are valid and do not produce any errors before opening a pull request. -Below are outlined the three most common types of documentation changes and the steps required to perform them. Please note that the following instructions do not cover the full range of features provided by Documenter.jl. Refer to [Documenter's documentation](https://juliadocs.github.io/Documenter.jl/stable/) if you encounter anything that is not covered by the sections below. +Below are outlined the three most common types of documentation changes and the steps required to perform them. Please note that the following instructions do not cover the full range of features provided by Documenter.jl. Refer to [Documenter's documentation](https://juliadocs.github.io/Documenter.jl/stable) if you encounter anything that is not covered by the sections below. #### Modifying files in `doc/src/` @@ -194,7 +194,7 @@ For new functionality and other substantial changes, add a brief summary to `NEW The Julia community uses [GitHub issues](https://github.com/JuliaLang/julia/issues) to track and discuss problems, feature requests, and pull requests (PR). You can make pull requests for incomplete features to get code review. The convention is to prefix the pull request title with "WIP:" for Work In Progress, or "RFC:" for Request for Comments when work is completed and ready for merging. This will prevent accidental merging of work that is in progress. -Note: These instructions are for adding to or improving functionality in the base library. Before getting started, it can be helpful to discuss the proposed changes or additions on the [Julia Discourse forum](https://discourse.julialang.org/) or in a GitHub issue---it's possible your proposed change belongs in a package rather than the core language. Also, keep in mind that changing stuff in the base can potentially break a lot of things. Finally, because of the time required to build Julia, note that it's usually faster to develop your code in stand-alone files, get it working, and then migrate it into the base libraries. +Note: These instructions are for adding to or improving functionality in the base library. Before getting started, it can be helpful to discuss the proposed changes or additions on the [Julia Discourse forum](https://discourse.julialang.org) or in a GitHub issue---it's possible your proposed change belongs in a package rather than the core language. Also, keep in mind that changing stuff in the base can potentially break a lot of things. Finally, because of the time required to build Julia, note that it's usually faster to develop your code in stand-alone files, get it working, and then migrate it into the base libraries. Add new code to Julia's base libraries as follows: @@ -216,7 +216,7 @@ or with the `runtests.jl` script, e.g. to run `test/bitarray.jl` and `test/math. ./usr/bin/julia test/runtests.jl bitarray math -Make sure that [Travis](http://www.travis-ci.org) greenlights the pull request with a [`Good to merge` message](http://blog.travis-ci.com/2012-09-04-pull-requests-just-got-even-more-awesome/). +Make sure that [Travis](http://www.travis-ci.org) greenlights the pull request with a [`Good to merge` message](http://blog.travis-ci.com/2012-09-04-pull-requests-just-got-even-more-awesome). ### Code Formatting Guidelines @@ -274,10 +274,10 @@ Make sure that [Travis](http://www.travis-ci.org) greenlights the pull request w * Design of Julia - [Julia: A Fresh Approach to Numerical Computing](http://arxiv.org/pdf/1411.1607v3.pdf) - [Julia: A Fast Dynamic Language for Technical Computing](https://julialang.org/images/julia-dynamic-2012-tr.pdf) - - [All Julia Publications](https://julialang.org/publications/) + - [All Julia Publications](https://julialang.org/publications) * Using GitHub - [Using Julia with GitHub (video)](http://www.youtube.com/watch?v=wnFYV3ZKtOg&feature=youtu.be) - [Using Julia on GitHub (notes for video)](https://gist.github.com/2712118#file_Julia_git_pull_request.md) - - [General GitHub documentation](http://help.github.com/) - - [GitHub pull request documentation](http://help.github.com/send-pull-requests/) + - [General GitHub documentation](http://help.github.com) + - [GitHub pull request documentation](http://help.github.com/send-pull-requests) From d86b37cac496e6090061966237272be48a8fc8d2 Mon Sep 17 00:00:00 2001 From: Gollor Date: Sat, 13 May 2017 04:07:29 +0300 Subject: [PATCH 0733/1534] Fixed relative path include on remote machines --- base/loading.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/base/loading.jl b/base/loading.jl index 2674b3dfd27f1..e09974252542a 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -263,6 +263,9 @@ const _require_dependencies = Any[] # a list of (path, mtime) tuples that are th const _track_dependencies = Ref(false) # set this to true to track the list of file dependencies function _include_dependency(_path::AbstractString) prev = source_path(nothing) + if myid() != 1 && prev === nothing + prev = remotecall_fetch(abspath, 1, ".") + end path = (prev === nothing) ? abspath(_path) : joinpath(dirname(prev), _path) if myid() == 1 && _track_dependencies[] apath = abspath(path) @@ -817,3 +820,4 @@ function stale_cachefile(modpath::String, cachefile::String) close(io) end end + From 7e7393c1e40ea593c96cc767a46d039ec3a59759 Mon Sep 17 00:00:00 2001 From: Gollor Date: Sat, 13 May 2017 04:11:40 +0300 Subject: [PATCH 0734/1534] Removed trailing whitespace --- base/loading.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/base/loading.jl b/base/loading.jl index e09974252542a..9ff3e889ec928 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -820,4 +820,3 @@ function stale_cachefile(modpath::String, cachefile::String) close(io) end end - From 03721cbe6940403edf81ec667d3e0b610ceb8128 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Fri, 12 May 2017 22:55:04 -0700 Subject: [PATCH 0735/1534] Add NEWS.md entry for removal of the /(::Integer, ::Integer) fallback (#19779). (#21815) --- NEWS.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/NEWS.md b/NEWS.md index 32ccc86752a38..434c3a5f69230 100644 --- a/NEWS.md +++ b/NEWS.md @@ -254,6 +254,10 @@ This section lists changes that do not have deprecation warnings. * `write` on an `IOBuffer` now returns a signed integer in order to be consistent with other buffers ([#20609]). + * The `<:Integer` division fallback `/(::Integer, ::Integer)`, which formerly + inappropriately took precedence over other division methods for some + mixed-integer-type division calls, has been removed ([#19779]). + * `@async`, `@spawn`, `@spawnat`, `@fetch` and `@fetchfrom` no longer implicitly localize variables. Previously, the expression would be wrapped in an implicit `let` block ([#19594]). @@ -546,6 +550,7 @@ Deprecated or removed [#19724]: https://github.com/JuliaLang/julia/issues/19724 [#19741]: https://github.com/JuliaLang/julia/issues/19741 [#19771]: https://github.com/JuliaLang/julia/issues/19771 +[#19779]: https://github.com/JuliaLang/julia/issues/19779 [#19784]: https://github.com/JuliaLang/julia/issues/19784 [#19786]: https://github.com/JuliaLang/julia/issues/19786 [#19787]: https://github.com/JuliaLang/julia/issues/19787 From a898a5049b850256b76ea726354c5b426108fe50 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Fri, 12 May 2017 22:56:10 -0700 Subject: [PATCH 0736/1534] Add NEWS.md entry for macro hygiene fix (#15850). (#21820) --- NEWS.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/NEWS.md b/NEWS.md index 434c3a5f69230..f3eb8514b9545 100644 --- a/NEWS.md +++ b/NEWS.md @@ -251,6 +251,12 @@ This section lists changes that do not have deprecation warnings. `airybiprimex`, `airyaix`, `airybix`, `airyaiprimex`, `airybiprimex`) ([#18050]). + * When a macro is called in the module in which that macro is defined, global variables + in the macro are now correctly resolved in the macro definition environment. Breakage + from this change commonly manifests as undefined variable errors that do not occur + under 0.5. Fixing such breakage typically requires sprinkling additional `esc`s in + the offending macro ([#15850]). + * `write` on an `IOBuffer` now returns a signed integer in order to be consistent with other buffers ([#20609]). @@ -484,6 +490,7 @@ Deprecated or removed [#11310]: https://github.com/JuliaLang/julia/issues/11310 [#12274]: https://github.com/JuliaLang/julia/issues/12274 [#12563]: https://github.com/JuliaLang/julia/issues/12563 +[#15850]: https://github.com/JuliaLang/julia/issues/15850 [#16213]: https://github.com/JuliaLang/julia/issues/16213 [#16961]: https://github.com/JuliaLang/julia/issues/16961 [#16984]: https://github.com/JuliaLang/julia/issues/16984 From 4c501a74ce07c54955cde273cc4cfa358457bce2 Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Sat, 13 May 2017 00:43:52 -0700 Subject: [PATCH 0737/1534] Improve comment --- contrib/fixup-libgfortran.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/fixup-libgfortran.sh b/contrib/fixup-libgfortran.sh index 9c7f078031a16..3d8579e7a6a55 100755 --- a/contrib/fixup-libgfortran.sh +++ b/contrib/fixup-libgfortran.sh @@ -61,7 +61,7 @@ for lib in arpack openspecfun lapack; do LIBQUADMATH_PATH=$(find_shlib "$(private_libname $lib)" libquadmath) # Take the directories, add them onto LIBGFORTRAN_DIRS, which we use to - # search for these libraries with in the future. + # search for these libraries in the future. LIBGFORTRAN_DIRS="$LIBGFORTRAN_DIRS $(dirname $LIBGFORTRAN_PATH)" LIBGFORTRAN_DIRS="$LIBGFORTRAN_DIRS $(dirname $LIBGCC_PATH)" LIBGFORTRAN_DIRS="$LIBGFORTRAN_DIRS $(dirname $LIBQUADMATH_PATH)" From 6a4acc0423e4c746166fcee0ce8dedf44f36aeaa Mon Sep 17 00:00:00 2001 From: Gollor Date: Sat, 13 May 2017 17:26:27 +0300 Subject: [PATCH 0738/1534] Added tests for remote including --- test/distributed_exec.jl | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/test/distributed_exec.jl b/test/distributed_exec.jl index 818c410505a2c..4b33afbb7e918 100644 --- a/test/distributed_exec.jl +++ b/test/distributed_exec.jl @@ -1569,6 +1569,41 @@ catch ex @test ex.captured.ex.exceptions[2].ex == UndefVarError(:DontExistOn1) end +@test let + # creates a new worker in the same folder and tries to include file on both procs + try + touch("temp.jl") + proc = addprocs_with_testenv(1) + include("temp.jl") + remotecall_fetch(include, proc[1], "temp.jl") + rmprocs(proc) + rm("temp.jl") + return true + catch e + try rm("temp.jl") end + return false + end +end == true + +@test let + # creates a new worker in the different folder and tries to include file on both procs + try + mkdir("temp_folder") + touch("temp.jl") + proc = addprocs_with_testenv(1, dir="temp_folder") + include("temp.jl") + remotecall_fetch(include, proc[1], "temp.jl") + rmprocs(proc) + rm("temp_folder") + rm("temp.jl") + return true + catch e + try rm("temp_folder") end + try rm("temp.jl") end + return false + end +end == true + # Run topology tests last after removing all workers, since a given # cluster at any time only supports a single topology. rmprocs(workers()) From 93cf6d93050465944cde7e6a5cdfc23f8fe28cc6 Mon Sep 17 00:00:00 2001 From: Gollor Date: Sat, 13 May 2017 18:07:58 +0300 Subject: [PATCH 0739/1534] Remote include tests use temp files now --- test/distributed_exec.jl | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/test/distributed_exec.jl b/test/distributed_exec.jl index 4b33afbb7e918..7aafbc11888c5 100644 --- a/test/distributed_exec.jl +++ b/test/distributed_exec.jl @@ -1571,35 +1571,43 @@ end @test let # creates a new worker in the same folder and tries to include file on both procs + working_directory = pwd() + cd(tempdir()) try - touch("temp.jl") + tmp_file = relpath(mktemp()[1]) proc = addprocs_with_testenv(1) - include("temp.jl") - remotecall_fetch(include, proc[1], "temp.jl") + include(tmp_file) + remotecall_fetch(include, proc[1], tmp_file) rmprocs(proc) - rm("temp.jl") + rm(tmp_file) + cd(working_directory) return true catch e - try rm("temp.jl") end + try rm(tmp_file) end + cd(working_directory) return false end end == true @test let # creates a new worker in the different folder and tries to include file on both procs + working_directory = pwd() + cd(tempdir()) try - mkdir("temp_folder") - touch("temp.jl") - proc = addprocs_with_testenv(1, dir="temp_folder") - include("temp.jl") - remotecall_fetch(include, proc[1], "temp.jl") + tmp_file = relpath(mktemp()[1]) + tmp_dir = relpath(mktempdir()) + proc = addprocs_with_testenv(1, dir=tmp_dir) + include(tmp_file) + remotecall_fetch(include, proc[1], tmp_file) rmprocs(proc) - rm("temp_folder") - rm("temp.jl") + rm(tmp_dir) + rm(tmp_file) + cd(working_directory) return true catch e - try rm("temp_folder") end - try rm("temp.jl") end + try rm(tmp_dir) end + try rm(tmp_file) end + cd(working_directory) return false end end == true From b1f668dfa97e44bbaec4ae1d5796a3f7f422a339 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Sat, 13 May 2017 18:24:01 +0200 Subject: [PATCH 0740/1534] improve cache locality in sparse * dense (#21829) --- base/sparse/linalg.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/sparse/linalg.jl b/base/sparse/linalg.jl index 4689ff521e5c9..4df1c8c50bacf 100644 --- a/base/sparse/linalg.jl +++ b/base/sparse/linalg.jl @@ -61,8 +61,8 @@ for (f, op, transp) in ((:A_mul_B, :identity, false), if β != 1 β != 0 ? scale!(C, β) : fill!(C, zero(eltype(C))) end - for col = 1:A.n - for k = 1:size(C, 2) + for k = 1:size(C, 2) + for col = 1:A.n if $transp tmp = zero(eltype(C)) @inbounds for j = A.colptr[col]:(A.colptr[col + 1] - 1) From 23792943a21e18683ca22e528fda5f33fa780cc9 Mon Sep 17 00:00:00 2001 From: Gollor Date: Sat, 13 May 2017 22:09:05 +0300 Subject: [PATCH 0741/1534] Fixed remote include tests --- test/distributed_exec.jl | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/test/distributed_exec.jl b/test/distributed_exec.jl index 7aafbc11888c5..969caf862e64b 100644 --- a/test/distributed_exec.jl +++ b/test/distributed_exec.jl @@ -1570,44 +1570,38 @@ catch ex end @test let - # creates a new worker in the same folder and tries to include file on both procs - working_directory = pwd() - cd(tempdir()) + # creates a new worker in the same folder and tries to include file + tmp_file = relpath(mktemp()[1]) try - tmp_file = relpath(mktemp()[1]) proc = addprocs_with_testenv(1) include(tmp_file) remotecall_fetch(include, proc[1], tmp_file) rmprocs(proc) rm(tmp_file) - cd(working_directory) return true catch e - try rm(tmp_file) end - cd(working_directory) + println(e) + rm(tmp_file, force=true) return false end end == true @test let - # creates a new worker in the different folder and tries to include file on both procs - working_directory = pwd() - cd(tempdir()) + # creates a new worker in the different folder and tries to include file + tmp_file = relpath(mktemp()[1]) + tmp_dir = relpath(mktempdir()) try - tmp_file = relpath(mktemp()[1]) - tmp_dir = relpath(mktempdir()) proc = addprocs_with_testenv(1, dir=tmp_dir) include(tmp_file) remotecall_fetch(include, proc[1], tmp_file) rmprocs(proc) rm(tmp_dir) rm(tmp_file) - cd(working_directory) return true catch e - try rm(tmp_dir) end - try rm(tmp_file) end - cd(working_directory) + println(e) + rm(tmp_dir, force=true) + rm(tmp_file, force=true) return false end end == true From 50e9d5642501c6808857f197746944d8f3667131 Mon Sep 17 00:00:00 2001 From: Mus M Date: Sat, 13 May 2017 15:52:46 -0400 Subject: [PATCH 0742/1534] update time.jl example to where syntax --- examples/time.jl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/time.jl b/examples/time.jl index 45bd30ff9fce5..2ffb69dcaabbd 100644 --- a/examples/time.jl +++ b/examples/time.jl @@ -16,7 +16,7 @@ const PREFIXES = [ const ZERO_INDEX = 9 const MAX_INDEX = 17 -function show{p}(io::IO, x::TimeDelta{p}) +function show(io::IO, x::TimeDelta{p}) where p k = max(1,min(MAX_INDEX,fld(p,3)+ZERO_INDEX)) r = p-3(k-ZERO_INDEX) prefix = PREFIXES[k] @@ -30,16 +30,16 @@ function show{p}(io::IO, x::TimeDelta{p}) end end -convert{p,q}(::Type{TimeDelta{p}}, x::TimeDelta{q}) = +convert(::Type{TimeDelta{p}}, x::TimeDelta{q}) where {p,q} = TimeDelta{p}(p <= q ? x.v*10^(q-p) : div(x.v,10^(p-q))) -promote_rule{p,q}(::Type{TimeDelta{p}}, ::Type{TimeDelta{q}}) = TimeDelta{min(p,q)} +promote_rule(::Type{TimeDelta{p}}, ::Type{TimeDelta{q}}) where {p,q} = TimeDelta{min(p,q)} --{p}(x::TimeDelta{p}) = TimeDelta{p}(-x.v) -+{p}(x::TimeDelta{p}, y::TimeDelta{p}) = TimeDelta{p}(x.v+y.v) --{p}(x::TimeDelta{p}, y::TimeDelta{p}) = TimeDelta{p}(x.v-y.v) +(-)(x::TimeDelta{p}) where {p} = TimeDelta{p}(-x.v) +(+)(x::TimeDelta{p}, y::TimeDelta{p}) where {p} = TimeDelta{p}(x.v+y.v) +(-)(x::TimeDelta{p}, y::TimeDelta{p}) where {p} = TimeDelta{p}(x.v-y.v) -+(x::TimeDelta, y::TimeDelta) = +(promote(x,y)...) --(x::TimeDelta, y::TimeDelta) = -(promote(x,y)...) +(+)(x::TimeDelta, y::TimeDelta) = +(promote(x,y)...) +(-)(x::TimeDelta, y::TimeDelta) = -(promote(x,y)...) end # module From 7ff63220cc479f7e36ac338d49adcd5c2415f023 Mon Sep 17 00:00:00 2001 From: Gollor Date: Sat, 13 May 2017 23:14:01 +0300 Subject: [PATCH 0743/1534] Remote include tests close io streams --- test/distributed_exec.jl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/distributed_exec.jl b/test/distributed_exec.jl index 969caf862e64b..cd531c6c3e15e 100644 --- a/test/distributed_exec.jl +++ b/test/distributed_exec.jl @@ -1571,7 +1571,9 @@ end @test let # creates a new worker in the same folder and tries to include file - tmp_file = relpath(mktemp()[1]) + tmp_file, temp_file_stream = mktemp() + close(temp_file_stream) + tmp_file = relpath(tmp_file) try proc = addprocs_with_testenv(1) include(tmp_file) @@ -1588,7 +1590,9 @@ end == true @test let # creates a new worker in the different folder and tries to include file - tmp_file = relpath(mktemp()[1]) + tmp_file, temp_file_stream = mktemp() + close(temp_file_stream) + tmp_file = relpath(tmp_file) tmp_dir = relpath(mktempdir()) try proc = addprocs_with_testenv(1, dir=tmp_dir) From adcf591877ef89fa3f6b3b548b35619338ddf30c Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sat, 13 May 2017 15:24:56 -0700 Subject: [PATCH 0744/1534] Add NEWS.md entry for `invoke` keyword argument support (#20345). (#21834) --- NEWS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS.md b/NEWS.md index ada6ec21f38b0..88e0856e1b9e8 100644 --- a/NEWS.md +++ b/NEWS.md @@ -388,6 +388,8 @@ Library improvements * A new `@macroexpand` macro was added as a convenient alternative to the `macroexpand` function ([#18660]). + * `invoke` now supports keyword arguments ([#20345]). + * A new `ConjArray` type was added, as a wrapper type for lazy complex conjugation of arrays. Currently, it is used by default for the new `RowVector` type only, and enforces that both `transpose(vec)` and `ctranspose(vec)` are views not copies ([#20047]). @@ -587,6 +589,7 @@ Deprecated or removed [#20268]: https://github.com/JuliaLang/julia/issues/20268 [#20321]: https://github.com/JuliaLang/julia/issues/20321 [#20327]: https://github.com/JuliaLang/julia/issues/20327 +[#20345]: https://github.com/JuliaLang/julia/issues/20345 [#20403]: https://github.com/JuliaLang/julia/issues/20403 [#20404]: https://github.com/JuliaLang/julia/issues/20404 [#20406]: https://github.com/JuliaLang/julia/issues/20406 From 07c4dae5cae9a1e6a3747a709c6afa10171876a9 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sat, 13 May 2017 15:25:15 -0700 Subject: [PATCH 0745/1534] Add NEWS.md entry for getindex(::AbstractString, ::AbstractVector) signature tightening (#20248). (#21835) --- NEWS.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/NEWS.md b/NEWS.md index 88e0856e1b9e8..8804978349373 100644 --- a/NEWS.md +++ b/NEWS.md @@ -244,6 +244,14 @@ This section lists changes that do not have deprecation warnings. * The `count` function no longer sums non-boolean values ([#20404]) + * The generic `getindex(::AbstractString, ::AbstractVector)` method's signature has been + tightened to `getindex(::AbstractString, ::AbstractVector{<:Integer})`. Consequently, + indexing into `AbstractString`s with non-`AbstractVector{<:Integer}` `AbstractVector`s + now throws a `MethodError` in the absence of an appropriate specialization. + (Previously such cases failed less explicitly with the exception of + `AbstractVector{Bool}`, which now throws an `ArgumentError` noting that + logical indexing into strings is not supported.) ([#20248]) + * Bessel, Hankel, Airy, error, Dawson, eta, zeta, digamma, inverse digamma, trigamma, and polygamma special functions have been moved from Base to the @@ -585,6 +593,7 @@ Deprecated or removed [#20079]: https://github.com/JuliaLang/julia/issues/20079 [#20164]: https://github.com/JuliaLang/julia/issues/20164 [#20228]: https://github.com/JuliaLang/julia/issues/20228 +[#20248]: https://github.com/JuliaLang/julia/issues/20248 [#20249]: https://github.com/JuliaLang/julia/issues/20249 [#20268]: https://github.com/JuliaLang/julia/issues/20268 [#20321]: https://github.com/JuliaLang/julia/issues/20321 From a40d1be3ab93846a8df7032540ee190384a1cfac Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sat, 13 May 2017 15:25:38 -0700 Subject: [PATCH 0746/1534] Add NEWS.md entry re. raising one or negative one to a negative integer power (#18342). (#21836) --- NEWS.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/NEWS.md b/NEWS.md index 8804978349373..53a4c26c880f3 100644 --- a/NEWS.md +++ b/NEWS.md @@ -394,6 +394,12 @@ Library improvements * A new `Dates.Time` type was added that supports representing the time of day with up to nanosecond resolution ([#12274]). + * Raising one or negative one to a negative integer power formerly threw a `DomainError`. + One raised to any negative integer power now yields one, negative one raised to any + negative even integer power now yields one, and negative one raised to any negative + odd integer power now yields negative one. Similarly, raising `true` to any negative + integer power now yields `true` rather than throwing a `DomainError` ([#18342]). + * A new `@macroexpand` macro was added as a convenient alternative to the `macroexpand` function ([#18660]). * `invoke` now supports keyword arguments ([#20345]). @@ -521,6 +527,7 @@ Deprecated or removed [#18251]: https://github.com/JuliaLang/julia/issues/18251 [#18330]: https://github.com/JuliaLang/julia/issues/18330 [#18339]: https://github.com/JuliaLang/julia/issues/18339 +[#18342]: https://github.com/JuliaLang/julia/issues/18342 [#18346]: https://github.com/JuliaLang/julia/issues/18346 [#18442]: https://github.com/JuliaLang/julia/issues/18442 [#18444]: https://github.com/JuliaLang/julia/issues/18444 From 1571b62c07a49b8e68c3807ab7c9161fd57e2323 Mon Sep 17 00:00:00 2001 From: Mohamed Date: Sun, 14 May 2017 02:30:02 +0300 Subject: [PATCH 0747/1534] clearing the meaning of comment (#21741) * clearing the meaning of comment * correct back file name. --- etc/juliarc.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/juliarc.jl b/etc/juliarc.jl index 5b218a1532a69..3993e62867710 100644 --- a/etc/juliarc.jl +++ b/etc/juliarc.jl @@ -1,3 +1,3 @@ # This file should contain site-specific commands to be executed on Julia startup -# Users should store their own personal commands in homedir(), in a file named .juliarc.jl +# Users may store their own personal commands in the user home directory `homedir()`, in a file named `.juliarc.jl` From dcffef03594779402bb5c2666fbcf24b4438adba Mon Sep 17 00:00:00 2001 From: Samuel Powell Date: Sun, 14 May 2017 00:42:44 +0100 Subject: [PATCH 0748/1534] Update ARM README (#21737) * Update ARM README * Document improved ARM support * Fix wording of file output * Clarify build dependencies * Builds are parallel, not multi-threaded * Split known-good devices into architectures, update AArch64 --- README.arm.md | 141 ++++++++++++++++++++++++-------------------------- 1 file changed, 68 insertions(+), 73 deletions(-) diff --git a/README.arm.md b/README.arm.md index 326e761fa52a1..b4320738be8c8 100644 --- a/README.arm.md +++ b/README.arm.md @@ -1,32 +1,20 @@ -# Julia binaries for ARM +# Julia on ARM (Linux) -[Nightly builds](https://status.julialang.org/download/linux-arm) are -available for ARMv7-A. - -# Hardware requirements - -Julia requires at least `armv6` and `vfpv2` instruction sets. It's recommended -to use at least `armv7-a`. `armv5` or soft float are not supported. +Julia fully supports ARMv8 (AArch64) processors, and supports ARMv7 and ARMv6 +(AArch32) with some caveats. This file provides general guidelines for compilation, +in addition to instructions for specific devices. -# Building Julia on ARM +A list of [known issues](https://github.com/JuliaLang/julia/labels/arm) for ARM is +available. If you encounter difficulties, please create an issue including the output +from `cat /proc/cpuinfo`. -Julia has been compiled on several ARMv7 / Cortex A15 Samsung -Chromebooks running Ubuntu Linux under Crouton, Raspberry Pi systems -and Odroid boards. This is a work in progress - several tests are -known to fail, and backtraces are not available. -Julia on ARM can be built by simply typing `make`, which will download all -the relevant libraries. This is the *recommended* way, and it will take a -few hours. +## Building Julia -If you get SIGILL during sysimg.o creation, it is likely that your cpu -does not support VFP. File an issue on the Julia issue tracker with -the contents of /proc/cpuinfo. +In most cases, Julia can be successfully built by following the platform independent +[build instructions](https://github.com/JuliaLang/julia/blob/master/README.md). -This is the list of known issues on ARM: - [https://github.com/JuliaLang/julia/labels/arm](https://github.com/JuliaLang/julia/labels/arm) - -# Build dependencies +### Build dependencies We recommend using at least Ubuntu 14.04 and gcc 4.8, which is part of the standard `build-essentials`. @@ -45,7 +33,7 @@ override USE_SYSTEM_MPFR=1 override USE_SYSTEM_ARPACK=1 ```` -The following command will install all the necessary libraries on Ubuntu. +The following command will install all the necessary libraries on Ubuntu: ```` sudo apt-get install libblas3gf liblapack3gf libarpack2 libfftw3-dev libgmp3-dev \ @@ -53,48 +41,60 @@ sudo apt-get install libblas3gf liblapack3gf libarpack2 libfftw3-dev libgmp3-dev g++-4.8 gfortran libgfortran3 m4 libedit-dev ```` -Note that OpenBLAS only supports ARMv7. For older ARM variants, using the reference BLAS -may be the simplest thing to do. +If you run into issues building LLVM, see [these notes](http://llvm.org/docs/HowToBuildOnARM.html). + + +## 32-bit (ARMv6, ARMv7) -# ARM specific build problems +Julia has been successfully compiled on several variants of the following ARMv6 & ARMv7 devices: -If you run into issues building LLVM, see these notes: -[http://llvm.org/docs/HowToBuildOnARM.html](http://llvm.org/docs/HowToBuildOnARM.html) +* ARMv7 / Cortex A15 Samsung Chromebooks running Ubuntu Linux under Crouton; +* [Raspberry Pi](https://www.raspberrypi.org). +* [Odroid](http://www.hardkernel.com/main/main.php). + + +Julia requires at least the `armv6` and `vfpv2` instruction sets. It's recommended to use `armv7-a`. +`armv5` or soft float are not supported. + +### Binaries + +[Nightly builds](https://status.julialang.org/download/linux-arm) are +available for ARMv7-A. -## Raspberry Pi 1 / Raspberry Pi Zero +### Device specific instructions -Note: These chips use ARMv6, which is not well supported at the moment. However it is -possible to get a working Julia build. +#### Raspberry Pi 1 / Raspberry Pi Zero -The Raspberry Pi ARM CPU type is not detected by LLVM. Before starting the -build, it is recommended to explicitly set the CPU target by adding the -following to `Make.user`: +The type of ARM CPU used in the Raspberry Pi is not detected by LLVM. Explicitly set the +CPU target by adding the following to `Make.user`: ```` JULIA_CPU_TARGET=arm1176jzf-s ```` -It is also preferable to use various system provided dependencies on -ARMv6 as described in [Build Dependencies](#build-dependencies). +It is preferable to use various system provided dependencies on ARMv6 as described in +[Build Dependencies](#build-dependencies). -You may need to increase the swap file size: edit the `/etc/dphys-swapfile`, changing the line +To complete the build, you may need to increase the swap file size. To do so, edit +`/etc/dphys-swapfile`, changing the line: CONF_SWAPSIZE=100 -to +to: CONF_SWAPSIZE=512 -Then restart the swapfile service: +before restarting the swapfile service: sudo /etc/init.d/dphys-swapfile stop sudo /etc/init.d/dphys-swapfile start -## Raspberry Pi 2 +#### Raspberry Pi 2 -For Raspberry Pi 2, which is ARMv7, the default build should work. However, the -CPU type is also not detected by LLVM. Fix this by adding -`JULIA_CPU_TARGET=cortex-a7` to `Make.user`. +The type of ARM CPU used in the Raspberry Pi 2 is not detected by LLVM. Explicitly set the +CPU target by adding the following to `Make.user`: + +```JULIA_CPU_TARGET=cortex-a7``` Depending on the exact compiler and distribution, there might be a build failure due to unsupported inline assembly. In that case, add `MARCH=armv7-a` to @@ -102,7 +102,7 @@ due to unsupported inline assembly. In that case, add `MARCH=armv7-a` to If building LLVM fails, you can download binaries from the LLVM website: -1. Download the [LLVM 3.7.0 binaries for ARMv7a] (http://llvm.org/releases/3.7.0/clang+llvm-3.7.0-armv7a-linux-gnueabihf.tar.xz) and extract them in a local directory. +1. Download the [LLVM 3.9.0 binaries for ARMv7a] (http://llvm.org/releases/3.9.0/clang+llvm-3.9.0-armv7a-linux-gnueabihf.tar.xz) and extract them in a local directory. 2. Add the following to `Make.user` (adjusting the path to the `llvm-config` binary): ``` @@ -112,9 +112,9 @@ If building LLVM fails, you can download binaries from the LLVM website: Please do let us know if you had to download a pre-built LLVM in [#10235](https://github.com/JuliaLang/julia/issues/10235). -## Chromebook +#### Chromebook -On Chromebooks, you have to first install Crouton. If you do not have +On Chromebooks, you have to first install Crouton. If you do not have an Ubuntu chroot running on your Chromebook using Crouton, you can do so by following these tutorials. @@ -125,47 +125,42 @@ These tutorials will end up installing Ubuntu 12.04, and you have to upgrade to Ubuntu 14.04, or install Ubuntu 14.04 from scratch by finding appropriate `crouton` help. -## Scaleway cloud hosted ARM servers +#### Scaleway cloud hosted ARM servers On the current [Scaleway](http://scaleway.com) ARM servers, the Julia build works out of the box. -## nVidia Jetson TX2 - -Julia builds and runs on the [nVidia Jetson TX2](http://www.nvidia.com/object/embedded-systems-dev-kits-modules.html) platform with minimal configuration changes. A full multi-threaded build, including LLVM, will complete in around two hours. All tests pass and CUDA functionality is available through, e.g., [CUDAdrv](https://github.com/JuliaGPU/CUDAdrv.jl). +## AArch64 (ARMv8) -Starting from the default configuration flashed by [Jetpack 3.0](https://developer.nvidia.com/embedded/jetpack): +Julia has been successfully built on the following ARMv8 devices: -``` -sudo apt-get install libssl-dev -``` +* [nVidia Jetson TX1 & TX2](http://www.nvidia.com/object/embedded-systems-dev-kits-modules.html); +* [X-Gene 1](https://www.apm.com/products/data-center/x-gene-family/x-gene/); +* [Overdrive 3000](https://softiron.com/products/overdrive-3000/); +* [Cavium ThunderX](http://www.cavium.com/ThunderX_ARM_Processors.html) on [packet.net](https://www.packet.net). -### Julia 0.5.1 - -The easiest method to build Julia 0.5.1 is to use system provided versions of BLAS and LAPACK: - -``` -sudo apt-get install libopenblas-dev liblapack-dev -``` - -Configure Make.user as follows: +Compilation on `ARMv8-A` requires that `Make.user` is configured as follows: ``` MARCH=armv8-a -JULIA_CPU_TARGET=cortex-a57 -override USE_SYSTEM_BLAS=1 -override USE_SYSTEM_LAPACK=1 ``` -Note that package manager functions fail with an error regarding SSL certificates. This can be overcome by following the instructions in [this comment](https://github.com/JuliaLang/julia/issues/13399#issuecomment-182018321). +### Device specific instructions + +#### nVidia Jetson TX2 -### Julia 0.6 beta +Julia builds and runs on the [nVidia Jetson TX2](http://www.nvidia.com/object/embedded-systems-dev-kits-modules.html) +platform with minimal configuration changes. -Configure Make.user as follows: +After configuring `Make.user` as per the `AArch64` instructions in this document, +follow the general [build instructions](https://github.com/JuliaLang/julia/blob/master/README.md). +The majority of the build dependencies specified in the instructions are installed by +the default configuration flashed by [Jetpack 3.0](https://developer.nvidia.com/embedded/jetpack). The remaining tools can be installed by issuing the following command: ``` -MARCH=armv8-a -JULIA_CPU_TARGET=cortex-a57 +sudo apt-get install gfortran wget cmake ``` -No further changes are required. +A full parallel build, including LLVM, +will complete in around two hours. All tests pass and CUDA functionality is available +through, e.g., [CUDAdrv](https://github.com/JuliaGPU/CUDAdrv.jl). From 7ac51556d83aa4b59f1b0ec62f4db8b23e68b929 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sat, 13 May 2017 18:19:06 -0700 Subject: [PATCH 0749/1534] Add NEWS.md entry for new polly command-line flag (#18159). (#21841) --- NEWS.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/NEWS.md b/NEWS.md index 53a4c26c880f3..e205b35f7af06 100644 --- a/NEWS.md +++ b/NEWS.md @@ -498,6 +498,14 @@ Deprecated or removed * `bitbroadcast` has been deprecated in favor of `broadcast`, which now produces a `BitArray` instead of `Array{Bool}` for functions yielding a boolean result ([#19771]). +Command-line option changes +--------------------------- + + * In `polly` builds (`USE_POLLY := 1`), the new flag `--polly={yes|no}` controls whether + `@polly` declarations are respected. (With `--polly=no`, `@polly` declarations are + ignored.) This flag is also available in non-`polly` builds (`USE_POLLY := 0`), + but has no effect ([#18159]). + [#265]: https://github.com/JuliaLang/julia/issues/265 [#4615]: https://github.com/JuliaLang/julia/issues/4615 @@ -524,6 +532,7 @@ Deprecated or removed [#17758]: https://github.com/JuliaLang/julia/issues/17758 [#17785]: https://github.com/JuliaLang/julia/issues/17785 [#18050]: https://github.com/JuliaLang/julia/issues/18050 +[#18159]: https://github.com/JuliaLang/julia/issues/18159 [#18251]: https://github.com/JuliaLang/julia/issues/18251 [#18330]: https://github.com/JuliaLang/julia/issues/18330 [#18339]: https://github.com/JuliaLang/julia/issues/18339 From b45cc9e87f1c1445b62f7e497317189ee417355c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Sun, 14 May 2017 03:22:26 +0200 Subject: [PATCH 0750/1534] Fix sinpi and cospi with Irrational arguments (#21781) * Fix sinpi and cospi with Irrational arguments * Rework the fix to sinpi/cospi with Irrational argument --- base/special/trig.jl | 18 +++++++++++------- test/math.jl | 13 +++++++++++++ 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/base/special/trig.jl b/base/special/trig.jl index 4b6039da0ff69..4e19371b65931 100644 --- a/base/special/trig.jl +++ b/base/special/trig.jl @@ -132,9 +132,9 @@ function sinpi(x::T) where T<:AbstractFloat end end -# Rationals and other Real types -function sinpi(x::T) where T<:Real - Tf = typeof(float(x)) +# Integers and Rationals +function sinpi(x::T) where T<:Union{Integer,Rational} + Tf = float(T) if !isfinite(x) throw(DomainError()) end @@ -191,8 +191,8 @@ function cospi(x::T) where T<:AbstractFloat end end -# Rationals and other Real types -function cospi(x::T) where T<:Real +# Integers and Rationals +function cospi(x::T) where T<:Union{Integer,Rational} if !isfinite(x) throw(DomainError()) end @@ -217,6 +217,8 @@ end sinpi(x::Integer) = x >= 0 ? zero(float(x)) : -zero(float(x)) cospi(x::Integer) = isodd(x) ? -one(float(x)) : one(float(x)) +sinpi(x::Real) = sinpi(float(x)) +cospi(x::Real) = cospi(float(x)) function sinpi(z::Complex{T}) where T F = float(T) @@ -292,7 +294,8 @@ Compute ``\\sin(\\pi x) / (\\pi x)`` if ``x \\neq 0``, and ``1`` if ``x = 0``. """ sinc(x::Number) = x==0 ? one(x) : oftype(x,sinpi(x)/(pi*x)) sinc(x::Integer) = x==0 ? one(x) : zero(x) -sinc(x::Complex{<:Integer}) = sinc(float(x)) +sinc(x::Complex{<:AbstractFloat}) = x==0 ? one(x) : oftype(x, sinpi(x)/(pi*x)) +sinc(x::Complex) = sinc(float(x)) sinc(x::Real) = x==0 ? one(x) : isinf(x) ? zero(x) : sinpi(x)/(pi*x) """ @@ -303,7 +306,8 @@ Compute ``\\cos(\\pi x) / x - \\sin(\\pi x) / (\\pi x^2)`` if ``x \\neq 0``, and """ cosc(x::Number) = x==0 ? zero(x) : oftype(x,(cospi(x)-sinpi(x)/(pi*x))/x) cosc(x::Integer) = cosc(float(x)) -cosc(x::Complex{<:Integer}) = cosc(float(x)) +cosc(x::Complex{<:AbstractFloat}) = x==0 ? zero(x) : oftype(x,(cospi(x)-sinpi(x)/(pi*x))/x) +cosc(x::Complex) = cosc(float(x)) cosc(x::Real) = x==0 || isinf(x) ? zero(x) : (cospi(x)-sinpi(x)/(pi*x))/x for (finv, f) in ((:sec, :cos), (:csc, :sin), (:cot, :tan), diff --git a/test/math.jl b/test/math.jl index 04ce580e47346..136c50f98463c 100644 --- a/test/math.jl +++ b/test/math.jl @@ -379,6 +379,19 @@ end @test cosc(Inf) == 0 end +@testset "Irrational args to sinpi/cospi/sinc/cosc" begin + for x in (pi, e, golden) + @test sinpi(x) ≈ Float64(sinpi(big(x))) + @test cospi(x) ≈ Float64(cospi(big(x))) + @test sinc(x) ≈ Float64(sinc(big(x))) + @test cosc(x) ≈ Float64(cosc(big(x))) + @test sinpi(complex(x, x)) ≈ Complex{Float64}(sinpi(complex(big(x), big(x)))) + @test cospi(complex(x, x)) ≈ Complex{Float64}(cospi(complex(big(x), big(x)))) + @test sinc(complex(x, x)) ≈ Complex{Float64}(sinc(complex(big(x), big(x)))) + @test cosc(complex(x, x)) ≈ Complex{Float64}(cosc(complex(big(x), big(x)))) + end +end + @testset "trig function type stability" begin @testset "$T $f" for T = (Float32,Float64,BigFloat), f = (sind,cosd,sinpi,cospi) @test Base.return_types(f,Tuple{T}) == [T] From 54bbf1985a48d65a5077adf171592e45f910269a Mon Sep 17 00:00:00 2001 From: Mus M Date: Sat, 13 May 2017 21:25:36 -0400 Subject: [PATCH 0751/1534] Update ModInts.jl example to new syntax (#21839) * Update ModInts.jl * Update ModInts.jl --- examples/ModInts.jl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/ModInts.jl b/examples/ModInts.jl index a6894cd9bfa76..59fde002d26c5 100644 --- a/examples/ModInts.jl +++ b/examples/ModInts.jl @@ -7,21 +7,21 @@ import Base: +, -, *, /, inv struct ModInt{n} <: Integer k::Int - ModInt{n}(k) where n = new(mod(k,n)) + ModInt{n}(k) where {n} = new(mod(k,n)) end -Base.show{n}(io::IO, k::ModInt{n}) = +Base.show(io::IO, k::ModInt{n}) where {n} = print(io, get(io, :compact, false) ? k.k : "$(k.k) mod $n") -+{n}(a::ModInt{n}, b::ModInt{n}) = ModInt{n}(a.k+b.k) --{n}(a::ModInt{n}, b::ModInt{n}) = ModInt{n}(a.k-b.k) -*{n}(a::ModInt{n}, b::ModInt{n}) = ModInt{n}(a.k*b.k) --{n}(a::ModInt{n}) = ModInt{n}(-a.k) +(+)(a::ModInt{n}, b::ModInt{n}) where {n} = ModInt{n}(a.k+b.k) +(-)(a::ModInt{n}, b::ModInt{n}) where {n} = ModInt{n}(a.k-b.k) +(*)(a::ModInt{n}, b::ModInt{n}) where {n} = ModInt{n}(a.k*b.k) +(-)(a::ModInt{n}) where {n} = ModInt{n}(-a.k) -inv{n}(a::ModInt{n}) = ModInt{n}(invmod(a.k, n)) -/{n}(a::ModInt{n}, b::ModInt{n}) = a*inv(b) # broaden for non-coprime? +inv(a::ModInt{n}) where {n} = ModInt{n}(invmod(a.k, n)) +(/)(a::ModInt{n}, b::ModInt{n}) where {n} = a*inv(b) # broaden for non-coprime? -Base.promote_rule{n}(::Type{ModInt{n}}, ::Type{Int}) = ModInt{n} -Base.convert{n}(::Type{ModInt{n}}, i::Int) = ModInt{n}(i) +Base.promote_rule(::Type{ModInt{n}}, ::Type{Int}) where {n} = ModInt{n} +Base.convert(::Type{ModInt{n}}, i::Int) where {n} = ModInt{n}(i) end # module From 02f383bae8332c7f74b3c8559e9706dd79146a53 Mon Sep 17 00:00:00 2001 From: Mus M Date: Sat, 13 May 2017 21:26:08 -0400 Subject: [PATCH 0752/1534] update ndgrid.jl to where sytnax (#21840) --- examples/ndgrid.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/ndgrid.jl b/examples/ndgrid.jl index 3bce2fce36d50..fc2e6bad8a203 100644 --- a/examples/ndgrid.jl +++ b/examples/ndgrid.jl @@ -2,7 +2,7 @@ ndgrid(v::AbstractVector) = copy(v) -function ndgrid{T}(v1::AbstractVector{T}, v2::AbstractVector{T}) +function ndgrid(v1::AbstractVector{T}, v2::AbstractVector{T}) where T m, n = length(v1), length(v2) v1 = reshape(v1, m, 1) v2 = reshape(v2, 1, n) @@ -15,7 +15,7 @@ function ndgrid_fill(a, v, s, snext) end end -function ndgrid{T}(vs::AbstractVector{T}...) +function ndgrid(vs::AbstractVector{T}...) where T n = length(vs) sz = map(length, vs) out = ntuple(i->Array{T}(sz), n) @@ -32,15 +32,15 @@ end meshgrid(v::AbstractVector) = meshgrid(v, v) -function meshgrid{T}(vx::AbstractVector{T}, vy::AbstractVector{T}) +function meshgrid(vx::AbstractVector{T}, vy::AbstractVector{T}) where T m, n = length(vy), length(vx) vx = reshape(vx, 1, n) vy = reshape(vy, m, 1) (repmat(vx, m, 1), repmat(vy, 1, n)) end -function meshgrid{T}(vx::AbstractVector{T}, vy::AbstractVector{T}, - vz::AbstractVector{T}) +function meshgrid(vx::AbstractVector{T}, vy::AbstractVector{T}, + vz::AbstractVector{T}) where T m, n, o = length(vy), length(vx), length(vz) vx = reshape(vx, 1, n, 1) vy = reshape(vy, m, 1, 1) From f55543afd7e900615b8b910fe250364ac5a3acd8 Mon Sep 17 00:00:00 2001 From: Mus M Date: Sat, 13 May 2017 21:27:33 -0400 Subject: [PATCH 0753/1534] Update sysinfo with some docs strings (#21843) * Update sysinfo with some docs strings * Update sysinfo.jl * Update sysinfo.jl * Update sysinfo.jl --- base/sysinfo.jl | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/base/sysinfo.jl b/base/sysinfo.jl index fb9119dd668b5..e930dddb25703 100644 --- a/base/sysinfo.jl +++ b/base/sysinfo.jl @@ -2,19 +2,19 @@ module Sys -export CPU_CORES, - WORD_SIZE, - ARCH, - MACHINE, - KERNEL, - JIT, - cpu_info, - cpu_name, - cpu_summary, - uptime, - loadavg, - free_memory, - total_memory +export CPU_CORES, + WORD_SIZE, + ARCH, + MACHINE, + KERNEL, + JIT, + cpu_info, + cpu_name, + cpu_summary, + uptime, + loadavg, + free_memory, + total_memory import ..Base: show @@ -141,12 +141,22 @@ function cpu_info() return cpus end +""" + Sys.uptime() + +Gets the current system uptime in seconds. +""" function uptime() uptime_ = Ref{Float64}() Base.uv_error("uv_uptime",ccall(:uv_uptime, Int32, (Ptr{Float64},), uptime_)) return uptime_[] end +""" + Sys.loadavg() + +Get the load average. See: https://en.wikipedia.org/wiki/Load_(computing). +""" function loadavg() loadavg_ = Vector{Float64}(3) ccall(:uv_loadavg, Void, (Ptr{Float64},), loadavg_) @@ -159,7 +169,7 @@ total_memory() = ccall(:uv_get_total_memory, UInt64, ()) """ Sys.get_process_title() -Get the process title. On some systems, will always return empty string. (not exported) +Get the process title. On some systems, will always return an empty string. """ function get_process_title() buf = zeros(UInt8, 512) @@ -171,7 +181,7 @@ end """ Sys.set_process_title(title::AbstractString) -Set the process title. No-op on some operating systems. (not exported) +Set the process title. No-op on some operating systems. """ function set_process_title(title::AbstractString) err = ccall(:uv_set_process_title, Cint, (Cstring,), title) @@ -189,7 +199,7 @@ else windows_version() = (0, 0) end """ - windows_version() + Sys.windows_version() Returns the version number for the Windows NT Kernel as a (major, minor) pair, or `(0, 0)` if this is not running on Windows. From 9b428dc2f9758a026dd3f9c358b3718988f92b57 Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Sat, 13 May 2017 23:24:28 -0700 Subject: [PATCH 0754/1534] Make @__DIR__ return pwd() when being run without a file (#21759) --- NEWS.md | 4 ++++ base/loading.jl | 4 ++-- test/loading.jl | 6 ++++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index e205b35f7af06..bdf591ec550f5 100644 --- a/NEWS.md +++ b/NEWS.md @@ -17,6 +17,10 @@ This section lists changes that do not have deprecation warnings. * `ntuple(f, n::Integer)` throws `ArgumentError` if `n` is negative. Previously an empty tuple was returned ([#21697]). + * `@__DIR__` returns the current working directory rather than `nothing` when not run + from a file ([#21759]). + + Library improvements -------------------- diff --git a/base/loading.jl b/base/loading.jl index 2674b3dfd27f1..e43e98247f6bb 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -529,7 +529,7 @@ end function source_dir() p = source_path(nothing) - p === nothing ? p : dirname(p) + p === nothing ? pwd() : dirname(p) end """ @@ -545,7 +545,7 @@ macro __FILE__() source_path() end @__DIR__ -> AbstractString `@__DIR__` expands to a string with the directory part of the absolute path of the file -containing the macro. Returns `nothing` if run from a REPL or an empty string if +containing the macro. Returns the current working directory if run from a REPL or if evaluated by `julia -e `. """ macro __DIR__() source_dir() end diff --git a/test/loading.jl b/test/loading.jl index 618700d228411..80f14a8ba08db 100644 --- a/test/loading.jl +++ b/test/loading.jl @@ -14,6 +14,12 @@ include_string_test_func = include_string("include_string_test() = @__FILE__", t @test isdir(@__DIR__) @test @__DIR__() == dirname(@__FILE__) +let exename = `$(Base.julia_cmd()) --precompiled=yes --startup-file=no` + wd = sprint(show, pwd()) + @test readchomp(`$exename -E "@__DIR__" -i`) == wd + @test readchomp(`$exename -E "cd(()->eval(:(@__DIR__)), tempdir())" -i`) != wd + @test readchomp(`$exename -E "@__DIR__"`) == wd # non-interactive +end # Issue #5789 and PR #13542: mktempdir() do dir From 177156ca8b25e28cc21508c150db0b92c1a9f010 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Sat, 13 May 2017 07:11:59 -0400 Subject: [PATCH 0755/1534] Build release tags on Travis this should hopefully result in automatic docs deployment to release-0.6 run travis on release tags but not pre-release tags --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 710b2662d7093..c6cc7166c9918 100644 --- a/.travis.yml +++ b/.travis.yml @@ -47,6 +47,7 @@ branches: only: - master - /^release-.*/ + - /^v\d+\.\d+\.\d+$/ notifications: email: false irc: From e327b390a0b2f687d0ab328305c5b2f6350a417a Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Sat, 13 May 2017 06:59:48 -0400 Subject: [PATCH 0756/1534] Fix doctest line numbers --- base/channels.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/channels.jl b/base/channels.jl index 646917b603b3c..95af3a85411ff 100644 --- a/base/channels.jl +++ b/base/channels.jl @@ -194,8 +194,8 @@ julia> take!(c) julia> put!(c,1); ERROR: foo Stacktrace: - [1] check_channel_state(::Channel{Any}) at ./channels.jl:126 - [2] put!(::Channel{Any}, ::Int64) at ./channels.jl:256 + [1] check_channel_state(::Channel{Any}) at ./channels.jl:131 + [2] put!(::Channel{Any}, ::Int64) at ./channels.jl:261 ``` """ function bind(c::Channel, task::Task) From e1f36c3346e006fc2180218b5f9dfc48954bc718 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Sat, 13 May 2017 16:46:13 -0700 Subject: [PATCH 0757/1534] Upgrade Documenter to v0.10.2 --- doc/REQUIRE | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/REQUIRE b/doc/REQUIRE index 165c8fcb20b26..e8869bde5e55a 100644 --- a/doc/REQUIRE +++ b/doc/REQUIRE @@ -1,3 +1,3 @@ -Compat 0.24.0 0.24.0+ +Compat 0.25.0 0.25.0+ DocStringExtensions 0.3.3 0.3.3+ -Documenter 0.10.0 0.10.0+ +Documenter 0.10.2 0.10.2+ From f6bd5fe6795e5e1848b52df4ad39d131536c6a64 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 14 May 2017 03:55:56 -0700 Subject: [PATCH 0758/1534] Add NEWS.md entry for dep of unintended zeros/ones methods (#21183). (#21844) --- NEWS.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/NEWS.md b/NEWS.md index bdf591ec550f5..ef5bc48cefd9b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -474,6 +474,11 @@ Deprecated or removed * The two-argument forms of `map` (`map!(f, A)`) and `asyncmap!` (`asyncmap!(f, A)`) have been deprecated in anticipation of future semantic changes ([#19721]). + * `zeros` and `ones` methods accepting an element type as the first argument and an + array as the second argument, for example `zeros(Float64, [1, 2, 3])`, have been + deprecated in favor of equivalent methods with the second argument instead the + size of the array, for example `zeros(Float64, size([1, 2, 3]))` ([#21183]). + * `isimag` has been deprecated ([#19949]). * The tuple-of-types form of `invoke`, `invoke(f, (types...), ...)`, has been deprecated @@ -630,3 +635,4 @@ Command-line option changes [#20543]: https://github.com/JuliaLang/julia/issues/20543 [#20609]: https://github.com/JuliaLang/julia/issues/20609 [#20889]: https://github.com/JuliaLang/julia/issues/20889 +[#21183]: https://github.com/JuliaLang/julia/issues/21183 From bd28e0238e3c703df229e444740136c9d3793b4b Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Sun, 14 May 2017 12:58:51 +0200 Subject: [PATCH 0759/1534] add two refs to file docs (#21845) --- base/path.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/base/path.jl b/base/path.jl index df03c9def77b5..c891083fce330 100644 --- a/base/path.jl +++ b/base/path.jl @@ -139,6 +139,8 @@ Get the directory part of a path. ```jldoctest julia> dirname("/home/myuser") "/home" + +See also: [`basename`](@ref) ``` """ dirname(path::AbstractString) = splitdir(path)[1] @@ -152,6 +154,8 @@ Get the file name part of a path. julia> basename("/home/myuser/example.jl") "example.jl" ``` + +See also: [`dirname`](@ref) """ basename(path::AbstractString) = splitdir(path)[2] From 320892a129ea35a9594d9c9cd68ec8b4f40856d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Sun, 14 May 2017 13:07:27 +0200 Subject: [PATCH 0760/1534] Fix log1p with complex Irrational argument (#21784) --- base/complex.jl | 2 +- test/complex.jl | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/base/complex.jl b/base/complex.jl index f6d4adf2ddd90..a7faac11f89ef 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -546,7 +546,7 @@ function log1p(z::Complex{T}) where T # This is based on a well-known trick for log1p of real z, # allegedly due to Kahan, only modified to handle real(u) <= 0 # differently to avoid inaccuracy near z==-2 and for correct branch cut - u = float(one(T)) + z + u = one(float(T)) + z u == 1 ? convert(typeof(u), z) : real(u) <= 0 ? log(u) : log(u)*z/(u-1) elseif isnan(zr) Complex(zr, zr) diff --git a/test/complex.jl b/test/complex.jl index ccf71b3c1528f..35852030e60ae 100644 --- a/test/complex.jl +++ b/test/complex.jl @@ -948,5 +948,6 @@ end for x in (pi, e, catalan) # No need to test all of them @test typeof(Complex(x, x)) == Complex{typeof(x)} @test exp(complex(x, x)) ≈ exp(x) * cis(x) + @test log1p(complex(x, x)) ≈ log(1 + complex(x, x)) end end From bfd5a0ecb626c28a26ffd103ab39ba31a8437983 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 14 May 2017 04:09:15 -0700 Subject: [PATCH 0761/1534] Add another PR number for deprecation of `_` as an rvalue (#20328). (#21852) --- NEWS.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index ef5bc48cefd9b..f918243c89d2a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -114,7 +114,8 @@ Language changes every function call, operator, and assignment in an expression ([#20321]). * The identifier `_` can be assigned, but accessing its value is deprecated, - allowing this syntax to be used in the future for discarding values ([#9343], [#18251]). + allowing this syntax to be used in the future for discarding values ([#9343], + [#18251], [#20328]). * The `typealias` keyword is deprecated, and should be replaced with `Vector{T} = Array{T,1}` or a `const` assignment ([#20500]). @@ -623,6 +624,7 @@ Command-line option changes [#20268]: https://github.com/JuliaLang/julia/issues/20268 [#20321]: https://github.com/JuliaLang/julia/issues/20321 [#20327]: https://github.com/JuliaLang/julia/issues/20327 +[#20328]: https://github.com/JuliaLang/julia/issues/20328 [#20345]: https://github.com/JuliaLang/julia/issues/20345 [#20403]: https://github.com/JuliaLang/julia/issues/20403 [#20404]: https://github.com/JuliaLang/julia/issues/20404 From 233435bb395b958d05808d62ccebb22bef71e98c Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Sat, 13 May 2017 15:46:58 -0700 Subject: [PATCH 0762/1534] Fix deprecated indexing of open call in windows displaysize missed from #12807, only happens when running in mintty --- base/stream.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/stream.jl b/base/stream.jl index 4bd1f4c070d88..9d24313c24fc5 100644 --- a/base/stream.jl +++ b/base/stream.jl @@ -362,7 +362,7 @@ function displaysize(io::TTY) if ispty(io) # io is actually a libuv pipe but a cygwin/msys2 pty try - h, w = map(x -> parse(Int, x), split(readstring(open(Base.Cmd(String["stty", "size"]), "r", io)[1]))) + h, w = parse.(Int, split(readstring(open(Base.Cmd(String["stty", "size"]), "r", io).out))) h > 0 || (h = default_size[1]) w > 0 || (w = default_size[2]) return h, w From 80c42adedb5f2b8597b07b8e59d6d1b37e5e1b9f Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Sat, 13 May 2017 15:48:59 -0700 Subject: [PATCH 0763/1534] run NEWS-update for recent 0.7 additions, just so these dont get mixed into any PRs that should be backported (this one shouldnt) --- NEWS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS.md b/NEWS.md index f918243c89d2a..649d140221bc9 100644 --- a/NEWS.md +++ b/NEWS.md @@ -638,3 +638,6 @@ Command-line option changes [#20609]: https://github.com/JuliaLang/julia/issues/20609 [#20889]: https://github.com/JuliaLang/julia/issues/20889 [#21183]: https://github.com/JuliaLang/julia/issues/21183 +[#21359]: https://github.com/JuliaLang/julia/issues/21359 +[#21697]: https://github.com/JuliaLang/julia/issues/21697 +[#21759]: https://github.com/JuliaLang/julia/issues/21759 From 1c457d80b4cdfa79d60211f8d8c51f5276b519c6 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 14 May 2017 07:45:13 -0700 Subject: [PATCH 0764/1534] Add NEWS.md entry for deprecation of Matrix() and Matrix{T}() (#20330). (#21851) --- NEWS.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS.md b/NEWS.md index f918243c89d2a..7c7ba54db8ba9 100644 --- a/NEWS.md +++ b/NEWS.md @@ -469,6 +469,9 @@ Deprecated or removed * `@test_approx_eq x y` has been deprecated in favor of `@test isapprox(x,y)` or `@test x ≈ y` ([#4615]). + * `Matrix()` and `Matrix{T}()` have been deprecated in favor of the explicit forms + `Matrix(0, 0)` and `Matrix{T}(0, 0)` ([#20330]). + * Vectorized functions have been deprecated in favor of dot syntax ([#17302], [#17265], [#18558], [#19711], [#19712], [#19791], [#19802], [#19931], [#20543], [#20228]). @@ -625,6 +628,7 @@ Command-line option changes [#20321]: https://github.com/JuliaLang/julia/issues/20321 [#20327]: https://github.com/JuliaLang/julia/issues/20327 [#20328]: https://github.com/JuliaLang/julia/issues/20328 +[#20330]: https://github.com/JuliaLang/julia/issues/20330 [#20345]: https://github.com/JuliaLang/julia/issues/20345 [#20403]: https://github.com/JuliaLang/julia/issues/20403 [#20404]: https://github.com/JuliaLang/julia/issues/20404 From da60928cc926531b1e396ad1c013ab6fc64136f4 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 14 May 2017 09:49:43 -0700 Subject: [PATCH 0765/1534] Add NEWS.md entry for deprecation of array-reducing isinteger (#19925). (#21856) --- NEWS.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS.md b/NEWS.md index 7c7ba54db8ba9..ca430d2f1fc36 100644 --- a/NEWS.md +++ b/NEWS.md @@ -464,6 +464,9 @@ Deprecated or removed `maxabs` and `minabs` have similarly been deprecated in favor of `maximum(abs, x)` and `minimum(abs, x)`. Likewise for the in-place counterparts of these functions ([#19598]). + * The array-reducing form of `isinteger` (`isinteger(x::AbstractArray)`) has been + deprecated in favor of `all(isinteger, x)` ([#19925]). + * `produce`, `consume` and iteration over a Task object have been deprecated in favor of using Channels for inter-task communication ([#19841]). @@ -611,6 +614,7 @@ Command-line option changes [#19901]: https://github.com/JuliaLang/julia/issues/19901 [#19903]: https://github.com/JuliaLang/julia/issues/19903 [#19919]: https://github.com/JuliaLang/julia/issues/19919 +[#19925]: https://github.com/JuliaLang/julia/issues/19925 [#19926]: https://github.com/JuliaLang/julia/issues/19926 [#19931]: https://github.com/JuliaLang/julia/issues/19931 [#19934]: https://github.com/JuliaLang/julia/issues/19934 From 3c81a1820c3ac998773cedb96907a7343013f43a Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 14 May 2017 09:53:29 -0700 Subject: [PATCH 0766/1534] Add NEWS.md entry for dep of character predicate methods over strings (#20342). (#21850) --- NEWS.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/NEWS.md b/NEWS.md index ca430d2f1fc36..fe465173d7988 100644 --- a/NEWS.md +++ b/NEWS.md @@ -478,6 +478,12 @@ Deprecated or removed * Vectorized functions have been deprecated in favor of dot syntax ([#17302], [#17265], [#18558], [#19711], [#19712], [#19791], [#19802], [#19931], [#20543], [#20228]). + * All methods of character predicates (`isalnum`, `isalpha`, `iscntrl`, `isdigit`, + `isnumber`, `isgraph`, `islower`, `isprint`, `ispunct`, `isspace`, `isupper`, + `isxdigit`) that accept `AbstractStrings` have been deprecated in favor of `all`. + For example, `isnumber("123")` should now be expressed `all(isnumber, "123")` + ([#20342]). + * The two-argument forms of `map` (`map!(f, A)`) and `asyncmap!` (`asyncmap!(f, A)`) have been deprecated in anticipation of future semantic changes ([#19721]). @@ -633,6 +639,7 @@ Command-line option changes [#20327]: https://github.com/JuliaLang/julia/issues/20327 [#20328]: https://github.com/JuliaLang/julia/issues/20328 [#20330]: https://github.com/JuliaLang/julia/issues/20330 +[#20342]: https://github.com/JuliaLang/julia/issues/20342 [#20345]: https://github.com/JuliaLang/julia/issues/20345 [#20403]: https://github.com/JuliaLang/julia/issues/20403 [#20404]: https://github.com/JuliaLang/julia/issues/20404 From d6a15c616e476a361d2ba6baef3461264d549592 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 14 May 2017 09:59:02 -0700 Subject: [PATCH 0767/1534] Add PR number to NEWS.md for dep of inner constructor syntax (#20308). (#21853) --- NEWS.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index fe465173d7988..7a90fbb64aebc 100644 --- a/NEWS.md +++ b/NEWS.md @@ -73,7 +73,8 @@ Language changes ``` the syntax `Foo(x) = new(x)` actually defined a constructor for `Foo{T,S}`, i.e. the case where the type parameters are specified. For clarity, this - definition now must be written as `Foo{T,S}(x) where {T,S<:Real} = new(x)` ([#11310]). + definition now must be written as `Foo{T,S}(x) where {T,S<:Real} = new(x)` + ([#11310], [#20308]). * The keywords used to define types have changed ([#19157], [#20418]). @@ -635,6 +636,7 @@ Command-line option changes [#20248]: https://github.com/JuliaLang/julia/issues/20248 [#20249]: https://github.com/JuliaLang/julia/issues/20249 [#20268]: https://github.com/JuliaLang/julia/issues/20268 +[#20308]: https://github.com/JuliaLang/julia/issues/20308 [#20321]: https://github.com/JuliaLang/julia/issues/20321 [#20327]: https://github.com/JuliaLang/julia/issues/20327 [#20328]: https://github.com/JuliaLang/julia/issues/20328 From b221e6549eb6c0e00ce1387221f61dfdc4e7b81f Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 14 May 2017 10:00:14 -0700 Subject: [PATCH 0768/1534] Add NEWS.md entry for dep of negate kwarg from Dates adjuster API (#20213). (#21855) --- NEWS.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/NEWS.md b/NEWS.md index 7a90fbb64aebc..a061be22d4479 100644 --- a/NEWS.md +++ b/NEWS.md @@ -471,6 +471,11 @@ Deprecated or removed * `produce`, `consume` and iteration over a Task object have been deprecated in favor of using Channels for inter-task communication ([#19841]). + * The `negate` keyword has been deprecated from all functions in the `Dates` adjuster + API (`adjust`, `tonext`, `toprev`, `Date`, `Time`, and `DateTime`). Instead use + predicate function negation via the `!` operator + (see [Library Improvements](#library-improvements)) ([#20213]). + * `@test_approx_eq x y` has been deprecated in favor of `@test isapprox(x,y)` or `@test x ≈ y` ([#4615]). * `Matrix()` and `Matrix{T}()` have been deprecated in favor of the explicit forms @@ -632,6 +637,7 @@ Command-line option changes [#20047]: https://github.com/JuliaLang/julia/issues/20047 [#20079]: https://github.com/JuliaLang/julia/issues/20079 [#20164]: https://github.com/JuliaLang/julia/issues/20164 +[#20213]: https://github.com/JuliaLang/julia/issues/20213 [#20228]: https://github.com/JuliaLang/julia/issues/20228 [#20248]: https://github.com/JuliaLang/julia/issues/20248 [#20249]: https://github.com/JuliaLang/julia/issues/20249 From be6cfa9b202f452f572145e59db9082a1f875036 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Sun, 14 May 2017 12:49:28 -0400 Subject: [PATCH 0769/1534] Fix compilation on LLVM-svn Disable eh frame deregistration overload since we don't actually use it. Close #21744 --- src/ccall.cpp | 18 ++++++++++-------- src/cgmemmgr.cpp | 5 +++++ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/ccall.cpp b/src/ccall.cpp index 150e68eeb586e..28218547bf113 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -1275,7 +1275,7 @@ std::string generate_func_sig() assert(rt && !jl_is_abstract_ref_type(rt)); #if JL_LLVM_VERSION >= 50000 - std::vector paramattrs; + std::vector paramattrs; #else std::vector paramattrs; #endif @@ -1302,7 +1302,7 @@ std::string generate_func_sig() #endif retattrs.addAttribute(Attribute::NoAlias); #if JL_LLVM_VERSION >= 50000 - paramattrs.push_back(AttributeList::get(jl_LLVMContext, 1, retattrs)); + paramattrs.push_back(std::move(retattrs)); #else paramattrs.push_back(AttributeSet::get(jl_LLVMContext, 1, retattrs)); #endif @@ -1388,24 +1388,26 @@ std::string generate_func_sig() do { // for each arg for which this type applies, add the appropriate LLVM parameter attributes if (i < nargs) { // if vararg, the last declared arg type may not have a corresponding arg value #if JL_LLVM_VERSION >= 50000 - AttributeList params = AttributeList::get(jl_LLVMContext, i + sret + 1, ab); + paramattrs.push_back(std::move(ab)); #else AttributeSet params = AttributeSet::get(jl_LLVMContext, i + sret + 1, ab); -#endif paramattrs.push_back(params); +#endif } i++; } while (current_isVa && i < nargs); // if is this is the vararg, loop to the end } for (i = 0; i < nargs + sret; ++i) { + const auto &as = paramattrs.at(i); #if JL_LLVM_VERSION >= 50000 - const AttributeList &as = paramattrs.at(i); + if (!as.hasAttributes()) + continue; #else - const AttributeSet &as = paramattrs.at(i); + if (as.isEmpty()) + continue; #endif - if (!as.isEmpty()) - attributes = attributes.addAttributes(jl_LLVMContext, i + 1, as); + attributes = attributes.addAttributes(jl_LLVMContext, i + 1, as); } if (rt == jl_bottom_type) { attributes = attributes.addAttribute(jl_LLVMContext, diff --git a/src/cgmemmgr.cpp b/src/cgmemmgr.cpp index bd74bada042ba..ea59a6a3c42c7 100644 --- a/src/cgmemmgr.cpp +++ b/src/cgmemmgr.cpp @@ -732,8 +732,11 @@ class RTDyldMemoryManagerJL : public SectionMemoryManager { } void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override; +#if 0 + // Disable for now since we are not actually using this. void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override; +#endif uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, StringRef SectionName) override; @@ -860,12 +863,14 @@ void RTDyldMemoryManagerJL::registerEHFrames(uint8_t *Addr, } } +#if 0 void RTDyldMemoryManagerJL::deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) { deregister_eh_frames((uint8_t*)LoadAddr, Size); } +#endif } From 5b33b2b9aa980b24af462aa974ee6053a6bd27f6 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 14 May 2017 17:12:01 -0700 Subject: [PATCH 0770/1534] Add NEWS.md entry for dep of ambiguous Dates convert and colon methods (#19920). (#21861) --- NEWS.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/NEWS.md b/NEWS.md index a061be22d4479..d94765cf3857c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -459,6 +459,14 @@ Deprecated or removed * `Dates.recur` has been deprecated in favor of `filter` ([#19288]) + * A number of ambiguous `convert` operations between `Number`s (especially `Real`s) + and `Date`, `DateTime`, and `Period` types have been deprecated in favor of + unambiguous `convert` and explicit constructor calls. Additionally, ambiguous colon + construction of `<:Period` ranges without step specification, for example + `Dates.Hour(1):Dates.Hour(2)`, has been deprecated in favor of such construction + including step specification, for example `Dates.Hour(1):Dates.Hour(1):Dates.Hour(2)` + ([#19920]). + * `cummin` and `cummax` have been deprecated in favor of `accumulate`. * `sumabs` and `sumabs2` have been deprecated in favor of `sum(abs, x)` and `sum(abs2, x)`, respectively. @@ -626,6 +634,7 @@ Command-line option changes [#19901]: https://github.com/JuliaLang/julia/issues/19901 [#19903]: https://github.com/JuliaLang/julia/issues/19903 [#19919]: https://github.com/JuliaLang/julia/issues/19919 +[#19920]: https://github.com/JuliaLang/julia/issues/19920 [#19925]: https://github.com/JuliaLang/julia/issues/19925 [#19926]: https://github.com/JuliaLang/julia/issues/19926 [#19931]: https://github.com/JuliaLang/julia/issues/19931 From 609b2d6adc52ebb7b6cb2be9678b56bfdbd9168e Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 15 May 2017 05:17:43 -0700 Subject: [PATCH 0771/1534] Add NEWS.md entry for deprecation of Array(T, dims...) (#19989). (#21857) --- NEWS.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/NEWS.md b/NEWS.md index ec0e9c95819ce..60cc91d37d263 100644 --- a/NEWS.md +++ b/NEWS.md @@ -469,6 +469,11 @@ Deprecated or removed * `cummin` and `cummax` have been deprecated in favor of `accumulate`. + * The `Array` constructor syntax `Array(T, dims...)` has been deprecated + in favor of the forms `Array{T,N}(dims...)` (where `N` is known, or + particularly `Vector{T}(dims...)` for `N = 1` and `Matrix{T}(dims...)` for `N = 2`), + and `Array{T}(dims...)` (where `N` is not known) ([#19989]). + * `sumabs` and `sumabs2` have been deprecated in favor of `sum(abs, x)` and `sum(abs2, x)`, respectively. `maxabs` and `minabs` have similarly been deprecated in favor of `maximum(abs, x)` and `minimum(abs, x)`. Likewise for the in-place counterparts of these functions ([#19598]). @@ -642,6 +647,7 @@ Command-line option changes [#19944]: https://github.com/JuliaLang/julia/issues/19944 [#19949]: https://github.com/JuliaLang/julia/issues/19949 [#19950]: https://github.com/JuliaLang/julia/issues/19950 +[#19989]: https://github.com/JuliaLang/julia/issues/19989 [#20009]: https://github.com/JuliaLang/julia/issues/20009 [#20047]: https://github.com/JuliaLang/julia/issues/20047 [#20079]: https://github.com/JuliaLang/julia/issues/20079 From a204bfdb4c2968ad5184c6e75451b0060851bf3f Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Mon, 15 May 2017 14:19:53 +0200 Subject: [PATCH 0772/1534] Disable two libgit2 tests with libgit2 < 0.26.0 (#21872) Without our patches libgit2-remote-push-NULL and libgit2-gitconfig-symlink, which are not yet included in an upstream release, these tests fail. Disable them so that builds using the system libgit2 can pass the tests. --- test/libgit2.jl | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test/libgit2.jl b/test/libgit2.jl index bd6c4a8144f41..fcf5827c14867 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -99,7 +99,8 @@ end end end -is_unix() && @testset "Default config with symlink" begin +# See #21872 and #21636 +LibGit2.version() >= v"0.26.0" && is_unix() && @testset "Default config with symlink" begin with_libgit2_temp_home() do tmphome write(joinpath(tmphome, "real_gitconfig"), "[fake]\n\tproperty = BBB") symlink(joinpath(tmphome, "real_gitconfig"), @@ -854,8 +855,10 @@ mktempdir() do dir end LibGit2.add!(our_repo, "file1") LibGit2.commit(our_repo, "add file1") - # we cannot yet locally push to non-bare repos - @test_throws LibGit2.GitError LibGit2.push(our_repo, remoteurl=up_path) + if LibGit2.version() >= v"0.26.0" # See #21872, #21639 and #21597 + # we cannot yet locally push to non-bare repos + @test_throws LibGit2.GitError LibGit2.push(our_repo, remoteurl=up_path) + end finally close(our_repo) close(up_repo) From 2c484bfcf1472831c1ee786860f7df3530feceb1 Mon Sep 17 00:00:00 2001 From: Mus M Date: Mon, 15 May 2017 12:00:02 -0400 Subject: [PATCH 0773/1534] Use where syntax in umfpack.jl --- base/sparse/umfpack.jl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/base/sparse/umfpack.jl b/base/sparse/umfpack.jl index 58981862d702e..1b8d59496fccb 100644 --- a/base/sparse/umfpack.jl +++ b/base/sparse/umfpack.jl @@ -382,24 +382,24 @@ function nnz(lu::UmfpackLU) end ### Solve with Factorization -A_ldiv_B!{T<:UMFVTypes}(lu::UmfpackLU{T}, B::StridedVecOrMat{T}) = A_ldiv_B!(B, lu, copy(B)) -At_ldiv_B!{T<:UMFVTypes}(lu::UmfpackLU{T}, B::StridedVecOrMat{T}) = At_ldiv_B!(B, lu, copy(B)) -Ac_ldiv_B!{T<:UMFVTypes}(lu::UmfpackLU{T}, B::StridedVecOrMat{T}) = Ac_ldiv_B!(B, lu, copy(B)) +A_ldiv_B!(lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = A_ldiv_B!(B, lu, copy(B)) +At_ldiv_B!(lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = At_ldiv_B!(B, lu, copy(B)) +Ac_ldiv_B!(lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = Ac_ldiv_B!(B, lu, copy(B)) A_ldiv_B!(lu::UmfpackLU{Float64}, B::StridedVecOrMat{<:Complex}) = A_ldiv_B!(B, lu, copy(B)) At_ldiv_B!(lu::UmfpackLU{Float64}, B::StridedVecOrMat{<:Complex}) = At_ldiv_B!(B, lu, copy(B)) Ac_ldiv_B!(lu::UmfpackLU{Float64}, B::StridedVecOrMat{<:Complex}) = Ac_ldiv_B!(B, lu, copy(B)) -A_ldiv_B!{T<:UMFVTypes}(X::StridedVecOrMat{T}, lu::UmfpackLU{T}, B::StridedVecOrMat{T}) = +A_ldiv_B!(X::StridedVecOrMat{T}, lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = _Aq_ldiv_B!(X, lu, B, UMFPACK_A) -At_ldiv_B!{T<:UMFVTypes}(X::StridedVecOrMat{T}, lu::UmfpackLU{T}, B::StridedVecOrMat{T}) = +At_ldiv_B!(X::StridedVecOrMat{T}, lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = _Aq_ldiv_B!(X, lu, B, UMFPACK_At) -Ac_ldiv_B!{T<:UMFVTypes}(X::StridedVecOrMat{T}, lu::UmfpackLU{T}, B::StridedVecOrMat{T}) = +Ac_ldiv_B!(X::StridedVecOrMat{T}, lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = _Aq_ldiv_B!(X, lu, B, UMFPACK_Aat) -A_ldiv_B!{Tb<:Complex}(X::StridedVecOrMat{Tb}, lu::UmfpackLU{Float64}, B::StridedVecOrMat{Tb}) = +A_ldiv_B!(X::StridedVecOrMat{Tb}, lu::UmfpackLU{Float64}, B::StridedVecOrMat{Tb}) where {Tb<:Complex} = _Aq_ldiv_B!(X, lu, B, UMFPACK_A) -At_ldiv_B!{Tb<:Complex}(X::StridedVecOrMat{Tb}, lu::UmfpackLU{Float64}, B::StridedVecOrMat{Tb}) = +At_ldiv_B!(X::StridedVecOrMat{Tb}, lu::UmfpackLU{Float64}, B::StridedVecOrMat{Tb}) where {Tb<:Complex} = _Aq_ldiv_B!(X, lu, B, UMFPACK_At) -Ac_ldiv_B!{Tb<:Complex}(X::StridedVecOrMat{Tb}, lu::UmfpackLU{Float64}, B::StridedVecOrMat{Tb}) = +Ac_ldiv_B!(X::StridedVecOrMat{Tb}, lu::UmfpackLU{Float64}, B::StridedVecOrMat{Tb}) where {Tb<:Complex} = _Aq_ldiv_B!(X, lu, B, UMFPACK_Aat) function _Aq_ldiv_B!(X::StridedVecOrMat, lu::UmfpackLU, B::StridedVecOrMat, transposeoptype) From 5847317e5e3cc4d353bbfa2225fcc4b36c0e23cd Mon Sep 17 00:00:00 2001 From: Jarrett Revels Date: Mon, 15 May 2017 14:13:07 -0400 Subject: [PATCH 0774/1534] redesign type inference outer loop (PR #21677) removes the global work queue, which allows increasing the precision of cycle detection and resolution, and decreases the need for the threading synchronization lock surrounding inference updates `inInference` flag usage to be merely a hint for `jl_type_infer` to not bother trying to infer a method (helps avoid accidental infinite recursion over inferring type inference), enable inferring inference --- base/inference.jl | 513 +++++++++++++++++++-------------------------- base/precompile.jl | 7 +- base/sysimg.jl | 5 +- src/gf.c | 65 +++--- src/interpreter.c | 2 +- test/staged.jl | 3 +- 6 files changed, 254 insertions(+), 341 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 9a4768bd38b19..059f5474ba21b 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -131,14 +131,11 @@ mutable struct InferenceState # ssavalue sparsity and restart info ssavalue_uses::Vector{IntSet} ssavalue_init::Vector{Any} - # call-graph edges connecting from a caller to a callee (and back) - # we shouldn't need to iterate edges very often, so we use it to optimize the lookup from edge -> linenum - # whereas backedges is optimized for iteration - edges::ObjectIdDict # a Dict{InferenceState, Vector{LineNum}} - backedges::Vector{Tuple{InferenceState, Vector{LineNum}}} - # iteration fixed-point detection - fixedpoint::Bool - inworkq::Bool + + backedges::Vector{Tuple{InferenceState, LineNum}} # call-graph backedges connecting from callee to caller + callers_in_cycle::Vector{InferenceState} + parent::Union{Void, InferenceState} + const_api::Bool const_ret::Bool @@ -148,6 +145,8 @@ mutable struct InferenceState inferred::Bool + dont_work_on_me::Bool + # src is assumed to be a newly-allocated CodeInfo, that can be modified in-place to contain intermediate results function InferenceState(linfo::MethodInstance, src::CodeInfo, optimize::Bool, cached::Bool, params::InferenceParams) @@ -266,41 +265,43 @@ mutable struct InferenceState Union{}, W, 1, n, cur_hand, handler_at, n_handlers, ssavalue_uses, ssavalue_init, - ObjectIdDict(), # Dict{InferenceState, Vector{LineNum}}(), - Vector{Tuple{InferenceState, Vector{LineNum}}}(), - false, false, false, false, optimize, cached, false) - push!(active, frame) - nactive[] += 1 + Vector{Tuple{InferenceState,LineNum}}(), # backedges + Vector{InferenceState}(), # callers_in_cycle + #=parent=#nothing, + false, false, optimize, cached, false, false) return frame end end -# create copies of the CodeInfo definition, and any fields that type-inference might modify -# TODO: post-inference see if we can swap back to the original arrays -function get_source(li::MethodInstance) - if isa(li.def.source, Array{UInt8,1}) - src = ccall(:jl_uncompress_ast, Any, (Any, Any), li.def, li.def.source) +function InferenceState(linfo::MethodInstance, + optimize::Bool, cached::Bool, params::InferenceParams) + # prepare an InferenceState object for inferring lambda + # create copies of the CodeInfo definition, and any fields that type-inference might modify + if linfo.def.isstaged + try + # user code might throw errors – ignore them + src = get_staged(linfo) + catch + return nothing + end else - src = ccall(:jl_copy_code_info, Ref{CodeInfo}, (Any,), li.def.source) - src.code = copy_exprargs(src.code) - src.slotnames = copy(src.slotnames) - src.slotflags = copy(src.slotflags) + # TODO: post-inference see if we can swap back to the original arrays? + if isa(linfo.def.source, Array{UInt8,1}) + src = ccall(:jl_uncompress_ast, Any, (Any, Any), linfo.def, linfo.def.source) + else + src = ccall(:jl_copy_code_info, Ref{CodeInfo}, (Any,), linfo.def.source) + src.code = copy_exprargs(src.code) + src.slotnames = copy(src.slotnames) + src.slotflags = copy(src.slotflags) + end end - return src + return InferenceState(linfo, src, optimize, cached, params) end function get_staged(li::MethodInstance) return ccall(:jl_code_for_staged, Any, (Any,), li)::CodeInfo end - -#### current global inference state #### - -const active = Vector{Any}() # set of all InferenceState objects being processed -const nactive = Array{Int,0}() -nactive[] = 0 -const workq = Vector{InferenceState}() # set of InferenceState objects that can make immediate progress - #### helper functions #### @inline slot_id(s) = isa(s, SlotNumber) ? (s::SlotNumber).id : (s::TypedSlot).id # using a function to ensure we can infer this @@ -1077,7 +1078,9 @@ function invoke_tfunc(f::ANY, types::ANY, argtype::ANY, sv::InferenceState) meth = entry.func (ti, env) = ccall(:jl_match_method, Ref{SimpleVector}, (Any, Any), argtype, meth.sig) - return typeinf_edge(meth::Method, ti, env, sv) + rt, edge = typeinf_edge(meth::Method, ti, env, sv) + edge !== nothing && add_backedge!(edge::MethodInstance, sv) + return rt end function tuple_tfunc(argtype::ANY) @@ -1272,43 +1275,31 @@ function abstract_call_gf_by_type(f::ANY, atype::ANY, sv::InferenceState) # this means too many methods matched return Any end - x::Array{Any,1} = applicable + applicable = applicable::Array{Any,1} fullmatch = false - for (m::SimpleVector) in x + for (m::SimpleVector) in applicable sig = m[1] sigtuple = unwrap_unionall(sig)::DataType method = m[3]::Method sparams = m[2]::SimpleVector recomputesvec = false - if !fullmatch && typeseq(sig, argtype) + if !fullmatch && (argtype <: method.sig) fullmatch = true end # limit argument type tuple growth - msig = unwrap_unionall(m[3].sig) + msig = unwrap_unionall(method.sig) lsig = length(msig.parameters) ls = length(sigtuple.parameters) td = type_depth(sig) - # look at the existing edges to detect growing argument lists mightlimitlength = ls > lsig + 1 mightlimitdepth = td > 2 - limitlength = false - if mightlimitlength - for (callee, _) in sv.edges - callee = callee::InferenceState - if method === callee.linfo.def && ls > length(unwrap_unionall(callee.linfo.specTypes).parameters) - limitlength = true - break - end - end - end - - # limit argument type size growth if mightlimitlength || mightlimitdepth # TODO: FIXME: this heuristic depends on non-local state making type-inference unpredictable - for infstate in active - infstate === nothing && continue + cyclei = 0 + infstate = sv + while infstate !== nothing infstate = infstate::InferenceState if isdefined(infstate.linfo, :def) && method === infstate.linfo.def if mightlimitlength && ls > length(unwrap_unionall(infstate.linfo.specTypes).parameters) @@ -1348,6 +1339,14 @@ function abstract_call_gf_by_type(f::ANY, atype::ANY, sv::InferenceState) end end end + # iterate through the cycle before walking to the parent + if cyclei < length(infstate.callers_in_cycle) + cyclei += 1 + infstate = infstate.callers_in_cycle[cyclei] + else + cyclei = 0 + infstate = infstate.parent + end end end @@ -1385,7 +1384,8 @@ function abstract_call_gf_by_type(f::ANY, atype::ANY, sv::InferenceState) end sparams = recomputed[2]::SimpleVector end - rt = typeinf_edge(method, sig, sparams, sv) + rt, edge = typeinf_edge(method, sig, sparams, sv) + edge !== nothing && add_backedge!(edge::MethodInstance, sv) rettype = tmerge(rettype, rt) if rettype === Any break @@ -1397,7 +1397,7 @@ function abstract_call_gf_by_type(f::ANY, atype::ANY, sv::InferenceState) add_mt_backedge(ftname.mt, argtype, sv) update_valid_age!(min_valid[1], max_valid[1], sv) end - if isempty(x) + if isempty(applicable) # TODO: this is needed because type intersection is wrong in some cases return Any end @@ -2317,31 +2317,6 @@ end inlining_enabled() = (JLOptions().can_inline == 1) coverage_enabled() = (JLOptions().code_coverage != 0) -# TODO: track the worlds for which this InferenceState -# is being used, and split it if the WIP requires it? -function converge_valid_age!(sv::InferenceState) - # push the validity range of sv into its fixedpoint callers - # recursing as needed to cover the graph - for (i, _) in sv.backedges - if i.fixedpoint - updated = false - if i.min_valid < sv.min_valid - i.min_valid = sv.min_valid - updated = true - end - if i.max_valid > sv.max_valid - i.max_valid = sv.max_valid - updated = true - end - @assert !isdefined(i.linfo, :def) || !i.cached || i.min_valid <= i.params.world <= i.max_valid "invalid age range update" - if updated - converge_valid_age!(i) - end - end - end - nothing -end - # work towards converging the valid age range for sv function update_valid_age!(min_valid::UInt, max_valid::UInt, sv::InferenceState) sv.min_valid = max(sv.min_valid, min_valid) @@ -2353,7 +2328,7 @@ update_valid_age!(edge::InferenceState, sv::InferenceState) = update_valid_age!( update_valid_age!(li::MethodInstance, sv::InferenceState) = update_valid_age!(min_world(li), max_world(li), sv) # temporarily accumulate our edges to later add as backedges in the callee -function add_backedge(li::MethodInstance, caller::InferenceState) +function add_backedge!(li::MethodInstance, caller::InferenceState) isdefined(caller.linfo, :def) || return # don't add backedges to toplevel exprs if caller.stmt_edges[caller.currpc] === () caller.stmt_edges[caller.currpc] = [] @@ -2419,72 +2394,92 @@ function code_for_method(method::Method, atypes::ANY, sparams::SimpleVector, wor return ccall(:jl_specializations_get_linfo, Ref{MethodInstance}, (Any, Any, Any, UInt), method, atypes, sparams, world) end -function typeinf_active(linfo::MethodInstance) - for infstate in active - infstate === nothing && continue - infstate = infstate::InferenceState - if linfo === infstate.linfo - return infstate - end +function typeinf_active(linfo::MethodInstance, sv::InferenceState) + for infstate in sv.callers_in_cycle + linfo === infstate.linfo && return infstate end return nothing end -function add_backedge(frame::InferenceState, caller::InferenceState, currpc::Int) +function add_backedge!(frame::InferenceState, caller::InferenceState, currpc::Int) update_valid_age!(frame, caller) - if haskey(caller.edges, frame) - Ws = caller.edges[frame]::Vector{Int} - if !(currpc in Ws) - push!(Ws, currpc) + backedge = (caller, currpc) + contains_is(frame.backedges, backedge) || push!(frame.backedges, backedge) + return frame +end + +# at the end, all items in b's cycle +# will now be added to a's cycle +function union_caller_cycle!(a::InferenceState, b::InferenceState) + callers_in_cycle = b.callers_in_cycle + b.parent = a.parent + b.callers_in_cycle = a.callers_in_cycle + contains_is(a.callers_in_cycle, b) || push!(a.callers_in_cycle, b) + if callers_in_cycle !== a.callers_in_cycle + for caller in callers_in_cycle + if caller !== b + caller.parent = a.parent + caller.callers_in_cycle = a.callers_in_cycle + push!(a.callers_in_cycle, caller) + end end - else - Ws = Int[currpc] - caller.edges[frame] = Ws - push!(frame.backedges, (caller, Ws)) end + return end -# build (and start inferring) the inference frame for the linfo -function typeinf_frame(linfo::MethodInstance, caller, optimize::Bool, cached::Bool, - params::InferenceParams) - # println(params.world, ' ', linfo) - if cached && linfo.inInference - # inference on this signature may be in progress, - # find the corresponding frame in the active list - frame = typeinf_active(linfo) - # TODO: this assertion seems iffy - assert(frame !== nothing) - else - # inference not started yet, make a new frame for a new lambda - if linfo.def.isstaged - try - # user code might throw errors – ignore them - src = get_staged(linfo) - catch - return nothing +function merge_call_chain!(parent::InferenceState, ancestor::InferenceState, child::InferenceState) + # add backedge of parent <- child + # then add all backedges of parent <- parent.parent + # and merge all of the callers into ancestor.callers_in_cycle + # and ensure that walking the parent list will get the same result (DAG) from everywhere + while true + add_backedge!(child, parent, parent.currpc) + union_caller_cycle!(ancestor, child) + child = parent + parent = child.parent + child === ancestor && break + end +end + +# Walk through `linfo`'s upstream call chain, starting at `parent`. If a parent +# frame matching `linfo` is encountered, then there is a cycle in the call graph +# (i.e. `linfo` is a descendant callee of itself). Upon encountering this cycle, +# we "resolve" it by merging the call chain, which entails unioning each intermediary +# frame's `callers_in_cycle` field and adding the appropriate backedges. Finally, +# we return `linfo`'s pre-existing frame. If no cycles are found, `nothing` is +# returned instead. +function resolve_call_cycle!(linfo::MethodInstance, parent::InferenceState) + frame = parent + while isa(frame, InferenceState) + if frame.linfo === linfo + merge_call_chain!(parent, frame, frame) + return frame + end + for caller in frame.callers_in_cycle + if caller.linfo === linfo + merge_call_chain!(parent, frame, caller) + return caller end - else - src = get_source(linfo) end - cached && (linfo.inInference = true) - frame = InferenceState(linfo, src, optimize, cached, params) + frame = frame.parent end - frame = frame::InferenceState + return nothing +end - if isa(caller, InferenceState) - # if we were called from inside inference, the caller will be the InferenceState object - # for which the edge was required - @assert caller.currpc > 0 - add_backedge(frame, caller, caller.currpc) - end - typeinf_loop(frame) +# build (and start inferring) the inference frame for the linfo +function typeinf_frame(linfo::MethodInstance, + optimize::Bool, cached::Bool, params::InferenceParams) + frame = InferenceState(linfo, optimize, cached, params) + frame === nothing && return nothing + cached && (linfo.inInference = true) + typeinf(frame) return frame end # compute (and cache) an inferred AST and return the current best estimate of the result type function typeinf_edge(method::Method, atypes::ANY, sparams::SimpleVector, caller::InferenceState) code = code_for_method(method, atypes, sparams, caller.params.world) - code === nothing && return Any + code === nothing && return Any, nothing code = code::MethodInstance if isdefined(code, :inferred) # return rettype if the code is already inferred @@ -2492,18 +2487,27 @@ function typeinf_edge(method::Method, atypes::ANY, sparams::SimpleVector, caller # so need to check whether the code itself is also inferred inf = code.inferred if !isa(inf, CodeInfo) || (inf::CodeInfo).inferred - add_backedge(code, caller) if isdefined(code, :inferred_const) - return abstract_eval_constant(code.inferred_const) + return abstract_eval_constant(code.inferred_const), code else - return code.rettype + return code.rettype, code end end end - frame = typeinf_frame(code, caller, true, true, caller.params) - frame === nothing && return Any + frame = resolve_call_cycle!(code, caller) + if frame === nothing + code.inInference = true + frame = InferenceState(code, true, true, caller.params) # always optimize and cache edge targets + if frame === nothing + code.inInference = false + return Any, nothing + end + frame.parent = caller + typeinf(frame) + return frame.bestguess, frame.inferred ? frame.linfo : nothing + end frame = frame::InferenceState - return frame.bestguess + return frame.bestguess, nothing end #### entry points for inferring a MethodInstance given a type signature #### @@ -2547,7 +2551,7 @@ function typeinf_code(linfo::MethodInstance, optimize::Bool, cached::Bool, end end end - frame = typeinf_frame(linfo, nothing, optimize, cached, params) + frame = typeinf_frame(linfo, optimize, cached, params) ccall(:jl_typeinf_end, Void, ()) frame === nothing && return svec(nothing, nothing, Any) frame = frame::InferenceState @@ -2575,7 +2579,7 @@ function typeinf_type(method::Method, atypes::ANY, sparams::SimpleVector, end end end - frame = typeinf_frame(code, nothing, cached, cached, params) + frame = typeinf_frame(code, cached, cached, params) ccall(:jl_typeinf_end, Void, ()) frame === nothing && return nothing frame = frame::InferenceState @@ -2589,11 +2593,10 @@ function typeinf_ext(linfo::MethodInstance, world::UInt) return typeinf_code(linfo, true, true, InferenceParams(world)) else # toplevel lambda - infer directly - linfo.inInference = true ccall(:jl_typeinf_begin, Void, ()) frame = InferenceState(linfo, linfo.inferred::CodeInfo, true, true, InferenceParams(world)) - typeinf_loop(frame) + typeinf(frame) ccall(:jl_typeinf_end, Void, ()) @assert frame.inferred # TODO: deal with this better @assert frame.linfo === linfo @@ -2603,83 +2606,9 @@ end #### do the work of inference #### -in_typeinf_loop = false -function typeinf_loop(frame) - global in_typeinf_loop - if in_typeinf_loop - frame.inworkq || typeinf_frame(frame) - return - end - try - in_typeinf_loop = true - # the core type-inference algorithm - # processes everything in workq, - # and returns when there is nothing left - while nactive[] > 0 - while active[end] === nothing - pop!(active) - end - if isempty(workq) - frame = active[end]::InferenceState - else - frame = pop!(workq) - end - typeinf_frame(frame) - if isempty(workq) && nactive[] > 0 - # nothing in active has an edge that hasn't reached a fixed-point - # so all of them can be considered finished now - fplist = Any[] - for i in active - i === nothing && continue - i = i::InferenceState - if i.fixedpoint - push!(fplist, i) - i.inworkq = true - end - end - for i in length(fplist):-1:1 - # optimize and record the results - # the reverse order makes it more likely to inline a callee into its caller - optimize(fplist[i]::InferenceState) # this may add incomplete work to active - end - for i in fplist - # push valid ages from each node across the graph cycle - converge_valid_age!(i::InferenceState) - end - for i in fplist - # record the results - finish(i::InferenceState) - end - for i in fplist - # update and record all of the back edges for the finished world - finalize_backedges(i::InferenceState) - end - end - end - # cleanup the active queue - empty!(active) - # while active[end] === nothing - # # this pops everything, but with exaggerated care just in case - # # something managed to add something to the queue at the same time - # # (or someone decides to use an alternative termination condition) - # pop!(active) - # end - in_typeinf_loop = false - catch ex - println("WARNING: An error occurred during inference. Type inference is now partially disabled.") - println(ex) - ccall(:jlbacktrace, Void, ()) - end - nothing -end - -global_sv = nothing -function typeinf_frame(frame) - global global_sv # TODO: actually pass this to all functions that need it - last_global_sv = global_sv - global_sv = frame +function typeinf_work(frame::InferenceState) @assert !frame.inferred - frame.inworkq = true + frame.dont_work_on_me = true # mark that this function is currently on the stack W = frame.ip s = frame.stmt_types n = frame.nstmts @@ -2765,18 +2694,15 @@ function typeinf_frame(frame) if tchanged(rt, frame.bestguess) # new (wider) return type for frame frame.bestguess = tmerge(frame.bestguess, rt) - for (caller, callerW) in frame.backedges + for (caller, caller_pc) in frame.backedges # notify backedges of updated type information - for caller_pc in callerW - if caller.stmt_types[caller_pc] !== () - if caller_pc < caller.pc´´ - caller.pc´´ = caller_pc - end - push!(caller.ip, caller_pc) + if caller.stmt_types[caller_pc] !== () + if caller_pc < caller.pc´´ + caller.pc´´ = caller_pc end + push!(caller.ip, caller_pc) end end - unmark_fixedpoint(frame) end elseif hd === :enter l = stmt.args[1]::Int @@ -2824,53 +2750,72 @@ function typeinf_frame(frame) end end end + frame.dont_work_on_me = false +end - # with no active ip's, type inference on frame is done if there are no outstanding (unfinished) edges - #@assert isempty(W) - @assert !frame.inferred - finished = isempty(frame.edges) - if isempty(workq) - # oops, there's a cycle somewhere in the `edges` graph - # so we've run out off the tree and will need to start work on the loop - frame.fixedpoint = true - end - - if finished || frame.fixedpoint - if finished - optimize(frame) - finish(frame) - finalize_backedges(frame) - else # fixedpoint propagation - for (i, _) in frame.edges - i = i::InferenceState - if !i.fixedpoint - update_valid_age!(i, frame) # work towards converging age at the same time - if !i.inworkq - push!(workq, i) - i.inworkq = true - end - i.fixedpoint = true - end +function typeinf(frame::InferenceState) + + typeinf_work(frame) + + # If the current frame is part of a cycle, solve the cycle before finishing + no_active_ips_in_callers = false + while !no_active_ips_in_callers + no_active_ips_in_callers = true + for caller in frame.callers_in_cycle + caller.dont_work_on_me && return + if caller.pc´´ <= caller.nstmts # equivalent to `isempty(caller.ip)` + # Note that `typeinf_work(caller)` can potentially modify the other frames + # `frame.callers_in_cycle`, which is why making incremental progress requires the + # outer while loop. + typeinf_work(caller) + no_active_ips_in_callers = false + end + if caller.min_valid < frame.min_valid + caller.min_valid = frame.min_valid + end + if caller.max_valid > frame.max_valid + caller.max_valid = frame.max_valid end end end - frame.inworkq = false - global_sv = last_global_sv - nothing -end -function unmark_fixedpoint(frame::InferenceState) - # type information changed for frame, so its edges are no longer stuck - # recursively unmark any nodes that had previously been thought to be at a fixedpoint - # based upon (recursively) assuming that frame was stuck - if frame.fixedpoint - frame.fixedpoint = false - for (i, _) in frame.backedges - unmark_fixedpoint(i) + # with no active ip's, type inference on frame is done + + if isempty(frame.callers_in_cycle) + @assert !(frame.dont_work_on_me) + frame.dont_work_on_me = true + optimize(frame) + finish(frame) + finalize_backedges(frame) + else # frame is in frame.callers_in_cycle + for caller in frame.callers_in_cycle + @assert !(caller.dont_work_on_me) + caller.dont_work_on_me = true + end + for caller in frame.callers_in_cycle + optimize(caller) + if frame.min_valid < caller.min_valid + frame.min_valid = caller.min_valid + end + if frame.max_valid > caller.max_valid + frame.max_valid = caller.max_valid + end + end + for caller in frame.callers_in_cycle + caller.min_valid = frame.min_valid + end + for caller in frame.callers_in_cycle + finish(caller) + end + for caller in frame.callers_in_cycle + finalize_backedges(caller) end end + + nothing end + function record_ssa_assign(ssa_id::Int, new::ANY, frame::InferenceState) old = frame.src.ssavaluetypes[ssa_id] if old === NF || !(new ⊑ old) @@ -2916,16 +2861,6 @@ end # inference completed on `me` # now converge the optimization work function optimize(me::InferenceState) - for (i, _) in me.edges - i = i::InferenceState - @assert i.fixedpoint - end - # below may call back into inference and - # see this InferenceState is in an incomplete state - # set `inworkq` to prevent it from trying to look - # at the object in any detail - @assert me.inworkq - # annotate fulltree with type information type_annotate!(me) @@ -3018,7 +2953,7 @@ function finish(me::InferenceState) # check if the existing me.linfo metadata is also sufficient to describe the current inference result # to decide if it is worth caching it again (which would also clear any generated code) - already_inferred = false + already_inferred = !me.linfo.inInference if isdefined(me.linfo, :inferred) inf = me.linfo.inferred if !isa(inf, CodeInfo) || (inf::CodeInfo).inferred @@ -3069,20 +3004,9 @@ function finish(me::InferenceState) end end - # lazy-delete the item from active for several reasons: - # efficiency, correctness, and recursion-safety - nactive[] -= 1 - active[findlast(active, me)] = nothing - - # update all of the callers by traversing the backedges + # update all of the callers with real backedges by traversing the temporary list of backedges for (i, _) in me.backedges - if !me.fixedpoint || !i.fixedpoint - # wake up each backedge, unless both me and it already reached a fixed-point (cycle resolution stage) - delete!(i.edges, me) - i.inworkq || push!(workq, i) - i.inworkq = true - end - add_backedge(me.linfo, i) + add_backedge!(me.linfo, i) end # finalize and record the linfo result @@ -3595,7 +3519,7 @@ function invoke_NF(argexprs, etype::ANY, atypes, sv, atype_unlimited::ANY, local sig = argtypes_to_type(atypes) local li = get_spec_lambda(sig, sv, invoke_data) li === nothing && return false - add_backedge(li, sv) + add_backedge!(li, sv) local stmt = [] push!(stmt, Expr(:(=), linfo_var, li)) spec_hit === nothing && (spec_hit = genlabel(sv)) @@ -3666,7 +3590,7 @@ function invoke_NF(argexprs, etype::ANY, atypes, sv, atype_unlimited::ANY, else local cache_linfo = get_spec_lambda(atype_unlimited, sv, invoke_data) cache_linfo === nothing && return NF - add_backedge(cache_linfo, sv) + add_backedge!(cache_linfo, sv) unshift!(argexprs, cache_linfo) ex = Expr(:invoke) ex.args = argexprs @@ -3904,7 +3828,7 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference linfo = linfo::MethodInstance if linfo.jlcall_api == 2 # in this case function can be inlined to a constant - add_backedge(linfo, sv) + add_backedge!(linfo, sv) return inline_as_constant(linfo.inferred_const, argexprs, sv, invoke_data) end @@ -3921,22 +3845,19 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference # as we'll be able to fix that up at the end of inlinable when we verify the return type. # But `next` and `indexed_next` make tuples which would end up burying some of that information in the AST # where we can't easily correct it afterwards. - frame = InferenceState(linfo, get_source(linfo), #=optimize=#true, #=cache=#false, sv.params) + frame = InferenceState(linfo, #=optimize=#true, #=cache=#false, sv.params) frame.stmt_types[1][3] = VarState(atypes[3], false) - typeinf_loop(frame) + typeinf(frame) else if isdefined(linfo, :inferred) && linfo.inferred !== nothing # use cache inferred = linfo.inferred - elseif linfo.inInference - # use WIP - frame = typeinf_active(linfo) elseif force_infer # create inferred code on-demand # but if we decided in the past not to try to infer this particular signature # (due to signature coarsening in abstract_call_gf_by_type) # don't infer it now, as attempting to force it now would be a bad idea (non terminating) - frame = typeinf_frame(linfo, nothing, #=optimize=#true, #=cache=#true, sv.params) + frame = typeinf_frame(linfo, #=optimize=#true, #=cache=#true, sv.params) end end @@ -3947,9 +3868,9 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference inferred = frame.src if frame.const_api # handle like jlcall_api == 2 if frame.inferred || !frame.cached - add_backedge(frame.linfo, sv) + add_backedge!(frame.linfo, sv) else - add_backedge(frame, sv, 0) + add_backedge!(frame, sv, 0) end if isa(frame.bestguess, Const) inferred_const = (frame.bestguess::Const).val @@ -4010,9 +3931,9 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference if isa(frame, InferenceState) && !frame.inferred && frame.cached # in this case, the actual backedge linfo hasn't been computed # yet, but will be when inference on the frame finishes - add_backedge(frame, sv, 0) + add_backedge!(frame, sv, 0) else - add_backedge(linfo, sv) + add_backedge!(linfo, sv) end spvals = Any[] @@ -5464,7 +5385,7 @@ end # especially try to make sure any recursive and leaf functions have concrete signatures, # since we won't be able to specialize & infer them at runtime -let fs = Any[typeinf_ext, typeinf_loop, typeinf_edge, occurs_outside_getfield, pure_eval_call] +let fs = Any[typeinf_ext, typeinf, typeinf_edge, occurs_outside_getfield, pure_eval_call] for x in t_ffunc_val push!(fs, x[3]) end diff --git a/base/precompile.jl b/base/precompile.jl index 8bc84db37f499..9bd0f90f30572 100644 --- a/base/precompile.jl +++ b/base/precompile.jl @@ -822,9 +822,8 @@ precompile(Tuple{getfield(Base.Cartesian, Symbol("#@nexprs")), Int64, Expr}) precompile(Tuple{typeof(Base.Cartesian._nexprs), Int64, Expr}) precompile(Tuple{typeof(Core.Inference.findnext), Array{Function, 1}, typeof(===), Int64}) precompile(Tuple{typeof(Core.Inference.builtin_tfunction), typeof(===), Array{Any, 1}, Core.Inference.InferenceState, Core.Inference.InferenceParams}) -precompile(Tuple{typeof(Core.Inference.typeinf_frame), Core.MethodInstance, Void, Bool, Bool, Core.Inference.InferenceParams}) -precompile(Tuple{typeof(Core.Inference.typeinf_loop), Core.Inference.InferenceState}) -precompile(Tuple{typeof(Core.Inference.typeinf_frame), Core.Inference.InferenceState}) +precompile(Tuple{typeof(Core.Inference.typeinf_frame), Core.MethodInstance, Bool, Bool, Core.Inference.InferenceParams}) +precompile(Tuple{typeof(Core.Inference.typeinf), Core.Inference.InferenceState}) precompile(Tuple{typeof(Base.Cartesian.inlineanonymous), Expr, Int64}) precompile(Tuple{typeof(Base.Cartesian.lreplace), Expr, Symbol, Int64}) precompile(Tuple{typeof(Base.copy), Expr}) @@ -869,7 +868,6 @@ precompile(Tuple{typeof(Core.Inference._widen_all_consts!), Expr, Array{Bool, 1} precompile(Tuple{typeof(Core.Inference._delete!), Core.Inference.IntSet, Int64}) precompile(Tuple{typeof(Core.Inference.promote_type), Type{Float16}, Type{Int64}}) precompile(Tuple{typeof(Core.Inference.mk_tuplecall), Array{Any, 1}, Core.Inference.InferenceState}) -precompile(Tuple{typeof(Core.Inference.get_source), Core.MethodInstance}) precompile(Tuple{typeof(Core.Inference.inlining_pass), Expr, Core.Inference.InferenceState, Array{Any, 1}, Int64}) precompile(Tuple{typeof(Core.Inference.annotate_slot_load!), Expr, Array{Any, 1}, Core.Inference.InferenceState, Array{Bool, 1}}) precompile(Tuple{typeof(Core.Inference.record_slot_assign!), Core.Inference.InferenceState}) @@ -886,7 +884,6 @@ precompile(Tuple{typeof(Core.Inference.return_type_tfunc), Array{Any, 1}, Array{ precompile(Tuple{typeof(Core.Inference.abstract_call), typeof(===), Tuple{}, Array{Any, 1}, Array{Any, 1}, Core.Inference.InferenceState}) precompile(Tuple{typeof(Core.Inference.abstract_call), typeof(===), Array{Any, 1}, Array{Any, 1}, Array{Any, 1}, Core.Inference.InferenceState}) precompile(Tuple{typeof(Core.Inference.type_too_complex), TypeVar, Int64}) -precompile(Tuple{typeof(Core.Inference.typeinf_frame), Core.MethodInstance, Core.Inference.InferenceState, Bool, Bool, Core.Inference.InferenceParams}) precompile(Tuple{typeof(Core.Inference.abstract_eval), Expr, Array{Any, 1}, Core.Inference.InferenceState}) precompile(Tuple{typeof(Core.Inference._setint!), Core.Inference.IntSet, Int64, Bool}) precompile(Tuple{typeof(Core.Inference.stupdate1!), Array{Any, 1}, Core.Inference.StateUpdate}) diff --git a/base/sysimg.jl b/base/sysimg.jl index d9851dbf30a0d..acfb4c7b68ee4 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -21,7 +21,6 @@ include("coreio.jl") eval(x) = Core.eval(Base, x) eval(m, x) = Core.eval(m, x) -(::Type{T})(arg) where {T} = convert(T, arg)::T # Hidden from the REPL. VecElement{T}(arg) where {T} = VecElement{T}(convert(T, arg)) convert(::Type{T}, arg) where {T<:VecElement} = T(arg) convert(::Type{T}, arg::T) where {T<:VecElement} = arg @@ -73,6 +72,10 @@ include("refpointer.jl") include("checked.jl") importall .Checked +# buggy handling of ispure in type-inference means this should be +# after re-defining the basic operations that they might try to call +(::Type{T})(arg) where {T} = convert(T, arg)::T # Hidden from the REPL. + # vararg Symbol constructor Symbol(x...) = Symbol(string(x...)) diff --git a/src/gf.c b/src/gf.c index 0a4f78878574a..599eabd62b9e1 100644 --- a/src/gf.c +++ b/src/gf.c @@ -238,46 +238,39 @@ jl_code_info_t *jl_type_infer(jl_method_instance_t **pli, size_t world, int forc JL_TIMING(INFERENCE); if (jl_typeinf_func == NULL) return NULL; - jl_code_info_t *src = NULL; #ifdef ENABLE_INFERENCE jl_method_instance_t *li = *pli; - jl_module_t *mod = NULL; - if (li->def != NULL) - mod = li->def->module; - static int inInference = 0; - int lastIn = inInference; - size_t last_age = jl_get_ptls_states()->world_age; - inInference = 1; - if (force || - (last_age != jl_typeinf_world && - mod != jl_gf_mtable(jl_typeinf_func)->module && - (mod != jl_core_module || !lastIn))) { // avoid any potential recursion in calling jl_typeinf_func on itself - assert(li->inInference == 0 && "unexpectedly asked to infer a method that is already being inferred"); - jl_value_t **fargs; - JL_GC_PUSHARGS(fargs, 3); - fargs[0] = (jl_value_t*)jl_typeinf_func; - fargs[1] = (jl_value_t*)li; - fargs[2] = jl_box_ulong(world); + if (li->inInference && !force) + return NULL; + + jl_value_t **fargs; + JL_GC_PUSHARGS(fargs, 3); + fargs[0] = (jl_value_t*)jl_typeinf_func; + fargs[1] = (jl_value_t*)li; + fargs[2] = jl_box_ulong(world); #ifdef TRACE_INFERENCE - if (li->specTypes != (jl_value_t*)jl_emptytuple_type) { - jl_printf(JL_STDERR,"inference on "); - jl_static_show_func_sig(JL_STDERR, (jl_value_t*)li->specTypes); - jl_printf(JL_STDERR, "\n"); - } + if (li->specTypes != (jl_value_t*)jl_emptytuple_type) { + jl_printf(JL_STDERR,"inference on "); + jl_static_show_func_sig(JL_STDERR, (jl_value_t*)li->specTypes); + jl_printf(JL_STDERR, "\n"); + } #endif - jl_get_ptls_states()->world_age = jl_typeinf_world; - jl_svec_t *linfo_src_rettype = (jl_svec_t*)jl_apply_with_saved_exception_state(fargs, 3, 0); - jl_get_ptls_states()->world_age = last_age; - assert((li->def || li->inInference == 0) && "inference failed on a toplevel expr"); - if (jl_is_svec(linfo_src_rettype) && jl_svec_len(linfo_src_rettype) == 3 && - jl_is_method_instance(jl_svecref(linfo_src_rettype, 0)) && - jl_is_code_info(jl_svecref(linfo_src_rettype, 1))) { - *pli = (jl_method_instance_t*)jl_svecref(linfo_src_rettype, 0); - src = (jl_code_info_t*)jl_svecref(linfo_src_rettype, 1); - } - JL_GC_POP(); + jl_ptls_t ptls = jl_get_ptls_states(); + size_t last_age = ptls->world_age; + ptls->world_age = jl_typeinf_world; + li->inInference = 1; + jl_svec_t *linfo_src_rettype = (jl_svec_t*)jl_apply_with_saved_exception_state(fargs, 3, 0); + ptls->world_age = last_age; + assert((li->def || li->inInference == 0) && "inference failed on a toplevel expr"); + + jl_code_info_t *src = NULL; + if (jl_is_svec(linfo_src_rettype) && jl_svec_len(linfo_src_rettype) == 3 && + jl_is_method_instance(jl_svecref(linfo_src_rettype, 0)) && + jl_is_code_info(jl_svecref(linfo_src_rettype, 1))) { + *pli = (jl_method_instance_t*)jl_svecref(linfo_src_rettype, 0); + src = (jl_code_info_t*)jl_svecref(linfo_src_rettype, 1); } - inInference = lastIn; + JL_GC_POP(); #endif return src; } @@ -1658,7 +1651,7 @@ jl_llvm_functions_t jl_compile_for_dispatch(jl_method_instance_t **pli, size_t w return decls; jl_code_info_t *src = NULL; - if (li->def && !jl_is_rettype_inferred(li) && !li->inInference && + if (li->def && !jl_is_rettype_inferred(li) && jl_symbol_name(li->def->name)[0] != '@') { // don't bother with typeinf on macros or toplevel thunks // but try to infer everything else diff --git a/src/interpreter.c b/src/interpreter.c index 4e78fea57383a..99fc01c7c7bb0 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -85,7 +85,7 @@ static jl_value_t *do_invoke(jl_value_t **args, size_t nargs, interpreter_state for (i = 1; i < nargs; i++) argv[i - 1] = eval(args[i], s); jl_method_instance_t *meth = (jl_method_instance_t*)args[0]; - assert(jl_is_method_instance(meth) && !meth->inInference); + assert(jl_is_method_instance(meth)); jl_value_t *result = jl_call_method_internal(meth, argv, nargs - 1); JL_GC_POP(); return result; diff --git a/test/staged.jl b/test/staged.jl index debc3ae58d165..7d6a95ff8b145 100644 --- a/test/staged.jl +++ b/test/staged.jl @@ -147,7 +147,6 @@ module TestGeneratedThrow foo() = (bar(rand() > 0.5 ? 1 : 1.0); error("foo")) function __init__() code_typed(foo,(); optimize = false) - @test Core.Inference.isempty(Core.Inference.active) && Core.Inference.isempty(Core.Inference.workq) cfunction(foo,Void,()) end end @@ -175,7 +174,7 @@ let gf_err, tsk = @async nothing # create a Task for yield to try to run end @test_throws ErrorException gf_err() @test_throws ErrorException gf_err() - @test gf_err_ref[] == 4 + @test gf_err_ref[] == 3 end gf_err_ref[] = 0 From bbe8e18daae4fcdda0c470870d893828fb82fb24 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Fri, 5 May 2017 18:11:18 -0400 Subject: [PATCH 0775/1534] Separate out EH handler lowering into its own pass Currently it's being done as part of the GC root lowering pass. However, I'm working on replacing that pass, so this functionality needed to be separated out anyway. While I'm here: 1. Simplify the algorithm to a simple DFS numbering 2. Have it insert lifetime intrinisics to allow the optimizer to do stack slot coloring later 3. Add a test for this pass --- src/Makefile | 2 +- src/jitlayers.cpp | 2 + src/jitlayers.h | 1 + src/llvm-gcroot.cpp | 198 ------------------------ src/llvm-lower-handlers.cpp | 240 ++++++++++++++++++++++++++++++ test/llvmpasses/lower-handlers.ll | 25 ++++ 6 files changed, 269 insertions(+), 199 deletions(-) create mode 100644 src/llvm-lower-handlers.cpp create mode 100644 test/llvmpasses/lower-handlers.ll diff --git a/src/Makefile b/src/Makefile index 9fde74da895a8..55e16733fcc11 100644 --- a/src/Makefile +++ b/src/Makefile @@ -53,7 +53,7 @@ endif LLVMLINK := ifeq ($(JULIACODEGEN),LLVM) -SRCS += codegen jitlayers disasm debuginfo llvm-simdloop llvm-ptls llvm-gcroot cgmemmgr +SRCS += codegen jitlayers disasm debuginfo llvm-simdloop llvm-ptls llvm-gcroot llvm-lower-handlers cgmemmgr FLAGS += -I$(shell $(LLVM_CONFIG_HOST) --includedir) LLVM_LIBS := all ifeq ($(USE_POLLY),1) diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index bd6a40518bad2..336bde973fbb1 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -111,6 +111,7 @@ void addOptimizationPasses(legacy::PassManager *PM) void addOptimizationPasses(PassManager *PM) #endif { + PM->add(createLowerExcHandlersPass()); PM->add(createLowerGCFramePass()); #ifdef JL_DEBUG_BUILD PM->add(createVerifierPass()); @@ -489,6 +490,7 @@ JuliaOJIT::JuliaOJIT(TargetMachine &TM) addOptimizationPasses(&PM); } else { + PM.add(createLowerExcHandlersPass()); PM.add(createLowerGCFramePass()); PM.add(createLowerPTLSPass(imaging_mode)); } diff --git a/src/jitlayers.h b/src/jitlayers.h index 73817ef527f71..92a318c2e3fbf 100644 --- a/src/jitlayers.h +++ b/src/jitlayers.h @@ -248,6 +248,7 @@ JL_DLLEXPORT extern LLVMContext &jl_LLVMContext; Pass *createLowerPTLSPass(bool imaging_mode); Pass *createLowerGCFramePass(); +Pass *createLowerExcHandlersPass(); // Whether the Function is an llvm or julia intrinsic. static inline bool isIntrinsicFunction(Function *F) { diff --git a/src/llvm-gcroot.cpp b/src/llvm-gcroot.cpp index 7e6bc07a8c492..5f0af51c20f1a 100644 --- a/src/llvm-gcroot.cpp +++ b/src/llvm-gcroot.cpp @@ -193,7 +193,6 @@ class JuliaGCAllocator { std::map > &bb_uses, std::map ®s_used); void rearrangeRoots(); - void lowerHandlers(); public: void allocate_frame(); }; @@ -231,176 +230,6 @@ struct HandlerData { #endif }; -void JuliaGCAllocator::lowerHandlers() -{ - if (!except_enter_func) - return; - auto jlenter_func = M.getNamedValue("jl_enter_handler"); - auto setjmp_func = M.getNamedValue(jl_setjmp_name); - // Collect all exception enters - std::map handlers; - for (auto &BB: F) { - for (auto &I: BB) { - auto call = dyn_cast(&I); - if (call && call->getCalledValue() == except_enter_func) { - handlers[call] = HandlerData(); - } - } - } - - if (handlers.empty()) - return; - - typedef std::map::iterator hdlr_iter_t; - // For each exception enter, compute the life time of the enter, find - // the corresponding leaves and collect a list of nested exception frames. - // This assumes the exception frames have simple structure. E.g. - // there's no recursion and different frames do not share the same leave. - std::function process_handler = [&] (hdlr_iter_t hdlr) { - auto enter = hdlr->first; - auto &data = hdlr->second; - if (data.processed) - return; - data.processed = true; - std::vector frontier = { - ++BasicBlock::iterator(enter) - }; - // Start from the enter, the enter is live until it hits a leave - // or the control flow terminates. - std::set visited; - auto add_inst = [&] (BasicBlock::iterator it) { - if (visited.insert(&*it).second) { - frontier.push_back(it); - } - }; - while (!frontier.empty()) { - BasicBlock::iterator IT = frontier.back(); - Instruction *I = &*IT; - ++IT; - frontier.pop_back(); - if (I->isTerminator()) { - BasicBlock *bb = I->getParent(); - for (auto S = succ_begin(bb), E = succ_end(bb); S != E; S++) - add_inst(S->getFirstInsertionPt()); - continue; - } - auto call = dyn_cast(I); - if (!call) { - add_inst(IT); - continue; - } - auto callee = call->getCalledValue(); - if (callee == except_enter_func) { - // Nested frame, make sure the frame is processed and skip to - // its leaves. - auto other_it = handlers.find(call); - assert(other_it != handlers.end()); - process_handler(other_it); - auto &other_data = other_it->second; - data.nested.insert(call); - // Record a reference to parent frame, there should be only - // one parent in most cases although more than one parent is - // also possible if LLVM split the enter call. - if (__unlikely(other_data.parent_vec)) { - other_data.parent_vec->push_back(enter); - } - else if (__unlikely(other_data.parent)) { - other_data.parent_vec.reset( - new std::vector{other_data.parent, enter}); - } - else { - other_data.parent = enter; - } - for (auto leave: other_it->second.leaves) { - if (leave.second > 0) { - data.leaves.push_back(std::make_pair(leave.first, - leave.second - 1)); - } - else { - add_inst(++BasicBlock::iterator(leave.first)); - } - } - } - else if (callee == jlleave_func) { - // Leave, record how many pops are left on this leave. - assert(call->getNumArgOperands() == 1); - auto arg = cast(call->getArgOperand(0)); - uint64_t pop_count = arg->getLimitedValue(); - assert(pop_count >= 1); - data.leaves.push_back(std::make_pair(call, pop_count - 1)); - } - else { - // Otherwise, go to the next instruction. - add_inst(IT); - } - } - }; - - // Make sure all frames are processed. - for (auto IT = handlers.begin(), E = handlers.end(); IT != E; ++IT) - process_handler(IT); - - std::set processing; - Value *handler_sz = ConstantInt::get(T_int32, sizeof(jl_handler_t)); - // Now allocate the stack slots. - // At each iteration, we allocate a new handler and assign all the remaining - // frames that don't have a non-processed child to this handler. - Instruction *firstInst = &F.getEntryBlock().front(); - while (!handlers.empty()) { - processing.clear(); -#if JL_LLVM_VERSION >= 50000 - auto buff = new AllocaInst(T_int8, 0, handler_sz, "", firstInst); -#else - auto buff = new AllocaInst(T_int8, handler_sz, "", firstInst); -#endif - buff->setAlignment(16); - // Collect the list of frames to process. - for (auto &hdlr: handlers) { - auto enter = hdlr.first; - auto &nested = hdlr.second.nested; - if (nested.empty()) { - processing.insert(enter); - } - } - // There shouldn't be loops so there has to be leafs - assert(!processing.empty()); - for (auto enter: processing) { - // Lower the enter - auto new_enter = CallInst::Create(jlenter_func, buff, "", enter); -#ifndef _OS_WINDOWS_ - // For LLVM 3.3 compatibility - Value *args[] = {buff, ConstantInt::get(T_int32,0)}; - auto sj = CallInst::Create(setjmp_func, args, "", enter); -#else - auto sj = CallInst::Create(setjmp_func, buff, "", enter); -#endif - // We need to mark this on the call site as well. See issue #6757 - sj->setCanReturnTwice(); -#if JL_LLVM_VERSION >= 30600 - if (auto dbg = enter->getMetadata(LLVMContext::MD_dbg)) { - new_enter->setMetadata(LLVMContext::MD_dbg, dbg); - sj->setMetadata(LLVMContext::MD_dbg, dbg); - } -#else - (void)new_enter; -#endif - // Remove it from all the parents. - auto it = handlers.find(enter); - if (__unlikely(it->second.parent_vec)) { - for (auto parent: *it->second.parent_vec) { - handlers.find(parent)->second.nested.erase(enter); - } - } - else if (it->second.parent) { - handlers.find(it->second.parent)->second.nested.erase(enter); - } - // Delete it. - handlers.erase(it); - enter->replaceAllUsesWith(sj); - enter->eraseFromParent(); - } - } -} Instruction *JuliaGCAllocator::get_pgcstack(Instruction *ptlsStates) { @@ -755,7 +584,6 @@ void JuliaGCAllocator::rearrangeRoots() void JuliaGCAllocator::allocate_frame() { - lowerHandlers(); if (!ptlsStates) return; Instruction *last_gcframe_inst = gcframe; @@ -1165,36 +993,11 @@ static void eraseFunction(Module &M, const char *name) } } -static void ensure_enter_function(Module &M) -{ - auto T_int8 = Type::getInt8Ty(M.getContext()); - auto T_pint8 = PointerType::get(T_int8, 0); - auto T_void = Type::getVoidTy(M.getContext()); - auto T_int32 = Type::getInt32Ty(M.getContext()); - if (!M.getNamedValue("jl_enter_handler")) { - std::vector ehargs(0); - ehargs.push_back(T_pint8); - Function::Create(FunctionType::get(T_void, ehargs, false), - Function::ExternalLinkage, "jl_enter_handler", &M); - } - if (!M.getNamedValue(jl_setjmp_name)) { - std::vector args2(0); - args2.push_back(T_pint8); -#ifndef _OS_WINDOWS_ - args2.push_back(T_int32); -#endif - Function::Create(FunctionType::get(T_int32, args2, false), - Function::ExternalLinkage, jl_setjmp_name, &M) - ->addFnAttr(Attribute::ReturnsTwice); - } -} - bool LowerGCFrame::runOnModule(Module &M) { MDNode *tbaa_gcframe = tbaa_make_child("jtbaa_gcframe").first; Function *ptls_getter = M.getFunction("jl_get_ptls_states"); - ensure_enter_function(M); FunctionType *functype = nullptr; Type *T_pjlvalue = nullptr; if (ptls_getter) { @@ -1214,7 +1017,6 @@ bool LowerGCFrame::runOnModule(Module &M) eraseFunction(M, "julia.gc_root_kill"); eraseFunction(M, "julia.jlcall_frame_decl"); eraseFunction(M, "julia.gcroot_flush"); - eraseFunction(M, "julia.except_enter"); return true; } diff --git a/src/llvm-lower-handlers.cpp b/src/llvm-lower-handlers.cpp new file mode 100644 index 0000000000000..c85c58ef94d57 --- /dev/null +++ b/src/llvm-lower-handlers.cpp @@ -0,0 +1,240 @@ +// This file is a part of Julia. License is MIT: https://julialang.org/license + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "llvm-version.h" +#include "julia.h" + +#define DEBUG_TYPE "lower_handlers" +#undef DEBUG + +using namespace llvm; + +/* Lowers Julia Exception Handlers and colors EH frames. + * + * Our task is to lower: + * call void @julia.except_enter() + * <...> + * call void jl_pop_handler(1) + * + * to + * + * call void @jl_enter_handler(jl_handler *%buff) + * <...> + * call void jl_pop_handler(1) + * + * Where buff is an appropriate stack slot handler. + * + * We make the following assumptions: + * - All EH frames are completely nested. + * - The exception nestedness of a BB is not dynamic. I.e. we don't allow + * the following: + * br i1 %cond, %left, %right + * / \ + * except.enter br mid + * br mid | + * \ / + * br i1 %cond, %left2, %right2 + * / \ + * jl_pop_hander ret + * ret + * + * The frontend doesn't emit structures like this. However, the optimizer + * could easily introduce them, so this pass should run early after IRGen. + * + * Because of these assumptions, the algorithm is very simple. We simply label + * the handler depth at every basic block using a DFS search. For each enter + * we encounter, we record the current depth and then allocate an exception + * handler frame for every level. + * + * As an additional optimization, we also insert lifetime intrinsics for the + * handler structures to tell LLVM that it is free to re-use the stack slot + * while the handler is not being used. + */ +struct LowerExcHandlers : public FunctionPass { + static char ID; + LowerExcHandlers() : FunctionPass(ID) + {} + +private: + Function *except_enter_func; + Function *leave_func; + Function *jlenter_func; + Function *setjmp_func; + Function *lifetime_start; + Function *lifetime_end; + + bool doInitialization(Module &M) override; + bool runOnFunction(Function &F) override; +}; + +/* + * If the module doesn't have declarations for the jl_enter_handler and setjmp + * functions, insert them. + */ +static void ensure_enter_function(Module &M) +{ + auto T_int8 = Type::getInt8Ty(M.getContext()); + auto T_pint8 = PointerType::get(T_int8, 0); + auto T_void = Type::getVoidTy(M.getContext()); + auto T_int32 = Type::getInt32Ty(M.getContext()); + if (!M.getNamedValue("jl_enter_handler")) { + std::vector ehargs(0); + ehargs.push_back(T_pint8); + Function::Create(FunctionType::get(T_void, ehargs, false), + Function::ExternalLinkage, "jl_enter_handler", &M); + } + if (!M.getNamedValue(jl_setjmp_name)) { + std::vector args2(0); + args2.push_back(T_pint8); +#ifndef _OS_WINDOWS_ + args2.push_back(T_int32); +#endif + Function::Create(FunctionType::get(T_int32, args2, false), + Function::ExternalLinkage, jl_setjmp_name, &M) + ->addFnAttr(Attribute::ReturnsTwice); + } +} + +bool LowerExcHandlers::doInitialization(Module &M) { + except_enter_func = M.getFunction("julia.except_enter"); + if (!except_enter_func) + return false; + ensure_enter_function(M); + leave_func = M.getFunction("jl_pop_handler"); + jlenter_func = M.getFunction("jl_enter_handler"); + setjmp_func = M.getFunction(jl_setjmp_name); + lifetime_start = Intrinsic::getDeclaration(&M, Intrinsic::lifetime_start); + lifetime_end = Intrinsic::getDeclaration(&M, Intrinsic::lifetime_end); +} + +bool LowerExcHandlers::runOnFunction(Function &F) { + if (!except_enter_func) + return false; // No EH frames in this module + + /* Step 1: EH Depth Numbering */ + std::map EnterDepth; + std::map LeaveDepth; + std::map ExitDepth; + int MaxDepth = 0; + // Compute EH Depth at each basic block using a DFS traversal. + for (df_iterator I = df_begin(&F.getEntryBlock()), + E = df_end(&F.getEntryBlock()); I != E; ++I) { + auto *BB = *I; + int Depth = 0; + /* Here we use the assumption that all incoming edges have the same + * EH depth. + */ + for (auto *Pred : predecessors(BB)) { + auto it = ExitDepth.find(Pred); + if (it != ExitDepth.end()) { + Depth = it->second; + break; + } + } + /* Compute the depth within the basic block */ + for (auto &I : *BB) { + auto *CI = dyn_cast(&I); + if (!CI) + continue; + Function *Callee = CI->getCalledFunction(); + if (!Callee) + continue; + if (Callee == except_enter_func) + EnterDepth[CI] = Depth++; + else if (Callee == leave_func) { + LeaveDepth[CI] = Depth; + Depth -= cast(CI->getArgOperand(0))->getLimitedValue(); + } + assert(Depth >= 0); + if (Depth > MaxDepth) + MaxDepth = Depth; + } + /* Remember the depth at the BB boundary */ + ExitDepth[BB] = Depth; + } + + /* Step 2: EH Frame lowering */ + // Allocate stack space for each handler. We allocate these as separate + // allocas so the optimizer can later merge and reaarange them if it wants + // to. + Value *handler_sz = ConstantInt::get(Type::getInt32Ty(F.getContext()), + sizeof(jl_handler_t)); + Value *handler_sz64 = ConstantInt::get(Type::getInt64Ty(F.getContext()), + sizeof(jl_handler_t)); + Instruction *firstInst = &F.getEntryBlock().front(); + std::vector buffs; + for (int i = 0; i < MaxDepth; ++i) { + auto *buff = new AllocaInst(Type::getInt8Ty(F.getContext()), +#if JL_LLVM_VERSION >= 50000 + 0, +#endif + handler_sz, "", firstInst); + buff->setAlignment(16); + buffs.push_back(buff); + } + + // Lower enter funcs + for (auto it : EnterDepth) { + assert(it.second >= 0); + AllocaInst *buff = buffs[it.second]; + CallInst *enter = it.first; + auto new_enter = CallInst::Create(jlenter_func, buff, "", enter); + Value *lifetime_args[] = { + handler_sz64, + buff + }; + CallInst::Create(lifetime_start, lifetime_args, "", new_enter); +#ifndef _OS_WINDOWS_ + // For LLVM 3.3 compatibility + Value *args[] = {buff, + ConstantInt::get(Type::getInt32Ty(F.getContext()), 0)}; + auto sj = CallInst::Create(setjmp_func, args, "", enter); +#else + auto sj = CallInst::Create(setjmp_func, buff, "", enter); +#endif + // We need to mark this on the call site as well. See issue #6757 + sj->setCanReturnTwice(); + if (auto dbg = enter->getMetadata(LLVMContext::MD_dbg)) { + new_enter->setMetadata(LLVMContext::MD_dbg, dbg); + sj->setMetadata(LLVMContext::MD_dbg, dbg); + } + enter->replaceAllUsesWith(sj); + enter->eraseFromParent(); + } + // Insert lifetime end intrinsics after every leave. + for (auto it : LeaveDepth) { + int StartDepth = it.second - 1; + int npops = cast(it.first->getArgOperand(0))->getLimitedValue(); + for (int i = 0; i < npops; ++i) { + assert(StartDepth-i >= 0); + Value *lifetime_args[] = { + handler_sz64, + buffs[StartDepth-i] + }; + auto LifetimeEnd = CallInst::Create(lifetime_end, lifetime_args); + LifetimeEnd->insertAfter(it.first); + } + } + return true; +} + +char LowerExcHandlers::ID = 0; +static RegisterPass X("LowerExcHandlers", "Lower Julia Exception Handlers", + false /* Only looks at CFG */, + false /* Analysis Pass */); + +Pass *createLowerExcHandlersPass() +{ + return new LowerExcHandlers(); +} diff --git a/test/llvmpasses/lower-handlers.ll b/test/llvmpasses/lower-handlers.ll new file mode 100644 index 0000000000000..0db907ecee969 --- /dev/null +++ b/test/llvmpasses/lower-handlers.ll @@ -0,0 +1,25 @@ +; RUN: opt -load libjulia.so -LowerExcHandlers -S %s | FileCheck %s + +attributes #1 = { returns_twice } +declare i32 @julia.except_enter() #1 +declare void @jl_pop_handler(i32) +declare i8**** @jl_get_ptls_states() + +define void @simple() { +top: + %ptls = call i8**** @jl_get_ptls_states() +; CHECK: call void @llvm.lifetime.start +; CHECK: call void @jl_enter_handler +; CHECK: setjmp + %r = call i32 @julia.except_enter() + %cmp = icmp eq i32 %r, 0 + br i1 %cmp, label %try, label %catch +try: + br label %after +catch: + br label %after +after: + call void @jl_pop_handler(i32 1) +; CHECK: llvm.lifetime.end + ret void +} From 6f7c7638b06e2f213a9b0a29cf007e7863bcedf3 Mon Sep 17 00:00:00 2001 From: Jim Garrison Date: Mon, 15 May 2017 15:41:37 -0400 Subject: [PATCH 0776/1534] Mention `inv` in docstrings of factorizations that implement it Ref https://github.com/JuliaLang/julia/issues/21453#issuecomment-296036653 [av skip] --- base/linalg/lu.jl | 1 + base/linalg/qr.jl | 2 +- base/sparse/cholmod.jl | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/base/linalg/lu.jl b/base/linalg/lu.jl index 67cc4dd81dbdb..bb11de6f77fd4 100644 --- a/base/linalg/lu.jl +++ b/base/linalg/lu.jl @@ -112,6 +112,7 @@ The relationship between `F` and `A` is |:---------------------------------|:-----|:-----------------------| | [`/`](@ref) | ✓ | | | [`\\`](@ref) | ✓ | ✓ | +| [`inv`](@ref) | ✓ | ✓ | | [`det`](@ref) | ✓ | ✓ | | [`logdet`](@ref) | ✓ | ✓ | | [`logabsdet`](@ref) | ✓ | ✓ | diff --git a/base/linalg/qr.jl b/base/linalg/qr.jl index b879ed801b780..2d6d723adefe1 100644 --- a/base/linalg/qr.jl +++ b/base/linalg/qr.jl @@ -238,7 +238,7 @@ The individual components of the factorization `F` can be accessed by indexing w - `F[:p]`: the permutation vector of the pivot ([`QRPivoted`](@ref) only) - `F[:P]`: the permutation matrix of the pivot ([`QRPivoted`](@ref) only) -The following functions are available for the `QR` objects: [`size`](@ref) +The following functions are available for the `QR` objects: [`inv`](@ref), [`size`](@ref), and [`\\`](@ref). When `A` is rectangular, `\\` will return a least squares solution and if the solution is not unique, the one with smallest norm is returned. diff --git a/base/sparse/cholmod.jl b/base/sparse/cholmod.jl index a8688986ed90a..2d812d07bba85 100644 --- a/base/sparse/cholmod.jl +++ b/base/sparse/cholmod.jl @@ -1511,7 +1511,7 @@ have the type tag, it must still be symmetric or Hermitian. A fill-reducing permutation is used. `F = ldltfact(A)` is most frequently used to solve systems of equations `A*x = b` with `F\\b`. The returned factorization object `F` also supports the methods [`diag`](@ref), -[`det`](@ref), and [`logdet`](@ref). +[`det`](@ref), [`logdet`](@ref), and [`inv`](@ref). You can extract individual factors from `F` using `F[:L]`. However, since pivoting is on by default, the factorization is internally represented as `A == P'*L*D*L'*P` with a permutation matrix `P`; From 84eeb40f13a9bd12ddb86a3d327460bbaff30a04 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Mon, 15 May 2017 19:25:25 -0400 Subject: [PATCH 0777/1534] Make CoreIO thread-safer Also test for `fd != -1` instead since that is a defined invalid value. --- src/jl_uv.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/jl_uv.c b/src/jl_uv.c index d1008481db2d9..3afc2c6cd6b25 100644 --- a/src/jl_uv.c +++ b/src/jl_uv.c @@ -355,7 +355,7 @@ JL_DLLEXPORT int jl_fs_write(int handle, const char *data, size_t len, int64_t offset) { jl_ptls_t ptls = jl_get_ptls_states(); - if (ptls->safe_restore) + if (ptls->safe_restore || ptls->tid != 0) return write(handle, data, len); uv_fs_t req; uv_buf_t buf[1]; @@ -432,7 +432,7 @@ JL_DLLEXPORT void jl_uv_puts(uv_stream_t *stream, const char *str, size_t n) sizeof(((uv_stream_t*)0)->type) == sizeof(((ios_t*)0)->bm), "UV and ios layout mismatch"); - uv_file fd = 0; + uv_file fd = -1; // Fallback for output during early initialisation... if (stream == (void*)STDOUT_FILENO || stream == (void*)STDERR_FILENO) { @@ -443,7 +443,18 @@ JL_DLLEXPORT void jl_uv_puts(uv_stream_t *stream, const char *str, size_t n) fd = ((jl_uv_file_t*)stream)->file; } - if (fd) { + // Hack to make CoreIO thread-safer + jl_ptls_t ptls = jl_get_ptls_states(); + if (ptls->tid != 0) { + if (stream == JL_STDOUT) { + fd = STDOUT_FILENO; + } + else if (stream == JL_STDERR) { + fd = STDERR_FILENO; + } + } + + if (fd != -1) { // Write to file descriptor... jl_fs_write(fd, str, n, -1); } From 213223f4b922662395336af9fc1ea31c6f5c6c7a Mon Sep 17 00:00:00 2001 From: Sanjay Sri Vallabh Date: Sun, 7 May 2017 14:43:42 +0530 Subject: [PATCH 0778/1534] Introduce USE_POLLY_ACC Introduce the USE_POLLY_ACC variable to enable Polly's GPGPU codegeneration facilities. --- Make.inc | 1 + deps/llvm.mk | 3 +++ src/Makefile | 3 +++ 3 files changed, 7 insertions(+) diff --git a/Make.inc b/Make.inc index 498394a37d95b..2737a661a4346 100644 --- a/Make.inc +++ b/Make.inc @@ -239,6 +239,7 @@ BUILD_LLVM_CLANG := 0 BUILD_LLDB := 0 USE_POLLY := 0 USE_POLLY_OPENMP := 0 +USE_POLLY_ACC := 0 # Cross-compile #XC_HOST := i686-w64-mingw32 diff --git a/deps/llvm.mk b/deps/llvm.mk index 5ac5ab438f51a..ec1bfb0da15f7 100644 --- a/deps/llvm.mk +++ b/deps/llvm.mk @@ -66,6 +66,9 @@ LLVM_CXXFLAGS += $(CXXFLAGS) LLVM_CPPFLAGS += $(CPPFLAGS) LLVM_LDFLAGS += $(LDFLAGS) LLVM_CMAKE += -DLLVM_TARGETS_TO_BUILD:STRING="$(LLVM_TARGETS)" -DCMAKE_BUILD_TYPE="$(LLVM_CMAKE_BUILDTYPE)" +ifeq ($(USE_POLLY_ACC),1) +LLVM_CMAKE += -DPOLLY_ENABLE_GPGPU_CODEGEN=ON +endif LLVM_CMAKE += -DLLVM_TOOLS_INSTALL_DIR=$(shell $(JULIAHOME)/contrib/relative_path.sh $(build_prefix) $(build_depsbindir)) LLVM_CMAKE += -DLLVM_BINDINGS_LIST="" -DLLVM_INCLUDE_DOCS=Off -DLLVM_ENABLE_TERMINFO=Off -DHAVE_HISTEDIT_H=Off -DHAVE_LIBEDIT=Off LLVM_FLAGS += --disable-profiling --enable-static --enable-targets=$(LLVM_TARGETS) diff --git a/src/Makefile b/src/Makefile index 9fde74da895a8..abeb5205637e4 100644 --- a/src/Makefile +++ b/src/Makefile @@ -64,6 +64,9 @@ FLAGS += -DUSE_POLLY ifeq ($(USE_POLLY_OPENMP),1) FLAGS += -fopenmp endif +ifeq ($(USE_POLLY_ACC),1) +LLVMLINK += -lPollyPPCG -Wl,-rpath=$(shell $(LLVM_CONFIG_HOST) --libdir),--no-as-needed -lGPURuntime -Wl,--as-needed +endif endif else SRCS += anticodegen From e51d366d505257e9be4f42c6b30c8c6cd56abc8d Mon Sep 17 00:00:00 2001 From: Sanjay Sri Vallabh Date: Mon, 15 May 2017 00:43:53 +0530 Subject: [PATCH 0779/1534] Trying out force linking GPURUNTIME through a header file. --- src/Makefile | 3 ++- src/codegen.cpp | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index abeb5205637e4..dc1ae7e56dbbb 100644 --- a/src/Makefile +++ b/src/Makefile @@ -65,7 +65,8 @@ ifeq ($(USE_POLLY_OPENMP),1) FLAGS += -fopenmp endif ifeq ($(USE_POLLY_ACC),1) -LLVMLINK += -lPollyPPCG -Wl,-rpath=$(shell $(LLVM_CONFIG_HOST) --libdir),--no-as-needed -lGPURuntime -Wl,--as-needed +LLVMLINK += -lPollyPPCG -lGPURuntime +FLAGS += -DUSE_POLLY_ACC endif endif else diff --git a/src/codegen.cpp b/src/codegen.cpp index a3cd82040a16e..f39bd1a08691e 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -105,6 +105,8 @@ #if defined(USE_POLLY) #include #include +#if define(USE_POLLY_ACC) +#include #endif #include "fix_llvm_assert.h" @@ -7304,6 +7306,9 @@ extern "C" void jl_init_codegen(void) PassRegistry &Registry = *PassRegistry::getPassRegistry(); polly::initializePollyPasses(Registry); initializeAnalysis(Registry); +#ifdef USE_POLLY_ACC + polly::ForceGPURuntimeLinking(); +#endif #endif InitializeNativeTarget(); From 23471d59c63e1801c3611220aef16e34c4a48644 Mon Sep 17 00:00:00 2001 From: Sanjay Sri Vallabh Date: Mon, 15 May 2017 16:50:53 +0530 Subject: [PATCH 0780/1534] USE_POLLY_ACC is defined. Problem with declaring polly_devSynch as extern. --- src/codegen.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index f39bd1a08691e..7c949f7090d71 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -105,9 +105,10 @@ #if defined(USE_POLLY) #include #include -#if define(USE_POLLY_ACC) +#if defined(USE_POLLY_ACC) #include #endif +#endif #include "fix_llvm_assert.h" using namespace llvm; @@ -7307,6 +7308,7 @@ extern "C" void jl_init_codegen(void) polly::initializePollyPasses(Registry); initializeAnalysis(Registry); #ifdef USE_POLLY_ACC +#pragma message "ForceGPURuntimeLinking!!\n" polly::ForceGPURuntimeLinking(); #endif #endif From 732f630c53619468d83fdd921e4d269cca5a8d3f Mon Sep 17 00:00:00 2001 From: Sanjay Sri Vallabh Date: Tue, 16 May 2017 09:42:43 +0530 Subject: [PATCH 0781/1534] included CUDA include folder GPUJIT.c --- src/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Makefile b/src/Makefile index dc1ae7e56dbbb..e45e77ea2f0f9 100644 --- a/src/Makefile +++ b/src/Makefile @@ -67,6 +67,8 @@ endif ifeq ($(USE_POLLY_ACC),1) LLVMLINK += -lPollyPPCG -lGPURuntime FLAGS += -DUSE_POLLY_ACC +FLAGS += -I/usr/local/cuda/include +FLAGS += -I$(shell $(LLVM_CONFIG_HOST) --src-root)/tools/polly/tools endif endif else From 10c07464ee56bb853c5148302314bc9c95f5a4e1 Mon Sep 17 00:00:00 2001 From: GregPlowman Date: Thu, 4 May 2017 21:52:57 +1000 Subject: [PATCH 0782/1534] Issue 19960 - loading module on remote workers --- base/loading.jl | 10 ++++++++-- test/compile.jl | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/base/loading.jl b/base/loading.jl index 5601825f94b68..7afb043954199 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -218,8 +218,14 @@ function _require_search_from_serialized(node::Int, mod::Symbol, sourcepath::Str end for path_to_try in paths::Vector{String} - if stale_cachefile(sourcepath, path_to_try) - continue + if node == myid() + if stale_cachefile(sourcepath, path_to_try) + continue + end + else + if @fetchfrom node stale_cachefile(sourcepath, path_to_try) + continue + end end restored = _require_from_serialized(node, mod, path_to_try, toplevel_load) if isa(restored, Exception) diff --git a/test/compile.jl b/test/compile.jl index caf55a6c1592a..2bfa971a00a60 100644 --- a/test/compile.jl +++ b/test/compile.jl @@ -524,4 +524,55 @@ let module_name = string("a",randstring()) rm(file_name) end +# Issue #19960 +let + # ideally this would test with workers on a remote host that does not have access to the master node filesystem for loading + # can simulate this for local workers by using relative load paths on master node that are not valid on workers + # so addprocs before changing directory to temp directory, otherwise workers will inherit temp working directory + + test_workers = addprocs(1) + temp_path = mktempdir() + save_cwd = pwd() + cd(temp_path) + load_path = mktempdir(temp_path) + load_cache_path = mktempdir(temp_path) + unshift!(LOAD_PATH, basename(load_path)) + unshift!(Base.LOAD_CACHE_PATH, basename(load_cache_path)) + + ModuleA = :Issue19960A + ModuleB = :Issue19960B + + write(joinpath(load_path, "$ModuleA.jl"), + """ + __precompile__(true) + module $ModuleA + export f + f() = myid() + end + """) + + write(joinpath(load_path, "$ModuleB.jl"), + """ + __precompile__(true) + module $ModuleB + using $ModuleA + export g + g() = f() + end + """) + + try + @eval using $ModuleB + for wid in test_workers + @test remotecall_fetch(g, wid) == wid + end + finally + shift!(LOAD_PATH) + shift!(Base.LOAD_CACHE_PATH) + cd(save_cwd) + rm(temp_path, recursive=true) + rmprocs(test_workers) + end +end + end # !withenv From 4009b0cfc98beed0ae68dea031e373516ea45e50 Mon Sep 17 00:00:00 2001 From: Mus M Date: Tue, 16 May 2017 00:54:23 -0400 Subject: [PATCH 0783/1534] Use VersionNumber for libllvm_version --- base/Makefile | 2 +- base/atomics.jl | 6 +++--- base/version.jl | 2 ++ test/cmdlineargs.jl | 2 +- test/llvmcall.jl | 2 +- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/base/Makefile b/base/Makefile index 04c97fda88e8d..02d68c08ea3cd 100644 --- a/base/Makefile +++ b/base/Makefile @@ -55,7 +55,7 @@ else endif @echo "const libfftw_name = \"$(LIBFFTWNAME)\"" >> $@ @echo "const libfftwf_name = \"$(LIBFFTWFNAME)\"" >> $@ - @echo "const libllvm_version = \"$$($(LLVM_CONFIG_HOST) --version)\"" >> $@ + @echo "const libllvm_version_string = \"$$($(LLVM_CONFIG_HOST) --version)\"" >> $@ @echo "const VERSION_STRING = \"$(JULIA_VERSION)\"" >> $@ @echo "const TAGGED_RELEASE_BANNER = \"$(TAGGED_RELEASE_BANNER)\"" >> $@ @echo "const SYSCONFDIR = \"$(sysconfdir_rel)\"" >> $@ diff --git a/base/atomics.jl b/base/atomics.jl index 7374bad3f4f2e..a2dfbef623b31 100644 --- a/base/atomics.jl +++ b/base/atomics.jl @@ -17,7 +17,7 @@ export # Disable 128-bit types on 32-bit Intel sytems due to LLVM problems; # see (fixed on LLVM 3.9) # 128-bit atomics do not exist on AArch32. -if (VersionNumber(Base.libllvm_version) < v"3.9-" && ARCH === :i686) || +if (Base.libllvm_version < v"3.9-" && ARCH === :i686) || startswith(string(ARCH), "arm") const inttypes = (Int8, Int16, Int32, Int64, UInt8, UInt16, UInt32, UInt64) @@ -330,8 +330,8 @@ alignment(::Type{T}) where {T} = ccall(:jl_alignment, Cint, (Csize_t,), sizeof(T for typ in atomictypes lt = llvmtypes[typ] ilt = llvmtypes[inttype(typ)] - rt = VersionNumber(Base.libllvm_version) >= v"3.6" ? "$lt, $lt*" : "$lt*" - irt = VersionNumber(Base.libllvm_version) >= v"3.6" ? "$ilt, $ilt*" : "$ilt*" + rt = Base.libllvm_version >= v"3.6" ? "$lt, $lt*" : "$lt*" + irt = Base.libllvm_version >= v"3.6" ? "$ilt, $ilt*" : "$ilt*" if VersionNumber(Base.libllvm_version) >= v"3.8" @eval getindex(x::Atomic{$typ}) = llvmcall($""" diff --git a/base/version.jl b/base/version.jl index 1bae427a64576..213f603ec53f8 100644 --- a/base/version.jl +++ b/base/version.jl @@ -223,6 +223,8 @@ catch e VersionNumber(0) end +libllvm_version = convert(VersionNumber, libllvm_version_string) + function banner(io::IO = STDOUT) if GIT_VERSION_INFO.tagged_commit commit_string = TAGGED_RELEASE_BANNER diff --git a/test/cmdlineargs.jl b/test/cmdlineargs.jl index 802f9ad31d070..47cb9b2488361 100644 --- a/test/cmdlineargs.jl +++ b/test/cmdlineargs.jl @@ -322,7 +322,7 @@ let exename = `$(Base.julia_cmd()) --precompiled=yes --startup-file=no` # issue #12671, starting from a non-directory # rm(dir) fails on windows with Permission denied # and was an upstream bug in llvm <= v3.3 - if !is_windows() && VersionNumber(Base.libllvm_version) > v"3.3" + if !is_windows() && Base.libllvm_version > v"3.3" testdir = mktempdir() cd(testdir) do rm(testdir) diff --git a/test/llvmcall.jl b/test/llvmcall.jl index ac75a3575ac29..fc59bd025939f 100644 --- a/test/llvmcall.jl +++ b/test/llvmcall.jl @@ -177,7 +177,7 @@ module ObjLoadTest end # Test for proper parenting -if VersionNumber(Base.libllvm_version) >= v"3.6" # llvm 3.6 changed the syntax for a gep, so just ignore this test on older versions +if Base.libllvm_version >= v"3.6" # llvm 3.6 changed the syntax for a gep, so just ignore this test on older versions local foo function foo() # this IR snippet triggers an optimization relying From b7074a0f23ea5d6103447aabbe119efa20e8163a Mon Sep 17 00:00:00 2001 From: Sanjay Sri Vallabh Date: Tue, 16 May 2017 12:07:02 +0530 Subject: [PATCH 0784/1534] Option to use nonstandard CUDA installation. --- Make.inc | 1 + src/Makefile | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Make.inc b/Make.inc index 2737a661a4346..8d9a3eff686af 100644 --- a/Make.inc +++ b/Make.inc @@ -240,6 +240,7 @@ BUILD_LLDB := 0 USE_POLLY := 0 USE_POLLY_OPENMP := 0 USE_POLLY_ACC := 0 +CUDALIB_INCLUDE_DIR := /usr/local/cuda/include # Cross-compile #XC_HOST := i686-w64-mingw32 diff --git a/src/Makefile b/src/Makefile index e45e77ea2f0f9..cd7b1c3caed7e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -67,7 +67,7 @@ endif ifeq ($(USE_POLLY_ACC),1) LLVMLINK += -lPollyPPCG -lGPURuntime FLAGS += -DUSE_POLLY_ACC -FLAGS += -I/usr/local/cuda/include +FLAGS += -I$(CUDALIB_INCLUDE_DIR) FLAGS += -I$(shell $(LLVM_CONFIG_HOST) --src-root)/tools/polly/tools endif endif From 04fc41085255aa39b49a92c0728c2789d57ab36f Mon Sep 17 00:00:00 2001 From: Sanjay Sri Vallabh Date: Tue, 16 May 2017 12:26:03 +0530 Subject: [PATCH 0785/1534] moved #include from codegen.cpp to jitlayers.cpp --- src/codegen.cpp | 7 ------- src/jitlayers.cpp | 7 +++++++ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 7c949f7090d71..a3cd82040a16e 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -105,9 +105,6 @@ #if defined(USE_POLLY) #include #include -#if defined(USE_POLLY_ACC) -#include -#endif #endif #include "fix_llvm_assert.h" @@ -7307,10 +7304,6 @@ extern "C" void jl_init_codegen(void) PassRegistry &Registry = *PassRegistry::getPassRegistry(); polly::initializePollyPasses(Registry); initializeAnalysis(Registry); -#ifdef USE_POLLY_ACC -#pragma message "ForceGPURuntimeLinking!!\n" - polly::ForceGPURuntimeLinking(); -#endif #endif InitializeNativeTarget(); diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index bd6a40518bad2..44dd0c802190d 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -25,6 +25,9 @@ #include #include #include +#if defined(USE_POLLY_ACC) +#include +#endif #endif #include @@ -202,6 +205,10 @@ void addOptimizationPasses(PassManager *PM) PM->add(polly::createCodePreparationPass()); polly::registerPollyPasses(*PM); PM->add(polly::createCodegenCleanupPass()); +#ifdef USE_POLLY_ACC +#pragma message "ForceGPURuntimeLinking!!\n" + polly::ForceGPURuntimeLinking(); +#endif #endif // LoopRotate strips metadata from terminator, so run LowerSIMD afterwards PM->add(createLowerSimdLoopPass()); // Annotate loop marked with "simdloop" as LLVM parallel loop From 85a47833c1bbf5fdcf2783fd3b54b6f2bf1a3f78 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Tue, 16 May 2017 02:04:57 -0700 Subject: [PATCH 0786/1534] Add NEWS.md entry for single-argument write deprecation (#17654). (#21880) --- NEWS.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS.md b/NEWS.md index 60cc91d37d263..5134e6ed295ea 100644 --- a/NEWS.md +++ b/NEWS.md @@ -457,6 +457,9 @@ Deprecated or removed * infix operator `$` has been deprecated in favor of infix `⊻` or function `xor()` ([#18977]). + * The single-argument form of `write` (`write(x)`, with implicit `STDOUT` output stream), + has been deprecated in favor of the explicit equivalent `write(STDOUT, x)` ([#17654]). + * `Dates.recur` has been deprecated in favor of `filter` ([#19288]) * A number of ambiguous `convert` operations between `Number`s (especially `Real`s) @@ -569,6 +572,7 @@ Command-line option changes [#17302]: https://github.com/JuliaLang/julia/issues/17302 [#17599]: https://github.com/JuliaLang/julia/issues/17599 [#17623]: https://github.com/JuliaLang/julia/issues/17623 +[#17654]: https://github.com/JuliaLang/julia/issues/17654 [#17723]: https://github.com/JuliaLang/julia/issues/17723 [#17758]: https://github.com/JuliaLang/julia/issues/17758 [#17785]: https://github.com/JuliaLang/julia/issues/17785 From 379ae499edaba942c83ca2301c47ecacc7edbe57 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Tue, 16 May 2017 02:06:21 -0700 Subject: [PATCH 0787/1534] Add NEWS.md entry for delete!(::EnvHash, ::AbstractString, def) dep (#18012). (#21881) --- NEWS.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/NEWS.md b/NEWS.md index 5134e6ed295ea..c0e0dfdf2aa7a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -455,6 +455,10 @@ Deprecated or removed * `num` and `den` have been deprecated in favor of `numerator` and `denominator` respectively ([#19233]). + * `delete!(ENV::EnvHash, k::AbstractString, def)` has been deprecated in favor of + `pop!(ENV, k, def)`. Be aware that `pop!` returns `k` or `def`, whereas `delete!` + returns `ENV` or `def` ([#18012]). + * infix operator `$` has been deprecated in favor of infix `⊻` or function `xor()` ([#18977]). * The single-argument form of `write` (`write(x)`, with implicit `STDOUT` output stream), @@ -576,6 +580,7 @@ Command-line option changes [#17723]: https://github.com/JuliaLang/julia/issues/17723 [#17758]: https://github.com/JuliaLang/julia/issues/17758 [#17785]: https://github.com/JuliaLang/julia/issues/17785 +[#18012]: https://github.com/JuliaLang/julia/issues/18012 [#18050]: https://github.com/JuliaLang/julia/issues/18050 [#18159]: https://github.com/JuliaLang/julia/issues/18159 [#18251]: https://github.com/JuliaLang/julia/issues/18251 From af9263459a25a34f45c8f68f8681751c8ac41711 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Tue, 16 May 2017 02:09:53 -0700 Subject: [PATCH 0788/1534] Add NEWS.md entry for at-textmime deprecation (#18441). (#21884) --- NEWS.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS.md b/NEWS.md index c0e0dfdf2aa7a..2513b0fe61008 100644 --- a/NEWS.md +++ b/NEWS.md @@ -449,6 +449,9 @@ Deprecated or removed Instead, `reshape` the array such that its dimensionality matches the number of indices ([#20079]). + * `Multimedia.@textmime "mime"` has been deprecated. Instead define + `Multimedia.istextmime(::MIME"mime") = true` ([#18441]). + * `isdefined(a::Array, i::Int)` has been deprecated in favor of `isassigned` ([#18346]). * `is` has been deprecated in favor of `===` (which used to be an alias for `is`) ([#17758]). @@ -588,6 +591,7 @@ Command-line option changes [#18339]: https://github.com/JuliaLang/julia/issues/18339 [#18342]: https://github.com/JuliaLang/julia/issues/18342 [#18346]: https://github.com/JuliaLang/julia/issues/18346 +[#18441]: https://github.com/JuliaLang/julia/issues/18441 [#18442]: https://github.com/JuliaLang/julia/issues/18442 [#18444]: https://github.com/JuliaLang/julia/issues/18444 [#18453]: https://github.com/JuliaLang/julia/issues/18453 From c7e4fe73c8ee94d8e17f817f0d6f687bdaf2e63f Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Tue, 16 May 2017 02:12:28 -0700 Subject: [PATCH 0789/1534] Add NEWS.md entry for ipermutedims deprecation (#18891). (#21885) --- NEWS.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS.md b/NEWS.md index 2513b0fe61008..9d57bfed7520f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -442,6 +442,9 @@ Compiler/Runtime improvements Deprecated or removed --------------------- + * `ipermutedims(A::AbstractArray, p)` has been deprecated in favor of + `permutedims(A, invperm(p))` ([#18891]). + * Linear indexing is now only supported when there is exactly one non-cartesian index provided. Allowing a trailing index at dimension `d` to linearly access the higher dimensions from array `A` (beyond `size(A, d)`) @@ -604,6 +607,7 @@ Command-line option changes [#18690]: https://github.com/JuliaLang/julia/issues/18690 [#18777]: https://github.com/JuliaLang/julia/issues/18777 [#18839]: https://github.com/JuliaLang/julia/issues/18839 +[#18891]: https://github.com/JuliaLang/julia/issues/18891 [#18931]: https://github.com/JuliaLang/julia/issues/18931 [#18965]: https://github.com/JuliaLang/julia/issues/18965 [#18977]: https://github.com/JuliaLang/julia/issues/18977 From 66402ac4deb68a65ba5904828b72316857235ae1 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Tue, 16 May 2017 02:14:01 -0700 Subject: [PATCH 0790/1534] Add NEWS.md entry for three-arg SubArray constructor deprecation (#19259). (#21883) --- NEWS.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/NEWS.md b/NEWS.md index 9d57bfed7520f..7b6f06deb6329 100644 --- a/NEWS.md +++ b/NEWS.md @@ -457,6 +457,10 @@ Deprecated or removed * `isdefined(a::Array, i::Int)` has been deprecated in favor of `isassigned` ([#18346]). + * The three-argument `SubArray` constructor (which accepts `dims::Tuple` as its third + argument) has been deprecated in favor of the two-argument equivalent (the + `dims::Tuple` argument being superfluous) ([#19259]). + * `is` has been deprecated in favor of `===` (which used to be an alias for `is`) ([#17758]). * `num` and `den` have been deprecated in favor of `numerator` and `denominator` respectively ([#19233]). @@ -615,6 +619,7 @@ Command-line option changes [#19157]: https://github.com/JuliaLang/julia/issues/19157 [#19233]: https://github.com/JuliaLang/julia/issues/19233 [#19239]: https://github.com/JuliaLang/julia/issues/19239 +[#19259]: https://github.com/JuliaLang/julia/issues/19259 [#19288]: https://github.com/JuliaLang/julia/issues/19288 [#19305]: https://github.com/JuliaLang/julia/issues/19305 [#19331]: https://github.com/JuliaLang/julia/issues/19331 From 38cfb73b9af111e5c96457830132d36c3f922592 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Tue, 16 May 2017 02:16:11 -0700 Subject: [PATCH 0791/1534] Add NEWS.md entry for dep of ambiguous UniformScaling-Number +/- methods (#17607). (#21882) --- NEWS.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/NEWS.md b/NEWS.md index 7b6f06deb6329..4220d2bb6566b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -463,6 +463,10 @@ Deprecated or removed * `is` has been deprecated in favor of `===` (which used to be an alias for `is`) ([#17758]). + * Ambiguous methods for addition and subtraction between `UniformScaling`s and `Number`s, + for example `(+)(J::UniformScaling, x::Number)`, have been deprecated in favor of + unambiguous, explicit equivalents, for example `J.λ + x` ([#17607]). + * `num` and `den` have been deprecated in favor of `numerator` and `denominator` respectively ([#19233]). * `delete!(ENV::EnvHash, k::AbstractString, def)` has been deprecated in favor of @@ -585,6 +589,7 @@ Command-line option changes [#17265]: https://github.com/JuliaLang/julia/issues/17265 [#17302]: https://github.com/JuliaLang/julia/issues/17302 [#17599]: https://github.com/JuliaLang/julia/issues/17599 +[#17607]: https://github.com/JuliaLang/julia/issues/17607 [#17623]: https://github.com/JuliaLang/julia/issues/17623 [#17654]: https://github.com/JuliaLang/julia/issues/17654 [#17723]: https://github.com/JuliaLang/julia/issues/17723 From 149e5893e0ae88cb2d6bb3245b41660929d4c94a Mon Sep 17 00:00:00 2001 From: Mus M Date: Tue, 16 May 2017 05:17:40 -0400 Subject: [PATCH 0792/1534] Use AbstractVector in _cpu_summary (#21876) --- base/sysinfo.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/sysinfo.jl b/base/sysinfo.jl index e930dddb25703..d629db2f1c4ef 100644 --- a/base/sysinfo.jl +++ b/base/sysinfo.jl @@ -92,7 +92,7 @@ CPUinfo(info::UV_cpu_info_t) = CPUinfo(unsafe_string(info.model), info.speed, show(io::IO, info::CPUinfo) = Base._show_cpuinfo(io, info, true, " ") -function _cpu_summary(io::IO, cpu::Array{CPUinfo}, i, j) +function _cpu_summary(io::IO, cpu::AbstractVector{CPUinfo}, i, j) if j-i < 9 header = true for x = i:j From 88e8a8492b8e2af00ad785b60a47dab8a85ff346 Mon Sep 17 00:00:00 2001 From: Sanjay Sri Vallabh Date: Tue, 16 May 2017 15:01:57 +0530 Subject: [PATCH 0793/1534] Needn't link GPURuntime anymore. --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index cd7b1c3caed7e..4e9a21d069588 100644 --- a/src/Makefile +++ b/src/Makefile @@ -65,7 +65,7 @@ ifeq ($(USE_POLLY_OPENMP),1) FLAGS += -fopenmp endif ifeq ($(USE_POLLY_ACC),1) -LLVMLINK += -lPollyPPCG -lGPURuntime +LLVMLINK += -lPollyPPCG FLAGS += -DUSE_POLLY_ACC FLAGS += -I$(CUDALIB_INCLUDE_DIR) FLAGS += -I$(shell $(LLVM_CONFIG_HOST) --src-root)/tools/polly/tools From 7397f2c7744641c368ca517ab95b138835b67d6b Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Tue, 16 May 2017 09:58:01 +0200 Subject: [PATCH 0794/1534] Remove unused DEPS_(C|CXX)FLAGS. --- Make.inc | 5 ----- deps/tools/common.mk | 6 +++--- deps/utf8proc.mk | 2 +- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/Make.inc b/Make.inc index 498394a37d95b..9d5b39835e654 100644 --- a/Make.inc +++ b/Make.inc @@ -535,11 +535,6 @@ endif JCXXFLAGS += $(SANITIZE_OPTS) JCFLAGS += $(SANITIZE_OPTS) LDFLAGS += $(SANITIZE_LDFLAGS) -# FIXME: sanitizing all dependencies doesn't work because of -Wl,--no-undefined -# https://github.com/JuliaLang/julia/issues/13858 -# use LLVM_SANITIZE to sanitize LLVM -#DEPS_CFLAGS += $(SANITIZE_OPTS) -#DEPS_CXXFLAGS += $(SANITIZE_OPTS) endif TAR := $(shell which gtar 2>/dev/null || which tar 2>/dev/null) diff --git a/deps/tools/common.mk b/deps/tools/common.mk index cf92a637451fa..df491b256c124 100644 --- a/deps/tools/common.mk +++ b/deps/tools/common.mk @@ -9,10 +9,10 @@ ifneq ($(USEMSVC), 1) CONFIGURE_COMMON += LDFLAGS="$(LDFLAGS) -Wl,--stack,8388608" endif endif -CONFIGURE_COMMON += F77="$(FC)" CC="$(CC) $(DEPS_CFLAGS)" CXX="$(CXX) $(DEPS_CXXFLAGS)" +CONFIGURE_COMMON += F77="$(FC)" CC="$(CC)" CXX="$(CXX)" -CMAKE_CC_ARG := $(CC_ARG) $(DEPS_CFLAGS) -CMAKE_CXX_ARG := $(CXX_ARG) $(DEPS_CXXFLAGS) +CMAKE_CC_ARG := $(CC_ARG) +CMAKE_CXX_ARG := $(CXX_ARG) CMAKE_COMMON := -DCMAKE_INSTALL_PREFIX:PATH=$(build_prefix) -DCMAKE_PREFIX_PATH=$(build_prefix) CMAKE_COMMON += -DCMAKE_INSTALL_LIBDIR=$(build_libdir) -DCMAKE_INSTALL_BINDIR=$(build_bindir) diff --git a/deps/utf8proc.mk b/deps/utf8proc.mk index d9e15a4b8dd18..5ee4e20d6739f 100644 --- a/deps/utf8proc.mk +++ b/deps/utf8proc.mk @@ -6,7 +6,7 @@ $(eval $(call git-external,utf8proc,UTF8PROC,,,$(BUILDDIR))) UTF8PROC_OBJ_LIB := $(build_libdir)/libutf8proc.a UTF8PROC_OBJ_HEADER := $(build_includedir)/utf8proc.h UTF8PROC_CFLAGS := -O2 -UTF8PROC_MFLAGS := CC="$(CC) $(DEPS_CFLAGS)" CFLAGS="$(CFLAGS) $(UTF8PROC_CFLAGS)" PICFLAG="$(fPIC)" AR="$(AR)" +UTF8PROC_MFLAGS := CC="$(CC)" CFLAGS="$(CFLAGS) $(UTF8PROC_CFLAGS)" PICFLAG="$(fPIC)" AR="$(AR)" $(BUILDDIR)/$(UTF8PROC_SRC_DIR)/build-compiled: $(BUILDDIR)/$(UTF8PROC_SRC_DIR)/source-extracted $(MAKE) -C $(dir $<) $(UTF8PROC_MFLAGS) libutf8proc.a From 1db6e10ed70fca347a08ceabebd0fef6a50d91ff Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Tue, 16 May 2017 10:18:37 +0200 Subject: [PATCH 0795/1534] Only populate Julia-specific LDFLAGS with ASAN options. --- Make.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Make.inc b/Make.inc index 9d5b39835e654..d40abf17adb86 100644 --- a/Make.inc +++ b/Make.inc @@ -534,7 +534,7 @@ SANITIZE_LDFLAGS := -fsanitize=address endif JCXXFLAGS += $(SANITIZE_OPTS) JCFLAGS += $(SANITIZE_OPTS) -LDFLAGS += $(SANITIZE_LDFLAGS) +JLDFLAGS += $(SANITIZE_LDFLAGS) endif TAR := $(shell which gtar 2>/dev/null || which tar 2>/dev/null) From 57ebd82e6702fc4a5a59abdbb5ad8eaaa56e53c1 Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Tue, 16 May 2017 09:00:05 -0400 Subject: [PATCH 0796/1534] Use correct transposition symbols in Ax_ldiv_B! for UMFPACK. Fixes #21877 (#21889) Make sure the methods are getting called from A'\b and A.'\b. Don't promote Factorizations in general Promote Bunch-Kaufman since it doesn't have a generic fallback solver --- base/linalg/bunchkaufman.jl | 5 +++++ base/linalg/factorization.jl | 2 +- base/sparse/linalg.jl | 37 +++++++++++++++++++----------------- base/sparse/umfpack.jl | 8 ++++---- test/sparse/umfpack.jl | 7 +++++++ 5 files changed, 37 insertions(+), 22 deletions(-) diff --git a/base/linalg/bunchkaufman.jl b/base/linalg/bunchkaufman.jl index af75be31adf1b..224fb39ab6371 100644 --- a/base/linalg/bunchkaufman.jl +++ b/base/linalg/bunchkaufman.jl @@ -150,6 +150,11 @@ function A_ldiv_B!(B::BunchKaufman{T}, R::StridedVecOrMat{T}) where T<:BlasCompl end end end +# There is no fallback solver for Bunch-Kaufman so we'll have to promote to same element type +function A_ldiv_B!(B::BunchKaufman{T}, R::StridedVecOrMat{S}) where {T,S} + TS = promote_type(T,S) + return A_ldiv_B!(convert(BunchKaufman{TS}, B), convert(AbstractArray{TS}, R)) +end function logabsdet(F::BunchKaufman) M = F.LD diff --git a/base/linalg/factorization.jl b/base/linalg/factorization.jl index ac795b33167e9..75e6c0a2db5f5 100644 --- a/base/linalg/factorization.jl +++ b/base/linalg/factorization.jl @@ -45,7 +45,7 @@ for (f1, f2) in ((:\, :A_ldiv_B!), TFB = typeof(oneunit(eltype(B)) / oneunit(eltype(F))) BB = similar(B, TFB, size(B)) copy!(BB, B) - $f2(convert(Factorization{TFB}, F), BB) + $f2(F, BB) end end end diff --git a/base/sparse/linalg.jl b/base/sparse/linalg.jl index 4df1c8c50bacf..695f25fd8619f 100644 --- a/base/sparse/linalg.jl +++ b/base/sparse/linalg.jl @@ -851,29 +851,32 @@ end scale!(A::SparseMatrixCSC, b::Number) = (scale!(A.nzval, b); A) scale!(b::Number, A::SparseMatrixCSC) = (scale!(b, A.nzval); A) -function (\)(A::SparseMatrixCSC, B::AbstractVecOrMat) - m, n = size(A) - if m == n - if istril(A) - if istriu(A) - return Diagonal(A) \ B +for f in (:\, :Ac_ldiv_B, :At_ldiv_B) + @eval begin + function ($f)(A::SparseMatrixCSC, B::AbstractVecOrMat) + m, n = size(A) + if m == n + if istril(A) + if istriu(A) + return ($f)(Diagonal(A), B) + else + return ($f)(LowerTriangular(A), B) + end + elseif istriu(A) + return ($f)(UpperTriangular(A), B) + end + if ishermitian(A) + return ($f)(Hermitian(A), B) + end + return ($f)(lufact(A), B) else - return LowerTriangular(A) \ B + return ($f)(qrfact(A), B) end - elseif istriu(A) - return UpperTriangular(A) \ B end - if ishermitian(A) - return Hermitian(A) \ B - end - return lufact(A) \ B - else - return qrfact(A) \ B + ($f)(::SparseMatrixCSC, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) end end -(\)(::SparseMatrixCSC, ::RowVector) = throw(DimensionMismatch("Cannot left-divide matrix by transposed vector")) - function factorize(A::SparseMatrixCSC) m, n = size(A) if m == n diff --git a/base/sparse/umfpack.jl b/base/sparse/umfpack.jl index 58981862d702e..0971fb7dc2d21 100644 --- a/base/sparse/umfpack.jl +++ b/base/sparse/umfpack.jl @@ -392,15 +392,15 @@ Ac_ldiv_B!(lu::UmfpackLU{Float64}, B::StridedVecOrMat{<:Complex}) = Ac_ldiv_B!(B A_ldiv_B!{T<:UMFVTypes}(X::StridedVecOrMat{T}, lu::UmfpackLU{T}, B::StridedVecOrMat{T}) = _Aq_ldiv_B!(X, lu, B, UMFPACK_A) At_ldiv_B!{T<:UMFVTypes}(X::StridedVecOrMat{T}, lu::UmfpackLU{T}, B::StridedVecOrMat{T}) = - _Aq_ldiv_B!(X, lu, B, UMFPACK_At) -Ac_ldiv_B!{T<:UMFVTypes}(X::StridedVecOrMat{T}, lu::UmfpackLU{T}, B::StridedVecOrMat{T}) = _Aq_ldiv_B!(X, lu, B, UMFPACK_Aat) +Ac_ldiv_B!{T<:UMFVTypes}(X::StridedVecOrMat{T}, lu::UmfpackLU{T}, B::StridedVecOrMat{T}) = + _Aq_ldiv_B!(X, lu, B, UMFPACK_At) A_ldiv_B!{Tb<:Complex}(X::StridedVecOrMat{Tb}, lu::UmfpackLU{Float64}, B::StridedVecOrMat{Tb}) = _Aq_ldiv_B!(X, lu, B, UMFPACK_A) At_ldiv_B!{Tb<:Complex}(X::StridedVecOrMat{Tb}, lu::UmfpackLU{Float64}, B::StridedVecOrMat{Tb}) = - _Aq_ldiv_B!(X, lu, B, UMFPACK_At) -Ac_ldiv_B!{Tb<:Complex}(X::StridedVecOrMat{Tb}, lu::UmfpackLU{Float64}, B::StridedVecOrMat{Tb}) = _Aq_ldiv_B!(X, lu, B, UMFPACK_Aat) +Ac_ldiv_B!{Tb<:Complex}(X::StridedVecOrMat{Tb}, lu::UmfpackLU{Float64}, B::StridedVecOrMat{Tb}) = + _Aq_ldiv_B!(X, lu, B, UMFPACK_At) function _Aq_ldiv_B!(X::StridedVecOrMat, lu::UmfpackLU, B::StridedVecOrMat, transposeoptype) if size(X, 2) != size(B, 2) diff --git a/test/sparse/umfpack.jl b/test/sparse/umfpack.jl index adbce3839a962..24273100fceee 100644 --- a/test/sparse/umfpack.jl +++ b/test/sparse/umfpack.jl @@ -72,9 +72,16 @@ end Ac0 = complex.(A0,A0) for Ti in Base.uniontypes(Base.SparseArrays.UMFPACK.UMFITypes) Ac = convert(SparseMatrixCSC{Complex128,Ti}, Ac0) + x = complex.(ones(size(Ac, 1)), ones(size(Ac,1))) lua = lufact(Ac) L,U,p,q,Rs = lua[:(:)] @test (Diagonal(Rs) * Ac)[p,q] ≈ L * U + b = Ac*x + @test Ac\b ≈ x + b = Ac'*x + @test Ac'\b ≈ x + b = Ac.'*x + @test Ac.'\b ≈ x end for elty in (Float64, Complex128) From c63678515840108969055da9a1e43400f6242b15 Mon Sep 17 00:00:00 2001 From: Sanjay Sri Vallabh Date: Tue, 16 May 2017 19:15:08 +0530 Subject: [PATCH 0797/1534] Removed function call since including LinkGPURuntime.h is enough. (https://reviews.llvm.org/D33198?id=99134) --- src/jitlayers.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index 44dd0c802190d..61ff2237cc9af 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -205,10 +205,6 @@ void addOptimizationPasses(PassManager *PM) PM->add(polly::createCodePreparationPass()); polly::registerPollyPasses(*PM); PM->add(polly::createCodegenCleanupPass()); -#ifdef USE_POLLY_ACC -#pragma message "ForceGPURuntimeLinking!!\n" - polly::ForceGPURuntimeLinking(); -#endif #endif // LoopRotate strips metadata from terminator, so run LowerSIMD afterwards PM->add(createLowerSimdLoopPass()); // Annotate loop marked with "simdloop" as LLVM parallel loop From 598f5850b6b567d8f010a3f35a9f4c9cd2257bfc Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Sun, 14 May 2017 13:24:38 +0200 Subject: [PATCH 0798/1534] allocate distinct seed arrays for RNGs in randjump --- base/random.jl | 2 +- test/random.jl | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/base/random.jl b/base/random.jl index 6383f2c599269..44a1e9dbd42d1 100644 --- a/base/random.jl +++ b/base/random.jl @@ -166,7 +166,7 @@ function randjump(mt::MersenneTwister, jumps::Integer, jumppoly::AbstractString) push!(mts, mt) for i in 1:jumps-1 cmt = mts[end] - push!(mts, MersenneTwister(cmt.seed, dSFMT.dsfmt_jump(cmt.state, jumppoly))) + push!(mts, MersenneTwister(copy(cmt.seed), dSFMT.dsfmt_jump(cmt.state, jumppoly))) end return mts end diff --git a/test/random.jl b/test/random.jl index 359ecf7d26b26..1be9333d7ecd7 100644 --- a/test/random.jl +++ b/test/random.jl @@ -475,6 +475,12 @@ end let seed = rand(UInt32, 10) r = MersenneTwister(seed) @test r.seed == seed && r.seed !== seed + # RNGs do not share their seed in randjump + let rs = randjump(r, 2) + @test rs[1].seed !== rs[2].seed + srand(rs[2]) + @test seed == rs[1].seed != rs[2].seed + end resize!(seed, 4) @test r.seed != seed end From f46ba0ada0c1bb003b026596d595fa7995e8f597 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 16 May 2017 11:53:43 -0400 Subject: [PATCH 0799/1534] fix #21848, bug in widening done by limit_type_depth This would widen e.g. `Complex{T} where T` to `_ <: Complex`, which is valid in some sense but yields a type that's not a supertype of the input, which is bad. --- base/inference.jl | 15 +++++++++++++-- test/inference.jl | 11 +++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 059f5474ba21b..532b48917a26b 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -707,8 +707,19 @@ function limit_type_depth(t::ANY, d::Int, cov::Bool, vars::Vector{TypeVar}=TypeV P = t.parameters isempty(P) && return t if d > MAX_TYPE_DEPTH - cov && return t.name.wrapper - var = TypeVar(:_, t.name.wrapper) + if isvarargtype(t) + # never replace Vararg with non-Vararg + return Vararg{limit_type_depth(P[1], d, cov, vars), P[2]} + end + widert = t.name.wrapper + if !(t <: widert) + # This can happen when a typevar has bounds too wide for its context, e.g. + # `Complex{T} where T` is not a subtype of `Complex`. In that case widen even + # faster to something safe to ensure the result is a supertype of the input. + widert = Any + end + cov && return widert + var = TypeVar(:_, widert) push!(vars, var) return var end diff --git a/test/inference.jl b/test/inference.jl index 318e33c4e552b..690acd3f43c96 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -777,3 +777,14 @@ function break_21369() end end @test_throws ErrorException break_21369() # not TypeError + +# issue #21848 +@test Core.Inference.limit_type_depth(Ref{Complex{T} where T}, Core.Inference.MAX_TYPE_DEPTH) == Ref +let T = Tuple{Tuple{Int64, Void}, + Tuple{Tuple{Int64, Void}, + Tuple{Int64, Tuple{Tuple{Int64, Void}, + Tuple{Tuple{Int64, Void}, Tuple{Int64, Tuple{Tuple{Int64, Void}, Tuple{Tuple, Tuple}}}}}}}} + @test Core.Inference.limit_type_depth(T, 0) >: T + @test Core.Inference.limit_type_depth(T, 1) >: T + @test Core.Inference.limit_type_depth(T, 2) >: T +end From 8f9a94829f27b9aeec315818133bf8337ba2d682 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Tue, 16 May 2017 09:20:26 -0700 Subject: [PATCH 0800/1534] add NEWS.md entry for three-argument rem and rem2pi (#21812) * Add NEWS.md entry for three-argument rem and the new rem2pi (#10946). * Clarify precise behaviour --- NEWS.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/NEWS.md b/NEWS.md index 4220d2bb6566b..27dc6ad493e44 100644 --- a/NEWS.md +++ b/NEWS.md @@ -414,6 +414,12 @@ Library improvements Currently, it is used by default for the new `RowVector` type only, and enforces that both `transpose(vec)` and `ctranspose(vec)` are views not copies ([#20047]). + * `rem` now accepts a `RoundingMode` argument via `rem(x, y, r::RoundingMode)`, yielding + `x - y*round(x/y, r)` without intermediate rounding. In particular, `rem(x, y, RoundNearest)` + yields a value in the interval `[-abs(y)/2, abs(y)/2]`), which corresponds to the IEE754 + `remainder` function. Similarly, `rem2pi(x, r::RoundingMode)` now exists as well, yielding + `rem(x, 2pi, r::RoundingMode)` but with greater accuracy ([#10946]). + * `map[!]` and `broadcast[!]` now have dedicated methods for sparse/structured vectors/matrices. Specifically, `map[!]` and `broadcast[!]` over combinations including one or more `SparseVector`, `SparseMatrixCSC`, `Diagonal`, `Bidiagonal`, `Tridiagonal`, @@ -574,6 +580,7 @@ Command-line option changes [#7669]: https://github.com/JuliaLang/julia/issues/7669 [#8974]: https://github.com/JuliaLang/julia/issues/8974 [#9343]: https://github.com/JuliaLang/julia/issues/9343 +[#10946]: https://github.com/JuliaLang/julia/issues/10946 [#11250]: https://github.com/JuliaLang/julia/issues/11250 [#11310]: https://github.com/JuliaLang/julia/issues/11310 [#12274]: https://github.com/JuliaLang/julia/issues/12274 From 9e269f0cf5a2e15e1331061fb1bc01d433f6024f Mon Sep 17 00:00:00 2001 From: Mus M Date: Tue, 16 May 2017 12:42:25 -0400 Subject: [PATCH 0801/1534] Update umfpack.jl --- base/sparse/umfpack.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/sparse/umfpack.jl b/base/sparse/umfpack.jl index a720948e3eb70..5e44206760f0f 100644 --- a/base/sparse/umfpack.jl +++ b/base/sparse/umfpack.jl @@ -395,7 +395,7 @@ At_ldiv_B!(X::StridedVecOrMat{T}, lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where _Aq_ldiv_B!(X, lu, B, UMFPACK_Aat) Ac_ldiv_B!(X::StridedVecOrMat{T}, lu::UmfpackLU{T}, B::StridedVecOrMat{T}) where {T<:UMFVTypes} = _Aq_ldiv_B!(X, lu, B, UMFPACK_At) -A_ldiv_B!{Tb<:Complex}(X::StridedVecOrMat{Tb}, lu::UmfpackLU{Float64}, B::StridedVecOrMat{Tb}) = +A_ldiv_B!(X::StridedVecOrMat{Tb}, lu::UmfpackLU{Float64}, B::StridedVecOrMat{Tb}) where {Tb<:Complex} = _Aq_ldiv_B!(X, lu, B, UMFPACK_A) At_ldiv_B!(X::StridedVecOrMat{Tb}, lu::UmfpackLU{Float64}, B::StridedVecOrMat{Tb}) where {Tb<:Complex} = _Aq_ldiv_B!(X, lu, B, UMFPACK_Aat) From bd76bfef55588709e0ac16564096c329d5773ca6 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 10 May 2017 16:48:34 -0400 Subject: [PATCH 0802/1534] fix remaining uses of old type keywords --- base/reflection.jl | 4 ++-- doc/src/manual/modules.md | 2 +- examples/queens.jl | 2 +- test/core.jl | 2 +- test/inference.jl | 2 +- test/sparse/sparsevector.jl | 2 +- test/subtype.jl | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/base/reflection.jl b/base/reflection.jl index 77de6bdf36cb6..58d9b67e19177 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -340,7 +340,7 @@ fieldoffset(x::DataType, idx::Integer) = (@_pure_meta; ccall(:jl_get_field_offse Determine the declared type of a field (specified by name or index) in a composite DataType `T`. ```jldoctest -julia> immutable Foo +julia> struct Foo x::Int64 y::String end @@ -361,7 +361,7 @@ Get the index of a named field, throwing an error if the field does not exist (w or returning 0 (when err==false). ```jldoctest -julia> immutable Foo +julia> struct Foo x::Int64 y::String end diff --git a/doc/src/manual/modules.md b/doc/src/manual/modules.md index cc8cfe7463447..bbd6b4248b1f6 100644 --- a/doc/src/manual/modules.md +++ b/doc/src/manual/modules.md @@ -21,7 +21,7 @@ importall OtherLib export MyType, foo -type MyType +struct MyType x end diff --git a/examples/queens.jl b/examples/queens.jl index 418637a2be8db..e44e2fd2c083b 100644 --- a/examples/queens.jl +++ b/examples/queens.jl @@ -2,7 +2,7 @@ # n-queens (nqueens) solver, for nsquaresx-by-nsquaresy board -immutable Queen +struct Queen x::Int y::Int end diff --git a/test/core.jl b/test/core.jl index 5b391e02eedad..487ae7edff2a3 100644 --- a/test/core.jl +++ b/test/core.jl @@ -4896,7 +4896,7 @@ foo21568() @test f21568([0]) == 1 # issue #21719 -type T21719{V} +mutable struct T21719{V} f tol::Float64 goal::V diff --git a/test/inference.jl b/test/inference.jl index 318e33c4e552b..a9e846b91229b 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -740,7 +740,7 @@ let e = code_typed(f21175, ())[1].first.code[1]::Expr end # issue #10207 -type T10207{A, B} +mutable struct T10207{A, B} a::A b::B end diff --git a/test/sparse/sparsevector.jl b/test/sparse/sparsevector.jl index 6b8f20eaf0afa..543b7668160fd 100644 --- a/test/sparse/sparsevector.jl +++ b/test/sparse/sparsevector.jl @@ -1124,7 +1124,7 @@ end @test issparse([sprand(10,.1); rand(10)]) -type t20488 end +mutable struct t20488 end @testset "similar" begin x = sparsevec(rand(3) .+ 0.1) diff --git a/test/subtype.jl b/test/subtype.jl index 7233b9054e05f..2c74f70ffc4bd 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -1102,7 +1102,7 @@ end # issue #21613 abstract type A21613{S <: Tuple} end -immutable B21613{S <: Tuple, L} <: A21613{S} +struct B21613{S <: Tuple, L} <: A21613{S} data::NTuple{L,Float64} end @testintersect(Tuple{Type{B21613{Tuple{L},L}} where L, Any}, From 9a8adb550b134d81b60418df9d8d6659093d52a2 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 10 May 2017 16:48:20 -0400 Subject: [PATCH 0803/1534] turn on deprecation warnings for `type` and `immutable` --- NEWS.md | 3 +++ src/julia-parser.scm | 5 ++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/NEWS.md b/NEWS.md index 27dc6ad493e44..fb01d5441bb2c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -32,6 +32,9 @@ Compiler/Runtime improvements Deprecated or removed --------------------- + * The keyword `immutable` is fully deprecated to `struct`, and + `type` is fully deprecated to `mutable struct` ([#19157], [#20418]). + * The method `srand(rng, filename, n=4)` has been deprecated ([#21359]). diff --git a/src/julia-parser.scm b/src/julia-parser.scm index a3806d96217bb..204aacbea1cd9 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -1331,11 +1331,10 @@ (expect-end (take-lineendings s) "primitive type")))))) ;; deprecated type keywords ((type) - ;; TODO fully deprecate post-0.6 - ;;(syntax-deprecation s "type" "mutable struct") + (syntax-deprecation s "type" "mutable struct") ;; retain in 0.7 (parse-struct-def s #t word)) ((immutable) - ;;(syntax-deprecation s "immutable" "struct") + (syntax-deprecation s "immutable" "struct") ;; retain in 0.7 (parse-struct-def s #f word)) ((bitstype) (let* ((nb (with-space-sensitive (parse-cond s))) From 262b51744398ab650e956463b3bdf151fd7be4ac Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 10 May 2017 15:36:17 -0400 Subject: [PATCH 0804/1534] give a syntax error for repeated keyword args. fixes #16937 --- NEWS.md | 2 ++ src/julia-syntax.scm | 5 +++++ test/parse.jl | 4 ++++ 3 files changed, 11 insertions(+) diff --git a/NEWS.md b/NEWS.md index 27dc6ad493e44..a06c288206f9c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -20,6 +20,8 @@ This section lists changes that do not have deprecation warnings. * `@__DIR__` returns the current working directory rather than `nothing` when not run from a file ([#21759]). + * Passing the same keyword argument multiple times is now a syntax error ([#16937]). + Library improvements -------------------- diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 842327fe740d7..ac378d93a5a14 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -1439,6 +1439,11 @@ ;; lower function call containing keyword arguments (define (lower-kw-call fexpr kw0 pa) + ;; check for keyword arguments syntactically passed more than once + (let ((dups (has-dups (map cadr (filter kwarg? kw0))))) + (if dups + (error (string "keyword argument \"" (car dups) "\" repeated in call to \"" (deparse fexpr) "\"")))) + (define (kwcall-unless-empty f pa kw-container-test kw-container) (let* ((expr_stmts (remove-argument-side-effects `(call ,f ,@pa))) (pa (cddr (car expr_stmts))) diff --git a/test/parse.jl b/test/parse.jl index df2f38cfbd36f..9580927538289 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -1187,3 +1187,7 @@ module Test21607 x end === 1.0 end + +# issue #16937 +@test expand(:(f(2, a=1, w=3, c=3, w=4, b=2))) == Expr(:error, + "keyword argument \"w\" repeated in call to \"f\"") From 169daa43b80a8c65550c5cde1d6fd1eb7c201cfe Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 10 May 2017 16:50:10 -0400 Subject: [PATCH 0805/1534] fix #20575, syntax error for juxtaposing a string literal --- NEWS.md | 2 ++ src/julia-parser.scm | 4 +++- test/parse.jl | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 27dc6ad493e44..c1dcc42c82090 100644 --- a/NEWS.md +++ b/NEWS.md @@ -17,6 +17,8 @@ This section lists changes that do not have deprecation warnings. * `ntuple(f, n::Integer)` throws `ArgumentError` if `n` is negative. Previously an empty tuple was returned ([#21697]). + * Juxtaposing string literals (e.g. `"x"y`) is now a syntax error ([#20575]). + * `@__DIR__` returns the current working directory rather than `nothing` when not run from a file ([#21759]). diff --git a/src/julia-parser.scm b/src/julia-parser.scm index a3806d96217bb..54c854be6b58f 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -876,9 +876,11 @@ ) (not (ts:space? s)) (not (operator? t)) - (not (initial-reserved-word? t)) (not (closing-token? t)) (not (newline? t)) + (or (not (string? expr)) ;; issue #20575 + (error "cannot juxtapose string literal")) + (not (initial-reserved-word? t)) (not (and (pair? expr) (syntactic-unary-op? (car expr)))) ;; TODO: this would disallow juxtaposition with 0, which is ambiguous ;; with e.g. hex literals `0x...`. however this is used for `0im`, which diff --git a/test/parse.jl b/test/parse.jl index df2f38cfbd36f..858393df4ee98 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -1149,6 +1149,10 @@ f21586(; @m21586(a), @m21586(b)) = a + b end @test Test21604.X(1.0) === Test21604.X(1.0) +# issue #20575 +@test_throws ParseError parse("\"a\"x") +@test_throws ParseError parse("\"a\"begin end") + # comment 298107224 on pull #21607 module Test21607 using Base.Test From 18562e0871083db5d8299fdfb686a9e89fcbb955 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 16 May 2017 14:05:34 -0400 Subject: [PATCH 0806/1534] fix #21906, `ccall` causes unnecessary variable `Box` --- src/julia-syntax.scm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 842327fe740d7..4994a61ca686d 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -2960,7 +2960,7 @@ f(x) = yt(x) (memq (car e) '(quote top core line inert local local-def unnecessary meta inbounds boundscheck simdloop decl implicit-global global globalref outerref - const = null method call ssavalue)))) + const = null method call foreigncall ssavalue)))) (lam:body lam)))) (unused (map cadr (filter (lambda (x) (memq (car x) '(method =))) leading)))) From ec5b4f3a46bc4a09539232949285f49a8dd1dd93 Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Tue, 16 May 2017 12:02:04 -0700 Subject: [PATCH 0807/1534] Add a missing return in doInitialization --- src/llvm-lower-handlers.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/llvm-lower-handlers.cpp b/src/llvm-lower-handlers.cpp index c85c58ef94d57..7b8f2388c1fbe 100644 --- a/src/llvm-lower-handlers.cpp +++ b/src/llvm-lower-handlers.cpp @@ -116,6 +116,7 @@ bool LowerExcHandlers::doInitialization(Module &M) { setjmp_func = M.getFunction(jl_setjmp_name); lifetime_start = Intrinsic::getDeclaration(&M, Intrinsic::lifetime_start); lifetime_end = Intrinsic::getDeclaration(&M, Intrinsic::lifetime_end); + return true; } bool LowerExcHandlers::runOnFunction(Function &F) { From a34fd5115a08c106c39dc715005f40cedb90e1d8 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Tue, 16 May 2017 15:58:50 -0400 Subject: [PATCH 0808/1534] Make `expm1(::Complex64)` type stable. (#21896) --- base/complex.jl | 11 ++++++++--- test/complex.jl | 7 +++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/base/complex.jl b/base/complex.jl index a7faac11f89ef..f786017d20108 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -515,7 +515,8 @@ function exp(z::Complex) end end -function expm1(z::Complex) +function expm1(z::Complex{T}) where T<:Real + Tf = float(T) zr,zi = reim(z) if isnan(zr) Complex(zr, zi==0 ? zi : zr) @@ -533,8 +534,12 @@ function expm1(z::Complex) Complex(erm1, zi) else er = erm1+one(erm1) - wr = isfinite(er) ? erm1 - 2.0*er*(sin(0.5*zi))^2 : er*cos(zi) - Complex(wr, er*sin(zi)) + if isfinite(er) + wr = erm1 - 2 * er * (sin(convert(Tf, 0.5) * zi))^2 + return Complex(wr, er * sin(zi)) + else + return Complex(er * cos(zi), er * sin(zi)) + end end end end diff --git a/test/complex.jl b/test/complex.jl index 35852030e60ae..3aa4dd02d25b7 100644 --- a/test/complex.jl +++ b/test/complex.jl @@ -951,3 +951,10 @@ end @test log1p(complex(x, x)) ≈ log(1 + complex(x, x)) end end + +@testset "expm1 type stability" begin + x = @inferred expm1(0.1im) + @test x isa Complex128 + x = @inferred expm1(0.1f0im) + @test x isa Complex64 +end From 623eab49cc985c7068fd129618d5a818871d8e3a Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Tue, 16 May 2017 19:47:37 -0700 Subject: [PATCH 0809/1534] Mark the backtrace test as broken on FreeBSD (#21917) --- test/cmdlineargs.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/cmdlineargs.jl b/test/cmdlineargs.jl index 802f9ad31d070..f5ca5f9698dd0 100644 --- a/test/cmdlineargs.jl +++ b/test/cmdlineargs.jl @@ -404,8 +404,8 @@ for precomp in ("yes", "no") bt = readstring(pipeline(ignorestatus(`$(Base.julia_cmd()) --startup-file=no --precompiled=$precomp -E 'include("____nonexistent_file")'`), stderr=catcmd)) @test contains(bt, "include_from_node1") - if is_windows() && Sys.WORD_SIZE == 32 && precomp == "yes" - # fixme, issue #17251 + if ((is_windows() && Sys.WORD_SIZE == 32) || (is_bsd() && !is_apple())) && precomp == "yes" + # FIXME: Issue #17251 (Windows), #20798 (FreeBSD) @test_broken contains(bt, "include_from_node1(::String) at $(joinpath(".","loading.jl"))") else @test contains(bt, "include_from_node1(::String) at $(joinpath(".","loading.jl"))") From 1bb28ecb6168f71adfba38429e18e1d3920e8efe Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Wed, 17 May 2017 08:24:00 -0400 Subject: [PATCH 0810/1534] Fix pool lookup function --- src/gc-debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gc-debug.c b/src/gc-debug.c index 69f02b0dab3ab..36f6792e47dfa 100644 --- a/src/gc-debug.c +++ b/src/gc-debug.c @@ -37,7 +37,7 @@ JL_DLLEXPORT jl_taggedvalue_t *jl_gc_find_taggedvalue_pool(char *p, size_t *osiz return NULL; size_t ofs = p - page_begin; // Check if this is a free page - if (!(info.pagetable0->allocmap[info.pagetable0_i32 / 32] & (uint32_t)(1 << info.pagetable0_i))) + if (!(info.pagetable0->allocmap[info.pagetable0_i32] & (uint32_t)(1 << info.pagetable0_i))) return NULL; int osize = info.meta->osize; // Shouldn't be needed, just in case From 4db8fbaed095d18a020f762d32eee6b9e55cf1e8 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Wed, 17 May 2017 13:59:21 -0400 Subject: [PATCH 0811/1534] Use cached urls for appveyor and contrib/prepare_release.sh downloads of nightlies --- contrib/prepare_release.sh | 2 +- contrib/windows/msys_build.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/prepare_release.sh b/contrib/prepare_release.sh index 9cd2b96a1b167..77e67de189e78 100755 --- a/contrib/prepare_release.sh +++ b/contrib/prepare_release.sh @@ -33,7 +33,7 @@ cd .. rm -rf julia-$version # download and rename binaries, with -latest copies -julianightlies="https://s3.amazonaws.com/julianightlies/bin" +julianightlies="https://julialangnightlies-s3.julialang.org/bin" curl -L -o julia-$version-linux-x86_64.tar.gz \ $julianightlies/linux/x64/$majmin/julia-$majminpatch-$shashort-linux64.tar.gz cp julia-$version-linux-x86_64.tar.gz julia-$majmin-latest-linux-x86_64.tar.gz diff --git a/contrib/windows/msys_build.sh b/contrib/windows/msys_build.sh index 9edba7e3d64a0..f33930c02d035 100755 --- a/contrib/windows/msys_build.sh +++ b/contrib/windows/msys_build.sh @@ -89,7 +89,7 @@ esac if ! [ -e julia-installer.exe ]; then f=julia-latest-win$bits.exe echo "Downloading $f" - $curlflags -O https://s3.amazonaws.com/julianightlies/bin/winnt/x$archsuffix/$f + $curlflags -O https://julialangnightlies-s3.julialang.org/bin/winnt/x$archsuffix/$f echo "Extracting $f" $SEVENZIP x -y $f >> get-deps.log fi From 49abbf3b24b9658d53f0be9203795f7043b3e475 Mon Sep 17 00:00:00 2001 From: Gollor Date: Wed, 17 May 2017 23:56:43 +0300 Subject: [PATCH 0812/1534] Added @vtjnash code except for relative path in dependency tracker --- base/loading.jl | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/base/loading.jl b/base/loading.jl index 9ff3e889ec928..7a8e9afa057df 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -263,10 +263,15 @@ const _require_dependencies = Any[] # a list of (path, mtime) tuples that are th const _track_dependencies = Ref(false) # set this to true to track the list of file dependencies function _include_dependency(_path::AbstractString) prev = source_path(nothing) - if myid() != 1 && prev === nothing - prev = remotecall_fetch(abspath, 1, ".") + if prev === nothing + if myid() == 1 + path = abspath(_path) + else + path = joinpath(remotecall_fetch(abspath, 1, "."), _path) + end + else + path = joinpath(dirname(prev), _path) end - path = (prev === nothing) ? abspath(_path) : joinpath(dirname(prev), _path) if myid() == 1 && _track_dependencies[] apath = abspath(path) push!(_require_dependencies, (apath, mtime(apath))) From eadb699d2088658518f907b83599ffbcb201e03b Mon Sep 17 00:00:00 2001 From: Gollor Date: Thu, 18 May 2017 00:07:06 +0300 Subject: [PATCH 0813/1534] Removed explicitly absolute path --- base/loading.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/base/loading.jl b/base/loading.jl index 7a8e9afa057df..3985f9668b741 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -273,8 +273,7 @@ function _include_dependency(_path::AbstractString) path = joinpath(dirname(prev), _path) end if myid() == 1 && _track_dependencies[] - apath = abspath(path) - push!(_require_dependencies, (apath, mtime(apath))) + push!(_require_dependencies, (path, mtime(path))) end return path, prev end From 49d130c96e834412d04984ff886ae12e7f9a1a04 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 17 May 2017 17:41:30 -0400 Subject: [PATCH 0814/1534] fix #21923, regressions in circular type definitions --- src/jltypes.c | 5 +---- src/julia-syntax.scm | 20 ++++++++++++-------- test/core.jl | 10 ++++++++++ 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/jltypes.c b/src/jltypes.c index 3edfd5296a687..d147cbfc0d442 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -1343,10 +1343,7 @@ static jl_value_t *inst_type_w_(jl_value_t *t, jl_typeenv_t *env, jl_typestack_t } jl_typeenv_t newenv = { ua->var, (jl_value_t*)((jl_unionall_t*)res)->var, env }; jl_value_t *newbody = inst_type_w_(ua->body, &newenv, &top, check); - if (newbody == ua->body) { - res = t; - } - else if (newbody == (jl_value_t*)jl_emptytuple_type) { + if (newbody == (jl_value_t*)jl_emptytuple_type) { // NTuple{0} => Tuple{} can make a typevar disappear res = (jl_value_t*)jl_emptytuple_type; } diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index ac378d93a5a14..9180e16b55b60 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -3315,7 +3315,7 @@ f(x) = yt(x) (set-car! (lam:vinfo lam) (append (car (lam:vinfo lam)) `((,g Any 2)))) g)) ;; evaluate the arguments of a call, creating temporary locations as needed - (define (compile-args lst break-labels) + (define (compile-args lst break-labels (linearize #t)) (if (null? lst) '() (let ((temps? (or *very-linear-mode* (any (lambda (e) @@ -3332,9 +3332,9 @@ f(x) = yt(x) (if (null? lst) (reverse! vals) (let* ((arg (car lst)) - (aval (compile arg break-labels #t #f))) + (aval (compile arg break-labels #t #f linearize))) (loop (cdr lst) - (cons (if (and temps? (not simple?) + (cons (if (and temps? linearize (not simple?) (not (simple-atom? arg)) (not (ssavalue? arg)) (not (simple-atom? aval)) (not (ssavalue? aval)) (not (and (pair? arg) @@ -3361,7 +3361,7 @@ f(x) = yt(x) ;; value must be returned. ;; `tail` means we are in tail position, where a value needs to be `return`ed ;; from the current function. - (define (compile e break-labels value tail) + (define (compile e break-labels value tail (linearize-args #t)) (if (or (not (pair? e)) (memq (car e) '(null ssavalue quote inert top core copyast the_exception $ globalref outerref cdecl stdcall fastcall thiscall llvmcall))) (let ((e1 (if (and arg-map (symbol? e)) @@ -3386,11 +3386,11 @@ f(x) = yt(x) ;; NOTE: 2nd and 3rd arguments of ccall must be left in place ;; the 1st should be compiled if an atom. (append (list) - (cond (atom? (cadr e) (compile-args (list (cadr e)) break-labels)) + (cond (atom? (cadr e) (compile-args (list (cadr e)) break-labels linearize-args)) (else (cadr e))) (list-head (cddr e) 2) - (compile-args (list-tail e 4) break-labels)) - (compile-args (cdr e) break-labels))) + (compile-args (list-tail e 4) break-labels linearize-args)) + (compile-args (cdr e) break-labels linearize-args))) (callex (cons (car e) args))) (cond (tail (emit-return callex)) (value callex) @@ -3602,7 +3602,11 @@ f(x) = yt(x) ((composite_type) (let* ((para (compile (caddr e) break-labels #t #f)) (supe (compile (list-ref e 4) break-labels #t #f)) - (ftys (compile (list-ref e 5) break-labels #t #f))) + ;; composite_type has an unconventional evaluation rule that + ;; needs to do work around the evaluation of the field types, + ;; so the field type expressions need to be kept in place as + ;; much as possible. (part of issue #21923) + (ftys (compile (list-ref e 5) break-labels #t #f #f))) (emit `(composite_type ,(cadr e) ,para ,(cadddr e) ,supe ,ftys ,@(list-tail e 6))))) (else (emit e))) diff --git a/test/core.jl b/test/core.jl index 487ae7edff2a3..24a432a40cc7a 100644 --- a/test/core.jl +++ b/test/core.jl @@ -245,6 +245,16 @@ abstract type Sup2a_ end abstract type Sup2b_{A <: Sup2a_, B} <: Sup2a_ end @test_throws ErrorException @eval abstract type Qux2_{T} <: Sup2b_{Qux2_{Int}, T} end # wrapped in eval to avoid #16793 +# issue #21923 +struct A21923{T,N}; v::Vector{A21923{T}}; end +@test fieldtype(A21923,1) == Vector{A21923{T}} where T +struct B21923{T,N}; v::Vector{B21923{T,M} where M}; end +@test fieldtype(B21923, 1) == Vector{B21923{T,M} where M} where T +struct C21923{T,N}; v::C21923{T,M} where M; end +@test fieldtype(C21923, 1) == C21923 +struct D21923{T,N}; v::D21923{T}; end +@test fieldtype(D21923, 1) == D21923 + # issue #3890 mutable struct A3890{T1} x::Matrix{Complex{T1}} From 99286f9588f7f0e8f3c7cd4abf198f7ff0521fc9 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Fri, 12 May 2017 08:48:54 -0400 Subject: [PATCH 0815/1534] Do not reinterpret to wrong alignment This is undefined behavior in LLVM and can actually segfault on real hardware including x86 in certain cases. Also add missing endianess test since it is changed in this commit. --- base/bitarray.jl | 5 +++-- base/dSFMT.jl | 10 +++++++--- base/io.jl | 36 ++++++++++++++++++++---------------- base/pcre.jl | 8 ++++---- test/core.jl | 9 ++++++--- test/misc.jl | 23 +++++++++++++++++++++++ 6 files changed, 63 insertions(+), 28 deletions(-) diff --git a/base/bitarray.jl b/base/bitarray.jl index 23602c25634fe..8766bef1b54f7 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -283,11 +283,12 @@ function copy_to_bitarray_chunks!(Bc::Vector{UInt64}, pos_d::Int, C::Array{Bool} nc8 = (nc >>> 3) << 3 if nc8 > 0 ind8 = 1 - C8 = reinterpret(UInt64, unsafe_wrap(Array, pointer(C, ind), nc8 << 6)) + P8 = Ptr{UInt64}(pointer(C, ind)) # unaligned i64 pointer @inbounds for i = 1:nc8 c = UInt64(0) for j = 0:7 - c |= (pack8bools(C8[ind8]) << (j<<3)) + # unaligned load + c |= (pack8bools(unsafe_load(P8, ind8)) << (j<<3)) ind8 += 1 end Bc[bind] = c diff --git a/base/dSFMT.jl b/base/dSFMT.jl index c95b372d9b6a5..bd22f22a2fa39 100644 --- a/base/dSFMT.jl +++ b/base/dSFMT.jl @@ -89,9 +89,13 @@ end # dSFMT jump function dsfmt_jump(s::DSFMT_state, jp::AbstractString) - index = s.val[end-1] - work = zeros(UInt64, JN32>>1) - dsfmt = reinterpret(UInt64, copy(s.val)) + val = s.val + nval = length(val) + index = val[nval - 1] + work = zeros(UInt64, JN32 >> 1) + dsfmt = Vector{UInt64}(nval >> 1) + ccall(:memcpy, Ptr{Void}, (Ptr{UInt64}, Ptr{Int32}, Csize_t), + dsfmt, val, (nval - 1) * sizeof(Int32)) dsfmt[end] = UInt64(N*2) for c in jp diff --git a/base/io.jl b/base/io.jl index 9ac08e77863b6..be201e7680217 100644 --- a/base/io.jl +++ b/base/io.jl @@ -215,6 +215,25 @@ readlines(s=STDIN; chomp::Bool=true) = collect(eachline(s, chomp=chomp)) ## byte-order mark, ntoh & hton ## +let endian_boms = reinterpret(UInt8, UInt32[0x01020304]) + global ntoh, hton, ltoh, htol + if endian_boms == UInt8[1:4;] + ntoh(x) = x + hton(x) = x + ltoh(x) = bswap(x) + htol(x) = bswap(x) + const global ENDIAN_BOM = 0x01020304 + elseif endian_boms == UInt8[4:-1:1;] + ntoh(x) = bswap(x) + hton(x) = bswap(x) + ltoh(x) = x + htol(x) = x + const global ENDIAN_BOM = 0x04030201 + else + error("seriously? what is this machine?") + end +end + """ ENDIAN_BOM @@ -222,22 +241,7 @@ The 32-bit byte-order-mark indicates the native byte order of the host machine. Little-endian machines will contain the value `0x04030201`. Big-endian machines will contain the value `0x01020304`. """ -const ENDIAN_BOM = reinterpret(UInt32,UInt8[1:4;])[1] - -if ENDIAN_BOM == 0x01020304 - ntoh(x) = x - hton(x) = x - ltoh(x) = bswap(x) - htol(x) = bswap(x) -elseif ENDIAN_BOM == 0x04030201 - ntoh(x) = bswap(x) - hton(x) = bswap(x) - ltoh(x) = x - htol(x) = x -else - error("seriously? what is this machine?") -end - +ENDIAN_BOM """ ntoh(x) diff --git a/base/pcre.jl b/base/pcre.jl index 1ce746c96fac5..316a5821c23fa 100644 --- a/base/pcre.jl +++ b/base/pcre.jl @@ -69,10 +69,10 @@ const OPTIONS_MASK = COMPILE_MASK | EXECUTE_MASK const UNSET = ~Csize_t(0) # Indicates that an output vector element is unset -function info(regex::Ptr{Void}, what::Integer, T) - buf = zeros(UInt8,sizeof(T)) +function info(regex::Ptr{Void}, what::Integer, ::Type{T}) where T + buf = Ref{T}() ret = ccall((:pcre2_pattern_info_8, PCRE_LIB), Int32, - (Ptr{Void}, Int32, Ptr{UInt8}), + (Ptr{Void}, Int32, Ptr{Void}), regex, what, buf) if ret != 0 error(ret == ERROR_NULL ? "NULL regex object" : @@ -80,7 +80,7 @@ function info(regex::Ptr{Void}, what::Integer, T) ret == ERROR_BADOPTION ? "invalid option flags" : "unknown error $ret") end - reinterpret(T,buf)[1] + buf[] end function get_ovec(match_data) diff --git a/test/core.jl b/test/core.jl index 487ae7edff2a3..3986f2e87a7cf 100644 --- a/test/core.jl +++ b/test/core.jl @@ -4848,12 +4848,15 @@ end let ni128 = sizeof(FP128test) ÷ sizeof(Int), ns128 = sizeof(FP128align) ÷ sizeof(Int), nbit = sizeof(Int) * 8, - arr = reinterpret(FP128align, collect(Int, 1:(2 * ns128))), + arr = Vector{FP128align}(2), offset = Base.datatype_alignment(FP128test) ÷ sizeof(Int), little, - expected + expected, + arrint = reinterpret(Int, arr) + + @test length(arrint) == 2 * ns128 + arrint .= 1:(2 * ns128) @test sizeof(FP128test) == 16 - @test length(arr) == 2 @test arr[1].i == 1 @test arr[2].i == 1 + ns128 expected = UInt128(0) diff --git a/test/misc.jl b/test/misc.jl index ab1166df3be10..4116a6ea9e52a 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -678,3 +678,26 @@ let foo() = begin end @test foo() == 2 end + +# Endian tests +# For now, we only support little endian. +# Add an `Sys.ARCH` test for big endian when/if we add support for that. +# Do **NOT** use `ENDIAN_BOM` to figure out the endianess +# since that's exactly what we want to test. +@test ENDIAN_BOM == 0x04030201 +@test ntoh(0x1) == 0x1 +@test hton(0x1) == 0x1 +@test ltoh(0x1) == 0x1 +@test htol(0x1) == 0x1 +@test ntoh(0x102) == 0x201 +@test hton(0x102) == 0x201 +@test ltoh(0x102) == 0x102 +@test htol(0x102) == 0x102 +@test ntoh(0x1020304) == 0x4030201 +@test hton(0x1020304) == 0x4030201 +@test ltoh(0x1020304) == 0x1020304 +@test htol(0x1020304) == 0x1020304 +@test ntoh(0x102030405060708) == 0x807060504030201 +@test hton(0x102030405060708) == 0x807060504030201 +@test ltoh(0x102030405060708) == 0x102030405060708 +@test htol(0x102030405060708) == 0x102030405060708 From c011b64fd3fc306137f09c0f3257e9c1c89b4a92 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Fri, 12 May 2017 08:55:16 -0400 Subject: [PATCH 0816/1534] Require unsafe_wrap and reinterpret to have proper alignment --- base/docs/helpdb/Base.jl | 8 ++++++++ src/array.c | 42 +++++++++++++++++++++++++++++++--------- test/core.jl | 25 ++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 9 deletions(-) diff --git a/base/docs/helpdb/Base.jl b/base/docs/helpdb/Base.jl index 52b62a85d1732..5445e1df462c6 100644 --- a/base/docs/helpdb/Base.jl +++ b/base/docs/helpdb/Base.jl @@ -1063,6 +1063,14 @@ For example, `reinterpret(Float32, UInt32(7))` interprets the 4 bytes corresponding to `UInt32(7)` as a `Float32`. +!!! warning + + It is not allowed to `reinterpret` an array to an element type with a larger alignment then + the alignment of the array. For a normal `Array`, this is the alignment of its element type. + For a reinterpreted array, this is the alignment of the `Array` it was reinterpreted from. + For example, `reinterpret(UInt32, UInt8[0, 0, 0, 0])` is not allowed but + `reinterpret(UInt32, reinterpret(UInt8, Float32[1.0]))` is allowed. + ```jldoctest julia> reinterpret(Float32, UInt32(7)) 1.0f-44 diff --git a/src/array.c b/src/array.c index 447fa98301ebd..97182ef1eab74 100644 --- a/src/array.c +++ b/src/array.c @@ -188,10 +188,19 @@ JL_DLLEXPORT jl_array_t *jl_reshape_array(jl_value_t *atype, jl_array_t *data, a->offset = 0; a->data = NULL; a->flags.isaligned = data->flags.isaligned; + jl_array_t *owner = (jl_array_t*)jl_array_owner(data); jl_value_t *el_type = jl_tparam0(atype); assert(store_unboxed(el_type) == !data->flags.ptrarray); if (!data->flags.ptrarray) { a->elsize = jl_datatype_size(el_type); + unsigned align = ((jl_datatype_t*)el_type)->layout->alignment; + jl_value_t *ownerty = jl_typeof(owner); + unsigned oldalign = (ownerty == (jl_value_t*)jl_string_type ? 1 : + ((jl_datatype_t*)jl_tparam0(ownerty))->layout->alignment); + if (oldalign < align) + jl_exceptionf(jl_argumenterror_type, + "reinterpret from alignment %u bytes to alignment %u bytes not allowed", + oldalign, align); a->flags.ptrarray = 0; } else { @@ -201,7 +210,7 @@ JL_DLLEXPORT jl_array_t *jl_reshape_array(jl_value_t *atype, jl_array_t *data, // if data is itself a shared wrapper, // owner should point back to the original array - jl_array_data_owner(a) = jl_array_owner(data); + jl_array_data_owner(a) = (jl_value_t*)owner; a->flags.how = 3; a->data = data->data; @@ -266,15 +275,22 @@ JL_DLLEXPORT jl_array_t *jl_ptr_to_array_1d(jl_value_t *atype, void *data, size_t nel, int own_buffer) { jl_ptls_t ptls = jl_get_ptls_states(); - size_t elsz; jl_array_t *a; jl_value_t *el_type = jl_tparam0(atype); int isunboxed = store_unboxed(el_type); - if (isunboxed) + size_t elsz; + unsigned align; + if (isunboxed) { elsz = jl_datatype_size(el_type); - else - elsz = sizeof(void*); + align = ((jl_datatype_t*)el_type)->layout->alignment; + } + else { + align = elsz = sizeof(void*); + } + if (((uintptr_t)data) & (align - 1)) + jl_exceptionf(jl_argumenterror_type, + "unsafe_wrap: pointer %p is not properly aligned to %u bytes", data, align); int ndimwords = jl_array_ndimwords(1); int tsz = JL_ARRAY_ALIGN(sizeof(jl_array_t) + ndimwords*sizeof(size_t), JL_CACHE_BYTE_ALIGNMENT); @@ -309,7 +325,7 @@ JL_DLLEXPORT jl_array_t *jl_ptr_to_array(jl_value_t *atype, void *data, jl_value_t *_dims, int own_buffer) { jl_ptls_t ptls = jl_get_ptls_states(); - size_t elsz, nel = 1; + size_t nel = 1; jl_array_t *a; size_t ndims = jl_nfields(_dims); wideint_t prod; @@ -326,10 +342,18 @@ JL_DLLEXPORT jl_array_t *jl_ptr_to_array(jl_value_t *atype, void *data, jl_value_t *el_type = jl_tparam0(atype); int isunboxed = store_unboxed(el_type); - if (isunboxed) + size_t elsz; + unsigned align; + if (isunboxed) { elsz = jl_datatype_size(el_type); - else - elsz = sizeof(void*); + align = ((jl_datatype_t*)el_type)->layout->alignment; + } + else { + align = elsz = sizeof(void*); + } + if (((uintptr_t)data) & (align - 1)) + jl_exceptionf(jl_argumenterror_type, + "unsafe_wrap: pointer %p is not properly aligned to %u bytes", data, align); int ndimwords = jl_array_ndimwords(ndims); int tsz = JL_ARRAY_ALIGN(sizeof(jl_array_t) + ndimwords*sizeof(size_t), JL_CACHE_BYTE_ALIGNMENT); diff --git a/test/core.jl b/test/core.jl index 3986f2e87a7cf..91f33bbccfaab 100644 --- a/test/core.jl +++ b/test/core.jl @@ -952,7 +952,15 @@ let @test aa == a aa = unsafe_wrap(Array, pointer(a), UInt16(length(a))) @test aa == a + aaa = unsafe_wrap(Array, pointer(a), (1, 1)) + @test size(aaa) == (1, 1) + @test aaa[1] == a[1] @test_throws InexactError unsafe_wrap(Array, pointer(a), -3) + # Misaligned pointer + res = @test_throws ArgumentError unsafe_wrap(Array, pointer(a) + 1, length(a)) + @test contains(res.value.msg, "is not properly aligned to $(sizeof(Int)) bytes") + res = @test_throws ArgumentError unsafe_wrap(Array, pointer(a) + 1, (1, 1)) + @test contains(res.value.msg, "is not properly aligned to $(sizeof(Int)) bytes") end struct FooBar2515 @@ -4906,3 +4914,20 @@ mutable struct T21719{V} end g21719(f, goal; tol = 1e-6) = T21719(f, tol, goal) @test isa(g21719(identity, 1.0; tol=0.1), T21719) + +# reinterpret alignment requirement +let arr8 = zeros(UInt8, 16), + arr64 = zeros(UInt64, 2), + arr64_8 = reinterpret(UInt8, arr64), + arr64_i + + # Not allowed to reinterpret arrays allocated as UInt8 array to a Int32 array + res = @test_throws ArgumentError reinterpret(Int32, arr8) + @test res.value.msg == "reinterpret from alignment 1 bytes to alignment 4 bytes not allowed" + # OK to reinterpret arrays allocated as UInt64 array to a Int64 array even though + # it is passed as a UInt8 array + arr64_i = reinterpret(Int64, arr64_8) + @test arr8 == arr64_8 + arr64_i[2] = 1234 + @test arr64[2] == 1234 +end From dfcbdb9313f2991c95dcd6d2134b7e5cc87773ae Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Wed, 17 May 2017 20:20:15 -0400 Subject: [PATCH 0817/1534] Use testsets and \approx in umfpack.jl (#21904) --- test/sparse/umfpack.jl | 306 +++++++++++++++++++++-------------------- 1 file changed, 156 insertions(+), 150 deletions(-) diff --git a/test/sparse/umfpack.jl b/test/sparse/umfpack.jl index 24273100fceee..a99dac1c92413 100644 --- a/test/sparse/umfpack.jl +++ b/test/sparse/umfpack.jl @@ -1,163 +1,169 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -se33 = speye(3) -do33 = ones(3) -@test isequal(se33 \ do33, do33) - -# based on deps/Suitesparse-4.0.2/UMFPACK/Demo/umfpack_di_demo.c - -using Base.SparseArrays.UMFPACK.increment! - -A0 = sparse(increment!([0,4,1,1,2,2,0,1,2,3,4,4]), - increment!([0,4,0,2,1,2,1,4,3,2,1,2]), - [2.,1.,3.,4.,-1.,-3.,3.,6.,2.,1.,4.,2.], 5, 5) - -for Tv in (Float64, Complex128) - for Ti in Base.uniontypes(Base.SparseArrays.UMFPACK.UMFITypes) - A = convert(SparseMatrixCSC{Tv,Ti}, A0) - lua = lufact(A) - @test nnz(lua) == 18 - @test_throws KeyError lua[:Z] - L,U,p,q,Rs = lua[:(:)] - @test (Diagonal(Rs) * A)[p,q] ≈ L * U - - det(lua) ≈ det(Array(A)) - - b = [8., 45., -3., 3., 19.] - x = lua\b - @test x ≈ float([1:5;]) - - @test norm(A*x-b,1) < eps(1e4) - z = complex.(b,zeros(b)) - x = Base.SparseArrays.A_ldiv_B!(lua, z) - @test x ≈ float([1:5;]) - @test z === x - y = similar(z) - A_ldiv_B!(y, lua, complex.(b,zeros(b))) - @test y ≈ x - - @test norm(A*x-b,1) < eps(1e4) - - b = [8., 20., 13., 6., 17.] - x = lua'\b - @test x ≈ float([1:5;]) - - @test norm(A'*x-b,1) < eps(1e4) - z = complex.(b,zeros(b)) - x = Base.SparseArrays.Ac_ldiv_B!(lua, z) - @test x ≈ float([1:5;]) - @test x === z - y = similar(x) - Base.SparseArrays.Ac_ldiv_B!(y, lua, complex.(b,zeros(b))) - @test y ≈ x - - @test norm(A'*x-b,1) < eps(1e4) - x = lua.'\b - @test x ≈ float([1:5;]) - - @test norm(A.'*x-b,1) < eps(1e4) - x = Base.SparseArrays.At_ldiv_B!(lua,complex.(b,zeros(b))) - @test x ≈ float([1:5;]) - y = similar(x) - Base.SparseArrays.At_ldiv_B!(y, lua,complex.(b,zeros(b))) - @test y ≈ x - - @test norm(A.'*x-b,1) < eps(1e4) - - # Element promotion and type inference - @inferred lua\ones(Int, size(A, 2)) +@testset "UMFPACK wrappers" begin + se33 = speye(3) + do33 = ones(3) + @test isequal(se33 \ do33, do33) + + # based on deps/Suitesparse-4.0.2/UMFPACK/Demo/umfpack_di_demo.c + + using Base.SparseArrays.UMFPACK.increment! + + A0 = sparse(increment!([0,4,1,1,2,2,0,1,2,3,4,4]), + increment!([0,4,0,2,1,2,1,4,3,2,1,2]), + [2.,1.,3.,4.,-1.,-3.,3.,6.,2.,1.,4.,2.], 5, 5) + + @testset "Core functionality for $Tv elements" for Tv in (Float64, Complex128) + # We might be able to support two index sizes one day + for Ti in Base.uniontypes(Base.SparseArrays.UMFPACK.UMFITypes) + A = convert(SparseMatrixCSC{Tv,Ti}, A0) + lua = lufact(A) + @test nnz(lua) == 18 + @test_throws KeyError lua[:Z] + L,U,p,q,Rs = lua[:(:)] + @test (Diagonal(Rs) * A)[p,q] ≈ L * U + + det(lua) ≈ det(Array(A)) + + b = [8., 45., -3., 3., 19.] + x = lua\b + @test x ≈ float([1:5;]) + + @test A*x ≈ b + z = complex.(b,zeros(b)) + x = Base.SparseArrays.A_ldiv_B!(lua, z) + @test x ≈ float([1:5;]) + @test z === x + y = similar(z) + A_ldiv_B!(y, lua, complex.(b,zeros(b))) + @test y ≈ x + + @test A*x ≈ b + + b = [8., 20., 13., 6., 17.] + x = lua'\b + @test x ≈ float([1:5;]) + + @test A'*x ≈ b + z = complex.(b,zeros(b)) + x = Base.SparseArrays.Ac_ldiv_B!(lua, z) + @test x ≈ float([1:5;]) + @test x === z + y = similar(x) + Base.SparseArrays.Ac_ldiv_B!(y, lua, complex.(b,zeros(b))) + @test y ≈ x + + @test A'*x ≈ b + x = lua.'\b + @test x ≈ float([1:5;]) + + @test A.'*x ≈ b + x = Base.SparseArrays.At_ldiv_B!(lua,complex.(b,zeros(b))) + @test x ≈ float([1:5;]) + y = similar(x) + Base.SparseArrays.At_ldiv_B!(y, lua,complex.(b,zeros(b))) + @test y ≈ x + + @test A.'*x ≈ b + + # Element promotion and type inference + @inferred lua\ones(Int, size(A, 2)) + end end -end -Ac0 = complex.(A0,A0) -for Ti in Base.uniontypes(Base.SparseArrays.UMFPACK.UMFITypes) - Ac = convert(SparseMatrixCSC{Complex128,Ti}, Ac0) - x = complex.(ones(size(Ac, 1)), ones(size(Ac,1))) - lua = lufact(Ac) - L,U,p,q,Rs = lua[:(:)] - @test (Diagonal(Rs) * Ac)[p,q] ≈ L * U - b = Ac*x - @test Ac\b ≈ x - b = Ac'*x - @test Ac'\b ≈ x - b = Ac.'*x - @test Ac.'\b ≈ x -end + @testset "More tests for complex cases" begin + Ac0 = complex.(A0,A0) + for Ti in Base.uniontypes(Base.SparseArrays.UMFPACK.UMFITypes) + Ac = convert(SparseMatrixCSC{Complex128,Ti}, Ac0) + x = complex.(ones(size(Ac, 1)), ones(size(Ac,1))) + lua = lufact(Ac) + L,U,p,q,Rs = lua[:(:)] + @test (Diagonal(Rs) * Ac)[p,q] ≈ L * U + b = Ac*x + @test Ac\b ≈ x + b = Ac'*x + @test Ac'\b ≈ x + b = Ac.'*x + @test Ac.'\b ≈ x + end + end -for elty in (Float64, Complex128) - for (m, n) in ((10,5), (5, 10)) - A = sparse([1:min(m,n); rand(1:m, 10)], [1:min(m,n); rand(1:n, 10)], elty == Float64 ? randn(min(m, n) + 10) : complex.(randn(min(m, n) + 10), randn(min(m, n) + 10))) - F = lufact(A) - L, U, p, q, Rs = F[:(:)] - @test (Diagonal(Rs) * A)[p,q] ≈ L * U + @testset "Rectangular cases" for elty in (Float64, Complex128) + for (m, n) in ((10,5), (5, 10)) + A = sparse([1:min(m,n); rand(1:m, 10)], [1:min(m,n); rand(1:n, 10)], elty == Float64 ? randn(min(m, n) + 10) : complex.(randn(min(m, n) + 10), randn(min(m, n) + 10))) + F = lufact(A) + L, U, p, q, Rs = F[:(:)] + @test (Diagonal(Rs) * A)[p,q] ≈ L * U + end end -end -#4523 - complex sparse \ -x = speye(2) + im * speye(2) -@test (x*(lufact(x) \ ones(2))) ≈ ones(2) - -@test det(sparse([1,3,3,1], [1,1,3,3], [1,1,1,1])) == 0 - -# UMFPACK_ERROR_n_nonpositive -@test_throws ArgumentError lufact(sparse(Int[], Int[], Float64[], 5, 0)) - -#15099 -for (Tin, Tout) in ( - (Complex32, Complex128), - (Complex64, Complex128), - (Complex128, Complex128), - (Float16, Float64), - (Float32, Float64), - (Float64, Float64), - (Int, Float64), - ) - - F = lufact(sparse(ones(Tin, 1, 1))) - L = sparse(ones(Tout, 1, 1)) - @test F[:p] == F[:q] == [1] - @test F[:Rs] == [1.0] - @test F[:L] == F[:U] == L - @test F[:(:)] == (L, L, [1], [1], [1.0]) -end + @testset "Issue #4523 - complex sparse \\" begin + x = speye(2) + im * speye(2) + @test (x*(lufact(x) \ ones(2))) ≈ ones(2) -for T in (BigFloat, Complex{BigFloat}) - @test_throws ArgumentError lufact(sparse(ones(T, 1, 1))) -end + @test det(sparse([1,3,3,1], [1,1,3,3], [1,1,1,1])) == 0 + end -#size(::UmfpackLU) -let - m = n = 1 - F = lufact(sparse(ones(m, n))) - @test size(F) == (m, n) - @test size(F, 1) == m - @test size(F, 2) == n - @test size(F, 3) == 1 - @test_throws ArgumentError size(F,-1) -end + @testset "UMFPACK_ERROR_n_nonpositive" begin + @test_throws ArgumentError lufact(sparse(Int[], Int[], Float64[], 5, 0)) + end -let - a = rand(5) - @test_throws ArgumentError Base.SparseArrays.UMFPACK.solve!(a, lufact(speye(5,5)), a, Base.SparseArrays.UMFPACK.UMFPACK_A) - aa = complex(a) - @test_throws ArgumentError Base.SparseArrays.UMFPACK.solve!(aa, lufact(complex(speye(5,5))), aa, Base.SparseArrays.UMFPACK.UMFPACK_A) -end + @testset "Issue #15099" for (Tin, Tout) in ( + (Complex32, Complex128), + (Complex64, Complex128), + (Complex128, Complex128), + (Float16, Float64), + (Float32, Float64), + (Float64, Float64), + (Int, Float64), + ) + + F = lufact(sparse(ones(Tin, 1, 1))) + L = sparse(ones(Tout, 1, 1)) + @test F[:p] == F[:q] == [1] + @test F[:Rs] == [1.0] + @test F[:L] == F[:U] == L + @test F[:(:)] == (L, L, [1], [1], [1.0]) + end -#18246,18244-lufact sparse pivot -let A = speye(4) - A[1:2,1:2] = [-.01 -200; 200 .001] - F = lufact(A) - @test F[:p] == [3 ; 4 ; 2 ; 1] -end + @testset "BigFloat not supported" for T in (BigFloat, Complex{BigFloat}) + @test_throws ArgumentError lufact(sparse(ones(T, 1, 1))) + end + + @testset "size(::UmfpackLU)" begin + m = n = 1 + F = lufact(sparse(ones(m, n))) + @test size(F) == (m, n) + @test size(F, 1) == m + @test size(F, 2) == n + @test size(F, 3) == 1 + @test_throws ArgumentError size(F,-1) + end + + @testset "Test aliasing" begin + a = rand(5) + @test_throws ArgumentError Base.SparseArrays.UMFPACK.solve!(a, lufact(speye(5,5)), a, Base.SparseArrays.UMFPACK.UMFPACK_A) + aa = complex(a) + @test_throws ArgumentError Base.SparseArrays.UMFPACK.solve!(aa, lufact(complex(speye(5,5))), aa, Base.SparseArrays.UMFPACK.UMFPACK_A) + end + + @testset "Issues #18246,18244 - lufact sparse pivot" begin + A = speye(4) + A[1:2,1:2] = [-.01 -200; 200 .001] + F = lufact(A) + @test F[:p] == [3 ; 4 ; 2 ; 1] + end + + @testset "Test that A[c|t]_ldiv_B!{T<:Complex}(X::StridedMatrix{T}, lu::UmfpackLU{Float64}, B::StridedMatrix{T}) works as expected." begin + N = 10 + p = 0.5 + A = N*speye(N) + sprand(N, N, p) + X = zeros(Complex{Float64}, N, N) + B = complex.(rand(N, N), rand(N, N)) + luA, lufA = lufact(A), lufact(Array(A)) + @test A_ldiv_B!(copy(X), luA, B) ≈ A_ldiv_B!(copy(X), lufA, B) + @test At_ldiv_B!(copy(X), luA, B) ≈ At_ldiv_B!(copy(X), lufA, B) + @test Ac_ldiv_B!(copy(X), luA, B) ≈ Ac_ldiv_B!(copy(X), lufA, B) + end -# Test that A[c|t]_ldiv_B!{T<:Complex}(X::StridedMatrix{T}, lu::UmfpackLU{Float64}, -# B::StridedMatrix{T}) works as expected. -let N = 10, p = 0.5 - A = N*speye(N) + sprand(N, N, p) - X = zeros(Complex{Float64}, N, N) - B = complex.(rand(N, N), rand(N, N)) - luA, lufA = lufact(A), lufact(Array(A)) - @test A_ldiv_B!(copy(X), luA, B) ≈ A_ldiv_B!(copy(X), lufA, B) - @test At_ldiv_B!(copy(X), luA, B) ≈ At_ldiv_B!(copy(X), lufA, B) - @test Ac_ldiv_B!(copy(X), luA, B) ≈ Ac_ldiv_B!(copy(X), lufA, B) end From 1ce1d75e59bae7ce99859d47281f62dbb3644e27 Mon Sep 17 00:00:00 2001 From: Gollor Date: Thu, 18 May 2017 04:50:12 +0300 Subject: [PATCH 0818/1534] Test trigger. From 7d83d9908f25ffe4f8a9ae0499bc17dfb7b6b005 Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Wed, 10 May 2017 20:26:34 -0700 Subject: [PATCH 0819/1534] Workaround for FreeBSD linking to outdated system libs FreeBSD's system libgcc_s declares its GCC version as 4.6, which is too old to build Julia. Since gfortran doesn't come installed by default, when it's installed it's done so through a GCC port, which includes its own libgcc_s. Linking to libgfortran from the port and to the system's libgcc_s causes versioning issues which wreck the build. This commit works around this issue by determining the version of GCC used for gfortran, then linking in the libgcc_s corresponding to that version everywhere. It's a bit of a kludge, but it gets the job done. With this change, all libraries which need to link to libgcc_s link to the proper version. --- Make.inc | 30 ++++++++++++++++++++++++++++++ deps/libgit2.mk | 3 +++ deps/llvm.mk | 8 ++++++++ deps/mbedtls.mk | 3 +++ deps/tools/common.mk | 7 +++++++ 5 files changed, 51 insertions(+) diff --git a/Make.inc b/Make.inc index d40abf17adb86..dda36ba03c7bd 100644 --- a/Make.inc +++ b/Make.inc @@ -520,6 +520,36 @@ ifeq (exists, $(shell [ -e $(BUILDROOT)/Make.user ] && echo exists )) include $(BUILDROOT)/Make.user endif +# A bit of a kludge to work around libraries linking to FreeBSD's outdated system libgcc_s +# Instead, let's link to the libgcc_s corresponding to the installation of gfortran +ifeq ($(OS),FreeBSD) +ifneq (,$(findstring gfortran,$(FC))) + +# First let's figure out what version of GCC we're dealing with +_GCCMAJOR := $(shell $(FC) -dumpversion | cut -d'.' -f1) +_GCCMINOR := $(shell $(FC) -dumpversion | cut -d'.' -f2) + +# The ports system uses major and minor for GCC < 5 (e.g. gcc49 for GCC 4.9), otherwise major only +ifeq ($(_GCCMAJOR),4) + _GCCVER := $(_GCCMAJOR)$(_GCCMINOR) +else + _GCCVER := $(_GCCMAJOR) +endif + +# Allow the user to specify this in Make.user +GCCPATH ?= $(LOCALBASE)/lib/gcc$(_GCCVER) + +LDFLAGS += -L$(build_libdir) -L$(GCCPATH) -Wl,-rpath,$(build_libdir) -Wl,-rpath,$(GCCPATH) + +# This ensures we get the right RPATH even if we're missing FFLAGS somewhere +FC += -Wl,-rpath=$(GCCPATH) + +# Build our own libc++ and libc++abi because otherwise /usr/lib/libc++.so and /lib/libcxxrt.so will +# be linked in when building LLVM, and those link to /lib/libgcc_s.so +BUILD_CUSTOM_LIBCXX ?= 1 +endif # gfortran +endif # FreeBSD + ifneq ($(CC_BASE)$(CXX_BASE),$(shell echo $(CC) | cut -d' ' -f1)$(shell echo $(CXX) | cut -d' ' -f1)) $(error Forgot override directive on CC or CXX in Make.user? Cowardly refusing to build) endif diff --git a/deps/libgit2.mk b/deps/libgit2.mk index 129fbe610fa17..e535c5d551713 100644 --- a/deps/libgit2.mk +++ b/deps/libgit2.mk @@ -41,8 +41,11 @@ LIBGIT2_OPTS += -DUSE_OPENSSL=OFF -DUSE_MBEDTLS=ON -DCMAKE_INSTALL_RPATH="\$$ORI endif ifeq ($(OS),FreeBSD) +# We're getting this from CMAKE_COMMON when GCCPATH is nonempty +ifeq ($(GCCPATH),) LIBGIT2_OPTS += -DCMAKE_INSTALL_RPATH="\$$ORIGIN" endif +endif # We need to bundle ca certs on linux now that we're using libgit2 with ssl ifeq ($(OS),Linux) diff --git a/deps/llvm.mk b/deps/llvm.mk index 5ac5ab438f51a..043c19483dfd2 100644 --- a/deps/llvm.mk +++ b/deps/llvm.mk @@ -135,6 +135,14 @@ LLVM_CMAKE += -DLLDB_DISABLE_PYTHON=ON endif # LLDB_DISABLE_PYTHON endif # BUILD_LLDB +# Part of the FreeBSD libgcc_s kludge +ifeq ($(OS),FreeBSD) +ifneq ($(GCCPATH),) +LLVM_CMAKE += -DCMAKE_INSTALL_RPATH="\$$ORIGIN:$(GCCPATH)" +LLVM_LDFLAGS += -Wl,-rpath,'\$$ORIGIN',-rpath,$(GCCPATH) +endif +endif + ifneq (,$(filter $(ARCH), powerpc64le ppc64le)) LLVM_CXXFLAGS += -mminimal-toc endif diff --git a/deps/mbedtls.mk b/deps/mbedtls.mk index 4199c947779ab..4ac9a033b3352 100644 --- a/deps/mbedtls.mk +++ b/deps/mbedtls.mk @@ -20,8 +20,11 @@ MBEDTLS_OPTS += -DCMAKE_INSTALL_RPATH="\$$ORIGIN" endif ifeq ($(OS),FreeBSD) +# We're getting this from CMAKE_COMMON when GCCPATH is nonempty +ifeq ($(GCCPATH),) MBEDTLS_OPTS += -DCMAKE_INSTALL_RPATH="\$$ORIGIN" endif +endif $(SRCDIR)/srccache/$(MBEDTLS_SRC).tgz: | $(SRCDIR)/srccache $(JLDOWNLOAD) $@ $(MBEDTLS_URL) diff --git a/deps/tools/common.mk b/deps/tools/common.mk index df491b256c124..93cc4e6560244 100644 --- a/deps/tools/common.mk +++ b/deps/tools/common.mk @@ -37,6 +37,13 @@ CMAKE_COMMON += -DCMAKE_RC_COMPILER="$$(which $(CROSS_COMPILE)windres)" endif endif +# Part of the FreeBSD libgcc_s kludge +ifeq ($(OS),FreeBSD) +ifneq ($(GCCPATH),) +CMAKE_COMMON += -DCMAKE_INSTALL_RPATH="\$$ORIGIN:$(GCCPATH)" +endif +endif + # For now this is LLVM specific, but I expect it won't be in the future ifeq ($(LLVM_USE_CMAKE),1) ifeq ($(CMAKE_GENERATOR),Ninja) From 78305aad4a57d426ea282d604c71a4865b6f4e6e Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Sat, 13 May 2017 14:02:35 -0700 Subject: [PATCH 0820/1534] Rearrange CMake RPATH specifications to be centrally defined --- deps/libgit2.mk | 9 +-------- deps/libssh2.mk | 8 -------- deps/llvm.mk | 1 - deps/mbedtls.mk | 11 ----------- deps/tools/common.mk | 6 +++++- 5 files changed, 6 insertions(+), 29 deletions(-) diff --git a/deps/libgit2.mk b/deps/libgit2.mk index e535c5d551713..11d5bcbee196b 100644 --- a/deps/libgit2.mk +++ b/deps/libgit2.mk @@ -37,14 +37,7 @@ LIBGIT2_OPTS += -DCURL_INCLUDE_DIRS=$(build_includedir) -DCURL_LIBRARIES="-L$(bu endif ifeq ($(OS),Linux) -LIBGIT2_OPTS += -DUSE_OPENSSL=OFF -DUSE_MBEDTLS=ON -DCMAKE_INSTALL_RPATH="\$$ORIGIN" -endif - -ifeq ($(OS),FreeBSD) -# We're getting this from CMAKE_COMMON when GCCPATH is nonempty -ifeq ($(GCCPATH),) -LIBGIT2_OPTS += -DCMAKE_INSTALL_RPATH="\$$ORIGIN" -endif +LIBGIT2_OPTS += -DUSE_OPENSSL=OFF -DUSE_MBEDTLS=ON endif # We need to bundle ca certs on linux now that we're using libgit2 with ssl diff --git a/deps/libssh2.mk b/deps/libssh2.mk index 8bbe6dd310dac..ea77379988ac0 100644 --- a/deps/libssh2.mk +++ b/deps/libssh2.mk @@ -20,14 +20,6 @@ else LIBSSH2_OPTS += -DCRYPTO_BACKEND=mbedTLS -DENABLE_ZLIB_COMPRESSION=OFF endif -ifeq ($(OS),Linux) -LIBSSH2_OPTS += -DCMAKE_INSTALL_RPATH="\$$ORIGIN" -endif - -ifeq ($(OS),FreeBSD) -LIBSSH2_OPTS += -DCMAKE_INSTALL_RPATH="\$$ORIGIN" -endif - $(SRCDIR)/srccache/$(LIBSSH2_SRC_DIR)/libssh2-encryptedpem.patch-applied: $(SRCDIR)/srccache/$(LIBSSH2_SRC_DIR)/source-extracted cd $(SRCDIR)/srccache/$(LIBSSH2_SRC_DIR) && patch -p1 -f < $(SRCDIR)/patches/libssh2-encryptedpem.patch echo 1 > $@ diff --git a/deps/llvm.mk b/deps/llvm.mk index 043c19483dfd2..8a3738841eaac 100644 --- a/deps/llvm.mk +++ b/deps/llvm.mk @@ -138,7 +138,6 @@ endif # BUILD_LLDB # Part of the FreeBSD libgcc_s kludge ifeq ($(OS),FreeBSD) ifneq ($(GCCPATH),) -LLVM_CMAKE += -DCMAKE_INSTALL_RPATH="\$$ORIGIN:$(GCCPATH)" LLVM_LDFLAGS += -Wl,-rpath,'\$$ORIGIN',-rpath,$(GCCPATH) endif endif diff --git a/deps/mbedtls.mk b/deps/mbedtls.mk index 4ac9a033b3352..9ebc0c071dbdd 100644 --- a/deps/mbedtls.mk +++ b/deps/mbedtls.mk @@ -15,17 +15,6 @@ ifeq ($(BUILD_OS),WINNT) MBEDTLS_OPTS += -G"MSYS Makefiles" endif -ifeq ($(OS),Linux) -MBEDTLS_OPTS += -DCMAKE_INSTALL_RPATH="\$$ORIGIN" -endif - -ifeq ($(OS),FreeBSD) -# We're getting this from CMAKE_COMMON when GCCPATH is nonempty -ifeq ($(GCCPATH),) -MBEDTLS_OPTS += -DCMAKE_INSTALL_RPATH="\$$ORIGIN" -endif -endif - $(SRCDIR)/srccache/$(MBEDTLS_SRC).tgz: | $(SRCDIR)/srccache $(JLDOWNLOAD) $@ $(MBEDTLS_URL) diff --git a/deps/tools/common.mk b/deps/tools/common.mk index 93cc4e6560244..130d62db80c95 100644 --- a/deps/tools/common.mk +++ b/deps/tools/common.mk @@ -37,12 +37,16 @@ CMAKE_COMMON += -DCMAKE_RC_COMPILER="$$(which $(CROSS_COMPILE)windres)" endif endif +ifneq (,$(findstring $(OS),Linux FreeBSD)) +INSTALL_RPATH := "\$$ORIGIN" # Part of the FreeBSD libgcc_s kludge ifeq ($(OS),FreeBSD) ifneq ($(GCCPATH),) -CMAKE_COMMON += -DCMAKE_INSTALL_RPATH="\$$ORIGIN:$(GCCPATH)" +INSTALL_RPATH := "\$$ORIGIN:$(GCCPATH)" endif endif +CMAKE_COMMON += -DCMAKE_INSTALL_RPATH=$(INSTALL_RPATH) +endif # Linux or FreeBSD # For now this is LLVM specific, but I expect it won't be in the future ifeq ($(LLVM_USE_CMAKE),1) From 259dacab8833446071263e073c9d097a38b8bd77 Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Wed, 17 May 2017 22:41:01 -0700 Subject: [PATCH 0821/1534] Pass LD and LDFLAGS to more dependencies (#21764) --- deps/blas.mk | 2 +- deps/llvm.mk | 1 + deps/tools/common.mk | 5 ++++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/deps/blas.mk b/deps/blas.mk index 55216c84ee112..3b3200bd17418 100644 --- a/deps/blas.mk +++ b/deps/blas.mk @@ -4,7 +4,7 @@ OPENBLAS_GIT_URL := git://github.com/xianyi/OpenBLAS.git OPENBLAS_TAR_URL = https://api.github.com/repos/xianyi/OpenBLAS/tarball/$1 $(eval $(call git-external,openblas,OPENBLAS,,,$(BUILDDIR))) -OPENBLAS_BUILD_OPTS := CC="$(CC)" FC="$(FC)" RANLIB="$(RANLIB)" TARGET=$(OPENBLAS_TARGET_ARCH) BINARY=$(BINARY) +OPENBLAS_BUILD_OPTS := CC="$(CC)" FC="$(FC)" LD="$(LD)" RANLIB="$(RANLIB)" TARGET=$(OPENBLAS_TARGET_ARCH) BINARY=$(BINARY) # Thread support ifeq ($(OPENBLAS_USE_THREAD), 1) diff --git a/deps/llvm.mk b/deps/llvm.mk index 5ac5ab438f51a..e008093fc0b5e 100644 --- a/deps/llvm.mk +++ b/deps/llvm.mk @@ -73,6 +73,7 @@ LLVM_FLAGS += --disable-bindings --disable-docs --disable-libedit --disable-term # LLVM has weird install prefixes (see llvm-$(LLVM_VER)/build_$(LLVM_BUILDTYPE)/Makefile.config for the full list) # We map them here to the "normal" ones, which means just prefixing "PROJ_" to the variable name. LLVM_MFLAGS := PROJ_libdir=$(build_libdir) PROJ_bindir=$(build_depsbindir) PROJ_includedir=$(build_includedir) +LLVM_MFLAGS += LD="$(LD)" ifeq ($(LLVM_ASSERTIONS), 1) LLVM_FLAGS += --enable-assertions LLVM_CMAKE += -DLLVM_ENABLE_ASSERTIONS:BOOL=ON diff --git a/deps/tools/common.mk b/deps/tools/common.mk index df491b256c124..76c000f904665 100644 --- a/deps/tools/common.mk +++ b/deps/tools/common.mk @@ -8,8 +8,10 @@ ifeq ($(OS),WINNT) ifneq ($(USEMSVC), 1) CONFIGURE_COMMON += LDFLAGS="$(LDFLAGS) -Wl,--stack,8388608" endif +else +CONFIGURE_COMMON += LDFLAGS="$(LDFLAGS)" endif -CONFIGURE_COMMON += F77="$(FC)" CC="$(CC)" CXX="$(CXX)" +CONFIGURE_COMMON += F77="$(FC)" CC="$(CC)" CXX="$(CXX)" LD="$(LD)" CMAKE_CC_ARG := $(CC_ARG) CMAKE_CXX_ARG := $(CXX_ARG) @@ -29,6 +31,7 @@ CMAKE_COMMON += -DCMAKE_CXX_COMPILER="$(CXX_BASE)" ifneq ($(strip $(CMAKE_CXX_ARG)),) CMAKE_COMMON += -DCMAKE_CXX_COMPILER_ARG1="$(CMAKE_CXX_ARG)" endif +CMAKE_COMMON += -DCMAKE_LINKER="$(LD)" ifeq ($(OS),WINNT) CMAKE_COMMON += -DCMAKE_SYSTEM_NAME=Windows From d28135df60be3703741ade50da8e35a03c4863c0 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Thu, 18 May 2017 12:50:56 +0200 Subject: [PATCH 0822/1534] re-enable ndigits(::Bool, b) (fix #21919) --- base/intfuncs.jl | 2 ++ test/intfuncs.jl | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index fca9fc16a1dc8..80844541b3cd8 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -371,6 +371,7 @@ function ndigits0znb(n::Integer, b::Integer) end ndigits0znb(n::Unsigned, b::Integer) = ndigits0znb(signed(n), b) +ndigits0znb(n::Bool, b::Integer) = n % Int # The suffix "pb" stands for "positive base" # TODO: allow b::Integer @@ -400,6 +401,7 @@ end ndigits0zpb(x::Base.BitSigned, b::Integer) = ndigits0zpb(unsigned(abs(x)), Int(b)) ndigits0zpb(x::Base.BitUnsigned, b::Integer) = ndigits0zpb(x, Int(b)) +ndigits0zpb(x::Bool, b::Integer) = x % Int # The suffix "0z" means that the output is 0 on input zero (cf. #16841) """ diff --git a/test/intfuncs.jl b/test/intfuncs.jl index 7a445307e197d..dfd860f64994a 100644 --- a/test/intfuncs.jl +++ b/test/intfuncs.jl @@ -103,6 +103,11 @@ end @test ndigits(9, 0x2) == 4 @test ndigits(0x9, 0x2) == 4 +# ndigits is defined for Bool +@test iszero([Base.ndigits0z(false, b) for b in [-20:-2;2:20]]) +@test all(n -> n == 1, Base.ndigits0z(true, b) for b in [-20:-2;2:20]) +@test all(n -> n == 1, ndigits(x, b) for b in [-20:-2;2:20] for x in [true, false]) + @test bin('3') == "110011" @test bin('3',7) == "0110011" @test bin(3) == "11" From b46682ff509222d25c2443af6b18e9a4a01cbe38 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Thu, 18 May 2017 12:56:01 +0200 Subject: [PATCH 0823/1534] ndigits functions: rename n -> x for consistency --- base/intfuncs.jl | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 80844541b3cd8..0be6371d9b1f6 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -360,39 +360,39 @@ ndigits(x::Integer) = iszero(x) ? 1 : ndigits0z(x) ## ndigits with specified base ## # The suffix "nb" stands for "negative base" -function ndigits0znb(n::Integer, b::Integer) - # precondition: b < -1 && !(typeof(n) <: Unsigned) +function ndigits0znb(x::Integer, b::Integer) + # precondition: b < -1 && !(typeof(x) <: Unsigned) d = 0 - while n != 0 - n = cld(n,b) + while x != 0 + x = cld(x,b) d += 1 end return d end -ndigits0znb(n::Unsigned, b::Integer) = ndigits0znb(signed(n), b) -ndigits0znb(n::Bool, b::Integer) = n % Int +ndigits0znb(x::Unsigned, b::Integer) = ndigits0znb(signed(x), b) +ndigits0znb(x::Bool, b::Integer) = x % Int # The suffix "pb" stands for "positive base" # TODO: allow b::Integer -function ndigits0zpb(n::Base.BitUnsigned, b::Int) +function ndigits0zpb(x::Base.BitUnsigned, b::Int) # precondition: b > 1 - b < 0 && return ndigits0znb(signed(n), b) - b == 2 && return sizeof(n)<<3 - leading_zeros(n) - b == 8 && return (sizeof(n)<<3 - leading_zeros(n) + 2) ÷ 3 - b == 16 && return sizeof(n)<<1 - leading_zeros(n)>>2 - b == 10 && return ndigits0z(n) + b < 0 && return ndigits0znb(signed(x), b) + b == 2 && return sizeof(x)<<3 - leading_zeros(x) + b == 8 && return (sizeof(x)<<3 - leading_zeros(x) + 2) ÷ 3 + b == 16 && return sizeof(x)<<1 - leading_zeros(x)>>2 + b == 10 && return ndigits0z(x) d = 0 - while n > typemax(Int) - n = div(n,b) + while x > typemax(Int) + x = div(x,b) d += 1 end - n = div(n,b) + x = div(x,b) d += 1 m = 1 - while m <= n + while m <= x m *= b d += 1 end From 71201d772bdb60d784c4bf7fb01043f002cb92b2 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Thu, 9 Jun 2016 21:16:28 +0530 Subject: [PATCH 0824/1534] base/digits: allow negative bases --- NEWS.md | 2 ++ base/gmp.jl | 2 ++ base/intfuncs.jl | 38 ++++++++++++++++++++++++++------------ test/intfuncs.jl | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 12 deletions(-) diff --git a/NEWS.md b/NEWS.md index 00b98f4144526..ef56f334e7757 100644 --- a/NEWS.md +++ b/NEWS.md @@ -28,6 +28,8 @@ This section lists changes that do not have deprecation warnings. Library improvements -------------------- + * the functions `base` and `digits` digits now accept a negative + base (like `ndigits` did). Compiler/Runtime improvements ----------------------------- diff --git a/base/gmp.jl b/base/gmp.jl index af0ebdc0d763c..57e68c62a001e 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -558,6 +558,7 @@ dec(n::BigInt, pad::Int) = base(10, n, pad) hex(n::BigInt, pad::Int) = base(16, n, pad) function base(b::Integer, n::BigInt) + b < 0 && return base(Int(b), n, 1, (b>0) & (n.size<0)) 2 <= b <= 62 || throw(ArgumentError("base must be 2 ≤ base ≤ 62, got $b")) nd = ndigits(n, b) str = Base._string_n(n < 0 ? nd+1 : nd) @@ -566,6 +567,7 @@ function base(b::Integer, n::BigInt) end function base(b::Integer, n::BigInt, pad::Integer) + b < 0 && return base(Int(b), n, pad, (b>0) & (n.size<0)) s = base(b, n) buf = IOBuffer() if n < 0 diff --git a/base/intfuncs.jl b/base/intfuncs.jl index fca9fc16a1dc8..c9026270107be 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -486,14 +486,21 @@ num2hex(n::Integer) = hex(n, sizeof(n)*2) const base36digits = ['0':'9';'a':'z'] const base62digits = ['0':'9';'A':'Z';'a':'z'] -function base(b::Int, x::Unsigned, pad::Int, neg::Bool) - 2 <= b <= 62 || throw(ArgumentError("base must be 2 ≤ base ≤ 62, got $b")) - digits = b <= 36 ? base36digits : base62digits + +function base(b::Int, x::Integer, pad::Int, neg::Bool) + (x >= 0) | (b < 0) || throw(DomainError()) + 2 <= abs(b) <= 62 || throw(ArgumentError("base must satisfy 2 ≤ abs(base) ≤ 62, got $b")) + digits = abs(b) <= 36 ? base36digits : base62digits i = neg + ndigits(x, b, pad) a = StringVector(i) - while i > neg - a[i] = digits[1+rem(x,b)] - x = div(x,b) + @inbounds while i > neg + if b > 0 + a[i] = digits[1+rem(x,b)] + x = div(x,b) + else + a[i] = digits[1+mod(x,-b)] + x = cld(x,b) + end i -= 1 end if neg; a[1]='-'; end @@ -514,7 +521,8 @@ julia> base(5,13,4) "0023" ``` """ -base(b::Integer, n::Integer, pad::Integer=1) = base(Int(b), unsigned(abs(n)), pad, n<0) +base(b::Integer, n::Integer, pad::Integer=1) = + base(Int(b), b > 0 ? unsigned(abs(n)) : convert(Signed, n), Int(pad), (b>0) & (n<0)) for sym in (:bin, :oct, :dec, :hex) @eval begin @@ -589,12 +597,18 @@ Fills an array of the digits of `n` in the given base. More significant digits a indexes. If the array length is insufficient, the least significant digits are filled up to the array length. If the array length is excessive, the excess portion is filled with zeros. """ -function digits!(a::AbstractArray{T,1}, n::Integer, base::Integer=10) where T<:Integer - 2 <= base || throw(ArgumentError("base must be ≥ 2, got $base")) - base - 1 <= typemax(T) || throw(ArgumentError("type $T too small for base $base")) +function digits!(a::AbstractVector{T}, n::Integer, base::Integer=10) where T<:Integer + base < 0 && isa(n, Unsigned) && return digits!(a, convert(Signed, n), base) + 2 <= abs(base) || throw(ArgumentError("base must be ≥ 2 or ≤ -2, got $base")) + abs(base) - 1 <= typemax(T) || throw(ArgumentError("type $T too small for base $base")) for i in eachindex(a) - a[i] = rem(n, base) - n = div(n, base) + if base > 0 + a[i] = rem(n, base) + n = div(n, base) + else + a[i] = mod(n, -base) + n = cld(n, base) + end end return a end diff --git a/test/intfuncs.jl b/test/intfuncs.jl index 7a445307e197d..ca0f5a426f083 100644 --- a/test/intfuncs.jl +++ b/test/intfuncs.jl @@ -131,6 +131,41 @@ end @test digits(4, 2) == [0, 0, 1] @test digits(5, 3) == [2, 1] +# digits with negative bases +@testset "digits/base with negative bases" begin + @testset "digits(n::$T, b)" for T in (Int, UInt, BigInt, Int32) + @test digits(T(8163), -10) == [3, 4, 2, 2, 1] + if !(T<:Unsigned) + @test digits(T(-8163), -10) == [7, 7, 9, 9] + end + end + @test [base(b, n) + for n = [-10^9, -10^5, -2^20, -2^10, -100, -83, -50, -34, -27, -16, -7, -3, -2, -1, + 0, 1, 2, 3, 4, 7, 16, 27, 34, 50, 83, 100, 2^10, 2^20, 10^5, 10^9] + for b = [-2, -3, -7, -10, -60]] == + ["11000101101001010100101000000000", "11211100201202120012", + "144246601121", "1000000000", "2hANlK", "111000111010100000", + "122011122112", "615462", "100000", "1XlK", "1100000000000000000000", + "11000202101022", "25055043", "19169584", "59Hi", "110000000000", + "12102002", "3005", "1036", "Iu", "11101100", "121112", "1515", + "1900", "2K", "11111101", "120011", "1651", "97", "2b", "11010010", + "2121", "1616", "50", "1A", "100010", "2202", "51", "46", "1Q", + "100101", "1000", "41", "33", "1X", "110000", "1102", "35", "24", + "1i", "1001", "1202", "10", "13", "1r", "1101", "10", "14", "17", + "1v", "10", "11", "15", "18", "1w", "11", "12", "16", "19", "1x", "0", + "0", "0", "0", "0", "1", "1", "1", "1", "1", "110", "2", "2", "2", + "2", "111", "120", "3", "3", "3", "100", "121", "4", "4", "4", + "11011", "111", "160", "7", "7", "10000", "211", "152", "196", "G", + "1101111", "12000", "146", "187", "R", "1100110", "12111", "136", + "174", "Y", "1110110", "11022", "101", "150", "o", "1010111", "10002", + "236", "123", "1xN", "110100100", "10201", "202", "100", "1xe", + "10000000000", "2211011", "14012", "19184", "1h4", + "100000000000000000000", "2001112212121", "162132144", "1052636", + "1uqiG", "1101001101111100000", "21002022201", "1103425", "1900000", + "SEe", "1001100111011111101111000000000", "120220201100111010001", + "44642116066", "19000000000", "1xIpcEe"] +end + @test leading_ones(UInt32(Int64(2) ^ 32 - 2)) == 31 @test leading_ones(1) == 0 @test leading_zeros(Int32(1)) == 31 From 1194f26db4204ef6a8651f007f3b7461e850ce58 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Thu, 18 May 2017 18:11:41 +0200 Subject: [PATCH 0825/1534] NEWS.md: add reference and update --- NEWS.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index ef56f334e7757..bd638af5b1ce8 100644 --- a/NEWS.md +++ b/NEWS.md @@ -29,7 +29,7 @@ Library improvements -------------------- * the functions `base` and `digits` digits now accept a negative - base (like `ndigits` did). + base (like `ndigits` did) ([#21692]). Compiler/Runtime improvements ----------------------------- @@ -596,6 +596,7 @@ Command-line option changes [#12563]: https://github.com/JuliaLang/julia/issues/12563 [#15850]: https://github.com/JuliaLang/julia/issues/15850 [#16213]: https://github.com/JuliaLang/julia/issues/16213 +[#16937]: https://github.com/JuliaLang/julia/issues/16937 [#16961]: https://github.com/JuliaLang/julia/issues/16961 [#16984]: https://github.com/JuliaLang/julia/issues/16984 [#16986]: https://github.com/JuliaLang/julia/issues/16986 @@ -716,9 +717,11 @@ Command-line option changes [#20500]: https://github.com/JuliaLang/julia/issues/20500 [#20530]: https://github.com/JuliaLang/julia/issues/20530 [#20543]: https://github.com/JuliaLang/julia/issues/20543 +[#20575]: https://github.com/JuliaLang/julia/issues/20575 [#20609]: https://github.com/JuliaLang/julia/issues/20609 [#20889]: https://github.com/JuliaLang/julia/issues/20889 [#21183]: https://github.com/JuliaLang/julia/issues/21183 [#21359]: https://github.com/JuliaLang/julia/issues/21359 +[#21692]: https://github.com/JuliaLang/julia/issues/21692 [#21697]: https://github.com/JuliaLang/julia/issues/21697 [#21759]: https://github.com/JuliaLang/julia/issues/21759 From b94cca127daba061b167f1e1b39de78e10c79d42 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Thu, 18 May 2017 12:37:00 -0700 Subject: [PATCH 0826/1534] Fix PR number in NEWS.md entry for num/den rename (#19246). (#21943) --- NEWS.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index bd638af5b1ce8..7b6831db13398 100644 --- a/NEWS.md +++ b/NEWS.md @@ -482,7 +482,7 @@ Deprecated or removed for example `(+)(J::UniformScaling, x::Number)`, have been deprecated in favor of unambiguous, explicit equivalents, for example `J.λ + x` ([#17607]). - * `num` and `den` have been deprecated in favor of `numerator` and `denominator` respectively ([#19233]). + * `num` and `den` have been deprecated in favor of `numerator` and `denominator` respectively ([#19233],[#19246]). * `delete!(ENV::EnvHash, k::AbstractString, def)` has been deprecated in favor of `pop!(ENV, k, def)`. Be aware that `pop!` returns `k` or `def`, whereas `delete!` @@ -641,6 +641,7 @@ Command-line option changes [#19157]: https://github.com/JuliaLang/julia/issues/19157 [#19233]: https://github.com/JuliaLang/julia/issues/19233 [#19239]: https://github.com/JuliaLang/julia/issues/19239 +[#19246]: https://github.com/JuliaLang/julia/issues/19246 [#19259]: https://github.com/JuliaLang/julia/issues/19259 [#19288]: https://github.com/JuliaLang/julia/issues/19288 [#19305]: https://github.com/JuliaLang/julia/issues/19305 From 6ba63e565e9a486ef911c19185fee42f6344b782 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Thu, 18 May 2017 12:37:38 -0700 Subject: [PATCH 0827/1534] Add NEWS.md entry for arithtype deprecation (#18218). (#21942) --- NEWS.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/NEWS.md b/NEWS.md index 7b6831db13398..5480fd65f7404 100644 --- a/NEWS.md +++ b/NEWS.md @@ -565,6 +565,10 @@ Deprecated or removed * `convert` methods from `Diagonal` and `Bidiagonal` to subtypes of `AbstractTriangular` have been deprecated ([#17723]). + * `Base.LinAlg.arithtype` has been deprecated. If you were using `arithtype` within a + `promote_op` call, instead use `promote_op(Base.LinAlg.matprod, Ts...)`. Otherwise, + consider defining equivalent functionality locally ([#18218]). + * Special characters (`#{}()[]<>|&*?~;`) should now be quoted in commands. For example, ``` `export FOO=1\;` ``` should replace ``` `export FOO=1;` ``` and ``` `cd $dir '&&' $thingie` ``` should replace ``` `cd $dir && $thingie` ``` ([#19786]). @@ -615,6 +619,7 @@ Command-line option changes [#18012]: https://github.com/JuliaLang/julia/issues/18012 [#18050]: https://github.com/JuliaLang/julia/issues/18050 [#18159]: https://github.com/JuliaLang/julia/issues/18159 +[#18218]: https://github.com/JuliaLang/julia/issues/18218 [#18251]: https://github.com/JuliaLang/julia/issues/18251 [#18330]: https://github.com/JuliaLang/julia/issues/18330 [#18339]: https://github.com/JuliaLang/julia/issues/18339 From cc7bd6cbb7a2560628570fc77a5000d10048f3af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Thu, 18 May 2017 23:36:40 +0200 Subject: [PATCH 0828/1534] Add gvim support in edit (#21873) Currently `gvim` is not recognized by `edit(path, line)`. I recommend to add it with option to run in background turned on. --- base/interactiveutil.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/interactiveutil.jl b/base/interactiveutil.jl index 8c949d1710706..5b959f063ea2a 100644 --- a/base/interactiveutil.jl +++ b/base/interactiveutil.jl @@ -40,7 +40,7 @@ function edit(path::AbstractString, line::Integer=0) end background = true line_unsupported = false - if startswith(name, "emacs") || name == "gedit" + if startswith(name, "emacs") || name == "gedit" || startswith(name, "gvim") cmd = line != 0 ? `$command +$line $path` : `$command $path` elseif startswith(name, "vim.") || name == "vi" || name == "vim" || name == "nvim" || name == "mvim" || name == "nano" cmd = line != 0 ? `$command +$line $path` : `$command $path` From 9f247886b117347ef59837f5e4354527e99362bf Mon Sep 17 00:00:00 2001 From: Felipe Noronha Date: Thu, 18 May 2017 19:33:42 -0300 Subject: [PATCH 0829/1534] Remove unnecessary at-async in parallel-computing docs (#21952) `remote_do` is already an async call. --- doc/src/manual/parallel-computing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/manual/parallel-computing.md b/doc/src/manual/parallel-computing.md index 35a509e98d6c8..0adb65bb63dbd 100644 --- a/doc/src/manual/parallel-computing.md +++ b/doc/src/manual/parallel-computing.md @@ -752,7 +752,7 @@ julia> n = 12; julia> @schedule make_jobs(n); # feed the jobs channel with "n" jobs julia> for p in workers() # start tasks on the workers to process requests in parallel - @async remote_do(do_work, p, jobs, results) + remote_do(do_work, p, jobs, results) end julia> @elapsed while n > 0 # print out results From cd4b4b82a33a2c52a765190ba2fc7ed1a0d1151b Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Thu, 18 May 2017 15:59:58 -0700 Subject: [PATCH 0830/1534] Implement, test, doc git descriptions for things (#20885) * Add GitDescribe functions and tests * Add docs for new functions * "git-describe" => "git describe" * Fix hypen --- base/libgit2/consts.jl | 5 +++ base/libgit2/repository.jl | 63 +++++++++++++++++++++++++++++++++++++ base/libgit2/types.jl | 64 +++++++++++++++++++++++++++----------- test/libgit2.jl | 10 +++++- 4 files changed, 123 insertions(+), 19 deletions(-) diff --git a/base/libgit2/consts.jl b/base/libgit2/consts.jl index b5aa73c41f9eb..bfcdfb822c000 100644 --- a/base/libgit2/consts.jl +++ b/base/libgit2/consts.jl @@ -201,6 +201,11 @@ module Consts const CLONE_NO_LOCAL = Cint(2) const CLONE_LOCAL_NO_LINKS = Cint(3) + # describe + const DESCRIBE_DEFAULT = Cuint(0) + const DESCRIBE_TAGS = Cuint(1 << 0) + const DESCRIBE_ALL = Cuint(1 << 1) + # status const STATUS_CURRENT = Cuint(0) const STATUS_INDEX_NEW = Cuint(1 << 0) diff --git a/base/libgit2/repository.jl b/base/libgit2/repository.jl index 020d0ffbeadf2..92834f0d9311e 100644 --- a/base/libgit2/repository.jl +++ b/base/libgit2/repository.jl @@ -227,6 +227,69 @@ function peel(::Type{T}, obj::GitObject) where T<:GitObject end peel(obj::GitObject) = peel(GitObject, obj) +""" + LibGit2.GitDescribeResult(commitish::GitObject; kwarg...) + +Produce a `GitDescribeResult` of the `commitish` `GitObject`, which +contains detailed information about it based on the keyword argument: + + * `options::DescribeOptions=DescribeOptions()` + +Equivalent to `git describe `. +""" +function GitDescribeResult(commitish::GitObject; + options::DescribeOptions=DescribeOptions()) + result_ptr_ptr = Ref{Ptr{Void}}(C_NULL) + @check ccall((:git_describe_commit, :libgit2), Cint, + (Ptr{Ptr{Void}}, Ptr{Void}, Ptr{DescribeOptions}), + result_ptr_ptr, commitish.ptr, Ref(options)) + return GitDescribeResult(commitish.owner, result_ptr_ptr[]) +end + +""" + LibGit2.GitDescribeResult(repo::GitRepo; kwarg...) + +Produce a `GitDescribeResult` of the repository `repo`'s working directory, +which can include all the commits and tags (or, for instance, HEAD only). +The `GitDescribeResult` contains detailed information about the workdir based +on the keyword argument: + + * `options::DescribeOptions=DescribeOptions()` + +Equivalent to `git describe`. +""" +function GitDescribeResult(repo::GitRepo; options::DescribeOptions=DescribeOptions()) + result_ptr_ptr = Ref{Ptr{Void}}(C_NULL) + @check ccall((:git_describe_workdir, :libgit2), Cint, + (Ptr{Ptr{Void}}, Ptr{Void}, Ptr{DescribeOptions}), + result_ptr_ptr, repo.ptr, Ref(options)) + return GitDescribeResult(repo, result_ptr_ptr[]) +end + +""" + LibGit2.format(result::GitDescribeResult; kwarg...) -> String + +Produce a formatted string based on a `GitDescribeResult`. +Formatting options are controlled by the keyword argument: + + * `options::DescribeFormatOptions=DescribeFormatOptions()` +""" +function format(result::GitDescribeResult; options::DescribeFormatOptions=DescribeFormatOptions()) + buf_ref = Ref(Buffer()) + @check ccall((:git_describe_format, :libgit2), Cint, + (Ptr{Buffer}, Ptr{Void}, Ptr{DescribeFormatOptions}), + buf_ref, result.ptr, Ref(options)) + buf = buf_ref[] + str = unsafe_string(buf.ptr, buf.size) + free(buf_ref) + return str +end + +function Base.show(io::IO, result::GitDescribeResult) + fmt_desc = format(result) + println(io, "GitDescribeResult:") + println(io, fmt_desc) +end function checkout_tree(repo::GitRepo, obj::GitObject; options::CheckoutOptions = CheckoutOptions()) diff --git a/base/libgit2/types.jl b/base/libgit2/types.jl index 89cb7e16a34ef..e1a2690041384 100644 --- a/base/libgit2/types.jl +++ b/base/libgit2/types.jl @@ -270,6 +270,33 @@ Matches the [`git_diff_options`](https://libgit2.github.com/libgit2/#HEAD/type/g new_prefix::Cstring end +""" + LibGit2.DescribeOptions + +Matches the [`git_describe_options`](https://libgit2.github.com/libgit2/#HEAD/type/git_describe_options) struct. +""" +@kwdef struct DescribeOptions + version::Cuint = 1 + max_candidates_tags::Cuint = 10 + describe_strategy::Cuint = Consts.DESCRIBE_DEFAULT + + pattern::Cstring + only_follow_first_parent::Cint + show_commit_oid_as_fallback::Cint +end + +""" + LibGit2.DescribeFormatOptions + +Matches the [`git_describe_format_options`](https://libgit2.github.com/libgit2/#HEAD/type/git_describe_format_options) struct. +""" +@kwdef struct DescribeFormatOptions + version::Cuint = 1 + abbreviated_size::Cuint = 7 + always_use_long_format::Cint + dirty_suffix::Cstring +end + """ LibGit2.DiffFile @@ -496,24 +523,25 @@ Base.isempty(obj::AbstractGitObject) = (obj.ptr == C_NULL) abstract type GitObject <: AbstractGitObject end for (typ, owntyp, sup, cname) in [ - (:GitRepo, nothing, :AbstractGitObject, :git_repository), - (:GitConfig, :(Nullable{GitRepo}), :AbstractGitObject, :git_config), - (:GitIndex, :(Nullable{GitRepo}), :AbstractGitObject, :git_index), - (:GitRemote, :GitRepo, :AbstractGitObject, :git_remote), - (:GitRevWalker, :GitRepo, :AbstractGitObject, :git_revwalk), - (:GitReference, :GitRepo, :AbstractGitObject, :git_reference), - (:GitDiff, :GitRepo, :AbstractGitObject, :git_diff), - (:GitDiffStats, :GitRepo, :AbstractGitObject, :git_diff_stats), - (:GitAnnotated, :GitRepo, :AbstractGitObject, :git_annotated_commit), - (:GitRebase, :GitRepo, :AbstractGitObject, :git_rebase), - (:GitStatus, :GitRepo, :AbstractGitObject, :git_status_list), - (:GitBranchIter, :GitRepo, :AbstractGitObject, :git_branch_iterator), - (:GitUnknownObject, :GitRepo, :GitObject, :git_object), - (:GitCommit, :GitRepo, :GitObject, :git_commit), - (:GitBlob, :GitRepo, :GitObject, :git_blob), - (:GitTree, :GitRepo, :GitObject, :git_tree), - (:GitTag, :GitRepo, :GitObject, :git_tag), - (:GitTreeEntry, :GitTree, :AbstractGitObject, :git_tree_entry), + (:GitRepo, nothing, :AbstractGitObject, :git_repository), + (:GitConfig, :(Nullable{GitRepo}), :AbstractGitObject, :git_config), + (:GitIndex, :(Nullable{GitRepo}), :AbstractGitObject, :git_index), + (:GitRemote, :GitRepo, :AbstractGitObject, :git_remote), + (:GitRevWalker, :GitRepo, :AbstractGitObject, :git_revwalk), + (:GitReference, :GitRepo, :AbstractGitObject, :git_reference), + (:GitDescribeResult, :GitRepo, :AbstractGitObject, :git_describe_result), + (:GitDiff, :GitRepo, :AbstractGitObject, :git_diff), + (:GitDiffStats, :GitRepo, :AbstractGitObject, :git_diff_stats), + (:GitAnnotated, :GitRepo, :AbstractGitObject, :git_annotated_commit), + (:GitRebase, :GitRepo, :AbstractGitObject, :git_rebase), + (:GitStatus, :GitRepo, :AbstractGitObject, :git_status_list), + (:GitBranchIter, :GitRepo, :AbstractGitObject, :git_branch_iterator), + (:GitUnknownObject, :GitRepo, :GitObject, :git_object), + (:GitCommit, :GitRepo, :GitObject, :git_commit), + (:GitBlob, :GitRepo, :GitObject, :git_blob), + (:GitTree, :GitRepo, :GitObject, :git_tree), + (:GitTag, :GitRepo, :GitObject, :git_tag), + (:GitTreeEntry, :GitTree, :AbstractGitObject, :git_tree_entry), ] if owntyp === nothing diff --git a/test/libgit2.jl b/test/libgit2.jl index fcf5827c14867..f179825ae3fda 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -440,7 +440,6 @@ mktempdir() do dir @test contains(showstr[4], "SHA:") @test showstr[5] == "Message:" @test showstr[6] == commit_msg1 - @test LibGit2.revcount(repo, string(commit_oid1), string(commit_oid3)) == (-1,0) finally close(cmt) @@ -560,6 +559,15 @@ mktempdir() do dir @test length(tags) == 1 @test tag2 ∈ tags @test tag1 ∉ tags + + description = LibGit2.GitDescribeResult(repo) + fmtted_description = LibGit2.format(description) + @test sprint(show, description) == "GitDescribeResult:\n$fmtted_description\n" + @test fmtted_description == "tag2" + description = LibGit2.GitDescribeResult(LibGit2.GitObject(repo, "HEAD")) + fmtted_description = LibGit2.format(description) + @test sprint(show, description) == "GitDescribeResult:\n$fmtted_description\n" + @test fmtted_description == "tag2" finally close(repo) end From 31f798eb820007906783d30824e865c87ebecf09 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Fri, 19 May 2017 03:52:29 +0200 Subject: [PATCH 0831/1534] add pop!(::Dict) to return a key=>value pair (#21947) --- base/dict.jl | 9 +++++++++ base/docs/helpdb/Base.jl | 25 ++++++++++++++++--------- base/set.jl | 10 +++++++++- test/dict.jl | 9 +++++++++ test/sets.jl | 1 + 5 files changed, 44 insertions(+), 10 deletions(-) diff --git a/base/dict.jl b/base/dict.jl index cd41a725d669f..493340836405c 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -544,6 +544,15 @@ function pop!(h::Dict, key, default) return index > 0 ? _pop!(h, index) : default end +function pop!(h::Dict) + isempty(h) && throw(ArgumentError("dict must be non-empty")) + idx = start(h) + key = h.keys[idx] + val = h.vals[idx] + _delete!(h, idx) + key => val +end + function _delete!(h::Dict, index) h.slots[index] = 0x2 ccall(:jl_arrayunset, Void, (Any, UInt), h.keys, index-1) diff --git a/base/docs/helpdb/Base.jl b/base/docs/helpdb/Base.jl index 5445e1df462c6..a3f96845c4261 100644 --- a/base/docs/helpdb/Base.jl +++ b/base/docs/helpdb/Base.jl @@ -2368,28 +2368,35 @@ pop!(collection,key,?) """ pop!(collection) -> item -Remove the last item in `collection` and return it. +Remove an item in `collection` and return it. If `collection` is an +ordered container, the last item is returned. ```jldoctest -julia> A=[1, 2, 3, 4, 5, 6] +julia> A=[1, 2, 3] 6-element Array{Int64,1}: 1 2 3 - 4 - 5 - 6 julia> pop!(A) -6 +3 julia> A 5-element Array{Int64,1}: 1 2 - 3 - 4 - 5 + +julia> S = Set([1, 2]) +Set([2, 1]) + +julia> pop!(S) +2 + +julia> S +Set([1]) + +julia> pop!(Dict(1=>2)) +1=>2 ``` """ pop!(collection) diff --git a/base/set.jl b/base/set.jl index 411c23e01db72..38665b5f55d94 100644 --- a/base/set.jl +++ b/base/set.jl @@ -35,7 +35,15 @@ in(x, s::Set) = haskey(s.dict, x) push!(s::Set, x) = (s.dict[x] = nothing; s) pop!(s::Set, x) = (pop!(s.dict, x); x) pop!(s::Set, x, deflt) = x in s ? pop!(s, x) : deflt -pop!(s::Set) = (idx = start(s.dict); val = s.dict.keys[idx]; _delete!(s.dict, idx); val) + +function pop!(s::Set) + isempty(s) && throw(ArgumentError("set must be non-empty")) + idx = start(s.dict) + val = s.dict.keys[idx] + _delete!(s.dict, idx) + val +end + delete!(s::Set, x) = (delete!(s.dict, x); s) copy(s::Set) = union!(similar(s), s) diff --git a/test/dict.jl b/test/dict.jl index 1ac24f0bb33b4..859ba16f69aa2 100644 --- a/test/dict.jl +++ b/test/dict.jl @@ -718,3 +718,12 @@ end @test 'b' ∈ key_str @test 'c' ∈ key_str end + +@testset "Dict pop!" begin + d = Dict(1=>2, 3=>4) + @test pop!(d, 1) == 2 + @test_throws KeyError pop!(d, 1) + @test pop!(d, 1, 0) == 0 + @test pop!(d) == (3=>4) + @test_throws ArgumentError pop!(d) +end diff --git a/test/sets.jl b/test/sets.jl index b066d6d12be79..f8cc3fc28edd7 100644 --- a/test/sets.jl +++ b/test/sets.jl @@ -78,6 +78,7 @@ push!(s,1); push!(s,2); push!(s,3) @test pop!(s) == 3 @test length(s) == 0 @test isempty(s) +@test_throws ArgumentError pop!(s) # copy data_in = (1,2,9,8,4) From 83e01097f4e89a166ce715275e9d84bec921af11 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Fri, 19 May 2017 11:30:18 +0200 Subject: [PATCH 0832/1534] fix incorrect doctest from #21947 --- base/docs/helpdb/Base.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/docs/helpdb/Base.jl b/base/docs/helpdb/Base.jl index a3f96845c4261..622a02c1e3152 100644 --- a/base/docs/helpdb/Base.jl +++ b/base/docs/helpdb/Base.jl @@ -2373,7 +2373,7 @@ ordered container, the last item is returned. ```jldoctest julia> A=[1, 2, 3] -6-element Array{Int64,1}: +3-element Array{Int64,1}: 1 2 3 @@ -2382,7 +2382,7 @@ julia> pop!(A) 3 julia> A -5-element Array{Int64,1}: +2-element Array{Int64,1}: 1 2 From 9fefc951003cf73ebdabe4b4572817cb586adfad Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Sun, 30 Apr 2017 17:21:00 +0200 Subject: [PATCH 0833/1534] group ccall'ed MPZ library functions in a module --- base/gmp.jl | 342 ++++++++++++++++++++++++------------------------- base/printf.jl | 6 +- base/random.jl | 18 +-- 3 files changed, 172 insertions(+), 194 deletions(-) diff --git a/base/gmp.jl b/base/gmp.jl index 57e68c62a001e..9f6277f892e63 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -44,16 +44,12 @@ mutable struct BigInt <: Integer d::Ptr{Limb} function BigInt() b = new(zero(Cint), zero(Cint), C_NULL) - ccall((:__gmpz_init,:libgmp), Void, (Ptr{BigInt},), &b) + MPZ.init!(b) finalizer(b, cglobal((:__gmpz_clear, :libgmp))) return b end end -const ZERO = BigInt() -const ONE = BigInt() -const _ONE = Limb[1] - function __init__() try if gmp_version().major != GMP_VERSION.major || gmp_bits_per_limb() != GMP_BITS_PER_LIMB @@ -76,6 +72,122 @@ function __init__() end end + +module MPZ +# wrapping of libgmp functions +# - "output parameters" are labeled x, y, z, and are returned when appropriate +# - constant input parameters are labeled a, b, c +# - a method modifying its input has a "!" appendend to its name, according to Julia's conventions +# - some convenient methods are added (in addition to the pure MPZ ones), e.g. `add(a, b) = add!(BigInt(), a, b)` +# and `add!(x, a) = add!(x, x, a)`. +using Base.GMP: BigInt, Limb + +const mpz_t = Ptr{BigInt} +const bitcnt_t = Culong + +gmpz(op::Symbol) = (Symbol(:__gmpz_, op), :libgmp) + +init!(x::BigInt) = (ccall((:__gmpz_init, :libgmp), Void, (mpz_t,), &x); x) +init2!(x::BigInt, a) = (ccall((:__gmpz_init2, :libgmp), Void, (mpz_t, bitcnt_t), &x, a); x) + +sizeinbase(a::BigInt, b) = Int(ccall((:__gmpz_sizeinbase, :libgmp), Csize_t, (mpz_t, Cint), &a, b)) + +for op in (:add, :sub, :mul, :fdiv_q, :tdiv_q, :fdiv_r, :tdiv_r, :gcd, :lcm, :and, :ior, :xor) + op! = Symbol(op, :!) + @eval begin + $op!(x::BigInt, a::BigInt, b::BigInt) = (ccall($(gmpz(op)), Void, (mpz_t, mpz_t, mpz_t), &x, &a, &b); x) + $op(a::BigInt, b::BigInt) = $op!(BigInt(), a, b) + $op!(x::BigInt, b::BigInt) = $op!(x, x, b) + end +end + +invert!(x::BigInt, a::BigInt, b::BigInt) = + ccall((:__gmpz_invert, :libgmp), Cint, (mpz_t, mpz_t, mpz_t), &x, &a, &b) +invert(a::BigInt, b::BigInt) = invert!(BigInt(), a, b) +invert!(x::BigInt, b::BigInt) = invert!(x, x, b) + +for op in (:add_ui, :sub_ui, :mul_ui, :mul_2exp, :fdiv_q_2exp, :pow_ui, :bin_ui) + op! = Symbol(op, :!) + @eval begin + $op!(x::BigInt, a::BigInt, b) = (ccall($(gmpz(op)), Void, (mpz_t, mpz_t, Culong), &x, &a, b); x) + $op(a::BigInt, b) = $op!(BigInt(), a, b) + $op!(x::BigInt, b) = $op!(x, x, b) + end +end + +ui_sub!(x::BigInt, a, b::BigInt) = (ccall((:__gmpz_ui_sub, :libgmp), Void, (mpz_t, Culong, mpz_t), &x, a, &b); x) +ui_sub(a, b::BigInt) = ui_sub!(BigInt(), a, b) + +for op in (:scan1, :scan0) + @eval $op(a::BigInt, b) = Int(ccall($(gmpz(op)), Culong, (mpz_t, Culong), &a, b)) +end + +mul_si!(x::BigInt, a::BigInt, b) = (ccall((:__gmpz_mul_si, :libgmp), Void, (mpz_t, mpz_t, Clong), &x, &a, b); x) +mul_si(a::BigInt, b) = mul_si!(BigInt(), a, b) +mul_si!(x::BigInt, b) = mul_si!(x, x, b) + +for op in (:neg, :com, :sqrt, :set) + op! = Symbol(op, :!) + @eval begin + $op!(x::BigInt, a::BigInt) = (ccall($(gmpz(op)), Void, (mpz_t, mpz_t), &x, &a); x) + $op(a::BigInt) = $op!(BigInt(), a) + end + op == :set && continue # MPZ.set!(x) would make no sense + @eval $op!(x::BigInt) = $op!(x, x) +end + +for (op, T) in ((:fac_ui, Culong), (:set_ui, Culong), (:set_si, Clong), (:set_d, Cdouble)) + op! = Symbol(op, :!) + @eval begin + $op!(x::BigInt, a) = (ccall($(gmpz(op)), Void, (mpz_t, $T), &x, a); x) + $op(a) = $op!(BigInt(), a) + end +end + +popcount(a::BigInt) = ccall((:__gmpz_popcount, :libgmp), Culong, (mpz_t,), &a) % Int + +mpn_popcount(d::Ptr{Limb}, s::Integer) = ccall((:__gmpn_popcount, :libgmp), Culong, (Ptr{Limb}, Csize_t), d, s) % Int +mpn_popcount(a::BigInt) = mpn_popcount(a.d, abs(a.size)) + +function tdiv_qr!(x::BigInt, y::BigInt, a::BigInt, b::BigInt) + ccall((:__gmpz_tdiv_qr, :libgmp), Void, (mpz_t, mpz_t, mpz_t, mpz_t), &x, &y, &a, &b) + x, y +end +tdiv_qr(a::BigInt, b::BigInt) = tdiv_qr!(BigInt(), BigInt(), a, b) + +powm!(x::BigInt, a::BigInt, b::BigInt, c::BigInt) = + (ccall((:__gmpz_powm, :libgmp), Void, (mpz_t, mpz_t, mpz_t, mpz_t), &x, &a, &b, &c); x) +powm(a::BigInt, b::BigInt, c::BigInt) = powm!(BigInt(), a, b, c) +powm!(x::BigInt, b::BigInt, c::BigInt) = powm!(x, x, b, c) + +function gcdext!(x::BigInt, y::BigInt, z::BigInt, a::BigInt, b::BigInt) + ccall((:__gmpz_gcdext, :libgmp), Void, (mpz_t, mpz_t, mpz_t, mpz_t, mpz_t), + &x, &y, &z, &a, &b) + x, y, z +end +gcdext(a::BigInt, b::BigInt) = gcdext!(BigInt(), BigInt(), BigInt(), a, b) + +cmp(a::BigInt, b::BigInt) = ccall((:__gmpz_cmp, :libgmp), Cint, (mpz_t, mpz_t), &a, &b) % Int +cmp_si(a::BigInt, b) = ccall((:__gmpz_cmp_si, :libgmp), Cint, (mpz_t, Clong), &a, b) % Int +cmp_ui(a::BigInt, b) = ccall((:__gmpz_cmp_ui, :libgmp), Cint, (mpz_t, Culong), &a, b) % Int +cmp_d(a::BigInt, b) = ccall((:__gmpz_cmp_d, :libgmp), Cint, (mpz_t, Cdouble), &a, b) % Int + +get_str!(x, a, b::BigInt) = (ccall((:__gmpz_get_str,:libgmp), Ptr{Cchar}, (Ptr{Cchar}, Cint, mpz_t), x, a, &b); x) +set_str!(x::BigInt, a, b) = ccall((:__gmpz_set_str, :libgmp), Cint, (mpz_t, Ptr{UInt8}, Cint), &x, a, b) % Int +get_d(a::BigInt) = ccall((:__gmpz_get_d, :libgmp), Cdouble, (mpz_t,), &a) + +limbs_write!(x::BigInt, a) = ccall((:__gmpz_limbs_write, :libgmp), Ptr{Limb}, (mpz_t, Clong), &x, a) +limbs_finish!(x::BigInt, a) = ccall((:__gmpz_limbs_finish, :libgmp), Void, (mpz_t, Clong), &x, a) +import!(x::BigInt, a, b, c, d, e, f) = + ccall((:__gmpz_import, :libgmp), Void, (mpz_t, Csize_t, Cint, Csize_t, Cint, Csize_t, Ptr{Void}), + &x, a, b, c, d, e, f) + +end # module MPZ + +const ZERO = BigInt() +const ONE = BigInt() +const _ONE = Limb[1] + widen(::Type{Int128}) = BigInt widen(::Type{UInt128}) = BigInt widen(::Type{BigInt}) = BigInt @@ -103,9 +215,7 @@ function tryparse_internal(::Type{BigInt}, s::AbstractString, startpos::Int, end if Base.containsnul(bstr) err = -1 # embedded NUL char (not handled correctly by GMP) else - err = ccall((:__gmpz_set_str, :libgmp), - Int32, (Ptr{BigInt}, Ptr{UInt8}, Int32), - &z, pointer(bstr)+(i-start(bstr)), base) + err = MPZ.set_str!(z, pointer(bstr)+(i-start(bstr)), base) end if err != 0 raise && throw(ArgumentError("invalid BigInt: $(repr(bstr))")) @@ -114,25 +224,11 @@ function tryparse_internal(::Type{BigInt}, s::AbstractString, startpos::Int, end Nullable(flipsign!(z, sgn)) end -function convert(::Type{BigInt}, x::Union{Clong,Int32}) - z = BigInt() - ccall((:__gmpz_set_si, :libgmp), Void, (Ptr{BigInt}, Clong), &z, x) - return z -end -function convert(::Type{BigInt}, x::Union{Culong,UInt32}) - z = BigInt() - ccall((:__gmpz_set_ui, :libgmp), Void, (Ptr{BigInt}, Culong), &z, x) - return z -end - +convert(::Type{BigInt}, x::Union{Clong,Int32}) = MPZ.set_si(x) +convert(::Type{BigInt}, x::Union{Culong,UInt32}) = MPZ.set_ui(x) convert(::Type{BigInt}, x::Bool) = BigInt(UInt(x)) - -function unsafe_trunc(::Type{BigInt}, x::Union{Float32,Float64}) - z = BigInt() - ccall((:__gmpz_set_d, :libgmp), Void, (Ptr{BigInt}, Cdouble), &z, x) - return z -end +unsafe_trunc(::Type{BigInt}, x::Union{Float32,Float64}) = MPZ.set_d(x) function convert(::Type{BigInt}, x::Union{Float32,Float64}) isinteger(x) || throw(InexactError()) @@ -210,9 +306,7 @@ function convert(::Type{T}, x::BigInt) where T<:Signed end -function (::Type{Float64})(n::BigInt, ::RoundingMode{:ToZero}) - ccall((:__gmpz_get_d, :libgmp), Float64, (Ptr{BigInt},), &n) -end +(::Type{Float64})(n::BigInt, ::RoundingMode{:ToZero}) = MPZ.get_d(n) function (::Type{T})(n::BigInt, ::RoundingMode{:ToZero}) where T<:Union{Float16,Float32} T(Float64(n,RoundToZero),RoundToZero) @@ -264,11 +358,7 @@ for (fJ, fC) in ((:+, :add), (:-,:sub), (:*, :mul), (:gcd, :gcd), (:lcm, :lcm), (:&, :and), (:|, :ior), (:xor, :xor)) @eval begin - function ($fJ)(x::BigInt, y::BigInt) - z = BigInt() - ccall(($(string(:__gmpz_,fC)), :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}), &z, &x, &y) - return z - end + ($fJ)(x::BigInt, y::BigInt) = MPZ.$fC(x, y) end end @@ -280,14 +370,14 @@ function invmod(x::BigInt, y::BigInt) if ya == 1 return z end - if (y==0 || ccall((:__gmpz_invert, :libgmp), Cint, (Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}), &z, &x, &ya) == 0) + if (y==0 || MPZ.invert!(z, x, ya) == 0) throw(DomainError()) end # GMP always returns a positive inverse; we instead want to # normalize such that div(z, y) == 0, i.e. we want a negative z # when y is negative. if y < 0 - z = z + y + MPZ.add!(z, y) end # The postcondition is: mod(z * x, y) == mod(big(1), m) && div(z, y) == 0 return z @@ -295,146 +385,69 @@ end # More efficient commutative operations for (fJ, fC) in ((:+, :add), (:*, :mul), (:&, :and), (:|, :ior), (:xor, :xor)) + fC! = Symbol(fC, :!) @eval begin - function ($fJ)(a::BigInt, b::BigInt, c::BigInt) - z = BigInt() - ccall(($(string(:__gmpz_,fC)), :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}), &z, &a, &b) - ccall(($(string(:__gmpz_,fC)), :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}), &z, &z, &c) - return z - end - function ($fJ)(a::BigInt, b::BigInt, c::BigInt, d::BigInt) - z = BigInt() - ccall(($(string(:__gmpz_,fC)), :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}), &z, &a, &b) - ccall(($(string(:__gmpz_,fC)), :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}), &z, &z, &c) - ccall(($(string(:__gmpz_,fC)), :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}), &z, &z, &d) - return z - end - function ($fJ)(a::BigInt, b::BigInt, c::BigInt, d::BigInt, e::BigInt) - z = BigInt() - ccall(($(string(:__gmpz_,fC)), :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}), &z, &a, &b) - ccall(($(string(:__gmpz_,fC)), :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}), &z, &z, &c) - ccall(($(string(:__gmpz_,fC)), :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}), &z, &z, &d) - ccall(($(string(:__gmpz_,fC)), :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}), &z, &z, &e) - return z - end + ($fJ)(a::BigInt, b::BigInt, c::BigInt) = MPZ.$fC!(MPZ.$fC(a, b), c) + ($fJ)(a::BigInt, b::BigInt, c::BigInt, d::BigInt) = MPZ.$fC!(MPZ.$fC!(MPZ.$fC(a, b), c), d) + ($fJ)(a::BigInt, b::BigInt, c::BigInt, d::BigInt, e::BigInt) = + MPZ.$fC!(MPZ.$fC!(MPZ.$fC!(MPZ.$fC(a, b), c), d), e) end end # Basic arithmetic without promotion -function +(x::BigInt, c::CulongMax) - z = BigInt() - ccall((:__gmpz_add_ui, :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Culong), &z, &x, c) - return z -end ++(x::BigInt, c::CulongMax) = MPZ.add_ui(x, c) +(c::CulongMax, x::BigInt) = x + c -function -(x::BigInt, c::CulongMax) - z = BigInt() - ccall((:__gmpz_sub_ui, :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Culong), &z, &x, c) - return z -end -function -(c::CulongMax, x::BigInt) - z = BigInt() - ccall((:__gmpz_ui_sub, :libgmp), Void, (Ptr{BigInt}, Culong, Ptr{BigInt}), &z, c, &x) - return z -end +-(x::BigInt, c::CulongMax) = MPZ.sub_ui(x, c) +-(c::CulongMax, x::BigInt) = MPZ.ui_sub(c, x) + +(x::BigInt, c::ClongMax) = c < 0 ? -(x, -(c % Culong)) : x + convert(Culong, c) +(c::ClongMax, x::BigInt) = c < 0 ? -(x, -(c % Culong)) : x + convert(Culong, c) -(x::BigInt, c::ClongMax) = c < 0 ? +(x, -(c % Culong)) : -(x, convert(Culong, c)) -(c::ClongMax, x::BigInt) = c < 0 ? -(x + -(c % Culong)) : -(convert(Culong, c), x) -function *(x::BigInt, c::CulongMax) - z = BigInt() - ccall((:__gmpz_mul_ui, :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Culong), &z, &x, c) - return z -end +*(x::BigInt, c::CulongMax) = MPZ.mul_ui(x, c) *(c::CulongMax, x::BigInt) = x * c -function *(x::BigInt, c::ClongMax) - z = BigInt() - ccall((:__gmpz_mul_si, :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Clong), &z, &x, c) - return z -end +*(x::BigInt, c::ClongMax) = MPZ.mul_si(x, c) *(c::ClongMax, x::BigInt) = x * c /(x::BigInt, y::Union{ClongMax,CulongMax}) = float(x)/y /(x::Union{ClongMax,CulongMax}, y::BigInt) = x/float(y) # unary ops -for (fJ, fC) in ((:-, :neg), (:~, :com)) - @eval begin - function ($fJ)(x::BigInt) - z = BigInt() - ccall(($(string(:__gmpz_,fC)), :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}), &z, &x) - return z - end - end -end - -function <<(x::BigInt, c::UInt) - c == 0 && return x - z = BigInt() - ccall((:__gmpz_mul_2exp, :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Culong), &z, &x, c) - return z -end - -function >>(x::BigInt, c::UInt) - c == 0 && return x - z = BigInt() - ccall((:__gmpz_fdiv_q_2exp, :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Culong), &z, &x, c) - return z -end +(-)(x::BigInt) = MPZ.neg(x) +(~)(x::BigInt) = MPZ.com(x) +<<(x::BigInt, c::UInt) = c == 0 ? x : MPZ.mul_2exp(x, c) +>>(x::BigInt, c::UInt) = c == 0 ? x : MPZ.fdiv_q_2exp(x, c) >>>(x::BigInt, c::UInt) = x >> c +trailing_zeros(x::BigInt) = MPZ.scan1(x, 0) +trailing_ones(x::BigInt) = MPZ.scan0(x, 0) -trailing_zeros(x::BigInt) = Int(ccall((:__gmpz_scan1, :libgmp), Culong, (Ptr{BigInt}, Culong), &x, 0)) -trailing_ones(x::BigInt) = Int(ccall((:__gmpz_scan0, :libgmp), Culong, (Ptr{BigInt}, Culong), &x, 0)) - -count_ones(x::BigInt) = Int(ccall((:__gmpz_popcount, :libgmp), Culong, (Ptr{BigInt},), &x)) +count_ones(x::BigInt) = MPZ.popcount(x) """ count_ones_abs(x::BigInt) Number of ones in the binary representation of abs(x). """ -count_ones_abs(x::BigInt) = iszero(x) ? 0 : ccall((:__gmpn_popcount, :libgmp), Culong, (Ptr{Limb}, Csize_t), x.d, abs(x.size)) % Int +count_ones_abs(x::BigInt) = iszero(x) ? 0 : MPZ.mpn_popcount(x) -function divrem(x::BigInt, y::BigInt) - z1 = BigInt() - z2 = BigInt() - ccall((:__gmpz_tdiv_qr, :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}), &z1, &z2, &x, &y) - z1, z2 -end +divrem(x::BigInt, y::BigInt) = MPZ.tdiv_qr(x, y) -function cmp(x::BigInt, y::BigInt) - ccall((:__gmpz_cmp, :libgmp), Int32, (Ptr{BigInt}, Ptr{BigInt}), &x, &y) -end -function cmp(x::BigInt, y::ClongMax) - ccall((:__gmpz_cmp_si, :libgmp), Int32, (Ptr{BigInt}, Clong), &x, y) -end -function cmp(x::BigInt, y::CulongMax) - ccall((:__gmpz_cmp_ui, :libgmp), Int32, (Ptr{BigInt}, Culong), &x, y) -end -cmp(x::BigInt, y::Integer) = cmp(x,big(y)) -cmp(x::Integer, y::BigInt) = -cmp(y,x) +cmp(x::BigInt, y::BigInt) = MPZ.cmp(x, y) +cmp(x::BigInt, y::ClongMax) = MPZ.cmp_si(x, y) +cmp(x::BigInt, y::CulongMax) = MPZ.cmp_ui(x, y) +cmp(x::BigInt, y::Integer) = cmp(x, big(y)) +cmp(x::Integer, y::BigInt) = -cmp(y, x) -function cmp(x::BigInt, y::CdoubleMax) - isnan(y) && throw(DomainError()) - ccall((:__gmpz_cmp_d, :libgmp), Int32, (Ptr{BigInt}, Cdouble), &x, y) -end -cmp(x::CdoubleMax, y::BigInt) = -cmp(y,x) +cmp(x::BigInt, y::CdoubleMax) = isnan(y) ? throw(DomainError()) : MPZ.cmp_d(x, y) +cmp(x::CdoubleMax, y::BigInt) = -cmp(y, x) -function isqrt(x::BigInt) - z = BigInt() - ccall((:__gmpz_sqrt, :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}), &z, &x) - return z -end +isqrt(x::BigInt) = MPZ.sqrt(x) -function ^(x::BigInt, y::Culong) - z = BigInt() - ccall((:__gmpz_pow_ui, :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Culong), &z, &x, y) - return z -end +^(x::BigInt, y::Culong) = MPZ.pow_ui(x, y) function bigint_pow(x::BigInt, y::Integer) if y<0; throw(DomainError()); end @@ -463,11 +476,8 @@ end ^(x::Bool , y::BigInt ) = Base.power_by_squaring(x, y) function powermod(x::BigInt, p::BigInt, m::BigInt) - r = BigInt() - ccall((:__gmpz_powm, :libgmp), Void, - (Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}), - &r, &x, &p, &m) - return m < 0 && r > 0 ? r + m : r # choose sign conistent with mod(x^p, m) + r = MPZ.powm(x, p, m) + return m < 0 && r > 0 ? MPZ.add!(r, m) : r # choose sign conistent with mod(x^p, m) end powermod(x::Integer, p::Integer, m::BigInt) = powermod(big(x), big(p), m) @@ -478,12 +488,7 @@ function gcdx(a::BigInt, b::BigInt) # we don't return the globals ONE and ZERO in case the user wants to # mutate the result end - g = BigInt() - s = BigInt() - t = BigInt() - ccall((:__gmpz_gcdext, :libgmp), Void, - (Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}), - &g, &s, &t, &a, &b) + g, s, t = MPZ.gcdext(a, b) if t == 0 # work around a difference in some versions of GMP if a == b @@ -495,28 +500,11 @@ function gcdx(a::BigInt, b::BigInt) g, s, t end -function sum(arr::AbstractArray{BigInt}) - n = BigInt(0) - for i in arr - ccall((:__gmpz_add, :libgmp), Void, - (Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}), - &n, &n, &i) - end - return n -end +sum(arr::AbstractArray{BigInt}) = foldl(MPZ.add!, BigInt(0), arr) -function factorial(x::BigInt) - isneg(x) && return BigInt(0) - z = BigInt() - ccall((:__gmpz_fac_ui, :libgmp), Void, (Ptr{BigInt}, Culong), &z, x) - return z -end +factorial(x::BigInt) = isneg(x) ? BigInt(0) : MPZ.fac_ui(x) -function binomial(n::BigInt, k::UInt) - z = BigInt() - ccall((:__gmpz_bin_ui, :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Culong), &z, &n, k) - return z -end +binomial(n::BigInt, k::UInt) = MPZ.bin_ui(n, k) binomial(n::BigInt, k::Integer) = k < 0 ? BigInt(0) : binomial(n, UInt(k)) ==(x::BigInt, y::BigInt) = cmp(x,y) == 0 @@ -562,8 +550,7 @@ function base(b::Integer, n::BigInt) 2 <= b <= 62 || throw(ArgumentError("base must be 2 ≤ base ≤ 62, got $b")) nd = ndigits(n, b) str = Base._string_n(n < 0 ? nd+1 : nd) - ccall((:__gmpz_get_str,:libgmp), Ptr{UInt8}, (Ptr{UInt8}, Cint, Ptr{BigInt}), str, b, &n) - return str + MPZ.get_str!(str, b, n) end function base(b::Integer, n::BigInt, pad::Integer) @@ -585,11 +572,11 @@ function ndigits0zpb(x::BigInt, b::Integer) b < 2 && throw(DomainError()) x.size == 0 && return 0 # for consistency with other ndigits0z methods if ispow2(b) && 2 <= b <= 62 # GMP assumes b is in this range - Int(ccall((:__gmpz_sizeinbase,:libgmp), Csize_t, (Ptr{BigInt}, Cint), &x, b)) + MPZ.sizeinbase(x, b) else # non-base 2 mpz_sizeinbase might return an answer 1 too big # use property that log(b, x) < ndigits(x, b) <= log(b, x) + 1 - n = Int(ccall((:__gmpz_sizeinbase,:libgmp), Csize_t, (Ptr{BigInt}, Cint), &x, 2)) + n = MPZ.sizeinbase(x, 2) lb = log2(b) # assumed accurate to <1ulp (true for openlibm) q,r = divrem(n,lb) iq = Int(q) @@ -627,8 +614,7 @@ function Base.deepcopy_internal(x::BigInt, stackdict::ObjectIdDict) if haskey(stackdict, x) return stackdict[x] end - y = BigInt() - ccall((:__gmpz_set,:libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}), &y, &x) + y = MPZ.set(x) stackdict[x] = y return y end diff --git a/base/printf.jl b/base/printf.jl index c5df8f402b0b0..48ead94958f59 100644 --- a/base/printf.jl +++ b/base/printf.jl @@ -881,8 +881,7 @@ function decode(b::Int, x::BigInt) pt = Base.ndigits(x, abs(b)) length(DIGITS) < pt+1 && resize!(DIGITS, pt+1) neg && (x.size = -x.size) - ccall((:__gmpz_get_str, :libgmp), Cstring, - (Ptr{UInt8}, Cint, Ptr{BigInt}), DIGITS, b, &x) + GMP.MPZ.get_str!(DIGITS, b, x) neg && (x.size = -x.size) return Int32(pt), Int32(pt), neg end @@ -901,8 +900,7 @@ function decode_0ct(x::BigInt) length(DIGITS) < pt+1 && resize!(DIGITS, pt+1) neg && (x.size = -x.size) p = convert(Ptr{UInt8}, DIGITS) + 1 - ccall((:__gmpz_get_str, :libgmp), Cstring, - (Ptr{UInt8}, Cint, Ptr{BigInt}), p, 8, &x) + GMP.MPZ.get_str!(p, 8, x) neg && (x.size = -x.size) return neg, Int32(pt), Int32(pt) end diff --git a/base/random.jl b/base/random.jl index 44a1e9dbd42d1..f4b86f3d353ab 100644 --- a/base/random.jl +++ b/base/random.jl @@ -3,7 +3,7 @@ module Random using Base.dSFMT -using Base.GMP: GMP_VERSION, Limb +using Base.GMP: GMP_VERSION, Limb, MPZ import Base: copymutable, copy, copy!, == export srand, @@ -613,15 +613,13 @@ if GMP_VERSION.major >= 6 x = BigInt() while true # note: on CRAY computers, the second argument may be of type Cint (48 bits) and not Clong - xd = ccall((:__gmpz_limbs_write, :libgmp), Ptr{Limb}, (Ptr{BigInt}, Clong), &x, g.nlimbs) + xd = MPZ.limbs_write!(x, g.nlimbs) limbs = unsafe_wrap(Array, xd, g.nlimbs) rand!(rng, limbs) limbs[end] &= g.mask - ccall((:__gmpz_limbs_finish, :libgmp), Void, (Ptr{BigInt}, Clong), &x, g.nlimbs) - x <= g.m && break + MPZ.limbs_finish!(x, g.nlimbs) + x <= g.m && return MPZ.add!(x, g.a) end - ccall((:__gmpz_add, :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}), &x, &x, &g.a) - return x end else function rand(rng::AbstractRNG, g::RangeGeneratorBigInt) @@ -629,13 +627,9 @@ else while true rand!(rng, g.limbs) g.limbs[end] &= g.mask - ccall((:__gmpz_import, :libgmp), Void, - (Ptr{BigInt}, Csize_t, Cint, Csize_t, Cint, Csize_t, Ptr{Limb}), - &x, length(g.limbs), -1, sizeof(Limb), 0, 0, g.limbs) - x <= g.m && break + MPZ.import!(x, length(g.limbs), -1, sizeof(Limb), 0, 0, g.limbs) + x <= g.m && return MPZ.add!(x, g.a) end - ccall((:__gmpz_add, :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}), &x, &x, &g.a) - return x end end From 0663c4fe3d547587bafbdc51abd6a1b98a5ea6e8 Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Fri, 19 May 2017 10:33:53 -0400 Subject: [PATCH 0834/1534] Add specialized findin version for sorted collections (#21934) --- base/array.jl | 50 +++++++++++++++++++++++++++++++++++++++++++----- test/arrayops.jl | 9 +++++++++ 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/base/array.jl b/base/array.jl index c384ee3db721a..e5dea7bc703b8 100644 --- a/base/array.jl +++ b/base/array.jl @@ -1725,6 +1725,47 @@ function indexin(a::AbstractArray, b::AbstractArray) [get(bdict, i, 0) for i in a] end +function _findin(a, b) + ind = Int[] + bset = Set(b) + @inbounds for (i,ai) in enumerate(a) + ai in bset && push!(ind, i) + end + ind +end + +function _sortedfindin(v, w) + viter, witer = eachindex(v), eachindex(w) + out = eltype(viter)[] + i, j = start(viter), start(witer) + if done(viter, i) || done(witer, j) + return out + end + viteri, i = next(viter, i) + witerj, j = next(witer, j) + @inbounds begin + vi, wj = v[viteri], w[witerj] + while !(done(viter, i) || done(witer, j)) + if vi < wj + viteri, i = next(viter, i) + vi = v[viteri] + elseif vi > wj + witerj, j = next(witer, j) + wj = w[witerj] + else + push!(out, viteri) + viteri, i = next(viter, i) + witerj, j = next(witer, j) + vi, wj = v[viteri], w[witerj] + end + end + if vi == wj + push!(out, viteri) + end + end + return out +end + """ findin(a, b) @@ -1751,12 +1792,11 @@ julia> findin(a,b) # 10 is the only common element ``` """ function findin(a, b) - ind = Array{Int,1}(0) - bset = Set(b) - @inbounds for (i,ai) in enumerate(a) - ai in bset && push!(ind, i) + if issorted(a, Sort.Forward) && issorted(b, Sort.Forward) + return _sortedfindin(a, b) + else + return _findin(a, b) end - ind end # Copying subregions diff --git a/test/arrayops.jl b/test/arrayops.jl index c6851c018f04d..ca922eba69da2 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -263,6 +263,15 @@ end b = [4, 6, 2, -7, 1] ind = findin(a, b) @test ind == [3,4] + @test findin(a, Int[]) == Int[] + @test findin(Int[], a) == Int[] + + a = [1,2,3,4,5] + b = [2,3,4,6] + @test findin(a, b) == [2,3,4] + @test findin(b, a) == [1,2,3] + @test findin(a, Int[]) == Int[] + @test findin(Int[], a) == Int[] rt = Base.return_types(setindex!, Tuple{Array{Int32, 3}, UInt8, Vector{Int}, Int16, UnitRange{Int}}) @test length(rt) == 1 && rt[1] == Array{Int32, 3} From 8bacb65bbab9cbb7da2a266dc384cdd62df372aa Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 19 May 2017 12:06:33 -0400 Subject: [PATCH 0835/1534] Method overwriting by an ambiguity should also invalidate the method cache fix #21963 --- src/gf.c | 4 ++-- test/ambiguous.jl | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/gf.c b/src/gf.c index 599eabd62b9e1..683b11bc1d24c 100644 --- a/src/gf.c +++ b/src/gf.c @@ -1162,10 +1162,10 @@ static int check_ambiguous_visitor(jl_typemap_entry_t *oldentry, struct typemap_ jl_static_show_func_sig(s, isect); jl_printf(s, "\nbefore the new definition.\n"); } - return 1; // there may be multiple ambiguities, keep going } - else if (closure->after) { + if (!msp || closure->after) { // record that this method definition is being partially replaced + // (either with a real definition, or an ambiguity error) if (closure->shadowed == NULL) { closure->shadowed = oldentry->func.value; } diff --git a/test/ambiguous.jl b/test/ambiguous.jl index 32139c496a44f..14c03f877b8da 100644 --- a/test/ambiguous.jl +++ b/test/ambiguous.jl @@ -85,6 +85,16 @@ cfunction(ambig, Int, (UInt8, Int)) # test for a crash (doesn't throw an error) ambig(x, y::Integer) = 3 @test_throws MethodError ambig(2, 0x03) +# Method overwriting by an ambiguity should also invalidate the method cache (#21963) +ambig(x::Union{Char, Int8}) = 'r' +@test ambig('c') == 'r' +@test ambig(Int8(1)) == 'r' +@test_throws MethodError ambig(Int16(1)) +ambig(x::Union{Char, Int16}) = 's' +@test_throws MethodError ambig('c') +@test ambig(Int8(1)) == 'r' +@test ambig(Int16(1)) == 's' + # Automatic detection of ambiguities module Ambig1 ambig(x, y) = 1 From a72aad42104df94e7daf84e51ec12465e75d5058 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Fri, 19 May 2017 12:17:29 -0700 Subject: [PATCH 0836/1534] Add NEWS.md entry for zero-arg Channel constructor dep (#18832). (#21932) --- NEWS.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/NEWS.md b/NEWS.md index 5480fd65f7404..6d2e626aeb680 100644 --- a/NEWS.md +++ b/NEWS.md @@ -573,6 +573,10 @@ Deprecated or removed ``` `export FOO=1\;` ``` should replace ``` `export FOO=1;` ``` and ``` `cd $dir '&&' $thingie` ``` should replace ``` `cd $dir && $thingie` ``` ([#19786]). + * Zero-argument `Channel` constructors (`Channel()`, `Channel{T}()`) have been deprecated + in favor of equivalents accepting an explicit `Channel` size + (`Channel(2)`, `Channel{T}(2)`) ([#18832]). + * The zero-argument constructor `MersenneTwister()` has been deprecated in favor of the explicit `MersenneTwister(0)` ([#16984]). @@ -637,6 +641,7 @@ Command-line option changes [#18660]: https://github.com/JuliaLang/julia/issues/18660 [#18690]: https://github.com/JuliaLang/julia/issues/18690 [#18777]: https://github.com/JuliaLang/julia/issues/18777 +[#18832]: https://github.com/JuliaLang/julia/issues/18832 [#18839]: https://github.com/JuliaLang/julia/issues/18839 [#18891]: https://github.com/JuliaLang/julia/issues/18891 [#18931]: https://github.com/JuliaLang/julia/issues/18931 From 907afec04bb91478ba03a8f720f9c76ea8c7d6b8 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Fri, 19 May 2017 15:52:14 -0700 Subject: [PATCH 0837/1534] Add NEWS.md entry for promote_op(::Type, Ts...) deprecation (#18642). (#21931) --- NEWS.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/NEWS.md b/NEWS.md index 6d2e626aeb680..35129cd434a8a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -580,6 +580,11 @@ Deprecated or removed * The zero-argument constructor `MersenneTwister()` has been deprecated in favor of the explicit `MersenneTwister(0)` ([#16984]). + * `Base.promote_type(op::Type, Ts::Type...)` has been removed as part of an overhaul + of `broadcast`'s promotion mechanism. If you need the functionality of that + `Base.promote_type` method, consider defining it locally via + `Core.Inference.return_type(op, Tuple{Ts...})` ([#18642]). + * `bitbroadcast` has been deprecated in favor of `broadcast`, which now produces a `BitArray` instead of `Array{Bool}` for functions yielding a boolean result ([#19771]). @@ -637,6 +642,7 @@ Command-line option changes [#18473]: https://github.com/JuliaLang/julia/issues/18473 [#18558]: https://github.com/JuliaLang/julia/issues/18558 [#18628]: https://github.com/JuliaLang/julia/issues/18628 +[#18642]: https://github.com/JuliaLang/julia/issues/18642 [#18644]: https://github.com/JuliaLang/julia/issues/18644 [#18660]: https://github.com/JuliaLang/julia/issues/18660 [#18690]: https://github.com/JuliaLang/julia/issues/18690 From d7620388ac012492b0daa7ccb19b3ca0edf356c3 Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Fri, 19 May 2017 20:19:37 -0700 Subject: [PATCH 0838/1534] Use isbindingresolved when checking imported packages (#21580) --- base/pkg/entry.jl | 2 +- test/pkg.jl | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/base/pkg/entry.jl b/base/pkg/entry.jl index 945953859d2b2..82bb1f5ab2fb9 100644 --- a/base/pkg/entry.jl +++ b/base/pkg/entry.jl @@ -541,7 +541,7 @@ function resolve( info("$(up)grading $pkg: v$ver1 => v$ver2") Write.update(pkg, Read.sha1(pkg,ver2)) pkgsym = Symbol(pkg) - if isdefined(Main, pkgsym) && isa(getfield(Main, pkgsym), Module) + if Base.isbindingresolved(Main, pkgsym) && isa(getfield(Main, pkgsym), Module) push!(imported, "- $pkg") end end diff --git a/test/pkg.jl b/test/pkg.jl index 9e81abeedd5e9..670d1dbcc42aa 100644 --- a/test/pkg.jl +++ b/test/pkg.jl @@ -489,6 +489,16 @@ temp_pkg_dir() do @test isempty(Pkg.dependents("Example")) @test isempty(Pkg.dependents("Example.jl")) + @test_warn s -> !contains(s, "updated but were already imported") begin + Pkg.add("Iterators") + Pkg.update("Iterators") + end + + # Do it again, because the above Iterators test will update things prematurely + LibGit2.with(LibGit2.GitRepo, metadata_dir) do repo + LibGit2.reset!(repo, LibGit2.GitHash(old_commit), LibGit2.Consts.RESET_HARD) + end + @test_warn ("INFO: Installing Colors v0.6.4", "INFO: Installing ColorTypes v0.2.2", "INFO: Installing FixedPointNumbers v0.1.3", From 1b7a095e86a27e51f8bd15f2f8d0dce68b2bc010 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Sat, 20 May 2017 15:19:09 +0200 Subject: [PATCH 0839/1534] unify methods for cholesky (#21595) --- base/linalg/cholesky.jl | 45 +++++++++-------------------------------- 1 file changed, 9 insertions(+), 36 deletions(-) diff --git a/base/linalg/cholesky.jl b/base/linalg/cholesky.jl index 5ba08622ded9c..0d09fa998028d 100644 --- a/base/linalg/cholesky.jl +++ b/base/linalg/cholesky.jl @@ -16,10 +16,7 @@ # supported for the four LAPACK element types. For other types, e.g. BigFloats Val{true} will # give an error. It is required that the input is Hermitian (including real symmetric) either # through the Hermitian and Symmetric views or exact symmetric or Hermitian elements which -# is checked for and an error is thrown if the check fails. The dispatch -# is further complicated by a limitation in the formulation of Unions. The relevant union -# would be Union{Symmetric{T<:Real,S}, Hermitian} but, right now, it doesn't work in Julia -# so we'll have to define methods for the two elements of the union separately. +# is checked for and an error is thrown if the check fails. # FixMe? The dispatch below seems overly complicated. One simplification could be to # merge the two Cholesky types into one. It would remove the need for Val completely but @@ -121,9 +118,7 @@ non_hermitian_error(f) = throw(ArgumentError("matrix is not symmetric/" * # chol!. Destructive methods for computing Cholesky factor of real symmetric or Hermitian # matrix -chol!(A::Hermitian) = - _chol!(A.uplo == 'U' ? A.data : LinAlg.copytri!(A.data, 'L', true), UpperTriangular) -chol!(A::Symmetric{<:Real,<:StridedMatrix}) = +chol!(A::RealHermSymComplexHerm{<:Real,<:StridedMatrix}) = _chol!(A.uplo == 'U' ? A.data : LinAlg.copytri!(A.data, 'L', true), UpperTriangular) function chol!(A::StridedMatrix) ishermitian(A) || non_hermitian_error("chol!") @@ -134,7 +129,7 @@ end # chol. Non-destructive methods for computing Cholesky factor of a real symmetric or # Hermitian matrix. Promotes elements to a type that is stable under square roots. -function chol(A::Hermitian) +function chol(A::RealHermSymComplexHerm) T = promote_type(typeof(chol(one(eltype(A)))), Float32) AA = similar(A, T, size(A)) if A.uplo == 'U' @@ -144,16 +139,6 @@ function chol(A::Hermitian) end chol!(Hermitian(AA, :U)) end -function chol(A::Symmetric{T,<:AbstractMatrix}) where T<:Real - TT = promote_type(typeof(chol(one(T))), Float32) - AA = similar(A, TT, size(A)) - if A.uplo == 'U' - copy!(AA, A.data) - else - Base.ctranspose!(AA, A.data) - end - chol!(Hermitian(AA, :U)) -end ## for StridedMatrices, check that matrix is symmetric/Hermitian """ @@ -206,14 +191,7 @@ chol(x::Number, args...) = _chol!(x, nothing) # cholfact!. Destructive methods for computing Cholesky factorization of real symmetric # or Hermitian matrix ## No pivoting -function cholfact!(A::Hermitian, ::Type{Val{false}}) - if A.uplo == 'U' - Cholesky(_chol!(A.data, UpperTriangular).data, 'U') - else - Cholesky(_chol!(A.data, LowerTriangular).data, 'L') - end -end -function cholfact!(A::Symmetric{<:Real}, ::Type{Val{false}}) +function cholfact!(A::RealHermSymComplexHerm, ::Type{Val{false}}) if A.uplo == 'U' Cholesky(_chol!(A.data, UpperTriangular).data, 'U') else @@ -248,8 +226,8 @@ function cholfact!(A::StridedMatrix, uplo::Symbol, ::Type{Val{false}}) end ### Default to no pivoting (and storing of upper factor) when not explicit -cholfact!(A::Hermitian) = cholfact!(A, Val{false}) -cholfact!(A::Symmetric{<:Real}) = cholfact!(A, Val{false}) +cholfact!(A::RealHermSymComplexHerm) = cholfact!(A, Val{false}) + #### for StridedMatrices, check that matrix is symmetric/Hermitian function cholfact!(A::StridedMatrix, uplo::Symbol = :U) ishermitian(A) || non_hermitian_error("cholfact!") @@ -288,9 +266,7 @@ end # cholfact. Non-destructive methods for computing Cholesky factorization of real symmetric # or Hermitian matrix ## No pivoting -cholfact(A::Hermitian, ::Type{Val{false}}) = - cholfact!(copy_oftype(A, promote_type(typeof(chol(one(eltype(A)))),Float32)), Val{false}) -cholfact(A::Symmetric{<:Real,<:StridedMatrix}, ::Type{Val{false}}) = +cholfact(A::RealHermSymComplexHerm{<:Real,<:StridedMatrix}, ::Type{Val{false}}) = cholfact!(copy_oftype(A, promote_type(typeof(chol(one(eltype(A)))),Float32)), Val{false}) ### for StridedMatrices, check that matrix is symmetric/Hermitian @@ -342,8 +318,8 @@ function cholfact(A::StridedMatrix, uplo::Symbol, ::Type{Val{false}}) end ### Default to no pivoting (and storing of upper factor) when not explicit -cholfact(A::Hermitian) = cholfact(A, Val{false}) -cholfact(A::Symmetric{<:Real,<:StridedMatrix}) = cholfact(A, Val{false}) +cholfact(A::RealHermSymComplexHerm{<:Real,<:StridedMatrix}) = cholfact(A, Val{false}) + #### for StridedMatrices, check that matrix is symmetric/Hermitian function cholfact(A::StridedMatrix, uplo::Symbol = :U) ishermitian(A) || non_hermitian_error("cholfact") @@ -352,9 +328,6 @@ end ## With pivoting -cholfact(A::Hermitian, ::Type{Val{true}}; tol = 0.0) = - cholfact!(copy_oftype(A, promote_type(typeof(chol(one(eltype(A)))),Float32)), - Val{true}; tol = tol) cholfact(A::RealHermSymComplexHerm{<:Real,<:StridedMatrix}, ::Type{Val{true}}; tol = 0.0) = cholfact!(copy_oftype(A, promote_type(typeof(chol(one(eltype(A)))),Float32)), Val{true}; tol = tol) From 04a62273bbc1271a05976e235b8a816dfd291865 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Sat, 20 May 2017 16:26:33 +0200 Subject: [PATCH 0840/1534] gmp.jl: fix typo and add comment for prod on BigInt --- base/gmp.jl | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/base/gmp.jl b/base/gmp.jl index 9f6277f892e63..2e7c667b07d3b 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -477,7 +477,7 @@ end function powermod(x::BigInt, p::BigInt, m::BigInt) r = MPZ.powm(x, p, m) - return m < 0 && r > 0 ? MPZ.add!(r, m) : r # choose sign conistent with mod(x^p, m) + return m < 0 && r > 0 ? MPZ.add!(r, m) : r # choose sign consistent with mod(x^p, m) end powermod(x::Integer, p::Integer, m::BigInt) = powermod(big(x), big(p), m) @@ -501,6 +501,12 @@ function gcdx(a::BigInt, b::BigInt) end sum(arr::AbstractArray{BigInt}) = foldl(MPZ.add!, BigInt(0), arr) +# note: a similar implementation for `prod` won't be efficient: +# 1) the time complexity of the allocations is negligible compared to the multiplications +# 2) assuming arr contains similarly sized BigInts, the multiplications are much more +# performant when doing e.g. ((a1*a2)*(a2*a3))*(...) rather than a1*(a2*(a3*(...))), +# which is exactly what the default implementation of `prod` does, via mapreduce +# (which maybe could be slightly optimized for BigInt) factorial(x::BigInt) = isneg(x) ? BigInt(0) : MPZ.fac_ui(x) From 486ee7abc973b1392cc6498544c782872a22e1c1 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Sat, 25 Feb 2017 11:29:55 +0100 Subject: [PATCH 0841/1534] Improve docstrings for unique() Fix the signature of the AbstractArray method, add a mention of isequal() and of ordering, and use imperative form. --- base/multidimensional.jl | 11 +++++++---- base/set.jl | 5 +++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index e85400ebd355a..fb50624abe322 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -1302,11 +1302,14 @@ end hash(x::Prehashed) = x.hash """ - unique(itr[, dim]) + unique(A::AbstractArray[, dim::Int]) + +Return an array containing only the unique elements of `A`, as determined by +[`isequal`](@ref), in the order that the first of each set of equivalent elements +originally appears. + +If `dim` is specified, return unique regions of `A` along dimension `dim`. -Returns an array containing only the unique elements of the iterable `itr`, in -the order that the first of each set of equivalent elements originally appears. -If `dim` is specified, returns unique regions of the array `itr` along `dim`. ```jldoctest julia> A = map(isodd, reshape(collect(1:8), (2,2,2))) diff --git a/base/set.jl b/base/set.jl index 38665b5f55d94..0d19af6e20437 100644 --- a/base/set.jl +++ b/base/set.jl @@ -123,8 +123,9 @@ const ⊆ = issubset """ unique(itr) -Returns an array containing one value from `itr` for each unique value, -as determined by [`isequal`](@ref). +Return an array containing only the unique elements of collection `itr`, +as determined by [`isequal`](@ref), in the order that the first of each +set of equivalent elements originally appears. ```jldoctest julia> unique([1; 2; 2; 6]) From f98856687f94f221295a6adb98530d67301f4076 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sat, 20 May 2017 12:23:12 -0700 Subject: [PATCH 0842/1534] Add NEWS.md entry for midpoints deprecation (#20058). (#21930) --- NEWS.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/NEWS.md b/NEWS.md index 35129cd434a8a..ab530702e8a9f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -588,6 +588,11 @@ Deprecated or removed * `bitbroadcast` has been deprecated in favor of `broadcast`, which now produces a `BitArray` instead of `Array{Bool}` for functions yielding a boolean result ([#19771]). + * To complete the deprecation of histogram-related functions, `midpoints` has been + deprecated. Instead use the + [StatsBase.jl package](https://github.com/JuliaStats/StatsBase.jl)'s + `midpoint` function ([#20058]). + Command-line option changes --------------------------- @@ -711,6 +716,7 @@ Command-line option changes [#19989]: https://github.com/JuliaLang/julia/issues/19989 [#20009]: https://github.com/JuliaLang/julia/issues/20009 [#20047]: https://github.com/JuliaLang/julia/issues/20047 +[#20058]: https://github.com/JuliaLang/julia/issues/20058 [#20079]: https://github.com/JuliaLang/julia/issues/20079 [#20164]: https://github.com/JuliaLang/julia/issues/20164 [#20213]: https://github.com/JuliaLang/julia/issues/20213 From d82f097667edcd238a4205aafb0d154a7739b809 Mon Sep 17 00:00:00 2001 From: Sanjay Sri Vallabh Date: Sun, 21 May 2017 17:30:47 +0530 Subject: [PATCH 0843/1534] Docmenting options --- Make.inc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Make.inc b/Make.inc index 8d9a3eff686af..3b33d88b9f3fe 100644 --- a/Make.inc +++ b/Make.inc @@ -237,9 +237,11 @@ BUILD_LLVM_CLANG := 0 # set to 1 to get lldb (often does not work, no chance with llvm3.2 and earlier) # see http://lldb.llvm.org/build.html for dependencies BUILD_LLDB := 0 + +# Options to enable Polly and its code-generation options USE_POLLY := 0 -USE_POLLY_OPENMP := 0 -USE_POLLY_ACC := 0 +USE_POLLY_OPENMP := 0 # Enable OpenMP code-generation +USE_POLLY_ACC := 0 # Enable GPU code-generation CUDALIB_INCLUDE_DIR := /usr/local/cuda/include # Cross-compile From 6e8a1e3dcb087e3add90ab774ea2bd26bb8c0b9f Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Sun, 21 May 2017 02:20:32 -0400 Subject: [PATCH 0844/1534] Fix fallthrough warning on gcc 7 --- src/flisp/print.c | 1 + src/init.c | 1 + src/support/MurmurHash3.c | 58 +++++++++++++++++++++------------------ src/support/dtypes.h | 10 +++++++ src/support/utf8.c | 20 +++++++------- 5 files changed, 53 insertions(+), 37 deletions(-) diff --git a/src/flisp/print.c b/src/flisp/print.c index d12cbf0f37338..8c7cbef8432f2 100644 --- a/src/flisp/print.c +++ b/src/flisp/print.c @@ -448,6 +448,7 @@ void fl_print_child(fl_context_t *fl_ctx, ios_t *f, value_t v) case TAG_CVALUE: case TAG_CPRIM: if (v == UNBOUND) { outs(fl_ctx, "#", f); break; } + JL_FALLTHROUGH; case TAG_VECTOR: case TAG_CONS: if (print_circle_prefix(fl_ctx, f, v)) break; diff --git a/src/init.c b/src/init.c index 29edd9b93f1ca..612f6b1e3c54f 100644 --- a/src/init.c +++ b/src/init.c @@ -363,6 +363,7 @@ static void *init_stdio_handle(uv_file fd,int readable) } #endif // ...and continue on as in the UV_FILE case + JL_FALLTHROUGH; case UV_FILE: file = (jl_uv_file_t*)malloc(sizeof(jl_uv_file_t)); file->loop = jl_io_loop; diff --git a/src/support/MurmurHash3.c b/src/support/MurmurHash3.c index cbdd6b35d4def..a89ac1ee9af36 100644 --- a/src/support/MurmurHash3.c +++ b/src/support/MurmurHash3.c @@ -129,8 +129,8 @@ void MurmurHash3_x86_32 ( const void * key, int len, switch(len & 3) { - case 3: k1 ^= tail[2] << 16; - case 2: k1 ^= tail[1] << 8; + case 3: k1 ^= tail[2] << 16; JL_FALLTHROUGH; + case 2: k1 ^= tail[1] << 8; JL_FALLTHROUGH; case 1: k1 ^= tail[0]; k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1; }; @@ -204,26 +204,29 @@ void MurmurHash3_x86_128 ( const void * key, const int len, switch(len & 15) { - case 15: k4 ^= tail[14] << 16; - case 14: k4 ^= tail[13] << 8; + case 15: k4 ^= tail[14] << 16; JL_FALLTHROUGH; + case 14: k4 ^= tail[13] << 8; JL_FALLTHROUGH; case 13: k4 ^= tail[12] << 0; k4 *= c4; k4 = ROTL32(k4,18); k4 *= c1; h4 ^= k4; + JL_FALLTHROUGH; - case 12: k3 ^= tail[11] << 24; - case 11: k3 ^= tail[10] << 16; - case 10: k3 ^= tail[ 9] << 8; + case 12: k3 ^= tail[11] << 24; JL_FALLTHROUGH; + case 11: k3 ^= tail[10] << 16; JL_FALLTHROUGH; + case 10: k3 ^= tail[ 9] << 8; JL_FALLTHROUGH; case 9: k3 ^= tail[ 8] << 0; k3 *= c3; k3 = ROTL32(k3,17); k3 *= c4; h3 ^= k3; + JL_FALLTHROUGH; - case 8: k2 ^= tail[ 7] << 24; - case 7: k2 ^= tail[ 6] << 16; - case 6: k2 ^= tail[ 5] << 8; + case 8: k2 ^= tail[ 7] << 24; JL_FALLTHROUGH; + case 7: k2 ^= tail[ 6] << 16; JL_FALLTHROUGH; + case 6: k2 ^= tail[ 5] << 8; JL_FALLTHROUGH; case 5: k2 ^= tail[ 4] << 0; k2 *= c2; k2 = ROTL32(k2,16); k2 *= c3; h2 ^= k2; + JL_FALLTHROUGH; - case 4: k1 ^= tail[ 3] << 24; - case 3: k1 ^= tail[ 2] << 16; - case 2: k1 ^= tail[ 1] << 8; + case 4: k1 ^= tail[ 3] << 24; JL_FALLTHROUGH; + case 3: k1 ^= tail[ 2] << 16; JL_FALLTHROUGH; + case 2: k1 ^= tail[ 1] << 8; JL_FALLTHROUGH; case 1: k1 ^= tail[ 0] << 0; k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1; }; @@ -293,22 +296,23 @@ void MurmurHash3_x64_128 ( const void * key, const int len, switch(len & 15) { - case 15: k2 ^= ((uint64_t)(tail[14])) << 48; - case 14: k2 ^= ((uint64_t)(tail[13])) << 40; - case 13: k2 ^= ((uint64_t)(tail[12])) << 32; - case 12: k2 ^= ((uint64_t)(tail[11])) << 24; - case 11: k2 ^= ((uint64_t)(tail[10])) << 16; - case 10: k2 ^= ((uint64_t)(tail[ 9])) << 8; + case 15: k2 ^= ((uint64_t)(tail[14])) << 48; JL_FALLTHROUGH; + case 14: k2 ^= ((uint64_t)(tail[13])) << 40; JL_FALLTHROUGH; + case 13: k2 ^= ((uint64_t)(tail[12])) << 32; JL_FALLTHROUGH; + case 12: k2 ^= ((uint64_t)(tail[11])) << 24; JL_FALLTHROUGH; + case 11: k2 ^= ((uint64_t)(tail[10])) << 16; JL_FALLTHROUGH; + case 10: k2 ^= ((uint64_t)(tail[ 9])) << 8; JL_FALLTHROUGH; case 9: k2 ^= ((uint64_t)(tail[ 8])) << 0; k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2; - - case 8: k1 ^= ((uint64_t)(tail[ 7])) << 56; - case 7: k1 ^= ((uint64_t)(tail[ 6])) << 48; - case 6: k1 ^= ((uint64_t)(tail[ 5])) << 40; - case 5: k1 ^= ((uint64_t)(tail[ 4])) << 32; - case 4: k1 ^= ((uint64_t)(tail[ 3])) << 24; - case 3: k1 ^= ((uint64_t)(tail[ 2])) << 16; - case 2: k1 ^= ((uint64_t)(tail[ 1])) << 8; + JL_FALLTHROUGH; + + case 8: k1 ^= ((uint64_t)(tail[ 7])) << 56; JL_FALLTHROUGH; + case 7: k1 ^= ((uint64_t)(tail[ 6])) << 48; JL_FALLTHROUGH; + case 6: k1 ^= ((uint64_t)(tail[ 5])) << 40; JL_FALLTHROUGH; + case 5: k1 ^= ((uint64_t)(tail[ 4])) << 32; JL_FALLTHROUGH; + case 4: k1 ^= ((uint64_t)(tail[ 3])) << 24; JL_FALLTHROUGH; + case 3: k1 ^= ((uint64_t)(tail[ 2])) << 16; JL_FALLTHROUGH; + case 2: k1 ^= ((uint64_t)(tail[ 1])) << 8; JL_FALLTHROUGH; case 1: k1 ^= ((uint64_t)(tail[ 0])) << 0; k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1; }; diff --git a/src/support/dtypes.h b/src/support/dtypes.h index 04ffc605e4baa..a3aa489cb0c42 100644 --- a/src/support/dtypes.h +++ b/src/support/dtypes.h @@ -204,4 +204,14 @@ typedef enum { T_INT8, T_UINT8, T_INT16, T_UINT16, T_INT32, T_UINT32, # define T_SIZE T_UINT32 #endif +#if defined(__GNUC__) && __GNUC__ >= 7 +#define JL_FALLTHROUGH __attribute__((fallthrough)) +#elif defined(__cplusplus) && defined(__clang_major__) && \ + defined(__clang_minor__) && (__clang_major__ > 4 || __clang_minor__ >= 5) +// We require at least clang 3.x +#define JL_FALLTHROUGH [[clang::fallthrough]] +#else +#define JL_FALLTHROUGH +#endif + #endif /* DTYPES_H */ diff --git a/src/support/utf8.c b/src/support/utf8.c index ea371d1a31689..e192be36b7410 100644 --- a/src/support/utf8.c +++ b/src/support/utf8.c @@ -109,11 +109,11 @@ size_t u8_toucs(uint32_t *dest, size_t sz, const char *src, size_t srcsz) ch = 0; switch (nb) { /* these fall through deliberately */ - case 5: ch += (unsigned char)*src++; ch <<= 6; - case 4: ch += (unsigned char)*src++; ch <<= 6; - case 3: ch += (unsigned char)*src++; ch <<= 6; - case 2: ch += (unsigned char)*src++; ch <<= 6; - case 1: ch += (unsigned char)*src++; ch <<= 6; + case 5: ch += (unsigned char)*src++; ch <<= 6; JL_FALLTHROUGH; + case 4: ch += (unsigned char)*src++; ch <<= 6; JL_FALLTHROUGH; + case 3: ch += (unsigned char)*src++; ch <<= 6; JL_FALLTHROUGH; + case 2: ch += (unsigned char)*src++; ch <<= 6; JL_FALLTHROUGH; + case 1: ch += (unsigned char)*src++; ch <<= 6; JL_FALLTHROUGH; case 0: ch += (unsigned char)*src++; } ch -= offsetsFromUTF8[nb]; @@ -252,11 +252,11 @@ size_t u8_strwidth(const char *s) ch = 0; switch (nb) { /* these fall through deliberately */ - case 5: ch += (unsigned char)*s++; ch <<= 6; - case 4: ch += (unsigned char)*s++; ch <<= 6; - case 3: ch += (unsigned char)*s++; ch <<= 6; - case 2: ch += (unsigned char)*s++; ch <<= 6; - case 1: ch += (unsigned char)*s++; ch <<= 6; + case 5: ch += (unsigned char)*s++; ch <<= 6; JL_FALLTHROUGH; + case 4: ch += (unsigned char)*s++; ch <<= 6; JL_FALLTHROUGH; + case 3: ch += (unsigned char)*s++; ch <<= 6; JL_FALLTHROUGH; + case 2: ch += (unsigned char)*s++; ch <<= 6; JL_FALLTHROUGH; + case 1: ch += (unsigned char)*s++; ch <<= 6; JL_FALLTHROUGH; case 0: ch += (unsigned char)*s++; } ch -= offsetsFromUTF8[nb]; From d7561065a000c6488ae6de8c8cfafe7d4a2ab6b6 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Sun, 21 May 2017 10:03:40 -0400 Subject: [PATCH 0845/1534] Fix all pedantic warnings in C Hopefully this will make it easier to compile C code as C++ with GCC/Clang --- src/dlload.c | 4 ++-- src/dump.c | 10 +++++----- src/flisp/cvalues.c | 2 +- src/flisp/flisp.c | 6 +++--- src/flisp/flisp.h | 2 +- src/flisp/print.c | 9 ++++----- src/gc-debug.c | 23 +++++++++++++---------- src/gc.c | 8 ++++---- src/gc.h | 2 +- src/jl_uv.c | 12 ++++++------ src/jltypes.c | 2 +- src/julia.h | 6 +++--- src/rtutils.c | 6 +++--- src/support/dtypes.h | 2 ++ src/support/htable.inc | 2 +- src/support/utf8.c | 12 ++++++------ src/typemap.c | 6 ++++-- 17 files changed, 60 insertions(+), 54 deletions(-) diff --git a/src/dlload.c b/src/dlload.c index 74d8280935356..d7232408f268c 100644 --- a/src/dlload.c +++ b/src/dlload.c @@ -134,13 +134,13 @@ static void *jl_load_dynamic_library_(const char *modname, unsigned flags, int t if (modname == NULL) { #ifdef _OS_WINDOWS_ if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, - (LPCWSTR)(&jl_load_dynamic_library), + (LPCWSTR)(uintptr_t)(&jl_load_dynamic_library), (HMODULE*)&handle)) { jl_error("could not load base module"); } #else Dl_info info; - if (!dladdr(&jl_load_dynamic_library, &info) || !info.dli_fname) + if (!dladdr((void*)(uintptr_t)&jl_load_dynamic_library, &info) || !info.dli_fname) jl_error("could not load base module"); handle = dlopen(info.dli_fname, RTLD_NOW); #endif diff --git a/src/dump.c b/src/dump.c index 7e4ca4a9ad75a..5d0ec1080df2f 100644 --- a/src/dump.c +++ b/src/dump.c @@ -240,7 +240,7 @@ static void jl_load_sysimg_so(void) size_t tls_getter_idx = *(size_t*)jl_dlsym(jl_sysimg_handle, "jl_ptls_states_getter_idx"); *sysimg_gvars[tls_getter_idx - 1] = - (jl_value_t*)jl_get_ptls_states_getter(); + (jl_value_t*)(uintptr_t)jl_get_ptls_states_getter(); size_t tls_offset_idx = *(size_t*)jl_dlsym(jl_sysimg_handle, "jl_tls_offset_idx"); *sysimg_gvars[tls_offset_idx - 1] = @@ -445,12 +445,12 @@ static void jl_update_all_fptrs(void) assert(li->def && li->jlcall_api && li->jlcall_api != 2); int32_t cfunc = delayed_fptrs[i].cfunc - 1; if (cfunc >= 0) { - jl_fptr_to_llvm((jl_fptr_t)fvars[cfunc], li, 1); + jl_fptr_to_llvm((jl_fptr_t)(uintptr_t)fvars[cfunc], li, 1); linfos[cfunc] = li; } int32_t func = delayed_fptrs[i].func - 1; if (func >= 0) { - jl_fptr_to_llvm((jl_fptr_t)fvars[func], li, 0); + jl_fptr_to_llvm((jl_fptr_t)(uintptr_t)fvars[func], li, 0); linfos[func] = li; } } @@ -2141,7 +2141,7 @@ static jl_value_t *jl_deserialize_value_(jl_serializer_state *s, jl_value_t *vta } } -typedef struct _linkedlist_t { +JL_EXTENSION typedef struct _linkedlist_t { struct _linkedlist_t *next; union { struct { @@ -3429,7 +3429,7 @@ void jl_init_serializer(void) i=2; while (id_to_fptrs[i] != NULL) { - ptrhash_put(&fptr_to_id, (void*)id_to_fptrs[i], (void*)i); + ptrhash_put(&fptr_to_id, (void*)(uintptr_t)id_to_fptrs[i], (void*)i); i += 1; } diff --git a/src/flisp/cvalues.c b/src/flisp/cvalues.c index 9116835dfc721..7da97f7b28c54 100644 --- a/src/flisp/cvalues.c +++ b/src/flisp/cvalues.c @@ -780,7 +780,7 @@ value_t cbuiltin(fl_context_t *fl_ctx, const char *name, builtin_t f) cv->type = fl_ctx->builtintype; cv->data = &cv->_space[0]; cv->len = sizeof(value_t); - *(void**)cv->data = (void*)f; + *(void**)cv->data = (void*)(uintptr_t)f; value_t sym = symbol(fl_ctx, name); ((symbol_t*)ptr(sym))->dlcache = cv; diff --git a/src/flisp/flisp.c b/src/flisp/flisp.c index fd9cbd641f7c3..fe25401f07421 100644 --- a/src/flisp/flisp.c +++ b/src/flisp/flisp.c @@ -1020,7 +1020,7 @@ static uint32_t process_keys(fl_context_t *fl_ctx, value_t kwtable, - allocate vararg array - push closed env, set up new environment */ -static value_t apply_cl(fl_context_t *fl_ctx, uint32_t nargs) +JL_EXTENSION static value_t apply_cl(fl_context_t *fl_ctx, uint32_t nargs) { VM_LABELS; VM_APPLY_LABELS; @@ -1173,7 +1173,7 @@ static value_t apply_cl(fl_context_t *fl_ctx, uint32_t nargs) } else if (iscbuiltin(fl_ctx, fl_apply_func)) { s = fl_ctx->SP; - fl_apply_v = ((builtin_t)(((void**)ptr(fl_apply_func))[3]))(fl_ctx, &fl_ctx->Stack[fl_ctx->SP-n], n); + fl_apply_v = ((builtin_t)(uintptr_t)(((void**)ptr(fl_apply_func))[3]))(fl_ctx, &fl_ctx->Stack[fl_ctx->SP-n], n); fl_ctx->SP = s-n; fl_ctx->Stack[fl_ctx->SP-1] = fl_apply_v; NEXT_OP; @@ -1223,7 +1223,7 @@ static value_t apply_cl(fl_context_t *fl_ctx, uint32_t nargs) } else if (iscbuiltin(fl_ctx, fl_apply_func)) { s = fl_ctx->SP; - fl_apply_v = ((builtin_t)(((void**)ptr(fl_apply_func))[3]))(fl_ctx, &fl_ctx->Stack[fl_ctx->SP-n], n); + fl_apply_v = ((builtin_t)(uintptr_t)(((void**)ptr(fl_apply_func))[3]))(fl_ctx, &fl_ctx->Stack[fl_ctx->SP-n], n); fl_ctx->SP = s-n; fl_ctx->Stack[fl_ctx->SP-1] = fl_apply_v; NEXT_OP; diff --git a/src/flisp/flisp.h b/src/flisp/flisp.h index ff114048d48b1..c5c122afda7a7 100644 --- a/src/flisp/flisp.h +++ b/src/flisp/flisp.h @@ -248,7 +248,7 @@ typedef struct _fltype_t { cvinitfunc_t init; } fltype_t; -typedef struct { +JL_EXTENSION typedef struct { fltype_t *type; void *data; size_t len; // length of *data in bytes diff --git a/src/flisp/print.c b/src/flisp/print.c index d12cbf0f37338..48612fa8803a3 100644 --- a/src/flisp/print.c +++ b/src/flisp/print.c @@ -641,10 +641,10 @@ static void cvalue_printdata(fl_context_t *fl_ctx, ios_t *f, void *data, if (init == 0) { #if defined(RTLD_SELF) jl_static_print = (size_t (*)(ios_t*, void*)) - dlsym(RTLD_SELF, "jl_static_show"); + (uintptr_t)dlsym(RTLD_SELF, "jl_static_show"); #elif defined(RTLD_DEFAULT) jl_static_print = (size_t (*)(ios_t*, void*)) - dlsym(RTLD_DEFAULT, "jl_static_show"); + (uintptr_t)dlsym(RTLD_DEFAULT, "jl_static_show"); #elif defined(_OS_WINDOWS_) HMODULE handle; if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | @@ -652,7 +652,7 @@ static void cvalue_printdata(fl_context_t *fl_ctx, ios_t *f, void *data, (LPCWSTR)(&cvalue_printdata), &handle)) { jl_static_print = (size_t (*)(ios_t*, void*)) - GetProcAddress(handle, "jl_static_show"); + (uintptr_t)GetProcAddress(handle, "jl_static_show"); } #endif init = 1; @@ -747,8 +747,7 @@ static void cvalue_print(fl_context_t *fl_ctx, ios_t *f, value_t v) void *fptr = *(void**)data; label = (value_t)ptrhash_get(&fl_ctx->reverse_dlsym_lookup_table, cv); if (label == (value_t)HT_NOTFOUND) { - fl_ctx->HPOS += ios_printf(f, "#", - (size_t)(builtin_t)fptr); + fl_ctx->HPOS += ios_printf(f, "#", (size_t)fptr); } else { if (fl_ctx->print_princ) { diff --git a/src/gc-debug.c b/src/gc-debug.c index 36f6792e47dfa..d8b4154c73cbe 100644 --- a/src/gc-debug.c +++ b/src/gc-debug.c @@ -1261,7 +1261,7 @@ NOINLINE void gc_mark_loop_unwind(jl_ptls_t ptls, gc_mark_sp_t sp, int pc_offset break; } jl_safe_printf("%p: Root object: %p :: %p (bits: %d)\n of type ", - data, data->obj, (void*)data->tag, (int)data->bits); + (void*)data, (void*)data->obj, (void*)data->tag, (int)data->bits); jl_((void*)data->tag); isroot = 1; } @@ -1272,7 +1272,7 @@ NOINLINE void gc_mark_loop_unwind(jl_ptls_t ptls, gc_mark_sp_t sp, int pc_offset break; } jl_safe_printf("%p: Queued root: %p :: %p (bits: %d)\n of type ", - data, data->obj, (void*)data->tag, (int)data->bits); + (void*)data, (void*)data->obj, (void*)data->tag, (int)data->bits); jl_((void*)data->tag); isroot = 1; } @@ -1282,7 +1282,8 @@ NOINLINE void gc_mark_loop_unwind(jl_ptls_t ptls, gc_mark_sp_t sp, int pc_offset jl_safe_printf("Mark stack unwind overflow -- ABORTING !!!\n"); break; } - jl_safe_printf("%p: Finalizer list from %p to %p\n", data, data->begin, data->end); + jl_safe_printf("%p: Finalizer list from %p to %p\n", + (void*)data, (void*)data->begin, (void*)data->end); isroot = 1; } else if (pc == gc_mark_label_addrs[GC_MARK_L_objarray]) { @@ -1292,8 +1293,8 @@ NOINLINE void gc_mark_loop_unwind(jl_ptls_t ptls, gc_mark_sp_t sp, int pc_offset break; } jl_safe_printf("%p: %s Array in object %p :: %p -- [%p, %p)\n of type ", - data, prefix, data->parent, ((void**)data->parent)[-1], - data->begin, data->end); + (void*)data, prefix, (void*)data->parent, ((void**)data->parent)[-1], + (void*)data->begin, (void*)data->end); jl_(jl_typeof(data->parent)); } else if (pc == gc_mark_label_addrs[GC_MARK_L_obj8]) { @@ -1305,7 +1306,7 @@ NOINLINE void gc_mark_loop_unwind(jl_ptls_t ptls, gc_mark_sp_t sp, int pc_offset jl_datatype_t *vt = (jl_datatype_t*)jl_typeof(data->parent); jl_fielddesc8_t *desc = (jl_fielddesc8_t*)jl_dt_layout_fields(vt->layout); jl_safe_printf("%p: %s Object (8bit) %p :: %p -- [%d, %d)\n of type ", - data, prefix, data->parent, ((void**)data->parent)[-1], + (void*)data, prefix, (void*)data->parent, ((void**)data->parent)[-1], (int)(data->begin - desc), (int)(data->end - desc)); jl_(jl_typeof(data->parent)); } @@ -1318,7 +1319,7 @@ NOINLINE void gc_mark_loop_unwind(jl_ptls_t ptls, gc_mark_sp_t sp, int pc_offset jl_datatype_t *vt = (jl_datatype_t*)jl_typeof(data->parent); jl_fielddesc16_t *desc = (jl_fielddesc16_t*)jl_dt_layout_fields(vt->layout); jl_safe_printf("%p: %s Object (16bit) %p :: %p -- [%d, %d)\n of type ", - data, prefix, data->parent, ((void**)data->parent)[-1], + (void*)data, prefix, (void*)data->parent, ((void**)data->parent)[-1], (int)(data->begin - desc), (int)(data->end - desc)); jl_(jl_typeof(data->parent)); } @@ -1331,7 +1332,7 @@ NOINLINE void gc_mark_loop_unwind(jl_ptls_t ptls, gc_mark_sp_t sp, int pc_offset jl_datatype_t *vt = (jl_datatype_t*)jl_typeof(data->parent); jl_fielddesc32_t *desc = (jl_fielddesc32_t*)jl_dt_layout_fields(vt->layout); jl_safe_printf("%p: %s Object (32bit) %p :: %p -- [%d, %d)\n of type ", - data, prefix, data->parent, ((void**)data->parent)[-1], + (void*)data, prefix, (void*)data->parent, ((void**)data->parent)[-1], (int)(data->begin - desc), (int)(data->end - desc)); jl_(jl_typeof(data->parent)); } @@ -1342,7 +1343,8 @@ NOINLINE void gc_mark_loop_unwind(jl_ptls_t ptls, gc_mark_sp_t sp, int pc_offset break; } jl_safe_printf("%p: %s Stack frame %p -- %d of %d (%s)\n", - data, prefix, data->s, (int)data->i, (int)data->nroots >> 1, + (void*)data, prefix, (void*)data->s, (int)data->i, + (int)data->nroots >> 1, (data->nroots & 1) ? "indirect" : "direct"); } else if (pc == gc_mark_label_addrs[GC_MARK_L_module_binding]) { @@ -1353,7 +1355,8 @@ NOINLINE void gc_mark_loop_unwind(jl_ptls_t ptls, gc_mark_sp_t sp, int pc_offset break; } jl_safe_printf("%p: %s Module (bindings) %p (bits %d) -- [%p, %p)\n", - data, prefix, data->parent, (int)data->bits, data->begin, data->end); + (void*)data, prefix, (void*)data->parent, (int)data->bits, + (void*)data->begin, (void*)data->end); } else { jl_safe_printf("Unknown pc %p --- ABORTING !!!\n", pc); diff --git a/src/gc.c b/src/gc.c index 371919569bfbb..f30ef6f20f7d5 100644 --- a/src/gc.c +++ b/src/gc.c @@ -140,7 +140,7 @@ static void finalize_object(arraylist_t *list, jl_value_t *o, void *f = items[i + 1]; move = 1; if (gc_ptr_tag(v, 1)) { - ((void (*)(void*))f)(o); + ((void (*)(void*))(uintptr_t)f)(o); } else { arraylist_push(copied_list, o); @@ -260,7 +260,7 @@ static void schedule_all_finalizers(arraylist_t *flist) schedule_finalization(v, f); } else { - ((void (*)(void*))f)(gc_ptr_clear_tag(v, 1)); + ((void (*)(void*))(uintptr_t)f)(gc_ptr_clear_tag(v, 1)); } } flist->len = 0; @@ -1683,7 +1683,7 @@ STATIC_INLINE int gc_mark_scan_obj32(jl_ptls_t ptls, gc_mark_sp_t *sp, gc_mark_o // Additional optimizations are done for some of the common cases by skipping // the unnecessary data stack pointer increment and the load from the stack // (i.e. store to load forwaring). See `objary_loaded`, `obj8_loaded` and `obj16_loaded`. -NOINLINE void gc_mark_loop(jl_ptls_t ptls, gc_mark_sp_t sp) +JL_EXTENSION NOINLINE void gc_mark_loop(jl_ptls_t ptls, gc_mark_sp_t sp) { if (__unlikely(ptls == NULL)) { gc_mark_label_addrs[GC_MARK_L_marked_obj] = gc_mark_laddr(marked_obj); @@ -2234,7 +2234,7 @@ static void sweep_finalizer_list(arraylist_t *list) if (isfreed) { // schedule finalizer or execute right away if it is not julia code if (is_cptr) { - ((void (*)(void*))fin)(jl_data_ptr(v)); + ((void (*)(void*))(uintptr_t)fin)(jl_data_ptr(v)); continue; } schedule_finalization(v, fin); diff --git a/src/gc.h b/src/gc.h index 9b6ea7d1c1ab0..472bbaaf65d32 100644 --- a/src/gc.h +++ b/src/gc.h @@ -211,7 +211,7 @@ typedef union { // layout for big (>2k) objects -typedef struct _bigval_t { +JL_EXTENSION typedef struct _bigval_t { struct _bigval_t *next; struct _bigval_t **prev; // pointer to the next field of the prev entry union { diff --git a/src/jl_uv.c b/src/jl_uv.c index 3afc2c6cd6b25..8b246d658af38 100644 --- a/src/jl_uv.c +++ b/src/jl_uv.c @@ -405,13 +405,13 @@ JL_DLLEXPORT int jl_fs_close(int handle) } JL_DLLEXPORT int jl_uv_write(uv_stream_t *stream, const char *data, size_t n, - uv_write_t *uvw, void *writecb) + uv_write_t *uvw, uv_write_cb writecb) { uv_buf_t buf[1]; buf[0].base = (char*)data; buf[0].len = n; JL_SIGATOMIC_BEGIN(); - int err = uv_write(uvw,stream,buf,1,(uv_write_cb)writecb); + int err = uv_write(uvw, stream, buf, 1, writecb); JL_SIGATOMIC_END(); return err; } @@ -941,15 +941,15 @@ void jl_work_notifier(uv_work_t *req, int status) free(baton); } -JL_DLLEXPORT int jl_queue_work(void *work_func, void *work_args, void *work_retval, - void *notify_func, int notify_idx) +JL_DLLEXPORT int jl_queue_work(work_cb_t work_func, void *work_args, void *work_retval, + notify_cb_t notify_func, int notify_idx) { struct work_baton *baton = (struct work_baton*) malloc(sizeof(struct work_baton)); baton->req.data = (void*) baton; - baton->work_func = (work_cb_t)work_func; + baton->work_func = work_func; baton->work_args = work_args; baton->work_retval = work_retval; - baton->notify_func = (notify_cb_t)notify_func; + baton->notify_func = notify_func; baton->notify_idx = notify_idx; uv_queue_work(jl_io_loop, &baton->req, jl_work_wrapper, jl_work_notifier); diff --git a/src/jltypes.c b/src/jltypes.c index d147cbfc0d442..bc130b86cf63f 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -826,7 +826,7 @@ JL_DLLEXPORT jl_value_t *jl_tupletype_fill(size_t n, jl_value_t *v) return p; } -typedef struct _jl_typestack_t { +JL_EXTENSION typedef struct _jl_typestack_t { union { jl_value_t *ua; jl_datatype_t *tt; diff --git a/src/julia.h b/src/julia.h index e72be5ebb4e14..3af8aad0bf450 100644 --- a/src/julia.h +++ b/src/julia.h @@ -74,7 +74,7 @@ struct _jl_taggedvalue_bits { uintptr_t gc:2; }; -struct _jl_taggedvalue_t { +JL_EXTENSION struct _jl_taggedvalue_t { union { uintptr_t header; jl_taggedvalue_t *next; @@ -140,7 +140,7 @@ typedef struct { uint16_t isaligned:1; // data allocated with memalign } jl_array_flags_t; -typedef struct { +JL_EXTENSION typedef struct { JL_DATA_TYPE void *data; #ifdef STORE_ARRAY_LEN @@ -190,7 +190,7 @@ typedef jl_value_t *(*jl_fptr_t)(jl_value_t*, jl_value_t**, uint32_t); typedef jl_value_t *(*jl_fptr_sparam_t)(jl_svec_t*, jl_value_t*, jl_value_t**, uint32_t); typedef jl_value_t *(*jl_fptr_linfo_t)(struct _jl_method_instance_t*, jl_value_t**, uint32_t, jl_svec_t*); -typedef struct { +JL_EXTENSION typedef struct { union { jl_fptr_t fptr; jl_fptr_t fptr1; diff --git a/src/rtutils.c b/src/rtutils.c index e5b2c8d8f11f8..9397cab1ec0a0 100644 --- a/src/rtutils.c +++ b/src/rtutils.c @@ -504,10 +504,10 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt { size_t n = 0; if ((uintptr_t)vt < 4096U) { - n += jl_printf(out, "", v, vt); + n += jl_printf(out, "", (void*)v, (void*)vt); } else if ((uintptr_t)v < 4096U) { - n += jl_printf(out, ""); } @@ -876,7 +876,7 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt n += jl_printf(out, ")"); } else { - n += jl_printf(out, ""); } diff --git a/src/support/dtypes.h b/src/support/dtypes.h index 04ffc605e4baa..89efe70560dcb 100644 --- a/src/support/dtypes.h +++ b/src/support/dtypes.h @@ -166,9 +166,11 @@ STATIC_INLINE unsigned int next_power_of_two(unsigned int val) #ifdef __GNUC__ #define __unlikely(x) __builtin_expect(!!(x), 0) #define __likely(x) __builtin_expect(!!(x), 1) +#define JL_EXTENSION __extension__ #else #define __unlikely(x) (x) #define __likely(x) (x) +#define JL_EXTENSION #endif #define DBL_MAXINT 9007199254740992LL diff --git a/src/support/htable.inc b/src/support/htable.inc index 3e504672162df..12be2b99b0c3d 100644 --- a/src/support/htable.inc +++ b/src/support/htable.inc @@ -189,7 +189,7 @@ int HTNAME##_remove(htable_t *h, void *key) \ \ void HTNAME##_adjoin(htable_t *h, void *key, void *val) \ { \ - return HTNAME##_adjoin_r(h, key, val, NULL); \ + HTNAME##_adjoin_r(h, key, val, NULL); \ } #define HTIMPL_R(HTNAME, HFUNC, EQFUNC) _HTIMPL_EX(HTNAME, HFUNC, EQFUNC, ) diff --git a/src/support/utf8.c b/src/support/utf8.c index ea371d1a31689..4e497dbfc5d7d 100644 --- a/src/support/utf8.c +++ b/src/support/utf8.c @@ -167,9 +167,9 @@ size_t u8_toutf8(char *dest, size_t sz, const uint32_t *src, size_t srcsz) if (dest >= dest_end-2) break; // invalid: use replacement char \ufffd - *dest++ = 0xef; - *dest++ = 0xbf; - *dest++ = 0xbd; + *dest++ = (char)0xef; + *dest++ = (char)0xbf; + *dest++ = (char)0xbd; } i++; } @@ -200,9 +200,9 @@ size_t u8_wc_toutf8(char *dest, uint32_t ch) dest[3] = (ch & 0x3F) | 0x80; return 4; } - dest[0] = 0xef; - dest[1] = 0xbf; - dest[2] = 0xbd; + dest[0] = (char)0xef; + dest[1] = (char)0xbf; + dest[2] = (char)0xbd; return 3; } diff --git a/src/typemap.c b/src/typemap.c index b06be06415d76..d85a0fa8b4787 100644 --- a/src/typemap.c +++ b/src/typemap.c @@ -977,8 +977,10 @@ static void jl_typemap_level_insert_(jl_typemap_level_t *cache, jl_typemap_entry t1 = jl_tparam(ttypes, offs); } // If the type at `offs` is Any, put it in the Any list - if (t1 && jl_is_any(t1)) - return jl_typemap_insert_generic(&cache->any, (jl_value_t*)cache, newrec, (jl_value_t*)jl_any_type, offs+1, tparams); + if (t1 && jl_is_any(t1)) { + jl_typemap_insert_generic(&cache->any, (jl_value_t*)cache, newrec, (jl_value_t*)jl_any_type, offs+1, tparams); + return; + } // Don't put Varargs in the optimized caches (too hard to handle in lookup and bp) if (t1 && !isva) { // if t1 != jl_typetype_type and the argument is Type{...}, this From 24086de7a606441af1a4db00f3b0524e9c1a434b Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Sat, 6 May 2017 12:23:54 -0400 Subject: [PATCH 0846/1534] Define `sincos` Fix #10442 --- base/exports.jl | 1 + base/fastmath.jl | 40 ++++++++++++++++++++++++++++++++++++++++ base/math.jl | 15 ++++++++++++++- base/mpfr.jl | 13 ++++++++++++- base/sysimg.jl | 8 ++++---- doc/src/stdlib/math.md | 1 + test/fastmath.jl | 1 + test/math.jl | 9 +++++++++ 8 files changed, 82 insertions(+), 6 deletions(-) diff --git a/base/exports.jl b/base/exports.jl index 039c5328f9bb1..ce570f899b3de 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -405,6 +405,7 @@ export significand, sin, sinc, + sincos, sind, sinh, sinpi, diff --git a/base/fastmath.jl b/base/fastmath.jl index fbef3beb0f836..d05a80131d971 100644 --- a/base/fastmath.jl +++ b/base/fastmath.jl @@ -76,6 +76,7 @@ const fast_op = :min => :min_fast, :minmax => :minmax_fast, :sin => :sin_fast, + :sincos => :sincos_fast, :sinh => :sinh_fast, :sqrt => :sqrt_fast, :tan => :tan_fast, @@ -273,6 +274,45 @@ atan2_fast(x::Float64, y::Float64) = # explicit implementations +# FIXME: Change to `ccall((:sincos, libm))` when `Ref` calling convention can be +# stack allocated. +@inline function sincos_fast(v::Float64) + return Base.llvmcall(""" + %f = bitcast i8 *%1 to void (double, double *, double *)* + %ps = alloca double + %pc = alloca double + call void %f(double %0, double *%ps, double *%pc) + %s = load double, double* %ps + %c = load double, double* %pc + %res0 = insertvalue [2 x double] undef, double %s, 0 + %res = insertvalue [2 x double] %res0, double %c, 1 + ret [2 x double] %res + """, Tuple{Float64,Float64}, Tuple{Float64,Ptr{Void}}, v, cglobal((:sincos, libm))) +end + +@inline function sincos_fast(v::Float32) + return Base.llvmcall(""" + %f = bitcast i8 *%1 to void (float, float *, float *)* + %ps = alloca float + %pc = alloca float + call void %f(float %0, float *%ps, float *%pc) + %s = load float, float* %ps + %c = load float, float* %pc + %res0 = insertvalue [2 x float] undef, float %s, 0 + %res = insertvalue [2 x float] %res0, float %c, 1 + ret [2 x float] %res + """, Tuple{Float32,Float32}, Tuple{Float32,Ptr{Void}}, v, cglobal((:sincosf, libm))) +end + +@inline function sincos_fast(v::Float16) + s, c = sincos_fast(Float32(v)) + return Float16(s), Float16(c) +end + +sincos_fast(v::AbstractFloat) = (sin_fast(v), cos_fast(v)) +sincos_fast(v::Real) = sincos_fast(float(v)::AbstractFloat) +sincos_fast(v) = (sin_fast(v), cos_fast(v)) + @fastmath begin exp10_fast(x::T) where {T<:FloatTypes} = exp2(log2(T(10))*x) exp10_fast(x::Integer) = exp10(float(x)) diff --git a/base/math.jl b/base/math.jl index 4d8eb64fc8d32..b5f691990574b 100644 --- a/base/math.jl +++ b/base/math.jl @@ -2,7 +2,7 @@ module Math -export sin, cos, tan, sinh, cosh, tanh, asin, acos, atan, +export sin, cos, sincos, tan, sinh, cosh, tanh, asin, acos, atan, asinh, acosh, atanh, sec, csc, cot, asec, acsc, acot, sech, csch, coth, asech, acsch, acoth, sinpi, cospi, sinc, cosc, @@ -419,6 +419,19 @@ for f in (:sin, :cos, :tan, :asin, :acos, :acosh, :atanh, :log, :log2, :log10, end end +""" + sincos(x) + +Compute sine and cosine of `x`, where `x` is in radians. +""" +@inline function sincos(x) + res = Base.FastMath.sincos_fast(x) + if (isnan(res[1]) | isnan(res[2])) & !isnan(x) + throw(DomainError()) + end + return res +end + sqrt(x::Float64) = sqrt_llvm(x) sqrt(x::Float32) = sqrt_llvm(x) diff --git a/base/mpfr.jl b/base/mpfr.jl index 5ff7007370d10..4855ca4909678 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -13,7 +13,7 @@ import nextfloat, prevfloat, promote_rule, rem, rem2pi, round, show, float, sum, sqrt, string, print, trunc, precision, exp10, expm1, gamma, lgamma, log1p, - eps, signbit, sin, cos, tan, sec, csc, cot, acos, asin, atan, + eps, signbit, sin, cos, sincos, tan, sec, csc, cot, acos, asin, atan, cosh, sinh, tanh, sech, csch, coth, acosh, asinh, atanh, atan2, cbrt, typemax, typemin, unsafe_trunc, realmin, realmax, rounding, setrounding, maxintfloat, widen, significand, frexp, tryparse, iszero, big @@ -24,6 +24,8 @@ import Base.GMP: ClongMax, CulongMax, CdoubleMax, Limb import Base.Math.lgamma_r +import Base.FastMath.sincos_fast + function __init__() try # set exponent to full range by default @@ -515,6 +517,15 @@ for f in (:exp, :exp2, :exp10, :expm1, :cosh, :sinh, :tanh, :sech, :csch, :coth, end end +function sincos_fast(v::BigFloat) + s = BigFloat() + c = BigFloat() + ccall((:mpfr_sin_cos, :libmpfr), Int32, (Ptr{BigFloat}, Ptr{BigFloat}, Ptr{BigFloat}, Int32), + &s, &c, &v, ROUNDING_MODE[]) + return (s, c) +end +sincos(v::BigFloat) = sincos_fast(v) + # return log(2) function big_ln2() c = BigFloat() diff --git a/base/sysimg.jl b/base/sysimg.jl index acfb4c7b68ee4..03b0e3e3b457e 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -258,6 +258,10 @@ importall .Order include("sort.jl") importall .Sort +# Fast math +include("fastmath.jl") +importall .FastMath + function deepcopy_internal end # BigInts and BigFloats @@ -343,10 +347,6 @@ importall .DFT include("dsp.jl") importall .DSP -# Fast math -include("fastmath.jl") -importall .FastMath - # libgit2 support include("libgit2/libgit2.jl") diff --git a/doc/src/stdlib/math.md b/doc/src/stdlib/math.md index a195a354e9a0f..2e106fe4952ae 100644 --- a/doc/src/stdlib/math.md +++ b/doc/src/stdlib/math.md @@ -58,6 +58,7 @@ Base.:(!) Base.isapprox Base.sin Base.cos +Base.sincos Base.tan Base.Math.sind Base.Math.cosd diff --git a/test/fastmath.jl b/test/fastmath.jl index 1a89a83503eda..80120e7c7b2fd 100644 --- a/test/fastmath.jl +++ b/test/fastmath.jl @@ -9,6 +9,7 @@ @test macroexpand(:(@fastmath min(1))) == :(Base.FastMath.min_fast(1)) @test macroexpand(:(@fastmath min)) == :(Base.FastMath.min_fast) @test macroexpand(:(@fastmath x.min)) == :(x.min) +@test macroexpand(:(@fastmath sincos(x))) == :(Base.FastMath.sincos_fast(x)) # basic arithmetic diff --git a/test/math.jl b/test/math.jl index 136c50f98463c..59cb22f12446d 100644 --- a/test/math.jl +++ b/test/math.jl @@ -627,3 +627,12 @@ end @testset "promote Float16 irrational #15359" begin @test typeof(Float16(.5) * pi) == Float16 end + +@testset "sincos" begin + @test sincos(1.0) === (sin(1.0), cos(1.0)) + @test sincos(1f0) === (sin(1f0), cos(1f0)) + @test sincos(Float16(1)) === (sin(Float16(1)), cos(Float16(1))) + @test sincos(1) === (sin(1), cos(1)) + @test sincos(big(1)) == (sin(big(1)), cos(big(1))) + @test sincos(big(1.0)) == (sin(big(1.0)), cos(big(1.0))) +end From 4ed22b1936a410a323c7e7d9f21256fd428bb1ef Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Sat, 6 May 2017 12:46:38 -0400 Subject: [PATCH 0847/1534] Use sincos in cis and other complex math functions --- base/complex.jl | 29 +++++++++++++++++++---------- base/fastmath.jl | 5 ++++- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/base/complex.jl b/base/complex.jl index f786017d20108..836253b1d65fa 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -424,7 +424,10 @@ sqrt(z::Complex) = sqrt(float(z)) # end # compute exp(im*theta) -cis(theta::Real) = Complex(cos(theta),sin(theta)) +function cis(theta::Real) + s, c = sincos(theta) + Complex(c, s) +end """ cis(z) @@ -433,7 +436,8 @@ Return ``\\exp(iz)``. """ function cis(z::Complex) v = exp(-imag(z)) - Complex(v*cos(real(z)), v*sin(real(z))) + s, c = sincos(real(z)) + Complex(v * c, v * s) end """ @@ -510,7 +514,8 @@ function exp(z::Complex) if iszero(zi) Complex(er, zi) else - Complex(er*cos(zi), er*sin(zi)) + s, c = sincos(zi) + Complex(er * c, er * s) end end end @@ -538,7 +543,8 @@ function expm1(z::Complex{T}) where T<:Real wr = erm1 - 2 * er * (sin(convert(Tf, 0.5) * zi))^2 return Complex(wr, er * sin(zi)) else - return Complex(er * cos(zi), er * sin(zi)) + s, c = sincos(zi) + return Complex(er * c, er * s) end end end @@ -600,13 +606,15 @@ end function exp2(z::Complex{T}) where T er = exp2(real(z)) theta = imag(z) * log(convert(T, 2)) - Complex(er*cos(theta), er*sin(theta)) + s, c = sincos(theta) + Complex(er * c, er * s) end function exp10(z::Complex{T}) where T er = exp10(real(z)) theta = imag(z) * log(convert(T, 10)) - Complex(er*cos(theta), er*sin(theta)) + s, c = sincos(theta) + Complex(er * c, er * s) end function ^(z::T, p::T) where T<:Complex @@ -628,8 +636,7 @@ function ^(z::T, p::T) where T<:Complex rp = rp*exp(-pim*theta) ntheta = ntheta + pim*log(r) end - cosntheta = cos(ntheta) - sinntheta = sin(ntheta) + sinntheta, cosntheta = sincos(ntheta) re, im = rp*cosntheta, rp*sinntheta if isinf(rp) if isnan(re) @@ -689,7 +696,8 @@ function sin(z::Complex{T}) where T Complex(F(NaN), F(NaN)) end else - Complex(sin(zr)*cosh(zi), cos(zr)*sinh(zi)) + s, c = sincos(zr) + Complex(s * cosh(zi), c * sinh(zi)) end end @@ -708,7 +716,8 @@ function cos(z::Complex{T}) where T Complex(F(NaN), F(NaN)) end else - Complex(cos(zr)*cosh(zi), -sin(zr)*sinh(zi)) + s, c = sincos(zr) + Complex(c * cosh(zi), -s * sinh(zi)) end end diff --git a/base/fastmath.jl b/base/fastmath.jl index d05a80131d971..6eca987d0703b 100644 --- a/base/fastmath.jl +++ b/base/fastmath.jl @@ -327,7 +327,10 @@ sincos_fast(v) = (sin_fast(v), cos_fast(v)) # complex numbers - cis_fast(x::T) where {T<:FloatTypes} = Complex{T}(cos(x), sin(x)) + function cis_fast(x::T) where {T<:FloatTypes} + s, c = sincos_fast(x) + Complex{T}(c, s) + end # See pow_fast(x::T, y::T) where {T<:ComplexTypes} = exp(y*log(x)) From 0394f47f455defd5758dc7031266a0eb0adebc57 Mon Sep 17 00:00:00 2001 From: Amit Murthy Date: Thu, 11 May 2017 21:58:02 +0530 Subject: [PATCH 0848/1534] Fix reuse of client port on Linux. Implement for OSX. --- base/distributed/cluster.jl | 15 +++++++--- base/distributed/managers.jl | 43 +++++++++++++++------------- base/socket.jl | 20 ++++++++----- doc/src/manual/parallel-computing.md | 9 +++--- test/distributed_exec.jl | 37 +++++++++++++++++++++++- 5 files changed, 88 insertions(+), 36 deletions(-) diff --git a/base/distributed/cluster.jl b/base/distributed/cluster.jl index 633dce7fef87f..de465fa0bcd89 100644 --- a/base/distributed/cluster.jl +++ b/base/distributed/cluster.jl @@ -153,8 +153,15 @@ function start_worker(out::IO, cookie::AbstractString) init_worker(cookie) interface = IPv4(LPROC.bind_addr) if LPROC.bind_port == 0 - (actual_port,sock) = listenany(interface, UInt16(9009)) - LPROC.bind_port = actual_port + addr = Base.InetAddr(interface, 0) + sock = Base.TCPServer() + if bind(sock, addr) && Base.trylisten(sock) == 0 + _addr, port = Base._sockname(sock, true) + LPROC.bind_port = port + else + close(sock) + error("no ports available") + end else sock = listen(interface, LPROC.bind_port) end @@ -256,9 +263,9 @@ end function parse_connection_info(str) m = match(r"^julia_worker:(\d+)#(.*)", str) if m !== nothing - (m.captures[2], parse(Int16, m.captures[1])) + (m.captures[2], parse(UInt16, m.captures[1])) else - ("", Int16(-1)) + ("", UInt16(0)) end end diff --git a/base/distributed/managers.jl b/base/distributed/managers.jl index 8654218f5b5a3..d7ed15a3e3115 100644 --- a/base/distributed/managers.jl +++ b/base/distributed/managers.jl @@ -455,31 +455,34 @@ end const client_port = Ref{Cushort}(0) function socket_reuse_port() - s = TCPSocket() - client_host = Ref{Cuint}(0) - ccall(:jl_tcp_bind, Int32, - (Ptr{Void}, UInt16, UInt32, Cuint), - s.handle, hton(client_port.x), hton(UInt32(0)), 0) < 0 && throw(SystemError("bind() : ")) - - # TODO: Support OSX and change the above code to call setsockopt before bind once libuv provides - # early access to a socket fd, i.e., before a bind call. - - @static if is_linux() - try - rc = ccall(:jl_tcp_reuseport, Int32, (Ptr{Void},), s.handle) - if rc > 0 # SO_REUSEPORT is unsupported, just return the ephemerally bound socket - return s - elseif rc < 0 - throw(SystemError("setsockopt() SO_REUSEPORT : ")) - end - getsockname(s) - catch e + @static if is_linux() || is_apple() + s = TCPSocket(delay = false) + + # Linux requires the port to be bound before setting REUSEPORT, OSX after. + is_linux() && bind_client_port(s) + rc = ccall(:jl_tcp_reuseport, Int32, (Ptr{Void},), s.handle) + if rc > 0 # SO_REUSEPORT is unsupported, just return the ephemerally bound socket + return s + elseif rc < 0 # This is an issue only on systems with lots of client connections, hence delay the warning - nworkers() > 128 && warn_once("Error trying to reuse client port number, falling back to plain socket : ", e) + nworkers() > 128 && warn_once("Error trying to reuse client port number, falling back to regular socket.") + # provide a clean new socket return TCPSocket() end + is_apple() && bind_client_port(s) + else + return TCPSocket() end +end + +function bind_client_port(s) + err = ccall(:jl_tcp_bind, Int32, (Ptr{Void}, UInt16, UInt32, Cuint), + s.handle, hton(client_port[]), hton(UInt32(0)), 0) + Base.uv_error("bind() failed", err) + + _addr, port = Base._sockname(s, true) + client_port[] = port return s end diff --git a/base/socket.jl b/base/socket.jl index 7ca828205c46c..763e864c38e06 100644 --- a/base/socket.jl +++ b/base/socket.jl @@ -282,10 +282,14 @@ mutable struct TCPSocket <: LibuvStream return tcp end end -function TCPSocket() + +# kw arg "delay": if true, libuv delays creation of the socket fd till the first bind call +function TCPSocket(; delay=true) tcp = TCPSocket(Libc.malloc(_sizeof_uv_tcp), StatusUninit) - err = ccall(:uv_tcp_init, Cint, (Ptr{Void}, Ptr{Void}), - eventloop(), tcp.handle) + af_spec = delay ? 0 : 2 # AF_UNSPEC is 0, AF_INET is 2 + + err = ccall(:uv_tcp_init_ex, Cint, (Ptr{Void}, Ptr{Void}, Cuint), + eventloop(), tcp.handle, af_spec) uv_error("failed to create tcp socket", err) tcp.status = StatusInit return tcp @@ -840,16 +844,18 @@ listenany(default_port) = listenany(IPv4(UInt32(0)), default_port) Get the IP address and the port that the given `TCPSocket` is connected to (or bound to, in the case of `TCPServer`). """ -function getsockname(sock::Union{TCPServer,TCPSocket}) +getsockname(sock::Union{TCPServer, TCPSocket}) = _sockname(sock, isa(sock, TCPServer)) + +function _sockname(sock, self) rport = Ref{Cushort}(0) raddress = zeros(UInt8, 16) rfamily = Ref{Cuint}(0) - r = if isa(sock, TCPServer) - ccall(:jl_tcp_getsockname, Int32, + if self + r = ccall(:jl_tcp_getsockname, Int32, (Ptr{Void}, Ref{Cushort}, Ptr{Void}, Ref{Cuint}), sock.handle, rport, raddress, rfamily) else - ccall(:jl_tcp_getpeername, Int32, + r = ccall(:jl_tcp_getpeername, Int32, (Ptr{Void}, Ref{Cushort}, Ptr{Void}, Ref{Cuint}), sock.handle, rport, raddress, rfamily) end diff --git a/doc/src/manual/parallel-computing.md b/doc/src/manual/parallel-computing.md index 0adb65bb63dbd..e9993cefdf0aa 100644 --- a/doc/src/manual/parallel-computing.md +++ b/doc/src/manual/parallel-computing.md @@ -1231,8 +1231,8 @@ as local laptops, departmental clusters, or even the cloud. This section covers requirements for the inbuilt `LocalManager` and `SSHManager`: * The master process does not listen on any port. It only connects out to the workers. - * Each worker binds to only one of the local interfaces and listens on the first free port starting - from `9009`. + * Each worker binds to only one of the local interfaces and listens on an ephemeral port number + assigned by the OS. * `LocalManager`, used by `addprocs(N)`, by default binds only to the loopback interface. This means that workers started later on remote hosts (or by anyone with malicious intentions) are unable to connect to the cluster. An `addprocs(4)` followed by an `addprocs(["remote_host"])` will fail. @@ -1250,8 +1250,9 @@ requirements for the inbuilt `LocalManager` and `SSHManager`: authenticated via public key infrastructure (PKI). Authentication credentials can be supplied via `sshflags`, for example ```sshflags=`-e ` ```. - Note that worker-worker connections are still plain TCP and the local security policy on the remote - cluster must allow for free connections between worker nodes, at least for ports 9009 and above. + In an all-to-all topology (the default), all workers connect to each other via plain TCP sockets. + The security policy on the cluster nodes must thus ensure free connectivity between workers for + the ephemeral port range (varies by OS). Securing and encrypting all worker-worker traffic (via SSH) or encrypting individual messages can be done via a custom ClusterManager. diff --git a/test/distributed_exec.jl b/test/distributed_exec.jl index 818c410505a2c..9d9c309009232 100644 --- a/test/distributed_exec.jl +++ b/test/distributed_exec.jl @@ -12,6 +12,41 @@ include("testenv.jl") addprocs_with_testenv(4) +# Test that the client port is reused. SO_REUSEPORT may not be supported on +# all UNIX platforms, Linux kernels prior to 3.9 and older versions of OSX +if is_unix() + # Run the test on all processes. + results = asyncmap(procs()) do p + remotecall_fetch(p) do + ports_lower = [] # ports of pids lower than myid() + ports_higher = [] # ports of pids higher than myid() + for w in Base.Distributed.PGRP.workers + w.id == myid() && continue + port = Base._sockname(w.r_stream, true)[2] + if (w.id == 1) + # master connects to workers + push!(ports_higher, port) + elseif w.id < myid() + push!(ports_lower, port) + elseif w.id > myid() + push!(ports_higher, port) + end + end + @assert (length(ports_lower) + length(ports_higher)) == nworkers() + for portset in [ports_lower, ports_higher] + if (length(portset) > 0) && (length(unique(portset)) != 1) + warn("SO_REUSEPORT TESTS FAILED. UNSUPPORTED/OLDER UNIX VERSION?") + return 0 + end + end + return myid() + end + end + + # Ensure that the code has indeed been successfully executed everywhere + @test all(p -> p in results, procs()) +end + id_me = myid() id_other = filter(x -> x != id_me, procs())[rand(1:(nprocs()-1))] @@ -923,7 +958,7 @@ if is_unix() # aka have ssh end end - remotecall_fetch(plst->rmprocs(plst; waitfor=5.0), 1, new_pids) + remotecall_fetch(rmprocs, 1, new_pids) end print("\n\nTesting SSHManager. A minimum of 4GB of RAM is recommended.\n") From 22720368896f99c7385f3955fcd25c51718feeba Mon Sep 17 00:00:00 2001 From: Amit Murthy Date: Fri, 19 May 2017 13:38:40 +0530 Subject: [PATCH 0849/1534] fix listenany to return correct port number for porthint of 0 --- base/distributed/cluster.jl | 11 ++--------- base/socket.jl | 4 ++++ test/socket.jl | 36 +++++++++++++++++++----------------- 3 files changed, 25 insertions(+), 26 deletions(-) diff --git a/base/distributed/cluster.jl b/base/distributed/cluster.jl index de465fa0bcd89..3fdb113989573 100644 --- a/base/distributed/cluster.jl +++ b/base/distributed/cluster.jl @@ -153,15 +153,8 @@ function start_worker(out::IO, cookie::AbstractString) init_worker(cookie) interface = IPv4(LPROC.bind_addr) if LPROC.bind_port == 0 - addr = Base.InetAddr(interface, 0) - sock = Base.TCPServer() - if bind(sock, addr) && Base.trylisten(sock) == 0 - _addr, port = Base._sockname(sock, true) - LPROC.bind_port = port - else - close(sock) - error("no ports available") - end + (port, sock) = listenany(interface, UInt16(0)) + LPROC.bind_port = port else sock = listen(interface, LPROC.bind_port) end diff --git a/base/socket.jl b/base/socket.jl index 763e864c38e06..0c4b0996d2830 100644 --- a/base/socket.jl +++ b/base/socket.jl @@ -826,6 +826,10 @@ function listenany(host::IPAddr, default_port) while true sock = TCPServer() if bind(sock, addr) && trylisten(sock) == 0 + if default_port == 0 + _addr, port = _sockname(sock, true) + return (port, sock) + end return (addr.port, sock) end close(sock) diff --git a/test/socket.jl b/test/socket.jl index aeb76aeff2166..1d215ec237efc 100644 --- a/test/socket.jl +++ b/test/socket.jl @@ -69,27 +69,29 @@ end # test show() function for UDPSocket() @test repr(UDPSocket()) == "UDPSocket(init)" -port = Channel(1) defaultport = rand(2000:4000) -tsk = @async begin - p, s = listenany(defaultport) - put!(port, p) - sock = accept(s) - # test write call - write(sock,"Hello World\n") - - # test "locked" println to a socket - @sync begin - for i in 1:100 - @async println(sock, "a", 1) +for testport in [0, defaultport] + port = Channel(1) + tsk = @async begin + p, s = listenany(testport) + put!(port, p) + sock = accept(s) + # test write call + write(sock,"Hello World\n") + + # test "locked" println to a socket + @sync begin + for i in 1:100 + @async println(sock, "a", 1) + end end + close(s) + close(sock) end - close(s) - close(sock) + wait(port) + @test readstring(connect(fetch(port))) == "Hello World\n" * ("a1\n"^100) + wait(tsk) end -wait(port) -@test readstring(connect(fetch(port))) == "Hello World\n" * ("a1\n"^100) -wait(tsk) mktempdir() do tmpdir socketname = is_windows() ? ("\\\\.\\pipe\\uv-test-" * randstring(6)) : joinpath(tmpdir, "socket") From fa8c4d2ac0c895de3c3d36924409b44ab6b3f2dd Mon Sep 17 00:00:00 2001 From: Amit Murthy Date: Fri, 19 May 2017 13:49:00 +0530 Subject: [PATCH 0850/1534] added NEWS entry --- NEWS.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS.md b/NEWS.md index ab530702e8a9f..5d5fc02e4e178 100644 --- a/NEWS.md +++ b/NEWS.md @@ -304,6 +304,10 @@ This section lists changes that do not have deprecation warnings. * `homedir` now determines the user's home directory via `libuv`'s `uv_os_homedir`, rather than from environment variables ([#19636]). + * Workers now listen on an ephemeral port assigned by the OS. Previously workers would + listen on the first free port available from 9009 ([#21818]). + + Library improvements -------------------- From e68690dc7e626b7d3ac42638b8ed0005d08701f6 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sun, 21 May 2017 11:17:09 -0700 Subject: [PATCH 0851/1534] Mention SharedArrays constructor deps in NEWS.md entry for #19989. (#21995) --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index ab530702e8a9f..ab9523a00eb52 100644 --- a/NEWS.md +++ b/NEWS.md @@ -508,7 +508,7 @@ Deprecated or removed * The `Array` constructor syntax `Array(T, dims...)` has been deprecated in favor of the forms `Array{T,N}(dims...)` (where `N` is known, or particularly `Vector{T}(dims...)` for `N = 1` and `Matrix{T}(dims...)` for `N = 2`), - and `Array{T}(dims...)` (where `N` is not known) ([#19989]). + and `Array{T}(dims...)` (where `N` is not known). Likewise for `SharedArray`s ([#19989]). * `sumabs` and `sumabs2` have been deprecated in favor of `sum(abs, x)` and `sum(abs2, x)`, respectively. `maxabs` and `minabs` have similarly been deprecated in favor of `maximum(abs, x)` and `minimum(abs, x)`. From 03a6768baac40e9e2e59f2bb770288ed29f379ba Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Sun, 21 May 2017 17:43:33 -0400 Subject: [PATCH 0852/1534] use titlecase, not uppercase, for ucfirst (#21967) --- base/strings/basic.jl | 12 ++++++++++-- test/strings/basic.jl | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/base/strings/basic.jl b/base/strings/basic.jl index df3e4bdf6db81..e31b2218de920 100644 --- a/base/strings/basic.jl +++ b/base/strings/basic.jl @@ -394,6 +394,8 @@ lowercase(s::AbstractString) = map(lowercase, s) titlecase(s::AbstractString) Capitalizes the first character of each word in `s`. +See also [`ucfirst`](@ref) to capitalize only the first +character in `s`. ```jldoctest julia> titlecase("the julia programming language") @@ -418,7 +420,10 @@ end """ ucfirst(s::AbstractString) -Returns `string` with the first character converted to uppercase. +Returns `string` with the first character converted to uppercase +(technically "title case" for Unicode). +See also [`titlecase`](@ref) to capitalize the first character of +every word in `s`. ```jldoctest julia> ucfirst("python") @@ -426,7 +431,10 @@ julia> ucfirst("python") ``` """ function ucfirst(s::AbstractString) - isempty(s) || isupper(s[1]) ? s : string(uppercase(s[1]),s[nextind(s,1):end]) + isempty(s) && return s + c = s[1] + tc = titlecase(c) + return c==tc ? s : string(tc,s[nextind(s,1):end]) end """ diff --git a/test/strings/basic.jl b/test/strings/basic.jl index b45b6757d80af..4c155f92b1b27 100644 --- a/test/strings/basic.jl +++ b/test/strings/basic.jl @@ -151,6 +151,7 @@ end @test ucfirst("hola")=="Hola" @test ucfirst("")=="" @test ucfirst("*")=="*" +@test ucfirst("DŽxx") == ucfirst("džxx") == "Džxx" @test lcfirst("Hola")=="hola" @test lcfirst("hola")=="hola" From c2502c9ac07d2534b780f0e6b9b105e923836582 Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Sun, 21 May 2017 17:47:48 -0400 Subject: [PATCH 0853/1534] Fix issymmetric and is hermitian for Symmetric and Hermitian matrices (#21994) by only looking at the "active" triangle of the memory --- base/linalg/symmetric.jl | 26 ++++++++++++++++++++++++-- test/linalg/symmetric.jl | 11 +++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/base/linalg/symmetric.jl b/base/linalg/symmetric.jl index 6d9c865edca32..dab1eedd4c235 100644 --- a/base/linalg/symmetric.jl +++ b/base/linalg/symmetric.jl @@ -176,11 +176,33 @@ function copy!(dest::Hermitian, src::Hermitian) return dest end +function Base.isreal(A::HermOrSym) + n = size(A, 1) + @inbounds if A.uplo == 'U' + for j in 1:n + for i in 1:(j - (A isa Hermitian)) + if !isreal(A.data[i,j]) + return false + end + end + end + else + for j in 1:n + for i in (j + (A isa Hermitian)):n + if !isreal(A.data[i,j]) + return false + end + end + end + end + return true +end + ishermitian(A::Hermitian) = true ishermitian(A::Symmetric{<:Real}) = true -ishermitian(A::Symmetric{<:Complex}) = isreal(A.data) +ishermitian(A::Symmetric{<:Complex}) = isreal(A) issymmetric(A::Hermitian{<:Real}) = true -issymmetric(A::Hermitian{<:Complex}) = isreal(A.data) +issymmetric(A::Hermitian{<:Complex}) = isreal(A) issymmetric(A::Symmetric) = true transpose(A::Symmetric) = A ctranspose(A::Symmetric{<:Real}) = A diff --git a/test/linalg/symmetric.jl b/test/linalg/symmetric.jl index ac43ea7a5420b..e6ce1449bd6fa 100644 --- a/test/linalg/symmetric.jl +++ b/test/linalg/symmetric.jl @@ -300,3 +300,14 @@ let X = [1 -1; -1 1] @test_throws ArgumentError Hermitian(X) + 2im*I @test_throws ArgumentError Hermitian(X) - 2im*I end + +@testset "Issue #21981" begin + B = complex(rand(4,4)) + B[4,1] += 1im; + @test ishermitian(Symmetric(B, :U)) + @test issymmetric(Hermitian(B, :U)) + B[4,1] = real(B[4,1]) + B[1,4] += 1im + @test ishermitian(Symmetric(B, :L)) + @test issymmetric(Hermitian(B, :L)) +end From c76de36b40704710fadf6e1b1593047eb9663884 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Sun, 21 May 2017 23:44:18 -0400 Subject: [PATCH 0854/1534] Minor clean up in symbol allocation and lookup * Remove `volatile`. The thread safety is provided by atomics and not volatile * Update comment. We are now relying on the GC bits to be `GC_OLD_MARKED` in order to not update it's metadata similar to other ptrfree permgen objects allocations. --- src/symbol.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/symbol.c b/src/symbol.c index 17d9ae12ec0be..e8a2b3cab1491 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -15,7 +15,7 @@ extern "C" { #endif -static jl_sym_t *volatile symtab = NULL; +static jl_sym_t *symtab = NULL; static uintptr_t hash_symbol(const char *str, size_t len) { @@ -34,7 +34,7 @@ static jl_sym_t *mk_symbol(const char *str, size_t len) jl_taggedvalue_t *tag = (jl_taggedvalue_t*)jl_gc_perm_alloc_nolock(nb, 0); sym = (jl_sym_t*)jl_valueof(tag); - // set to old marked since we don't need write barrier on it. + // set to old marked so that we won't look at it in the GC or write barrier. tag->header = ((uintptr_t)jl_sym_type) | GC_OLD_MARKED; sym->left = sym->right = NULL; sym->hash = hash_symbol(str, len); @@ -43,10 +43,9 @@ static jl_sym_t *mk_symbol(const char *str, size_t len) return sym; } -static jl_sym_t *symtab_lookup(jl_sym_t *volatile *ptree, const char *str, - size_t len, jl_sym_t *volatile **slot) +static jl_sym_t *symtab_lookup(jl_sym_t **ptree, const char *str, size_t len, jl_sym_t ***slot) { - jl_sym_t *node = jl_atomic_load_acquire(ptree); + jl_sym_t *node = jl_atomic_load_acquire(ptree); // consume uintptr_t h = hash_symbol(str, len); // Tree nodes sorted by major key of (int(hash)) and minor key of (str). @@ -64,7 +63,7 @@ static jl_sym_t *symtab_lookup(jl_sym_t *volatile *ptree, const char *str, ptree = &node->left; else ptree = &node->right; - node = jl_atomic_load_acquire(ptree); + node = jl_atomic_load_acquire(ptree); // consume } if (slot != NULL) *slot = ptree; @@ -73,7 +72,7 @@ static jl_sym_t *symtab_lookup(jl_sym_t *volatile *ptree, const char *str, static jl_sym_t *_jl_symbol(const char *str, size_t len) { - jl_sym_t *volatile *slot; + jl_sym_t **slot; jl_sym_t *node = symtab_lookup(&symtab, str, len, &slot); if (node == NULL) { JL_LOCK_NOGC(&gc_perm_lock); From 35e38966751a2f705ec6177346fd05f0ec5471af Mon Sep 17 00:00:00 2001 From: Amit Murthy Date: Fri, 12 May 2017 16:34:05 +0530 Subject: [PATCH 0855/1534] getsockname mirrors UNIX getsockname now. Added getpeername. --- NEWS.md | 5 +++ base/distributed/managers.jl | 2 +- base/exports.jl | 1 + base/socket.jl | 21 ++++++++---- doc/src/stdlib/io-network.md | 1 + test/socket.jl | 63 ++++++++++++------------------------ 6 files changed, 44 insertions(+), 49 deletions(-) diff --git a/NEWS.md b/NEWS.md index a786c3814f2ed..65fc77458a860 100644 --- a/NEWS.md +++ b/NEWS.md @@ -3,6 +3,8 @@ Julia v0.7.0 Release Notes New language features --------------------- + * `getpeername` on a `TCPSocket` returns the address and port of the remote + endpoint of the TCP connection ([#21825]). Language changes @@ -24,6 +26,9 @@ This section lists changes that do not have deprecation warnings. * Passing the same keyword argument multiple times is now a syntax error ([#16937]). + * `getsockname` on a `TCPSocket` now returns the locally bound address and port + of the socket. Previously the address of the remote endpoint was being + returned ([#21825]). Library improvements -------------------- diff --git a/base/distributed/managers.jl b/base/distributed/managers.jl index d7ed15a3e3115..46b422e19f448 100644 --- a/base/distributed/managers.jl +++ b/base/distributed/managers.jl @@ -481,7 +481,7 @@ function bind_client_port(s) s.handle, hton(client_port[]), hton(UInt32(0)), 0) Base.uv_error("bind() failed", err) - _addr, port = Base._sockname(s, true) + _addr, port = getsockname(s) client_port[] = port return s end diff --git a/base/exports.jl b/base/exports.jl index 039c5328f9bb1..376a9704b6d55 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -1071,6 +1071,7 @@ export getaddrinfo, gethostname, getipaddr, + getpeername, getsockname, htol, hton, diff --git a/base/socket.jl b/base/socket.jl index 0c4b0996d2830..ae4e055c91325 100644 --- a/base/socket.jl +++ b/base/socket.jl @@ -827,7 +827,7 @@ function listenany(host::IPAddr, default_port) sock = TCPServer() if bind(sock, addr) && trylisten(sock) == 0 if default_port == 0 - _addr, port = _sockname(sock, true) + _addr, port = getsockname(sock) return (port, sock) end return (addr.port, sock) @@ -845,15 +845,24 @@ listenany(default_port) = listenany(IPv4(UInt32(0)), default_port) """ getsockname(sock::Union{TCPServer, TCPSocket}) -> (IPAddr, UInt16) -Get the IP address and the port that the given `TCPSocket` is connected to -(or bound to, in the case of `TCPServer`). +Get the IP address and port that the given socket is bound to. """ -getsockname(sock::Union{TCPServer, TCPSocket}) = _sockname(sock, isa(sock, TCPServer)) +getsockname(sock::Union{TCPSocket, TCPServer}) = _sockname(sock, true) -function _sockname(sock, self) + +""" + getpeername(sock::TCPSocket) -> (IPAddr, UInt16) + +Get the IP address and port of the remote endpoint that the given +socket is connected to. Valid only for connected TCP sockets. +""" +getpeername(sock::TCPSocket) = _sockname(sock, false) + +function _sockname(sock, self=true) rport = Ref{Cushort}(0) raddress = zeros(UInt8, 16) rfamily = Ref{Cuint}(0) + if self r = ccall(:jl_tcp_getsockname, Int32, (Ptr{Void}, Ref{Cushort}, Ptr{Void}, Ref{Cuint}), @@ -886,7 +895,7 @@ function _sockname(sock, self) naddr = ntoh(unsafe_load(Ptr{UInt128}(pointer(raddress)), 1)) addr = IPv6(naddr) else - error("unsupported address family: $(getindex(rfamily))") + error(string("unsupported address family: ", getindex(rfamily))) end else error("cannot obtain socket name") diff --git a/doc/src/stdlib/io-network.md b/doc/src/stdlib/io-network.md index cb697abfbac33..88fd2b2cf3bb0 100644 --- a/doc/src/stdlib/io-network.md +++ b/doc/src/stdlib/io-network.md @@ -162,6 +162,7 @@ Base.listen(::Any) Base.listen(::AbstractString) Base.getaddrinfo Base.getsockname +Base.getpeername Base.IPv4 Base.IPv6 Base.nb_available diff --git a/test/socket.jl b/test/socket.jl index 1d215ec237efc..917d3c240a13c 100644 --- a/test/socket.jl +++ b/test/socket.jl @@ -193,56 +193,35 @@ if !is_windows() || Sys.windows_version() >= Sys.WINDOWS_VISTA_VER end begin - default_port = UInt16(11011) - default_addr = IPv4("127.0.0.1") + for (addr, porthint) in [(IPv4("127.0.0.1"), UInt16(11011)), + (IPv6("::1"), UInt16(11012)), (getipaddr(), UInt16(11013))] + port, listen_sock = listenany(addr, porthint) + gsn_addr, gsn_port = getsockname(listen_sock) - sock = Base.TCPServer() - bind(sock,Base.InetAddr(default_addr,default_port)) - listen(sock) + @test addr == gsn_addr + @test port == gsn_port - new_addr, new_port = getsockname(sock) + @test_throws MethodError getpeername(listen_sock) - @test default_addr == new_addr - @test default_port == new_port - close(sock) -end + # connect to it + client_sock = connect(addr, port) + server_sock = accept(listen_sock) -begin - default_port = UInt16(21011) - default_addr = IPv6("::1") + self_client_addr, self_client_port = getsockname(client_sock) + peer_client_addr, peer_client_port = getpeername(client_sock) + self_srvr_addr, self_srvr_port = getsockname(server_sock) + peer_srvr_addr, peer_srvr_port = getpeername(server_sock) - sock = Base.TCPServer() - addr = Base.InetAddr(default_addr,default_port) - bind(sock,addr) - listen(sock) + @test self_client_addr == peer_client_addr == self_srvr_addr == peer_srvr_addr - new_addr, new_port = getsockname(sock) + @test peer_client_port == self_srvr_port + @test peer_srvr_port == self_client_port + @test self_srvr_port != self_client_port - @test default_addr == new_addr - @test default_port == new_port - close(sock) -end - -begin - default_port = UInt16(11011) - default_addr = getipaddr() - - sock = Base.TCPServer() - bind(sock,Base.InetAddr(default_addr,default_port)) - listen(sock) - - @async begin - sleep(1) - ssock = connect(default_addr, default_port) + close(listen_sock) + close(client_sock) + close(server_sock) end - - csock = accept(sock) - new_addr, new_port = getsockname(csock) - - @test default_addr == new_addr - @test new_port > 0 - close(csock) - close(sock) end # Local-machine broadcast From 47d8592131a06a2485c78fef800bbffdec7d8338 Mon Sep 17 00:00:00 2001 From: Sanjay Sri Vallabh Date: Mon, 22 May 2017 19:43:26 +0530 Subject: [PATCH 0856/1534] Stop compilation if CUDALIB_INCLUDE_DIR not set. --- Make.inc | 2 +- src/Makefile | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Make.inc b/Make.inc index 3b33d88b9f3fe..0de5964e73473 100644 --- a/Make.inc +++ b/Make.inc @@ -242,7 +242,7 @@ BUILD_LLDB := 0 USE_POLLY := 0 USE_POLLY_OPENMP := 0 # Enable OpenMP code-generation USE_POLLY_ACC := 0 # Enable GPU code-generation -CUDALIB_INCLUDE_DIR := /usr/local/cuda/include +CUDALIB_INCLUDE_DIR := # Path to CUDA header files # Cross-compile #XC_HOST := i686-w64-mingw32 diff --git a/src/Makefile b/src/Makefile index 4e9a21d069588..551eb16ffbf83 100644 --- a/src/Makefile +++ b/src/Makefile @@ -67,6 +67,9 @@ endif ifeq ($(USE_POLLY_ACC),1) LLVMLINK += -lPollyPPCG FLAGS += -DUSE_POLLY_ACC +ifeq ($(CUDALIB_INCLUDE_DIR),) +$(error CUDALIB_INCLUDE_DIR not set: Please provide the path to CUDA header files) +endif FLAGS += -I$(CUDALIB_INCLUDE_DIR) FLAGS += -I$(shell $(LLVM_CONFIG_HOST) --src-root)/tools/polly/tools endif From d3bc3295b4596ed5ed916379cdd8d9cab5e49a02 Mon Sep 17 00:00:00 2001 From: Amit Murthy Date: Mon, 22 May 2017 21:17:58 +0530 Subject: [PATCH 0857/1534] Return socket correctly in socket_reuse_port (#22017) * Return socket correctly in socket_reuse_port * Run reuseport tests only if SO_REUSEPORT is supported. * Test fix - test for successful addition of workers in distributed test --- base/distributed/managers.jl | 1 + test/distributed_exec.jl | 18 +++++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/base/distributed/managers.jl b/base/distributed/managers.jl index 46b422e19f448..c5e4fd24515c8 100644 --- a/base/distributed/managers.jl +++ b/base/distributed/managers.jl @@ -471,6 +471,7 @@ function socket_reuse_port() return TCPSocket() end is_apple() && bind_client_port(s) + return s else return TCPSocket() end diff --git a/test/distributed_exec.jl b/test/distributed_exec.jl index 9d9c309009232..febc80d4301f6 100644 --- a/test/distributed_exec.jl +++ b/test/distributed_exec.jl @@ -11,10 +11,9 @@ include("testenv.jl") end addprocs_with_testenv(4) +@test nprocs() == 5 -# Test that the client port is reused. SO_REUSEPORT may not be supported on -# all UNIX platforms, Linux kernels prior to 3.9 and older versions of OSX -if is_unix() +function reuseport_tests() # Run the test on all processes. results = asyncmap(procs()) do p remotecall_fetch(p) do @@ -47,6 +46,19 @@ if is_unix() @test all(p -> p in results, procs()) end +# Test that the client port is reused. SO_REUSEPORT may not be supported on +# all UNIX platforms, Linux kernels prior to 3.9 and older versions of OSX +if is_unix() + # Run reuse client port tests only if SO_REUSEPORT is supported. + s = TCPSocket(delay = false) + is_linux() && Base.Distributed.bind_client_port(s) + if ccall(:jl_tcp_reuseport, Int32, (Ptr{Void},), s.handle) == 0 + reuseport_tests() + else + info("SO_REUSEPORT is unsupported, skipping reuseport tests.") + end +end + id_me = myid() id_other = filter(x -> x != id_me, procs())[rand(1:(nprocs()-1))] From 628ab6d1d83134977ac9a503484206c5a23a484b Mon Sep 17 00:00:00 2001 From: Sanjay Sri Vallabh Date: Mon, 22 May 2017 23:34:30 +0530 Subject: [PATCH 0858/1534] Stop compilation if CUDALIB_INCLUDE_DIR not set when USE_POLLY_ACC==1 --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 551eb16ffbf83..7332bc2350eb5 100644 --- a/src/Makefile +++ b/src/Makefile @@ -68,7 +68,7 @@ ifeq ($(USE_POLLY_ACC),1) LLVMLINK += -lPollyPPCG FLAGS += -DUSE_POLLY_ACC ifeq ($(CUDALIB_INCLUDE_DIR),) -$(error CUDALIB_INCLUDE_DIR not set: Please provide the path to CUDA header files) +$(error CUDALIB_INCLUDE_DIR not set: If compiling with USE_POLLY_ACC, user must provide the path to CUDA header files) endif FLAGS += -I$(CUDALIB_INCLUDE_DIR) FLAGS += -I$(shell $(LLVM_CONFIG_HOST) --src-root)/tools/polly/tools From 915910c3e3301891dad754d7443907ca49a9eaa5 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Fri, 19 May 2017 19:06:19 -0400 Subject: [PATCH 0859/1534] Add necessary LLVM patches --- deps/llvm.mk | 2 + deps/patches/llvm-D32593.patch | 83 ++++++++++++++++++++++++++++++++++ deps/patches/llvm-D33179.patch | 64 ++++++++++++++++++++++++++ 3 files changed, 149 insertions(+) create mode 100644 deps/patches/llvm-D32593.patch create mode 100644 deps/patches/llvm-D33179.patch diff --git a/deps/llvm.mk b/deps/llvm.mk index ee025c46f27ac..5e530f4e2cd7e 100644 --- a/deps/llvm.mk +++ b/deps/llvm.mk @@ -497,6 +497,8 @@ $(eval $(call LLVM_PATCH,llvm-PR278923)) # Issue #19976, Remove for 4.0 $(eval $(call LLVM_PATCH,llvm-D28759-loopclearance)) $(eval $(call LLVM_PATCH,llvm-D28786-callclearance)) $(eval $(call LLVM_PATCH,llvm-rL293230-icc17-cmake)) # Remove for 4.0 +$(eval $(call LLVM_PATCH,llvm-D32593)) +$(eval $(call LLVM_PATCH,llvm-D33179)) endif # LLVM_VER ifeq ($(LLVM_VER),3.7.1) diff --git a/deps/patches/llvm-D32593.patch b/deps/patches/llvm-D32593.patch new file mode 100644 index 0000000000000..19c4acb960f97 --- /dev/null +++ b/deps/patches/llvm-D32593.patch @@ -0,0 +1,83 @@ +From 5eeab81d22e07b6e12821067fced590f534c251a Mon Sep 17 00:00:00 2001 +From: Keno Fischer +Date: Thu, 27 Apr 2017 14:33:33 -0400 +Subject: [PATCH] [SROA] Fix crash due to bad bitcast + +Summary: +As shown in the test case, SROA was crashing when trying to split +stores (to the alloca) of loads (from anywhere), because it assumed +the pointer operand to the loads and stores had to have the same +address space. This isn't the case. Make sure to use the correct +pointer type for both the load and the store. + +Reviewers: chandlerc, majnemer, sanjoy + +Subscribers: arsenm, llvm-commits + +Differential Revision: https://reviews.llvm.org/D32593 +--- + lib/Transforms/Scalar/SROA.cpp | 7 ++++--- + test/Transforms/SROA/address-spaces.ll | 18 ++++++++++++++++++ + 2 files changed, 22 insertions(+), 3 deletions(-) + +diff --git a/lib/Transforms/Scalar/SROA.cpp b/lib/Transforms/Scalar/SROA.cpp +index d01e91a..610d5a8 100644 +--- a/lib/Transforms/Scalar/SROA.cpp ++++ b/lib/Transforms/Scalar/SROA.cpp +@@ -3697,7 +3697,8 @@ bool SROA::presplitLoadsAndStores(AllocaInst &AI, AllocaSlices &AS) { + int Idx = 0, Size = Offsets.Splits.size(); + for (;;) { + auto *PartTy = Type::getIntNTy(Ty->getContext(), PartSize * 8); +- auto *PartPtrTy = PartTy->getPointerTo(SI->getPointerAddressSpace()); ++ auto *LoadPartPtrTy = PartTy->getPointerTo(LI->getPointerAddressSpace()); ++ auto *StorePartPtrTy = PartTy->getPointerTo(SI->getPointerAddressSpace()); + + // Either lookup a split load or create one. + LoadInst *PLoad; +@@ -3708,7 +3709,7 @@ bool SROA::presplitLoadsAndStores(AllocaInst &AI, AllocaSlices &AS) { + PLoad = IRB.CreateAlignedLoad( + getAdjustedPtr(IRB, DL, LoadBasePtr, + APInt(DL.getPointerSizeInBits(), PartOffset), +- PartPtrTy, LoadBasePtr->getName() + "."), ++ LoadPartPtrTy, LoadBasePtr->getName() + "."), + getAdjustedAlignment(LI, PartOffset, DL), /*IsVolatile*/ false, + LI->getName()); + } +@@ -3718,7 +3719,7 @@ bool SROA::presplitLoadsAndStores(AllocaInst &AI, AllocaSlices &AS) { + StoreInst *PStore = IRB.CreateAlignedStore( + PLoad, getAdjustedPtr(IRB, DL, StoreBasePtr, + APInt(DL.getPointerSizeInBits(), PartOffset), +- PartPtrTy, StoreBasePtr->getName() + "."), ++ StorePartPtrTy, StoreBasePtr->getName() + "."), + getAdjustedAlignment(SI, PartOffset, DL), /*IsVolatile*/ false); + + // Now build a new slice for the alloca. +diff --git a/test/Transforms/SROA/address-spaces.ll b/test/Transforms/SROA/address-spaces.ll +index 119f225..8fba30c 100644 +--- a/test/Transforms/SROA/address-spaces.ll ++++ b/test/Transforms/SROA/address-spaces.ll +@@ -83,3 +83,21 @@ define void @pr27557() { + store i32 addrspace(3)* @l, i32 addrspace(3)** %3, align 8 + ret void + } ++ ++; Make sure pre-splitting doesn't try to introduce an illegal bitcast ++define float @presplit(i64 addrspace(1)* %p) { ++entry: ++; CHECK-LABEL: @presplit( ++; CHECK: %[[CAST:.*]] = bitcast i64 addrspace(1)* {{.*}} to i32 addrspace(1)* ++; CHECK: load i32, i32 addrspace(1)* %[[CAST]] ++ %b = alloca i64 ++ %b.cast = bitcast i64* %b to [2 x float]* ++ %b.gep1 = getelementptr [2 x float], [2 x float]* %b.cast, i32 0, i32 0 ++ %b.gep2 = getelementptr [2 x float], [2 x float]* %b.cast, i32 0, i32 1 ++ %l = load i64, i64 addrspace(1)* %p ++ store i64 %l, i64* %b ++ %f1 = load float, float* %b.gep1 ++ %f2 = load float, float* %b.gep2 ++ %ret = fadd float %f1, %f2 ++ ret float %ret ++} +-- +2.9.3 + diff --git a/deps/patches/llvm-D33179.patch b/deps/patches/llvm-D33179.patch new file mode 100644 index 0000000000000..2be915018de24 --- /dev/null +++ b/deps/patches/llvm-D33179.patch @@ -0,0 +1,64 @@ +From b1a005ba688397ca360e89cd6c6f51f232d6c25e Mon Sep 17 00:00:00 2001 +From: Keno Fischer +Date: Fri, 19 May 2017 18:42:20 -0400 +Subject: [PATCH] [Sink] Fix predicate in legality check + +Summary: +isSafeToSpeculativelyExecute is the wrong predicate to use here. +All that checks for is whether it is safe to hoist a value due to +unaligned/un-dereferencable accesses. However, not only are we doing +sinking rather than hoisting, our concern is that the location +we're loading from may have been modified. Instead forbid sinking +any load across a critical edge. + +Reviewers: majnemer + +Subscribers: llvm-commits + +Differential Revision: https://reviews.llvm.org/D33179 +--- + lib/Transforms/Scalar/Sink.cpp | 2 +- + test/Transforms/Sink/badloadsink.ll | 18 ++++++++++++++++++ + 2 files changed, 19 insertions(+), 1 deletion(-) + create mode 100644 test/Transforms/Sink/badloadsink.ll + +diff --git a/lib/Transforms/Scalar/Sink.cpp b/lib/Transforms/Scalar/Sink.cpp +index 102e9ea..5210f16 100644 +--- a/lib/Transforms/Scalar/Sink.cpp ++++ b/lib/Transforms/Scalar/Sink.cpp +@@ -114,7 +114,7 @@ static bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo, + if (SuccToSinkTo->getUniquePredecessor() != Inst->getParent()) { + // We cannot sink a load across a critical edge - there may be stores in + // other code paths. +- if (!isSafeToSpeculativelyExecute(Inst)) ++ if (isa(Inst)) + return false; + + // We don't want to sink across a critical edge if we don't dominate the +diff --git a/test/Transforms/Sink/badloadsink.ll b/test/Transforms/Sink/badloadsink.ll +new file mode 100644 +index 0000000..e3f4884 +--- /dev/null ++++ b/test/Transforms/Sink/badloadsink.ll +@@ -0,0 +1,18 @@ ++; RUN: opt < %s -basicaa -sink -S | FileCheck %s ++declare void @foo(i64 *) ++define i64 @sinkload(i1 %cmp) { ++; CHECK-LABEL: @sinkload ++top: ++ %a = alloca i64 ++; CHECK: call void @foo(i64* %a) ++; CHECK-NEXT: %x = load i64, i64* %a ++ call void @foo(i64* %a) ++ %x = load i64, i64* %a ++ br i1 %cmp, label %A, label %B ++A: ++ store i64 0, i64 *%a ++ br label %B ++B: ++; CHECK-NOT: load i64, i64 *%a ++ ret i64 %x ++} +-- +2.9.3 + From 51c5ef48f8aeae6c841b5931f67dc16fc95c7e83 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 16 May 2017 13:49:06 -0400 Subject: [PATCH 0860/1534] show statement type for :invoke Expr heads --- base/show.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/base/show.jl b/base/show.jl index 9058f42485d41..3e39b419f284b 100644 --- a/base/show.jl +++ b/base/show.jl @@ -1036,7 +1036,9 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int) show_type = false # print anything else as "Expr(head, args...)" else - show_type = false + if head !== :invoke + show_type = false + end if emphstate && ex.head !== :lambda && ex.head !== :method io = IOContext(io, :TYPEEMPHASIZE => false) emphstate = false From 8cc5e2bc3e62790ea0625ef007fdf970d809485c Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 19 May 2017 10:35:04 -0400 Subject: [PATCH 0861/1534] fix bug in PR #21620 would segfault when reaching the jl_datatype_nfields call --- src/codegen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index a3cd82040a16e..35061fe614f11 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3048,7 +3048,7 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, jl_datatype_t *sty = (jl_datatype_t*)expr_type(args[1], ctx); rt1 = (jl_value_t*)sty; jl_datatype_t *uty = (jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)sty); - if (jl_is_structtype(uty) && uty != jl_module_type) { + if (jl_is_structtype(uty) && uty != jl_module_type && ((jl_datatype_t*)uty)->layout) { size_t idx = (size_t)-1; if (jl_is_quotenode(args[2]) && jl_is_symbol(jl_fieldref(args[2],0))) { idx = jl_field_index(uty, (jl_sym_t*)jl_fieldref(args[2],0), 0); From 93898af5b8b68746741747318e76d9319a49b429 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 15 May 2017 16:23:31 -0400 Subject: [PATCH 0862/1534] inference: ignore uncached functions during cycle resolution --- base/inference.jl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 532b48917a26b..f842406ecbcfe 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -1431,7 +1431,7 @@ function precise_container_type(arg::ANY, typ::ANY, vtypes::VarTable, sv::Infere if isa(typ, Const) val = typ.val if isa(val, SimpleVector) || isa(val, Tuple) - return Any[ abstract_eval_constant(x) for x in val ] + return Any[ Const(val[i]) for i in 1:length(val) ] # avoid making a tuple Generator here! end end @@ -2508,12 +2508,14 @@ function typeinf_edge(method::Method, atypes::ANY, sparams::SimpleVector, caller frame = resolve_call_cycle!(code, caller) if frame === nothing code.inInference = true - frame = InferenceState(code, true, true, caller.params) # always optimize and cache edge targets + frame = InferenceState(code, #=optimize=#true, #=cached=#true, caller.params) # always optimize and cache edge targets if frame === nothing code.inInference = false return Any, nothing end - frame.parent = caller + if caller.cached # don't involve uncached functions in cycle resolution + frame.parent = caller + end typeinf(frame) return frame.bestguess, frame.inferred ? frame.linfo : nothing end From 941738bf34d6ad93c9ad1acf023639b6f5b8ca26 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 17 May 2017 15:25:54 -0400 Subject: [PATCH 0863/1534] inference: prohibit inlining of methods (un)specialized on Unions TODO: this is helping to avoid a type-system bug mis-computing sparams during intersection, but that can already cause significant problems elsewhere too --- base/inference.jl | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/base/inference.jl b/base/inference.jl index f842406ecbcfe..15693525ba53a 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -2851,6 +2851,7 @@ end #### finalize and record the result of running type inference #### function isinlineable(m::Method, src::CodeInfo) + # compute the cost (size) of inlining this code inlineable = false cost = 1000 if m.module === _topmod(m.module) @@ -2943,7 +2944,25 @@ function optimize(me::InferenceState) end # determine and cache inlineability - if !me.src.inlineable && !force_noinline && isdefined(me.linfo, :def) + if !force_noinline + # don't keep ASTs for functions specialized on a Union argument + # TODO: this helps avoid a type-system bug mis-computing sparams during intersection + sig = unwrap_unionall(me.linfo.specTypes) + if isa(sig, DataType) && sig.name === Tuple.name + for P in sig.parameters + P = unwrap_unionall(P) + if isa(P, Union) + force_noinline = true + break + end + end + else + force_noinline = true + end + end + if force_noinline + me.src.inlineable = false + elseif !me.src.inlineable && isdefined(me.linfo, :def) me.src.inlineable = isinlineable(me.linfo.def, me.src) end me.src.inferred = true From cf0c6a1e5e0983f1ab11c774b54c7496d6e46650 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 17 May 2017 03:12:35 -0400 Subject: [PATCH 0864/1534] enable inference of _apply on non-constant functions --- base/inference.jl | 77 ++++++++++++++++++++++++++--------------------- 1 file changed, 42 insertions(+), 35 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 15693525ba53a..437dd6f995025 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -1499,44 +1499,64 @@ function abstract_iteration(itertype::ANY, vtypes::VarTable, sv::InferenceState) return Vararg{valtype} end +function tuple_tail_elem(init::ANY, ct) + return Vararg{widenconst(foldl((a, b) -> tmerge(a, unwrapva(b)), init, ct))} +end + # do apply(af, fargs...), where af is a function value -function abstract_apply(af::ANY, fargs::Vector{Any}, aargtypes::Vector{Any}, vtypes::VarTable, sv::InferenceState) +function abstract_apply(aft::ANY, fargs::Vector{Any}, aargtypes::Vector{Any}, vtypes::VarTable, sv::InferenceState) + if !isa(aft, Const) && !isconstType(aft) + if !(isleaftype(aft) || aft <: Type) || (aft <: Builtin) || (aft <: IntrinsicFunction) + return Any + end + # non-constant function, but type is known + end res = Union{} nargs = length(fargs) assert(nargs == length(aargtypes)) - splitunions = countunionsplit(aargtypes) <= sv.params.MAX_APPLY_UNION_ENUM - ctypes = Any[Any[]] + splitunions = 1 < countunionsplit(aargtypes) <= sv.params.MAX_APPLY_UNION_ENUM + ctypes = Any[Any[aft]] for i = 1:nargs if aargtypes[i] === Any # bail out completely and infer as f(::Any...) - # instead could keep what we got so far and just append a Vararg{Any} (by just - # using the normal logic from below), but that makes the time of the subarray - # test explode - ctypes = Any[Any[Vararg{Any}]] + # instead could infer the precise types for the types up to this point and just append a Vararg{Any} + # (by just using the normal logic from below), but that makes the time of the subarray test explode + push!(ctypes[1], Vararg{Any}) break end - ctypes´ = [] - for ti in (splitunions ? uniontypes(aargtypes[i]) : Any[aargtypes[i]]) - cti = precise_container_type(fargs[i], ti, vtypes, sv) - for ct in ctypes - if !isempty(ct) && isvarargtype(ct[end]) - tail = foldl((a,b)->tmerge(a,unwrapva(b)), unwrapva(ct[end]), cti) - push!(ctypes´, push!(ct[1:end-1], Vararg{widenconst(tail)})) - else - push!(ctypes´, append_any(ct, cti)) + end + if length(ctypes[1]) == 1 + for i = 1:nargs + ctypes´ = [] + for ti in (splitunions ? uniontypes(aargtypes[i]) : Any[aargtypes[i]]) + cti = precise_container_type(fargs[i], ti, vtypes, sv) + for ct in ctypes + if !isempty(ct) && isvarargtype(ct[end]) + tail = tuple_tail_elem(unwrapva(ct[end]), cti) + push!(ctypes´, push!(ct[1:(end - 1)], tail)) + else + push!(ctypes´, append_any(ct, cti)) + end end end + ctypes = ctypes´ end - ctypes = ctypes´ end for ct in ctypes if length(ct) > sv.params.MAX_TUPLETYPE_LEN - tail = foldl((a,b)->tmerge(a,unwrapva(b)), Bottom, ct[sv.params.MAX_TUPLETYPE_LEN:end]) + tail = tuple_tail_elem(Bottom, ct[sv.params.MAX_TUPLETYPE_LEN:end]) resize!(ct, sv.params.MAX_TUPLETYPE_LEN) - ct[end] = Vararg{widenconst(tail)} + ct[end] = tail end - at = append_any(Any[Const(af)], ct) - res = tmerge(res, abstract_call(af, (), at, vtypes, sv)) + if isa(aft, Const) + rt = abstract_call(aft.val, (), ct, vtypes, sv) + elseif isconstType(aft) + rt = abstract_call(aft.parameters[1], (), ct, vtypes, sv) + else + astype = argtypes_to_type(ct) + rt = abstract_call_gf_by_type(nothing, astype, sv) + end + res = tmerge(res, rt) if res === Any break end @@ -1651,20 +1671,7 @@ typename_static(t::ANY) = isType(t) ? _typename(t.parameters[1]) : Any function abstract_call(f::ANY, fargs::Union{Tuple{},Vector{Any}}, argtypes::Vector{Any}, vtypes::VarTable, sv::InferenceState) if f === _apply length(fargs) > 1 || return Any - aft = argtypes[2] - if isa(aft, Const) - af = aft.val - else - if isType(aft) && isleaftype(aft.parameters[1]) - af = aft.parameters[1] - elseif isleaftype(aft) && isdefined(aft, :instance) - af = aft.instance - else - # TODO jb/functions: take advantage of case where non-constant `af`'s type is known - return Any - end - end - return abstract_apply(af, fargs[3:end], argtypes[3:end], vtypes, sv) + return abstract_apply(argtypes[2], fargs[3:end], argtypes[3:end], vtypes, sv) end la = length(argtypes) From c678d592ce08ce8344ff46e0aefa2c2e2f58f503 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 17 May 2017 15:40:02 -0400 Subject: [PATCH 0865/1534] fix recompilation of Core.Inference --- base/int.jl | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/base/int.jl b/base/int.jl index 1597c0320dd0a..bbbe846976f85 100644 --- a/base/int.jl +++ b/base/int.jl @@ -362,22 +362,24 @@ end # @doc isn't available when running in Core at this point. # Tuple syntax for documention two function signatures at the same time # doesn't work either at this point. -isdefined(Main, :Base) && for fname in (:mod, :rem) - @eval @doc """ - rem(x::Integer, T::Type{<:Integer}) -> T - mod(x::Integer, T::Type{<:Integer}) -> T - %(x::Integer, T::Type{<:Integer}) -> T - - Find `y::T` such that `x` ≡ `y` (mod n), where n is the number of integers representable - in `T`, and `y` is an integer in `[typemin(T),typemax(T)]`. - If `T` can represent any integer (e.g. `T == BigInt`), then this operation corresponds to - a conversion to `T`. - - ```jldoctest - julia> 129 % Int8 - -127 - ``` - """ -> $fname(x::Integer, T::Type{<:Integer}) +if module_name(current_module()) === :Base + for fname in (:mod, :rem) + @eval @doc (""" + rem(x::Integer, T::Type{<:Integer}) -> T + mod(x::Integer, T::Type{<:Integer}) -> T + %(x::Integer, T::Type{<:Integer}) -> T + + Find `y::T` such that `x` ≡ `y` (mod n), where n is the number of integers representable + in `T`, and `y` is an integer in `[typemin(T),typemax(T)]`. + If `T` can represent any integer (e.g. `T == BigInt`), then this operation corresponds to + a conversion to `T`. + + ```jldoctest + julia> 129 % Int8 + -127 + ``` + """ -> $fname(x::Integer, T::Type{<:Integer})) + end end rem(x::T, ::Type{T}) where {T<:Integer} = x From 8e1deb293a183c2aa91e48cbd697c821022bdcac Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 17 May 2017 15:48:47 -0400 Subject: [PATCH 0866/1534] inference: move magic parameter value to the inference params block --- base/inference.jl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 437dd6f995025..9f73259dafcf0 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -15,6 +15,7 @@ struct InferenceParams inlining::Bool # parameters limiting potentially-infinite types (configurable) + MAX_METHODS::Int MAX_TUPLETYPE_LEN::Int MAX_TUPLE_DEPTH::Int MAX_TUPLE_SPLAT::Int @@ -24,12 +25,13 @@ struct InferenceParams # reasonable defaults function InferenceParams(world::UInt; inlining::Bool = inlining_enabled(), + max_methods::Int = 4, tupletype_len::Int = 15, tuple_depth::Int = 4, tuple_splat::Int = 16, union_splitting::Int = 4, apply_union_enum::Int = 8) - return new(world, inlining, tupletype_len, + return new(world, inlining, max_methods, tupletype_len, tuple_depth, tuple_splat, union_splitting, apply_union_enum) end end @@ -1280,7 +1282,7 @@ function abstract_call_gf_by_type(f::ANY, atype::ANY, sv::InferenceState) end min_valid = UInt[typemin(UInt)] max_valid = UInt[typemax(UInt)] - applicable = _methods_by_ftype(argtype, 4, sv.params.world, min_valid, max_valid) + applicable = _methods_by_ftype(argtype, sv.params.MAX_METHODS, sv.params.world, min_valid, max_valid) rettype = Bottom if applicable === false # this means too many methods matched From 4f1b479d755bad5d8e36a0d6a7ce3c70bcbbe484 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 16 May 2017 13:25:57 -0400 Subject: [PATCH 0867/1534] fix definition of ntuple with a Val argument to not expect inference to be non-terminating this same issue applied to several other similar functions similarly, need to avoid nesting the use of functional code (like map) too deeply inside the array code to avoid the appearance of indeterminate recursion in inference --- base/abstractarray.jl | 50 ++++++------ base/array.jl | 7 +- base/broadcast.jl | 25 +++--- base/multidimensional.jl | 7 +- base/sparse/higherorderfns.jl | 148 +++++++++++----------------------- base/sysimg.jl | 19 +++++ base/tuple.jl | 60 ++++---------- test/broadcast.jl | 26 +++--- 8 files changed, 137 insertions(+), 205 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 6b97d97c2327a..b408ab3397434 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -1160,30 +1160,32 @@ cat_similar(A::AbstractArray, T, shape) = similar(A, T, shape) cat_shape(dims, shape::Tuple) = shape @inline cat_shape(dims, shape::Tuple, nshape::Tuple, shapes::Tuple...) = - cat_shape(dims, _cshp(dims, (), shape, nshape), shapes...) - -_cshp(::Tuple{}, out, ::Tuple{}, ::Tuple{}) = out -_cshp(::Tuple{}, out, ::Tuple{}, nshape) = (out..., nshape...) -_cshp(dims, out, ::Tuple{}, ::Tuple{}) = (out..., map(b -> 1, dims)...) -@inline _cshp(dims, out, shape, ::Tuple{}) = - _cshp(tail(dims), (out..., shape[1] + dims[1]), tail(shape), ()) -@inline _cshp(dims, out, ::Tuple{}, nshape) = - _cshp(tail(dims), (out..., nshape[1]), (), tail(nshape)) -@inline function _cshp(::Tuple{}, out, shape, ::Tuple{}) - _cs(length(out) + 1, false, shape[1], 1) - _cshp((), (out..., 1), tail(shape), ()) -end -@inline function _cshp(::Tuple{}, out, shape, nshape) - next = _cs(length(out) + 1, false, shape[1], nshape[1]) - _cshp((), (out..., next), tail(shape), tail(nshape)) -end -@inline function _cshp(dims, out, shape, nshape) - next = _cs(length(out) + 1, dims[1], shape[1], nshape[1]) - _cshp(tail(dims), (out..., next), tail(shape), tail(nshape)) -end - -_cs(d, concat, a, b) = concat ? (a + b) : (a == b ? a : throw(DimensionMismatch(string( - "mismatch in dimension ", d, " (expected ", a, " got ", b, ")")))) + cat_shape(dims, _cshp(1, dims, shape, nshape), shapes...) + +_cshp(ndim::Int, ::Tuple{}, ::Tuple{}, ::Tuple{}) = () +_cshp(ndim::Int, ::Tuple{}, ::Tuple{}, nshape) = nshape +_cshp(ndim::Int, dims, ::Tuple{}, ::Tuple{}) = ntuple(b -> 1, Val{length(dims)}) +@inline _cshp(ndim::Int, dims, shape, ::Tuple{}) = + (shape[1] + dims[1], _cshp(ndim + 1, tail(dims), tail(shape), ())...) +@inline _cshp(ndim::Int, dims, ::Tuple{}, nshape) = + (nshape[1], _cshp(ndim + 1, tail(dims), (), tail(nshape))...) +@inline function _cshp(ndim::Int, ::Tuple{}, shape, ::Tuple{}) + _cs(ndim, shape[1], 1) + (1, _cshp(ndim + 1, (), tail(shape), ())...) +end +@inline function _cshp(ndim::Int, ::Tuple{}, shape, nshape) + next = _cs(ndim, shape[1], nshape[1]) + (next, _cshp(ndim + 1, (), tail(shape), tail(nshape))...) +end +@inline function _cshp(ndim::Int, dims, shape, nshape) + a = shape[1] + b = nshape[1] + next = dims[1] ? a + b : _cs(ndim, a, b) + (next, _cshp(ndim + 1, tail(dims), tail(shape), tail(nshape))...) +end + +_cs(d, a, b) = (a == b ? a : throw(DimensionMismatch( + "mismatch in dimension $d (expected $a got $b)"))) dims2cat{n}(::Type{Val{n}}) = ntuple(i -> (i == n), Val{n}) dims2cat(dims) = ntuple(i -> (i in dims), maximum(dims)) diff --git a/base/array.jl b/base/array.jl index e5dea7bc703b8..bbb2c3ec72a8d 100644 --- a/base/array.jl +++ b/base/array.jl @@ -73,12 +73,7 @@ end size(a::Array, d) = arraysize(a, d) size(a::Vector) = (arraysize(a,1),) size(a::Matrix) = (arraysize(a,1), arraysize(a,2)) -size(a::Array) = (@_inline_meta; _size((), a)) -_size(out::NTuple{N}, A::Array{_,N}) where {_,N} = out -function _size(out::NTuple{M}, A::Array{_,N}) where _ where M where N - @_inline_meta - _size((out..., size(A,M+1)), A) -end +size(a::Array{<:Any,N}) where {N} = (@_inline_meta; ntuple(M -> size(a, M), Val{N})) asize_from(a::Array, n) = n > ndims(a) ? () : (arraysize(a,n), asize_from(a, n+1)...) diff --git a/base/broadcast.jl b/base/broadcast.jl index 2d98b4031b0d9..44acd0569de02 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -45,23 +45,22 @@ promote_containertype(::Type{T}, ::Type{T}) where {T} = T ## Calculate the broadcast indices of the arguments, or error if incompatible # array inputs broadcast_indices() = () -broadcast_indices(A) = broadcast_indices(containertype(A), A) -broadcast_indices(::ScalarType, A) = () -broadcast_indices(::Type{Tuple}, A) = (OneTo(length(A)),) -broadcast_indices(::Type{Array}, A::Ref) = () -broadcast_indices(::Type{Array}, A) = indices(A) -@inline broadcast_indices(A, B...) = broadcast_shape((), broadcast_indices(A), map(broadcast_indices, B)...) +broadcast_indices(A) = _broadcast_indices(containertype(A), A) +@inline broadcast_indices(A, B...) = broadcast_shape(broadcast_indices(A), broadcast_indices(B...)) +_broadcast_indices(::Type, A) = () +_broadcast_indices(::Type{Tuple}, A) = (OneTo(length(A)),) +_broadcast_indices(::Type{Array}, A::Ref) = () +_broadcast_indices(::Type{Array}, A) = indices(A) # shape (i.e., tuple-of-indices) inputs broadcast_shape(shape::Tuple) = shape -@inline broadcast_shape(shape::Tuple, shape1::Tuple, shapes::Tuple...) = broadcast_shape(_bcs((), shape, shape1), shapes...) +@inline broadcast_shape(shape::Tuple, shape1::Tuple, shapes::Tuple...) = broadcast_shape(_bcs(shape, shape1), shapes...) # _bcs consolidates two shapes into a single output shape -_bcs(out, ::Tuple{}, ::Tuple{}) = out -@inline _bcs(out, ::Tuple{}, newshape) = _bcs((out..., newshape[1]), (), tail(newshape)) -@inline _bcs(out, shape, ::Tuple{}) = _bcs((out..., shape[1]), tail(shape), ()) -@inline function _bcs(out, shape, newshape) - newout = _bcs1(shape[1], newshape[1]) - _bcs((out..., newout), tail(shape), tail(newshape)) +_bcs(::Tuple{}, ::Tuple{}) = () +@inline _bcs(::Tuple{}, newshape::Tuple) = (newshape[1], _bcs((), tail(newshape))...) +@inline _bcs(shape::Tuple, ::Tuple{}) = (shape[1], _bcs(tail(shape), ())...) +@inline function _bcs(shape::Tuple, newshape::Tuple) + return (_bcs1(shape[1], newshape[1]), _bcs(tail(shape), tail(newshape))...) end # _bcs1 handles the logic for a single dimension _bcs1(a::Integer, b::Integer) = a == 1 ? b : (b == 1 ? a : (a == b ? a : throw(DimensionMismatch("arrays could not be broadcast to a common size")))) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index e85400ebd355a..a3b5ef5a97658 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -138,9 +138,10 @@ module IteratorsMD eachindex(::IndexCartesian, A::AbstractArray) = CartesianRange(indices(A)) @inline eachindex(::IndexCartesian, A::AbstractArray, B::AbstractArray...) = - CartesianRange(maxsize((), A, B...)) - maxsize(sz) = sz - @inline maxsize(sz, A, B...) = maxsize(maxt(sz, size(A)), B...) + CartesianRange(maxsize(A, B...)) + maxsize() = () + @inline maxsize(A) = size(A) + @inline maxsize(A, B...) = maxt(size(A), maxsize(B...)) @inline maxt(a::Tuple{}, b::Tuple{}) = () @inline maxt(a::Tuple{}, b::Tuple) = b @inline maxt(a::Tuple, b::Tuple{}) = a diff --git a/base/sparse/higherorderfns.jl b/base/sparse/higherorderfns.jl index 3e70ec228410a..87c83069e3299 100644 --- a/base/sparse/higherorderfns.jl +++ b/base/sparse/higherorderfns.jl @@ -6,7 +6,8 @@ module HigherOrderFns # particularly map[!]/broadcast[!] for SparseVectors and SparseMatrixCSCs at present. import Base: map, map!, broadcast, broadcast! import Base.Broadcast: _containertype, promote_containertype, - broadcast_indices, broadcast_c, broadcast_c! + broadcast_indices, _broadcast_indices, + broadcast_c, broadcast_c! using Base: front, tail, to_shape using ..SparseArrays: SparseVector, SparseMatrixCSC, AbstractSparseVector, @@ -325,10 +326,6 @@ function _map_zeropres!(f::Tf, C::SparseVecOrMat, As::Vararg{SparseVecOrMat,N}) rows = _rowforind_all(rowsentinel, ks, stopks, As) activerow = min(rows...) while activerow < rowsentinel - # activerows = _isactiverow_all(activerow, rows) - # Cx = f(_gatherargs(activerows, ks, As)...) - # ks = _updateind_all(activerows, ks) - # rows = _updaterow_all(rowsentinel, activerows, rows, ks, stopks, As) vals, ks, rows = _fusedupdate_all(rowsentinel, activerow, rows, ks, stopks, As) Cx = f(vals...) if !_iszero(Cx) @@ -359,10 +356,6 @@ function _map_notzeropres!(f::Tf, fillvalue, C::SparseVecOrMat, As::Vararg{Spars rows = _rowforind_all(rowsentinel, ks, stopks, As) activerow = min(rows...) while activerow < rowsentinel - # activerows = _isactiverow_all(activerow, rows) - # Cx = f(_gatherargs(activerows, ks, As)...) - # ks = _updateind_all(activerows, ks) - # rows = _updaterow_all(rowsentinel, activerows, rows, ks, stopks, As) vals, ks, rows = _fusedupdate_all(rowsentinel, activerow, rows, ks, stopks, As) Cx = f(vals...) Cx != fillvalue && (storedvals(C)[jo + activerow] = Cx) @@ -371,6 +364,7 @@ function _map_notzeropres!(f::Tf, fillvalue, C::SparseVecOrMat, As::Vararg{Spars end return C end + # helper methods for map/map! methods just above @inline _colstartind(j, A) = colstartind(A, j) @inline _colstartind_all(j, ::Tuple{}) = () @@ -388,28 +382,7 @@ end @inline _rowforind_all(rowsentinel, ks, stopks, As) = ( _rowforind(rowsentinel, first(ks), first(stopks), first(As)), _rowforind_all(rowsentinel, tail(ks), tail(stopks), tail(As))...) -# fusing the following defs. avoids a few branches, yielding 5-30% runtime reduction -# @inline _isactiverow(activerow, row) = row == activerow -# @inline _isactiverow_all(activerow, ::Tuple{}) = () -# @inline _isactiverow_all(activerow, rows) = ( -# _isactiverow(activerow, first(rows)), -# _isactiverow_all(activerow, tail(rows))...) -# @inline _gatherarg(isactiverow, k, A) = isactiverow ? storedvals(A)[k] : zero(eltype(A)) -# @inline _gatherargs(::Tuple{}, ::Tuple{}, ::Tuple{}) = () -# @inline _gatherargs(activerows, ks, As) = ( -# _gatherarg(first(activerows), first(ks), first(As)), -# _gatherargs(tail(activerows), tail(ks), tail(As))...) -# @inline _updateind(isactiverow, k) = isactiverow ? (k + oneunit(k)) : k -# @inline _updateind_all(::Tuple{}, ::Tuple{}) = () -# @inline _updateind_all(activerows, ks) = ( -# _updateind(first(activerows), first(ks)), -# _updateind_all(tail(activerows), tail(ks))...) -# @inline _updaterow(rowsentinel, isrowactive, presrow, k, stopk, A) = -# isrowactive ? (k < stopk ? storedinds(A)[k] : oftype(presrow, rowsentinel)) : presrow -# @inline _updaterow_all(rowsentinel, ::Tuple{}, ::Tuple{}, ::Tuple{}, ::Tuple{}, ::Tuple{}) = () -# @inline _updaterow_all(rowsentinel, activerows, rows, ks, stopks, As) = ( -# _updaterow(rowsentinel, first(activerows), first(rows), first(ks), first(stopks), first(As)), -# _updaterow_all(rowsentinel, tail(activerows), tail(rows), tail(ks), tail(stopks), tail(As))...) + @inline function _fusedupdate(rowsentinel, activerow, row, k, stopk, A) # returns (val, nextk, nextrow) if row == activerow @@ -419,14 +392,11 @@ end (zero(eltype(A)), k, row) end end -@inline _fusedupdate_all(rowsentinel, activerow, rows, ks, stopks, As) = - _fusedupdate_all((#=vals=#), (#=nextks=#), (#=nextrows=#), rowsentinel, activerow, rows, ks, stopks, As) -@inline _fusedupdate_all(vals, nextks, nextrows, rowsent, activerow, ::Tuple{}, ::Tuple{}, ::Tuple{}, ::Tuple{}) = - (vals, nextks, nextrows) -@inline function _fusedupdate_all(vals, nextks, nextrows, rowsentinel, activerow, rows, ks, stopks, As) +@inline _fusedupdate_all(rowsentinel, activerow, ::Tuple{}, ::Tuple{}, ::Tuple{}, ::Tuple{}) = ((#=vals=#), (#=nextks=#), (#=nextrows=#)) +@inline function _fusedupdate_all(rowsentinel, activerow, rows, ks, stopks, As) val, nextk, nextrow = _fusedupdate(rowsentinel, activerow, first(rows), first(ks), first(stopks), first(As)) - return _fusedupdate_all((vals..., val), (nextks..., nextk), (nextrows..., nextrow), - rowsentinel, activerow, tail(rows), tail(ks), tail(stopks), tail(As)) + vals, nextks, nextrows = _fusedupdate_all(rowsentinel, activerow, tail(rows), tail(ks), tail(stopks), tail(As)) + return ((val, vals...), (nextk, nextks...), (nextrow, nextrows...)) end @@ -803,10 +773,6 @@ function _broadcast_zeropres!(f::Tf, C::SparseVecOrMat, As::Vararg{SparseVecOrMa activerow = min(rows...) if _iszero(defaultCx) # zero-preserving column scan while activerow < rowsentinel - # activerows = _isactiverow_all(activerow, rows) - # Cx = f(_gatherbcargs(activerows, defargs, ks, As)...) - # ks = _updateind_all(activerows, ks) - # rows = _updaterow_all(rowsentinel, activerows, rows, ks, stopks, As) args, ks, rows = _fusedupdatebc_all(rowsentinel, activerow, rows, defargs, ks, stopks, As) Cx = f(args...) if !_iszero(Cx) @@ -820,10 +786,6 @@ function _broadcast_zeropres!(f::Tf, C::SparseVecOrMat, As::Vararg{SparseVecOrMa else # zero-non-preserving column scan for Ci in 1:numrows(C) if Ci == activerow - # activerows = _isactiverow_all(activerow, rows) - # Cx = f(_gatherbcargs(activerows, defargs, ks, As)...) - # ks = _updateind_all(activerows, ks) - # rows = _updaterow_all(rowsentinel, activerows, rows, ks, stopks, As) args, ks, rows = _fusedupdatebc_all(rowsentinel, activerow, rows, defargs, ks, stopks, As) Cx = f(args...) activerow = min(rows...) @@ -864,10 +826,6 @@ function _broadcast_notzeropres!(f::Tf, fillvalue, C::SparseVecOrMat, As::Vararg activerow = min(rows...) if defaultCx == fillvalue # fillvalue-preserving column scan while activerow < rowsentinel - # activerows = _isactiverow_all(activerow, rows) - # Cx = f(_gatherbcargs(activerows, defargs, ks, As)...) - # ks = _updateind_all(activerows, ks) - # rows = _updaterow_all(rowsentinel, activerows, rows, ks, stopks, As) args, ks, rows = _fusedupdatebc_all(rowsentinel, activerow, rows, defargs, ks, stopks, As) Cx = f(args...) Cx != fillvalue && (storedvals(C)[jo + activerow] = Cx) @@ -876,10 +834,6 @@ function _broadcast_notzeropres!(f::Tf, fillvalue, C::SparseVecOrMat, As::Vararg else # fillvalue-non-preserving column scan for Ci in 1:numrows(C) if Ci == activerow - # activerows = _isactiverow_all(activerow, rows) - # Cx = f(_gatherbcargs(activerows, defargs, ks, As)...) - # ks = _updateind_all(activerows, ks) - # rows = _updaterow_all(rowsentinel, activerows, rows, ks, stopks, As) args, ks, rows = _fusedupdatebc_all(rowsentinel, activerow, rows, defargs, ks, stopks, As) Cx = f(args...) activerow = min(rows...) @@ -892,6 +846,7 @@ function _broadcast_notzeropres!(f::Tf, fillvalue, C::SparseVecOrMat, As::Vararg end return C end + # helper method for broadcast/broadcast! methods just above @inline _expandsvert(C, A) = numrows(A) != numrows(C) @inline _expandsvert_all(C, ::Tuple{}) = () @@ -926,28 +881,6 @@ end @inline _defargforcol_all(j, isemptys, expandsverts, ks, As) = ( _defargforcol(j, first(isemptys), first(expandsverts), first(ks), first(As)), _defargforcol_all(j, tail(isemptys), tail(expandsverts), tail(ks), tail(As))...) -# fusing the following defs. avoids a few branches and construction of a tuple, yielding 1-20% runtime reduction -# @inline _isactiverow(activerow, row) = row == activerow -# @inline _isactiverow_all(activerow, ::Tuple{}) = () -# @inline _isactiverow_all(activerow, rows) = ( -# _isactiverow(activerow, first(rows)), -# _isactiverow_all(activerow, tail(rows))...) -# @inline _gatherbcarg(isactiverow, defarg, k, A) = isactiverow ? storedvals(A)[k] : defarg -# @inline _gatherbcargs(::Tuple{}, ::Tuple{}, ::Tuple{}, ::Tuple{}) = () -# @inline _gatherbcargs(activerows, defargs, ks, As) = ( -# _gatherbcarg(first(activerows), first(defargs), first(ks), first(As)), -# _gatherbcargs(tail(activerows), tail(defargs), tail(ks), tail(As))...) -# @inline _updateind(isactiverow, k) = isactiverow ? (k + oneunit(k)) : k -# @inline _updateind_all(::Tuple{}, ::Tuple{}) = () -# @inline _updateind_all(activerows, ks) = ( -# _updateind(first(activerows), first(ks)), -# _updateind_all(tail(activerows), tail(ks))...) -# @inline _updaterow(rowsentinel, isrowactive, presrow, k, stopk, A) = -# isrowactive ? (k < stopk ? storedinds(A)[k] : oftype(presrow, rowsentinel)) : presrow -# @inline _updaterow_all(rowsentinel, ::Tuple{}, ::Tuple{}, ::Tuple{}, ::Tuple{}, ::Tuple{}) = () -# @inline _updaterow_all(rowsentinel, activerows, rows, ks, stopks, As) = ( -# _updaterow(rowsentinel, first(activerows), first(rows), first(ks), first(stopks), first(As)), -# _updaterow_all(rowsentinel, tail(activerows), tail(rows), tail(ks), tail(stopks), tail(As))...) @inline function _fusedupdatebc(rowsentinel, activerow, row, defarg, k, stopk, A) # returns (val, nextk, nextrow) if row == activerow @@ -957,21 +890,18 @@ end (defarg, k, row) end end -@inline _fusedupdatebc_all(rowsentinel, activerow, rows, defargs, ks, stopks, As) = - _fusedupdatebc_all((#=vals=#), (#=nextks=#), (#=nextrows=#), rowsentinel, activerow, rows, defargs, ks, stopks, As) -@inline _fusedupdatebc_all(vals, nextks, nextrows, rowsent, activerow, ::Tuple{}, ::Tuple{}, ::Tuple{}, ::Tuple{}, ::Tuple{}) = - (vals, nextks, nextrows) -@inline function _fusedupdatebc_all(vals, nextks, nextrows, rowsentinel, activerow, rows, defargs, ks, stopks, As) +@inline _fusedupdatebc_all(rowsent, activerow, ::Tuple{}, ::Tuple{}, ::Tuple{}, ::Tuple{}, ::Tuple{}) = ((#=vals=#), (#=nextks=#), (#=nextrows=#)) +@inline function _fusedupdatebc_all(rowsentinel, activerow, rows, defargs, ks, stopks, As) val, nextk, nextrow = _fusedupdatebc(rowsentinel, activerow, first(rows), first(defargs), first(ks), first(stopks), first(As)) - return _fusedupdatebc_all((vals..., val), (nextks..., nextk), (nextrows..., nextrow), - rowsentinel, activerow, tail(rows), tail(defargs), tail(ks), tail(stopks), tail(As)) + vals, nextks, nextrows = _fusedupdatebc_all(rowsentinel, activerow, tail(rows), tail(defargs), tail(ks), tail(stopks), tail(As)) + return ((val, vals...), (nextk, nextks...), (nextrow, nextrows...)) end # (10) broadcast[!] over combinations of broadcast scalars and sparse vectors/matrices # broadcast shape promotion for combinations of sparse arrays and other types -broadcast_indices(::Type{AbstractSparseArray}, A) = indices(A) +_broadcast_indices(::Type{AbstractSparseArray}, A) = indices(A) # broadcast container type promotion for combinations of sparse arrays and other types _containertype(::Type{<:SparseVecOrMat}) = AbstractSparseArray # combinations of sparse arrays with broadcast scalars should yield sparse arrays @@ -996,22 +926,38 @@ end # evaluated f) and a reduced argument tuple (passedargstup) containing only the sparse # vectors/matrices in mixedargs in their orginal order, and such that the result of # broadcast(parevalf, passedargstup...) is broadcast(f, mixedargs...) -@inline capturescalars(f, mixedargs) = - capturescalars((passed, tofill) -> f(tofill...), (), mixedargs...) -# Recursion cases for capturescalars -@inline capturescalars(f, passedargstup, scalararg, mixedargs...) = - capturescalars(capturescalar(f, scalararg), passedargstup, mixedargs...) -@inline capturescalars(f, passedargstup, nonscalararg::SparseVecOrMat, mixedargs...) = - capturescalars(passnonscalar(f), (passedargstup..., nonscalararg), mixedargs...) -@inline passnonscalar(f) = (passed, tofill) -> f(Base.front(passed), (last(passed), tofill...)) -@inline capturescalar(f, scalararg) = (passed, tofill) -> f(passed, (scalararg, tofill...)) -# Base cases for capturescalars -@inline capturescalars(f, passedargstup, scalararg) = - (capturelastscalar(f, scalararg), passedargstup) -@inline capturescalars(f, passedargstup, nonscalararg::SparseVecOrMat) = - (passlastnonscalar(f), (passedargstup..., nonscalararg)) -@inline passlastnonscalar(f) = (passed...) -> f(Base.front(passed), (last(passed),)) -@inline capturelastscalar(f, scalararg) = (passed...) -> f(passed, (scalararg,)) +@inline function capturescalars(f, mixedargs) + let makeargs = _capturescalars(mixedargs...), + parevalf = (passed...) -> f(makeargs(passed...)...), + passedsrcargstup = _capturenonscalars(mixedargs...) + return (parevalf, passedsrcargstup) + end +end + +@inline _capturenonscalars(nonscalararg::SparseVecOrMat, mixedargs...) = + (nonscalararg, _capturenonscalars(mixedargs...)...) +@inline _capturenonscalars(scalararg, mixedargs...) = + _capturenonscalars(mixedargs...) +@inline _capturenonscalars() = () + +@inline _capturescalars(nonscalararg::SparseVecOrMat, mixedargs...) = + let f = _capturescalars(mixedargs...) + (head, tail...) -> (head, f(tail...)...) # pass-through + end +@inline _capturescalars(scalararg, mixedargs...) = + let f = _capturescalars(mixedargs...) + (tail...) -> (scalararg, f(tail...)...) # add scalararg + end +# TODO: use the implicit version once inference can handle it +# handle too-many-arguments explicitly +@inline function _capturescalars() + too_many_arguments() = () + too_many_arguments(tail...) = throw(ArgumentError("too many")) +end +#@inline _capturescalars(nonscalararg::SparseVecOrMat) = +# (head,) -> (head,) # pass-through +#@inline _capturescalars(scalararg) = +# () -> (scalararg,) # add scalararg # NOTE: The following two method definitions work around #19096. broadcast(f::Tf, ::Type{T}, A::SparseMatrixCSC) where {Tf,T} = broadcast(y -> f(T, y), A) @@ -1039,7 +985,7 @@ struct PromoteToSparse end # broadcast containertype definitions for structured matrices StructuredMatrix = Union{Diagonal,Bidiagonal,Tridiagonal,SymTridiagonal} _containertype(::Type{<:StructuredMatrix}) = PromoteToSparse -broadcast_indices(::Type{PromoteToSparse}, A) = indices(A) +_broadcast_indices(::Type{PromoteToSparse}, A) = indices(A) # combinations explicitly involving Tuples and PromoteToSparse collections # divert to the generic AbstractArray broadcast code diff --git a/base/sysimg.jl b/base/sysimg.jl index acfb4c7b68ee4..39c787e8b5359 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -195,6 +195,25 @@ include("nullable.jl") include("broadcast.jl") importall .Broadcast +# define the real ntuple functions +@generated function ntuple(f::F, ::Type{Val{N}}) where {F,N} + Core.typeassert(N, Int) + (N >= 0) || return :(throw($(ArgumentError(string("tuple length should be ≥0, got ", N))))) + return quote + $(Expr(:meta, :inline)) + @nexprs $N i -> t_i = f(i) + @ncall $N tuple t + end +end +@generated function fill_to_length(t::Tuple, val, ::Type{Val{N}}) where {N} + M = length(t.parameters) + M > N && return :(throw($(ArgumentError("input tuple of length $M, requested $N")))) + return quote + $(Expr(:meta, :inline)) + (t..., $(Any[ :val for i = (M + 1):N ]...)) + end +end + # base64 conversions (need broadcast) include("base64.jl") importall .Base64 diff --git a/base/tuple.jl b/base/tuple.jl index dc041a47937fb..ee60f5169d79c 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -24,12 +24,13 @@ getindex(t::Tuple, r::AbstractArray{<:Any,1}) = ([t[ri] for ri in r]...) getindex(t::Tuple, b::AbstractArray{Bool,1}) = length(b) == length(t) ? getindex(t,find(b)) : throw(BoundsError(t, b)) # returns new tuple; N.B.: becomes no-op if i is out-of-bounds -setindex(x::Tuple, v, i::Integer) = _setindex((), x, v, i::Integer) -function _setindex(y::Tuple, r::Tuple, v, i::Integer) +setindex(x::Tuple, v, i::Integer) = (@_inline_meta; _setindex(v, i, x...)) +function _setindex(v, i::Integer, first, tail...) @_inline_meta - _setindex((y..., ifelse(length(y) + 1 == i, v, first(r))), tail(r), v, i) + return (ifelse(i == 1, v, first), _setindex(v, i - 1, tail...)...) end -_setindex(y::Tuple, r::Tuple{}, v, i::Integer) = y +_setindex(v, i::Integer) = () + ## iterating ## @@ -126,36 +127,11 @@ function _ntuple(f, n) ([f(i) for i = 1:n]...) end -# inferrable ntuple -ntuple(f, ::Type{Val{0}}) = (@_inline_meta; ()) +# inferrable ntuple (enough for bootstrapping) +ntuple(f, ::Type{Val{0}}) = () ntuple(f, ::Type{Val{1}}) = (@_inline_meta; (f(1),)) ntuple(f, ::Type{Val{2}}) = (@_inline_meta; (f(1), f(2))) ntuple(f, ::Type{Val{3}}) = (@_inline_meta; (f(1), f(2), f(3))) -ntuple(f, ::Type{Val{4}}) = (@_inline_meta; (f(1), f(2), f(3), f(4))) -ntuple(f, ::Type{Val{5}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5))) -ntuple(f, ::Type{Val{6}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6))) -ntuple(f, ::Type{Val{7}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7))) -ntuple(f, ::Type{Val{8}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8))) -ntuple(f, ::Type{Val{9}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9))) -ntuple(f, ::Type{Val{10}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10))) -ntuple(f, ::Type{Val{11}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10), f(11))) -ntuple(f, ::Type{Val{12}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10), f(11), f(12))) -ntuple(f, ::Type{Val{13}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10), f(11), f(12), f(13))) -ntuple(f, ::Type{Val{14}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10), f(11), f(12), f(13), f(14))) -ntuple(f, ::Type{Val{15}}) = (@_inline_meta; (f(1), f(2), f(3), f(4), f(5), f(6), f(7), f(8), f(9), f(10), f(11), f(12), f(13), f(14), f(15))) - -function ntuple(f::F, ::Type{Val{N}}) where {F,N} - Core.typeassert(N, Int) - (N >= 0) || throw(ArgumentError(string("tuple length should be ≥0, got ", N))) - _ntuple((), f, Val{N}) -end - -# Build up the output until it has length N -_ntuple(out::NTuple{N,Any}, f::F, ::Type{Val{N}}) where {F,N} = out -function _ntuple(out::NTuple{M,Any}, f::F, ::Type{Val{N}}) where {F,N,M} - @_inline_meta - _ntuple((out..., f(M+1)), f, Val{N}) -end # 1 argument function map(f, t::Tuple{}) = () @@ -211,20 +187,14 @@ end # type-stable padding -fill_to_length(t::Tuple, val, ::Type{Val{N}}) where {N} = _ftl((), val, Val{N}, t...) -_ftl(out::NTuple{N,Any}, val, ::Type{Val{N}}) where {N} = out -function _ftl(out::NTuple{N,Any}, val, ::Type{Val{N}}, t...) where N - @_inline_meta - throw(ArgumentError("input tuple of length $(N+length(t)), requested $N")) -end -function _ftl(out, val, ::Type{Val{N}}, t1, t...) where N - @_inline_meta - _ftl((out..., t1), val, Val{N}, t...) -end -function _ftl(out, val, ::Type{Val{N}}) where N - @_inline_meta - _ftl((out..., val), val, Val{N}) -end +fill_to_length(t::NTuple{N,Any}, val, ::Type{Val{N}}) where {N} = t +fill_to_length(t::Tuple{}, val, ::Type{Val{1}}) = (val,) +fill_to_length(t::Tuple{Any}, val, ::Type{Val{2}}) = (t..., val) +fill_to_length(t::Tuple{}, val, ::Type{Val{2}}) = (val, val) +#function fill_to_length(t::Tuple, val, ::Type{Val{N}}) where {N} +# @_inline_meta +# return (t..., ntuple(i -> val, N - length(t))...) +#end # constructing from an iterator diff --git a/test/broadcast.jl b/test/broadcast.jl index 8e89a12e65a89..bb7fdeaf3db1c 100644 --- a/test/broadcast.jl +++ b/test/broadcast.jl @@ -3,21 +3,21 @@ module TestBroadcastInternals using Base.Broadcast: broadcast_indices, check_broadcast_indices, - check_broadcast_shape, newindex, _bcs, _bcsm + check_broadcast_shape, newindex, _bcs using Base: Test, OneTo -@test @inferred(_bcs((), (3,5), (3,5))) == (3,5) -@test @inferred(_bcs((), (3,1), (3,5))) == (3,5) -@test @inferred(_bcs((), (3,), (3,5))) == (3,5) -@test @inferred(_bcs((), (3,5), (3,))) == (3,5) -@test_throws DimensionMismatch _bcs((), (3,5), (4,5)) -@test_throws DimensionMismatch _bcs((), (3,5), (3,4)) -@test @inferred(_bcs((), (-1:1, 2:5), (-1:1, 2:5))) == (-1:1, 2:5) -@test @inferred(_bcs((), (-1:1, 2:5), (1, 2:5))) == (-1:1, 2:5) -@test @inferred(_bcs((), (-1:1, 1), (1, 2:5))) == (-1:1, 2:5) -@test @inferred(_bcs((), (-1:1,), (-1:1, 2:5))) == (-1:1, 2:5) -@test_throws DimensionMismatch _bcs((), (-1:1, 2:6), (-1:1, 2:5)) -@test_throws DimensionMismatch _bcs((), (-1:1, 2:5), (2, 2:5)) +@test @inferred(_bcs((3,5), (3,5))) == (3,5) +@test @inferred(_bcs((3,1), (3,5))) == (3,5) +@test @inferred(_bcs((3,), (3,5))) == (3,5) +@test @inferred(_bcs((3,5), (3,))) == (3,5) +@test_throws DimensionMismatch _bcs((3,5), (4,5)) +@test_throws DimensionMismatch _bcs((3,5), (3,4)) +@test @inferred(_bcs((-1:1, 2:5), (-1:1, 2:5))) == (-1:1, 2:5) +@test @inferred(_bcs((-1:1, 2:5), (1, 2:5))) == (-1:1, 2:5) +@test @inferred(_bcs((-1:1, 1), (1, 2:5))) == (-1:1, 2:5) +@test @inferred(_bcs((-1:1,), (-1:1, 2:5))) == (-1:1, 2:5) +@test_throws DimensionMismatch _bcs((-1:1, 2:6), (-1:1, 2:5)) +@test_throws DimensionMismatch _bcs((-1:1, 2:5), (2, 2:5)) @test @inferred(broadcast_indices(zeros(3,4), zeros(3,4))) == (OneTo(3),OneTo(4)) @test @inferred(broadcast_indices(zeros(3,4), zeros(3))) == (OneTo(3),OneTo(4)) From 7d92d6dcbf668279c7d4e976303c446e3603ea37 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 18 May 2017 12:04:19 -0400 Subject: [PATCH 0868/1534] inferrable version of tuple front() --- base/tuple.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/base/tuple.jl b/base/tuple.jl index ee60f5169d79c..f78502525a839 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -83,13 +83,13 @@ safe_tail(t::Tuple{}) = () function front(t::Tuple) @_inline_meta - _front((), t...) + _front(t...) end -front(::Tuple{}) = throw(ArgumentError("Cannot call front on an empty tuple")) -_front(out, v) = out -function _front(out, v, t...) +_front() = throw(ArgumentError("Cannot call front on an empty tuple")) +_front(v) = () +function _front(v, t...) @_inline_meta - _front((out..., v), t...) + (v, _front(t...)...) end ## mapping ## From 106cefa0b313cde4f7b332ebcb19faf98d5bfda0 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 18 May 2017 12:04:41 -0400 Subject: [PATCH 0869/1534] eliminate turing machine from size_strides --- base/abstractarray.jl | 12 +++++------- base/reshapedarray.jl | 6 +----- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index b408ab3397434..857409db27ef8 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -202,13 +202,11 @@ julia> strides(A) (1, 3, 12) ``` """ -strides(A::AbstractArray) = _strides((1,), A) -_strides(out::Tuple{Int}, A::AbstractArray{<:Any,0}) = () -_strides(out::NTuple{N,Int}, A::AbstractArray{<:Any,N}) where {N} = out -function _strides(out::NTuple{M,Int}, A::AbstractArray) where M - @_inline_meta - _strides((out..., out[M]*size(A, M)), A) -end +strides(A::AbstractArray) = size_to_strides(1, size(A)...) +@inline size_to_strides(s, d, sz...) = (s, size_to_strides(s * d, sz...)...) +size_to_strides(s, d) = (s,) +size_to_strides(s) = () + function isassigned(a::AbstractArray, i::Int...) try diff --git a/base/reshapedarray.jl b/base/reshapedarray.jl index 5109359421402..f93deb13ab264 100644 --- a/base/reshapedarray.jl +++ b/base/reshapedarray.jl @@ -148,7 +148,7 @@ _reshape(R::ReshapedArray, dims::Dims) = _reshape(R.parent, dims) function __reshape(p::Tuple{AbstractArray,IndexCartesian}, dims::Dims) parent = p[1] - strds = front(size_strides(parent)) + strds = front(size_to_strides(size(parent)..., 1)) strds1 = map(s->max(1,s), strds) # for resizing empty arrays mi = map(SignedMultiplicativeInverse, strds1) ReshapedArray(parent, dims, reverse(mi)) @@ -159,10 +159,6 @@ function __reshape(p::Tuple{AbstractArray,IndexLinear}, dims::Dims) ReshapedArray(parent, dims, ()) end -@inline size_strides(A::AbstractArray) = tail(size_strides((1,), size(A)...)) -size_strides(out::Tuple) = out -@inline size_strides(out, s, sz...) = size_strides((out..., out[end]*s), sz...) - size(A::ReshapedArray) = A.dims similar(A::ReshapedArray, eltype::Type, dims::Dims) = similar(parent(A), eltype, dims) IndexStyle(::Type{<:ReshapedArrayLF}) = IndexLinear() From a2e808166773e78e6bb2f1a61b975fba57044dbe Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 18 May 2017 12:35:30 -0400 Subject: [PATCH 0870/1534] eliminate turing machines from more array functions --- base/abstractarray.jl | 8 ++++---- base/permuteddimsarray.jl | 5 +---- base/reshapedarray.jl | 8 ++++---- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 857409db27ef8..994136c9e41a1 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -1668,15 +1668,15 @@ end function _sub2ind!(Iout, inds, Iinds, I) @_noinline_meta for i in Iinds - # Iout[i] = sub2ind(inds, map(Ij->Ij[i], I)...) + # Iout[i] = sub2ind(inds, map(Ij -> Ij[i], I)...) Iout[i] = sub2ind_vec(inds, i, I) end Iout end -sub2ind_vec(inds, i, I) = (@_inline_meta; _sub2ind_vec(inds, (), i, I...)) -_sub2ind_vec(inds, out, i, I1, I...) = (@_inline_meta; _sub2ind_vec(inds, (out..., I1[i]), i, I...)) -_sub2ind_vec(inds, out, i) = (@_inline_meta; sub2ind(inds, out...)) +sub2ind_vec(inds, i, I) = (@_inline_meta; sub2ind(inds, _sub2ind_vec(i, I...)...)) +_sub2ind_vec(i, I1, I...) = (@_inline_meta; (I1[i], _sub2ind_vec(i, I...)...)) +_sub2ind_vec(i) = () function ind2sub(inds::Union{DimsInteger{N},Indices{N}}, ind::AbstractVector{<:Integer}) where N M = length(ind) diff --git a/base/permuteddimsarray.jl b/base/permuteddimsarray.jl index c51b8cb34caff..7c483b8215a6b 100644 --- a/base/permuteddimsarray.jl +++ b/base/permuteddimsarray.jl @@ -74,10 +74,7 @@ end val end -# For some reason this is faster than ntuple(d->I[perm[d]], Val{N}) (#15276?) -@inline genperm(I::NTuple{N,Any}, perm::Dims{N}) where {N} = _genperm((), I, perm...) -_genperm(out, I) = out -@inline _genperm(out, I, p, perm...) = _genperm((out..., I[p]), I, perm...) +@inline genperm(I::NTuple{N,Any}, perm::Dims{N}) where {N} = ntuple(d -> I[perm[d]], Val{N}) @inline genperm(I, perm::AbstractVector{Int}) = genperm(I, (perm...,)) """ diff --git a/base/reshapedarray.jl b/base/reshapedarray.jl index f93deb13ab264..7a276188d66df 100644 --- a/base/reshapedarray.jl +++ b/base/reshapedarray.jl @@ -167,11 +167,11 @@ parentindexes(A::ReshapedArray) = map(s->1:s, size(parent(A))) reinterpret(::Type{T}, A::ReshapedArray, dims::Dims) where {T} = reinterpret(T, parent(A), dims) @inline ind2sub_rs(::Tuple{}, i::Int) = i -@inline ind2sub_rs(strds, i) = ind2sub_rs((), strds, i-1) -@inline ind2sub_rs(out, ::Tuple{}, ind) = (ind+1, out...) -@inline function ind2sub_rs(out, strds, ind) +@inline ind2sub_rs(strds, i) = _ind2sub_rs(strds, i - 1) +@inline _ind2sub_rs(::Tuple{}, ind) = (ind + 1,) +@inline function _ind2sub_rs(strds, ind) d, r = divrem(ind, strds[1]) - ind2sub_rs((d+1, out...), tail(strds), r) + (_ind2sub_rs(tail(strds), r)..., d + 1) end @inline function getindex(A::ReshapedArrayLF, index::Int) From 42877611c0f2db3ae84f33389a55bd24a2048760 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 18 May 2017 14:37:09 -0400 Subject: [PATCH 0871/1534] remove incorrect pure annotation from rdims and make it inferrable --- base/reshapedarray.jl | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/base/reshapedarray.jl b/base/reshapedarray.jl index 7a276188d66df..85c45e9e8739c 100644 --- a/base/reshapedarray.jl +++ b/base/reshapedarray.jl @@ -111,18 +111,25 @@ _throw_reshape_colon_dimmismatch(A, dims) = reshape(parent::AbstractArray{T,N}, ndims::Type{Val{N}}) where {T,N} = parent function reshape(parent::AbstractArray, ndims::Type{Val{N}}) where N - reshape(parent, rdims((), indices(parent), Val{N})) + reshape(parent, rdims(Val{N}, indices(parent))) end + # Move elements from inds to out until out reaches the desired # dimensionality N, either filling with OneTo(1) or collapsing the # product of trailing dims into the last element -@pure rdims(out::NTuple{N,Any}, inds::Tuple{}, ::Type{Val{N}}) where {N} = out -@pure function rdims(out::NTuple{N,Any}, inds::Tuple{Any, Vararg{Any}}, ::Type{Val{N}}) where N - l = length(last(out)) * prod(map(length, inds)) - (front(out)..., OneTo(l)) -end -@pure rdims(out::Tuple, inds::Tuple{}, ::Type{Val{N}}) where {N} = rdims((out..., OneTo(1)), (), Val{N}) -@pure rdims(out::Tuple, inds::Tuple{Any, Vararg{Any}}, ::Type{Val{N}}) where {N} = rdims((out..., first(inds)), tail(inds), Val{N}) +rdims_trailing(l, inds...) = length(l) * rdims_trailing(inds...) +rdims_trailing(l) = length(l) +rdims(out::Type{Val{N}}, inds::Tuple) where {N} = rdims(ntuple(i -> OneTo(1), Val{N}), inds) +rdims(out::Tuple{}, inds::Tuple{}) = () # N == 0, M == 0 +rdims(out::Tuple{}, inds::Tuple{Any}) = throw(ArgumentError("new dimensions cannot be empty")) # N == 0 +rdims(out::Tuple{}, inds::NTuple{M,Any}) where {M} = throw(ArgumentError("new dimensions cannot be empty")) # N == 0 +rdims(out::Tuple{Any}, inds::Tuple{}) = out # N == 1, M == 0 +rdims(out::NTuple{N,Any}, inds::Tuple{}) where {N} = out # N > 1, M == 0 +rdims(out::Tuple{Any}, inds::Tuple{Any}) = inds # N == 1, M == 1 +rdims(out::Tuple{Any}, inds::NTuple{M,Any}) where {M} = (OneTo(rdims_trailing(inds...)),) # N == 1, M > 1 +rdims(out::NTuple{N,Any}, inds::NTuple{N,Any}) where {N} = inds # N > 1, M == N +rdims(out::NTuple{N,Any}, inds::NTuple{M,Any}) where {N,M} = (first(inds), rdims(tail(out), tail(inds))...) # N > 1, M > 1, M != N + # _reshape on Array returns an Array _reshape(parent::Vector, dims::Dims{1}) = parent From c2c09977f6e7354f6341a21f668715bfb35f3edb Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Sat, 20 May 2017 17:36:29 +0900 Subject: [PATCH 0872/1534] limit maximum vector alignment to heap alignment --- src/cgutils.cpp | 6 +++++- src/datatype.c | 5 ++++- test/vecelement.jl | 54 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 06c06215dfad1..1793bee77bc97 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -524,7 +524,11 @@ static Type *julia_struct_to_llvm(jl_value_t *jt, jl_unionall_t *ua, bool *isbox #endif unsigned llvm_alignment = DL.getABITypeAlignment((Type*)jst->struct_decl); unsigned julia_alignment = jst->layout->alignment; - assert(llvm_alignment == julia_alignment); + // Check that the alignment adheres to the heap alignment. + assert(julia_alignment <= JL_SMALL_BYTE_ALIGNMENT); + // TODO: Fix alignment calculation in LLVM, as well as in the GC and the struct declaration + if (llvm_alignment <= JL_SMALL_BYTE_ALIGNMENT) + assert(julia_alignment == llvm_alignment); } #endif } diff --git a/src/datatype.c b/src/datatype.c index 0bf85c8af246a..ce7c46c24e790 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -310,7 +310,10 @@ void jl_compute_field_offsets(jl_datatype_t *st) // Some tuples become LLVM vectors with stronger alignment than what was calculated above. unsigned al = jl_special_vector_alignment(nfields, lastty); assert(al % alignm == 0); - if (al) + // JL_SMALL_BYTE_ALIGNMENT is the smallest alignment we can guarantee on the heap. + if (al > JL_SMALL_BYTE_ALIGNMENT) + alignm = JL_SMALL_BYTE_ALIGNMENT; + else if (al) alignm = al; } st->size = LLT_ALIGN(sz, alignm); diff --git a/test/vecelement.jl b/test/vecelement.jl index 95209b143c28b..e9a5e42957389 100644 --- a/test/vecelement.jl +++ b/test/vecelement.jl @@ -23,6 +23,13 @@ for i=1:20 end end +# Try various large tuple lengths and element types #20961 +for i in (34, 36, 48, 64, 72, 80, 96) + for t in [Bool, Int8, Int16, Int32, Int64, Float32, Float64] + call_iota(i,t) + end +end + # Another crash report for #15244 motivated this test. struct Bunch{N,T} elts::NTuple{N,Base.VecElement{T}} @@ -65,3 +72,50 @@ a[1] = Gr(5.0, Bunch((VecElement(6.0), VecElement(7.0))), 8.0) @test a[2] == Gr(1.0, Bunch((VecElement(2.0), VecElement(3.0))), 4.0) @test isa(VecElement((1,2)), VecElement{Tuple{Int,Int}}) + +# The following test mimic SIMD.jl +const _llvmtypes = Dict{DataType, String}( + Float64 => "double", + Float32 => "float", + Int32 => "i32", + Int64 => "i64" +) + +@generated function vecadd(x::Vec{N, T}, y::Vec{N, T}) where {N, T} + llvmT = _llvmtypes[T] + func = T <: AbstractFloat ? "fadd" : "add" + exp = """ + %3 = $(func) <$(N) x $(llvmT)> %0, %1 + ret <$(N) x $(llvmT)> %3 + """ + return quote + Base.@_inline_meta + Base.llvmcall($exp, Vec{$N, $T}, Tuple{Vec{$N, $T}, Vec{$N, $T}}, x, y) + end +end + +function f20961(x::Vector{Vec{N, T}}, y::Vector{Vec{N, T}}) where{N, T} + @inbounds begin + a = x[1] + b = y[1] + return vecadd(a, b) + end +end + +# Test various SIMD Vectors with known good sizes +for T in (Float64, Float32, Int64, Int32) + for N in 1:36 + # For some vectortypes Julia emits llvm arrays instead of vectors + if N % 7 == 0 || N % 11 == 0 || N % 13 == 0 || N % 15 == 0 || + N % 19 == 0 || N % 23 == 0 || N % 25 == 0 || N % 27 == 0 || + N % 29 == 0 || N % 31 == 0 + continue + end + a = ntuple(i->VecElement(T(i)), N) + result = ntuple(i-> VecElement(T(i+i)), N) + b = vecadd(a, a) + @test b == result + b = f20961([a], [a]) + @test b == result + end +end From 5115a380cd4bb77f6612608d1c9a3eca86ed412f Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Sun, 21 May 2017 18:00:40 +0900 Subject: [PATCH 0873/1534] introduce jl_datatype_align --- src/abi_arm.cpp | 2 +- src/abi_ppc64le.cpp | 2 +- src/array.c | 8 ++++---- src/ccall.cpp | 4 ++-- src/cgutils.cpp | 10 +++++----- src/codegen.cpp | 4 ++-- src/datatype.c | 6 +++--- src/intrinsics.cpp | 4 ++-- src/julia.h | 1 + src/runtime_intrinsics.c | 4 ++-- 10 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/abi_arm.cpp b/src/abi_arm.cpp index c89a24cd928ad..1a5d3d0651368 100644 --- a/src/abi_arm.cpp +++ b/src/abi_arm.cpp @@ -270,7 +270,7 @@ Type *preferred_llvm_type(jl_datatype_t *dt, bool isret) const override // For a Composite Type, the alignment of the copy will have 4-byte // alignment if its natural alignment is <= 4 and 8-byte alignment if // its natural alignment is >= 8 - size_t align = dt->layout->alignment; + size_t align = jl_datatype_align(dt); if (align < 4) align = 4; if (align > 8) diff --git a/src/abi_ppc64le.cpp b/src/abi_ppc64le.cpp index 5c4cc4b4d5b5b..a6ae101040b4c 100644 --- a/src/abi_ppc64le.cpp +++ b/src/abi_ppc64le.cpp @@ -144,7 +144,7 @@ Type *preferred_llvm_type(jl_datatype_t *dt, bool isret) const override // rewrite integer-sized (non-HFA) struct to an array // the bitsize of the integer gives the desired alignment if (size > 8) { - if (dt->layout->alignment <= 8) { + if (jl_datatype_align(dt) <= 8) { return ArrayType::get(T_int64, (size + 7) / 8); } else { diff --git a/src/array.c b/src/array.c index 97182ef1eab74..9cd3cd2dc0152 100644 --- a/src/array.c +++ b/src/array.c @@ -193,10 +193,10 @@ JL_DLLEXPORT jl_array_t *jl_reshape_array(jl_value_t *atype, jl_array_t *data, assert(store_unboxed(el_type) == !data->flags.ptrarray); if (!data->flags.ptrarray) { a->elsize = jl_datatype_size(el_type); - unsigned align = ((jl_datatype_t*)el_type)->layout->alignment; + unsigned align = jl_datatype_align(el_type); jl_value_t *ownerty = jl_typeof(owner); unsigned oldalign = (ownerty == (jl_value_t*)jl_string_type ? 1 : - ((jl_datatype_t*)jl_tparam0(ownerty))->layout->alignment); + jl_datatype_align(jl_tparam0(ownerty))); if (oldalign < align) jl_exceptionf(jl_argumenterror_type, "reinterpret from alignment %u bytes to alignment %u bytes not allowed", @@ -283,7 +283,7 @@ JL_DLLEXPORT jl_array_t *jl_ptr_to_array_1d(jl_value_t *atype, void *data, unsigned align; if (isunboxed) { elsz = jl_datatype_size(el_type); - align = ((jl_datatype_t*)el_type)->layout->alignment; + align = jl_datatype_align(el_type); } else { align = elsz = sizeof(void*); @@ -346,7 +346,7 @@ JL_DLLEXPORT jl_array_t *jl_ptr_to_array(jl_value_t *atype, void *data, unsigned align; if (isunboxed) { elsz = jl_datatype_size(el_type); - align = ((jl_datatype_t*)el_type)->layout->alignment; + align = jl_datatype_align(el_type); } else { align = elsz = sizeof(void*); diff --git a/src/ccall.cpp b/src/ccall.cpp index 28218547bf113..30af151ebc872 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -618,7 +618,7 @@ static Value *julia_to_address(Type *to, jl_value_t *jlto, jl_unionall_t *jlto_e builder.CreateMemCpy(slot, data_pointer(jvinfo, ctx, slot->getType()), (uint64_t)jl_datatype_size(ety), - (uint64_t)((jl_datatype_t*)ety)->layout->alignment); + (uint64_t)jl_datatype_align(ety)); mark_gc_use(jvinfo); } if (slot->getType() != to) @@ -657,7 +657,7 @@ static Value *julia_to_native(Type *to, bool toboxed, jl_value_t *jlto, jl_union builder.CreateMemCpy(slot, data_pointer(jvinfo, ctx, slot->getType()), (uint64_t)jl_datatype_size(jlto), - (uint64_t)((jl_datatype_t*)jlto)->layout->alignment); + (uint64_t)jl_datatype_align(jlto)); mark_gc_use(jvinfo); } return slot; diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 1793bee77bc97..8f27692e446eb 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -157,7 +157,7 @@ static DIType julia_type_to_di(jl_value_t *jt, DIBuilder *dbuilder, bool isboxed llvm::DIType *t = dbuilder->createBasicType( jl_symbol_name(jdt->name->name), SizeInBits, - 8 * jdt->layout->alignment, + 8 * jl_datatype_align(jdt), llvm::dwarf::DW_ATE_unsigned); jdt->ditype = t; return t; @@ -165,7 +165,7 @@ static DIType julia_type_to_di(jl_value_t *jt, DIBuilder *dbuilder, bool isboxed DIType t = dbuilder->createBasicType( jl_symbol_name(jdt->name->name), SizeInBits, - 8 * jdt->layout->alignment, + 8 * jl_datatype_align(jdt), llvm::dwarf::DW_ATE_unsigned); MDNode *M = t; jdt->ditype = M; @@ -189,7 +189,7 @@ static DIType julia_type_to_di(jl_value_t *jt, DIBuilder *dbuilder, bool isboxed NULL, // File 0, // LineNumber jl_datatype_nbits(jdt), // SizeInBits - 8 * jdt->layout->alignment, // AlignInBits + 8 * jl_datatype_align(jdt), // AlignInBits DIFlagZero, // Flags NULL, // DerivedFrom DINodeArray(), // Elements @@ -523,7 +523,7 @@ static Type *julia_struct_to_llvm(jl_value_t *jt, jl_unionall_t *ua, bool *isbox *jl_ExecutionEngine->getDataLayout(); #endif unsigned llvm_alignment = DL.getABITypeAlignment((Type*)jst->struct_decl); - unsigned julia_alignment = jst->layout->alignment; + unsigned julia_alignment = jl_datatype_align(jst); // Check that the alignment adheres to the heap alignment. assert(julia_alignment <= JL_SMALL_BYTE_ALIGNMENT); // TODO: Fix alignment calculation in LLVM, as well as in the GC and the struct declaration @@ -1169,7 +1169,7 @@ static Value *emit_bounds_check(const jl_cgval_t &ainfo, jl_value_t *ty, Value * // It is currently unused, but might be used in the future for a more precise answer. static unsigned julia_alignment(Value* /*ptr*/, jl_value_t *jltype, unsigned alignment) { - if (!alignment && ((jl_datatype_t*)jltype)->layout->alignment > MAX_ALIGN) { + if (!alignment && jl_datatype_align(jltype) > MAX_ALIGN) { // Type's natural alignment exceeds strictest alignment promised in heap, so return the heap alignment. return MAX_ALIGN; } diff --git a/src/codegen.cpp b/src/codegen.cpp index a3cd82040a16e..78fbb4362bae9 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3688,7 +3688,7 @@ static void union_alloca_type(jl_uniontype_t *ut, [&](unsigned idx, jl_datatype_t *jt) { if (!jl_is_datatype_singleton(jt)) { size_t nb1 = jl_datatype_size(jt); - size_t align1 = jt->layout->alignment; + size_t align1 = jl_datatype_align(jt); if (nb1 > nbytes) nbytes = nb1; if (align1 > align) @@ -3959,7 +3959,7 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) builder.CreateMemCpy(vi.value.V, data_pointer(rval_info, ctx, T_pint8), copy_bytes, - ((jl_datatype_t*)rval_info.typ)->layout->alignment, + jl_datatype_align(rval_info.typ), vi.isVolatile, tbaa); } diff --git a/src/datatype.c b/src/datatype.c index ce7c46c24e790..2ccad9adc121f 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -278,7 +278,7 @@ void jl_compute_field_offsets(jl_datatype_t *st) // Should never happen if (__unlikely(fsz > max_size)) goto throw_ovf; - al = ((jl_datatype_t*)ty)->layout->alignment; + al = jl_datatype_align(ty); desc[i].isptr = 0; if (((jl_datatype_t*)ty)->layout->haspadding) haspadding = 1; @@ -441,7 +441,7 @@ static jl_value_t *jl_new_bits_internal(jl_value_t *dt, void *data, size_t *len) size_t nb = jl_datatype_size(bt); if (nb == 0) return jl_new_struct_uninit(bt); - *len = LLT_ALIGN(*len, bt->layout->alignment); + *len = LLT_ALIGN(*len, jl_datatype_align(bt)); data = (char*)data + (*len); *len += nb; if (bt == jl_uint8_type) return jl_box_uint8(*(uint8_t*)data); @@ -762,7 +762,7 @@ JL_DLLEXPORT size_t jl_get_alignment(jl_datatype_t *ty) { if (ty->layout == NULL) jl_error("non-leaf type doesn't have an alignment"); - return ty->layout->alignment; + return jl_datatype_align(ty); } #ifdef __cplusplus diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index a4171275cee1f..949a1334fe9c0 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -616,7 +616,7 @@ static jl_cgval_t emit_pointerref(jl_cgval_t *argv, jl_codectx_t *ctx) Value *strct = emit_allocobj(ctx, size, literal_pointer_val((jl_value_t*)ety)); im1 = builder.CreateMul(im1, ConstantInt::get(T_size, - LLT_ALIGN(size, ((jl_datatype_t*)ety)->layout->alignment))); + LLT_ALIGN(size, jl_datatype_align(ety)))); Value *thePtr = emit_unbox(T_pint8, e, e.typ); thePtr = builder.CreateGEP(emit_bitcast(thePtr, T_pint8), im1); builder.CreateMemCpy(emit_bitcast(strct, T_pint8), thePtr, size, 1); @@ -673,7 +673,7 @@ static jl_cgval_t emit_pointerset(jl_cgval_t *argv, jl_codectx_t *ctx) thePtr = emit_unbox(T_pint8, e, e.typ); uint64_t size = jl_datatype_size(ety); im1 = builder.CreateMul(im1, ConstantInt::get(T_size, - LLT_ALIGN(size, ((jl_datatype_t*)ety)->layout->alignment))); + LLT_ALIGN(size, jl_datatype_align(ety)))); builder.CreateMemCpy(builder.CreateGEP(thePtr, im1), data_pointer(x, ctx, T_pint8), size, align_nb); } diff --git a/src/julia.h b/src/julia.h index 3af8aad0bf450..4b8439fb11852 100644 --- a/src/julia.h +++ b/src/julia.h @@ -773,6 +773,7 @@ STATIC_INLINE void jl_array_uint8_set(void *a, size_t i, uint8_t x) #define jl_field_type(st,i) jl_svecref(((jl_datatype_t*)st)->types, (i)) #define jl_field_count(st) jl_svec_len(((jl_datatype_t*)st)->types) #define jl_datatype_size(t) (((jl_datatype_t*)t)->size) +#define jl_datatype_align(t) (((jl_datatype_t*)t)->layout->alignment) #define jl_datatype_nbits(t) ((((jl_datatype_t*)t)->size)*8) #define jl_datatype_nfields(t) (((jl_datatype_t*)(t))->layout->nfields) diff --git a/src/runtime_intrinsics.c b/src/runtime_intrinsics.c index d38c733df0db4..e00e13dce82ca 100644 --- a/src/runtime_intrinsics.c +++ b/src/runtime_intrinsics.c @@ -46,7 +46,7 @@ JL_DLLEXPORT jl_value_t *jl_pointerref(jl_value_t *p, jl_value_t *i, jl_value_t else { if (!jl_is_datatype(ety)) jl_error("pointerref: invalid pointer"); - size_t nb = LLT_ALIGN(jl_datatype_size(ety), ((jl_datatype_t*)ety)->layout->alignment); + size_t nb = LLT_ALIGN(jl_datatype_size(ety), jl_datatype_align(ety)); char *pp = (char*)jl_unbox_long(p) + (jl_unbox_long(i)-1)*nb; return jl_new_bits(ety, pp); } @@ -67,7 +67,7 @@ JL_DLLEXPORT jl_value_t *jl_pointerset(jl_value_t *p, jl_value_t *x, jl_value_t else { if (!jl_is_datatype(ety)) jl_error("pointerset: invalid pointer"); - size_t nb = LLT_ALIGN(jl_datatype_size(ety), ((jl_datatype_t*)ety)->layout->alignment); + size_t nb = LLT_ALIGN(jl_datatype_size(ety), jl_datatype_align(ety)); char *pp = (char*)jl_unbox_long(p) + (jl_unbox_long(i)-1)*nb; if (jl_typeof(x) != ety) jl_error("pointerset: type mismatch in assign"); From ed286e4911352797bffe24d5e9a68d4f2f903761 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Sun, 21 May 2017 18:17:03 +0900 Subject: [PATCH 0874/1534] Introduce JL_HEAP_ALIGNMENT --- src/cgutils.cpp | 8 ++++---- src/datatype.c | 7 ++++--- src/gc.c | 1 + src/gc.h | 2 +- src/intrinsics.cpp | 2 +- src/julia_internal.h | 2 ++ 6 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 8f27692e446eb..3df26140a8b3e 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -525,9 +525,9 @@ static Type *julia_struct_to_llvm(jl_value_t *jt, jl_unionall_t *ua, bool *isbox unsigned llvm_alignment = DL.getABITypeAlignment((Type*)jst->struct_decl); unsigned julia_alignment = jl_datatype_align(jst); // Check that the alignment adheres to the heap alignment. - assert(julia_alignment <= JL_SMALL_BYTE_ALIGNMENT); + assert(julia_alignment <= JL_HEAP_ALIGNMENT); // TODO: Fix alignment calculation in LLVM, as well as in the GC and the struct declaration - if (llvm_alignment <= JL_SMALL_BYTE_ALIGNMENT) + if (llvm_alignment <= JL_HEAP_ALIGNMENT) assert(julia_alignment == llvm_alignment); } #endif @@ -1169,9 +1169,9 @@ static Value *emit_bounds_check(const jl_cgval_t &ainfo, jl_value_t *ty, Value * // It is currently unused, but might be used in the future for a more precise answer. static unsigned julia_alignment(Value* /*ptr*/, jl_value_t *jltype, unsigned alignment) { - if (!alignment && jl_datatype_align(jltype) > MAX_ALIGN) { + if (!alignment && jl_datatype_align(jltype) > JL_HEAP_ALIGNMENT) { // Type's natural alignment exceeds strictest alignment promised in heap, so return the heap alignment. - return MAX_ALIGN; + return JL_HEAP_ALIGNMENT; } return alignment; } diff --git a/src/datatype.c b/src/datatype.c index 2ccad9adc121f..9dd129bec91e0 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -290,6 +290,7 @@ void jl_compute_field_offsets(jl_datatype_t *st) al = fsz; desc[i].isptr = 1; } + assert(al <= JL_HEAP_ALIGNMENT && (JL_HEAP_ALIGNMENT % al) == 0); if (al != 0) { size_t alsz = LLT_ALIGN(sz, al); if (sz & (al - 1)) @@ -310,9 +311,9 @@ void jl_compute_field_offsets(jl_datatype_t *st) // Some tuples become LLVM vectors with stronger alignment than what was calculated above. unsigned al = jl_special_vector_alignment(nfields, lastty); assert(al % alignm == 0); - // JL_SMALL_BYTE_ALIGNMENT is the smallest alignment we can guarantee on the heap. - if (al > JL_SMALL_BYTE_ALIGNMENT) - alignm = JL_SMALL_BYTE_ALIGNMENT; + // JL_HEAP_ALIGNMENT is the biggest alignment we can guarantee on the heap. + if (al > JL_HEAP_ALIGNMENT) + alignm = JL_HEAP_ALIGNMENT; else if (al) alignm = al; } diff --git a/src/gc.c b/src/gc.c index f30ef6f20f7d5..4339b3f9f3832 100644 --- a/src/gc.c +++ b/src/gc.c @@ -706,6 +706,7 @@ JL_DLLEXPORT jl_value_t *jl_gc_big_alloc(jl_ptls_t ptls, size_t sz) { maybe_collect(ptls); size_t offs = offsetof(bigval_t, header); + static_assert(sizeof(bigval_t) % JL_HEAP_ALIGNMENT == 0, ""); size_t allocsz = LLT_ALIGN(sz + offs, JL_CACHE_BYTE_ALIGNMENT); if (allocsz < sz) // overflow in adding offs, size was "negative" jl_throw(jl_memory_exception); diff --git a/src/gc.h b/src/gc.h index 472bbaaf65d32..a5120af953ec3 100644 --- a/src/gc.h +++ b/src/gc.h @@ -32,7 +32,7 @@ extern "C" { #define GC_PAGE_LG2 14 // log2(size of a page) #define GC_PAGE_SZ (1 << GC_PAGE_LG2) // 16k -#define GC_PAGE_OFFSET (JL_SMALL_BYTE_ALIGNMENT - (sizeof(jl_taggedvalue_t) % JL_SMALL_BYTE_ALIGNMENT)) +#define GC_PAGE_OFFSET (JL_HEAP_ALIGNMENT - (sizeof(jl_taggedvalue_t) % JL_HEAP_ALIGNMENT)) #define jl_malloc_tag ((void*)0xdeadaa01) #define jl_singleton_tag ((void*)0xdeadaa02) diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index 949a1334fe9c0..dc1f8ed89f0c0 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -331,7 +331,7 @@ static Value *emit_unbox(Type *to, const jl_cgval_t &x, jl_value_t *jt, Value *d int alignment; if (x.isboxed) { - // julia's gc gives 16-byte aligned addresses + // julia's gc gives 16-byte aligned addresses alignment = 16; } else if (jt) { diff --git a/src/julia_internal.h b/src/julia_internal.h index 182a8c84e2422..688a312042d43 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -223,6 +223,8 @@ STATIC_INLINE int JL_CONST_FUNC jl_gc_szclass(size_t sz) #endif #define JL_SMALL_BYTE_ALIGNMENT 16 #define JL_CACHE_BYTE_ALIGNMENT 64 +// JL_HEAP_ALIGNMENT is the maximum alignment that the GC can provide +#define JL_HEAP_ALIGNMENT JL_SMALL_BYTE_ALIGNMENT #define GC_MAX_SZCLASS (2032-sizeof(void*)) STATIC_INLINE jl_value_t *jl_gc_alloc_(jl_ptls_t ptls, size_t sz, void *ty) From b9671b0c03586400ce4e66fba54958f589d24c6b Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Sun, 21 May 2017 18:33:41 +0900 Subject: [PATCH 0875/1534] fix julia_alignment Make julia_alignment actually return the jl_datatype_align if `alignment == 0` and check that the requested alignment is coherent with the heap alignment. --- src/cgutils.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 3df26140a8b3e..e9554702765fb 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -1169,9 +1169,10 @@ static Value *emit_bounds_check(const jl_cgval_t &ainfo, jl_value_t *ty, Value * // It is currently unused, but might be used in the future for a more precise answer. static unsigned julia_alignment(Value* /*ptr*/, jl_value_t *jltype, unsigned alignment) { - if (!alignment && jl_datatype_align(jltype) > JL_HEAP_ALIGNMENT) { - // Type's natural alignment exceeds strictest alignment promised in heap, so return the heap alignment. - return JL_HEAP_ALIGNMENT; + if (!alignment) { + alignment = jl_datatype_align(jltype); + assert(alignment <= JL_HEAP_ALIGNMENT); + assert(JL_HEAP_ALIGNMENT % alignment == 0); } return alignment; } From 3c5c27a15bf9eee8a98bc4527820dfd74c8697f5 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Mon, 22 May 2017 17:07:49 -0700 Subject: [PATCH 0876/1534] Add NEWS.md entry for dep of getindex(::Tuple, ::AbstractArray{_,N}) where N>1 (#19737). (#21988) --- NEWS.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/NEWS.md b/NEWS.md index 65fc77458a860..ec7c38c0b5203 100644 --- a/NEWS.md +++ b/NEWS.md @@ -563,6 +563,11 @@ Deprecated or removed * `broadcast_zpreserving` has been deprecated ([#19533], [#19720]). + * Methods allowing indexing of tuples by `AbstractArray`s with more than one dimension + have been deprecated. (Indexing a tuple by such a higher-dimensional `AbstractArray` + should yield a tuple with more than one dimension, but tuples are one-dimensional.) + ([#19737]). + * `@test_approx_eq a b` has been deprecated in favor of `@test a ≈ b` (or, equivalently, `@test ≈(a, b)` or `@test isapprox(a, b)`). `@test_approx_eq_eps` has been deprecated in favor of new `@test` syntax: @@ -699,6 +704,7 @@ Command-line option changes [#19721]: https://github.com/JuliaLang/julia/issues/19721 [#19722]: https://github.com/JuliaLang/julia/issues/19722 [#19724]: https://github.com/JuliaLang/julia/issues/19724 +[#19737]: https://github.com/JuliaLang/julia/issues/19737 [#19741]: https://github.com/JuliaLang/julia/issues/19741 [#19771]: https://github.com/JuliaLang/julia/issues/19771 [#19779]: https://github.com/JuliaLang/julia/issues/19779 From d8aae1b72d9899f0f682a7366ee171f1c820dbae Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Mon, 22 May 2017 23:01:13 -0400 Subject: [PATCH 0877/1534] More flexible perm-gen allocation alignment control --- src/datatype.c | 2 +- src/dump.c | 2 +- src/gc-pages.c | 9 ++++-- src/gc.c | 71 +++++++++++++++++++++++++++----------------- src/julia_internal.h | 9 ++++-- src/symbol.c | 2 +- test/core.jl | 9 ++++++ 7 files changed, 68 insertions(+), 36 deletions(-) diff --git a/src/datatype.c b/src/datatype.c index 0bf85c8af246a..1ae148da466aa 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -135,7 +135,7 @@ static jl_datatype_layout_t *jl_get_layout(uint32_t nfields, jl_datatype_layout_t *flddesc = (jl_datatype_layout_t*)jl_gc_perm_alloc(sizeof(jl_datatype_layout_t) + nfields * fielddesc_size + - (has_padding ? sizeof(uint32_t) : 0), 0); + (has_padding ? sizeof(uint32_t) : 0), 0, 4, 0); if (has_padding) { if (first_ptr > UINT16_MAX) first_ptr = UINT16_MAX; diff --git a/src/dump.c b/src/dump.c index 5d0ec1080df2f..601d73ec1d0f5 100644 --- a/src/dump.c +++ b/src/dump.c @@ -1506,7 +1506,7 @@ static jl_value_t *jl_deserialize_datatype(jl_serializer_state *s, int pos, jl_v size_t fielddesc_size = nf > 0 ? jl_fielddesc_size(fielddesc_type) : 0; jl_datatype_layout_t *layout = (jl_datatype_layout_t*)jl_gc_perm_alloc( sizeof(jl_datatype_layout_t) + nf * fielddesc_size + - (has_padding ? sizeof(uint32_t) : 0), 0); + (has_padding ? sizeof(uint32_t) : 0), 0, 4, 0); if (has_padding) { layout = (jl_datatype_layout_t*)(((char*)layout) + sizeof(uint32_t)); jl_datatype_layout_n_nonptr(layout) = read_int32(s->s); diff --git a/src/gc-pages.c b/src/gc-pages.c index ea485079db51d..b0b3feca52c6e 100644 --- a/src/gc-pages.c +++ b/src/gc-pages.c @@ -91,7 +91,8 @@ static jl_gc_pagemeta_t *jl_gc_alloc_new_page(void) // if any allocation fails, this just stops recording more pages from that point // and will free (munmap) the remainder jl_gc_pagemeta_t *page_meta = - (jl_gc_pagemeta_t*)jl_gc_perm_alloc_nolock(pg_cnt * sizeof(jl_gc_pagemeta_t), 1); + (jl_gc_pagemeta_t*)jl_gc_perm_alloc_nolock(pg_cnt * sizeof(jl_gc_pagemeta_t), 1, + sizeof(void*), 0); pg = 0; if (page_meta) { for (; pg < pg_cnt; pg++) { @@ -114,7 +115,8 @@ static jl_gc_pagemeta_t *jl_gc_alloc_new_page(void) memory_map.freemap1[info.pagetable_i32] |= msk; // has free info.pagetable1 = *(ppagetable1 = &memory_map.meta1[i]); if (!info.pagetable1) { - info.pagetable1 = (pagetable1_t*)jl_gc_perm_alloc_nolock(sizeof(pagetable1_t), 1); + info.pagetable1 = (pagetable1_t*)jl_gc_perm_alloc_nolock(sizeof(pagetable1_t), 1, + sizeof(void*), 0); *ppagetable1 = info.pagetable1; if (!info.pagetable1) break; @@ -129,7 +131,8 @@ static jl_gc_pagemeta_t *jl_gc_alloc_new_page(void) info.pagetable1->freemap0[info.pagetable1_i32] |= msk; // has free info.pagetable0 = *(ppagetable0 = &info.pagetable1->meta0[i]); if (!info.pagetable0) { - info.pagetable0 = (pagetable0_t*)jl_gc_perm_alloc_nolock(sizeof(pagetable0_t), 1); + info.pagetable0 = (pagetable0_t*)jl_gc_perm_alloc_nolock(sizeof(pagetable0_t), 1, + sizeof(void*), 0); *ppagetable0 = info.pagetable0; if (!info.pagetable0) break; diff --git a/src/gc.c b/src/gc.c index f30ef6f20f7d5..776c94b69249a 100644 --- a/src/gc.c +++ b/src/gc.c @@ -2821,51 +2821,68 @@ jl_value_t *jl_gc_realloc_string(jl_value_t *s, size_t sz) // 20k limit for pool allocation. At most 1% fragmentation #define GC_PERM_POOL_LIMIT (20 * 1024) jl_mutex_t gc_perm_lock = {0, 0}; -static char *gc_perm_pool = NULL; -static size_t gc_perm_size = 0; +static uintptr_t gc_perm_pool = 0; +static uintptr_t gc_perm_end = 0; + +static void *gc_perm_alloc_large(size_t sz, int zero, unsigned align, unsigned offset) +{ + // `align` must be power of two + assert(offset == 0 || offset < align); + const size_t malloc_align = sizeof(void*) == 8 ? 16 : 4; + if (align > 1 && (offset != 0 || align > malloc_align)) + sz += align - 1; + uintptr_t base = (uintptr_t)(zero ? calloc(1, sz) : malloc(sz)); + unsigned diff = (offset - base) % align; + return (void*)(base + diff); +} + +STATIC_INLINE void *gc_try_perm_alloc_pool(size_t sz, unsigned align, unsigned offset) +{ + uintptr_t pool = LLT_ALIGN(gc_perm_pool + offset, (uintptr_t)align) - offset; + uintptr_t end = pool + sz; + if (end > gc_perm_end) + return NULL; + gc_perm_pool = end; + return (void*)jl_assume(pool); +} // **NOT** a safepoint -void *jl_gc_perm_alloc_nolock(size_t sz, int zero) +void *jl_gc_perm_alloc_nolock(size_t sz, int zero, unsigned align, unsigned offset) { // The caller should have acquired `gc_perm_lock` + assert(align < GC_PERM_POOL_LIMIT); #ifndef MEMDEBUG if (__unlikely(sz > GC_PERM_POOL_LIMIT)) #endif - return zero ? calloc(1, sz) : malloc(sz); - sz = LLT_ALIGN(sz, JL_SMALL_BYTE_ALIGNMENT); - if (__unlikely(sz > gc_perm_size)) { + return gc_perm_alloc_large(sz, zero, align, offset); + void *ptr = gc_try_perm_alloc_pool(sz, align, offset); + if (__likely(ptr)) + return ptr; #ifdef _OS_WINDOWS_ - void *pool = VirtualAlloc(NULL, - GC_PERM_POOL_SIZE + JL_SMALL_BYTE_ALIGNMENT, - MEM_COMMIT, PAGE_READWRITE); - if (__unlikely(pool == NULL)) - return NULL; - pool = (void*)LLT_ALIGN((uintptr_t)pool, JL_SMALL_BYTE_ALIGNMENT); + void *pool = VirtualAlloc(NULL, GC_PERM_POOL_SIZE, MEM_COMMIT, PAGE_READWRITE); + if (__unlikely(pool == NULL)) + return NULL; #else - void *pool = mmap(0, GC_PERM_POOL_SIZE, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - if (__unlikely(pool == MAP_FAILED)) - return NULL; + void *pool = mmap(0, GC_PERM_POOL_SIZE, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (__unlikely(pool == MAP_FAILED)) + return NULL; #endif - gc_perm_pool = (char*)pool; - gc_perm_size = GC_PERM_POOL_SIZE; - } - assert(((uintptr_t)gc_perm_pool) % JL_SMALL_BYTE_ALIGNMENT == 0); - void *p = gc_perm_pool; - gc_perm_size -= sz; - gc_perm_pool += sz; - return p; + gc_perm_pool = (uintptr_t)pool; + gc_perm_end = gc_perm_pool + GC_PERM_POOL_SIZE; + return gc_try_perm_alloc_pool(sz, align, offset); } // **NOT** a safepoint -void *jl_gc_perm_alloc(size_t sz, int zero) +void *jl_gc_perm_alloc(size_t sz, int zero, unsigned align, unsigned offset) { + assert(align < GC_PERM_POOL_LIMIT); #ifndef MEMDEBUG if (__unlikely(sz > GC_PERM_POOL_LIMIT)) #endif - return zero ? calloc(1, sz) : malloc(sz); + return gc_perm_alloc_large(sz, zero, align, offset); JL_LOCK_NOGC(&gc_perm_lock); - void *p = jl_gc_perm_alloc_nolock(sz, zero); + void *p = jl_gc_perm_alloc_nolock(sz, zero, align, offset); JL_UNLOCK_NOGC(&gc_perm_lock); return p; } diff --git a/src/julia_internal.h b/src/julia_internal.h index 182a8c84e2422..9bdcd01d36623 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -129,8 +129,8 @@ JL_DLLEXPORT jl_value_t *jl_gc_pool_alloc(jl_ptls_t ptls, int pool_offset, JL_DLLEXPORT jl_value_t *jl_gc_big_alloc(jl_ptls_t ptls, size_t allocsz); int jl_gc_classify_pools(size_t sz, int *osize); extern jl_mutex_t gc_perm_lock; -void *jl_gc_perm_alloc_nolock(size_t sz, int zero); -void *jl_gc_perm_alloc(size_t sz, int zero); +void *jl_gc_perm_alloc_nolock(size_t sz, int zero, unsigned align, unsigned offset); +void *jl_gc_perm_alloc(size_t sz, int zero, unsigned align, unsigned offset); // pools are 16376 bytes large (GC_POOL_SZ - GC_PAGE_OFFSET) static const int jl_gc_sizeclasses[JL_GC_N_POOLS] = { @@ -268,7 +268,10 @@ STATIC_INLINE void *jl_gc_alloc_buf(jl_ptls_t ptls, size_t sz) STATIC_INLINE jl_value_t *jl_gc_permobj(size_t sz, void *ty) { const size_t allocsz = sz + sizeof(jl_taggedvalue_t); - jl_taggedvalue_t *o = (jl_taggedvalue_t*)jl_gc_perm_alloc(allocsz, 0); + unsigned align = (sz == 0 ? sizeof(void*) : (allocsz <= sizeof(void*) * 2 ? + sizeof(void*) * 2 : 16)); + jl_taggedvalue_t *o = (jl_taggedvalue_t*)jl_gc_perm_alloc(allocsz, 0, align, + sizeof(void*) % align); uintptr_t tag = (uintptr_t)ty; o->header = tag | GC_OLD_MARKED; return jl_valueof(o); diff --git a/src/symbol.c b/src/symbol.c index e8a2b3cab1491..7be4136fa70d1 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -32,7 +32,7 @@ static jl_sym_t *mk_symbol(const char *str, size_t len) jl_sym_t *sym; size_t nb = symbol_nbytes(len); - jl_taggedvalue_t *tag = (jl_taggedvalue_t*)jl_gc_perm_alloc_nolock(nb, 0); + jl_taggedvalue_t *tag = (jl_taggedvalue_t*)jl_gc_perm_alloc_nolock(nb, 0, sizeof(void*), 0); sym = (jl_sym_t*)jl_valueof(tag); // set to old marked so that we won't look at it in the GC or write barrier. tag->header = ((uintptr_t)jl_sym_type) | GC_OLD_MARKED; diff --git a/test/core.jl b/test/core.jl index b98dbb686b09e..b58b3c1169e3e 100644 --- a/test/core.jl +++ b/test/core.jl @@ -4941,3 +4941,12 @@ let arr8 = zeros(UInt8, 16), arr64_i[2] = 1234 @test arr64[2] == 1234 end + +# Alignment of perm boxes +for i in 1:10 + # Int64 box should be 16bytes aligned even on 32bits + ptr1 = ccall(:jl_box_int64, UInt, (Int64,), i) + ptr2 = ccall(:jl_box_int64, UInt, (Int64,), i) + @test ptr1 === ptr2 + @test ptr1 % 16 == 0 +end From 5e962ca124432d932ecbd720049bd5741c54f65b Mon Sep 17 00:00:00 2001 From: Evey Dee Date: Tue, 23 May 2017 15:03:35 +0800 Subject: [PATCH 0878/1534] Update README.md Fixed broken link. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6cf204e48a403..fa4df7ad034fc 100644 --- a/README.md +++ b/README.md @@ -427,4 +427,4 @@ is available through [Sublime-IJulia](https://github.com/quinnj/Sublime-IJulia) plugin enables interaction between IJulia and Sublime Text. -In the terminal, Julia makes great use of both control-key and meta-key bindings. To make the meta-key bindings more accessible, many terminal emulator programs (e.g., `Terminal`, `iTerm`, `xterm`, etc.) allow you to use the alt or option key as meta. See the section in the manual on [interacting with Julia](https://docs.julialang.org/en/latest/manual/interacting-with-julia/) for more details. +In the terminal, Julia makes great use of both control-key and meta-key bindings. To make the meta-key bindings more accessible, many terminal emulator programs (e.g., `Terminal`, `iTerm`, `xterm`, etc.) allow you to use the alt or option key as meta. See the section in the manual on [interacting with Julia](https://docs.julialang.org/en/latest/manual/interacting-with-julia.html) for more details. From 0506394e6bb229b77462a6f0297a3cea4109fe93 Mon Sep 17 00:00:00 2001 From: Ranjan Anantharaman Date: Tue, 23 May 2017 19:01:36 +0530 Subject: [PATCH 0879/1534] Patch to further fix building julia with llvm-svn (#22015) --- src/llvm-lower-handlers.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/llvm-lower-handlers.cpp b/src/llvm-lower-handlers.cpp index 7b8f2388c1fbe..4ef6f15a02aa5 100644 --- a/src/llvm-lower-handlers.cpp +++ b/src/llvm-lower-handlers.cpp @@ -114,8 +114,15 @@ bool LowerExcHandlers::doInitialization(Module &M) { leave_func = M.getFunction("jl_pop_handler"); jlenter_func = M.getFunction("jl_enter_handler"); setjmp_func = M.getFunction(jl_setjmp_name); + +#if JL_LLVM_VERSION >= 50000 + auto T_pint8 = Type::getInt8PtrTy(M.getContext(), 0); + lifetime_start = Intrinsic::getDeclaration(&M, Intrinsic::lifetime_start, { T_pint8 }); + lifetime_end = Intrinsic::getDeclaration(&M, Intrinsic::lifetime_end, { T_pint8 }); +#else lifetime_start = Intrinsic::getDeclaration(&M, Intrinsic::lifetime_start); lifetime_end = Intrinsic::getDeclaration(&M, Intrinsic::lifetime_end); +#endif return true; } From 0b49fd520116201cb49b498cdce47fd85a94851a Mon Sep 17 00:00:00 2001 From: duguxy Date: Tue, 23 May 2017 22:02:45 +0800 Subject: [PATCH 0880/1534] Wrong parameter names for sygvd! in the document (#22035) --- base/linalg/lapack.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/linalg/lapack.jl b/base/linalg/lapack.jl index 96b04e5e68bd0..14d8f76df34ae 100644 --- a/base/linalg/lapack.jl +++ b/base/linalg/lapack.jl @@ -5095,7 +5095,7 @@ syevr!(jobz::Char, range::Char, uplo::Char, A::StridedMatrix, vl::AbstractFloat, vu::AbstractFloat, il::Integer, iu::Integer, abstol::AbstractFloat) """ - sygvd!(jobz, range, uplo, A, vl, vu, il, iu, abstol) -> (w, A, B) + sygvd!(itype, jobz, uplo, A, B) -> (w, A, B) Finds the generalized eigenvalues (`jobz = N`) or eigenvalues and eigenvectors (`jobz = V`) of a symmetric matrix `A` and symmetric From cfa19995c121f0471ab817f24751382ebb27fcc2 Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Tue, 23 May 2017 10:29:30 -0400 Subject: [PATCH 0881/1534] Only try to call specialized findin method for sorted input when elements are Real. (#22010) * Only try to call specialized findin method for sorted input when elements are Real. * Fix termination cirteria in _sortedfindin Use total order `isless` for tests Add tests * Define eachindex for numbers * Add a few comments to the algorithm --- base/abstractarray.jl | 2 +- base/array.jl | 31 ++++++++++++++++++++++--------- test/arrayops.jl | 14 ++++++++++++++ 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 6b97d97c2327a..5cb851d822b4a 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -753,7 +753,7 @@ next(A::AbstractArray, i) = (@_propagate_inbounds_meta; (idx, s) = next(i[1], i[ done(A::AbstractArray, i) = (@_propagate_inbounds_meta; done(i[1], i[2])) # eachindex iterates over all indices. IndexCartesian definitions are later. -eachindex(A::AbstractVector) = (@_inline_meta(); indices1(A)) +eachindex(A::Union{Number,AbstractVector}) = (@_inline_meta(); indices1(A)) """ eachindex(A...) diff --git a/base/array.jl b/base/array.jl index e5dea7bc703b8..530cbf6456448 100644 --- a/base/array.jl +++ b/base/array.jl @@ -1734,6 +1734,9 @@ function _findin(a, b) ind end +# If two collections are already sorted, findin can be computed with +# a single traversal of the two collections. This is much faster than +# using a hash table (although it has the same complexity). function _sortedfindin(v, w) viter, witer = eachindex(v), eachindex(w) out = eltype(viter)[] @@ -1745,23 +1748,30 @@ function _sortedfindin(v, w) witerj, j = next(witer, j) @inbounds begin vi, wj = v[viteri], w[witerj] - while !(done(viter, i) || done(witer, j)) - if vi < wj + while true + if isless(vi, wj) + if done(viter, i) + break + end viteri, i = next(viter, i) vi = v[viteri] - elseif vi > wj + elseif isless(wj, vi) + if done(witer, j) + break + end witerj, j = next(witer, j) wj = w[witerj] else push!(out, viteri) + if done(viter, i) + break + end + # We only increment the v iterator because v can have + # repeated matches to a single value in w viteri, i = next(viter, i) - witerj, j = next(witer, j) - vi, wj = v[viteri], w[witerj] + vi = v[viteri] end end - if vi == wj - push!(out, viteri) - end end return out end @@ -1791,13 +1801,16 @@ julia> findin(a,b) # 10 is the only common element 4 ``` """ -function findin(a, b) +function findin(a::Array{<:Real}, b::Union{Array{<:Real},Real}) if issorted(a, Sort.Forward) && issorted(b, Sort.Forward) return _sortedfindin(a, b) else return _findin(a, b) end end +# issorted fails for some element types so the method above has to be restricted +# to element with isless/< defined. +findin(a, b) = _findin(a, b) # Copying subregions # TODO: DEPRECATE FOR #14770 diff --git a/test/arrayops.jl b/test/arrayops.jl index ca922eba69da2..8b5e6d559af9f 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -273,6 +273,20 @@ end @test findin(a, Int[]) == Int[] @test findin(Int[], a) == Int[] + a = collect(1:3:15) + b = collect(2:4:10) + @test findin(a, b) == [4] + @test findin([a[1:4]; a[4:end]], b) == [4,5] + + @test findin([1.0, NaN, 2.0], NaN) == [2] + @test findin([1.0, 2.0, NaN], NaN) == [3] + + @testset "findin for uncomparable element types" begin + a = [1 + 1im, 1 - 1im] + @test findin(a, 1 + 1im) == [1] + @test findin(a, a) == [1,2] + end + rt = Base.return_types(setindex!, Tuple{Array{Int32, 3}, UInt8, Vector{Int}, Int16, UnitRange{Int}}) @test length(rt) == 1 && rt[1] == Array{Int32, 3} end From df3cd1cb733fe580a9609ed3bbc4304b119cc4c2 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 23 May 2017 17:16:33 -0400 Subject: [PATCH 0882/1534] fix jl_gc_realloc_string size miscomputation fix #22021 --- src/gc.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/gc.c b/src/gc.c index f30ef6f20f7d5..59a8afbc16026 100644 --- a/src/gc.c +++ b/src/gc.c @@ -2792,7 +2792,8 @@ jl_value_t *jl_gc_realloc_string(jl_value_t *s, size_t sz) return snew; } size_t newsz = sz + sizeof(size_t) + 1; - size_t offs = offsetof(bigval_t, header); + size_t offs = sizeof(bigval_t); + size_t oldsz = LLT_ALIGN(strsz + offs, JL_CACHE_BYTE_ALIGNMENT); size_t allocsz = LLT_ALIGN(newsz + offs, JL_CACHE_BYTE_ALIGNMENT); if (allocsz < sz) // overflow in adding offs, size was "negative" jl_throw(jl_memory_exception); @@ -2804,9 +2805,7 @@ jl_value_t *jl_gc_realloc_string(jl_value_t *s, size_t sz) // the old pointer to be left alone if we can't grow in place. // for now it's up to the caller to make sure there are no references to the // old pointer. - bigval_t *newbig = - (bigval_t*)gc_managed_realloc_(ptls, hdr, allocsz, LLT_ALIGN(strsz+offs, JL_CACHE_BYTE_ALIGNMENT), - 1, s, 0); + bigval_t *newbig = (bigval_t*)gc_managed_realloc_(ptls, hdr, allocsz, oldsz, 1, s, 0); newbig->sz = allocsz; newbig->age = 0; gc_big_object_link(newbig, &ptls->heap.big_objects); From a1ffb9e37e86e7838b01e5475e41c007bb99d74c Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Tue, 23 May 2017 20:58:20 -0400 Subject: [PATCH 0883/1534] Don't use totality when defining the (potentially) partial order relation <= (#22027) --- base/operators.jl | 2 +- test/operators.jl | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/base/operators.jl b/base/operators.jl index fc712541e303d..bbec5c09e28f3 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -235,7 +235,7 @@ julia> 5 <= 3 false ``` """ -<=(x, y) = !(y < x) +<=(x, y) = (x < y) | (x == y) const ≤ = <= """ diff --git a/test/operators.jl b/test/operators.jl index 66fbe1aae8a47..e79d3f5a93d53 100644 --- a/test/operators.jl +++ b/test/operators.jl @@ -97,3 +97,18 @@ end B = 3 .> [1 -1 5] .> 0 @test B == [true false false] end + +struct TypeWrapper + t::Type +end +Base.:(<)(x::TypeWrapper, y::TypeWrapper) = (x.t <: y.t) & (x.t != y.t) +@testset "poset" begin + # Real + # / \ + # Int Float64 + # \ / + # Union{} + @test TypeWrapper(Int) <= TypeWrapper(Int) + @test TypeWrapper(Int) <= TypeWrapper(Real) + @test !(TypeWrapper(Int) <= TypeWrapper(Float64)) +end From d74dbd7e2ddb408aaa9421303409f87058e728ae Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Tue, 23 May 2017 18:16:57 -0700 Subject: [PATCH 0884/1534] Add PR number to NEWS.md entry for cummin/cummax deprecation (#18931). (#21987) --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index ec7c38c0b5203..57bdc86a382e9 100644 --- a/NEWS.md +++ b/NEWS.md @@ -512,7 +512,7 @@ Deprecated or removed including step specification, for example `Dates.Hour(1):Dates.Hour(1):Dates.Hour(2)` ([#19920]). - * `cummin` and `cummax` have been deprecated in favor of `accumulate`. + * `cummin` and `cummax` have been deprecated in favor of `accumulate` ([#18931]). * The `Array` constructor syntax `Array(T, dims...)` has been deprecated in favor of the forms `Array{T,N}(dims...)` (where `N` is known, or From b7fdf5ce2a064c722f1f05e2d3c6644aba7560f6 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Tue, 23 May 2017 18:29:42 -0700 Subject: [PATCH 0885/1534] Add NEWS.md entry for takebuf_{array|string} deprecation (#19088). (#21975) --- NEWS.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS.md b/NEWS.md index 57bdc86a382e9..7af25f0dfb6be 100644 --- a/NEWS.md +++ b/NEWS.md @@ -576,6 +576,9 @@ Deprecated or removed `@test a ≈ b atol=c` in place of `@test ≈(a, b, atol=c)` (and hence `@test_approx_eq_eps a b c`) ([#19901]). + * `takebuf_array` has been deprecated in favor of `take!`, and `takebuf_string(x)` + has been deprecated in favor of `String(take!(x))` ([#19088]). + * `convert` methods from `Diagonal` and `Bidiagonal` to subtypes of `AbstractTriangular` have been deprecated ([#17723]). @@ -673,6 +676,7 @@ Command-line option changes [#18965]: https://github.com/JuliaLang/julia/issues/18965 [#18977]: https://github.com/JuliaLang/julia/issues/18977 [#19018]: https://github.com/JuliaLang/julia/issues/19018 +[#19088]: https://github.com/JuliaLang/julia/issues/19088 [#19157]: https://github.com/JuliaLang/julia/issues/19157 [#19233]: https://github.com/JuliaLang/julia/issues/19233 [#19239]: https://github.com/JuliaLang/julia/issues/19239 From e0207724ada01ad6e015ea4b76818345aa16ffa7 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Tue, 23 May 2017 18:31:09 -0700 Subject: [PATCH 0886/1534] Add PR number and quotes to NEWS.md entry for #18754. (#21842) --- NEWS.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/NEWS.md b/NEWS.md index 7af25f0dfb6be..2ceb9f8117117 100644 --- a/NEWS.md +++ b/NEWS.md @@ -455,13 +455,13 @@ Compiler/Runtime improvements ----------------------------- * `ccall` is now implemented as a macro, - removing the need for special code-generator support for Intrinsics. + removing the need for special code-generator support for `Intrinsics` ([#18754]). * `ccall` gained limited support for a `llvmcall` calling-convention. - This can replace many uses of `llvmcall` with a simpler, shorter declaration. + This can replace many uses of `llvmcall` with a simpler, shorter declaration ([#18754]). - * All Intrinsics are now Builtin functions instead and have proper error checking - and fall-back static compilation support. + * All `Intrinsics` are now `Builtin` functions instead and have proper error checking + and fall-back static compilation support ([#18754]). Deprecated or removed --------------------- @@ -668,6 +668,7 @@ Command-line option changes [#18644]: https://github.com/JuliaLang/julia/issues/18644 [#18660]: https://github.com/JuliaLang/julia/issues/18660 [#18690]: https://github.com/JuliaLang/julia/issues/18690 +[#18754]: https://github.com/JuliaLang/julia/issues/18754 [#18777]: https://github.com/JuliaLang/julia/issues/18777 [#18832]: https://github.com/JuliaLang/julia/issues/18832 [#18839]: https://github.com/JuliaLang/julia/issues/18839 From b77a688a01a2d8cf6f2a5feaf64f016df0d5c2a7 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Tue, 23 May 2017 18:33:28 -0700 Subject: [PATCH 0887/1534] Add NEWS.md entry for _promote_array_type deprecation (#19766). (#21990) --- NEWS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS.md b/NEWS.md index 2ceb9f8117117..cf9977e99b6d8 100644 --- a/NEWS.md +++ b/NEWS.md @@ -561,6 +561,8 @@ Deprecated or removed * The tuple-of-types form of `invoke`, `invoke(f, (types...), ...)`, has been deprecated in favor of the tuple-type form `invoke(f, Tuple{types...}, ...)` ([#18444]). + * `Base._promote_array_type` has been deprecated ([#19766]). + * `broadcast_zpreserving` has been deprecated ([#19533], [#19720]). * Methods allowing indexing of tuples by `AbstractArray`s with more than one dimension @@ -711,6 +713,7 @@ Command-line option changes [#19724]: https://github.com/JuliaLang/julia/issues/19724 [#19737]: https://github.com/JuliaLang/julia/issues/19737 [#19741]: https://github.com/JuliaLang/julia/issues/19741 +[#19766]: https://github.com/JuliaLang/julia/issues/19766 [#19771]: https://github.com/JuliaLang/julia/issues/19771 [#19779]: https://github.com/JuliaLang/julia/issues/19779 [#19784]: https://github.com/JuliaLang/julia/issues/19784 From 152d2559a79d062eeeda8e93ba6d6f2fd956d3d3 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Tue, 23 May 2017 18:34:37 -0700 Subject: [PATCH 0888/1534] Add NEWS.md entry for promote_eltype_op deprecation (#19814, #19937). (#21992) --- NEWS.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/NEWS.md b/NEWS.md index cf9977e99b6d8..56fdb0f31aa88 100644 --- a/NEWS.md +++ b/NEWS.md @@ -556,6 +556,8 @@ Deprecated or removed deprecated in favor of equivalent methods with the second argument instead the size of the array, for example `zeros(Float64, size([1, 2, 3]))` ([#21183]). + * `Base.promote_eltype_op` has been deprecated ([#19669], [#19814], [#19937]). + * `isimag` has been deprecated ([#19949]). * The tuple-of-types form of `invoke`, `invoke(f, (types...), ...)`, has been deprecated @@ -700,6 +702,7 @@ Command-line option changes [#19598]: https://github.com/JuliaLang/julia/issues/19598 [#19635]: https://github.com/JuliaLang/julia/issues/19635 [#19636]: https://github.com/JuliaLang/julia/issues/19636 +[#19669]: https://github.com/JuliaLang/julia/issues/19669 [#19670]: https://github.com/JuliaLang/julia/issues/19670 [#19677]: https://github.com/JuliaLang/julia/issues/19677 [#19680]: https://github.com/JuliaLang/julia/issues/19680 @@ -723,6 +726,7 @@ Command-line option changes [#19800]: https://github.com/JuliaLang/julia/issues/19800 [#19802]: https://github.com/JuliaLang/julia/issues/19802 [#19811]: https://github.com/JuliaLang/julia/issues/19811 +[#19814]: https://github.com/JuliaLang/julia/issues/19814 [#19841]: https://github.com/JuliaLang/julia/issues/19841 [#19900]: https://github.com/JuliaLang/julia/issues/19900 [#19901]: https://github.com/JuliaLang/julia/issues/19901 @@ -733,6 +737,7 @@ Command-line option changes [#19926]: https://github.com/JuliaLang/julia/issues/19926 [#19931]: https://github.com/JuliaLang/julia/issues/19931 [#19934]: https://github.com/JuliaLang/julia/issues/19934 +[#19937]: https://github.com/JuliaLang/julia/issues/19937 [#19944]: https://github.com/JuliaLang/julia/issues/19944 [#19949]: https://github.com/JuliaLang/julia/issues/19949 [#19950]: https://github.com/JuliaLang/julia/issues/19950 From a4bafff9690f1d0607734f7deef2ecc92f51e29f Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Tue, 23 May 2017 18:35:39 -0700 Subject: [PATCH 0889/1534] Add NEWS.md entry for unsafe_wrap(String, ...) deprecation (#19449). (#21993) --- NEWS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS.md b/NEWS.md index 56fdb0f31aa88..d443f931c7f02 100644 --- a/NEWS.md +++ b/NEWS.md @@ -551,6 +551,8 @@ Deprecated or removed * The two-argument forms of `map` (`map!(f, A)`) and `asyncmap!` (`asyncmap!(f, A)`) have been deprecated in anticipation of future semantic changes ([#19721]). + * `unsafe_wrap(String, ...)` has been deprecated in favor of `unsafe_string` ([#19449]). + * `zeros` and `ones` methods accepting an element type as the first argument and an array as the second argument, for example `zeros(Float64, [1, 2, 3])`, have been deprecated in favor of equivalent methods with the second argument instead the From 9ba1b49b380783941fcdccd775c7f54bb8060cf5 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Tue, 23 May 2017 18:36:49 -0700 Subject: [PATCH 0890/1534] Fix typo in NEWS.md entry for midpoints deprecation (#20058). (#22008) --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index d443f931c7f02..20e61e114dc92 100644 --- a/NEWS.md +++ b/NEWS.md @@ -614,7 +614,7 @@ Deprecated or removed * To complete the deprecation of histogram-related functions, `midpoints` has been deprecated. Instead use the [StatsBase.jl package](https://github.com/JuliaStats/StatsBase.jl)'s - `midpoint` function ([#20058]). + `midpoints` function ([#20058]). Command-line option changes --------------------------- From 18d7af800b713bd67504156ddb40d2999fb27f5e Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Tue, 23 May 2017 18:38:00 -0700 Subject: [PATCH 0891/1534] Add NEWS.md entry for enumerate(::IndexStyle, itr) addition and indexing traits rename (#16378). (#21997) --- NEWS.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/NEWS.md b/NEWS.md index 20e61e114dc92..03667d85d753d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -451,6 +451,11 @@ Library improvements `map(uppercase ∘ hex, 250:255)` is now equivalent to `map(x -> uppercase(hex(x)), 250:255)` ([#17155]). + * `enumerate` now supports the two-argument form `enumerate(::IndexStyle, iterable)`. + This form allows specification of the returned indices' style. For example, + `enumerate(IndexLinear, iterable)` yields linear indices and + `enumerate(IndexCartesian, iterable)` yields cartesian indices ([#16378]). + Compiler/Runtime improvements ----------------------------- @@ -548,6 +553,11 @@ Deprecated or removed For example, `isnumber("123")` should now be expressed `all(isnumber, "123")` ([#20342]). + * A few names related to indexing traits have been changed: `LinearIndexing` and + `linearindexing` have been deprecated in favor of `IndexStyle`. `LinearFast` has + been deprecated in favor of `IndexLinear`, and `LinearSlow` has been deprecated in + favor of `IndexCartesian` ([#16378]). + * The two-argument forms of `map` (`map!(f, A)`) and `asyncmap!` (`asyncmap!(f, A)`) have been deprecated in anticipation of future semantic changes ([#19721]). @@ -637,6 +647,7 @@ Command-line option changes [#12563]: https://github.com/JuliaLang/julia/issues/12563 [#15850]: https://github.com/JuliaLang/julia/issues/15850 [#16213]: https://github.com/JuliaLang/julia/issues/16213 +[#16378]: https://github.com/JuliaLang/julia/issues/16378 [#16937]: https://github.com/JuliaLang/julia/issues/16937 [#16961]: https://github.com/JuliaLang/julia/issues/16961 [#16984]: https://github.com/JuliaLang/julia/issues/16984 From ee5108b8b725f2354f489704fb5823e3af266846 Mon Sep 17 00:00:00 2001 From: Evey Dee Date: Wed, 24 May 2017 09:47:30 +0800 Subject: [PATCH 0892/1534] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fa4df7ad034fc..b0805eb8dfb0e 100644 --- a/README.md +++ b/README.md @@ -427,4 +427,4 @@ is available through [Sublime-IJulia](https://github.com/quinnj/Sublime-IJulia) plugin enables interaction between IJulia and Sublime Text. -In the terminal, Julia makes great use of both control-key and meta-key bindings. To make the meta-key bindings more accessible, many terminal emulator programs (e.g., `Terminal`, `iTerm`, `xterm`, etc.) allow you to use the alt or option key as meta. See the section in the manual on [interacting with Julia](https://docs.julialang.org/en/latest/manual/interacting-with-julia.html) for more details. +In the terminal, Julia makes great use of both control-key and meta-key bindings. To make the meta-key bindings more accessible, many terminal emulator programs (e.g., `Terminal`, `iTerm`, `xterm`, etc.) allow you to use the alt or option key as meta. See the section in the manual on [interacting with Julia](https://docs.julialang.org/en/latest/manual/interacting-with-julia) for more details. From 7f790246229b44f194b7b9937516d3676c2f9a41 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Tue, 23 May 2017 17:48:04 -0400 Subject: [PATCH 0893/1534] Add extra early memcpyopt pass Under certain circumstances, we emit loads/stores of large LLVM structs. A lot of these can be trivially folded to memcpy and memcpyopt is capable of doing so, but we weren't running it until after SROA. SROA unfortunately, likes to take these apart, causing exponential compile-time blow up and reduced runtime peroformance. In one particular case (2000 element tuple), this change results in a 100x improvement in compile time. --- src/jitlayers.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index 804361fb85ee3..54a950a4ec99d 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -161,6 +161,7 @@ void addOptimizationPasses(PassManager *PM) // list of passes from vmkit PM->add(createCFGSimplificationPass()); // Clean up disgusting code PM->add(createPromoteMemoryToRegisterPass()); // Kill useless allocas + PM->add(createMemCpyOptPass()); // hopefully these functions (from llvmcall) don't try to interact with the Julia runtime // or have anything that might corrupt the createLowerPTLSPass pass From 366053546967e1b0cd2c5a10782833f032dce841 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Thu, 20 Apr 2017 23:11:50 -0400 Subject: [PATCH 0894/1534] Try to loosen cfunction optimization type check. --- src/ccall.cpp | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/ccall.cpp b/src/ccall.cpp index 28218547bf113..c1355d5429777 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -1787,18 +1787,26 @@ static jl_cgval_t emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) jl_value_t *frt = expr_type(args[6], ctx); if (f && (jl_is_type_type((jl_value_t*)frt) && !jl_has_free_typevars(jl_tparam0(frt)))) { fargt = static_eval(args[8], ctx, true, true); - if (fargt) { - if (jl_is_tuple(fargt)) { - // TODO: maybe deprecation warning, better checking - fargt = (jl_value_t*)jl_apply_tuple_type_v((jl_value_t**)jl_data_ptr(fargt), jl_nfields(fargt)); - } - } - else { + if (!fargt) { fargt = expr_type(args[8], ctx); - if (jl_is_type_type((jl_value_t*)fargt)) + if (jl_is_type_type((jl_value_t*)fargt)) { fargt = jl_tparam0(fargt); + if (jl_has_free_typevars(fargt) || !jl_is_tuple_type(fargt)) { + fargt = nullptr; + } + } + else { + fargt = nullptr; + } + } + else if (jl_is_tuple(fargt)) { + // TODO: maybe deprecation warning, better checking + fargt = (jl_value_t*)jl_apply_tuple_type_v((jl_value_t**)jl_data_ptr(fargt), jl_nfields(fargt)); } - if (jl_is_tuple_type(fargt) && jl_is_leaf_type(fargt)) { + else if (!jl_is_tuple_type(fargt)) { + fargt = nullptr; + } + if (fargt) { frt = jl_tparam0(frt); Value *llvmf = NULL; JL_TRY { From 1ee84c8ec4fe0adcac571fe2ab3a8a1c7422c3f0 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 5 May 2017 15:59:50 -0400 Subject: [PATCH 0895/1534] get loaddocs to give line numbers when it fails --- base/docs/Docs.jl | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/base/docs/Docs.jl b/base/docs/Docs.jl index 005d4a6a9f881..53552372a265d 100644 --- a/base/docs/Docs.jl +++ b/base/docs/Docs.jl @@ -749,11 +749,21 @@ include("utils.jl") # Swap out the bootstrap macro with the real one. Core.atdoc!(docm) +macro local_hygiene(expr) + # removes `esc` Exprs relative to the module argument to expand + # and resolves everything else relative to this (Doc) module + # this allows us to get good errors and backtraces + # from calling docm (by not using macros), + # while also getting macro-expansion correct (by using the macro-expander) + return expr +end function loaddocs(docs) + unescape = GlobalRef(Docs, Symbol("@local_hygiene")) for (mod, ex, str, file, line) in docs data = Dict(:path => string(file), :linenumber => line) doc = docstr(str, data) - eval(mod, :(@doc($doc, $ex, false))) + docstring = eval(mod, Expr(:body, Expr(:return, Expr(:call, QuoteNode(docm), QuoteNode(doc), QuoteNode(ex), false)))) # expand the real @doc macro now (using a hack because macroexpand takes current-module as an implicit argument) + eval(mod, Expr(:macrocall, unescape, nothing, docstring)) end empty!(docs) end From fcdf4376415fde3b76faeb1c6f6841735497c8ea Mon Sep 17 00:00:00 2001 From: Isaiah Date: Fri, 5 May 2017 15:57:25 -0400 Subject: [PATCH 0896/1534] pass file and line information as an argument named `__source__` to all macros also emit an explicit push_loc in @generated functions rather than depending on the existence of a LineNumberNode and other lowering heuristics to produce it --- NEWS.md | 10 ++ base/boot.jl | 4 +- base/docs/Docs.jl | 12 +- base/docs/basedocs.jl | 7 - base/docs/utils.jl | 2 +- base/exports.jl | 1 + base/expr.jl | 11 +- base/inference.jl | 37 +++-- base/interactiveutil.jl | 6 +- base/loading.jl | 53 ++++--- base/math.jl | 2 +- base/show.jl | 36 +++-- doc/REQUIRE | 2 +- doc/src/devdocs/ast.md | 36 ++--- doc/src/manual/metaprogramming.md | 47 ++++++ doc/src/stdlib/file.md | 2 +- .../clustermanager/simple/UnixDomainCM.jl | 3 +- examples/clustermanager/simple/test_simple.jl | 2 +- src/ast.c | 50 +++++-- src/codegen.cpp | 6 +- src/jltypes.c | 4 +- src/julia-parser.scm | 66 +++++---- src/julia-syntax.scm | 1 + src/julia.h | 17 +-- src/method.c | 50 +++++-- src/rtutils.c | 4 +- test/ambiguous.jl | 2 +- test/docs.jl | 21 +-- test/loading.jl | 12 +- test/parse.jl | 40 +++--- test/reflection.jl | 8 +- test/replutil.jl | 43 +++--- test/show.jl | 136 +++++++++++++----- test/stacktraces.jl | 4 +- test/worlds.jl | 2 +- 35 files changed, 491 insertions(+), 248 deletions(-) diff --git a/NEWS.md b/NEWS.md index 03667d85d753d..5a00f40c02b00 100644 --- a/NEWS.md +++ b/NEWS.md @@ -24,6 +24,16 @@ This section lists changes that do not have deprecation warnings. * `@__DIR__` returns the current working directory rather than `nothing` when not run from a file ([#21759]). + * `@__FILE__` and `@__DIR__` return information relative to the file that it was parsed from, + rather than from the task-local `SOURCE_PATH` global when it was expanded. + + * All macros receive an extra argument `__source__::LineNumberNode` which describes the + parser location in the source file for the `@` of the macro call. + It can be accessed as a normal argument variable in the body of the macro. + This is implemented by inserting an extra leading argument into the + `Expr(:macrocall, :@name, LineNumberNode(...), args...)` + surface syntax. ([#21746]) + * Passing the same keyword argument multiple times is now a syntax error ([#16937]). * `getsockname` on a `TCPSocket` now returns the locally bound address and port diff --git a/base/boot.jl b/base/boot.jl index d0a686e761bf5..c818bdfd0dead 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -87,6 +87,7 @@ #struct LineNumberNode # line::Int +# file::Any # nominally Union{Symbol,Void} #end #struct LabelNode @@ -281,7 +282,8 @@ _new(:GotoNode, :Int) _new(:NewvarNode, :SlotNumber) _new(:QuoteNode, :ANY) _new(:SSAValue, :Int) -eval(:((::Type{LineNumberNode})(l::Int) = $(Expr(:new, :LineNumberNode, :l)))) +eval(:((::Type{LineNumberNode})(l::Int) = $(Expr(:new, :LineNumberNode, :l, nothing)))) +eval(:((::Type{LineNumberNode})(l::Int, f::ANY) = $(Expr(:new, :LineNumberNode, :l, :f)))) eval(:((::Type{GlobalRef})(m::Module, s::Symbol) = $(Expr(:new, :GlobalRef, :m, :s)))) eval(:((::Type{SlotNumber})(n::Int) = $(Expr(:new, :SlotNumber, :n)))) eval(:((::Type{TypedSlot})(n::Int, t::ANY) = $(Expr(:new, :TypedSlot, :n, :t)))) diff --git a/base/docs/Docs.jl b/base/docs/Docs.jl index 53552372a265d..40bbb74f42729 100644 --- a/base/docs/Docs.jl +++ b/base/docs/Docs.jl @@ -83,9 +83,11 @@ function initmeta(m::Module = current_module()) end function signature!(tv, expr::Expr) - if isexpr(expr, (:call, :macrocall)) + is_macrocall = isexpr(expr, :macrocall) + if is_macrocall || isexpr(expr, :call) sig = :(Union{Tuple{}}) - for arg in expr.args[2:end] + first_arg = is_macrocall ? 3 : 2 # skip function arguments + for arg in expr.args[first_arg:end] isexpr(arg, :parameters) && continue if isexpr(arg, :kw) # optional arg push!(sig.args, :(Tuple{$(sig.args[end].args[2:end]...)})) @@ -599,7 +601,7 @@ function __doc__!(meta, def, define) # the Base image). We just need to convert each `@__doc__` marker to an `@doc`. finddoc(def) do each each.head = :macrocall - each.args = [Symbol("@doc"), meta, each.args[end], define] + each.args = [Symbol("@doc"), nothing, meta, each.args[end], define] # TODO: forward line number info end else # `def` has already been defined during Base image gen so we just need to find and @@ -642,7 +644,7 @@ const BINDING_HEADS = [:typealias, :const, :global, :(=)] # deprecation: remove isquotedmacrocall(x) = isexpr(x, :copyast, 1) && isa(x.args[1], QuoteNode) && - isexpr(x.args[1].value, :macrocall, 1) + isexpr(x.args[1].value, :macrocall, 2) # Simple expressions / atoms the may be documented. isbasicdoc(x) = isexpr(x, :.) || isa(x, Union{QuoteNode, Symbol}) is_signature(x) = isexpr(x, :call) || (isexpr(x, :(::), 2) && isexpr(x.args[1], :call)) || isexpr(x, :where) @@ -730,7 +732,7 @@ function docm(ex) parsedoc(keywords[ex]) elseif isa(ex, Union{Expr, Symbol}) binding = esc(bindingexpr(namify(ex))) - if isexpr(ex, [:call, :macrocall]) + if isexpr(ex, :call) || isexpr(ex, :macrocall) sig = esc(signature(ex)) :($(doc)($binding, $sig)) else diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index 9134bbc3925f7..4221f061bfcc3 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -644,13 +644,6 @@ to be set after construction. See `struct` and the manual for more information. """ kw"mutable struct" -""" - @__LINE__ -> Int - -`@__LINE__` expands to the line number of the call-site. -""" -kw"@__LINE__" - """ ans diff --git a/base/docs/utils.jl b/base/docs/utils.jl index 0daf26f78c183..4a3a8b1e7a479 100644 --- a/base/docs/utils.jl +++ b/base/docs/utils.jl @@ -190,7 +190,7 @@ function repl(io::IO, s::Symbol) $(_repl(s)) end end -isregex(x) = isexpr(x, :macrocall, 2) && x.args[1] === Symbol("@r_str") && !isempty(x.args[2]) +isregex(x) = isexpr(x, :macrocall, 3) && x.args[1] === Symbol("@r_str") && !isempty(x.args[3]) repl(io::IO, ex::Expr) = isregex(ex) ? :(apropos($io, $ex)) : _repl(ex) repl(io::IO, str::AbstractString) = :(apropos($io, $str)) repl(io::IO, other) = :(@doc $(esc(other))) diff --git a/base/exports.jl b/base/exports.jl index 376a9704b6d55..3a4c2fafdbd11 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -1248,6 +1248,7 @@ export # parser internal @__FILE__, @__DIR__, + @__LINE__, @int128_str, @uint128_str, @big_str, diff --git a/base/expr.jl b/base/expr.jl index 21d66ec4a445c..d23a1909701f6 100644 --- a/base/expr.jl +++ b/base/expr.jl @@ -276,9 +276,16 @@ end remove_linenums!(ex) = ex function remove_linenums!(ex::Expr) - filter!(x->!((isa(x,Expr) && x.head === :line) || isa(x,LineNumberNode)), ex.args) + if ex.head === :body || ex.head === :block || ex.head === :quote + # remove line number expressions from metadata (not argument literal or inert) position + filter!(ex.args) do x + isa(x, Expr) && x.head === :line && return false + isa(x, LineNumberNode) && return false + return true + end + end for subex in ex.args remove_linenums!(subex) end - ex + return ex end diff --git a/base/inference.jl b/base/inference.jl index 9f73259dafcf0..45c030af11efb 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -4140,39 +4140,38 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference end do_coverage = coverage_enabled() - if do_coverage - line = method.line - if !isempty(stmts) && isa(stmts[1], LineNumberNode) - line = (shift!(stmts)::LineNumberNode).line + line::Int = method.line + file = method.file + if !isempty(stmts) + if !do_coverage && all(inlining_ignore, stmts) + empty!(stmts) + elseif isa(stmts[1], LineNumberNode) + linenode = shift!(stmts)::LineNumberNode + line = linenode.line + isa(linenode.file, Symbol) && (file = linenode.file) end + end + if do_coverage # Check if we are switching module, which is necessary to catch user # code inlined into `Base` with `--code-coverage=user`. # Assume we are inlining directly into `enclosing` instead of another # function inlined in it mod = method.module if mod === sv.mod - unshift!(stmts, Expr(:meta, :push_loc, method.file, + unshift!(stmts, Expr(:meta, :push_loc, file, method.name, line)) else - unshift!(stmts, Expr(:meta, :push_loc, method.file, + unshift!(stmts, Expr(:meta, :push_loc, file, method.name, line, mod)) end push!(stmts, Expr(:meta, :pop_loc)) elseif !isempty(stmts) - if all(inlining_ignore, stmts) - empty!(stmts) + unshift!(stmts, Expr(:meta, :push_loc, file, + method.name, line)) + if isa(stmts[end], LineNumberNode) + stmts[end] = Expr(:meta, :pop_loc) else - line::Int = method.line - if isa(stmts[1], LineNumberNode) - line = (shift!(stmts)::LineNumberNode).line - end - unshift!(stmts, Expr(:meta, :push_loc, method.file, - method.name, line)) - if isa(stmts[end], LineNumberNode) - stmts[end] = Expr(:meta, :pop_loc) - else - push!(stmts, Expr(:meta, :pop_loc)) - end + push!(stmts, Expr(:meta, :pop_loc)) end end if !isempty(stmts) && !propagate_inbounds diff --git a/base/interactiveutil.jl b/base/interactiveutil.jl index 5b959f063ea2a..34f7724736493 100644 --- a/base/interactiveutil.jl +++ b/base/interactiveutil.jl @@ -349,7 +349,7 @@ function code_warntype(io::IO, f, t::ANY) end code_warntype(f, t::ANY) = code_warntype(STDOUT, f, t) -typesof(args...) = Tuple{map(a->(isa(a,Type) ? Type{a} : typeof(a)), args)...} +typesof(args...) = Tuple{Any[ Core.Typeof(a) for a in args ]...} gen_call_with_extracted_types(fcn, ex0::Symbol) = Expr(:call, fcn, Meta.quot(ex0)) function gen_call_with_extracted_types(fcn, ex0) @@ -371,9 +371,9 @@ function gen_call_with_extracted_types(fcn, ex0) exret = Expr(:none) is_macro = false ex = expand(ex0) - if isa(ex0, Expr) && ex0.head == :macrocall # Make @edit @time 1+2 edit the macro + if isa(ex0, Expr) && ex0.head == :macrocall # Make @edit @time 1+2 edit the macro by using the types of the *expressions* is_macro = true - exret = Expr(:call, fcn, esc(ex0.args[1]), typesof(ex0.args[2:end]...)) + exret = Expr(:call, fcn, esc(ex0.args[1]), Tuple{#=__source__=#LineNumberNode, Any[ Core.Typeof(a) for a in ex0.args[3:end] ]...}) elseif !isa(ex, Expr) exret = Expr(:call, :error, "expression is not a function call or symbol") elseif ex.head == :call diff --git a/base/loading.jl b/base/loading.jl index 201b483ace14f..18c4765790531 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -538,24 +538,6 @@ function source_dir() p === nothing ? pwd() : dirname(p) end -""" - @__FILE__ -> AbstractString - -`@__FILE__` expands to a string with the absolute file path of the file containing the -macro. Returns `nothing` if run from a REPL or an empty string if evaluated by -`julia -e `. Alternatively see [`PROGRAM_FILE`](@ref). -""" -macro __FILE__() source_path() end - -""" - @__DIR__ -> AbstractString - -`@__DIR__` expands to a string with the directory part of the absolute path of the file -containing the macro. Returns the current working directory if run from a REPL or if -evaluated by `julia -e `. -""" -macro __DIR__() source_dir() end - include_from_node1(path::AbstractString) = include_from_node1(String(path)) function include_from_node1(_path::String) path, prev = _include_dependency(_path) @@ -823,3 +805,38 @@ function stale_cachefile(modpath::String, cachefile::String) close(io) end end + +""" + @__LINE__ -> Int + +`@__LINE__` expands to the line number of the location of the macrocall. +Returns `0` if the line number could not be determined. +""" +macro __LINE__() + return __source__.line +end + +""" + @__FILE__ -> AbstractString + +`@__FILE__` expands to a string with the path to the file containing the +macrocall, or an empty string if evaluated by `julia -e `. +Returns `nothing` if the macro was missing parser source information. +Alternatively see [`PROGRAM_FILE`](@ref). +""" +macro __FILE__() + __source__.file === nothing && return nothing + return String(__source__.file) +end + +""" + @__DIR__ -> AbstractString + +`@__DIR__` expands to a string with the absolute path to the directory of the file +containing the macrocall. +Returns the current working directory if run from a REPL or if evaluated by `julia -e `. +""" +macro __DIR__() + __source__.file === nothing && return nothing + return abspath(dirname(String(__source__.file))) +end diff --git a/base/math.jl b/base/math.jl index 4d8eb64fc8d32..a383ca43aeb8c 100644 --- a/base/math.jl +++ b/base/math.jl @@ -124,7 +124,7 @@ macro evalpoly(z, p...) :(s = muladd(x, x, y*y)), as..., :(muladd($ai, tt, $b))) - R = Expr(:macrocall, Symbol("@horner"), :tt, map(esc, p)...) + R = Expr(:macrocall, Symbol("@horner"), (), :tt, map(esc, p)...) :(let tt = $(esc(z)) isa(tt, Complex) ? $C : $R end) diff --git a/base/show.jl b/base/show.jl index 3e39b419f284b..f21483c699771 100644 --- a/base/show.jl +++ b/base/show.jl @@ -505,10 +505,6 @@ const prec_decl = operator_precedence(:(::)) is_expr(ex, head::Symbol) = (isa(ex, Expr) && (ex.head == head)) is_expr(ex, head::Symbol, n::Int) = is_expr(ex, head) && length(ex.args) == n -is_linenumber(ex::LineNumberNode) = true -is_linenumber(ex::Expr) = (ex.head == :line) -is_linenumber(ex) = false - is_quoted(ex) = false is_quoted(ex::QuoteNode) = true is_quoted(ex::Expr) = is_expr(ex, :quote, 1) || is_expr(ex, :inert, 1) @@ -538,18 +534,22 @@ end emphasize(io, str::AbstractString) = have_color ? print_with_color(Base.error_color(), io, str; bold = true) : print(io, uppercase(str)) -show_linenumber(io::IO, line) = print(io," # line ",line,':') -show_linenumber(io::IO, line, file) = print(io," # ", file,", line ",line,':') +show_linenumber(io::IO, line) = print(io, "#= line ", line, " =#") +show_linenumber(io::IO, line, file) = print(io, "#= ", file, ":", line, " =#") +show_linenumber(io::IO, line, file::Void) = show_linenumber(io, line) # show a block, e g if/for/etc function show_block(io::IO, head, args::Vector, body, indent::Int) - print(io, head, ' ') - show_list(io, args, ", ", indent) + print(io, head) + if !isempty(args) + print(io, ' ') + show_list(io, args, ", ", indent) + end ind = head === :module || head === :baremodule ? indent : indent + indent_width exs = (is_expr(body, :block) || is_expr(body, :body)) ? body.args : Any[body] for ex in exs - if !is_linenumber(ex); print(io, '\n', " "^ind); end + print(io, '\n', " "^ind) show_unquoted(io, ex, ind, -1) end print(io, '\n', " "^indent) @@ -566,7 +566,7 @@ end # show an indented list function show_list(io::IO, items, sep, indent::Int, prec::Int=0, enclose_operators::Bool=false) n = length(items) - if n == 0; return end + n == 0 && return indent += indent_width first = true for item in items @@ -613,7 +613,7 @@ end ## AST printing ## show_unquoted(io::IO, sym::Symbol, ::Int, ::Int) = print(io, sym) -show_unquoted(io::IO, ex::LineNumberNode, ::Int, ::Int) = show_linenumber(io, ex.line) +show_unquoted(io::IO, ex::LineNumberNode, ::Int, ::Int) = show_linenumber(io, ex.line, ex.file) show_unquoted(io::IO, ex::LabelNode, ::Int, ::Int) = print(io, ex.label, ": ") show_unquoted(io::IO, ex::GotoNode, ::Int, ::Int) = print(io, "goto ", ex.label) show_unquoted(io::IO, ex::GlobalRef, ::Int, ::Int) = print(io, ex.mod, '.', ex.name) @@ -913,12 +913,20 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int) print(io, head, ' ') show_list(io, args, ", ", indent) - elseif head === :macrocall && nargs >= 1 + elseif head === :macrocall && nargs >= 2 + # first show the line number argument as a comment + if isa(args[2], LineNumberNode) || is_expr(args[2], :line) + print(io, args[2], ' ') + end # Use the functional syntax unless specifically designated with prec=-1 + # and hide the line number argument from the argument list if prec >= 0 - show_call(io, :call, ex.args[1], ex.args[2:end], indent) + show_call(io, :call, args[1], args[3:end], indent) else - show_list(io, args, ' ', indent) + show_args = Vector{Any}(length(args) - 1) + show_args[1] = args[1] + show_args[2:end] = args[3:end] + show_list(io, show_args, ' ', indent) end elseif head === :line && 1 <= nargs <= 2 diff --git a/doc/REQUIRE b/doc/REQUIRE index e8869bde5e55a..aed1a491d5225 100644 --- a/doc/REQUIRE +++ b/doc/REQUIRE @@ -1,3 +1,3 @@ Compat 0.25.0 0.25.0+ DocStringExtensions 0.3.3 0.3.3+ -Documenter 0.10.2 0.10.2+ +Documenter 0.10.3 0.10.3+ diff --git a/doc/src/devdocs/ast.md b/doc/src/devdocs/ast.md index 62006cf4d62d3..157dd60a624c0 100644 --- a/doc/src/devdocs/ast.md +++ b/doc/src/devdocs/ast.md @@ -407,21 +407,21 @@ call. Finally, chains of comparisons have their own special expression structure ### Macros -| Input | AST | -|:------------- |:------------------------------------- | -| `@m x y` | `(macrocall @m x y)` | -| `Base.@m x y` | `(macrocall (. Base (quote @m)) x y)` | -| `@Base.m x y` | `(macrocall (. Base (quote @m)) x y)` | +| Input | AST | +|:------------- |:-------------------------------------------- | +| `@m x y` | `(macrocall @m (line) x y)` | +| `Base.@m x y` | `(macrocall (. Base (quote @m)) (line) x y)` | +| `@Base.m x y` | `(macrocall (. Base (quote @m)) (line) x y)` | ### Strings -| Input | AST | -|:--------------- |:---------------------------- | -| `"a"` | `"a"` | -| `x"y"` | `(macrocall @x_str "y")` | -| `x"y"z` | `(macrocall @x_str "y" "z")` | -| `"x = $x"` | `(string "x = " x)` | -| ``` `a b c` ``` | `(macrocall @cmd "a b c")` | +| Input | AST | +|:--------------- |:----------------------------------- | +| `"a"` | `"a"` | +| `x"y"` | `(macrocall @x_str (line) "y")` | +| `x"y"z` | `(macrocall @x_str (line) "y" "z")` | +| `"x = $x"` | `(string "x = " x)` | +| ``` `a b c` ``` | `(macrocall @cmd (line) "a b c")` | Doc string syntax: @@ -430,7 +430,7 @@ Doc string syntax: f(x) = x ``` -parses as `(macrocall (|.| Core '@doc) "some docs" (= (call f x) (block x)))`. +parses as `(macrocall (|.| Core '@doc) (line) "some docs" (= (call f x) (block x)))`. ### Imports and such @@ -449,11 +449,11 @@ parses as `(macrocall (|.| Core '@doc) "some docs" (= (call f x) (block x)))`. Julia supports more number types than many scheme implementations, so not all numbers are represented directly as scheme numbers in the AST. -| Input | AST | -|:----------------------- |:------------------------------------------------ | -| `11111111111111111111` | `(macrocall @int128_str "11111111111111111111")` | -| `0xfffffffffffffffff` | `(macrocall @uint128_str "0xfffffffffffffffff")` | -| `1111...many digits...` | `(macrocall @big_str "1111....")` | +| Input | AST | +|:----------------------- |:------------------------------------------------------- | +| `11111111111111111111` | `(macrocall @int128_str (null) "11111111111111111111")` | +| `0xfffffffffffffffff` | `(macrocall @uint128_str (null) "0xfffffffffffffffff")` | +| `1111...many digits...` | `(macrocall @big_str (null) "1111....")` | ### Block forms diff --git a/doc/src/manual/metaprogramming.md b/doc/src/manual/metaprogramming.md index 6e937ba18b8c2..50d8c6de6f924 100644 --- a/doc/src/manual/metaprogramming.md +++ b/doc/src/manual/metaprogramming.md @@ -509,6 +509,27 @@ julia> @showarg(println("Yo!")) :(println("Yo!")) ``` +In addition to the given argument list, every macro is passed an extra argument named `__source__` +providing information (in the form of a `LineNumberNode` object) about the parser location +of the `@` sign from the macro invocation. + +This allows macros to include better error diagnostic information, +and is commonly used by logging, string-parser macros, and docs, for example, +as well as to implement the `@__LINE__`, `@__FILE__`, and `@__DIR__` macros. + +The location information can be accessed by referencing `__source__.line` and `__source__.file`: + +```jldoctest +julia> macro __LOCATION__(); return QuoteNode(__source__); end + +julia> dump( + @__LOCATION__( + )) +LineNumberNode + line: Int64 2 + file: Symbol REPL[2] +``` + ### Building an advanced macro Here is a simplified definition of Julia's `@assert` macro: @@ -708,6 +729,32 @@ julia> foo() This kind of manipulation of variables should be used judiciously, but is occasionally quite handy. +Getting the hygiene rules correct can be a formidable challenge. +Before using a macro, you might want to consider whether a function closure +would be sufficient. Another useful strategy is to defer as much work as possible to runtime. +For example, many macros simply wrap their arguments in a QuoteNode or other similar Expr. +Some examples of this include `@task body` which simply returns `schedule(Task(() -> $body))`, +and `@eval expr`, which simply returns `eval(QuoteNode(expr))`. + +To demonstrate, we might rewrite the `@time` example above as: + +```julia +macro time(expr) + return :(timeit(() -> $(esc(expr)))) +end +function timeit(f) + t0 = time() + val = f() + t1 = time() + println("elapsed time: ", t1-t0, " seconds") + return val +end +``` + +However, we don't do this for a good reason: wrapping the `expr` in a new scope block (the anonymous function) +also slightly changes the meaning of the expression (the scope of any variables in it), +while we want `@time` to be usable with minimum impact on the wrapped code. + ## Code Generation When a significant amount of repetitive boilerplate code is required, it is common to generate diff --git a/doc/src/stdlib/file.md b/doc/src/stdlib/file.md index e0f5874d0d527..26e9f9d577928 100644 --- a/doc/src/stdlib/file.md +++ b/doc/src/stdlib/file.md @@ -49,7 +49,7 @@ Base.Filesystem.dirname Base.Filesystem.basename Base.@__FILE__ Base.@__DIR__ -@__LINE__ +Base.@__LINE__ Base.Filesystem.isabspath Base.Filesystem.isdirpath Base.Filesystem.joinpath diff --git a/examples/clustermanager/simple/UnixDomainCM.jl b/examples/clustermanager/simple/UnixDomainCM.jl index e3a1f7f9d350a..afffa610a21b9 100644 --- a/examples/clustermanager/simple/UnixDomainCM.jl +++ b/examples/clustermanager/simple/UnixDomainCM.jl @@ -12,7 +12,8 @@ function launch(manager::UnixDomainCM, params::Dict, launched::Array, c::Conditi for i in 1:manager.np sockname = tempname() try - cmd = `$(params[:exename]) --startup-file=no $(@__FILE__) udwrkr $sockname $cookie` + __file__ = @__FILE__ + cmd = `$(params[:exename]) --startup-file=no $__file__ udwrkr $sockname $cookie` pobj = open(cmd) wconfig = WorkerConfig() diff --git a/examples/clustermanager/simple/test_simple.jl b/examples/clustermanager/simple/test_simple.jl index 57e8a8a0f28fe..2460eadd77b53 100644 --- a/examples/clustermanager/simple/test_simple.jl +++ b/examples/clustermanager/simple/test_simple.jl @@ -1,6 +1,6 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -cmanpath = joinpath(dirname(@__FILE__), "UnixDomainCM.jl") +cmanpath = joinpath(@__DIR__, "UnixDomainCM.jl") include(cmanpath) npids = addprocs(UnixDomainCM(2)) diff --git a/src/ast.c b/src/ast.c index 6b9ac084649ff..9b3b8c124e6a6 100644 --- a/src/ast.c +++ b/src/ast.c @@ -176,19 +176,40 @@ value_t fl_invoke_julia_macro(fl_context_t *fl_ctx, value_t *args, uint32_t narg { JL_TIMING(MACRO_INVOCATION); jl_ptls_t ptls = jl_get_ptls_states(); - if (nargs < 1) - argcount(fl_ctx, "invoke-julia-macro", nargs, 1); + if (nargs < 2) // macro name and location + argcount(fl_ctx, "invoke-julia-macro", nargs, 2); jl_method_instance_t *mfunc = NULL; jl_value_t **margs; // Reserve one more slot for the result JL_GC_PUSHARGS(margs, nargs + 1); int i; - for(i=1; i < nargs; i++) margs[i] = scm_to_julia(fl_ctx, args[i], 1); + margs[0] = scm_to_julia(fl_ctx, args[0], 1); + // __source__ argument + jl_value_t *lno = scm_to_julia(fl_ctx, args[1], 1); + margs[1] = lno; + if (jl_is_expr(lno) && ((jl_expr_t*)lno)->head == line_sym) { + jl_value_t *file = jl_nothing; + jl_value_t *line = NULL; + switch (jl_expr_nargs(lno)) { // fall-through is intentional + case 2: + file = jl_exprarg(lno, 1); // file + case 1: + line = jl_exprarg(lno, 0); // line + default: ; + } + if (line == NULL) + line = jl_box_long(0); + margs[1] = jl_new_struct(jl_linenumbernode_type, line, file); + } + else if (!jl_typeis(lno, jl_linenumbernode_type)) { + margs[1] = jl_new_struct(jl_linenumbernode_type, jl_box_long(0), jl_nothing); + } + for (i = 2; i < nargs; i++) + margs[i] = scm_to_julia(fl_ctx, args[i], 1); jl_value_t *result = NULL; size_t world = jl_get_ptls_states()->world_age; JL_TRY { - margs[0] = scm_to_julia(fl_ctx, args[0], 1); margs[0] = jl_toplevel_eval(margs[0]); mfunc = jl_method_lookup(jl_gf_mtable(margs[0]), margs, nargs, 1, world); if (mfunc == NULL) { @@ -560,10 +581,13 @@ static jl_value_t *scm_to_julia_(fl_context_t *fl_ctx, value_t e, int eo) else n++; if (!eo) { - if (sym == line_sym && n==1) { + if (sym == line_sym && (n == 1 || n == 2)) { jl_value_t *linenum = scm_to_julia_(fl_ctx, car_(e), 0); - JL_GC_PUSH1(&linenum); - jl_value_t *temp = jl_new_struct(jl_linenumbernode_type, linenum); + jl_value_t *file = jl_nothing; + JL_GC_PUSH2(&linenum, &file); + if (n == 2) + file = scm_to_julia_(fl_ctx, car_(cdr_(e)), 0); + jl_value_t *temp = jl_new_struct(jl_linenumbernode_type, linenum, file); JL_GC_POP(); return temp; } @@ -724,8 +748,16 @@ static value_t julia_to_scm_(fl_context_t *fl_ctx, jl_value_t *v) // shouldn't allocate in this case. if (jl_typeis(v, jl_labelnode_type)) return julia_to_list2(fl_ctx, (jl_value_t*)label_sym, jl_fieldref(v,0)); - if (jl_typeis(v, jl_linenumbernode_type)) - return julia_to_list2(fl_ctx, (jl_value_t*)line_sym, jl_fieldref(v,0)); + if (jl_typeis(v, jl_linenumbernode_type)) { + jl_value_t *file = jl_fieldref(v,1); // non-allocating + jl_value_t *line = jl_fieldref(v,0); // allocating + value_t args = julia_to_list2(fl_ctx, line, file); + fl_gc_handle(fl_ctx, &args); + value_t hd = julia_to_scm_(fl_ctx, (jl_value_t*)line_sym); + value_t scmv = fl_cons(fl_ctx, hd, args); + fl_free_gc_handles(fl_ctx, 1); + return scmv; + } if (jl_typeis(v, jl_gotonode_type)) return julia_to_list2(fl_ctx, (jl_value_t*)goto_sym, jl_fieldref(v,0)); if (jl_typeis(v, jl_quotenode_type)) diff --git a/src/codegen.cpp b/src/codegen.cpp index 35061fe614f11..acd0c23ed5fa4 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -4083,13 +4083,13 @@ static jl_cgval_t emit_expr(jl_value_t *expr, jl_codectx_t *ctx) return emit_getfield((jl_value_t*)jl_globalref_mod(expr), jl_globalref_name(expr), ctx); } if (jl_is_labelnode(expr)) { - jl_error("Labelnode in value position"); + jl_error("LabelNode in value position"); } if (jl_is_linenode(expr)) { - jl_error("Linenode in value position"); + jl_error("LineNumberNode in value position"); } if (jl_is_gotonode(expr)) { - jl_error("Gotonode in value position"); + jl_error("GotoNode in value position"); } if (!jl_is_expr(expr)) { int needroot = true; diff --git a/src/jltypes.c b/src/jltypes.c index bc130b86cf63f..91a579b36ae50 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -1850,8 +1850,8 @@ void jl_init_types(void) jl_linenumbernode_type = jl_new_datatype(jl_symbol("LineNumberNode"), jl_any_type, jl_emptysvec, - jl_perm_symsvec(1, "line"), - jl_svec(1, jl_long_type), 0, 0, 1); + jl_perm_symsvec(2, "line", "file"), + jl_svec(2, jl_long_type, jl_any_type), 0, 0, 2); jl_labelnode_type = jl_new_datatype(jl_symbol("LabelNode"), jl_any_type, jl_emptysvec, diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 6626739da4af7..7e05db3f7ff89 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -347,10 +347,10 @@ ((eq? pred char-bin?) (fix-uint-neg neg (sized-uint-literal n s 1))) (is-float32-literal (numchk n s) (float n)) (n (if (and (integer? n) (> n 9223372036854775807)) - `(macrocall @int128_str ,s) + `(macrocall @int128_str (null) ,s) n)) - ((within-int128? s) `(macrocall @int128_str ,s)) - (else `(macrocall @big_str ,s)))))) + ((within-int128? s) `(macrocall @int128_str (null) ,s)) + (else `(macrocall @big_str (null) ,s)))))) (define (fix-uint-neg neg n) (if neg @@ -366,7 +366,7 @@ ((<= l 16) (numchk n s) (uint16 n)) ((<= l 32) (numchk n s) (uint32 n)) ((<= l 64) (numchk n s) (uint64 n)) - ((<= l 128) `(macrocall @uint128_str ,s)) + ((<= l 128) `(macrocall @uint128_str (null) ,s)) (else (error "Hex or binary literal too large for UInt128"))))) (define (sized-uint-oct-literal n s) @@ -379,7 +379,7 @@ (else (uint64 n))) (begin (if (equal? s "0o") (numchk n s)) (if (oct-within-uint128? s) - `(macrocall @uint128_str ,s) + `(macrocall @uint128_str (null) ,s) (error "Octal literal too large for UInt128")))))) (define (strip-leading-0s s) @@ -856,11 +856,11 @@ (define (maybe-negate op num) (if (eq? op '-) (if (large-number? num) - (if (eqv? (caddr num) "-170141183460469231731687303715884105728") - `(macrocall @big_str "170141183460469231731687303715884105728") - `(,(car num) ,(cadr num) ,(string.tail (caddr num) 1))) + (if (eqv? (cadddr num) "-170141183460469231731687303715884105728") + `(macrocall @big_str (null) "170141183460469231731687303715884105728") + `(,(car num) ,(cadr num) ,(caddr num) ,(string.tail (cadddr num) 1))) (if (= num -9223372036854775808) - `(macrocall @int128_str "9223372036854775808") + `(macrocall @int128_str (null) "9223372036854775808") (- num))) num)) @@ -1100,7 +1100,7 @@ (else (let ((name (parse-atom s))) (if (and (pair? name) (eq? (car name) 'macrocall)) - `(macrocall (|.| ,ex (quote ,(cadr name))) + `(macrocall (|.| ,ex (quote ,(cadr name))) ; move macrocall outside by rewriting A.@B as @A.B ,@(cddr name)) `(|.| ,ex (quote ,name)))))))) ((|.'| |'|) @@ -1117,16 +1117,17 @@ (not (operator? ex)) (not (ts:space? s))) ;; custom string and command literals; x"s" => @x_str "s" - (let* ((macstr (begin (take-token s) + (let* ((startloc (line-number-node s)) + (macstr (begin (take-token s) (parse-raw-literal s t))) (nxt (peek-token s)) (macname (macroify-name ex (macsuffix t)))) (if (and (symbol? nxt) (not (operator? nxt)) (not (ts:space? s))) ;; string literal suffix, "s"x - (loop `(macrocall ,macname ,macstr + (loop `(macrocall ,macname ,startloc ,macstr ,(string (take-token s)))) - (loop `(macrocall ,macname ,macstr)))) + (loop `(macrocall ,macname ,startloc ,macstr)))) ex)) (else ex)))))) @@ -2122,26 +2123,27 @@ ((eqv? t #\@) (take-token s) (with-space-sensitive - (let ((head (if (eq? (peek-token s) '|.|) + (let ((startloc (line-number-node s)) + (head (if (eq? (peek-token s) '|.|) (begin (take-token s) '__dot__) (parse-unary-prefix s)))) - (if (eq? head '__LINE__) - (input-port-line (ts:port s)) - (begin - (peek-token s) - (if (ts:space? s) - `(macrocall ,(macroify-name head) - ,@(parse-space-separated-exprs s)) - (let ((call (parse-call-chain s head #t))) - (if (and (pair? call) (eq? (car call) 'call)) - `(macrocall ,(macroify-name (cadr call)) ,@(cddr call)) - `(macrocall ,(macroify-name call) - ,@(parse-space-separated-exprs s)))))))))) - + (peek-token s) + (if (ts:space? s) + `(macrocall ,(macroify-name head) + ,startloc + ,@(parse-space-separated-exprs s)) + (let ((call (parse-call-chain s head #t))) + (if (and (pair? call) (eq? (car call) 'call)) + `(macrocall ,(macroify-name (cadr call)) + ,startloc + ,@(cddr call)) + `(macrocall ,(macroify-name call) + ,startloc + ,@(parse-space-separated-exprs s)))))))) ;; command syntax ((eqv? t #\`) (take-token s) - `(macrocall @cmd ,(parse-raw-literal s #\`))) + `(macrocall @cmd ,(line-number-node s) ,(parse-raw-literal s #\`))) ((or (string? t) (number? t) (large-number? t)) (take-token s)) @@ -2167,16 +2169,20 @@ (and (pair? e) (eq? 'string (car e))) ; string interpolation (and (length= e 3) (eq? (car e) 'macrocall) (simple-string-literal? (caddr e)) + (eq? (cadr e) '@doc_str)) + (and (length= e 4) (eq? (car e) 'macrocall) + (simple-string-literal? (cadddr e)) (eq? (cadr e) '@doc_str)))) (define (parse-docstring s production) - (let* ((ex (production s))) + (let ((startloc (line-number-node s)) ; be sure to use the line number from the head of the docstring + (ex (production s))) (if (and (doc-string-literal? ex) (let loop ((t (peek-token s))) (cond ((closing-token? t) #f) ((newline? t) (take-token s) (loop (peek-token s))) (else #t)))) - `(macrocall (core @doc) ,ex ,(production s)) + `(macrocall (core @doc) ,startloc ,ex ,(production s)) ex))) ;; --- main entry point --- diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 86ed90c300ac6..78bdb2cd76d55 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -1162,6 +1162,7 @@ (error "macros cannot accept keyword arguments")) (expand-forms `(function (call ,(symbol (string #\@ (cadr (cadr e)))) + (|::| __source__ (core LineNumberNode)) ,@(map (lambda (v) (if (symbol? v) `(|::| ,v (core ANY)) diff --git a/src/julia.h b/src/julia.h index 3af8aad0bf450..9dbeff414a06e 100644 --- a/src/julia.h +++ b/src/julia.h @@ -741,17 +741,18 @@ STATIC_INLINE void jl_array_uint8_set(void *a, size_t i, uint8_t x) #define jl_exprargset(e, n, v) jl_array_ptr_set(((jl_expr_t*)(e))->args, n, v) #define jl_expr_nargs(e) jl_array_len(((jl_expr_t*)(e))->args) -#define jl_fieldref(s,i) jl_get_nth_field(((jl_value_t*)s),i) +#define jl_fieldref(s,i) jl_get_nth_field(((jl_value_t*)(s)),i) #define jl_nfields(v) jl_datatype_nfields(jl_typeof(v)) // Not using jl_fieldref to avoid allocations -#define jl_linenode_line(x) (((intptr_t*)x)[0]) -#define jl_labelnode_label(x) (((intptr_t*)x)[0]) -#define jl_slot_number(x) (((intptr_t*)x)[0]) -#define jl_typedslot_get_type(x) (((jl_value_t**)x)[1]) -#define jl_gotonode_label(x) (((intptr_t*)x)[0]) -#define jl_globalref_mod(s) (*(jl_module_t**)s) -#define jl_globalref_name(s) (((jl_sym_t**)s)[1]) +#define jl_linenode_line(x) (((intptr_t*)(x))[0]) +#define jl_linenode_file(x) (((jl_value_t**)(x))[1]) +#define jl_labelnode_label(x) (((intptr_t*)(x))[0]) +#define jl_slot_number(x) (((intptr_t*)(x))[0]) +#define jl_typedslot_get_type(x) (((jl_value_t**)(x))[1]) +#define jl_gotonode_label(x) (((intptr_t*)(x))[0]) +#define jl_globalref_mod(s) (*(jl_module_t**)(s)) +#define jl_globalref_name(s) (((jl_sym_t**)(s))[1]) #define jl_nparams(t) jl_svec_len(((jl_datatype_t*)(t))->parameters) #define jl_tparam0(t) jl_svecref(((jl_datatype_t*)(t))->parameters, 0) diff --git a/src/method.c b/src/method.c index 5a4f9f8100f92..30e7a702823e2 100644 --- a/src/method.c +++ b/src/method.c @@ -300,19 +300,27 @@ JL_DLLEXPORT jl_code_info_t *jl_code_for_staged(jl_method_instance_t *linfo) jl_array_ptr_set(ex->args, 0, argnames); jl_fill_argnames((jl_array_t*)linfo->def->source, argnames); + // build the rest of the body to pass to expand jl_expr_t *scopeblock = jl_exprn(jl_symbol("scope-block"), 1); jl_array_ptr_set(ex->args, 1, scopeblock); - jl_expr_t *body = jl_exprn(jl_symbol("block"), 2); - jl_array_ptr_set(((jl_expr_t*)jl_exprarg(ex,1))->args, 0, body); + jl_expr_t *body = jl_exprn(jl_symbol("block"), 3); + jl_array_ptr_set(((jl_expr_t*)jl_exprarg(ex, 1))->args, 0, body); + + // add location meta linenum = jl_box_long(linfo->def->line); - jl_value_t *linenode = jl_new_struct(jl_linenumbernode_type, linenum); + jl_value_t *linenode = jl_new_struct(jl_linenumbernode_type, linenum, linfo->def->file); jl_array_ptr_set(body->args, 0, linenode); + jl_expr_t *pushloc = jl_exprn(meta_sym, 3); + jl_array_ptr_set(body->args, 1, pushloc); + jl_array_ptr_set(pushloc->args, 0, jl_symbol("push_loc")); + jl_array_ptr_set(pushloc->args, 1, linfo->def->file); // file + jl_array_ptr_set(pushloc->args, 2, jl_symbol("@generated body")); // function // invoke code generator assert(jl_nparams(tt) == jl_array_len(argnames) || (linfo->def->isva && (jl_nparams(tt) >= jl_array_len(argnames) - 1))); - jl_array_ptr_set(body->args, 1, - jl_call_staged(sparam_vals, generator, jl_svec_data(tt->parameters), jl_nparams(tt))); + jl_value_t *generated_body = jl_call_staged(sparam_vals, generator, jl_svec_data(tt->parameters), jl_nparams(tt)); + jl_array_ptr_set(body->args, 2, generated_body); if (linfo->def->sparam_syms != jl_emptysvec) { // mark this function as having the same static parameters as the generator @@ -335,8 +343,17 @@ JL_DLLEXPORT jl_code_info_t *jl_code_for_staged(jl_method_instance_t *linfo) jl_array_t *stmts = (jl_array_t*)func->code; size_t i, l; for (i = 0, l = jl_array_len(stmts); i < l; i++) { - jl_array_ptr_set(stmts, i, jl_resolve_globals(jl_array_ptr_ref(stmts, i), linfo->def->module, env)); + jl_value_t *stmt = jl_array_ptr_ref(stmts, i); + stmt = jl_resolve_globals(stmt, linfo->def->module, env); + jl_array_ptr_set(stmts, i, stmt); } + + // add pop_loc meta + jl_array_ptr_1d_push(stmts, jl_nothing); + jl_expr_t *poploc = jl_exprn(meta_sym, 1); + jl_array_ptr_set(stmts, jl_array_len(stmts) - 1, poploc); + jl_array_ptr_set(poploc->args, 0, jl_symbol("pop_loc")); + ptls->in_pure_callback = last_in; jl_lineno = last_lineno; ptls->current_module = last_m; @@ -401,10 +418,25 @@ static void jl_method_set_source(jl_method_t *m, jl_code_info_t *src) int set_lineno = 0; for (i = 0; i < n; i++) { jl_value_t *st = jl_array_ptr_ref(stmts, i); - if (jl_is_expr(st) && ((jl_expr_t*)st)->head == line_sym) { + if (jl_is_linenode(st)) { if (!set_lineno) { - m->line = jl_unbox_long(jl_exprarg(st, 0)); - m->file = (jl_sym_t*)jl_exprarg(st, 1); + m->line = jl_linenode_line(st); + jl_value_t *file = jl_linenode_file(st); + if (jl_is_symbol(file)) + m->file = (jl_sym_t*)file; + st = jl_nothing; + set_lineno = 1; + } + } + else if (jl_is_expr(st) && ((jl_expr_t*)st)->head == line_sym) { + if (!set_lineno) { + switch (jl_expr_nargs(st)) { // fall-through is intentional + case 2: + m->file = (jl_sym_t*)jl_exprarg(st, 1); + case 1: + m->line = jl_unbox_long(jl_exprarg(st, 0)); + default: ; + } st = jl_nothing; set_lineno = 1; } diff --git a/src/rtutils.c b/src/rtutils.c index 9397cab1ec0a0..b04ad0228a28f 100644 --- a/src/rtutils.c +++ b/src/rtutils.c @@ -757,7 +757,9 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt n += jl_printf(out, ">"); } else if (vt == jl_linenumbernode_type) { - n += jl_printf(out, "# line %" PRIuPTR, jl_linenode_line(v)); + n += jl_printf(out, "#= "); + n += jl_static_show_x(out, jl_linenode_file(v), depth); + n += jl_printf(out, ":%" PRIuPTR " =#", jl_linenode_line(v)); } else if (vt == jl_expr_type) { jl_expr_t *e = (jl_expr_t*)v; diff --git a/test/ambiguous.jl b/test/ambiguous.jl index 32139c496a44f..049cffb728158 100644 --- a/test/ambiguous.jl +++ b/test/ambiguous.jl @@ -1,7 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license # DO NOT ALTER ORDER OR SPACING OF METHODS BELOW -const lineoffset = @__LINE__ + 0 # XXX: __LINE__ at the end of a line is off-by-one +const lineoffset = @__LINE__ ambig(x, y) = 1 ambig(x::Integer, y) = 2 ambig(x, y::Integer) = 3 diff --git a/test/docs.jl b/test/docs.jl index 46b1523e56401..d1d65d5615ae7 100644 --- a/test/docs.jl +++ b/test/docs.jl @@ -48,7 +48,7 @@ end # General tests for docstrings. -const LINE_NUMBER = @__LINE__+1 +const LINE_NUMBER = @__LINE__() + 1 "DocsTest" module DocsTest @@ -906,23 +906,24 @@ let x = Binding(Main, :⊕) @test parse(string(x)) == :(⊕) end +doc_util_path = Symbol(joinpath("docs", "utils.jl")) # Docs.helpmode tests: we test whether the correct expressions are being generated here, # rather than complete integration with Julia's REPL mode system. for (line, expr) in Pair[ "sin" => :sin, "Base.sin" => :(Base.sin), - "@time(x)" => :(@time(x)), - "@time" => :(:@time), - ":@time" => :(:@time), - "@time()" => :(@time), - "Base.@time()" => :(Base.@time), + "@time(x)" => Expr(:macrocall, Symbol("@time"), LineNumberNode(1, :none), :x), + "@time" => Expr(:macrocall, Symbol("@time"), LineNumberNode(1, :none)), + ":@time" => Expr(:quote, (Expr(:macrocall, Symbol("@time"), LineNumberNode(1, :none)))), + "@time()" => Expr(:macrocall, Symbol("@time"), LineNumberNode(1, :none)), + "Base.@time()" => Expr(:macrocall, Expr(:., :Base, QuoteNode(Symbol("@time"))), LineNumberNode(1, :none)), "ccall" => :ccall, # keyword "while " => :while, # keyword, trailing spaces should be stripped. "0" => 0, "\"...\"" => "...", - "r\"...\"" => :(r"..."), + "r\"...\"" => Expr(:macrocall, Symbol("@r_str"), LineNumberNode(1, :none), "...") ] - @test Docs.helpmode(line) == :(Base.Docs.@repl($STDOUT, $expr)) + @test Docs.helpmode(line) == Expr(:macrocall, Expr(:., Expr(:., :Base, QuoteNode(:Docs)), QuoteNode(Symbol("@repl"))), LineNumberNode(117, doc_util_path), STDOUT, expr) buf = IOBuffer() @test eval(Base, Docs.helpmode(buf, line)) isa Union{Base.Markdown.MD,Void} end @@ -961,8 +962,8 @@ dynamic_test.x = "test 2" @test @doc(dynamic_test) == "test 2 Union{}" @test @doc(dynamic_test(::String)) == "test 2 Tuple{String}" -@test Docs._repl(:(dynamic_test(1.0))) == :(@doc $(Expr(:escape, :(dynamic_test(::typeof(1.0)))))) -@test Docs._repl(:(dynamic_test(::String))) == :(@doc $(Expr(:escape, :(dynamic_test(::String))))) +@test Docs._repl(:(dynamic_test(1.0))) == Expr(:macrocall, Symbol("@doc"), LineNumberNode(204, doc_util_path), esc(:(dynamic_test(::typeof(1.0))))) +@test Docs._repl(:(dynamic_test(::String))) == Expr(:macrocall, Symbol("@doc"), LineNumberNode(204, doc_util_path), esc(:(dynamic_test(::String)))) # Equality testing diff --git a/test/loading.jl b/test/loading.jl index 80f14a8ba08db..b50ca7960966e 100644 --- a/test/loading.jl +++ b/test/loading.jl @@ -2,22 +2,24 @@ using Base.Test -@test @__LINE__ == 5 +@test @__LINE__() == 5 include("test_sourcepath.jl") thefname = "the fname!//\\&\1*" include_string_test_func = include_string("include_string_test() = @__FILE__", thefname) -@test include_string_test_func() == Base.source_path() +@test include_string_test_func() == thefname @test include_string("Base.source_path()", thefname) == Base.source_path() @test basename(@__FILE__) == "loading.jl" @test isabspath(@__FILE__) @test isdir(@__DIR__) @test @__DIR__() == dirname(@__FILE__) -let exename = `$(Base.julia_cmd()) --precompiled=yes --startup-file=no` - wd = sprint(show, pwd()) +let exename = `$(Base.julia_cmd()) --precompiled=yes --startup-file=no`, + wd = sprint(show, abspath(pwd(), "")), + s_dir = sprint(show, joinpath(realpath(tempdir()), "")) + @test wd != s_dir @test readchomp(`$exename -E "@__DIR__" -i`) == wd - @test readchomp(`$exename -E "cd(()->eval(:(@__DIR__)), tempdir())" -i`) != wd + @test readchomp(`$exename -E "cd(()->eval(:(@__DIR__)), $s_dir)" -i`) == s_dir @test readchomp(`$exename -E "@__DIR__"`) == wd # non-interactive end diff --git a/test/parse.jl b/test/parse.jl index 12377dbdbb01e..c45e8e297a398 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -147,10 +147,10 @@ macro test999_str(args...); args; end # issue 11970 @test parseall(""" -macro f(args...) end; @f "" + macro f(args...) end; @f "macro argument" """) == Expr(:toplevel, - Expr(:macro, Expr(:call, :f, Expr(:..., :args)), Expr(:block, Expr(:line, 1, :none))), - Expr(:macrocall, Symbol("@f"), "")) + Expr(:macro, Expr(:call, :f, Expr(:..., :args)), Expr(:block, LineNumberNode(1, :none))), + Expr(:macrocall, Symbol("@f"), LineNumberNode(1, :none), "macro argument")) # blocks vs. tuples @test parse("()") == Expr(:tuple) @@ -351,7 +351,7 @@ parsehex(s) = parse(Int,s,16) # issue #17705 @test parse("2e3_") == Expr(:call, :*, 2e3, :_) @test parse("2e-3_") == Expr(:call, :*, 2e-3, :_) -@test parse("2e3_\"x\"") == Expr(:call, :*, 2e3, Expr(:macrocall, Symbol("@__str"), "x")) +@test parse("2e3_\"x\"") == Expr(:call, :*, 2e3, Expr(:macrocall, Symbol("@__str"), LineNumberNode(1, :none), "x")) # multibyte spaces @test parse(Int, "3\u2003\u202F") == 3 @@ -514,7 +514,7 @@ let b = IOBuffer(""" end f() """) - @test Base.parse_input_line(b) == Expr(:let, Expr(:block, Expr(:line, 2, :none), :x), Expr(:(=), :x, :x)) + @test Base.parse_input_line(b) == Expr(:let, Expr(:block, LineNumberNode(2, :none), :x), Expr(:(=), :x, :x)) @test Base.parse_input_line(b) == Expr(:call, :f) @test Base.parse_input_line(b) === nothing end @@ -574,7 +574,7 @@ f16517() = try error(); catch 0; end # issue #16671 @test parse("1.") === 1.0 -isline(x) = isa(x,Expr) && x.head === :line +isline(x) = isa(x, LineNumberNode) # issue #16672 @test count(isline, parse("begin end").args) == 1 @@ -584,9 +584,9 @@ isline(x) = isa(x,Expr) && x.head === :line # issue #16736 let - local lineoffset0 = @__LINE__ + 1 - local lineoffset1 = @__LINE__ - local lineoffset2 = @__LINE__ - 1 + local lineoffset0 = @__LINE__() + 1 + local lineoffset1 = @__LINE__() + local lineoffset2 = @__LINE__() - 1 @test lineoffset0 == lineoffset1 == lineoffset2 end @@ -596,13 +596,13 @@ end y end") == Expr(:try, Expr(:block, - Expr(:line, 1, :none), + LineNumberNode(1, :none), :x), false, Expr(:block, - Expr(:line, 2, :none), + LineNumberNode(2, :none), Expr(:call, :test), - Expr(:line, 3, :none), + LineNumberNode(3, :none), :y)) # test that pre 0.5 deprecated syntax is a parse error @@ -775,12 +775,12 @@ module B15838 end @test A15838.@f() === nothing @test A15838.@f(1) === :b -let nometh = expand(:(A15838.@f(1, 2))) +let nometh = expand(:(A15838.@f(1, 2))), __source__ = LineNumberNode(@__LINE__, Symbol(@__FILE__)) @test (nometh::Expr).head === :error @test length(nometh.args) == 1 e = nometh.args[1]::MethodError @test e.f === getfield(A15838, Symbol("@f")) - @test e.args === (1,2) + @test e.args === (__source__, 1, 2) end # issue 10046 @@ -904,8 +904,8 @@ f1_exprs = get_expr_list(@code_typed(f1(1))[1]) f2_exprs = get_expr_list(@code_typed(f2(1))[1]) @test Meta.isexpr(f1_exprs[end], :return) -@test is_pop_loc(f2_exprs[end - 1]) -@test Meta.isexpr(f2_exprs[end], :return) +@test is_pop_loc(f2_exprs[end]) +@test Meta.isexpr(f2_exprs[end - 1], :return) if Base.JLOptions().code_coverage != 0 && Base.JLOptions().can_inline != 0 @test count_meta_loc(f1_exprs) == 1 @@ -924,10 +924,10 @@ end @test :(x`s\`"\x\$\\`) == :(@x_cmd "s`\"\\x\\\$\\\\") # Check multiline command literals -@test :``` +@test :(@cmd "multiline\ncommand\n") == :``` multiline command -``` == :(@cmd "multiline\ncommand\n") +``` macro julia_cmd(s) Meta.quot(parse(s)) @@ -980,7 +980,7 @@ let ..(x,y) = x + y end # issue #7669 -@test parse("@a(b=1, c=2)") == Expr(:macrocall, Symbol("@a"), :(b=1), :(c=2)) +@test parse("@a(b=1, c=2)") == Expr(:macrocall, Symbol("@a"), LineNumberNode(1, :none), :(b=1), :(c=2)) # issue #19685 let f = function (x; kw...) @@ -1070,7 +1070,7 @@ end @test expand(:(@err20000)) == Expr(:error, "oops!") # issue #20000 -@test parse("@m(a; b=c)") == Expr(:macrocall, Symbol("@m"), +@test parse("@m(a; b=c)") == Expr(:macrocall, Symbol("@m"), LineNumberNode(1, :none), Expr(:parameters, Expr(:kw, :b, :c)), :a) # issue #21054 diff --git a/test/reflection.jl b/test/reflection.jl index d66098e3fde77..0e00763f70c26 100644 --- a/test/reflection.jl +++ b/test/reflection.jl @@ -337,7 +337,7 @@ end return true end end -@test functionloc(f14346)[2] == @__LINE__-4 +@test functionloc(f14346)[2] == @__LINE__() - 4 # test jl_get_llvm_fptr. We test functions both in and definitely not in the system image definitely_not_in_sysimg() = nothing @@ -366,10 +366,10 @@ let using .MacroTest a = 1 m = getfield(current_module(), Symbol("@macrotest")) - @test which(m, Tuple{Int,Symbol})==@which @macrotest 1 a - @test which(m, Tuple{Int,Int})==@which @macrotest 1 1 + @test which(m, Tuple{LineNumberNode, Int, Symbol}) == @which @macrotest 1 a + @test which(m, Tuple{LineNumberNode, Int, Int}) == @which @macrotest 1 1 - @test first(methods(m,Tuple{Int, Int}))==@which MacroTest.@macrotest 1 1 + @test first(methods(m, Tuple{LineNumberNode, Int, Int})) == @which MacroTest.@macrotest 1 1 @test functionloc(@which @macrotest 1 1) == @functionloc @macrotest 1 1 end diff --git a/test/replutil.jl b/test/replutil.jl index 63e3091c9b7a7..ac4bec2258976 100644 --- a/test/replutil.jl +++ b/test/replutil.jl @@ -12,7 +12,7 @@ function test_have_color(buf, color, no_color) end cfile = " at $(@__FILE__):" -c1line = @__LINE__ + 1 +c1line = @__LINE__() + 1 method_c1(x::Float64, s::AbstractString...) = true buf = IOBuffer() @@ -59,7 +59,7 @@ color = "\e[0m\nClosest candidates are:\n method_c2(\e[1m\e[31m::Int32\e[0m, :: no_color = no_color = "\nClosest candidates are:\n method_c2(!Matched::Int32, ::Float64, ::Any...)$cfile$(c2line+2)\n method_c2(!Matched::Int32, ::Any...)$cfile$(c2line+1)\n method_c2(::T<:Real, ::T<:Real, !Matched::T<:Real) where T<:Real$cfile$(c2line+5)\n ..." test_have_color(buf, color, no_color) -c3line = @__LINE__ + 1 +c3line = @__LINE__() + 1 method_c3(x::Float64, y::Float64) = true Base.show_method_candidates(buf, Base.MethodError(method_c3,(1.,))) color = "\e[0m\nClosest candidates are:\n method_c3(::Float64, \e[1m\e[31m::Float64\e[0m)$cfile$c3line\e[0m" @@ -75,7 +75,7 @@ test_have_color(buf, "\e[0m\nClosest candidates are:\n method_c4(::AbstractString)$cfile$(c4line+2)\n method_c4()$cfile$(c4line+1)\e[0m", "\nClosest candidates are:\n method_c4(::AbstractString)$cfile$(c4line+2)\n method_c4()$cfile$(c4line+1)") -c5line = @__LINE__ + 1 +c5line = @__LINE__() + 1 method_c5(::Type{Float64}) = true Base.show_method_candidates(buf, MethodError(method_c5,(Float64,))) test_have_color(buf, "\e[0m\nClosest candidates are:\n method_c5(::Type{Float64})$cfile$c5line\e[0m", @@ -92,12 +92,12 @@ for f in [getindex, setindex!] test_have_color(buf, "", "") end -PR16155line = @__LINE__ + 2 +PR16155line = @__LINE__() + 2 mutable struct PR16155 a::Int64 b end -PR16155line2 = @__LINE__ + 1 +PR16155line2 = @__LINE__() + 1 (::Type{T}){T<:PR16155}(arg::Any) = "replace call-to-convert method from sysimg" Base.show_method_candidates(buf, MethodError(PR16155,(1.0, 2.0, Int64(3)))) @@ -146,12 +146,12 @@ else @test contains(error_out3, "method_c6_in_module(::Any; y)$cfile$(c6mline + 3) got unsupported keyword argument \"x\"") end -c7line = @__LINE__ + 1 +c7line = @__LINE__() + 1 method_c7(a, b; kargs...) = a Base.show_method_candidates(buf, MethodError(method_c7, (1, 1)), [(:x, 1), (:y, 2)]) test_have_color(buf, "\e[0m\nClosest candidates are:\n method_c7(::Any, ::Any; kargs...)$cfile$c7line\e[0m", "\nClosest candidates are:\n method_c7(::Any, ::Any; kargs...)$cfile$c7line") -c8line = @__LINE__ + 1 +c8line = @__LINE__() + 1 method_c8(a, b; y=1, w=1) = a Base.show_method_candidates(buf, MethodError(method_c8, (1, 1)), [(:x, 1), (:y, 2), (:z, 1), (:w, 1)]) test_have_color(buf, "\e[0m\nClosest candidates are:\n method_c8(::Any, ::Any; y, w)$cfile$c8line\e[1m\e[31m got unsupported keyword arguments \"x\", \"z\"\e[0m\e[0m", @@ -344,7 +344,7 @@ end @test stringmime("text/plain", FunctionLike()) == "(::FunctionLike) (generic function with 0 methods)" @test ismatch(r"^@doc \(macro with \d+ method[s]?\)$", stringmime("text/plain", getfield(Base, Symbol("@doc")))) -method_defs_lineno = @__LINE__+1 +method_defs_lineno = @__LINE__() + 1 Base.Symbol() = throw(ErrorException("1")) (::Symbol)() = throw(ErrorException("2")) EightBitType() = throw(ErrorException("3")) @@ -361,15 +361,24 @@ let err_str, sp = Base.source_path() sn = basename(sp) - @test sprint(show, which(Symbol, Tuple{})) == "Symbol() in $curmod_str at $sp:$(method_defs_lineno + 0)" - @test sprint(show, which(:a, Tuple{})) == "(::Symbol)() in $curmod_str at $sp:$(method_defs_lineno + 1)" - @test sprint(show, which(EightBitType, Tuple{})) == "$(curmod_prefix)EightBitType() in $curmod_str at $sp:$(method_defs_lineno + 2)" - @test sprint(show, which(reinterpret(EightBitType, 0x54), Tuple{})) == "(::$(curmod_prefix)EightBitType)() in $curmod_str at $sp:$(method_defs_lineno + 3)" - @test sprint(show, which(EightBitTypeT, Tuple{})) == "(::Type{$(curmod_prefix)EightBitTypeT})() in $curmod_str at $sp:$(method_defs_lineno + 4)" - @test sprint(show, which(EightBitTypeT{Int32}, Tuple{})) == "(::Type{$(curmod_prefix)EightBitTypeT{T}})() where T in $curmod_str at $sp:$(method_defs_lineno + 5)" - @test sprint(show, which(reinterpret(EightBitTypeT{Int32}, 0x54), Tuple{})) == "(::$(curmod_prefix)EightBitTypeT)() in $curmod_str at $sp:$(method_defs_lineno + 6)" - @test startswith(sprint(show, which(getfield(Base, Symbol("@doc")), Tuple{Vararg{Any}})), "@doc(x...) in Core at boot.jl:") - @test startswith(sprint(show, which(FunctionLike(), Tuple{})), "(::$(curmod_prefix)FunctionLike)() in $curmod_str at $sp:$(method_defs_lineno + 7)") + @test sprint(show, which(Symbol, Tuple{})) == + "Symbol() in $curmod_str at $sp:$(method_defs_lineno + 0)" + @test sprint(show, which(:a, Tuple{})) == + "(::Symbol)() in $curmod_str at $sp:$(method_defs_lineno + 1)" + @test sprint(show, which(EightBitType, Tuple{})) == + "$(curmod_prefix)EightBitType() in $curmod_str at $sp:$(method_defs_lineno + 2)" + @test sprint(show, which(reinterpret(EightBitType, 0x54), Tuple{})) == + "(::$(curmod_prefix)EightBitType)() in $curmod_str at $sp:$(method_defs_lineno + 3)" + @test sprint(show, which(EightBitTypeT, Tuple{})) == + "(::Type{$(curmod_prefix)EightBitTypeT})() in $curmod_str at $sp:$(method_defs_lineno + 4)" + @test sprint(show, which(EightBitTypeT{Int32}, Tuple{})) == + "(::Type{$(curmod_prefix)EightBitTypeT{T}})() where T in $curmod_str at $sp:$(method_defs_lineno + 5)" + @test sprint(show, which(reinterpret(EightBitTypeT{Int32}, 0x54), Tuple{})) == + "(::$(curmod_prefix)EightBitTypeT)() in $curmod_str at $sp:$(method_defs_lineno + 6)" + @test startswith(sprint(show, which(getfield(Base, Symbol("@doc")), Tuple{LineNumberNode, Vararg{Any}})), + "@doc(__source__::LineNumberNode, x...) in Core at boot.jl:") + @test startswith(sprint(show, which(FunctionLike(), Tuple{})), + "(::$(curmod_prefix)FunctionLike)() in $curmod_str at $sp:$(method_defs_lineno + 7)") @test stringmime("text/plain", FunctionLike()) == "(::FunctionLike) (generic function with 1 method)" @test stringmime("text/plain", Core.arraysize) == "arraysize (built-in function)" diff --git a/test/show.jl b/test/show.jl index 44e3cca5a3199..ca12dd1c8d336 100644 --- a/test/show.jl +++ b/test/show.jl @@ -15,8 +15,8 @@ struct T5589 end @test replstr(T5589(Array{String,1}(100))) == "$(curmod_prefix)T5589(String[#undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef … #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef, #undef])" -@test replstr(parse("mutable struct X end")) == ":(mutable struct X # none, line 1:\n end)" -@test replstr(parse("struct X end")) == ":(struct X # none, line 1:\n end)" +@test replstr(parse("mutable struct X end")) == ":(mutable struct X\n #= none:1 =#\n end)" +@test replstr(parse("struct X end")) == ":(struct X\n #= none:1 =#\n end)" s = "ccall(:f, Int, (Ptr{Void},), &x)" @test replstr(parse(s)) == ":($s)" @@ -42,12 +42,14 @@ macro test_repr(x) local x1 = parse($x) local x2 = eval(parse(repr(x1))) local x3 = eval(parse(repr(x2))) - x3 == x1 ? nothing : error(string( - "repr test failed:", - "\noriginal: ", $x, - "\n\nparsed: ", x2, "\n", sprint(dump, x2), - "\n\nreparsed: ", x3, "\n", sprint(dump, x3) - )) + if x3 != x1 + error(string( + "repr test failed:", + "\noriginal: ", $x, + "\n\nparsed: ", x2, "\n", sprint(dump, x2), + "\n\nreparsed: ", x3, "\n", sprint(dump, x3) + )) + end end end end @@ -94,76 +96,128 @@ end # control structures (shamelessly stolen from base/bitarray.jl) @test_repr """mutable struct BitArray{N} <: AbstractArray{Bool, N} + # line meta chunks::Vector{UInt64} + # line meta len::Int + # line meta dims::NTuple{N,Int} + # line meta function BitArray(dims::Int...) + # line meta if length(dims) != N + # line meta error(\"number of dimensions must be \$N (got \$(length(dims)))\") end + # line meta n = 1 + # line meta for d in dims + # line meta if d < 0 + # line meta error(\"dimension size must be nonnegative (got \$d)\") end + # line meta n *= d end + # line meta nc = num_bit_chunks(n) + # line meta chunks = Array{UInt64,1}(nc) + # line meta if nc > 0 + # line meta chunks[end] = UInt64(0) end + # line meta b = new(chunks, n) + # line meta if N != 1 + # line meta b.dims = dims end + # line meta return b end end""" @test_repr """function copy_chunks(dest::Vector{UInt64}, pos_d::Integer, src::Vector{UInt64}, pos_s::Integer, numbits::Integer) + # line meta if numbits == 0 + # line meta return end + # line meta if dest === src && pos_d > pos_s + # line meta return copy_chunks_rtol(dest, pos_d, pos_s, numbits) end + # line meta kd0, ld0 = get_chunks_id(pos_d) + # line meta kd1, ld1 = get_chunks_id(pos_d + numbits - 1) + # line meta ks0, ls0 = get_chunks_id(pos_s) + # line meta ks1, ls1 = get_chunks_id(pos_s + numbits - 1) + # line meta delta_kd = kd1 - kd0 + # line meta delta_ks = ks1 - ks0 + # line meta u = _msk64 + # line meta if delta_kd == 0 + # line meta msk_d0 = ~(u << ld0) | (u << ld1 << 1) else + # line meta msk_d0 = ~(u << ld0) + # line meta msk_d1 = (u << ld1 << 1) end + # line meta if delta_ks == 0 + # line meta msk_s0 = (u << ls0) & ~(u << ls1 << 1) else + # line meta msk_s0 = (u << ls0) end + # line meta chunk_s0 = glue_src_bitchunks(src, ks0, ks1, msk_s0, ls0) + # line meta dest[kd0] = (dest[kd0] & msk_d0) | ((chunk_s0 << ld0) & ~msk_d0) + # line meta if delta_kd == 0 + # line meta return end + # line meta for i = 1 : kd1 - kd0 - 1 + # line meta chunk_s1 = glue_src_bitchunks(src, ks0 + i, ks1, msk_s0, ls0) + # line meta chunk_s = (chunk_s0 >>> (63 - ld0) >>> 1) | (chunk_s1 << ld0) + # line meta dest[kd0 + i] = chunk_s + # line meta chunk_s0 = chunk_s1 end + # line meta if ks1 >= ks0 + delta_kd + # line meta chunk_s1 = glue_src_bitchunks(src, ks0 + delta_kd, ks1, msk_s0, ls0) else + # line meta chunk_s1 = UInt64(0) end + # line meta chunk_s = (chunk_s0 >>> (63 - ld0) >>> 1) | (chunk_s1 << ld0) + # line meta dest[kd1] = (dest[kd1] & msk_d1) | (chunk_s & ~msk_d1) + # line meta return end""" @@ -201,13 +255,21 @@ end""" @test_repr "[1 2 3; 4 5 6; 7 8 9]'" @test_repr "baremodule X +# line meta +# line meta importall ..A.b +# line meta import ...B.c +# line meta import D +# line meta import B.C.D.E.F.g end" @test_repr "baremodule Y +# line meta +# line meta export A, B, C +# line meta export D, E, F end" @@ -261,22 +323,22 @@ end @test string(:(-{x})) == "-{x}" # issue #11393 -@test_repr "@m(x,y) + z" -@test_repr "(@m(x,y),z)" -@test_repr "[@m(x,y),z]" -@test_repr "A[@m(x,y),z]" -@test_repr "T{@m(x,y),z}" +@test_repr "@m(x, y) + z" +@test_repr "(@m(x, y), z)" +@test_repr "[@m(x, y), z]" +@test_repr "A[@m(x, y), z]" +@test_repr "T{@m(x, y), z}" @test_repr "@m x @n(y) z" -@test_repr "f(@m(x,y);z=@n(a))" -@test_repr "@m(x,y).z" -@test_repr "::@m(x,y)+z" +@test_repr "f(@m(x, y); z=@n(a))" +@test_repr "@m(x, y).z" +@test_repr "::@m(x, y) + z" @test_repr "[@m(x) y z]" @test_repr "[@m(x) y; z]" @test_repr "let @m(x), y=z; end" -@test repr(:(@m x y)) == ":(@m x y)" -@test string(:(@m x y)) == "@m x y" -@test string(:(@m x y;)) == "begin \n @m x y\nend" +@test repr(:(@m x y)) == ":(#= $(@__FILE__):$(@__LINE__) =# @m x y)" +@test string(:(@m x y)) == "#= $(@__FILE__):$(@__LINE__) =# @m x y" +@test string(:(@m x y;)) == "begin\n #= $(@__FILE__):$(@__LINE__) =# @m x y\nend" # issue #11436 @test_repr "1 => 2 => 3" @@ -447,25 +509,33 @@ end # issue #15309 -l1, l2, l2n = Expr(:line,42), Expr(:line,42,:myfile), LineNumberNode(42) -@test string(l2n) == " # line 42:" -@test string(l2) == " # myfile, line 42:" -@test string(l1) == string(l2n) -ex = Expr(:block, l1, :x, l2, :y, l2n, :z) -@test replace(string(ex)," ","") == replace(""" -begin # line 42: - x # myfile, line 42: - y # line 42: - z -end""", " ", "") +let ex, + l1 = Expr(:line, 42), + l2 = Expr(:line, 42, :myfile), + l2n = LineNumberNode(42) + @test string(l2n) == "#= line 42 =#" + @test string(l2) == "#= myfile:42 =#" + @test string(l1) == string(l2n) + ex = Expr(:block, l1, :x, l2, :y, l2n, :z) + @test replace(string(ex)," ","") == replace(""" + begin + #= line 42 =# + x + #= myfile:42 =# + y + #= line 42 =# + z + end""", " ", "") +end # Test the printing of whatever form of line number representation # that is used in the arguments to a macro looks the same as for # regular quoting macro strquote(ex) - QuoteNode(string(ex)) + return QuoteNode(string(ex)) +end +let str_ex2a = @strquote(begin x end), str_ex2b = string(quote x end) + @test str_ex2a == str_ex2b end -str_ex2a, str_ex2b = @strquote(begin x end), string(quote x end) -@test str_ex2a == str_ex2b # test structured zero matrix printing for select structured types diff --git a/test/stacktraces.jl b/test/stacktraces.jl index ac1814354f12c..19e23aa0f18f1 100644 --- a/test/stacktraces.jl +++ b/test/stacktraces.jl @@ -6,7 +6,7 @@ let @noinline child() = stacktrace() @noinline parent() = child() @noinline grandparent() = parent() - line_numbers = @__LINE__ - [3, 2, 1] + line_numbers = @__LINE__() - [3, 2, 1] stack = grandparent() # Basic tests. @@ -68,7 +68,7 @@ let ct = current_task() return catch_stacktrace() end end - line_numbers = @__LINE__ .- [15, 10, 5] + line_numbers = @__LINE__() .- [15, 10, 5] # Test try...catch with stacktrace @test try_stacktrace()[1] == StackFrame(:try_stacktrace, @__FILE__, line_numbers[2]) diff --git a/test/worlds.jl b/test/worlds.jl index 13bb28597c090..1dfea7f6fe8d9 100644 --- a/test/worlds.jl +++ b/test/worlds.jl @@ -136,7 +136,7 @@ f265(::Int) = 1 # test for method errors h265() = true -loc_h265 = "$(Base.source_path()):$(@__LINE__ - 1)" +loc_h265 = "$(@__FILE__):$(@__LINE__() - 1)" @test h265() @test_throws MethodError put_n_take!(h265, ()) @test_throws MethodError wait(t265) From 6b05e37815448e351c34b35bb76909f22cae6980 Mon Sep 17 00:00:00 2001 From: Chris Foster Date: Tue, 7 Mar 2017 17:40:49 +1000 Subject: [PATCH 0897/1534] Add tests for new __LINE__ behaviour inside macros --- test/loading.jl | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/test/loading.jl b/test/loading.jl index b50ca7960966e..a39e094061859 100644 --- a/test/loading.jl +++ b/test/loading.jl @@ -2,7 +2,34 @@ using Base.Test -@test @__LINE__() == 5 +# Tests for @__LINE__ inside and outside of macros +@test (@__LINE__) == 6 + +macro macro_caller_lineno() + @test 9 == (@__LINE__) != __source__.line > 12 + return __source__.line +end + +@test @macro_caller_lineno() == (@__LINE__) > 12 + +# @__LINE__ in a macro expands to the location of the macrocall in the source +# while __source__.line is the location of the macro caller +macro nested_LINE_expansion() + return quote + return (@emit_LINE, $(__source__.line)) + end +end +macro nested_LINE_expansion2() + return :((@emit_LINE, $(__source__.line))) +end +macro emit_LINE() + return quote + (@__LINE__, $(__source__.line)) + end +end +@test (@emit_LINE) == ((@__LINE__) - 3, @__LINE__) +@test @nested_LINE_expansion() == ((@__LINE__() - 4, @__LINE__() - 12), @__LINE__()) +@test @nested_LINE_expansion2() == ((@__LINE__() - 5, @__LINE__() - 9), @__LINE__()) include("test_sourcepath.jl") thefname = "the fname!//\\&\1*" From 014c5d59cdb1c91b64ed5d51165d09b952e28f96 Mon Sep 17 00:00:00 2001 From: Morten Piibeleht Date: Sun, 14 May 2017 14:16:11 +1200 Subject: [PATCH 0898/1534] Use julia-repl in documentation With the highlighting updates in Documenter v0.10.1 it is now possible to have specialized highlighting for REPL blocks via the julia-repl attribute on code blocks. Doctests already use this, so this makes the highlighting for non-doctest REPL blocks consistent. --- base/abstractarray.jl | 6 +- base/array.jl | 2 +- base/bitarray.jl | 2 +- base/distributed/pmap.jl | 2 +- base/libgit2/libgit2.jl | 5 +- base/libgit2/reference.jl | 2 +- base/libgit2/remote.jl | 8 +-- base/multidimensional.jl | 2 +- base/regex.jl | 2 +- base/util.jl | 16 ++--- doc/src/devdocs/backtraces.md | 2 +- doc/src/devdocs/cartesian.md | 2 +- doc/src/devdocs/reflection.md | 14 ++-- doc/src/devdocs/subarrays.md | 8 +-- doc/src/devdocs/types.md | 8 +-- doc/src/manual/arrays.md | 14 ++-- doc/src/manual/calling-c-and-fortran-code.md | 8 +-- doc/src/manual/constructors.md | 4 +- doc/src/manual/conversion-and-promotion.md | 12 ++-- doc/src/manual/documentation.md | 2 +- doc/src/manual/faq.md | 14 ++-- .../integers-and-floating-point-numbers.md | 14 ++-- doc/src/manual/interacting-with-julia.md | 18 +++--- doc/src/manual/metaprogramming.md | 6 +- doc/src/manual/methods.md | 6 +- doc/src/manual/networking-and-streams.md | 32 +++++----- doc/src/manual/packages.md | 44 ++++++------- doc/src/manual/parallel-computing.md | 64 +++++++++---------- doc/src/manual/performance-tips.md | 20 +++--- doc/src/manual/profile.md | 12 ++-- doc/src/manual/running-external-programs.md | 10 +-- doc/src/manual/stacktraces.md | 22 +++---- doc/src/manual/strings.md | 4 +- doc/src/manual/types.md | 2 +- doc/src/manual/variables-and-scoping.md | 6 +- doc/src/manual/variables.md | 4 +- doc/src/stdlib/sort.md | 14 ++-- doc/src/stdlib/test.md | 18 +++--- 38 files changed, 215 insertions(+), 216 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 92236060a78fb..629dbb740d684 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -480,7 +480,7 @@ default is an `Array{element_type}(dims...)`. For example, `similar(1:10, 1, 4)` returns an uninitialized `Array{Int,2}` since ranges are neither mutable nor support 2 dimensions: -```julia +```julia-repl julia> similar(1:10, 1, 4) 1×4 Array{Int64,2}: 4419743872 4374413872 4419743888 0 @@ -489,7 +489,7 @@ julia> similar(1:10, 1, 4) Conversely, `similar(trues(10,10), 2)` returns an uninitialized `BitVector` with two elements since `BitArray`s are both mutable and can support 1-dimensional arrays: -```julia +```julia-repl julia> similar(trues(10,10), 2) 2-element BitArray{1}: false @@ -499,7 +499,7 @@ julia> similar(trues(10,10), 2) Since `BitArray`s can only store elements of type `Bool`, however, if you request a different element type it will create a regular `Array` instead: -```julia +```julia-repl julia> similar(falses(10), Float64, 2, 4) 2×4 Array{Float64,2}: 2.18425e-314 2.18425e-314 2.18425e-314 2.18425e-314 diff --git a/base/array.jl b/base/array.jl index c6b4c24da7ef5..53b67cac5f114 100644 --- a/base/array.jl +++ b/base/array.jl @@ -701,7 +701,7 @@ julia> resize!([6, 5, 4, 3, 2, 1], 3) 4 ``` -```julia +```julia-repl julia> resize!([6, 5, 4, 3, 2, 1], 8) 8-element Array{Int64,1}: 6 diff --git a/base/bitarray.jl b/base/bitarray.jl index 8766bef1b54f7..4167747cd4fad 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -35,7 +35,7 @@ end Construct an uninitialized `BitArray` with the given dimensions. Behaves identically to the [`Array`](@ref) constructor. -```julia +```julia-repl julia> BitArray(2, 2) 2×2 BitArray{2}: false false diff --git a/base/distributed/pmap.jl b/base/distributed/pmap.jl index e470ae24d8309..3cf4c895d3db3 100644 --- a/base/distributed/pmap.jl +++ b/base/distributed/pmap.jl @@ -60,7 +60,7 @@ which is then returned inline with the results to the caller. Consider the following two examples. The first one returns the exception object inline, the second a 0 in place of any exception: -```julia +```julia-repl julia> pmap(x->iseven(x) ? error("foo") : x, 1:4; on_error=identity) 4-element Array{Any,1}: 1 diff --git a/base/libgit2/libgit2.jl b/base/libgit2/libgit2.jl index c8ba346ec52f1..f7418b6e38428 100644 --- a/base/libgit2/libgit2.jl +++ b/base/libgit2/libgit2.jl @@ -75,7 +75,7 @@ is in the repository. # Example -```julia +```julia-repl julia> repo = LibGit2.GitRepo(repo_path); julia> LibGit2.add!(repo, test_file); @@ -220,7 +220,7 @@ Returns `true` if `a`, a [`GitHash`](@ref) in string form, is an ancestor of # Example -```julia +```julia-repl julia> repo = LibGit2.GitRepo(repo_path); julia> LibGit2.add!(repo, test_file1); @@ -954,4 +954,3 @@ end end # module - diff --git a/base/libgit2/reference.jl b/base/libgit2/reference.jl index 00acb2513131a..bb193345fc246 100644 --- a/base/libgit2/reference.jl +++ b/base/libgit2/reference.jl @@ -48,7 +48,7 @@ end Returns a shortened version of the name of `ref` that's "human-readable". -```julia +```julia-repl julia> repo = LibGit2.GitRepo(path_to_repo); julia> branch_ref = LibGit2.head(repo); diff --git a/base/libgit2/remote.jl b/base/libgit2/remote.jl index 9819f614da9cc..d0d0d74ba8b25 100644 --- a/base/libgit2/remote.jl +++ b/base/libgit2/remote.jl @@ -78,7 +78,7 @@ Get the URL of a remote git repository. # Example -```julia +```julia-repl julia> repo_url = "https://github.com/JuliaLang/Example.jl"; julia> repo = LibGit2.clone(cache_repo, "test_directory"); @@ -104,7 +104,7 @@ the name will be an empty string `""`. # Example -```julia +```julia-repl julia> repo_url = "https://github.com/JuliaLang/Example.jl"; julia> repo = LibGit2.clone(cache_repo, "test_directory"); @@ -158,7 +158,7 @@ Add a *fetch* refspec for the specified `rmt`. This refspec will contain information about which branch(es) to fetch from. # Example -```julia +```julia-repl julia> LibGit2.add_fetch!(repo, remote, "upstream"); julia> LibGit2.fetch_refspecs(remote) @@ -178,7 +178,7 @@ Add a *push* refspec for the specified `rmt`. This refspec will contain information about which branch(es) to push to. # Example -```julia +```julia-repl julia> LibGit2.add_push!(repo, remote, "refs/heads/master"); julia> remote = LibGit2.get(LibGit2.GitRemote, repo, branch); diff --git a/base/multidimensional.jl b/base/multidimensional.jl index a3b5ef5a97658..09fb0757562d5 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -909,7 +909,7 @@ their indices; any offset results in a (circular) wraparound. If the arrays have overlapping indices, then on the domain of the overlap `dest` agrees with `src`. -```julia +```julia-repl julia> src = reshape(collect(1:16), (4,4)) 4×4 Array{Int64,2}: 1 5 9 13 diff --git a/base/regex.jl b/base/regex.jl index 775d610131af9..3ea60fd7ff4f2 100644 --- a/base/regex.jl +++ b/base/regex.jl @@ -75,7 +75,7 @@ after the ending quote, to change its behaviour: For example, this regex has all three flags enabled: -```julia +```julia-repl julia> match(r"a+.*b+.*?d\$"ism, "Goodbye,\\nOh, angry,\\nBad world\\n") RegexMatch("angry,\\nBad world") ``` diff --git a/base/util.jl b/base/util.jl index b2167ca36b168..66972107def5b 100644 --- a/base/util.jl +++ b/base/util.jl @@ -82,7 +82,7 @@ gc_bytes() = ccall(:jl_gc_total_bytes, Int64, ()) Set a timer to be read by the next call to [`toc`](@ref) or [`toq`](@ref). The macro call `@time expr` can also be used to time evaluation. -```julia +```julia-repl julia> tic() 0x0000c45bc7abac95 @@ -105,7 +105,7 @@ end Return, but do not print, the time elapsed since the last [`tic`](@ref). The macro calls `@timed expr` and `@elapsed expr` also return evaluation time. -```julia +```julia-repl julia> tic() 0x0000c46477a9675d @@ -132,7 +132,7 @@ end Print and return the time elapsed since the last [`tic`](@ref). The macro call `@time expr` can also be used to time evaluation. -```julia +```julia-repl julia> tic() 0x0000c45bc7abac95 @@ -219,7 +219,7 @@ returning the value of the expression. See also [`@timev`](@ref), [`@timed`](@ref), [`@elapsed`](@ref), and [`@allocated`](@ref). -```julia +```julia-repl julia> @time rand(10^6); 0.001525 seconds (7 allocations: 7.630 MiB) @@ -253,7 +253,7 @@ expression. See also [`@time`](@ref), [`@timed`](@ref), [`@elapsed`](@ref), and [`@allocated`](@ref). -```julia +```julia-repl julia> @timev rand(10^6); 0.001006 seconds (7 allocations: 7.630 MiB) elapsed time (ns): 1005567 @@ -282,7 +282,7 @@ number of seconds it took to execute as a floating-point number. See also [`@time`](@ref), [`@timev`](@ref), [`@timed`](@ref), and [`@allocated`](@ref). -```julia +```julia-repl julia> @elapsed sleep(0.3) 0.301391426 ``` @@ -314,7 +314,7 @@ for the effects of compilation. See also [`@time`](@ref), [`@timev`](@ref), [`@timed`](@ref), and [`@elapsed`](@ref). -```julia +```julia-repl julia> @allocated rand(10^6) 8000080 ``` @@ -343,7 +343,7 @@ counters. See also [`@time`](@ref), [`@timev`](@ref), [`@elapsed`](@ref), and [`@allocated`](@ref). -```julia +```julia-repl julia> val, t, bytes, gctime, memallocs = @timed rand(10^6); julia> t diff --git a/doc/src/devdocs/backtraces.md b/doc/src/devdocs/backtraces.md index c053f4cf48c1e..059b18ceb4966 100644 --- a/doc/src/devdocs/backtraces.md +++ b/doc/src/devdocs/backtraces.md @@ -18,7 +18,7 @@ No matter the error, we will always need to know what version of Julia you are r first starts up, a header is printed out with a version number and date. If your version is `0.2.0` or higher, please include the output of `versioninfo()` in any report you create: -```julia +```julia-repl julia> versioninfo() Julia Version 0.3.3-pre+25 Commit 417b50a* (2014-11-03 11:32 UTC) diff --git a/doc/src/devdocs/cartesian.md b/doc/src/devdocs/cartesian.md index 3d74c1acbaf6c..b97c6f2d3418c 100644 --- a/doc/src/devdocs/cartesian.md +++ b/doc/src/devdocs/cartesian.md @@ -53,7 +53,7 @@ is `@nref 3 A i` (as in `A[i_1,i_2,i_3]`, where the array comes first). If you're developing code with Cartesian, you may find that debugging is easier when you examine the generated code, using `macroexpand`: -```julia +```julia-repl julia> macroexpand(:(@nref 2 A i)) :(A[i_1,i_2]) ``` diff --git a/doc/src/devdocs/reflection.md b/doc/src/devdocs/reflection.md index 244731b33f611..cb0b8ae9c8679 100644 --- a/doc/src/devdocs/reflection.md +++ b/doc/src/devdocs/reflection.md @@ -14,7 +14,7 @@ The names of `DataType` fields may be interrogated using [`fieldnames()`](@ref). given the following type, `fieldnames(Point)` returns an arrays of [`Symbol`](@ref) elements representing the field names: -```julia +```julia-repl julia> struct Point x::Int y @@ -29,7 +29,7 @@ julia> fieldnames(Point) The type of each field in a `Point` object is stored in the `types` field of the `Point` variable itself: -```julia +```julia-repl julia> Point.types svec(Int64,Any) ``` @@ -39,7 +39,7 @@ defaults to the `Any` type. Types are themselves represented as a structure called `DataType`: -```julia +```julia-repl julia> typeof(Point) DataType ``` @@ -52,7 +52,7 @@ of these fields is the `types` field observed in the example above. The *direct* subtypes of any `DataType` may be listed using [`subtypes()`](@ref). For example, the abstract `DataType``AbstractFloat` has four (concrete) subtypes: -```julia +```julia-repl julia> subtypes(AbstractFloat) 4-element Array{DataType,1}: BigFloat @@ -83,7 +83,7 @@ the unquoted and interpolated expression (`Expr`) form for a given macro. To use `quote` the expression block itself (otherwise, the macro will be evaluated and the result will be passed instead!). For example: -```julia +```julia-repl julia> macroexpand( :(@edit println("")) ) :((Base.edit)(println,(Base.typesof)(""))) ``` @@ -95,7 +95,7 @@ Finally, the [`expand()`](@ref) function gives the `lowered` form of any express particular interest for understanding both macros and top-level statements such as function declarations and variable assignments: -```julia +```julia-repl julia> expand( :(f() = 1) ) :(begin $(Expr(:method, :f)) @@ -123,7 +123,7 @@ generation for any function which has not previously been called). For convenience, there are macro versions of the above functions which take standard function calls and expand argument types automatically: -```julia +```julia-repl julia> @code_llvm +(1,1) ; Function Attrs: sspreq diff --git a/doc/src/devdocs/subarrays.md b/doc/src/devdocs/subarrays.md index 4c6fdb5964ed0..e7637dc47b214 100644 --- a/doc/src/devdocs/subarrays.md +++ b/doc/src/devdocs/subarrays.md @@ -74,7 +74,7 @@ If in our example above `A` is a `Array{Float64, 3}`, our `S1` case above would Note in particular the tuple parameter, which stores the types of the indices used to create `S1`. Likewise, -```julia +```julia-repl julia> S1.indexes (Colon(),5,2:6) ``` @@ -137,7 +137,7 @@ For `SubArray` types, the availability of efficient linear indexing is based pur of the indices, and does not depend on values like the size of the parent array. You can ask whether a given set of indices supports fast linear indexing with the internal `Base.viewindexing` function: -```julia +```julia-repl julia> Base.viewindexing(S1.indexes) IndexCartesian() @@ -152,7 +152,7 @@ we can define dispatch directly on `SubArray{T,N,A,I,true}` without any intermed Since this computation doesn't depend on runtime values, it can miss some cases in which the stride happens to be uniform: -```julia +```julia-repl julia> A = reshape(1:4*2, 4, 2) 4×2 Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}}: 1 5 @@ -171,7 +171,7 @@ A view constructed as `view(A, 2:2:4, :)` happens to have uniform stride, and th indexing indeed could be performed efficiently. However, success in this case depends on the size of the array: if the first dimension instead were odd, -```julia +```julia-repl julia> A = reshape(1:5*2, 5, 2) 5×2 Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}}: 1 6 diff --git a/doc/src/devdocs/types.md b/doc/src/devdocs/types.md index 1433117aedc95..63a274c61f74b 100644 --- a/doc/src/devdocs/types.md +++ b/doc/src/devdocs/types.md @@ -169,7 +169,7 @@ Array{T,N} These can be distinguished by examining the `name` field of the type, which is an object of type `TypeName`: -```julia +```julia-repl julia> dump(Array{Int,1}.name) TypeName name: Symbol Array @@ -207,7 +207,7 @@ TypeName In this case, the relevant field is `wrapper`, which holds a reference to the top-level type used to make new `Array` types. -```julia +```julia-repl julia> pointer_from_objref(Array) Ptr{Void} @0x00007fcc7de64850 @@ -299,7 +299,7 @@ Union{} What is the "primary" tuple-type? -```julia +```julia-repl julia> pointer_from_objref(Tuple) Ptr{Void} @0x00007f5998a04370 @@ -461,7 +461,7 @@ Build Julia with `make debug` and fire up Julia within a debugger. Because the subtyping code is used heavily in the REPL itself--and hence breakpoints in this code get triggered often--it will be easiest if you make the following definition: -```julia +```julia-repl julia> function mysubtype(a,b) ccall(:jl_breakpoint, Void, (Any,), nothing) issubtype(a, b) diff --git a/doc/src/manual/arrays.md b/doc/src/manual/arrays.md index e8cfbfc06e500..090b036351dd1 100644 --- a/doc/src/manual/arrays.md +++ b/doc/src/manual/arrays.md @@ -137,7 +137,7 @@ of the variable ranges `rx`, `ry`, etc. and each `F(x,y,...)` evaluation returns The following example computes a weighted average of the current element and its left and right neighbor along a 1-d grid. : -```julia +```julia-repl julia> x = rand(8) 8-element Array{Float64,1}: 0.843025 @@ -182,7 +182,7 @@ julia> sum(1/n^2 for n=1:1000) When writing a generator expression with multiple dimensions inside an argument list, parentheses are needed to separate the generator from subsequent arguments: -```julia +```julia-repl julia> map(tuple, 1/(i+j) for i=1:2, j=1:2, [1:4;]) ERROR: syntax: invalid iteration specification ``` @@ -556,7 +556,7 @@ It is sometimes useful to perform element-by-element binary operations on arrays sizes, such as adding a vector to each column of a matrix. An inefficient way to do this would be to replicate the vector to the size of the matrix: -```julia +```julia-repl julia> a = rand(2,1); A = rand(2,3); julia> repmat(a,1,3)+A @@ -569,7 +569,7 @@ This is wasteful when dimensions get large, so Julia offers [`broadcast()`](@ref singleton dimensions in array arguments to match the corresponding dimension in the other array without using extra memory, and applies the given function elementwise: -```julia +```julia-repl julia> broadcast(+, a, A) 2×3 Array{Float64,2}: 1.20813 1.82068 1.25387 @@ -666,7 +666,7 @@ The following example computes the QR decomposition of a small section of a larg creating any temporaries, and by calling the appropriate LAPACK function with the right leading dimension size and stride parameters. -```julia +```julia-repl julia> a = rand(10,10) 10×10 Array{Float64,2}: 0.561255 0.226678 0.203391 0.308912 … 0.750307 0.235023 0.217964 @@ -768,7 +768,7 @@ The [`sparse()`](@ref) function is often a handy way to construct sparse matrice its input a vector `I` of row indices, a vector `J` of column indices, and a vector `V` of nonzero values. `sparse(I,J,V)` constructs a sparse matrix such that `S[I[k], J[k]] = V[k]`. -```jldoctest +```julia-repl julia> I = [1, 4, 3, 5]; J = [4, 7, 18, 9]; V = [1, 2, -5, 3]; julia> S = sparse(I,J,V) @@ -782,7 +782,7 @@ julia> S = sparse(I,J,V) The inverse of the [`sparse()`](@ref) function is [`findn()`](@ref), which retrieves the inputs used to create the sparse matrix. -```julia +```julia-repl julia> findn(S) ([1,4,5,3],[4,7,9,18]) diff --git a/doc/src/manual/calling-c-and-fortran-code.md b/doc/src/manual/calling-c-and-fortran-code.md index b5cfa8e76fd6b..b8164f86ad8da 100644 --- a/doc/src/manual/calling-c-and-fortran-code.md +++ b/doc/src/manual/calling-c-and-fortran-code.md @@ -55,7 +55,7 @@ to [`ccall`](@ref) are as follows: As a complete but simple example, the following calls the `clock` function from the standard C library: -```julia +```julia-repl julia> t = ccall((:clock, "libc"), Int32, ()) 2292761 @@ -70,7 +70,7 @@ Int32 written with a trailing comma. For example, to call the `getenv` function to get a pointer to the value of an environment variable, one makes a call like this: -```julia +```julia-repl julia> path = ccall((:getenv, "libc"), Cstring, (Cstring,), "SHELL") Cstring(@0x00007fff5fbffc45) @@ -113,7 +113,7 @@ indicate errors in various different ways, including by returning -1, 0, 1 and o This wrapper throws an exception clearly indicating the problem if the caller tries to get a non-existent environment variable: -```julia +```julia-repl julia> getenv("SHELL") "/bin/bash" @@ -905,7 +905,7 @@ Global variables exported by native libraries can be accessed by name using the function. The arguments to [`cglobal()`](@ref) are a symbol specification identical to that used by [`ccall`](@ref), and a type describing the value stored in the variable: -```julia +```julia-repl julia> cglobal((:errno, :libc), Int32) Ptr{Int32} @0x00007f418d0816b8 ``` diff --git a/doc/src/manual/constructors.md b/doc/src/manual/constructors.md index dcf9fe4b68719..e36ec65dda0fb 100644 --- a/doc/src/manual/constructors.md +++ b/doc/src/manual/constructors.md @@ -181,7 +181,7 @@ julia> mutable struct SelfReferential This type may appear innocuous enough, until one considers how to construct an instance of it. If `a` is an instance of `SelfReferential`, then a second instance can be created by the call: -```julia +```julia-repl julia> b = SelfReferential(a) ``` @@ -246,7 +246,7 @@ and does not reference other objects. The plain data types consist of primitive and immutable structs of other plain data types. The initial contents of a plain data type is undefined: -```julia +```julia-repl julia> struct HasPlain n::Int HasPlain() = new() diff --git a/doc/src/manual/conversion-and-promotion.md b/doc/src/manual/conversion-and-promotion.md index 12166fb148c61..576f485e47358 100644 --- a/doc/src/manual/conversion-and-promotion.md +++ b/doc/src/manual/conversion-and-promotion.md @@ -46,7 +46,7 @@ generally takes two arguments: the first is a type object while the second is a to that type; the returned value is the value converted to an instance of given type. The simplest way to understand this function is to see it in action: -```julia +```julia-repl julia> x = 12 12 @@ -79,7 +79,7 @@ julia> convert(Array{Float64}, a) Conversion isn't always possible, in which case a no method error is thrown indicating that `convert` doesn't know how to perform the requested conversion: -```julia +```julia-repl julia> convert(AbstractFloat, "foo") ERROR: MethodError: Cannot `convert` an object of type String to an object of type AbstractFloat This may have arisen from a call to the constructor AbstractFloat(...), @@ -111,7 +111,7 @@ example, since the type is a singleton, there would never be any reason to use i the body. When invoked, the method determines whether a numeric value is true or false as a boolean, by comparing it to one and zero: -```julia +```julia-repl julia> convert(Bool, 1) true @@ -201,7 +201,7 @@ any number of arguments, and returns a tuple of the same number of values, conve type, or throws an exception if promotion is not possible. The most common use case for promotion is to convert numeric arguments to a common type: -```julia +```julia-repl julia> promote(1, 2.5) (1.0,2.5) @@ -258,7 +258,7 @@ Rational(n::Integer, d::Integer) = Rational(promote(n,d)...) This allows calls like the following to work: -```julia +```julia-repl julia> Rational(Int8(15),Int32(-5)) -3//1 @@ -302,7 +302,7 @@ which, given any number of type objects, returns the common type to which those to `promote` should be promoted. Thus, if one wants to know, in absence of actual values, what type a collection of values of certain types would promote to, one can use `promote_type`: -```julia +```julia-repl julia> promote_type(Int8, UInt16) Int64 ``` diff --git a/doc/src/manual/documentation.md b/doc/src/manual/documentation.md index 390c45993432f..59d1a23f2e43d 100644 --- a/doc/src/manual/documentation.md +++ b/doc/src/manual/documentation.md @@ -27,7 +27,7 @@ Compute the Bar index between `x` and `y`. If `y` is missing, compute the Bar index between all pairs of columns of `x`. # Examples -```julia +```julia-repl julia> bar([1, 2], [1, 2]) 1 ``` diff --git a/doc/src/manual/faq.md b/doc/src/manual/faq.md index 630131dc1ed57..e019cce47fa78 100644 --- a/doc/src/manual/faq.md +++ b/doc/src/manual/faq.md @@ -391,7 +391,7 @@ arithmetic. For example, since Julia integers use normal machine integer arithme to aggressively optimize simple little functions like `f(k) = 5k-1`. The machine code for this function is just this: -```julia +```julia-repl julia> code_native(f, Tuple{Int}) .text Filename: none @@ -407,7 +407,7 @@ Source line: 1 The actual body of the function is a single `leaq` instruction, which computes the integer multiply and add at once. This is even more beneficial when `f` gets inlined into another function: -```julia +```julia-repl julia> function g(k, n) for i = 1:n k = f(k) @@ -442,7 +442,7 @@ L26: Since the call to `f` gets inlined, the loop body ends up being just a single `leaq` instruction. Next, consider what happens if we make the number of loop iterations fixed: -```julia +```julia-repl julia> function g(k) for i = 1:10 k = f(k) @@ -485,7 +485,7 @@ to checked integer arithmetic in Julia, but for now, we have to live with the po As the error states, an immediate cause of an `UndefVarError` on a remote node is that a binding by that name does not exist. Let us explore some of the possible causes. -```julia +```julia-repl julia> module Foo foo() = remotecall_fetch(x->x, 2, "Hello") end @@ -502,7 +502,7 @@ an `UndefVarError` is thrown. Globals under modules other than `Main` are not serialized by value to the remote node. Only a reference is sent. Functions which create global bindings (except under `Main`) may cause an `UndefVarError` to be thrown later. -```julia +```julia-repl julia> @everywhere module Foo function foo() global gvar = "Hello" @@ -522,7 +522,7 @@ a new global binding `gvar` on the local node, but this was not found on node 2 Note that this does not apply to globals created under module `Main`. Globals under module `Main` are serialized and new bindings created under `Main` on the remote node. -```julia +```julia-repl julia> gvar_self = "Node1" "Node1" @@ -540,7 +540,7 @@ julia> remotecall_fetch(whos, 2) This does not apply to `function` or `type` declarations. However, anonymous functions bound to global variables are serialized as can be seen below. -```julia +```julia-repl julia> bar() = 1 bar (generic function with 1 method) diff --git a/doc/src/manual/integers-and-floating-point-numbers.md b/doc/src/manual/integers-and-floating-point-numbers.md index 9d0932bbde923..e8bacb86b5ac1 100644 --- a/doc/src/manual/integers-and-floating-point-numbers.md +++ b/doc/src/manual/integers-and-floating-point-numbers.md @@ -59,7 +59,7 @@ julia> 1234 The default type for an integer literal depends on whether the target system has a 32-bit architecture or a 64-bit architecture: -```julia +```julia-repl # 32-bit system: julia> typeof(1) Int32 @@ -72,7 +72,7 @@ Int64 The Julia internal variable [`Sys.WORD_SIZE`](@ref) indicates whether the target system is 32-bit or 64-bit: -```julia +```julia-repl # 32-bit system: julia> Sys.WORD_SIZE 32 @@ -85,7 +85,7 @@ julia> Sys.WORD_SIZE Julia also defines the types `Int` and `UInt`, which are aliases for the system's signed and unsigned native integer types respectively: -```julia +```julia-repl # 32-bit system: julia> Int Int32 @@ -597,7 +597,7 @@ julia> 1.5x^2 - .5x + 1 It also makes writing exponential functions more elegant: -```julia +```julia-repl julia> 2^2x 64 ``` @@ -607,7 +607,7 @@ negation. So `2^3x` is parsed as `2^(3x)`, and `2x^3` is parsed as `2*(x^3)`. Numeric literals also work as coefficients to parenthesized expressions: -```julia +```julia-repl julia> 2(x-1)^2 - 3(x-1) + 1 3 ``` @@ -615,7 +615,7 @@ julia> 2(x-1)^2 - 3(x-1) + 1 Additionally, parenthesized expressions can be used as coefficients to variables, implying multiplication of the expression by the variable: -```julia +```julia-repl julia> (x-1)x 6 ``` @@ -623,7 +623,7 @@ julia> (x-1)x Neither juxtaposition of two parenthesized expressions, nor placing a variable before a parenthesized expression, however, can be used to imply multiplication: -```julia +```julia-repl julia> (x-1)(x+1) ERROR: MethodError: objects of type Int64 are not callable diff --git a/doc/src/manual/interacting-with-julia.md b/doc/src/manual/interacting-with-julia.md index f388251f77802..962b1f82da396 100644 --- a/doc/src/manual/interacting-with-julia.md +++ b/doc/src/manual/interacting-with-julia.md @@ -63,7 +63,7 @@ at detecting when a paste occurs. When the cursor is at the beginning of the line, the prompt can be changed to a help mode by typing `?`. Julia will attempt to print help or documentation for anything entered in help mode: -```julia +```julia-repl julia> ? # upon typing ?, the prompt changes (in place) to: help?> help?> string @@ -111,7 +111,7 @@ system shell to execute system commands. Just as `?` entered help mode when at t of the line, a semicolon (`;`) will enter the shell mode. And it can be exited by pressing backspace at the beginning of the line. -```julia +```julia-repl julia> ; # upon typing ;, the prompt changes (in place) to: shell> shell> echo hello @@ -209,7 +209,7 @@ Users should refer to `base/LineEdit.jl` to discover the available actions on ke In both the Julian and help modes of the REPL, one can enter the first few characters of a function or type and then press the tab key to get a list all matches: -```julia +```julia-repl julia> stri[TAB] stride strides string stringmime strip @@ -220,7 +220,7 @@ StridedArray StridedMatrix StridedVecOrMat StridedVector String The tab key can also be used to substitute LaTeX math symbols with their Unicode equivalents, and get a list of LaTeX matches as well: -```julia +```julia-repl julia> \pi[TAB] julia> π π = 3.1415926535897... @@ -258,7 +258,7 @@ A full list of tab-completions can be found in the [Unicode Input](@ref) section Completion of paths works for strings and julia's shell mode: -```julia +```julia-repl julia> path="/[TAB]" .dockerenv .juliabox/ boot/ etc/ lib/ media/ opt/ root/ sbin/ sys/ usr/ .dockerinit bin/ dev/ home/ lib64/ mnt/ proc/ run/ srv/ tmp/ var/ @@ -269,7 +269,7 @@ shell> /[TAB] Tab completion can help with investigation of the available methods matching the input arguments: -```julia +```julia-repl julia> max([TAB] # All methods are displayed, not shown here due to size of the list julia> max([1, 2], [TAB] # All methods where `Vector{Int}` matches as first argument @@ -284,7 +284,7 @@ max(a, b, c, xs...) in Base at operators.jl:281 Keywords are also displayed in the suggested methods, see second line after `;` where `limit` and `keep` are keyword arguments: -```julia +```julia-repl julia> split("1 1 1", [TAB] split(str::AbstractString) in Base at strings/util.jl:278 split{T<:AbstractString}(str::T, splitter; limit, keep) in Base at strings/util.jl:254 @@ -296,14 +296,14 @@ completion to be able to remove non-matching methods. Tab completion can also help completing fields: -```julia +```julia-repl julia> Pkg.a[TAB] add available ``` Fields for output from functions can also be completed: -```julia +```julia-repl julia> split("","")[1].[TAB] endof offset string ``` diff --git a/doc/src/manual/metaprogramming.md b/doc/src/manual/metaprogramming.md index 6e937ba18b8c2..c0a3f794534a1 100644 --- a/doc/src/manual/metaprogramming.md +++ b/doc/src/manual/metaprogramming.md @@ -238,7 +238,7 @@ julia> ex = :(a in $:((1,2,3)) ) Interpolating symbols into a nested expression requires enclosing each symbol in an enclosing quote block: -```julia +```julia-repl julia> :( :a in $( :(:a + :b) ) ) ^^^^^^^^^^ quoted inner expression @@ -298,7 +298,7 @@ Since expressions are just `Expr` objects which can be constructed programmatica it is possible to dynamically generate arbitrary code which can then be run using [`eval()`](@ref). Here is a simple example: -```julia +```julia-repl julia> a = 1; julia> ex = Expr(:call, :+, a, :b) @@ -920,7 +920,7 @@ we returned from the definition, now with the *value* of `x`. What happens if we evaluate `foo` again with a type that we have already used? -```julia generated +```julia-repl generated julia> foo(4) 16 ``` diff --git a/doc/src/manual/methods.md b/doc/src/manual/methods.md index 1b46b99ab47c7..53cc3f650b7f0 100644 --- a/doc/src/manual/methods.md +++ b/doc/src/manual/methods.md @@ -163,7 +163,7 @@ f (generic function with 2 methods) This output tells us that `f` is a function object with two methods. To find out what the signatures of those methods are, use the [`methods()`](@ref) function: -```julia +```julia-repl julia> methods(f) # 2 methods for generic function "f": f(x::Float64, y::Float64) in Main at none:1 @@ -193,7 +193,7 @@ Although it seems a simple concept, multiple dispatch on the types of values is most powerful and central feature of the Julia language. Core operations typically have dozens of methods: -```julia +```julia-repl julia> methods(+) # 180 methods for generic function "+": +(x::Bool, z::Complex{Bool}) in Base at complex.jl:224 @@ -412,7 +412,7 @@ Indeed, any new method definition won't be visible to the current runtime enviro including Tasks and Threads (and any previously defined `@generated` functions). Let's start with an example to see what this means: -```julia +```julia-repl julia> function tryeval() @eval newfun() = 1 newfun() diff --git a/doc/src/manual/networking-and-streams.md b/doc/src/manual/networking-and-streams.md index 8919f55b60e4f..6b7b9bacba35c 100644 --- a/doc/src/manual/networking-and-streams.md +++ b/doc/src/manual/networking-and-streams.md @@ -11,7 +11,7 @@ functionality. All Julia streams expose at least a [`read()`](@ref) and a [`write()`](@ref) method, taking the stream as their first argument, e.g.: -```julia +```julia-repl julia> write(STDOUT,"Hello World"); # suppress return value 11 with ; Hello World julia> read(STDIN,Char) @@ -28,7 +28,7 @@ takes the type of the data to be read as the second argument. For example, to read a simple byte array, we could do: -```julia +```julia-repl julia> x = zeros(UInt8, 4) 4-element Array{UInt8,1}: 0x00 @@ -48,7 +48,7 @@ abcd However, since this is slightly cumbersome, there are several convenience methods provided. For example, we could have written the above as: -```julia +```julia-repl julia> read(STDIN,4) abcd 4-element Array{UInt8,1}: @@ -60,7 +60,7 @@ abcd or if we had wanted to read the entire line instead: -```julia +```julia-repl julia> readline(STDIN) abcd "abcd" @@ -120,7 +120,7 @@ Like many other environments, Julia has an [`open()`](@ref) function, which take returns an `IOStream` object that you can use to read and write things from the file. For example if we have a file, `hello.txt`, whose contents are `Hello, World!`: -```julia +```julia-repl julia> f = open("hello.txt") IOStream() @@ -131,7 +131,7 @@ julia> readlines(f) If you want to write to a file, you can open it with the write (`"w"`) flag: -```julia +```julia-repl julia> f = open("hello.txt","w") IOStream() @@ -143,7 +143,7 @@ If you examine the contents of `hello.txt` at this point, you will notice that i has actually been written to disk yet. This is because the `IOStream` must be closed before the write is actually flushed to disk: -```julia +```julia-repl julia> close(f) ``` @@ -162,7 +162,7 @@ end You can call: -```julia +```julia-repl julia> open(read_and_capitalize, "hello.txt") "HELLO AGAIN." ``` @@ -173,7 +173,7 @@ contents. To avoid even having to define a named function, you can use the `do` syntax, which creates an anonymous function on the fly: -```julia +```julia-repl julia> open("hello.txt") do f uppercase(readstring(f)) end @@ -184,7 +184,7 @@ julia> open("hello.txt") do f Let's jump right in with a simple example involving TCP sockets. Let's first create a simple server: -```julia +```julia-repl julia> @async begin server = listen(2000) while true @@ -200,7 +200,7 @@ usage is somewhat simpler than the raw Unix socket API. The first call to [`list create a server waiting for incoming connections on the specified port (2000) in this case. The same function may also be used to create various other kinds of servers: -```julia +```julia-repl julia> listen(2000) # Listens on localhost:2000 (IPv4) TCPServer(active) @@ -230,7 +230,7 @@ cwd, etc.) is the same you should be able to pass the same arguments to [`connec you did to listen to establish the connection. So let's try that out (after having created the server above): -```julia +```julia-repl julia> connect(2000) TCPSocket(open, 0 bytes waiting) @@ -250,7 +250,7 @@ task resumed execution (because a connection request was now available), accepte printed the message and waited for the next client. Reading and writing works in the same way. To see this, consider the following simple echo server: -```julia +```julia-repl julia> @async begin server = listen(2001) while true @@ -276,7 +276,7 @@ Hello World from the Echo Server As with other streams, use [`close()`](@ref) to disconnect the socket: -```julia +```julia-repl julia> close(clientside) ``` @@ -286,7 +286,7 @@ One of the [`connect()`](@ref) methods that does not follow the [`listen()`](@re `connect(host::String,port)`, which will attempt to connect to the host given by the `host` parameter on the port given by the port parameter. It allows you to do things like: -```julia +```julia-repl julia> connect("google.com",80) TCPSocket(RawFD(30) open, 0 bytes waiting) ``` @@ -294,7 +294,7 @@ TCPSocket(RawFD(30) open, 0 bytes waiting) At the base of this functionality is [`getaddrinfo()`](@ref), which will do the appropriate address resolution: -```julia +```julia-repl julia> getaddrinfo("google.com") ip"74.125.226.225" ``` diff --git a/doc/src/manual/packages.md b/doc/src/manual/packages.md index 6955cf4265039..336f769e23813 100644 --- a/doc/src/manual/packages.md +++ b/doc/src/manual/packages.md @@ -16,7 +16,7 @@ add your code to the curated METADATA repository. The [`Pkg.status()`](@ref) function prints out a summary of the state of packages you have installed. Initially, you'll have no packages installed: -```julia +```julia-repl julia> Pkg.status() INFO: Initializing package repository /Users/stefan/.julia/v0.6 INFO: Cloning METADATA from git://github.com/JuliaLang/METADATA.jl @@ -27,7 +27,7 @@ Your package directory is automatically initialized the first time you run a `Pk that expects it to exist – which includes [`Pkg.status()`](@ref). Here's an example non-trivial set of required and additional packages: -```julia +```julia-repl julia> Pkg.status() Required packages: - Distributions 0.2.8 @@ -43,7 +43,7 @@ will explain these states and annotations as we encounter them. For programmatic returns a dictionary, mapping installed package names to the version of that package which is installed: -```julia +```julia-repl julia> Pkg.installed() Dict{String,VersionNumber} with 4 entries: "Distributions" => v"0.2.8" @@ -73,7 +73,7 @@ commands, which add or remove a single requirement to `REQUIRE` and then call [` You can add a package to the list of requirements with the [`Pkg.add()`](@ref) function, and the package and all the packages that it depends on will be installed: -```julia +```julia-repl julia> Pkg.status() No packages installed. @@ -106,7 +106,7 @@ that the `Distributions` package should be installed since it is required but no stated before, you can accomplish the same thing by editing your `~/.julia/v0.6/REQUIRE` file by hand and then running [`Pkg.resolve()`](@ref) yourself: -```julia +```julia-repl $ echo UTF16 >> ~/.julia/v0.6/REQUIRE julia> Pkg.resolve() @@ -131,7 +131,7 @@ specific ranges of versions of packages. When you decide that you don't want to have a package around any more, you can use [`Pkg.rm()`](@ref) to remove the requirement for it from the `REQUIRE` file: -```julia +```julia-repl julia> Pkg.rm("Distributions") INFO: Removing Distributions v0.2.7 INFO: Removing Stats v0.2.6 @@ -207,7 +207,7 @@ in the previous section interact with registered packages, but the package manag and work with unregistered packages too. To install an unregistered package, use [`Pkg.clone(url)`](@ref), where `url` is a git URL from which the package can be cloned: -```julia +```julia-repl julia> Pkg.clone("git://example.com/path/to/Package.jl.git") INFO: Cloning Package from git://example.com/path/to/Package.jl.git Cloning into 'Package'... @@ -242,7 +242,7 @@ When package developers publish new registered versions of packages that you're of course, want the new shiny versions. To get the latest and greatest versions of all your packages, just do [`Pkg.update()`](@ref): -```julia +```julia-repl julia> Pkg.update() INFO: Updating METADATA... INFO: Computing changes... @@ -276,7 +276,7 @@ You can also update only a subset of the installed packages, by providing argume function. In that case, only the packages provided as arguments and their dependencies will be updated: -```julia +```julia-repl julia> Pkg.update("Example") INFO: Updating METADATA... INFO: Computing changes... @@ -295,7 +295,7 @@ registered versions, or you may be a developer of the package and need to make c or some other development branch. In such cases, you can do [`Pkg.checkout(pkg)`](@ref) to checkout the `master` branch of `pkg` or [`Pkg.checkout(pkg,branch)`](@ref) to checkout some other branch: -```julia +```julia-repl julia> Pkg.add("Distributions") INFO: Installing Distributions v0.2.9 INFO: Installing NumericExtensions v0.2.17 @@ -337,7 +337,7 @@ for this (described below). When you decide that you no longer want to have a package checked out on a branch, you can "free" it back to the control of the package manager with [`Pkg.free(pkg)`](@ref): -```julia +```julia-repl julia> Pkg.free("Distributions") INFO: Freeing Distributions... INFO: No packages to install, update or remove. @@ -356,7 +356,7 @@ be updated as new registered versions of the package are published. If you want to pin a package at a specific version so that calling [`Pkg.update()`](@ref) won't change the version the package is on, you can use the [`Pkg.pin()`](@ref) function: -```julia +```julia-repl julia> Pkg.pin("Stats") INFO: Creating Stats branch pinned.47c198b1.tmp @@ -374,7 +374,7 @@ the same thing. [`Pkg.pin()`](@ref) works by creating a throw-away branch for th to pin the package at and then checking that branch out. By default, it pins a package at the current commit, but you can choose a different version by passing a second argument: -```julia +```julia-repl julia> Pkg.pin("Stats",v"0.2.5") INFO: Creating Stats branch pinned.1fd0983b.tmp INFO: No packages to install, update or remove. @@ -391,7 +391,7 @@ Now the `Stats` package is pinned at commit `1fd0983b`, which corresponds to ver When you decide to "unpin" a package and let the package manager update it again, you can use [`Pkg.free()`](@ref) like you would to move off of any branch: -```julia +```julia-repl julia> Pkg.free("Stats") INFO: Freeing Stats... INFO: No packages to install, update or remove. @@ -424,7 +424,7 @@ local metadata repository using that custom location and branch and then periodi custom branch with the official `metadata-v2` branch. In order to use a custom repository and branch, issue the following command: -```julia +```julia-repl julia> Pkg.init("https://me.example.com/METADATA.jl.git", "branch") ``` @@ -525,7 +525,7 @@ starting with `Pkg.` or `PkgDev.` is meant to be typed at the Julia prompt; anyt with `git` is meant to be typed in [julia's shell mode](@ref man-shell-mode) (or using the shell that comes with your operating system). Within Julia, you can combine these two modes: -```julia +```julia-repl julia> cd(Pkg.dir("Foo")) # go to Foo's folder shell> git command arguments... # command will apply to Foo @@ -743,7 +743,7 @@ Suppose you want to create a new Julia package called `FooBar`. To get started, where `pkg` is the new package name and `license` is the name of a license that the package generator knows about: -```julia +```julia-repl julia> PkgDev.generate("FooBar","MIT") INFO: Initializing FooBar repo: /Users/stefan/.julia/v0.6/FooBar INFO: Origin: git://github.com/StefanKarpinski/FooBar.jl.git @@ -830,7 +830,7 @@ For your package, it will be your GitHub user name and the name of your package, idea. People you send this URL to can use [`Pkg.clone()`](@ref) to install the package and try it out: -```julia +```julia-repl julia> Pkg.clone("git://github.com/StefanKarpinski/FooBar.jl.git") INFO: Cloning FooBar from git@github.com:StefanKarpinski/FooBar.jl.git ``` @@ -849,7 +849,7 @@ INFO: Cloning FooBar from git@github.com:StefanKarpinski/FooBar.jl.git Once you've decided that `FooBar` is ready to be registered as an official package, you can add it to your local copy of `METADATA` using `PkgDev.register()`: -```julia +```julia-repl julia> PkgDev.register("FooBar") INFO: Registering FooBar at git://github.com/StefanKarpinski/FooBar.jl.git INFO: Committing METADATA for FooBar @@ -880,7 +880,7 @@ need to merge your local `METADATA` upstream into the official repo. The `PkgDev will fork the `METADATA` repository on GitHub, push your changes to your fork, and open a pull request: -```julia +```julia-repl julia> PkgDev.publish() INFO: Validating METADATA INFO: No new package versions to publish @@ -910,7 +910,7 @@ Once the package URL for `FooBar` is registered in the official `METADATA` repo, to clone the package from, but there still aren't any registered versions available. You can tag and register it with the `PkgDev.tag()` command: -```julia +```julia-repl julia> PkgDev.tag("FooBar") INFO: Tagging FooBar v0.0.1 INFO: Committing METADATA for FooBar @@ -958,7 +958,7 @@ they've been included upstream. Again, use the `PkgDev.publish()` command, which that individual package repos have been tagged, pushes them if they haven't already been, and then opens a pull request to `METADATA`: -```julia +```julia-repl julia> PkgDev.publish() INFO: Validating METADATA INFO: Pushing FooBar permanent tags: v0.0.1 diff --git a/doc/src/manual/parallel-computing.md b/doc/src/manual/parallel-computing.md index e9993cefdf0aa..185e813f9d889 100644 --- a/doc/src/manual/parallel-computing.md +++ b/doc/src/manual/parallel-computing.md @@ -71,7 +71,7 @@ you read from a remote object to obtain data needed by the next local operation. [`remotecall_fetch()`](@ref) exists for this purpose. It is equivalent to `fetch(remotecall(...))` but is more efficient. -```julia +```julia-repl julia> remotecall_fetch(getindex, 2, r, 1, 1) 0.18526337335308085 ``` @@ -83,7 +83,7 @@ The syntax of [`remotecall()`](@ref) is not especially convenient. The macro [`@ makes things easier. It operates on an expression rather than a function, and picks where to do the operation for you: -```julia +```julia-repl julia> r = @spawn rand(2,2) Future(2, 1, 4, Nullable{Any}()) @@ -113,7 +113,7 @@ have fetched, the remote stored value is deleted. Your code must be available on any process that runs it. For example, type the following into the Julia prompt: -```julia +```julia-repl julia> function rand2(dims...) return 2*rand(dims...) end @@ -169,7 +169,7 @@ Starting Julia with `julia -p 2`, you can use this to verify the following: You can force a command to run on all processes using the [`@everywhere`](@ref) macro. For example, `@everywhere` can also be used to directly define a function on all processes: -```julia +```julia-repl julia> @everywhere id = myid() julia> remotecall_fetch(()->id, 2) @@ -216,7 +216,7 @@ operation. Consider these two approaches to constructing and squaring a random m Method 1: -```julia +```julia-repl julia> A = rand(1000,1000); julia> Bref = @spawn A^2; @@ -228,7 +228,7 @@ julia> fetch(Bref); Method 2: -```julia +```julia-repl julia> Bref = @spawn rand(1000,1000)^2; [...] @@ -256,7 +256,7 @@ Expressions executed remotely via `@spawn`, or closures specified for remote exe a little differently compared to global bindings in other modules. Consider the following code snippet: -```julia +```julia-repl A = rand(10,10) remotecall_fetch(()->foo(A), 2) ``` @@ -296,7 +296,7 @@ altogether if possible. If you must reference globals, consider using `let` bloc For example: -```julia +```julia-repl julia> A = rand(10,10); julia> remotecall_fetch(()->A, 2); @@ -339,7 +339,7 @@ end The function `count_heads` simply adds together `n` random bits. Here is how we can perform some trials on two machines, and add together the results: -```julia +```julia-repl julia> @everywhere include("count_heads.jl") julia> a = @spawn count_heads(100000000) @@ -424,7 +424,7 @@ in some range (or, more generally, to all elements in some collection). This is operation called *parallel map*, implemented in Julia as the [`pmap()`](@ref) function. For example, we could compute the singular values of several large random matrices in parallel as follows: -```julia +```julia-repl julia> M = Matrix{Float64}[rand(1000,1000) for i = 1:10]; julia> pmap(svd, M); @@ -453,7 +453,7 @@ work to processes only when they finish their current tasks. As an example, consider computing the singular values of matrices of different sizes: -```julia +```julia-repl julia> M = Matrix{Float64}[rand(800,800), rand(600,600), rand(800,800), rand(600,600)]; julia> pmap(svd, M); @@ -553,7 +553,7 @@ A channel can be visualized as a pipe, i.e., it has a write end and read end. freely via [`take!()`](@ref) and [`put!()`](@ref) calls. [`close()`](@ref) closes a [`Channel`](@ref). On a closed [`Channel`](@ref), [`put!()`](@ref) will fail. For example: -```julia +```julia-repl julia> c = Channel(2); julia> put!(c, 1) # `put!` on an open channel succeeds @@ -569,7 +569,7 @@ ERROR: InvalidStateException("Channel is closed.",:closed) * [`take!()`](@ref) and [`fetch()`](@ref) (which retrieves but does not remove the value) on a closed channel successfully return any existing values until it is emptied. Continuing the above example: -```julia +```julia-repl julia> fetch(c) # Any number of `fetch` calls succeed. 1 @@ -590,7 +590,7 @@ long as the `Channel` has data or is open. The loop variable takes on all values For example, the following would cause the `for` loop to wait for more data: -```julia +```julia-repl julia> c = Channel{Int}(10); julia> foreach(i->put!(c, i), 1:3) # add a few entries @@ -600,7 +600,7 @@ julia> data = [i for i in c] while this will return after reading all data: -```julia +```julia-repl julia> c = Channel{Int}(10); julia> foreach(i->put!(c, i), 1:3); # add a few entries @@ -620,7 +620,7 @@ Each task in this simulation reads a `job_id`, waits for a random amout of time a tuple of `job_id` and the simulated time to the results channel. Finally all the `results` are printed out. -```julia +```julia-repl julia> const jobs = Channel{Int}(32); julia> const results = Channel{Tuple}(32); @@ -725,7 +725,7 @@ are written to the channel. Each remotely executing task in this simulation read waits for a random amount of time and writes back a tuple of `job_id`, time taken and its own `pid` to the results channel. Finally all the `results` are printed out on the master process. -```julia +```julia-repl julia> addprocs(4); # add worker processes julia> const jobs = RemoteChannel(()->Channel{Int}(32)); @@ -845,7 +845,7 @@ portion of the array, thereby parallelizing initialization. Here's a brief example: -```julia +```julia-repl julia> addprocs(3) 3-element Array{Int64,1}: 2 @@ -872,7 +872,7 @@ julia> S convenient for splitting up tasks among processes. You can, of course, divide the work any way you wish: -```julia +```julia-repl julia> S = SharedArray{Int,2}((3,4), init = S -> S[indexpids(S):length(procs(S)):length(S)] = myid()) 3×4 SharedArray{Int64,2}: 2 2 2 2 @@ -910,7 +910,7 @@ not be ready at the time it's needed for computing `q[i,j,t+1]`. In such cases, off chunking the array manually. Let's split along the second dimension. Define a function that returns the `(irange, jrange)` indexes assigned to this worker: -```julia +```julia-repl julia> @everywhere function myrange(q::SharedArray) idx = indexpids(q) if idx == 0 # This worker is not assigned a piece @@ -924,7 +924,7 @@ julia> @everywhere function myrange(q::SharedArray) Next, define the kernel: -```julia +```julia-repl julia> @everywhere function advection_chunk!(q, u, irange, jrange, trange) @show (irange, jrange, trange) # display so we can see what's happening for t in trange, j in jrange, i in irange @@ -936,20 +936,20 @@ julia> @everywhere function advection_chunk!(q, u, irange, jrange, trange) We also define a convenience wrapper for a `SharedArray` implementation -```julia +```julia-repl julia> @everywhere advection_shared_chunk!(q, u) = advection_chunk!(q, u, myrange(q)..., 1:size(q,3)-1) ``` Now let's compare three different versions, one that runs in a single process: -```julia +```julia-repl julia> advection_serial!(q, u) = advection_chunk!(q, u, 1:size(q,1), 1:size(q,2), 1:size(q,3)-1); ``` one that uses [`@parallel`](@ref): -```julia +```julia-repl julia> function advection_parallel!(q, u) for t = 1:size(q,3)-1 @sync @parallel for j = 1:size(q,2) @@ -964,7 +964,7 @@ julia> function advection_parallel!(q, u) and one that delegates in chunks: -```julia +```julia-repl julia> function advection_shared!(q, u) @sync begin for p in procs(q) @@ -977,7 +977,7 @@ julia> function advection_shared!(q, u) If we create `SharedArray`s and time these functions, we get the following results (with `julia -p 4`): -```julia +```julia-repl julia> q = SharedArray{Float64,3}((500,500,500)); julia> u = SharedArray{Float64,3}((500,500,500)); @@ -985,7 +985,7 @@ julia> u = SharedArray{Float64,3}((500,500,500)); Run the functions once to JIT-compile and [`@time`](@ref) them on the second run: -```julia +```julia-repl julia> @time advection_serial!(q, u); (irange,jrange,trange) = (1:500,1:500,1:499) 830.220 milliseconds (216 allocations: 13820 bytes) @@ -1300,7 +1300,7 @@ in the future. By default, Julia starts up with a single thread of execution. This can be verified by using the command [`Threads.nthreads()`](@ref): -```julia +```julia-repl julia> Threads.nthreads() 1 ``` @@ -1318,14 +1318,14 @@ start up the command line in the location of `julia.exe` and use `set` instead o Let's verify there are 4 threads at our disposal. -```julia +```julia-repl julia> Threads.nthreads() 4 ``` But we are currently on the master thread. To check, we use the command [`Threads.threadid()`](@ref) -```julia +```julia-repl julia> Threads.threadid() 1 ``` @@ -1355,7 +1355,7 @@ thread ID into each location. Julia supports parallel loops using the [`Threads.@threads`](@ref) macro. This macro is affixed in front of a `for` loop to indicate to Julia that the loop is a multi-threaded region: -```julia +```julia-repl julia> Threads.@threads for i = 1:10 a[i] = Threads.threadid() end @@ -1364,7 +1364,7 @@ julia> Threads.@threads for i = 1:10 The iteration space is split amongst the threads, after which each thread writes its thread ID to its assigned locations: -```julia +```julia-repl julia> a 10-element Array{Float64,1}: 1.0 diff --git a/doc/src/manual/performance-tips.md b/doc/src/manual/performance-tips.md index b4a542c433be3..e0b058aa7581e 100644 --- a/doc/src/manual/performance-tips.md +++ b/doc/src/manual/performance-tips.md @@ -34,13 +34,13 @@ being done, and what their inputs and outputs are. In the following REPL session: -```julia +```julia-repl julia> x = 1.0 ``` is equivalent to: -```julia +```julia-repl julia> global x = 1.0 ``` @@ -51,7 +51,7 @@ so all the performance issues discussed previously apply. A useful tool for measuring performance is the [`@time`](@ref) macro. The following example illustrates good working style: -```julia +```julia-repl julia> function f(n) s = 0 for i = 1:n @@ -88,7 +88,7 @@ As a teaser, an improved version of this function allocates no memory (the allocation reported below is due to running the `@time` macro in global scope) and has an order of magnitude faster execution after the first call: -```julia +```julia-repl julia> @time f_improved(1) 0.007008 seconds (1.32 k allocations: 63.640 KiB) 0.5 @@ -257,7 +257,7 @@ like `m` but not for objects like `t`. Of course, all of this is true only if we construct `m` with a concrete type. We can break this by explicitly constructing it with an abstract type: -```julia myambig2 +```julia-repl myambig2 julia> m = MyType{AbstractFloat}(3.2) MyType{AbstractFloat}(3.2) @@ -429,7 +429,7 @@ the array type `A`. However, there's one remaining hole: we haven't enforced that `A` has element type `T`, so it's perfectly possible to construct an object like this: -```julia +```julia-repl julia> b = MyContainer{Int64, UnitRange{Float64}}(UnitRange(1.3, 5.0)); julia> typeof(b) @@ -843,7 +843,7 @@ end Now we will time each of these functions using the same random `10000` by `1` input vector: -```julia +```julia-repl julia> x = randn(10000); julia> fmt(f) = println(rpad(string(f)*": ", 14, ' '), @elapsed f(x)) @@ -906,7 +906,7 @@ end Timing results: -```julia +```julia-repl julia> @time loopinc() 0.529894 seconds (40.00 M allocations: 1.490 GiB, 12.14% gc time) 50000015000000 @@ -951,7 +951,7 @@ Both `f` and `fdot` compute the same thing. However, `fdot` (defined with the help of the [`@.`](@ref @__dot__) macro) is significantly faster when applied to an array: -```julia +```julia-repl julia> x = rand(10^6); julia> @time f(x); @@ -992,7 +992,7 @@ This can be done for individual slices by calling [`view()`](@ref), or more simply for a whole expression or block of code by putting [`@views`](@ref) in front of that expression. For example: -```julia +```julia-repl julia> fcopy(x) = sum(x[2:end-1]) julia> @views fview(x) = sum(x[2:end-1]) diff --git a/doc/src/manual/profile.md b/doc/src/manual/profile.md index 55ad6ee430f69..863c41de36c9c 100644 --- a/doc/src/manual/profile.md +++ b/doc/src/manual/profile.md @@ -36,7 +36,7 @@ any alternatives. Let's work with a simple test case: -```julia +```julia-repl julia> function myfunc() A = rand(200, 200, 400) maximum(A) @@ -46,20 +46,20 @@ julia> function myfunc() It's a good idea to first run the code you intend to profile at least once (unless you want to profile Julia's JIT-compiler): -```julia +```julia-repl julia> myfunc() # run once to force compilation ``` Now we're ready to profile this function: -```julia +```julia-repl julia> @profile myfunc() ``` To see the profiling results, there is a [graphical browser](https://github.com/timholy/ProfileView.jl) available, but here we'll use the text-based display that comes with the standard library: -```julia +```julia-repl julia> Profile.print() 80 ./event.jl:73; (::Base.REPL.##1#2{Base.REPL.REPLBackend})() 80 ./REPL.jl:97; macro expansion @@ -126,7 +126,7 @@ Overall, we can tentatively conclude that generating the random numbers is appro as finding the maximum element. We could increase our confidence in this result by collecting more samples: -```julia +```julia-repl julia> @profile (for i = 1:100; myfunc(); end) julia> Profile.print() @@ -150,7 +150,7 @@ using the `C=true` output mode described below, or by using [ProfileView.jl](htt This illustrates the default "tree" dump; an alternative is the "flat" dump, which accumulates counts independent of their nesting: -```julia +```julia-repl julia> Profile.print(format=:flat) Count File Line Function 6714 ./ -1 anonymous diff --git a/doc/src/manual/running-external-programs.md b/doc/src/manual/running-external-programs.md index 36e624f9f08f1..244e63d7637e6 100644 --- a/doc/src/manual/running-external-programs.md +++ b/doc/src/manual/running-external-programs.md @@ -49,7 +49,7 @@ true More generally, you can use [`open()`](@ref) to read from or write to an external command. -```julia +```julia-repl julia> open(`less`, "w", STDOUT) do io for i = 1:3 println(io, i) @@ -256,7 +256,7 @@ This pipes the output of the `echo` command to the `sort` command. Of course, th interesting since there's only one line to sort, but we can certainly do much more interesting things: -```julia +```julia-repl julia> run(pipeline(`cut -d: -f3 /etc/passwd`, `sort -n`, `tail -n5`)) 210 211 @@ -273,7 +273,7 @@ that shells cannot. Julia can run multiple commands in parallel: -```julia +```julia-repl julia> run(`echo hello` & `echo world`) world hello @@ -326,7 +326,7 @@ setup of pipes between processes is a powerful one. To give some sense of the co that can be created easily, here are some more sophisticated examples, with apologies for the excessive use of Perl one-liners: -```julia +```julia-repl julia> prefixer(prefix, sleep) = `perl -nle '$|=1; print "'$prefix' ", $_; sleep '$sleep';'`; julia> run(pipeline(`perl -le '$|=1; for(0..9){ print; sleep 1 }'`, prefixer("A",2) & prefixer("B",2))) @@ -352,7 +352,7 @@ the output is buffered and printed to the pipe at once, to be read by just one c Here is an even more complex multi-stage producer-consumer example: -```julia +```julia-repl julia> run(pipeline(`perl -le '$|=1; for(0..9){ print; sleep 1 }'`, prefixer("X",3) & prefixer("Y",3) & prefixer("Z",3), prefixer("A",2) & prefixer("B",2))) diff --git a/doc/src/manual/stacktraces.md b/doc/src/manual/stacktraces.md index 2c74b980126e4..82f0ad70f5070 100644 --- a/doc/src/manual/stacktraces.md +++ b/doc/src/manual/stacktraces.md @@ -7,7 +7,7 @@ easy to use programmatically. The primary function used to obtain a stack trace is [`stacktrace()`](@ref): -```julia +```julia-repl julia> stacktrace() 4-element Array{StackFrame,1}: eval(::Module, ::Any) at boot.jl:236 @@ -20,7 +20,7 @@ Calling [`stacktrace()`](@ref) returns a vector of [`StackFrame`](@ref) s. For e alias [`StackTrace`](@ref) can be used in place of `Vector{StackFrame}`. (Examples with `[...]` indicate that output may vary depending on how the code is run.) -```julia +```julia-repl julia> example() = stacktrace() example (generic function with 1 method) @@ -51,7 +51,7 @@ Note that when calling [`stacktrace()`](@ref) you'll typically see a frame with When calling [`stacktrace()`](@ref) from the REPL you'll also have a few extra frames in the stack from `REPL.jl`, usually looking something like this: -```julia +```julia-repl julia> example() = stacktrace() example (generic function with 1 method) @@ -71,7 +71,7 @@ indicating whether the frame has been inlined, a flag indicating whether it is a default C functions do not appear in the stack trace), and an integer representation of the pointer returned by [`backtrace()`](@ref): -```julia +```julia-repl julia> top_frame = stacktrace()[1] eval(::Module, ::Any) at boot.jl:236 @@ -94,7 +94,7 @@ julia> top_frame.from_c false ``` -```julia +```julia-repl julia> top_frame.pointer 0x00007f390d152a59 ``` @@ -107,7 +107,7 @@ more. While having easy access to information about the current state of the callstack can be helpful in many places, the most obvious application is in error handling and debugging. -```julia +```julia-repl julia> @noinline bad_function() = undeclared_variable bad_function (generic function with 1 method) @@ -135,7 +135,7 @@ This can be remedied by calling [`catch_stacktrace()`](@ref) instead of [`stackt Instead of returning callstack information for the current context, [`catch_stacktrace()`](@ref) returns stack information for the context of the most recent exception: -```julia +```julia-repl julia> @noinline bad_function() = undeclared_variable bad_function (generic function with 1 method) @@ -155,7 +155,7 @@ julia> example() Notice that the stack trace now indicates the appropriate line number and the missing frame. -```julia +```julia-repl julia> @noinline child() = error("Whoops!") child (generic function with 1 method) @@ -186,7 +186,7 @@ ERROR: Whoops! A call to [`backtrace()`](@ref) returns a vector of `Ptr{Void}`, which may then be passed into [`stacktrace()`](@ref) for translation: -```julia +```julia-repl julia> trace = backtrace() 21-element Array{Ptr{Void},1}: Ptr{Void} @0x00007f10049d5b2f @@ -225,7 +225,7 @@ by [`stacktrace()`](@ref) only has 5. This is because, by default, [`stacktrace( any lower-level C functions from the stack. If you want to include stack frames from C calls, you can do it like this: -```julia +```julia-repl julia> stacktrace(trace, true) 27-element Array{StackFrame,1}: jl_backtrace_from_here at stackwalk.c:103 @@ -260,7 +260,7 @@ julia> stacktrace(trace, true) Individual pointers returned by [`backtrace()`](@ref) can be translated into [`StackFrame`](@ref) s by passing them into [`StackTraces.lookup()`](@ref): -```julia +```julia-repl julia> pointer = backtrace()[1]; julia> frame = StackTraces.lookup(pointer) diff --git a/doc/src/manual/strings.md b/doc/src/manual/strings.md index bbf29c24f4609..15f76384178d0 100644 --- a/doc/src/manual/strings.md +++ b/doc/src/manual/strings.md @@ -692,7 +692,7 @@ julia> m.offsets It is convenient to have captures returned as an array so that one can use destructuring syntax to bind them to local variables: -```julia +```julia-repl julia> first, second, third = m.captures; first "a" ``` @@ -808,7 +808,7 @@ The Unicode escape `\u2200` is encoded in UTF-8 as the three bytes 226, 136, 128 resulting byte array does not correspond to a valid UTF-8 string -- if you try to use this as a regular string literal, you will get a syntax error: -```julia +```julia-repl julia> "DATA\xff\u2200" ERROR: syntax: invalid UTF-8 sequence ``` diff --git a/doc/src/manual/types.md b/doc/src/manual/types.md index d1fbf2c5dea15..7b1184a82a616 100644 --- a/doc/src/manual/types.md +++ b/doc/src/manual/types.md @@ -1059,7 +1059,7 @@ This can be done with a simple assignment statement. For example, `UInt` is aliased to either `UInt32` or `UInt64` as is appropriate for the size of pointers on the system: -```julia +```julia-repl # 32-bit system: julia> UInt UInt32 diff --git a/doc/src/manual/variables-and-scoping.md b/doc/src/manual/variables-and-scoping.md index af4d02bfcefc8..07004ea14cd2e 100644 --- a/doc/src/manual/variables-and-scoping.md +++ b/doc/src/manual/variables-and-scoping.md @@ -174,7 +174,7 @@ julia> x Within soft scopes, the *global* keyword is never necessary, although allowed. The only case when it would change the semantics is (currently) a syntax error: -```julia +```julia-repl julia> let local j = 2 let @@ -332,7 +332,7 @@ The reason to allow *modifying local* variables of parent scopes in nested funct constructing [closures](https://en.wikipedia.org/wiki/Closure_%28computer_programming%29) which have a private state, for instance the `state` variable in the following example: -```julia +```julia-repl julia> let state = 0 global counter @@ -411,7 +411,7 @@ julia> Fs[2]() Since the `begin` construct does not introduce a new scope, it can be useful to use a zero-argument `let` to just introduce a new scope block without creating any new bindings: -```julia +```julia-repl julia> let local x = 1 let diff --git a/doc/src/manual/variables.md b/doc/src/manual/variables.md index 49c7a9f01167d..8683b3ace795b 100644 --- a/doc/src/manual/variables.md +++ b/doc/src/manual/variables.md @@ -3,7 +3,7 @@ A variable, in Julia, is a name associated (or bound) to a value. It's useful when you want to store a value (that you obtained after some math, for example) for later use. For example: -```julia +```julia-repl # Assign the value 10 to the variable x julia> x = 10 10 @@ -100,7 +100,7 @@ to define `⊗` as an infix Kronecker product). The only explicitly disallowed names for variables are the names of built-in statements: -```julia +```julia-repl julia> else = false ERROR: syntax: unexpected "else" diff --git a/doc/src/stdlib/sort.md b/doc/src/stdlib/sort.md index acd98784759bd..fb762cdc28414 100644 --- a/doc/src/stdlib/sort.md +++ b/doc/src/stdlib/sort.md @@ -3,7 +3,7 @@ Julia has an extensive, flexible API for sorting and interacting with already-sorted arrays of values. By default, Julia picks reasonable algorithms and sorts in standard ascending order: -```julia +```julia-repl julia> sort([2,3,1]) 3-element Array{Int64,1}: 1 @@ -13,7 +13,7 @@ julia> sort([2,3,1]) You can easily sort in reverse order as well: -```julia +```julia-repl julia> sort([2,3,1], rev=true) 3-element Array{Int64,1}: 3 @@ -23,7 +23,7 @@ julia> sort([2,3,1], rev=true) To sort an array in-place, use the "bang" version of the sort function: -```julia +```julia-repl julia> a = [2,3,1]; julia> sort!(a); @@ -38,7 +38,7 @@ julia> a Instead of directly sorting an array, you can compute a permutation of the array's indices that puts the array into sorted order: -```julia +```julia-repl julia> v = randn(5) 5-element Array{Float64,1}: 0.297288 @@ -66,7 +66,7 @@ julia> v[p] Arrays can easily be sorted according to an arbitrary transformation of their values: -```julia +```julia-repl julia> sort(v, by=abs) 5-element Array{Float64,1}: -0.0104452 @@ -78,7 +78,7 @@ julia> sort(v, by=abs) Or in reverse order by a transformation: -```julia +```julia-repl julia> sort(v, by=abs, rev=true) 5-element Array{Float64,1}: -0.839027 @@ -90,7 +90,7 @@ julia> sort(v, by=abs, rev=true) If needed, the sorting algorithm can be chosen: -```julia +```julia-repl julia> sort(v, alg=InsertionSort) 5-element Array{Float64,1}: -0.839027 diff --git a/doc/src/stdlib/test.md b/doc/src/stdlib/test.md index cf8503f851bc4..62ec7e4f3d4ac 100644 --- a/doc/src/stdlib/test.md +++ b/doc/src/stdlib/test.md @@ -26,7 +26,7 @@ Base.Test.@test_throws For example, suppose we want to check our new function `foo(x)` works as expected: -```julia +```julia-repl julia> using Base.Test julia> foo(x) = length(x)^2 @@ -35,7 +35,7 @@ foo (generic function with 1 method) If the condition is true, a `Pass` is returned: -```julia +```julia-repl julia> @test foo("bar") == 9 Test Passed Expression: foo("bar") == 9 @@ -49,7 +49,7 @@ Test Passed If the condition is false, then a `Fail` is returned and an exception is thrown: -```julia +```julia-repl julia> @test foo("f") == 20 Test Failed Expression: foo("f") == 20 @@ -63,7 +63,7 @@ If the condition could not be evaluated because an exception was thrown, which o case because `length()` is not defined for symbols, an `Error` object is returned and an exception is thrown: -```julia +```julia-repl julia> @test foo(:cat) == 1 Error During Test Test threw an exception of type MethodError @@ -80,7 +80,7 @@ ERROR: There was an error during testing If we expect that evaluating an expression *should* throw an exception, then we can use `@test_throws()` to check that this occurs: -```julia +```julia-repl julia> @test_throws MethodError foo(:cat) Test Passed Expression: foo(:cat) @@ -104,7 +104,7 @@ Base.Test.@testset We can put our tests for the `foo(x)` function in a test set: -```julia +```julia-repl julia> @testset "Foo Tests" begin @test foo("a") == 1 @test foo("ab") == 4 @@ -116,7 +116,7 @@ Foo Tests | 3 3 Test sets can also be nested: -```julia +```julia-repl julia> @testset "Foo Tests" begin @testset "Animals" begin @test foo("cat") == 9 @@ -134,7 +134,7 @@ Foo Tests | 8 8 In the event that a nested test set has no failures, as happened here, it will be hidden in the summary. If we do have a test failure, only the details for the failed test sets will be shown: -```julia +```julia-repl julia> @testset "Foo Tests" begin @testset "Animals" begin @testset "Felines" begin @@ -169,7 +169,7 @@ As calculations on floating-point values can be imprecise, you can perform appro checks using either `@test a ≈ b` (where `≈`, typed via tab completion of `\approx`, is the [`isapprox()`](@ref) function) or use [`isapprox()`](@ref) directly. -```julia +```julia-repl julia> @test 1 ≈ 0.999999999 julia> @test 1 ≈ 0.999999 From f67d4fdfe91f10789a1cee034230578a629514f3 Mon Sep 17 00:00:00 2001 From: Morten Piibeleht Date: Sun, 14 May 2017 14:37:35 +1200 Subject: [PATCH 0899/1534] Use at-repl for versioninfo() output --- doc/src/devdocs/backtraces.md | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/doc/src/devdocs/backtraces.md b/doc/src/devdocs/backtraces.md index 059b18ceb4966..647530b5d8c66 100644 --- a/doc/src/devdocs/backtraces.md +++ b/doc/src/devdocs/backtraces.md @@ -18,18 +18,8 @@ No matter the error, we will always need to know what version of Julia you are r first starts up, a header is printed out with a version number and date. If your version is `0.2.0` or higher, please include the output of `versioninfo()` in any report you create: -```julia-repl -julia> versioninfo() -Julia Version 0.3.3-pre+25 -Commit 417b50a* (2014-11-03 11:32 UTC) -Platform Info: - OS: Linux (x86_64-linux-gnu) - CPU: Intel(R) Core(TM) i7 CPU L 640 @ 2.13GHz - WORD_SIZE: 64 - BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Nehalem) - LAPACK: libopenblas - LIBM: libopenlibm - LLVM: libLLVM-3.3 +```@repl +versioninfo() ``` ## Segfaults during bootstrap (`sysimg.jl`) From b710de95c4a6a7d3773d62c63384373de9d78e29 Mon Sep 17 00:00:00 2001 From: Morten Piibeleht Date: Sun, 14 May 2017 14:44:53 +1200 Subject: [PATCH 0900/1534] Enable highlighting in the manual A couple of code examples were not highlighted for some reason. --- doc/src/devdocs/subarrays.md | 4 ++-- doc/src/manual/performance-tips.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/src/devdocs/subarrays.md b/doc/src/devdocs/subarrays.md index e7637dc47b214..cd9ca81b3ea65 100644 --- a/doc/src/devdocs/subarrays.md +++ b/doc/src/devdocs/subarrays.md @@ -54,7 +54,7 @@ any runtime overhead. The strategy adopted is first and foremost expressed in the definition of the type: -``` +```julia struct SubArray{T,N,P,I,L} <: AbstractArray{T,N} parent::P indexes::I @@ -89,7 +89,7 @@ types. For example, for `S1`, one needs to apply the `i,j` indices to the first of the parent array, whereas for `S2` one needs to apply them to the second and third. The simplest approach to indexing would be to do the type-analysis at runtime: -``` +```julia parentindexes = Array{Any}(0) for thisindex in S.indexes ... diff --git a/doc/src/manual/performance-tips.md b/doc/src/manual/performance-tips.md index e0b058aa7581e..209ab0f1c91df 100644 --- a/doc/src/manual/performance-tips.md +++ b/doc/src/manual/performance-tips.md @@ -465,7 +465,7 @@ It is often convenient to work with data structures that may contain values of a of type `Array{Any}`). But, if you're using one of these structures and happen to know the type of an element, it helps to share this knowledge with the compiler: -``` +```julia function foo(a::Array{Any,1}) x = a[1]::Int32 b = x+1 @@ -481,7 +481,7 @@ expected type, potentially catching certain bugs earlier. Keyword arguments can have declared types: -``` +```julia function with_keyword(x; name::Int = 1) ... end From c90c17f194ea7d3908daa099054eb83277939f54 Mon Sep 17 00:00:00 2001 From: Morten Piibeleht Date: Sun, 14 May 2017 15:02:12 +1200 Subject: [PATCH 0901/1534] Remove highlighting from REQUIRE code These blocks are not Julia code, but special REQUIRE file syntax instead. --- doc/src/manual/packages.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/src/manual/packages.md b/doc/src/manual/packages.md index 336f769e23813..7538c632a9d55 100644 --- a/doc/src/manual/packages.md +++ b/doc/src/manual/packages.md @@ -1080,7 +1080,7 @@ If a requirement line has leading words that begin with `@`, it is a system-depe If your system matches these system conditionals, the requirement is included, if not, the requirement is ignored. For example: -```julia +``` @osx Homebrew ``` @@ -1098,7 +1098,7 @@ conditions that are currently supported are (hierarchically): The `@unix` condition is satisfied on all UNIX systems, including Linux and BSD. Negated system conditionals are also supported by adding a `!` after the leading `@`. Examples: -```julia +``` @!windows @unix @!osx ``` From 6e08c1883811706b952ce5d26371f388bc2eeeb0 Mon Sep 17 00:00:00 2001 From: Morten Piibeleht Date: Sun, 14 May 2017 15:03:30 +1200 Subject: [PATCH 0902/1534] Enable bash highlighting Also add a newline to the end of the file. --- doc/src/manual/parallel-computing.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/src/manual/parallel-computing.md b/doc/src/manual/parallel-computing.md index 185e813f9d889..0108eb0097060 100644 --- a/doc/src/manual/parallel-computing.md +++ b/doc/src/manual/parallel-computing.md @@ -1308,7 +1308,7 @@ julia> Threads.nthreads() The number of threads Julia starts up with is controlled by an environment variable called `JULIA_NUM_THREADS`. Now, let's start up Julia with 4 threads: -``` +```bash export JULIA_NUM_THREADS=4 ``` @@ -1415,4 +1415,3 @@ It is very important that the called function does not call back into Julia. introduced a new set of communication mechanisms, collectively referred to as Remote Memory Access (RMA). The motivation for adding RMA to the MPI standard was to facilitate one-sided communication patterns. For additional information on the latest MPI standard, see [http://mpi-forum.org/docs](http://mpi-forum.org/docs/). - From 6e5c55dd733489afab03ce49ee170643f5ef5255 Mon Sep 17 00:00:00 2001 From: Morten Piibeleht Date: Wed, 17 May 2017 19:46:15 +1200 Subject: [PATCH 0903/1534] Use a non-deprecated package in an example UTF16.jl has been deprecated for a while. Use SHA.jl instead as the example. --- doc/src/manual/packages.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/doc/src/manual/packages.md b/doc/src/manual/packages.md index 7538c632a9d55..569806656811f 100644 --- a/doc/src/manual/packages.md +++ b/doc/src/manual/packages.md @@ -31,7 +31,7 @@ set of required and additional packages: julia> Pkg.status() Required packages: - Distributions 0.2.8 - - UTF16 0.2.0 + - SHA 0.3.2 Additional packages: - NumericExtensions 0.2.17 - Stats 0.2.6 @@ -48,7 +48,7 @@ julia> Pkg.installed() Dict{String,VersionNumber} with 4 entries: "Distributions" => v"0.2.8" "Stats" => v"0.2.6" -"UTF16" => v"0.2.0" +"SHA" => v"0.3.2" "NumericExtensions" => v"0.2.17" ``` @@ -107,22 +107,22 @@ stated before, you can accomplish the same thing by editing your `~/.julia/v0.6/ by hand and then running [`Pkg.resolve()`](@ref) yourself: ```julia-repl -$ echo UTF16 >> ~/.julia/v0.6/REQUIRE +$ echo SHA >> ~/.julia/v0.6/REQUIRE julia> Pkg.resolve() -INFO: Cloning cache of UTF16 from git://github.com/nolta/UTF16.jl.git -INFO: Installing UTF16 v0.2.0 +INFO: Cloning cache of SHA from git://github.com/staticfloat/SHA.jl.git +INFO: Installing SHA v0.3.2 julia> Pkg.status() Required packages: - Distributions 0.2.7 - - UTF16 0.2.0 + - SHA 0.3.2 Additional packages: - NumericExtensions 0.2.17 - Stats 0.2.6 ``` -This is functionally equivalent to calling [`Pkg.add("UTF16")`](@ref), except that [`Pkg.add()`](@ref) +This is functionally equivalent to calling [`Pkg.add("SHA")`](@ref), except that [`Pkg.add()`](@ref) doesn't change `REQUIRE` until *after* installation has completed, so if there are problems, `REQUIRE` will be left as it was before calling [`Pkg.add()`](@ref). The format of the `REQUIRE` file is described in [Requirements Specification](@ref); it allows, among other things, requiring @@ -140,10 +140,10 @@ INFO: REQUIRE updated. julia> Pkg.status() Required packages: - - UTF16 0.2.0 + - SHA 0.3.2 -julia> Pkg.rm("UTF16") -INFO: Removing UTF16 v0.2.0 +julia> Pkg.rm("SHA") +INFO: Removing SHA v0.3.2 INFO: REQUIRE updated. julia> Pkg.status() From 96b65f1ef7a2335a93e77efa39b432e8c428b54c Mon Sep 17 00:00:00 2001 From: Morten Piibeleht Date: Sun, 14 May 2017 15:24:40 +1200 Subject: [PATCH 0904/1534] Edit manual/conversion-and-promotion.md The REPL example is basically exactly as above, and does not add anything to the latter bit about the actual convert methods. --- doc/src/manual/conversion-and-promotion.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/doc/src/manual/conversion-and-promotion.md b/doc/src/manual/conversion-and-promotion.md index 576f485e47358..c3d0b2dafad99 100644 --- a/doc/src/manual/conversion-and-promotion.md +++ b/doc/src/manual/conversion-and-promotion.md @@ -134,11 +134,6 @@ actual Julia behaviour. This is the actual implementation in Julia: ```julia convert(::Type{T}, z::Complex) where {T<:Real} = (imag(z) == 0 ? convert(T, real(z)) : throw(InexactError())) - -julia> convert(Bool, 1im) -ERROR: InexactError() - in convert(::Type{Bool}, ::Complex{Int64}) at ./complex.jl:18 - ... ``` ### [Case Study: Rational Conversions](@id man-rational-conversion) From 814a8a1954e9ff88b760741a9068e2ca2946e9bc Mon Sep 17 00:00:00 2001 From: Morten Piibeleht Date: Wed, 17 May 2017 19:24:08 +1200 Subject: [PATCH 0905/1534] Fix line numbers in doctests --- base/docs/helpdb/Base.jl | 2 +- doc/src/manual/constructors.md | 2 +- doc/src/manual/conversion-and-promotion.md | 4 ++-- doc/src/manual/mathematical-operations.md | 14 +++++++------- doc/src/manual/types.md | 4 ++-- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/base/docs/helpdb/Base.jl b/base/docs/helpdb/Base.jl index 622a02c1e3152..ac2f43e33778e 100644 --- a/base/docs/helpdb/Base.jl +++ b/base/docs/helpdb/Base.jl @@ -1957,7 +1957,7 @@ julia> convert(Int, 3.0) julia> convert(Int, 3.5) ERROR: InexactError() Stacktrace: - [1] convert(::Type{Int64}, ::Float64) at ./float.jl:679 + [1] convert(::Type{Int64}, ::Float64) at ./float.jl:680 ``` If `T` is a `AbstractFloat` or `Rational` type, diff --git a/doc/src/manual/constructors.md b/doc/src/manual/constructors.md index e36ec65dda0fb..607e702671211 100644 --- a/doc/src/manual/constructors.md +++ b/doc/src/manual/constructors.md @@ -301,7 +301,7 @@ Point{Int64}(1, 2) julia> Point{Int64}(1.0,2.5) ## explicit T ## ERROR: InexactError() Stacktrace: - [1] convert(::Type{Int64}, ::Float64) at ./float.jl:679 + [1] convert(::Type{Int64}, ::Float64) at ./float.jl:680 [2] Point{Int64}(::Float64, ::Float64) at ./none:2 julia> Point{Float64}(1.0, 2.5) ## explicit T ## diff --git a/doc/src/manual/conversion-and-promotion.md b/doc/src/manual/conversion-and-promotion.md index c3d0b2dafad99..a2632c5c68d2f 100644 --- a/doc/src/manual/conversion-and-promotion.md +++ b/doc/src/manual/conversion-and-promotion.md @@ -120,8 +120,8 @@ false julia> convert(Bool, 1im) ERROR: InexactError() - in convert(::Type{Bool}, ::Complex{Int64}) at ./complex.jl:23 - ... +Stacktrace: + [1] convert(::Type{Bool}, ::Complex{Int64}) at ./complex.jl:23 julia> convert(Bool, 0im) false diff --git a/doc/src/manual/mathematical-operations.md b/doc/src/manual/mathematical-operations.md index 150acc2c0322d..2727ec20cd853 100644 --- a/doc/src/manual/mathematical-operations.md +++ b/doc/src/manual/mathematical-operations.md @@ -397,7 +397,7 @@ julia> Int8(127) julia> Int8(128) ERROR: InexactError() Stacktrace: - [1] Int8(::Int64) at ./sysimg.jl:24 + [1] Int8(::Int64) at ./sysimg.jl:77 julia> Int8(127.0) 127 @@ -405,14 +405,14 @@ julia> Int8(127.0) julia> Int8(3.14) ERROR: InexactError() Stacktrace: - [1] convert(::Type{Int8}, ::Float64) at ./float.jl:658 - [2] Int8(::Float64) at ./sysimg.jl:24 + [1] convert(::Type{Int8}, ::Float64) at ./float.jl:659 + [2] Int8(::Float64) at ./sysimg.jl:77 julia> Int8(128.0) ERROR: InexactError() Stacktrace: - [1] convert(::Type{Int8}, ::Float64) at ./float.jl:658 - [2] Int8(::Float64) at ./sysimg.jl:24 + [1] convert(::Type{Int8}, ::Float64) at ./float.jl:659 + [2] Int8(::Float64) at ./sysimg.jl:77 julia> 127 % Int8 127 @@ -426,8 +426,8 @@ julia> round(Int8,127.4) julia> round(Int8,127.6) ERROR: InexactError() Stacktrace: - [1] trunc(::Type{Int8}, ::Float64) at ./float.jl:651 - [2] round(::Type{Int8}, ::Float64) at ./float.jl:337 + [1] trunc(::Type{Int8}, ::Float64) at ./float.jl:652 + [2] round(::Type{Int8}, ::Float64) at ./float.jl:338 ``` See [Conversion and Promotion](@ref conversion-and-promotion) for how to define your own conversions and promotions. diff --git a/doc/src/manual/types.md b/doc/src/manual/types.md index 7b1184a82a616..633ba5b47fac7 100644 --- a/doc/src/manual/types.md +++ b/doc/src/manual/types.md @@ -341,7 +341,7 @@ must be convertible to `Int`: julia> Foo((), 23.5, 1) ERROR: InexactError() Stacktrace: - [1] convert(::Type{Int64}, ::Float64) at ./float.jl:679 + [1] convert(::Type{Int64}, ::Float64) at ./float.jl:680 [2] Foo(::Tuple{}, ::Float64, ::Int64) at ./none:2 ``` @@ -645,7 +645,7 @@ ERROR: MethodError: Cannot `convert` an object of type Float64 to an object of t This may have arisen from a call to the constructor Point{Float64}(...), since type constructors fall back to convert methods. Stacktrace: - [1] Point{Float64}(::Float64) at ./sysimg.jl:24 + [1] Point{Float64}(::Float64) at ./sysimg.jl:77 julia> Point{Float64}(1.0,2.0,3.0) ERROR: MethodError: no method matching Point{Float64}(::Float64, ::Float64, ::Float64) From a64bcf8e6553423620d39a22a9fc1dc41027a00e Mon Sep 17 00:00:00 2001 From: Morten Piibeleht Date: Wed, 17 May 2017 19:26:35 +1200 Subject: [PATCH 0906/1534] Fix a doctest in base/path.jl --- base/path.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/path.jl b/base/path.jl index c891083fce330..28ac0b520e85d 100644 --- a/base/path.jl +++ b/base/path.jl @@ -139,9 +139,9 @@ Get the directory part of a path. ```jldoctest julia> dirname("/home/myuser") "/home" +``` See also: [`basename`](@ref) -``` """ dirname(path::AbstractString) = splitdir(path)[1] From d9063cb8d4daf69a9b30356c2a6f896bf538c9a7 Mon Sep 17 00:00:00 2001 From: Morten Piibeleht Date: Thu, 18 May 2017 09:45:23 +1200 Subject: [PATCH 0907/1534] Enable a doctest in base/regex.jl --- base/regex.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/regex.jl b/base/regex.jl index 3ea60fd7ff4f2..75e8dcc70e821 100644 --- a/base/regex.jl +++ b/base/regex.jl @@ -75,7 +75,7 @@ after the ending quote, to change its behaviour: For example, this regex has all three flags enabled: -```julia-repl +```jldoctest julia> match(r"a+.*b+.*?d\$"ism, "Goodbye,\\nOh, angry,\\nBad world\\n") RegexMatch("angry,\\nBad world") ``` From 1d20519c02616755b71028e3e7f43f865ae83986 Mon Sep 17 00:00:00 2001 From: Morten Piibeleht Date: Thu, 25 May 2017 16:40:03 +1200 Subject: [PATCH 0908/1534] Enable doctests the the manual Switching to julia-repl revealed several code blocks that could trivially be turned into doctests. --- doc/src/devdocs/cartesian.md | 14 +++++++-- doc/src/devdocs/reflection.md | 20 ++++++------- doc/src/devdocs/subarrays.md | 4 +-- doc/src/manual/arrays.md | 8 ++--- doc/src/manual/conversion-and-promotion.md | 29 +++++++++---------- .../integers-and-floating-point-numbers.md | 10 +++---- doc/src/manual/metaprogramming.md | 2 +- doc/src/manual/performance-tips.md | 4 +-- doc/src/manual/running-external-programs.md | 2 +- doc/src/manual/strings.md | 4 +-- doc/src/manual/variables-and-scoping.md | 6 ++-- doc/src/stdlib/sort.md | 6 ++-- 12 files changed, 59 insertions(+), 50 deletions(-) diff --git a/doc/src/devdocs/cartesian.md b/doc/src/devdocs/cartesian.md index b97c6f2d3418c..f084ef510a223 100644 --- a/doc/src/devdocs/cartesian.md +++ b/doc/src/devdocs/cartesian.md @@ -53,9 +53,19 @@ is `@nref 3 A i` (as in `A[i_1,i_2,i_3]`, where the array comes first). If you're developing code with Cartesian, you may find that debugging is easier when you examine the generated code, using `macroexpand`: -```julia-repl +```@meta +DocTestSetup = quote + import Base.Cartesian: @nref +end +``` + +```jldoctest julia> macroexpand(:(@nref 2 A i)) -:(A[i_1,i_2]) +:(A[i_1, i_2]) +``` + +```@meta +DocTestSetup = nothing ``` ### Supplying the number of expressions diff --git a/doc/src/devdocs/reflection.md b/doc/src/devdocs/reflection.md index cb0b8ae9c8679..9579a21eddaf6 100644 --- a/doc/src/devdocs/reflection.md +++ b/doc/src/devdocs/reflection.md @@ -14,7 +14,7 @@ The names of `DataType` fields may be interrogated using [`fieldnames()`](@ref). given the following type, `fieldnames(Point)` returns an arrays of [`Symbol`](@ref) elements representing the field names: -```julia-repl +```jldoctest struct_point julia> struct Point x::Int y @@ -29,9 +29,9 @@ julia> fieldnames(Point) The type of each field in a `Point` object is stored in the `types` field of the `Point` variable itself: -```julia-repl +```jldoctest struct_point julia> Point.types -svec(Int64,Any) +svec(Int64, Any) ``` While `x` is annotated as an `Int`, `y` was unannotated in the type definition, therefore `y` @@ -39,7 +39,7 @@ defaults to the `Any` type. Types are themselves represented as a structure called `DataType`: -```julia-repl +```jldoctest struct_point julia> typeof(Point) DataType ``` @@ -52,9 +52,9 @@ of these fields is the `types` field observed in the example above. The *direct* subtypes of any `DataType` may be listed using [`subtypes()`](@ref). For example, the abstract `DataType``AbstractFloat` has four (concrete) subtypes: -```julia-repl +```jldoctest julia> subtypes(AbstractFloat) -4-element Array{DataType,1}: +4-element Array{Union{DataType, UnionAll},1}: BigFloat Float16 Float32 @@ -83,9 +83,9 @@ the unquoted and interpolated expression (`Expr`) form for a given macro. To use `quote` the expression block itself (otherwise, the macro will be evaluated and the result will be passed instead!). For example: -```julia-repl +```jldoctest julia> macroexpand( :(@edit println("")) ) -:((Base.edit)(println,(Base.typesof)(""))) +:((Base.edit)(println, (Base.typesof)(""))) ``` The functions `Base.Meta.show_sexpr()` and [`dump()`](@ref) are used to display S-expr style views @@ -95,11 +95,11 @@ Finally, the [`expand()`](@ref) function gives the `lowered` form of any express particular interest for understanding both macros and top-level statements such as function declarations and variable assignments: -```julia-repl +```jldoctest julia> expand( :(f() = 1) ) :(begin $(Expr(:method, :f)) - $(Expr(:method, :f, :((Core.svec)((Core.svec)((Core.Typeof)(f)),(Core.svec)())), CodeInfo(:(begin # none, line 1: + $(Expr(:method, :f, :((Core.svec)((Core.svec)((Core.Typeof)(f)), (Core.svec)())), CodeInfo(:(begin # none, line 1: return 1 end)), false)) return f diff --git a/doc/src/devdocs/subarrays.md b/doc/src/devdocs/subarrays.md index cd9ca81b3ea65..469907cd8fea1 100644 --- a/doc/src/devdocs/subarrays.md +++ b/doc/src/devdocs/subarrays.md @@ -152,7 +152,7 @@ we can define dispatch directly on `SubArray{T,N,A,I,true}` without any intermed Since this computation doesn't depend on runtime values, it can miss some cases in which the stride happens to be uniform: -```julia-repl +```jldoctest julia> A = reshape(1:4*2, 4, 2) 4×2 Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}}: 1 5 @@ -171,7 +171,7 @@ A view constructed as `view(A, 2:2:4, :)` happens to have uniform stride, and th indexing indeed could be performed efficiently. However, success in this case depends on the size of the array: if the first dimension instead were odd, -```julia-repl +```jldoctest julia> A = reshape(1:5*2, 5, 2) 5×2 Base.ReshapedArray{Int64,2,UnitRange{Int64},Tuple{}}: 1 6 diff --git a/doc/src/manual/arrays.md b/doc/src/manual/arrays.md index 090b036351dd1..e9d75f8644072 100644 --- a/doc/src/manual/arrays.md +++ b/doc/src/manual/arrays.md @@ -768,7 +768,7 @@ The [`sparse()`](@ref) function is often a handy way to construct sparse matrice its input a vector `I` of row indices, a vector `J` of column indices, and a vector `V` of nonzero values. `sparse(I,J,V)` constructs a sparse matrix such that `S[I[k], J[k]] = V[k]`. -```julia-repl +```jldoctest sparse_function julia> I = [1, 4, 3, 5]; J = [4, 7, 18, 9]; V = [1, 2, -5, 3]; julia> S = sparse(I,J,V) @@ -782,12 +782,12 @@ julia> S = sparse(I,J,V) The inverse of the [`sparse()`](@ref) function is [`findn()`](@ref), which retrieves the inputs used to create the sparse matrix. -```julia-repl +```jldoctest sparse_function julia> findn(S) -([1,4,5,3],[4,7,9,18]) +([1, 4, 5, 3], [4, 7, 9, 18]) julia> findnz(S) -([1,4,5,3],[4,7,9,18],[1,2,3,-5]) +([1, 4, 5, 3], [4, 7, 9, 18], [1, 2, 3, -5]) ``` Another way to create sparse matrices is to convert a dense matrix into a sparse matrix using diff --git a/doc/src/manual/conversion-and-promotion.md b/doc/src/manual/conversion-and-promotion.md index a2632c5c68d2f..b72d2715b6aeb 100644 --- a/doc/src/manual/conversion-and-promotion.md +++ b/doc/src/manual/conversion-and-promotion.md @@ -46,7 +46,7 @@ generally takes two arguments: the first is a type object while the second is a to that type; the returned value is the value converted to an instance of given type. The simplest way to understand this function is to see it in action: -```julia-repl +```jldoctest julia> x = 12 12 @@ -66,12 +66,12 @@ julia> typeof(ans) Float64 julia> a = Any[1 2 3; 4 5 6] -2x3 Array{Any,2}: +2×3 Array{Any,2}: 1 2 3 4 5 6 julia> convert(Array{Float64}, a) -2x3 Array{Float64,2}: +2×3 Array{Float64,2}: 1.0 2.0 3.0 4.0 5.0 6.0 ``` @@ -79,12 +79,11 @@ julia> convert(Array{Float64}, a) Conversion isn't always possible, in which case a no method error is thrown indicating that `convert` doesn't know how to perform the requested conversion: -```julia-repl +```jldoctest julia> convert(AbstractFloat, "foo") ERROR: MethodError: Cannot `convert` an object of type String to an object of type AbstractFloat This may have arisen from a call to the constructor AbstractFloat(...), since type constructors fall back to convert methods. - ... ``` Some languages consider parsing strings as numbers or formatting numbers as strings to be conversions @@ -111,7 +110,7 @@ example, since the type is a singleton, there would never be any reason to use i the body. When invoked, the method determines whether a numeric value is true or false as a boolean, by comparing it to one and zero: -```julia-repl +```jldoctest julia> convert(Bool, 1) true @@ -196,24 +195,24 @@ any number of arguments, and returns a tuple of the same number of values, conve type, or throws an exception if promotion is not possible. The most common use case for promotion is to convert numeric arguments to a common type: -```julia-repl +```jldoctest julia> promote(1, 2.5) -(1.0,2.5) +(1.0, 2.5) julia> promote(1, 2.5, 3) -(1.0,2.5,3.0) +(1.0, 2.5, 3.0) julia> promote(2, 3//4) -(2//1,3//4) +(2//1, 3//4) julia> promote(1, 2.5, 3, 3//4) -(1.0,2.5,3.0,0.75) +(1.0, 2.5, 3.0, 0.75) julia> promote(1.5, im) -(1.5 + 0.0im,0.0 + 1.0im) +(1.5 + 0.0im, 0.0 + 1.0im) julia> promote(1 + 2im, 3//4) -(1//1 + 2//1*im,3//4 + 0//1*im) +(1//1 + 2//1*im, 3//4 + 0//1*im) ``` Floating-point values are promoted to the largest of the floating-point argument types. Integer @@ -253,7 +252,7 @@ Rational(n::Integer, d::Integer) = Rational(promote(n,d)...) This allows calls like the following to work: -```julia-repl +```jldoctest julia> Rational(Int8(15),Int32(-5)) -3//1 @@ -297,7 +296,7 @@ which, given any number of type objects, returns the common type to which those to `promote` should be promoted. Thus, if one wants to know, in absence of actual values, what type a collection of values of certain types would promote to, one can use `promote_type`: -```julia-repl +```jldoctest julia> promote_type(Int8, UInt16) Int64 ``` diff --git a/doc/src/manual/integers-and-floating-point-numbers.md b/doc/src/manual/integers-and-floating-point-numbers.md index e8bacb86b5ac1..5e1c54347bd3f 100644 --- a/doc/src/manual/integers-and-floating-point-numbers.md +++ b/doc/src/manual/integers-and-floating-point-numbers.md @@ -584,7 +584,7 @@ To make common numeric formulas and expressions clearer, Julia allows variables preceded by a numeric literal, implying multiplication. This makes writing polynomial expressions much cleaner: -```jldoctest +```jldoctest numeric-coefficients julia> x = 3 3 @@ -597,7 +597,7 @@ julia> 1.5x^2 - .5x + 1 It also makes writing exponential functions more elegant: -```julia-repl +```jldoctest numeric-coefficients julia> 2^2x 64 ``` @@ -607,7 +607,7 @@ negation. So `2^3x` is parsed as `2^(3x)`, and `2x^3` is parsed as `2*(x^3)`. Numeric literals also work as coefficients to parenthesized expressions: -```julia-repl +```jldoctest numeric-coefficients julia> 2(x-1)^2 - 3(x-1) + 1 3 ``` @@ -615,7 +615,7 @@ julia> 2(x-1)^2 - 3(x-1) + 1 Additionally, parenthesized expressions can be used as coefficients to variables, implying multiplication of the expression by the variable: -```julia-repl +```jldoctest numeric-coefficients julia> (x-1)x 6 ``` @@ -623,7 +623,7 @@ julia> (x-1)x Neither juxtaposition of two parenthesized expressions, nor placing a variable before a parenthesized expression, however, can be used to imply multiplication: -```julia-repl +```jldoctest numeric-coefficients julia> (x-1)(x+1) ERROR: MethodError: objects of type Int64 are not callable diff --git a/doc/src/manual/metaprogramming.md b/doc/src/manual/metaprogramming.md index c0a3f794534a1..2351621e6269e 100644 --- a/doc/src/manual/metaprogramming.md +++ b/doc/src/manual/metaprogramming.md @@ -920,7 +920,7 @@ we returned from the definition, now with the *value* of `x`. What happens if we evaluate `foo` again with a type that we have already used? -```julia-repl generated +```jldoctest generated julia> foo(4) 16 ``` diff --git a/doc/src/manual/performance-tips.md b/doc/src/manual/performance-tips.md index 209ab0f1c91df..14c91c0d9e379 100644 --- a/doc/src/manual/performance-tips.md +++ b/doc/src/manual/performance-tips.md @@ -257,7 +257,7 @@ like `m` but not for objects like `t`. Of course, all of this is true only if we construct `m` with a concrete type. We can break this by explicitly constructing it with an abstract type: -```julia-repl myambig2 +```jldoctest myambig2 julia> m = MyType{AbstractFloat}(3.2) MyType{AbstractFloat}(3.2) @@ -429,7 +429,7 @@ the array type `A`. However, there's one remaining hole: we haven't enforced that `A` has element type `T`, so it's perfectly possible to construct an object like this: -```julia-repl +```jldoctest containers2 julia> b = MyContainer{Int64, UnitRange{Float64}}(UnitRange(1.3, 5.0)); julia> typeof(b) diff --git a/doc/src/manual/running-external-programs.md b/doc/src/manual/running-external-programs.md index 244e63d7637e6..c1840aafce31a 100644 --- a/doc/src/manual/running-external-programs.md +++ b/doc/src/manual/running-external-programs.md @@ -49,7 +49,7 @@ true More generally, you can use [`open()`](@ref) to read from or write to an external command. -```julia-repl +```jldoctest julia> open(`less`, "w", STDOUT) do io for i = 1:3 println(io, i) diff --git a/doc/src/manual/strings.md b/doc/src/manual/strings.md index 15f76384178d0..4d4b9d5a0f158 100644 --- a/doc/src/manual/strings.md +++ b/doc/src/manual/strings.md @@ -645,7 +645,7 @@ For when a capture doesn't match, instead of a substring, `m.captures` contains position, and `m.offsets` has a zero offset (recall that indices in Julia are 1-based, so a zero offset into a string is invalid). Here is a pair of somewhat contrived examples: -```jldoctest +```jldoctest acdmatch julia> m = match(r"(a|b)(c)?(d)", "acd") RegexMatch("acd", 1="a", 2="c", 3="d") @@ -692,7 +692,7 @@ julia> m.offsets It is convenient to have captures returned as an array so that one can use destructuring syntax to bind them to local variables: -```julia-repl +```jldoctest acdmatch julia> first, second, third = m.captures; first "a" ``` diff --git a/doc/src/manual/variables-and-scoping.md b/doc/src/manual/variables-and-scoping.md index 07004ea14cd2e..054a28c411a83 100644 --- a/doc/src/manual/variables-and-scoping.md +++ b/doc/src/manual/variables-and-scoping.md @@ -174,7 +174,7 @@ julia> x Within soft scopes, the *global* keyword is never necessary, although allowed. The only case when it would change the semantics is (currently) a syntax error: -```julia-repl +```jldoctest julia> let local j = 2 let @@ -332,7 +332,7 @@ The reason to allow *modifying local* variables of parent scopes in nested funct constructing [closures](https://en.wikipedia.org/wiki/Closure_%28computer_programming%29) which have a private state, for instance the `state` variable in the following example: -```julia-repl +```jldoctest julia> let state = 0 global counter @@ -411,7 +411,7 @@ julia> Fs[2]() Since the `begin` construct does not introduce a new scope, it can be useful to use a zero-argument `let` to just introduce a new scope block without creating any new bindings: -```julia-repl +```jldoctest julia> let local x = 1 let diff --git a/doc/src/stdlib/sort.md b/doc/src/stdlib/sort.md index fb762cdc28414..3397d772bdda8 100644 --- a/doc/src/stdlib/sort.md +++ b/doc/src/stdlib/sort.md @@ -3,7 +3,7 @@ Julia has an extensive, flexible API for sorting and interacting with already-sorted arrays of values. By default, Julia picks reasonable algorithms and sorts in standard ascending order: -```julia-repl +```jldoctest julia> sort([2,3,1]) 3-element Array{Int64,1}: 1 @@ -13,7 +13,7 @@ julia> sort([2,3,1]) You can easily sort in reverse order as well: -```julia-repl +```jldoctest julia> sort([2,3,1], rev=true) 3-element Array{Int64,1}: 3 @@ -23,7 +23,7 @@ julia> sort([2,3,1], rev=true) To sort an array in-place, use the "bang" version of the sort function: -```julia-repl +```jldoctest julia> a = [2,3,1]; julia> sort!(a); From 4cbfd59551a770ef610bbd3ce35be6b68770063b Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Thu, 25 May 2017 09:52:08 +0200 Subject: [PATCH 0909/1534] jump to numbered method in the REPL (#22007) --- NEWS.md | 4 +++ base/REPL.jl | 6 ++-- base/methodshow.jl | 6 +++- base/replutil.jl | 10 +++--- doc/src/manual/interacting-with-julia.md | 2 +- doc/src/manual/methods.md | 40 ++++++++++++------------ 6 files changed, 38 insertions(+), 30 deletions(-) diff --git a/NEWS.md b/NEWS.md index 03667d85d753d..6795618411d01 100644 --- a/NEWS.md +++ b/NEWS.md @@ -36,6 +36,10 @@ Library improvements * the functions `base` and `digits` digits now accept a negative base (like `ndigits` did) ([#21692]). + * Method lists are now printed as a numbered list. In addition, the source code of a + method can be opened in an editor by entering the corresponding number in the REPL + and pressing `^Q` ([#22007]). + Compiler/Runtime improvements ----------------------------- diff --git a/base/REPL.jl b/base/REPL.jl index dda4a65ac0dad..973322131e41a 100644 --- a/base/REPL.jl +++ b/base/REPL.jl @@ -891,11 +891,11 @@ function setup_interface(repl::LineEditREPL; hascolor = repl.hascolor, extra_rep end end, - # Open the editor at the location of a stackframe + # Open the editor at the location of a stackframe or method # This is accessing a global variable that gets set in - # the show_backtrace function. + # the show_backtrace and show_method_table functions. "^Q" => (s, o...) -> begin - linfos = Base.LAST_BACKTRACE_LINE_INFOS + linfos = Base.LAST_SHOWN_LINE_INFOS str = String(take!(LineEdit.buffer(s))) n = tryparse(Int, str) isnull(n) && @goto writeback diff --git a/base/methodshow.jl b/base/methodshow.jl index c9f304a509c9e..c6ef522b3261a 100644 --- a/base/methodshow.jl +++ b/base/methodshow.jl @@ -150,11 +150,15 @@ function show_method_table(io::IO, ms::MethodList, max::Int=-1, header::Bool=tru kwtype = isdefined(mt, :kwsorter) ? Nullable{DataType}(typeof(mt.kwsorter)) : Nullable{DataType}() n = rest = 0 local last + + resize!(LAST_SHOWN_LINE_INFOS, 0) for meth in ms if max==-1 || n n_frames += 1, t) n_frames != 0 && print(io, "\nStacktrace:") process_entry = (last_frame, n) -> begin frame_counter += 1 show_trace_entry(IOContext(io, :backtrace => true), last_frame, n, prefix = string(" [", frame_counter, "] ")) - push!(LAST_BACKTRACE_LINE_INFOS, (string(last_frame.file), last_frame.line)) + push!(LAST_SHOWN_LINE_INFOS, (string(last_frame.file), last_frame.line)) end process_backtrace(process_entry, t) end diff --git a/doc/src/manual/interacting-with-julia.md b/doc/src/manual/interacting-with-julia.md index f388251f77802..d4c76213676ce 100644 --- a/doc/src/manual/interacting-with-julia.md +++ b/doc/src/manual/interacting-with-julia.md @@ -171,7 +171,7 @@ to do so). | `^K` | "Kill" to end of line, placing the text in a buffer | | `^Y` | "Yank" insert the text from the kill buffer | | `^T` | Transpose the characters about the cursor | -| `^Q` | Write a number in REPL and press `^Q` to open editor at corresponding stackframe | +| `^Q` | Write a number in REPL and press `^Q` to open editor at corresponding stackframe or method | ### Customizing keybindings diff --git a/doc/src/manual/methods.md b/doc/src/manual/methods.md index 1b46b99ab47c7..466c8e9a5590b 100644 --- a/doc/src/manual/methods.md +++ b/doc/src/manual/methods.md @@ -166,8 +166,8 @@ of those methods are, use the [`methods()`](@ref) function: ```julia julia> methods(f) # 2 methods for generic function "f": -f(x::Float64, y::Float64) in Main at none:1 -f(x::Number, y::Number) in Main at none:1 +[1] f(x::Float64, y::Float64) in Main at none:1 +[2] f(x::Number, y::Number) in Main at none:1 ``` which shows that `f` has two methods, one taking two `Float64` arguments and one taking arguments @@ -196,25 +196,25 @@ of methods: ```julia julia> methods(+) # 180 methods for generic function "+": -+(x::Bool, z::Complex{Bool}) in Base at complex.jl:224 -+(x::Bool, y::Bool) in Base at bool.jl:89 -+(x::Bool) in Base at bool.jl:86 -+(x::Bool, y::T) where T<:AbstractFloat in Base at bool.jl:96 -+(x::Bool, z::Complex) in Base at complex.jl:231 -+(a::Float16, b::Float16) in Base at float.jl:372 -+(x::Float32, y::Float32) in Base at float.jl:374 -+(x::Float64, y::Float64) in Base at float.jl:375 -+(z::Complex{Bool}, x::Bool) in Base at complex.jl:225 -+(z::Complex{Bool}, x::Real) in Base at complex.jl:239 -+(x::Char, y::Integer) in Base at char.jl:40 -+(c::BigInt, x::BigFloat) in Base.MPFR at mpfr.jl:303 -+(a::BigInt, b::BigInt, c::BigInt, d::BigInt, e::BigInt) in Base.GMP at gmp.jl:303 -+(a::BigInt, b::BigInt, c::BigInt, d::BigInt) in Base.GMP at gmp.jl:296 -+(a::BigInt, b::BigInt, c::BigInt) in Base.GMP at gmp.jl:290 -+(x::BigInt, y::BigInt) in Base.GMP at gmp.jl:258 -+(x::BigInt, c::Union{UInt16, UInt32, UInt64, UInt8}) in Base.GMP at gmp.jl:315 +[1] +(x::Bool, z::Complex{Bool}) in Base at complex.jl:227 +[2] +(x::Bool, y::Bool) in Base at bool.jl:89 +[3] +(x::Bool) in Base at bool.jl:86 +[4] +(x::Bool, y::T) where T<:AbstractFloat in Base at bool.jl:96 +[5] +(x::Bool, z::Complex) in Base at complex.jl:234 +[6] +(a::Float16, b::Float16) in Base at float.jl:373 +[7] +(x::Float32, y::Float32) in Base at float.jl:375 +[8] +(x::Float64, y::Float64) in Base at float.jl:376 +[9] +(z::Complex{Bool}, x::Bool) in Base at complex.jl:228 +[10] +(z::Complex{Bool}, x::Real) in Base at complex.jl:242 +[11] +(x::Char, y::Integer) in Base at char.jl:40 +[12] +(c::BigInt, x::BigFloat) in Base.MPFR at mpfr.jl:307 +[13] +(a::BigInt, b::BigInt, c::BigInt, d::BigInt, e::BigInt) in Base.GMP at gmp.jl:392 +[14] +(a::BigInt, b::BigInt, c::BigInt, d::BigInt) in Base.GMP at gmp.jl:391 +[15] +(a::BigInt, b::BigInt, c::BigInt) in Base.GMP at gmp.jl:390 +[16] +(x::BigInt, y::BigInt) in Base.GMP at gmp.jl:361 +[17] +(x::BigInt, c::Union{UInt16, UInt32, UInt64, UInt8}) in Base.GMP at gmp.jl:398 ... -+(a, b, c, xs...) at operators.jl:119 +[180] +(a, b, c, xs...) in Base at operators.jl:424 ``` Multiple dispatch together with the flexible parametric type system give Julia its ability to From 215adb22735e664bd7c18c1132c3a182eec56a31 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Thu, 25 May 2017 09:53:14 +0200 Subject: [PATCH 0910/1534] Fix `@deprecate` with the new `where` syntax (#22034) * fix at-deprecate with where syntax * tests for at-deprecate --- base/deprecated.jl | 32 +++++++++++++++++++------------- test/misc.jl | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 13 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index cedc68e0e2a92..e882c3be8481a 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -18,37 +18,43 @@ # the name of the function, which is used to ensure that the deprecation warning # is only printed the first time for each call place. -macro deprecate(old,new,ex=true) +macro deprecate(old, new, ex=true) meta = Expr(:meta, :noinline) @gensym oldmtname - if isa(old,Symbol) - oldname = Expr(:quote,old) - newname = Expr(:quote,new) + if isa(old, Symbol) + oldname = Expr(:quote, old) + newname = Expr(:quote, new) Expr(:toplevel, - ex ? Expr(:export,esc(old)) : nothing, + ex ? Expr(:export, esc(old)) : nothing, :(function $(esc(old))(args...) $meta - depwarn(string($oldname," is deprecated, use ",$newname," instead."), + depwarn(string($oldname, " is deprecated, use ", $newname, " instead."), $oldmtname) $(esc(new))(args...) end), :(const $oldmtname = Core.Typeof($(esc(old))).name.mt.name)) - elseif isa(old,Expr) && old.head == :call + elseif isa(old, Expr) && (old.head == :call || old.head == :where) remove_linenums!(new) oldcall = sprint(show_unquoted, old) newcall = sprint(show_unquoted, new) - oldsym = if isa(old.args[1],Symbol) - old.args[1]::Symbol - elseif isa(old.args[1],Expr) && old.args[1].head == :curly - old.args[1].args[1]::Symbol + # if old.head is a :where, step down one level to the :call to avoid code duplication below + callexpr = old.head == :call ? old : old.args[1] + if callexpr.head == :call + if isa(callexpr.args[1], Symbol) + oldsym = callexpr.args[1]::Symbol + elseif isa(callexpr.args[1], Expr) && callexpr.args[1].head == :curly + oldsym = callexpr.args[1].args[1]::Symbol + else + error("invalid usage of @deprecate") + end else error("invalid usage of @deprecate") end Expr(:toplevel, - ex ? Expr(:export,esc(oldsym)) : nothing, + ex ? Expr(:export, esc(oldsym)) : nothing, :($(esc(old)) = begin $meta - depwarn(string($oldcall," is deprecated, use ",$newcall," instead."), + depwarn(string($oldcall, " is deprecated, use ", $newcall, " instead."), $oldmtname) $(esc(new)) end), diff --git a/test/misc.jl b/test/misc.jl index 4116a6ea9e52a..599aadf854064 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -701,3 +701,44 @@ end @test hton(0x102030405060708) == 0x807060504030201 @test ltoh(0x102030405060708) == 0x102030405060708 @test htol(0x102030405060708) == 0x102030405060708 + +module DeprecationTests # to test @deprecate + f() = true + + # test the Symbol path of @deprecate + @deprecate f1 f + @deprecate f2 f false # test that f2 is not exported + + # test the Expr path of @deprecate + @deprecate f3() f() + @deprecate f4() f() false # test that f4 is not exported + @deprecate f5(x::T) where T f() + + # test deprecation of a constructor + struct A{T} end + @deprecate A{T}(x::S) where {T, S} f() +end # module + +@testset "@deprecate" begin + using .DeprecationTests + # enable when issue #22043 is fixed + # @test @test_warn "f1 is deprecated, use f instead." f1() + # @test @test_nowarn f1() + + # @test_throws UndefVarError f2() # not exported + # @test @test_warn "f2 is deprecated, use f instead." DeprecationTests.f2() + # @test @test_nowarn DeprecationTests.f2() + + # @test @test_warn "f3() is deprecated, use f() instead." f3() + # @test @test_nowarn f3() + + # @test_throws UndefVarError f4() # not exported + # @test @test_warn "f4() is deprecated, use f() instead." DeprecationTests.f4() + # @test @test_nowarn DeprecationTests.f4() + + # @test @test_warn "f5(x::T) where T is deprecated, use f() instead." f5(1) + # @test @test_nowarn f5(1) + + # @test @test_warn "A{T}(x::S) where {T, S} is deprecated, use f() instead." A{Int}(1.) + # @test @test_nowarn A{Int}(1.) +end From 888adbcb9eb0da0d12c771af29dcb854b5ed0e6d Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Thu, 25 May 2017 09:54:22 +0200 Subject: [PATCH 0911/1534] document AbstractArray and doctest for Array (#22052) --- base/abstractarray.jl | 7 +++++++ base/array.jl | 14 +++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 92236060a78fb..2ac43912a6960 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -2,6 +2,13 @@ ## Basic functions ## +""" + AbstractArray{T, N} + +Abstract array supertype which arrays inherit from. +""" +AbstractArray + """ size(A::AbstractArray, [dim...]) diff --git a/base/array.jl b/base/array.jl index c6b4c24da7ef5..3677f92717a9a 100644 --- a/base/array.jl +++ b/base/array.jl @@ -53,10 +53,22 @@ import Core: arraysize, arrayset, arrayref Array{T,N}(dims) Construct an uninitialized `N`-dimensional dense array with element type `T`, -where `N` is determined from the length or number of `dims`. `dims` may +where `N` is determined from the length or number of `dims`. `dims` may be a tuple or a series of integer arguments corresponding to the lengths in each dimension. If the rank `N` is supplied explicitly as in `Array{T,N}(dims)`, then it must match the length or number of `dims`. + +# Example + +```jldoctest +julia> A = Array{Float64, 2}(2, 2); + +julia> ndims(A) +2 + +julia> eltype(A) +Float64 +``` """ Array From 3494ae70001bc7c19b4b87d76f3bbee2ab519c62 Mon Sep 17 00:00:00 2001 From: Nathan Smith Date: Thu, 25 May 2017 12:40:13 -0400 Subject: [PATCH 0912/1534] Add complex randn (#21973) * Add complex randn --- NEWS.md | 5 ++++- base/random.jl | 9 ++++++++- base/sysimg.jl | 6 +++--- test/random.jl | 13 ++++++++++--- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/NEWS.md b/NEWS.md index 6795618411d01..923c7dcbdbdad 100644 --- a/NEWS.md +++ b/NEWS.md @@ -33,9 +33,12 @@ This section lists changes that do not have deprecation warnings. Library improvements -------------------- - * the functions `base` and `digits` digits now accept a negative + * The functions `base` and `digits` digits now accept a negative base (like `ndigits` did) ([#21692]). + * The function `randn` now accepts complex arguments (`Complex{T <: AbstractFloat}`) + ([#21973]). + * Method lists are now printed as a numbered list. In addition, the source code of a method can be opened in an editor by entering the corresponding number in the REPL and pressing `^Q` ([#22007]). diff --git a/base/random.jl b/base/random.jl index f4b86f3d353ab..3697302a05153 100644 --- a/base/random.jl +++ b/base/random.jl @@ -1181,7 +1181,9 @@ const ziggurat_exp_r = 7.6971174701310497140446280481 Generate a normally-distributed random number of type `T` with mean 0 and standard deviation 1. Optionally generate an array of normally-distributed random numbers. The `Base` module currently provides an implementation for the types -`Float16`, `Float32`, and `Float64` (the default). +`Float16`, `Float32`, and `Float64` (the default), and their `Complex` counterparts. +When the type argument is complex, the values are drawn from the circularly symmetric +complex normal distribution. """ @inline function randn(rng::AbstractRNG=GLOBAL_RNG) @inbounds begin @@ -1284,6 +1286,11 @@ let Floats = Union{Float16,Float32,Float64} end end +# complex randn +Base.@irrational SQRT_HALF 0.7071067811865475244008 sqrt(big(0.5)) +randn(rng::AbstractRNG, ::Type{Complex{T}}) where {T <: AbstractFloat} = + Complex{T}(SQRT_HALF * randn(rng, T), SQRT_HALF * randn(rng, T)) + ## random UUID generation struct UUID diff --git a/base/sysimg.jl b/base/sysimg.jl index a35f38ef2e423..11a239a5f93bd 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -297,6 +297,9 @@ include("combinatorics.jl") # more hashing definitions include("hashing2.jl") +# irrational mathematical constants +include("irrationals.jl") + # random number generation include("dSFMT.jl") include("random.jl") @@ -357,9 +360,6 @@ const × = cross # statistics include("statistics.jl") -# irrational mathematical constants -include("irrationals.jl") - # signal processing include("dft.jl") importall .DFT diff --git a/test/random.jl b/test/random.jl index 1be9333d7ecd7..0d54f0a426cc4 100644 --- a/test/random.jl +++ b/test/random.jl @@ -13,6 +13,7 @@ srand(0); rand(); x = rand(384) @test typeof(rand(false:true)) === Bool @test typeof(rand(Char)) === Char @test length(randn(4, 5)) == 20 +@test length(randn(Complex128, 4, 5)) == 20 @test length(bitrand(4, 5)) == 20 @test rand(MersenneTwister(0)) == 0.8236475079774124 @@ -65,6 +66,11 @@ randn!(MersenneTwister(42), A) @test A == [-0.5560268761463861 0.027155338009193845; -0.444383357109696 -0.29948409035891055] +B = zeros(Complex128, 2) +randn!(MersenneTwister(42), B) +@test B == [Complex128(-0.5560268761463861,-0.444383357109696), + Complex128(0.027155338009193845,-0.29948409035891055)] * 0.7071067811865475244008 + for T in (Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128, BigInt, Float16, Float32, Float64, Rational{Int}) r = rand(convert(T, 97):convert(T, 122)) @@ -306,8 +312,9 @@ end # test all rand APIs for rng in ([], [MersenneTwister(0)], [RandomDevice()]) - types = [Base.BitInteger_types..., Bool, Float16, Float32, Float64, Char] ftypes = [Float16, Float32, Float64] + cftypes = [Complex32, Complex64, Complex128, ftypes...] + types = [Bool, Char, Base.BitInteger_types..., ftypes...] b2 = big(2) u3 = UInt(3) for f in [rand, randn, randexp] @@ -316,7 +323,7 @@ for rng in ([], [MersenneTwister(0)], [RandomDevice()]) f(rng..., 2, 3) ::Array{Float64, 2} f(rng..., b2, u3) ::Array{Float64, 2} f(rng..., (2, 3)) ::Array{Float64, 2} - for T in (f === rand ? types : ftypes) + for T in (f === rand ? types : f === randn ? cftypes : ftypes) a0 = f(rng..., T) ::T a1 = f(rng..., T, 5) ::Vector{T} a2 = f(rng..., T, 2, 3) ::Array{T, 2} @@ -330,7 +337,7 @@ for rng in ([], [MersenneTwister(0)], [RandomDevice()]) end end for f! in [rand!, randn!, randexp!] - for T in (f! === rand! ? types : ftypes) + for T in (f! === rand! ? types : f! === randn! ? cftypes : ftypes) X = T == Bool ? T[0,1] : T[0,1,2] for A in (Array{T}(5), Array{T}(2, 3)) f!(rng..., A) ::typeof(A) From 4158b5ebfce628bf899fdd7f5b165bbb41cf9901 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Thu, 25 May 2017 11:59:28 -0700 Subject: [PATCH 0913/1534] Fix opensuse repo links for make win-extras (#22058) --- Makefile | 4 ++-- contrib/windows/get_toolchain.sh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index dda792566108a..f88264d5ed4fa 100644 --- a/Makefile +++ b/Makefile @@ -590,7 +590,7 @@ ifneq (,$(filter $(ARCH), i386 i486 i586 i686)) cd $(JULIAHOME)/dist-extras && \ $(JLDOWNLOAD) http://downloads.sourceforge.net/sevenzip/7z920.exe && \ 7z x -y 7z920.exe 7z.exe 7z.dll && \ - ../contrib/windows/winrpm.sh http://download.opensuse.org/repositories/windows:/mingw:/win32/openSUSE_42.2 \ + ../contrib/windows/winrpm.sh http://download.opensuse.org/repositories/windows:/mingw:/win32/openSUSE_Leap_42.2 \ "mingw32-libgfortran3 mingw32-libquadmath0 mingw32-libstdc++6 mingw32-libgcc_s_sjlj1 mingw32-libssp0 mingw32-libwinpthread1 mingw32-libexpat1 mingw32-zlib1" && \ cp usr/i686-w64-mingw32/sys-root/mingw/bin/*.dll . else ifeq ($(ARCH),x86_64) @@ -599,7 +599,7 @@ else ifeq ($(ARCH),x86_64) 7z x -y 7z920-x64.msi _7z.exe _7z.dll && \ mv _7z.dll 7z.dll && \ mv _7z.exe 7z.exe && \ - ../contrib/windows/winrpm.sh http://download.opensuse.org/repositories/windows:/mingw:/win64/openSUSE_42.2 \ + ../contrib/windows/winrpm.sh http://download.opensuse.org/repositories/windows:/mingw:/win64/openSUSE_Leap_42.2 \ "mingw64-libgfortran3 mingw64-libquadmath0 mingw64-libstdc++6 mingw64-libgcc_s_seh1 mingw64-libssp0 mingw64-libwinpthread1 mingw64-libexpat1 mingw64-zlib1" && \ cp usr/x86_64-w64-mingw32/sys-root/mingw/bin/*.dll . else diff --git a/contrib/windows/get_toolchain.sh b/contrib/windows/get_toolchain.sh index 290a18195ef58..01e9ad973b213 100755 --- a/contrib/windows/get_toolchain.sh +++ b/contrib/windows/get_toolchain.sh @@ -27,7 +27,7 @@ case $bits in ;; esac echo "Downloading $host toolchain, check $PWD/get_toolchain.log for full output" -contrib/windows/winrpm.sh http://download.opensuse.org/repositories/windows:/mingw:/win$bits/openSUSE_42.2 \ +contrib/windows/winrpm.sh http://download.opensuse.org/repositories/windows:/mingw:/win$bits/openSUSE_Leap_42.2 \ "mingw$bits-gcc mingw$bits-gcc-c++ mingw$bits-gcc-fortran \ mingw$bits-libssp0 mingw$bits-libstdc++6 mingw$bits-libgfortran3" > get_toolchain.log From 3900e338d068d933baec8fbbea44f98c0ad62f1f Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 24 May 2017 16:44:33 -0400 Subject: [PATCH 0914/1534] fix scope rules: implicitly using a global doesn't add it to the scope fix #21900 --- base/REPL.jl | 1 + base/libgit2/libgit2.jl | 2 +- src/jlfrontend.scm | 29 ++++++++------- src/julia-syntax.scm | 54 +++++++++++++--------------- test/core.jl | 78 ++++++++++++++++++++++++++++++++++++++--- test/libgit2.jl | 1 + 6 files changed, 115 insertions(+), 50 deletions(-) diff --git a/base/REPL.jl b/base/REPL.jl index dda4a65ac0dad..8054e048600cb 100644 --- a/base/REPL.jl +++ b/base/REPL.jl @@ -633,6 +633,7 @@ function respond(f, repl, main; pass_empty = false) line = String(take!(buf)) if !isempty(line) || pass_empty reset(repl) + local val, bt try # note: value wrapped carefully here to ensure it doesn't get passed through expand response = eval(Main, Expr(:body, Expr(:return, Expr(:call, QuoteNode(f), QuoteNode(line))))) diff --git a/base/libgit2/libgit2.jl b/base/libgit2/libgit2.jl index c8ba346ec52f1..800e5a71b53d8 100644 --- a/base/libgit2/libgit2.jl +++ b/base/libgit2/libgit2.jl @@ -149,10 +149,10 @@ function isdiff(repo::GitRepo, treeish::AbstractString, paths::AbstractString="" diff = diff_tree(repo, tree, paths, cached=cached) result = count(diff) > 0 close(diff) + return result finally close(tree) end - return result end """ diff --git a/src/jlfrontend.scm b/src/jlfrontend.scm index 5c973bacd83f0..28f62d2525fb0 100644 --- a/src/jlfrontend.scm +++ b/src/jlfrontend.scm @@ -50,6 +50,7 @@ (cdr e)))) tab))) +;; find variables that should be forced to be global in a toplevel expr (define (find-possible-globals e) (table.keys (find-possible-globals- e (table)))) @@ -59,19 +60,6 @@ (define (some-gensym? x) (or (gensym? x) (memq x *gensyms*))) -;; find variables that should be forced to be global in a toplevel expr -(define (toplevel-expr-globals e) - (diff - (delete-duplicates - (append - ;; vars assigned at the outer level - (filter (lambda (x) (not (some-gensym? x))) (find-assigned-vars e '())) - ;; vars declared const or global outside any scope block - (find-decls 'const e) - (find-decls 'global e) - ;; vars assigned anywhere, if they have been defined as global - (filter defined-julia-global (find-possible-globals e)))) - (find-decls 'local e))) ;; return a lambda expression representing a thunk for a top-level expression ;; note: expansion of stuff inside module is delayed, so the contents obey @@ -81,11 +69,22 @@ (if (and (pair? ex0) (eq? (car ex0) 'toplevel)) ex0 (let* ((ex (julia-expand0 ex0)) - (gv (toplevel-expr-globals ex)) + (lv (find-decls 'local ex)) + (gv (diff (delete-duplicates + (append (find-decls 'const ex) ;; convert vars declared const outside any scope block to outer-globals + (find-decls 'global ex) ;; convert vars declared global outside any scope block to outer-globals + ;; vars assigned at the outer level + (filter (lambda (x) (not (some-gensym? x))) + (find-assigned-vars ex '())))) + lv)) + ;; vars assigned anywhere, if they have not been explicitly defined + (existing-gv (filter (lambda (x) (and (not (or (memq x lv) (memq x gv))) (defined-julia-global x))) + (find-possible-globals ex))) (th (julia-expand1 `(lambda () () (scope-block - (block ,@(map (lambda (v) `(implicit-global ,v)) gv) + (block ,@(map (lambda (v) `(implicit-global ,v)) existing-gv) + ,@(map (lambda (v) `(implicit-global ,v)) gv) ,ex)))))) (if (and (null? (cdadr (caddr th))) (= 0 (cadddr (caddr th)))) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 86ed90c300ac6..637d25e9d1271 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -2500,7 +2500,7 @@ ;; 3. variables assigned inside this scope-block that don't exist in outer ;; scopes ;; returns lambdas in the form (lambda (args...) (locals...) body) -(define (resolve-scopes- e env implicitglobals lam renames newlam) +(define (resolve-scopes- e env outerglobals implicitglobals lam renames newlam) (cond ((symbol? e) (let ((r (assq e renames))) (if r (cdr r) e))) ;; return the renaming for e, or e ((or (not (pair? e)) (quoted? e) (memq (car e) '(toplevel global))) e) @@ -2511,10 +2511,11 @@ (let* ((lv (lam:vars e)) (env (append lv env)) (body (resolve-scopes- (lam:body e) env - ;; don't propagate implicit globals - ;; issue #7234 + ;; don't propagate implicit or outer globals + '() '() e + ;; remove renames corresponding to local variables from the environment (filter (lambda (ren) (not (memq (car ren) lv))) renames) #t))) @@ -2522,17 +2523,16 @@ ((eq? (car e) 'scope-block) (let* ((blok (cadr e)) ;; body of scope-block expression (other-locals (if lam (caddr lam) '())) ;; locals that are explicitly part of containing lambda expression - (iglo (find-decls 'implicit-global blok)) ;; implicitly defined globals used in blok + (iglo (find-decls 'implicit-global blok)) ;; globals defined implicitly outside blok (glob (diff (find-global-decls blok) iglo)) ;; all globals declared in blok (vars-def (check-dups (find-local-def-decls blok) '())) (locals-declared (check-dups (find-local-decls blok) vars-def)) - (locals-implicit (diff (implicit-locals - blok - ;; being declared global prevents a variable - ;; assignment from introducing a local - (append env glob implicitglobals iglo) - (append glob iglo)) - vars-def)) + (locals-implicit (implicit-locals + blok + ;; being declared global prevents a variable + ;; assignment from introducing a local + (append env glob iglo outerglobals locals-declared vars-def) + (append glob iglo))) (vars (delete-duplicates (append! locals-declared locals-implicit))) (all-vars (append vars vars-def)) (need-rename? @@ -2551,26 +2551,22 @@ (renamed (map named-gensy need-rename)) (renamed-def (map named-gensy need-rename-def)) (new-env (append all-vars glob env)) ;; all variables declared in or outside blok - (new-iglo-table ;; initial list of implicit globals from outside blok which aren't part of the local vars - (let ((tab (table))) - (for-each (lambda (v) (if (not (memq v all-vars)) (put! tab v #t))) iglo) - (for-each (lambda (v) (if (not (memq v all-vars)) (put! tab v #t))) implicitglobals) - tab)) - (new-iglo (table.keys ;; compute list of all globals used implicitly in blok - (unbound-vars blok - new-env ;; list of everything else - new-iglo-table))) + ;; compute list of all globals used implicitly in blok (need renames) + (new-iglo (table.keys (unbound-vars blok + new-env ;; list of everything else + (table)))) ;; combine the list of new renamings with the inherited list (new-renames (append (map cons need-rename renamed) ;; map from definition name -> gensym name (map cons need-rename-def renamed-def) (map (lambda (g) (cons g `(outerref ,g))) new-iglo) (filter (lambda (ren) ;; old renames list, with anything in vars removed - (not (or (memq (car ren) all-vars) - (memq (car ren) iglo) - (memq (car ren) implicitglobals) - (memq (car ren) glob)))) + (let ((var (car ren))) + (not (or (memq var all-vars) ;; remove anything new + (memq var implicitglobals) ;; remove anything only added implicitly in the last scope block + (memq var glob))))) ;; remove anything that's now global renames))) - (body (resolve-scopes- blok new-env new-iglo lam new-renames #f)) + (new-oglo (append iglo outerglobals)) ;; list of all outer-globals from outside blok + (body (resolve-scopes- blok new-env new-oglo new-iglo lam new-renames #f)) (real-new-vars (append (diff vars need-rename) renamed)) (real-new-vars-def (append (diff vars-def need-rename-def) renamed-def))) (for-each (lambda (v) @@ -2590,18 +2586,18 @@ (error "module expression not at top level")) ((eq? (car e) 'break-block) `(break-block ,(cadr e) ;; ignore type symbol of break-block expression - ,(resolve-scopes- (caddr e) env implicitglobals lam renames #f))) ;; body of break-block expression + ,(resolve-scopes- (caddr e) env outerglobals implicitglobals lam renames #f))) ;; body of break-block expression ((eq? (car e) 'with-static-parameters) `(with-static-parameters ;; ignore list of sparams in break-block expression - ,(resolve-scopes- (cadr e) env implicitglobals lam renames #f) + ,(resolve-scopes- (cadr e) env outerglobals implicitglobals lam renames #f) ,@(cddr e))) ;; body of break-block expression (else (cons (car e) (map (lambda (x) - (resolve-scopes- x env implicitglobals lam renames #f)) + (resolve-scopes- x env outerglobals implicitglobals lam renames #f)) (cdr e)))))) -(define (resolve-scopes e) (resolve-scopes- e '() '() #f '() #f)) +(define (resolve-scopes e) (resolve-scopes- e '() '() '() #f '() #f)) ;; pass 3: analyze variables diff --git a/test/core.jl b/test/core.jl index b58b3c1169e3e..37afe6c68fb26 100644 --- a/test/core.jl +++ b/test/core.jl @@ -438,16 +438,27 @@ glotest() @test loc_x == 10 # issue #7234 +f7234_cnt = 0 begin glob_x2 = 24 - f7234_a() = (glob_x2 += 1) + function f7234_a() + global f7234_cnt += 1 + glob_x2 += 1 + global f7234_cnt += -10000 + end end @test_throws UndefVarError f7234_a() +@test f7234_cnt == 1 begin global glob_x2 = 24 - f7234_b() = (glob_x2 += 1) + function f7234_b() + global f7234_cnt += 1 + glob_x2 += 1 + global f7235_cnt += -10000 + end end @test_throws UndefVarError f7234_b() +@test f7234_cnt == 2 # existing globals can be inherited by non-function blocks for i = 1:2 glob_x2 += 1 @@ -486,16 +497,23 @@ end @test h19333() == 4 # let - new variables, including undefinedness +let_undef_cnt = 0 function let_undef() first = true for i = 1:2 - let x - if first; x=1; first=false; end - x+1 + let x # new x + if first # not defined on second pass + x = 1 + first = false + end + global let_undef_cnt += 1 + x + 1 + global let_undef_cnt += 23 end end end @test_throws UndefVarError let_undef() +@test let_undef_cnt == 25 # const implies local in a local scope block function const_implies_local() @@ -521,6 +539,56 @@ end @test a[2](10) == 12 @test a[3](10) == 13 +# issue #21900 +f21900_cnt = 0 +function f21900() + for i = 1:1 + x = 0 + end + global f21900_cnt += 1 + x + global f21900_cnt += -1000 + nothing +end +@test_throws UndefVarError f21900() +@test f21900_cnt == 1 + +@test_throws UndefVarError @eval begin + for i21900 = 1:10 + for j21900 = 1:10 + foo21900 = 10 + end + bar21900 = 0 + bar21900 = foo21900 + 1 + end +end +@test !isdefined(:foo21900) +@test !isdefined(:bar21900) +bar21900 = 0 +@test_throws UndefVarError @eval begin + for i21900 = 1:10 + for j21900 = 1:10 + foo21900 = 10 + end + bar21900 = -1 + bar21900 = foo21900 + 1 + end +end +@test bar21900 == -1 +@test !isdefined(:foo21900) +foo21900 = 0 +@test nothing === @eval begin + for i21900 = 1:10 + for j21900 = 1:10 + foo21900 = 10 + end + bar21900 = -1 + bar21900 = foo21900 + 1 + end +end +@test foo21900 == 10 +@test bar21900 == 11 + # ? syntax @test (true ? 1 : false ? 2 : 3) == 1 diff --git a/test/libgit2.jl b/test/libgit2.jl index f179825ae3fda..18d0137a63555 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -1628,6 +1628,7 @@ mktempdir() do dir loopback = ip"127.0.0.1" for hostname in hostnames + local addr try addr = getaddrinfo(hostname) catch From 53ea47e7e3f82812a81635fe9aadb774c43ca458 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Fri, 26 May 2017 02:03:40 +0200 Subject: [PATCH 0915/1534] check that reinterp on vector of tuples doesnt segfault --- test/inference.jl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/inference.jl b/test/inference.jl index bdcabb2ff7a72..50ef73ede078b 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -776,3 +776,15 @@ function break_21369() end end @test_throws ErrorException break_21369() # not TypeError + + +function segfaultfunction_20847{N, T}(A::Vector{NTuple{N, T}}) + B = reinterpret(T, A, (N, length(A))) + return nothing +end + +tuplevec_20847 = Tuple{Float64, Float64}[(0.0,0.0), (1.0,0.0)] + +for A in (1,) + @test segfaultfunction_20847(tuplevec_20847) == nothing +end From 03639b9be834e79880b4a6a3e61f95a4c677f8c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Fri, 26 May 2017 19:37:05 +0200 Subject: [PATCH 0916/1534] Fix complex exp2 and exp10 with boolean and irrational argument (#21874) Fix #21200. --- base/complex.jl | 6 ++++-- test/complex.jl | 11 ++++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/base/complex.jl b/base/complex.jl index 836253b1d65fa..9d6c49eb870ab 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -603,19 +603,21 @@ function ^(z::Complex{T}, p::Complex{T})::Complex{T} where T<:AbstractFloat end end -function exp2(z::Complex{T}) where T +function exp2(z::Complex{T}) where T<:AbstractFloat er = exp2(real(z)) theta = imag(z) * log(convert(T, 2)) s, c = sincos(theta) Complex(er * c, er * s) end +exp2(z::Complex) = exp2(float(z)) -function exp10(z::Complex{T}) where T +function exp10(z::Complex{T}) where T<:AbstractFloat er = exp10(real(z)) theta = imag(z) * log(convert(T, 10)) s, c = sincos(theta) Complex(er * c, er * s) end +exp10(z::Complex) = exp10(float(z)) function ^(z::T, p::T) where T<:Complex if isinteger(p) diff --git a/test/complex.jl b/test/complex.jl index 3aa4dd02d25b7..161222835a686 100644 --- a/test/complex.jl +++ b/test/complex.jl @@ -883,6 +883,7 @@ end @test exp2(1.0+0.0im) == 2.0+0.0im #wolframalpha @test exp2(1.0+3.0im) ≈ -0.9739888359315627962096198412+1.74681016354974281701922im + @test exp2(im) ≈ 0.7692389013639721 + 0.6389612763136348im end @testset "exp10" begin @@ -890,6 +891,7 @@ end @test exp10(1.0+0.0im) == 10.0+0.0im #wolframalpha @test exp10(1.0+2.0im) ≈ -1.0701348355877020772086517528518239460495529361-9.9425756941378968736161937190915602112878340717im + @test exp10(im) ≈ -0.6682015101903132 + 0.7439803369574931im end @testset "round and float, PR #8291" begin @@ -946,9 +948,12 @@ end @testset "Complex Irrationals, issue #21204" begin for x in (pi, e, catalan) # No need to test all of them - @test typeof(Complex(x, x)) == Complex{typeof(x)} - @test exp(complex(x, x)) ≈ exp(x) * cis(x) - @test log1p(complex(x, x)) ≈ log(1 + complex(x, x)) + z = Complex(x, x) + @test typeof(z) == Complex{typeof(x)} + @test exp(z) ≈ exp(x) * cis(x) + @test log1p(z) ≈ log(1 + z) + @test exp2(z) ≈ exp(z * log(2)) + @test exp10(z) ≈ exp(z * log(10)) end end From b1b01b56a28b0a7d6bcd0d8a4b00aba466fc52e6 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Fri, 26 May 2017 21:02:10 +0200 Subject: [PATCH 0917/1534] improve docs for mktempdir (#22078) --- base/file.jl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/base/file.jl b/base/file.jl index b344e264b79ec..b9e85066eaaaa 100644 --- a/base/file.jl +++ b/base/file.jl @@ -359,6 +359,7 @@ mktemp(parent) mktempdir(parent=tempdir()) Create a temporary directory in the `parent` directory and return its path. +If `parent` does not exist, throw an error. """ mktempdir(parent) @@ -366,7 +367,8 @@ mktempdir(parent) """ mktemp(f::Function, parent=tempdir()) -Apply the function `f` to the result of `mktemp(parent)` and remove the temporary file upon completion. +Apply the function `f` to the result of [`mktemp(parent)`](@ref) and remove the +temporary file upon completion. """ function mktemp(fn::Function, parent=tempdir()) (tmp_path, tmp_io) = mktemp(parent) @@ -381,8 +383,8 @@ end """ mktempdir(f::Function, parent=tempdir()) -Apply the function `f` to the result of `mktempdir(parent)` and remove the temporary -directory upon completion. +Apply the function `f` to the result of [`mktempdir(parent)`](@ref) and remove the +temporary directory upon completion. """ function mktempdir(fn::Function, parent=tempdir()) tmpdir = mktempdir(parent) From 6071f1a02e995132a2ca67d0ca0f3bacc09f8964 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Fri, 26 May 2017 21:33:06 +0200 Subject: [PATCH 0918/1534] test 0 dim array constructor (#22080) --- test/arrayops.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/arrayops.jl b/test/arrayops.jl index 8b5e6d559af9f..480ebca4d89c1 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -2146,3 +2146,6 @@ end Base.:*(a::T11053, b::Real) = T11053(a.a*b) Base.:(==)(a::T11053, b::T11053) = a.a == b.a @test [T11053(1)] * 5 == [T11053(1)] .* 5 == [T11053(5.0)] + +#15907 +@test typeof(Array{Int,0}()) == Array{Int,0} From 64cb7e087c795474a8beba3352affa78fae9a6cd Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Fri, 26 May 2017 22:44:27 +0200 Subject: [PATCH 0919/1534] add test for foldr on one element range (#22085) --- test/reduce.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/reduce.jl b/test/reduce.jl index 74a4c72eee030..cf89d564262f8 100644 --- a/test/reduce.jl +++ b/test/reduce.jl @@ -362,3 +362,6 @@ end test18695(r) = sum( t^2 for t in r ) @test @inferred(test18695([1.0,2.0,3.0,4.0])) == 30.0 @test_throws ArgumentError test18695(Any[]) + +# issue #21107 +@test foldr(-,2:2) == 2 From 8c19eec243b6fc9f816f48b3c8061ea33279ad3a Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Fri, 26 May 2017 23:34:19 +0200 Subject: [PATCH 0920/1534] add test for code that used to crash, #17003 (#22081) --- test/inference.jl | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/inference.jl b/test/inference.jl index b1a4a3b55e358..a1d8501efc203 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -778,6 +778,25 @@ function break_21369() end @test_throws ErrorException break_21369() # not TypeError +# issue #17003 +abstract type AArray_17003{T,N} end +AVector_17003{T} = AArray_17003{T,1} + +struct Nable_17003{T} +end + +struct NArray_17003{T,N} <: AArray_17003{Nable_17003{T},N} +end + +(::Type{NArray_17003}){T,N}(::Array{T,N}) = NArray_17003{T,N}() + +gl_17003 = [1, 2, 3] + +f2_17003(item::AVector_17003) = nothing +f2_17003(::Any) = f2_17003(NArray_17003(gl_17003)) + +@test f2_17003(1) == nothing + # issue #20847 function segfaultfunction_20847{N, T}(A::Vector{NTuple{N, T}}) B = reinterpret(T, A, (N, length(A))) From c3fb8e77cc7747178c1c82551da4f045e8f55921 Mon Sep 17 00:00:00 2001 From: Douglas Bates Date: Fri, 26 May 2017 16:37:20 -0500 Subject: [PATCH 0921/1534] Remove redundant calls to size (#22086) The values of `p` and `q` are not used in these two methods --- base/linalg/matmul.jl | 2 -- 1 file changed, 2 deletions(-) diff --git a/base/linalg/matmul.jl b/base/linalg/matmul.jl index 94a6cb0b7e0a8..0fce02cbb699f 100644 --- a/base/linalg/matmul.jl +++ b/base/linalg/matmul.jl @@ -7,7 +7,6 @@ matprod(x, y) = x*y + x*y # multiply by diagonal matrix as vector function scale!(C::AbstractMatrix, A::AbstractMatrix, b::AbstractVector) m, n = size(A) - p, q = size(C) if size(A) != size(C) throw(DimensionMismatch("size of A, $(size(A)), does not match size of C, $(size(C))")) end @@ -25,7 +24,6 @@ end function scale!(C::AbstractMatrix, b::AbstractVector, A::AbstractMatrix) m, n = size(A) - p, q = size(C) if size(A) != size(C) throw(DimensionMismatch("size of A, $(size(A)), does not match size of C, $(size(C))")) end From 85907b0094febaf35c3a97f4d4006c1d7dd50254 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Sat, 27 May 2017 01:28:11 +0200 Subject: [PATCH 0922/1534] add test for code_typed on generated function (#22084) --- test/inference.jl | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/inference.jl b/test/inference.jl index a1d8501efc203..c03636fb26198 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -819,3 +819,12 @@ let T = Tuple{Tuple{Int64, Void}, @test Core.Inference.limit_type_depth(T, 1) >: T @test Core.Inference.limit_type_depth(T, 2) >: T end + +# Issue #20902, check that this doesn't error. +@generated function test_20902() + quote + 10 + 11 + end +end +@test length(code_typed(test_20902, (), optimize = false)) == 1 +@test length(code_typed(test_20902, (), optimize = false)) == 1 From 7a05f686a27d9e070efb523b51420f90d9310e43 Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Sat, 27 May 2017 02:51:51 -0500 Subject: [PATCH 0923/1534] Clarify stored and nonzero values for sparse arrays (#22091) Closes #13427. --- doc/src/manual/arrays.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/src/manual/arrays.md b/doc/src/manual/arrays.md index e9d75f8644072..53aae9054dd26 100644 --- a/doc/src/manual/arrays.md +++ b/doc/src/manual/arrays.md @@ -712,7 +712,7 @@ gains in either time or space when compared to performing the same operations on ### Compressed Sparse Column (CSC) Storage In Julia, sparse matrices are stored in the [Compressed Sparse Column (CSC) format](https://en.wikipedia.org/wiki/Sparse_matrix#Compressed_sparse_column_.28CSC_or_CCS.29). -Julia sparse matrices have the type `SparseMatrixCSC{Tv,Ti}`, where `Tv` is the type of the nonzero +Julia sparse matrices have the type `SparseMatrixCSC{Tv,Ti}`, where `Tv` is the type of the stored values, and `Ti` is the integer type for storing column pointers and row indices.: ```julia @@ -720,8 +720,8 @@ struct SparseMatrixCSC{Tv,Ti<:Integer} <: AbstractSparseMatrix{Tv,Ti} m::Int # Number of rows n::Int # Number of columns colptr::Vector{Ti} # Column i is in colptr[i]:(colptr[i+1]-1) - rowval::Vector{Ti} # Row values of nonzeros - nzval::Vector{Tv} # Nonzero values + rowval::Vector{Ti} # Row indices of stored values + nzval::Vector{Tv} # Stored values, typically nonzeros end ``` @@ -765,7 +765,7 @@ julia> speye(3,5) ``` The [`sparse()`](@ref) function is often a handy way to construct sparse matrices. It takes as -its input a vector `I` of row indices, a vector `J` of column indices, and a vector `V` of nonzero +its input a vector `I` of row indices, a vector `J` of column indices, and a vector `V` of stored values. `sparse(I,J,V)` constructs a sparse matrix such that `S[I[k], J[k]] = V[k]`. ```jldoctest sparse_function From 71d14aeaec85f7fc5c7c356378a361dd37eeeeaa Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Sat, 27 May 2017 08:28:13 -0500 Subject: [PATCH 0924/1534] Test inferability of xcorr with views (#22093) Fix #17351. --- test/subarray.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/subarray.jl b/test/subarray.jl index fb2d8d8300017..45d31b6fe3ecd 100644 --- a/test/subarray.jl +++ b/test/subarray.jl @@ -555,3 +555,11 @@ let @test Base.IndexStyle(view(a, :, :)) == Base.IndexLinear() @test isbits(view(a, :, :)) end + +# Issue #17351 +let + x = rand(10) + u = rand(10, 3) + su = view(u, :, 1) + @test size(@inferred(xcorr(x, su))) == (19,) +end From f67f58e525f7b11517e6f77135a767e3a38f2f4d Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Sun, 28 May 2017 00:47:16 +0200 Subject: [PATCH 0925/1534] add AbstractArray to stdlib (#22059) * add AbstractArray to stdlib and moved constructors to the top * add some references --- doc/src/devdocs/offset-arrays.md | 2 +- doc/src/devdocs/subarrays.md | 2 +- doc/src/devdocs/types.md | 2 +- doc/src/manual/arrays.md | 2 +- doc/src/manual/interfaces.md | 2 +- doc/src/stdlib/arrays.md | 43 ++++++++++++++++---------------- doc/src/stdlib/collections.md | 6 ++--- 7 files changed, 30 insertions(+), 29 deletions(-) diff --git a/doc/src/devdocs/offset-arrays.md b/doc/src/devdocs/offset-arrays.md index 443473d16a61d..9951c72231de9 100644 --- a/doc/src/devdocs/offset-arrays.md +++ b/doc/src/devdocs/offset-arrays.md @@ -59,7 +59,7 @@ the ranges may not start at 1. If you just want the range for a particular dime is `indices(A, d)`. Base implements a custom range type, `OneTo`, where `OneTo(n)` means the same thing as `1:n` but -in a form that guarantees (via the type system) that the lower index is 1. For any new `AbstractArray` +in a form that guarantees (via the type system) that the lower index is 1. For any new [`AbstractArray`](@ref) type, this is the default returned by `indices`, and it indicates that this array type uses "conventional" 1-based indexing. Note that if you don't want to be bothered supporting arrays with non-1 indexing, you can add the following line: diff --git a/doc/src/devdocs/subarrays.md b/doc/src/devdocs/subarrays.md index 469907cd8fea1..16a11c39cf7e3 100644 --- a/doc/src/devdocs/subarrays.md +++ b/doc/src/devdocs/subarrays.md @@ -1,6 +1,6 @@ # SubArrays -Julia's `SubArray` type is a container encoding a "view" of a parent `AbstractArray`. This page +Julia's `SubArray` type is a container encoding a "view" of a parent [`AbstractArray`](@ref). This page documents some of the design principles and implementation of `SubArray`s. ## Indexing: cartesian vs. linear indexing diff --git a/doc/src/devdocs/types.md b/doc/src/devdocs/types.md index 63a274c61f74b..44a1a7480e4c5 100644 --- a/doc/src/devdocs/types.md +++ b/doc/src/devdocs/types.md @@ -433,7 +433,7 @@ When we are done evaluating the body of a `UnionAll` type whose variable is diag we look at the final values of the bounds. Since the variable must be concrete, a contradiction occurs if its lower bound could not be a subtype of a concrete type. -For example, an abstract type like `AbstractArray` cannot be a subtype of a concrete +For example, an abstract type like [`AbstractArray`](@ref) cannot be a subtype of a concrete type, but a concrete type like `Int` can be, and the empty type `Bottom` can be as well. If a lower bound fails this test the algorithm stops with the answer `false`. diff --git a/doc/src/manual/arrays.md b/doc/src/manual/arrays.md index 53aae9054dd26..757ac1f384a77 100644 --- a/doc/src/manual/arrays.md +++ b/doc/src/manual/arrays.md @@ -510,7 +510,7 @@ iterate over any array type. ### Array traits -If you write a custom `AbstractArray` type, you can specify that it has fast linear indexing using +If you write a custom [`AbstractArray`](@ref) type, you can specify that it has fast linear indexing using ```julia Base.IndexStyle(::Type{<:MyArray}) = IndexLinear() diff --git a/doc/src/manual/interfaces.md b/doc/src/manual/interfaces.md index fd7b5cba85501..91ae4fbe21e57 100644 --- a/doc/src/manual/interfaces.md +++ b/doc/src/manual/interfaces.md @@ -187,7 +187,7 @@ julia> Squares(10)[[3,4.,5]] While this is starting to support more of the [indexing operations supported by some of the builtin types](@ref man-array-indexing), there's still quite a number of behaviors missing. This `Squares` sequence is starting to look more and more like a vector as we've added behaviors to it. Instead of defining all these behaviors -ourselves, we can officially define it as a subtype of an `AbstractArray`. +ourselves, we can officially define it as a subtype of an [`AbstractArray`](@ref). ## [Abstract Arrays](@id man-interface-array) diff --git a/doc/src/stdlib/arrays.md b/doc/src/stdlib/arrays.md index cb3468061dbc4..2fc43f52bee53 100644 --- a/doc/src/stdlib/arrays.md +++ b/doc/src/stdlib/arrays.md @@ -1,28 +1,9 @@ # [Arrays](@id lib-arrays) -## Basic functions - -```@docs -Base.ndims -Base.size -Base.indices(::Any) -Base.indices(::AbstractArray, ::Any) -Base.length(::AbstractArray) -Base.eachindex -Base.linearindices -Base.IndexStyle -Base.countnz -Base.conj! -Base.stride -Base.strides -Base.ind2sub -Base.sub2ind -Base.LinAlg.checksquare -``` - -## Constructors +## Constructors and Types ```@docs +Core.AbstractArray Core.Array Base.getindex(::Type, ::Any...) Base.zeros @@ -41,6 +22,26 @@ Base.Random.randsubseq Base.Random.randsubseq! ``` +## Basic functions + +```@docs +Base.ndims +Base.size +Base.indices(::Any) +Base.indices(::AbstractArray, ::Any) +Base.length(::AbstractArray) +Base.eachindex +Base.linearindices +Base.IndexStyle +Base.countnz +Base.conj! +Base.stride +Base.strides +Base.ind2sub +Base.sub2ind +Base.LinAlg.checksquare +``` + ## Broadcast and vectorization See also the [dot syntax for vectorizing functions](@ref man-vectorized); diff --git a/doc/src/stdlib/collections.md b/doc/src/stdlib/collections.md index 29d8c38f3b1a8..1ab225a854208 100644 --- a/doc/src/stdlib/collections.md +++ b/doc/src/stdlib/collections.md @@ -39,7 +39,7 @@ Fully implemented by: * `UnitRange` * `Tuple` * `Number` - * `AbstractArray` + * [`AbstractArray`](@ref) * [`IntSet`](@ref) * [`ObjectIdDict`](@ref) * [`Dict`](@ref) @@ -63,7 +63,7 @@ Fully implemented by: * `UnitRange` * `Tuple` * `Number` - * `AbstractArray` + * [`AbstractArray`](@ref) * [`IntSet`](@ref) * [`ObjectIdDict`](@ref) * [`Dict`](@ref) @@ -145,7 +145,7 @@ Fully implemented by: * [`Array`](@ref) * [`BitArray`](@ref) - * `AbstractArray` + * [`AbstractArray`](@ref) * `SubArray` * [`ObjectIdDict`](@ref) * [`Dict`](@ref) From 82e96382251a1e163860df03c846acec86d07c36 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Sun, 28 May 2017 03:51:40 +0200 Subject: [PATCH 0926/1534] add test for #19805, cfunction segfault (#22079) --- test/ccall.jl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/ccall.jl b/test/ccall.jl index ad97132813279..204a40c6080f3 100644 --- a/test/ccall.jl +++ b/test/ccall.jl @@ -1265,3 +1265,15 @@ end (::CallableSingleton)(x, y) = x + y @test ccall(cfunction(CallableSingleton(), Int, Tuple{Int,Int}), Int, (Int, Int), 1, 2) === 3 + +# 19805 +mutable struct callinfos_19805{FUNC_FT<:Function} + f :: FUNC_FT +end + +evalf_callback_19805{FUNC_FT}(ci::callinfos_19805{FUNC_FT}) = ci.f(0.5)::Float64 + +evalf_callback_c_19805{FUNC_FT}(ci::callinfos_19805{FUNC_FT}) = cfunction( + evalf_callback_19805, Float64, (callinfos_19805{FUNC_FT},)) + +@test_throws ErrorException evalf_callback_c_19805( callinfos_19805(sin) ) From f5ed68fbad3ffcd4ef9710dff21e28d623bd9d8b Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Sun, 28 May 2017 14:41:59 +0200 Subject: [PATCH 0927/1534] Document number types (#22067) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * document π, e, γ and φ * add type-documentation for number types - replace the uninformative list in doc/src/stdlib/numbers.md with these new docstrings - move constructor docstring for BigInt from helpdb/Base.jl to base/gmp.jl - add a doctest for BigInt constructor * add supertypes to number type docs * move irrational to concrete types --- base/complex.jl | 8 ++++ base/docs/helpdb/Base.jl | 94 +++++++++++++++++++++++++++++++++------ base/gmp.jl | 24 ++++++++++ base/irrationals.jl | 13 ++++-- base/mpfr.jl | 39 +++++++++------- base/rational.jl | 5 +++ doc/src/stdlib/numbers.md | 58 +++++++++++++++--------- 7 files changed, 187 insertions(+), 54 deletions(-) diff --git a/base/complex.jl b/base/complex.jl index 9d6c49eb870ab..237918f122f11 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -1,5 +1,13 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license +""" + Complex{T<:Real} <: Number + +Complex number type with real and imaginary part of type `T`. + +`Complex32`, `Complex64` and `Complex128` are aliases for +`Complex{Float16}`, `Complex{Float32}` and `Complex{Float64}` respectively. +""" struct Complex{T<:Real} <: Number re::T im::T diff --git a/base/docs/helpdb/Base.jl b/base/docs/helpdb/Base.jl index ac2f43e33778e..d0e408c4cff3e 100644 --- a/base/docs/helpdb/Base.jl +++ b/base/docs/helpdb/Base.jl @@ -229,7 +229,7 @@ julia> Float32(1/3, RoundUp) See [`RoundingMode`](@ref) for available rounding modes. """ -Float32 +Float32(x) """ Mmap.mmap(io::Union{IOStream,AbstractString,Mmap.AnonymousMmap}[, type::Type{Array{T,N}}, dims, offset]; grow::Bool=true, shared::Bool=true) @@ -814,7 +814,7 @@ julia> Float64(pi, RoundUp) See [`RoundingMode`](@ref) for available rounding modes. """ -Float64 +Float64(x) """ union(s1,s2...) @@ -1431,18 +1431,6 @@ recurses infinitely. """ StackOverflowError -""" - BigInt(x) - -Create an arbitrary precision integer. `x` may be an `Int` (or anything that can be -converted to an `Int`). The usual mathematical operators are defined for this type, and -results are promoted to a `BigInt`. - -Instances can be constructed from strings via [`parse`](@ref), or using the `big` -string literal. -""" -BigInt - """ ==(x, y) @@ -2414,3 +2402,81 @@ seekend Integer division was attempted with a denominator value of 0. """ DivideError + +""" + Number + +Abstract supertype for all number types. +""" +Number + +""" + Real <: Number + +Abstract supertype for all real numbers. +""" +Real + +""" + AbstractFloat <: Real + +Abstract supertype for all floating point numbers. +""" +AbstractFloat + +""" + Integer <: Real + +Abstract supertype for all integers. +""" +Integer + +""" + Signed <: Integer + +Abstract supertype for all signed integers. +""" +Signed + +""" + Unsigned <: Integer + +Abstract supertype for all unsigned integers. +""" +Unsigned + +""" + Bool <: Integer + +Boolean type. +""" +Bool + +for bit in (16, 32, 64) + @eval begin + """ + Float$($bit) <: AbstractFloat + + $($bit)-bit floating point number type. + """ + $(Symbol("Float", bit)) + end +end + +for bit in (8, 16, 32, 64, 128) + @eval begin + """ + Int$($bit) <: Signed + + $($bit)-bit signed integer type. + """ + $(Symbol("Int", bit)) + + """ + UInt$($bit) <: Unsigned + + $($bit)-bit unsigned integer type. + """ + $(Symbol("UInt", bit)) + end +end diff --git a/base/gmp.jl b/base/gmp.jl index 2e7c667b07d3b..b78132e4b4856 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -37,7 +37,11 @@ else error("GMP: cannot determine the type mp_limb_t (__gmp_bits_per_limb == $GMP_BITS_PER_LIMB)") end +""" + BigInt <: Integer +Arbitrary precision integer type. +""" mutable struct BigInt <: Integer alloc::Cint size::Cint @@ -50,6 +54,26 @@ mutable struct BigInt <: Integer end end +""" + BigInt(x) + +Create an arbitrary precision integer. `x` may be an `Int` (or anything that can be +converted to an `Int`). The usual mathematical operators are defined for this type, and +results are promoted to a `BigInt`. + +Instances can be constructed from strings via [`parse`](@ref), or using the `big` +string literal. + +```jldoctest +julia> parse(BigInt, "42") +42 + +julia> big"313" +313 +``` +""" +BigInt(x) + function __init__() try if gmp_version().major != GMP_VERSION.major || gmp_bits_per_limb() != GMP_BITS_PER_LIMB diff --git a/base/irrationals.jl b/base/irrationals.jl index d2d76abbc0df0..91d56999474a2 100644 --- a/base/irrationals.jl +++ b/base/irrationals.jl @@ -2,6 +2,11 @@ ## general machinery for irrational mathematical constants +""" + Irrational <: Real + +Irrational number type. +""" struct Irrational{sym} <: Real end show(io::IO, x::Irrational{sym}) where {sym} = print(io, "$sym = $(string(float(x))[1:15])...") @@ -156,7 +161,7 @@ julia> pi π = 3.1415926535897... ``` """ -const pi = π +π, const pi = π """ e @@ -169,7 +174,7 @@ julia> e e = 2.7182818284590... ``` """ -const eu = e +e, const eu = e """ γ @@ -182,7 +187,7 @@ julia> eulergamma γ = 0.5772156649015... ``` """ -const eulergamma = γ +γ, const eulergamma = γ """ φ @@ -195,7 +200,7 @@ julia> golden φ = 1.6180339887498... ``` """ -const golden = φ +φ, const golden = φ """ catalan diff --git a/base/mpfr.jl b/base/mpfr.jl index 4855ca4909678..4f04480babb69 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -43,23 +43,9 @@ const DEFAULT_PRECISION = [256] # Basic type and initialization definitions """ - BigFloat(x) - -Create an arbitrary precision floating point number. `x` may be an `Integer`, a `Float64` or -a `BigInt`. The usual mathematical operators are defined for this type, and results are -promoted to a `BigFloat`. - -Note that because decimal literals are converted to floating point numbers when parsed, -`BigFloat(2.1)` may not yield what you expect. You may instead prefer to initialize -constants from strings via [`parse`](@ref), or using the `big` string literal. + BigFloat <: AbstractFloat -```jldoctest -julia> BigFloat(2.1) -2.100000000000000088817841970012523233890533447265625000000000000000000000000000 - -julia> big"2.1" -2.099999999999999999999999999999999999999999999999999999999999999999999999999986 -``` +Arbitrary precision floating point number type. """ mutable struct BigFloat <: AbstractFloat prec::Clong @@ -81,6 +67,27 @@ mutable struct BigFloat <: AbstractFloat end end +""" + BigFloat(x) + +Create an arbitrary precision floating point number. `x` may be an `Integer`, a `Float64` or +a `BigInt`. The usual mathematical operators are defined for this type, and results are +promoted to a `BigFloat`. + +Note that because decimal literals are converted to floating point numbers when parsed, +`BigFloat(2.1)` may not yield what you expect. You may instead prefer to initialize +constants from strings via [`parse`](@ref), or using the `big` string literal. + +```jldoctest +julia> BigFloat(2.1) +2.100000000000000088817841970012523233890533447265625000000000000000000000000000 + +julia> big"2.1" +2.099999999999999999999999999999999999999999999999999999999999999999999999999986 +``` +""" +BigFloat(x) + widen(::Type{Float64}) = BigFloat widen(::Type{BigFloat}) = BigFloat diff --git a/base/rational.jl b/base/rational.jl index 611d7ca5e3252..1fe97049be83f 100644 --- a/base/rational.jl +++ b/base/rational.jl @@ -1,5 +1,10 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license +""" + Rational{T<:Integer} <: Real + +Rational number type, with numerator and denominator of type `T`. +""" struct Rational{T<:Integer} <: Real num::T den::T diff --git a/doc/src/stdlib/numbers.md b/doc/src/stdlib/numbers.md index 36ee7e5634d2f..df3a4f63ce637 100644 --- a/doc/src/stdlib/numbers.md +++ b/doc/src/stdlib/numbers.md @@ -2,22 +2,40 @@ ## Standard Numeric Types - * `Bool` - * `Int8` - * `UInt8` - * `Int16` - * `UInt16` - * `Int32` - * `UInt32` - * `Int64` - * `UInt64` - * `Int128` - * `UInt128` - * `Float16` - * `Float32` - * `Float64` - * `Complex64` - * `Complex128` +### Abstract number types + +```@docs +Core.Number +Core.Real +Core.AbstractFloat +Core.Integer +Core.Signed +Core.Unsigned +``` + +### Concrete number types + +```@docs +Core.Float16 +Core.Float32 +Core.Float64 +Base.BigFloat +Core.Bool +Core.Int8 +Core.UInt8 +Core.Int16 +Core.UInt16 +Core.Int32 +Core.UInt32 +Core.Int64 +Core.UInt64 +Core.Int128 +Core.UInt128 +Base.BigInt +Base.Complex +Base.Rational +Base.Irrational +``` ## Data Formats @@ -73,10 +91,10 @@ Base.nextfloat Base.prevfloat Base.isinteger Base.isreal -Core.Float32 -Core.Float64 -Base.GMP.BigInt -Base.MPFR.BigFloat +Core.Float32(::Any) +Core.Float64(::Any) +Base.GMP.BigInt(::Any) +Base.MPFR.BigFloat(::Any) Base.Rounding.rounding Base.Rounding.setrounding(::Type, ::Any) Base.Rounding.setrounding(::Function, ::Type, ::RoundingMode) From 6b0d54e6cb4272c609489a05bf8404e89befab7e Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Sun, 28 May 2017 14:44:10 +0200 Subject: [PATCH 0928/1534] undeprecate real and imag for sparse matrices (#22090) make sure aliasing is the same as for AbstracArrays for SparseArray{<:Real} add tests for this add shortcut for conj(SparseArray{<:Complex} which is faster than broadcasting --- base/deprecated.jl | 2 +- base/sparse/sparsematrix.jl | 4 ++++ base/sparse/sparsevector.jl | 5 ++--- test/sparse/sparse.jl | 25 +++++++++++++++++-------- test/sparse/sparsevector.jl | 4 +++- 5 files changed, 27 insertions(+), 13 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index e882c3be8481a..5c844f33d238e 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -200,7 +200,7 @@ end # Deprecate vectorized unary functions over sparse matrices in favor of compact broadcast syntax (#17265). for f in (:sin, :sinh, :sind, :asin, :asinh, :asind, :tan, :tanh, :tand, :atan, :atanh, :atand, - :sinpi, :cosc, :ceil, :floor, :trunc, :round, :real, :imag, + :sinpi, :cosc, :ceil, :floor, :trunc, :round, :log1p, :expm1, :abs, :abs2, :log, :log2, :log10, :exp, :exp2, :exp10, :sinc, :cospi, :cos, :cosh, :cosd, :acos, :acosd, diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl index cee5b35516408..58e363a2e299d 100644 --- a/base/sparse/sparsematrix.jl +++ b/base/sparse/sparsematrix.jl @@ -1447,6 +1447,10 @@ sparse(S::UniformScaling, m::Integer, n::Integer=m) = speye_scaled(S.λ, m, n) conj!(A::SparseMatrixCSC) = (@inbounds broadcast!(conj, A.nzval, A.nzval); A) (-)(A::SparseMatrixCSC) = SparseMatrixCSC(A.m, A.n, copy(A.colptr), copy(A.rowval), map(-, A.nzval)) +# the rest of real, conj, imag are handled correctly via AbstractArray methods +conj(A::SparseMatrixCSC{<:Complex}) = + SparseMatrixCSC(A.m, A.n, copy(A.colptr), copy(A.rowval), conj(A.nzval)) +imag(A::SparseMatrixCSC{Tv,Ti}) where {Tv<:Real,Ti} = spzeros(Tv, Ti, A.m, A.n) ## Binary arithmetic and boolean operators (+)(A::SparseMatrixCSC, B::SparseMatrixCSC) = map(+, A, B) diff --git a/base/sparse/sparsevector.jl b/base/sparse/sparsevector.jl index 7f915492a2fd3..dd9e19d9bc729 100644 --- a/base/sparse/sparsevector.jl +++ b/base/sparse/sparsevector.jl @@ -985,7 +985,6 @@ hvcat(rows::Tuple{Vararg{Int}}, xs::_TypedDenseConcatGroup{T}...) where {T} = Ba ### Unary Map # zero-preserving functions (z->z, nz->nz) -conj(x::SparseVector) = SparseVector(length(x), copy(nonzeroinds(x)), conj(nonzeros(x))) -(x::SparseVector) = SparseVector(length(x), copy(nonzeroinds(x)), -(nonzeros(x))) # functions f, such that @@ -1019,9 +1018,9 @@ macro unarymap_nz2z_z2z(op, TF) end) end -real(x::AbstractSparseVector{<:Real}) = x +# the rest of real, conj, imag are handled correctly via AbstractArray methods @unarymap_nz2z_z2z real Complex - +conj(x::SparseVector{<:Complex}) = SparseVector(length(x), copy(nonzeroinds(x)), conj(nonzeros(x))) imag(x::AbstractSparseVector{Tv,Ti}) where {Tv<:Real,Ti<:Integer} = SparseVector(length(x), Ti[], Tv[]) @unarymap_nz2z_z2z imag Complex diff --git a/test/sparse/sparse.jl b/test/sparse/sparse.jl index 43a0c4c346577..e22c0b7fe1d0d 100644 --- a/test/sparse/sparse.jl +++ b/test/sparse/sparse.jl @@ -538,10 +538,12 @@ end @test tan.(Afull) == Array(tan.(A)) # should be redundant with sin test @test ceil.(Afull) == Array(ceil.(A)) @test floor.(Afull) == Array(floor.(A)) # should be redundant with ceil test - @test real.(Afull) == Array(real.(A)) - @test imag.(Afull) == Array(imag.(A)) - @test real.(Cfull) == Array(real.(C)) - @test imag.(Cfull) == Array(imag.(C)) + @test real.(Afull) == Array(real.(A)) == Array(real(A)) + @test imag.(Afull) == Array(imag.(A)) == Array(imag(A)) + @test conj.(Afull) == Array(conj.(A)) == Array(conj(A)) + @test real.(Cfull) == Array(real.(C)) == Array(real(C)) + @test imag.(Cfull) == Array(imag.(C)) == Array(imag(C)) + @test conj.(Cfull) == Array(conj.(C)) == Array(conj(C)) # Test representatives of [unary functions that map zeros to zeros and nonzeros to nonzeros] @test expm1.(Afull) == Array(expm1.(A)) @test abs.(Afull) == Array(abs.(A)) @@ -559,12 +561,19 @@ end I = rand(T[1:100;], 2, 2) D = R + I*im S = sparse(D) - @test R == real.(S) - @test I == imag.(S) - @test real.(sparse(R)) == R - @test nnz(imag.(sparse(R))) == 0 + spR = sparse(R) + + @test R == real.(S) == real(S) + @test I == imag.(S) == imag(S) + @test conj(full(S)) == conj.(S) == conj(S) + @test real.(spR) == R + @test nnz(imag.(spR)) == nnz(imag(spR)) == 0 @test abs.(S) == abs.(D) @test abs2.(S) == abs2.(D) + + # test aliasing of real and conj of real valued matrix + @test real(spR) === spR + @test conj(spR) === spR end end diff --git a/test/sparse/sparsevector.jl b/test/sparse/sparsevector.jl index 543b7668160fd..77024341a19ba 100644 --- a/test/sparse/sparsevector.jl +++ b/test/sparse/sparsevector.jl @@ -637,14 +637,16 @@ let x = spv_x1, x2 = spv_x2 @test exact_equal(complex.(x2, x), SparseVector(8, [1,2,5,6,7], [3.25+0.0im, 4.0+1.25im, -0.75im, -5.5+3.5im, -6.0+0.0im])) - # real & imag + # real, imag and conj @test real(x) === x @test exact_equal(imag(x), spzeros(Float64, length(x))) + @test conj(x) === x xcp = complex.(x, x2) @test exact_equal(real(xcp), x) @test exact_equal(imag(xcp), x2) + @test exact_equal(conj(xcp), complex.(x, -x2)) end ### Zero-preserving math functions: sparse -> sparse From efca045215eba9bd043f8989d5690d8eef303905 Mon Sep 17 00:00:00 2001 From: Mus M Date: Sun, 28 May 2017 14:27:46 -0400 Subject: [PATCH 0929/1534] Use the pure Julia exp function for fastmath (#21948) --- base/fastmath.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/fastmath.jl b/base/fastmath.jl index 6eca987d0703b..a66762c2eb6bb 100644 --- a/base/fastmath.jl +++ b/base/fastmath.jl @@ -251,7 +251,7 @@ sqrt_fast(x::FloatTypes) = sqrt_llvm_fast(x) const libm = Base.libm_name for f in (:acos, :acosh, :asin, :asinh, :atan, :atanh, :cbrt, :cos, - :cosh, :exp2, :exp, :expm1, :lgamma, :log10, :log1p, :log2, + :cosh, :exp2, :expm1, :lgamma, :log10, :log1p, :log2, :log, :sin, :sinh, :tan, :tanh) f_fast = fast_op[f] @eval begin From 06521f178115539b7ae43d702a975206bf2b6d5c Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Sun, 28 May 2017 22:58:04 +0200 Subject: [PATCH 0930/1534] printf.jl: add missing import of GMP (#22104) --- base/printf.jl | 2 +- test/printf.jl | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/base/printf.jl b/base/printf.jl index 48ead94958f59..f1f4515d3f798 100644 --- a/base/printf.jl +++ b/base/printf.jl @@ -1,7 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license module Printf -using Base.Grisu +using Base: Grisu, GMP export @printf, @sprintf ### printf formatter generation ### diff --git a/test/printf.jl b/test/printf.jl index 4a50982aa368b..89d0a7ee7ddf1 100644 --- a/test/printf.jl +++ b/test/printf.jl @@ -25,8 +25,9 @@ for (fmt, val) in (("%i", "42"), ("%f", "42.000000"), ("%g", "42")), num in (UInt16(42), UInt32(42), UInt64(42), UInt128(42), - Int16(42), Int32(42), Int64(42), Int128(42)) + Int16(42), Int32(42), Int64(42), Int128(42), big"42") #big"42" causes stack overflow on %a ; gh #14409 + num isa BigInt && fmt in ["%a", "%#o", "%g"] && continue @test @eval(@sprintf($fmt, $num) == $val) end From 96e430199b7104134e79a0daffe6c97caca84c90 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Mon, 29 May 2017 06:59:42 +0200 Subject: [PATCH 0931/1534] Reference all the numbers (#22107) * references for Rational * references for Complex * references for Number * references to Real * references for AbstractFloat * references for Integer * references for Signed * references for Unsigned * references to Bool * references for Float16 * references for Float32 * references for Float64 * references for Int8 * references for UInt8 * references for Int16 * references for UInt16 * references for Int32 * references for UInt32 * references for Int64 * references for UInt64 * references for Int128 * references for UInt128 * references for BigInt * references for BigFloat --- base/Enums.jl | 5 +- base/abstractarray.jl | 2 +- base/array.jl | 4 +- base/c.jl | 2 +- base/ctypes.jl | 22 +-- base/dates/accessors.jl | 17 +-- base/dates/adjusters.jl | 8 +- base/dates/conversions.jl | 4 +- base/dates/periods.jl | 2 +- base/dates/query.jl | 2 +- base/dates/rounding.jl | 4 +- base/dates/types.jl | 8 +- base/docs/basedocs.jl | 4 +- base/docs/helpdb/Base.jl | 22 +-- base/error.jl | 2 +- base/float.jl | 16 +-- base/floatfuncs.jl | 2 +- base/gmp.jl | 4 +- base/linalg/qr.jl | 4 +- base/math.jl | 19 +-- base/mpfr.jl | 18 +-- base/number.jl | 4 +- base/operators.jl | 7 +- base/promotion.jl | 4 +- base/random.jl | 17 +-- base/rational.jl | 4 +- base/reflection.jl | 4 +- base/rounding.jl | 8 +- base/show.jl | 2 +- base/socket.jl | 4 +- base/sparse/sparsematrix.jl | 4 +- base/sparse/umfpack.jl | 6 +- base/special/gamma.jl | 2 +- base/test.jl | 2 +- doc/src/devdocs/offset-arrays.md | 4 +- doc/src/devdocs/reflection.md | 2 +- doc/src/devdocs/types.md | 6 +- doc/src/manual/arrays.md | 4 +- doc/src/manual/calling-c-and-fortran-code.md | 8 +- doc/src/manual/constructors.md | 17 +-- doc/src/manual/control-flow.md | 4 +- doc/src/manual/conversion-and-promotion.md | 31 ++-- doc/src/manual/dates.md | 17 +-- doc/src/manual/documentation.md | 4 +- doc/src/manual/embedding.md | 12 +- doc/src/manual/environment-variables.md | 2 +- doc/src/manual/faq.md | 9 +- .../integers-and-floating-point-numbers.md | 52 +++---- doc/src/manual/mathematical-operations.md | 2 +- doc/src/manual/metaprogramming.md | 2 +- doc/src/manual/methods.md | 28 ++-- doc/src/manual/noteworthy-differences.md | 12 +- doc/src/manual/performance-tips.md | 22 +-- doc/src/manual/strings.md | 8 +- doc/src/manual/style-guide.md | 13 +- doc/src/manual/types.md | 136 ++++++++++-------- doc/src/stdlib/linalg.md | 8 +- doc/src/stdlib/numbers.md | 13 +- 58 files changed, 343 insertions(+), 312 deletions(-) diff --git a/base/Enums.jl b/base/Enums.jl index 9e8a144da1e58..13976a72d8e5f 100644 --- a/base/Enums.jl +++ b/base/Enums.jl @@ -45,8 +45,9 @@ julia> f(apple) "I'm a Fruit with value: 1" ``` -`BaseType`, which defaults to `Int32`, must be a primitive subtype of Integer. Member values can be converted between -the enum type and `BaseType`. `read` and `write` perform these conversions automatically. +`BaseType`, which defaults to [`Int32`](@ref), must be a primitive subtype of `Integer`. +Member values can be converted between the enum type and `BaseType`. `read` and `write` +perform these conversions automatically. """ macro enum(T,syms...) if isempty(syms) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 440372def4d58..af3bfe47825dd 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -503,7 +503,7 @@ julia> similar(trues(10,10), 2) false ``` -Since `BitArray`s can only store elements of type `Bool`, however, if you request a +Since `BitArray`s can only store elements of type [`Bool`](@ref), however, if you request a different element type it will create a regular `Array` instead: ```julia-repl diff --git a/base/array.jl b/base/array.jl index a4ae57bd971ae..80c04a30903dc 100644 --- a/base/array.jl +++ b/base/array.jl @@ -266,7 +266,7 @@ end eye([T::Type=Float64,] m::Integer, n::Integer) `m`-by-`n` identity matrix. -The default element type is `Float64`. +The default element type is [`Float64`](@ref). """ function eye(::Type{T}, m::Integer, n::Integer) where T a = zeros(T,m,n) @@ -287,7 +287,7 @@ eye(::Type{T}, n::Integer) where {T} = eye(T, n, n) eye([T::Type=Float64,] n::Integer) `n`-by-`n` identity matrix. -The default element type is `Float64`. +The default element type is [`Float64`](@ref). """ eye(n::Integer) = eye(Float64, n) diff --git a/base/c.jl b/base/c.jl index 410bb1e2f153e..80c58a4640614 100644 --- a/base/c.jl +++ b/base/c.jl @@ -45,7 +45,7 @@ Culong """ Cwchar_t -Equivalent to the native `wchar_t` c-type (`Int32`). +Equivalent to the native `wchar_t` c-type ([`Int32`](@ref)). """ Cwchar_t diff --git a/base/ctypes.jl b/base/ctypes.jl index 387fdd9d8c7dd..26640ed82bef5 100644 --- a/base/ctypes.jl +++ b/base/ctypes.jl @@ -6,7 +6,7 @@ """ Cuchar -Equivalent to the native `unsigned char` c-type (`UInt8`). +Equivalent to the native `unsigned char` c-type ([`UInt8`](@ref)). """ const Cuchar = UInt8 @@ -14,7 +14,7 @@ const Cuchar = UInt8 """ Cshort -Equivalent to the native `signed short` c-type (`Int16`). +Equivalent to the native `signed short` c-type ([`Int16`](@ref)). """ const Cshort = Int16 @@ -22,7 +22,7 @@ const Cshort = Int16 """ Cushort -Equivalent to the native `unsigned short` c-type (`UInt16`). +Equivalent to the native `unsigned short` c-type ([`UInt16`](@ref)). """ const Cushort = UInt16 @@ -30,7 +30,7 @@ const Cushort = UInt16 """ Cint -Equivalent to the native `signed int` c-type (`Int32`). +Equivalent to the native `signed int` c-type ([`Int32`](@ref)). """ const Cint = Int32 @@ -38,7 +38,7 @@ const Cint = Int32 """ Cuint -Equivalent to the native `unsigned int` c-type (`UInt32`). +Equivalent to the native `unsigned int` c-type ([`UInt32`](@ref)). """ const Cuint = UInt32 @@ -70,7 +70,7 @@ const Cssize_t = Int """ Cintmax_t -Equivalent to the native `intmax_t` c-type (`Int64`). +Equivalent to the native `intmax_t` c-type ([`Int64`](@ref)). """ const Cintmax_t = Int64 @@ -78,7 +78,7 @@ const Cintmax_t = Int64 """ Cuintmax_t -Equivalent to the native `uintmax_t` c-type (`UInt64`). +Equivalent to the native `uintmax_t` c-type ([`UInt64`](@ref)). """ const Cuintmax_t = UInt64 @@ -86,7 +86,7 @@ const Cuintmax_t = UInt64 """ Clonglong -Equivalent to the native `signed long long` c-type (`Int64`). +Equivalent to the native `signed long long` c-type ([`Int64`](@ref)). """ const Clonglong = Int64 @@ -94,7 +94,7 @@ const Clonglong = Int64 """ Culonglong -Equivalent to the native `unsigned long long` c-type (`UInt64`). +Equivalent to the native `unsigned long long` c-type ([`UInt64`](@ref)). """ const Culonglong = UInt64 @@ -102,7 +102,7 @@ const Culonglong = UInt64 """ Cfloat -Equivalent to the native `float` c-type (`Float32`). +Equivalent to the native `float` c-type ([`Float32`](@ref)). """ const Cfloat = Float32 @@ -110,6 +110,6 @@ const Cfloat = Float32 """ Cdouble -Equivalent to the native `double` c-type (`Float64`). +Equivalent to the native `double` c-type ([`Float64`](@ref)). """ const Cdouble = Float64 diff --git a/base/dates/accessors.jl b/base/dates/accessors.jl index d6ca886643001..27c41d118dfc8 100644 --- a/base/dates/accessors.jl +++ b/base/dates/accessors.jl @@ -74,7 +74,7 @@ for func in (:year, :month) @doc """ $($name)(dt::TimeType) -> Int64 - The $($name) of a `Date` or `DateTime` as an `Int64`. + The $($name) of a `Date` or `DateTime` as an [`Int64`](@ref). """ $func(dt::TimeType) end end @@ -83,9 +83,10 @@ end week(dt::TimeType) -> Int64 Return the [ISO week date](https://en.wikipedia.org/wiki/ISO_week_date) of a `Date` or -`DateTime` as an `Int64`. Note that the first week of a year is the week that contains the -first Thursday of the year which can result in dates prior to January 4th being in the last -week of the previous year. For example `week(Date(2005,1,1))` is the 53rd week of 2004. +`DateTime` as an [`Int64`](@ref). Note that the first week of a year is the week that +contains the first Thursday of the year which can result in dates prior to January 4th +being in the last week of the previous year. For example `week(Date(2005,1,1))` is the 53rd +week of 2004. """ week(dt::TimeType) @@ -95,7 +96,7 @@ for func in (:day, :dayofmonth) @doc """ $($name)(dt::TimeType) -> Int64 - The day of month of a `Date` or `DateTime` as an `Int64`. + The day of month of a `Date` or `DateTime` as an [`Int64`](@ref). """ $func(dt::TimeType) end end @@ -103,7 +104,7 @@ end """ hour(dt::DateTime) -> Int64 -The hour of day of a `DateTime` as an `Int64`. +The hour of day of a `DateTime` as an [`Int64`](@ref). """ hour(dt::DateTime) @@ -113,7 +114,7 @@ for func in (:minute, :second, :millisecond) @doc """ $($name)(dt::DateTime) -> Int64 - The $($name) of a `DateTime` as an `Int64`. + The $($name) of a `DateTime` as an [`Int64`](@ref). """ $func(dt::DateTime) end end @@ -137,7 +138,7 @@ for func in (:hour, :minute, :second, :millisecond, :microsecond, :nanosecond) @doc """ $($name)(t::Time) -> Int64 - The $($name) of a `Time` as an `Int64`. + The $($name) of a `Time` as an [`Int64`](@ref). """ $func(t::Time) end end diff --git a/base/dates/adjusters.jl b/base/dates/adjusters.jl index 357faec442a27..b93236e95bd9e 100644 --- a/base/dates/adjusters.jl +++ b/base/dates/adjusters.jl @@ -253,8 +253,8 @@ tonext(dt::TimeType, dow::Int; same::Bool=false) = adjust(ISDAYOFWEEK[dow], same tonext(func::Function, dt::TimeType; step=Day(1), limit=10000, same=false) -> TimeType Adjusts `dt` by iterating at most `limit` iterations by `step` increments until `func` -returns `true`. `func` must take a single `TimeType` argument and return a `Bool`. `same` -allows `dt` to be considered in satisfying `func`. +returns `true`. `func` must take a single `TimeType` argument and return a [`Bool`](@ref). +`same` allows `dt` to be considered in satisfying `func`. """ function tonext(func::Function, dt::TimeType; step::Period=Day(1), negate=nothing, limit::Int=10000, same::Bool=false) func = deprecate_negate(:tonext, func, "func,dt", negate) @@ -274,8 +274,8 @@ toprev(dt::TimeType, dow::Int; same::Bool=false) = adjust(ISDAYOFWEEK[dow], same toprev(func::Function, dt::TimeType; step=Day(-1), limit=10000, same=false) -> TimeType Adjusts `dt` by iterating at most `limit` iterations by `step` increments until `func` -returns `true`. `func` must take a single `TimeType` argument and return a `Bool`. `same` -allows `dt` to be considered in satisfying `func`. +returns `true`. `func` must take a single `TimeType` argument and return a [`Bool`](@ref). +`same` allows `dt` to be considered in satisfying `func`. """ function toprev(func::Function, dt::TimeType; step::Period=Day(-1), negate=nothing, limit::Int=10000, same::Bool=false) func = deprecate_negate(:toprev, func, "func,dt", negate) diff --git a/base/dates/conversions.jl b/base/dates/conversions.jl index 9016c5600d149..853f20b01cc77 100644 --- a/base/dates/conversions.jl +++ b/base/dates/conversions.jl @@ -53,7 +53,7 @@ end datetime2unix(dt::DateTime) -> Float64 Takes the given `DateTime` and returns the number of seconds -since the unix epoch `1970-01-01T00:00:00` as a `Float64`. +since the unix epoch `1970-01-01T00:00:00` as a [`Float64`](@ref). """ datetime2unix(dt::DateTime) = (value(dt) - UNIXEPOCH) / 1000.0 @@ -116,6 +116,6 @@ end datetime2julian(dt::DateTime) -> Float64 Takes the given `DateTime` and returns the number of Julian calendar days since the julian -epoch `-4713-11-24T12:00:00` as a `Float64`. +epoch `-4713-11-24T12:00:00` as a [`Float64`](@ref). """ datetime2julian(dt::DateTime) = (value(dt) - JULIANEPOCH) / 86400000.0 diff --git a/base/dates/periods.jl b/base/dates/periods.jl index 7fbba3d59f86f..27eafa5774ea1 100644 --- a/base/dates/periods.jl +++ b/base/dates/periods.jl @@ -33,7 +33,7 @@ for period in (:Year, :Month, :Week, :Day, :Hour, :Minute, :Second, :Millisecond $($period_str)(v) Construct a `$($period_str)` object with the given `v` value. Input must be - losslessly convertible to an `Int64`. + losslessly convertible to an [`Int64`](@ref). """ $period(v) end end diff --git a/base/dates/query.jl b/base/dates/query.jl index effdd68a1bbdf..2e632e239566b 100644 --- a/base/dates/query.jl +++ b/base/dates/query.jl @@ -101,7 +101,7 @@ dayofyear(y, m, d) = MONTHDAYS[m] + d + (m > 2 && isleapyear(y)) """ dayofweek(dt::TimeType) -> Int64 -Returns the day of the week as an `Int64` with `1 = Monday, 2 = Tuesday, etc.`. +Returns the day of the week as an [`Int64`](@ref) with `1 = Monday, 2 = Tuesday, etc.`. """ dayofweek(dt::TimeType) = dayofweek(days(dt)) diff --git a/base/dates/rounding.jl b/base/dates/rounding.jl index b1714fff075ef..8adbf80902b57 100644 --- a/base/dates/rounding.jl +++ b/base/dates/rounding.jl @@ -27,7 +27,7 @@ epochms2datetime(i) = DateTime(UTM(DATETIMEEPOCH + Int64(i))) date2epochdays(dt::Date) -> Int64 Takes the given `Date` and returns the number of days since the rounding epoch -(`0000-01-01T00:00:00`) as an `Int64`. +(`0000-01-01T00:00:00`) as an [`Int64`](@ref). """ date2epochdays(dt::Date) = value(dt) - DATEEPOCH @@ -35,7 +35,7 @@ date2epochdays(dt::Date) = value(dt) - DATEEPOCH datetime2epochms(dt::DateTime) -> Int64 Takes the given `DateTime` and returns the number of milliseconds since the rounding epoch -(`0000-01-01T00:00:00`) as an `Int64`. +(`0000-01-01T00:00:00`) as an [`Int64`](@ref). """ datetime2epochms(dt::DateTime) = value(dt) - DATETIMEEPOCH diff --git a/base/dates/types.jl b/base/dates/types.jl index 87871c9ee9f5a..12e3e62bf25f2 100644 --- a/base/dates/types.jl +++ b/base/dates/types.jl @@ -47,7 +47,7 @@ end Nanosecond(v) Construct a `Period` type with the given `v` value. Input must be losslessly convertible -to an `Int64`. +to an [`Int64`](@ref). """ Period(v) @@ -173,7 +173,7 @@ argerror() = Nullable{ArgumentError}() """ DateTime(y, [m, d, h, mi, s, ms]) -> DateTime -Construct a `DateTime` type by parts. Arguments must be convertible to `Int64`. +Construct a `DateTime` type by parts. Arguments must be convertible to [`Int64`](@ref). """ function DateTime(y::Int64, m::Int64=1, d::Int64=1, h::Int64=0, mi::Int64=0, s::Int64=0, ms::Int64=0) @@ -197,7 +197,7 @@ end """ Date(y, [m, d]) -> Date -Construct a `Date` type by parts. Arguments must be convertible to `Int64`. +Construct a `Date` type by parts. Arguments must be convertible to [`Int64`](@ref). """ function Date(y::Int64, m::Int64=1, d::Int64=1) err = validargs(Date, y, m, d) @@ -214,7 +214,7 @@ end """ Time(h, [mi, s, ms, us, ns]) -> Time -Construct a `Time` type by parts. Arguments must be convertible to `Int64`. +Construct a `Time` type by parts. Arguments must be convertible to [`Int64`](@ref). """ function Time(h::Int64, mi::Int64=0, s::Int64=0, ms::Int64=0, us::Int64=0, ns::Int64=0) err = validargs(Time, h, mi, s, ms, us, ns) diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index 4221f061bfcc3..ece074d231a1a 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -81,7 +81,7 @@ Julia’s type system more than just a collection of object implementations. For abstract type Number end abstract type Real <: Number end -`Number` has no supertype, whereas `Real` is an abstract subtype of `Number`. +[`Number`](@ref) has no supertype, whereas [`Real`](@ref) is an abstract subtype of `Number`. """ kw"abstract type" @@ -124,7 +124,7 @@ primitive type declarations: The number after the name indicates how many bits of storage the type requires. Currently, only sizes that are multiples of 8 bits are supported. -The `Bool` declaration shows how a primitive type can be optionally +The [`Bool`](@ref) declaration shows how a primitive type can be optionally declared to be a subtype of some supertype. """ kw"primitive type" diff --git a/base/docs/helpdb/Base.jl b/base/docs/helpdb/Base.jl index d0e408c4cff3e..a3f2530e4fef3 100644 --- a/base/docs/helpdb/Base.jl +++ b/base/docs/helpdb/Base.jl @@ -243,7 +243,7 @@ determines how the bytes of the array are interpreted. Note that the file must b binary format, and no format conversions are possible (this is a limitation of operating systems, not Julia). -`dims` is a tuple or single `Integer` specifying the size or length of the array. +`dims` is a tuple or single [`Integer`](@ref) specifying the size or length of the array. The file is passed via the stream argument, either as an open `IOStream` or filename string. When you initialize the stream, use `"r"` for a "read-only" array, and `"w+"` to create a @@ -1061,7 +1061,7 @@ For arrays, this constructs an array with the same binary data as the given array, but with the specified element type. For example, `reinterpret(Float32, UInt32(7))` interprets the 4 bytes corresponding to `UInt32(7)` as a -`Float32`. +[`Float32`](@ref). !!! warning @@ -1147,8 +1147,8 @@ searchsortedfirst """ big(x) -Convert a number to a maximum precision representation (typically `BigInt` or `BigFloat`). -See [`BigFloat`](@ref) for information about some pitfalls with floating-point numbers. +Convert a number to a maximum precision representation (typically [`BigInt`](@ref) or +`BigFloat`). See [`BigFloat`](@ref) for information about some pitfalls with floating-point numbers. """ big @@ -1434,10 +1434,10 @@ StackOverflowError """ ==(x, y) -Generic equality operator, giving a single `Bool` result. Falls back to `===`. Should be -implemented for all types with a notion of equality, based on the abstract value that an -instance represents. For example, all numeric types are compared by numeric value, ignoring -type. Strings are compared as sequences of characters, ignoring encoding. +Generic equality operator, giving a single [`Bool`](@ref) result. Falls back to `===`. +Should be implemented for all types with a notion of equality, based on the abstract value +that an instance represents. For example, all numeric types are compared by numeric value, +ignoring type. Strings are compared as sequences of characters, ignoring encoding. Follows IEEE semantics for floating-point numbers. @@ -1934,7 +1934,7 @@ done Convert `x` to a value of type `T`. -If `T` is an `Integer` type, an [`InexactError`](@ref) will be raised if `x` +If `T` is an [`Integer`](@ref) type, an [`InexactError`](@ref) will be raised if `x` is not representable by `T`, for example if `x` is not integer-valued, or is outside the range supported by `T`. @@ -1948,7 +1948,7 @@ Stacktrace: [1] convert(::Type{Int64}, ::Float64) at ./float.jl:680 ``` -If `T` is a `AbstractFloat` or `Rational` type, +If `T` is a [`AbstractFloat`](@ref) or [`Rational`](@ref) type, then it will return the closest value to `x` representable by `T`. ```jldoctest @@ -2160,7 +2160,7 @@ isvalid(value) isvalid(T, value) -> Bool Returns `true` if the given value is valid for that type. Types currently can -be either `Char` or `String`. Values for `Char` can be of type `Char` or `UInt32`. +be either `Char` or `String`. Values for `Char` can be of type `Char` or [`UInt32`](@ref). Values for `String` can be of that type, or `Vector{UInt8}`. """ isvalid(T,value) diff --git a/base/error.jl b/base/error.jl index 108f5c83716d4..f26df61ee91d8 100644 --- a/base/error.jl +++ b/base/error.jl @@ -98,7 +98,7 @@ end """ ExponentialBackOff(; n=1, first_delay=0.05, max_delay=10.0, factor=5.0, jitter=0.1) -A `Float64` iterator of length `n` whose elements exponentially increase at a +A [`Float64`](@ref) iterator of length `n` whose elements exponentially increase at a rate in the interval `factor` * (1 ± `jitter`). The first element is `first_delay` and all elements are clamped to `max_delay`. """ diff --git a/base/float.jl b/base/float.jl index 68d0d5138f0fe..65836552b2b31 100644 --- a/base/float.jl +++ b/base/float.jl @@ -5,25 +5,25 @@ """ Inf16 -Positive infinity of type `Float16`. +Positive infinity of type [`Float16`](@ref). """ const Inf16 = bitcast(Float16, 0x7c00) """ NaN16 -A not-a-number value of type `Float16`. +A not-a-number value of type [`Float16`](@ref). """ const NaN16 = bitcast(Float16, 0x7e00) """ Inf32 -Positive infinity of type `Float32`. +Positive infinity of type [`Float32`](@ref). """ const Inf32 = bitcast(Float32, 0x7f800000) """ NaN32 -A not-a-number value of type `Float32`. +A not-a-number value of type [`Float32`](@ref). """ const NaN32 = bitcast(Float32, 0x7fc00000) const Inf64 = bitcast(Float64, 0x7ff0000000000000) @@ -32,13 +32,13 @@ const NaN64 = bitcast(Float64, 0x7ff8000000000000) """ Inf -Positive infinity of type `Float64`. +Positive infinity of type [`Float64`](@ref). """ const Inf = Inf64 """ NaN -A not-a-number value of type `Float64`. +A not-a-number value of type [`Float64`](@ref). """ const NaN = NaN64 @@ -750,8 +750,8 @@ of `x` is different, then the larger of the two is taken, that is eps(x) == max(x-prevfloat(x), nextfloat(x)-x) The exceptions to this rule are the smallest and largest finite values -(e.g. `nextfloat(-Inf)` and `prevfloat(Inf)` for `Float64`), which round to the smaller of -the values. +(e.g. `nextfloat(-Inf)` and `prevfloat(Inf)` for [`Float64`](@ref)), which round to the +smaller of the values. The rationale for this behavior is that `eps` bounds the floating point rounding error. Under the default `RoundNearest` rounding mode, if ``y`` is a real number and ``x`` diff --git a/base/floatfuncs.jl b/base/floatfuncs.jl index e75486a46257c..a5973c7d99986 100644 --- a/base/floatfuncs.jl +++ b/base/floatfuncs.jl @@ -78,7 +78,7 @@ julia> round(pi, 3, 2) !!! note Rounding to specified digits in bases other than 2 can be inexact when - operating on binary floating point numbers. For example, the `Float64` + operating on binary floating point numbers. For example, the [`Float64`](@ref) value represented by `1.15` is actually *less* than 1.15, yet will be rounded to 1.2. diff --git a/base/gmp.jl b/base/gmp.jl index b78132e4b4856..07926f9865042 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -58,8 +58,8 @@ end BigInt(x) Create an arbitrary precision integer. `x` may be an `Int` (or anything that can be -converted to an `Int`). The usual mathematical operators are defined for this type, and -results are promoted to a `BigInt`. +converted to an `Int`). The usual mathematical operators are defined for this type, and +results are promoted to a [`BigInt`](@ref). Instances can be constructed from strings via [`parse`](@ref), or using the `big` string literal. diff --git a/base/linalg/qr.jl b/base/linalg/qr.jl index 2d6d723adefe1..13aa153575f1e 100644 --- a/base/linalg/qr.jl +++ b/base/linalg/qr.jl @@ -226,8 +226,8 @@ The returned object `F` stores the factorization in a packed format: - if `pivot == Val{true}` then `F` is a [`QRPivoted`](@ref) object, - - otherwise if the element type of `A` is a BLAS type (`Float32`, `Float64`, `Complex64` - or `Complex128`), then `F` is a [`QRCompactWY`](@ref) object, + - otherwise if the element type of `A` is a BLAS type ([`Float32`](@ref), [`Float64`](@ref), + `Complex64` or `Complex128`), then `F` is a [`QRCompactWY`](@ref) object, - otherwise `F` is a [`QR`](@ref) object. diff --git a/base/math.jl b/base/math.jl index 8861d2176e165..1956adf268260 100644 --- a/base/math.jl +++ b/base/math.jl @@ -161,7 +161,8 @@ log(b::T, x::T) where {T<:Number} = log(x)/log(b) """ log(b,x) -Compute the base `b` logarithm of `x`. Throws [`DomainError`](@ref) for negative `Real` arguments. +Compute the base `b` logarithm of `x`. Throws [`DomainError`](@ref) for negative +[`Real`](@ref) arguments. ```jldoctest julia> log(4,8) @@ -351,8 +352,8 @@ atanh(x) """ log(x) -Compute the natural logarithm of `x`. Throws [`DomainError`](@ref) for negative `Real` arguments. -Use complex negative arguments to obtain complex results. +Compute the natural logarithm of `x`. Throws [`DomainError`](@ref) for negative +[`Real`](@ref) arguments. Use complex negative arguments to obtain complex results. There is an experimental variant in the `Base.Math.JuliaLibm` module, which is typically faster and more accurate. @@ -362,7 +363,8 @@ log(x) """ log2(x) -Compute the logarithm of `x` to base 2. Throws [`DomainError`](@ref) for negative `Real` arguments. +Compute the logarithm of `x` to base 2. Throws [`DomainError`](@ref) for negative +[`Real`](@ref) arguments. # Example ```jldoctest @@ -379,7 +381,7 @@ log2(x) log10(x) Compute the logarithm of `x` to base 10. -Throws [`DomainError`](@ref) for negative `Real` arguments. +Throws [`DomainError`](@ref) for negative [`Real`](@ref) arguments. # Example ```jldoctest @@ -395,7 +397,8 @@ log10(x) """ log1p(x) -Accurate natural logarithm of `1+x`. Throws [`DomainError`](@ref) for `Real` arguments less than -1. +Accurate natural logarithm of `1+x`. Throws [`DomainError`](@ref) for [`Real`](@ref) +arguments less than -1. There is an experimental variant in the `Base.Math.JuliaLibm` module, which is typically faster and more accurate. @@ -438,8 +441,8 @@ sqrt(x::Float32) = sqrt_llvm(x) """ sqrt(x) -Return ``\\sqrt{x}``. Throws [`DomainError`](@ref) for negative `Real` arguments. Use complex -negative arguments instead. The prefix operator `√` is equivalent to `sqrt`. +Return ``\\sqrt{x}``. Throws [`DomainError`](@ref) for negative [`Real`](@ref) arguments. +Use complex negative arguments instead. The prefix operator `√` is equivalent to `sqrt`. """ sqrt(x::Real) = sqrt(float(x)) diff --git a/base/mpfr.jl b/base/mpfr.jl index 4f04480babb69..40e0fd59cf0ac 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -70,9 +70,9 @@ end """ BigFloat(x) -Create an arbitrary precision floating point number. `x` may be an `Integer`, a `Float64` or -a `BigInt`. The usual mathematical operators are defined for this type, and results are -promoted to a `BigFloat`. +Create an arbitrary precision floating point number. `x` may be an [`Integer`](@ref), a +[`Float64`](@ref) or a [`BigInt`](@ref). The usual mathematical operators are defined for +this type, and results are promoted to a [`BigFloat`](@ref). Note that because decimal literals are converted to floating point numbers when parsed, `BigFloat(2.1)` may not yield what you expect. You may instead prefer to initialize @@ -133,7 +133,7 @@ float(::Type{BigInt}) = BigFloat """ BigFloat(x, prec::Int) -Create a representation of `x` as a `BigFloat` with precision `prec`. +Create a representation of `x` as a [`BigFloat`](@ref) with precision `prec`. """ function BigFloat(x, prec::Int) setprecision(BigFloat, prec) do @@ -144,7 +144,8 @@ end """ BigFloat(x, prec::Int, rounding::RoundingMode) -Create a representation of `x` as a `BigFloat` with precision `prec` and rounding mode `rounding`. +Create a representation of `x` as a [`BigFloat`](@ref) with precision `prec` and +rounding mode `rounding`. """ function BigFloat(x, prec::Int, rounding::RoundingMode) setrounding(BigFloat, rounding) do @@ -155,7 +156,8 @@ end """ BigFloat(x, rounding::RoundingMode) -Create a representation of `x` as a `BigFloat` with the current global precision and rounding mode `rounding`. +Create a representation of `x` as a [`BigFloat`](@ref) with the current global precision +and rounding mode `rounding`. """ function BigFloat(x::Union{Integer, AbstractFloat, String}, rounding::RoundingMode) BigFloat(x, precision(BigFloat), rounding) @@ -164,7 +166,7 @@ end """ BigFloat(x::String) -Create a representation of the string `x` as a `BigFloat`. +Create a representation of the string `x` as a [`BigFloat`](@ref). """ BigFloat(x::String) = parse(BigFloat, x) @@ -728,7 +730,7 @@ end """ precision(BigFloat) -Get the precision (in bits) currently used for `BigFloat` arithmetic. +Get the precision (in bits) currently used for [`BigFloat`](@ref) arithmetic. """ precision(::Type{BigFloat}) = DEFAULT_PRECISION[end] # precision of the type BigFloat itself diff --git a/base/number.jl b/base/number.jl index 704bf42fc0070..d34f3ba10a438 100644 --- a/base/number.jl +++ b/base/number.jl @@ -190,8 +190,8 @@ _default_type(::Type{Number}) = Int """ factorial(n) -Factorial of `n`. If `n` is an `Integer`, the factorial is computed as an -integer (promoted to at least 64 bits). Note that this may overflow if `n` is not small, +Factorial of `n`. If `n` is an [`Integer`](@ref), the factorial is computed as an +integer (promoted to at least 64 bits). Note that this may overflow if `n` is not small, but you can use `factorial(big(n))` to compute the result exactly in arbitrary precision. If `n` is not an `Integer`, `factorial(n)` is equivalent to [`gamma(n+1)`](@ref). diff --git a/base/operators.jl b/base/operators.jl index bbec5c09e28f3..47ac4b25de3ea 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -532,8 +532,8 @@ Unsigned right bit shift operator, `x >>> n`. For `n >= 0`, the result is `x` shifted right by `n` bits, where `n >= 0`, filling with `0`s. For `n < 0`, this is equivalent to `x << -n`. -For `Unsigned` integer types, this is equivalent to [`>>`](@ref). For -`Signed` integer types, this is equivalent to `signed(unsigned(x) >> n)`. +For [`Unsigned`](@ref) integer types, this is equivalent to [`>>`](@ref). For +[`Signed`](@ref) integer types, this is equivalent to `signed(unsigned(x) >> n)`. ```jldoctest julia> Int8(-14) >>> 2 @@ -545,7 +545,8 @@ julia> bits(Int8(-14)) julia> bits(Int8(60)) "00111100" ``` -`BigInt`s are treated as if having infinite size, so no filling is required and this + +[`BigInt`](@ref)s are treated as if having infinite size, so no filling is required and this is equivalent to [`>>`](@ref). See also [`>>`](@ref), [`<<`](@ref). diff --git a/base/promotion.jl b/base/promotion.jl index 4fbe3f7068a2c..5c55b3d1e34d3 100644 --- a/base/promotion.jl +++ b/base/promotion.jl @@ -137,8 +137,8 @@ promote_type(::Type{Bottom}, ::Type{T}) where {T} = (@_pure_meta; T) Determine a type big enough to hold values of each argument type without loss, whenever possible. In some cases, where no type exists to which both types can be promoted losslessly, some loss is tolerated; for example, `promote_type(Int64, Float64)` returns -`Float64` even though strictly, not all `Int64` values can be represented exactly as -`Float64` values. +[`Float64`](@ref) even though strictly, not all [`Int64`](@ref) values can be represented +exactly as `Float64` values. ```jldoctest julia> promote_type(Int64, Float64) diff --git a/base/random.jl b/base/random.jl index 3697302a05153..847c61e2f9a1f 100644 --- a/base/random.jl +++ b/base/random.jl @@ -221,8 +221,8 @@ end Reseed the random number generator. If a `seed` is provided, the RNG will give a reproducible sequence of numbers, otherwise Julia will get entropy from the system. For -`MersenneTwister`, the `seed` may be a non-negative integer or a vector of `UInt32` integers. -`RandomDevice` does not support seeding. +`MersenneTwister`, the `seed` may be a non-negative integer or a vector of [`UInt32`](@ref) +integers. `RandomDevice` does not support seeding. """ srand(r::MersenneTwister) = srand(r, make_seed()) srand(r::MersenneTwister, n::Integer) = srand(r, make_seed(n)) @@ -258,9 +258,10 @@ Pick a random element or array of random elements from the set of values specifi * an indexable collection (for example `1:n` or `['x','y','z']`), or * a type: the set of values to pick from is then equivalent to `typemin(S):typemax(S)` for - integers (this is not applicable to `BigInt`), and to ``[0, 1)`` for floating point numbers; + integers (this is not applicable to [`BigInt`](@ref)), and to ``[0, 1)`` for floating + point numbers; -`S` defaults to `Float64`. +`S` defaults to [`Float64`](@ref). """ @inline rand() = rand(GLOBAL_RNG, CloseOpen) @inline rand(T::Type) = rand(GLOBAL_RNG, T) @@ -1181,9 +1182,9 @@ const ziggurat_exp_r = 7.6971174701310497140446280481 Generate a normally-distributed random number of type `T` with mean 0 and standard deviation 1. Optionally generate an array of normally-distributed random numbers. The `Base` module currently provides an implementation for the types -`Float16`, `Float32`, and `Float64` (the default), and their `Complex` counterparts. -When the type argument is complex, the values are drawn from the circularly symmetric -complex normal distribution. +[`Float16`](@ref), [`Float32`](@ref), and [`Float64`](@ref) (the default), and their +[`Complex`](@ref) counterparts. When the type argument is complex, the values are drawn +from the circularly symmetric complex normal distribution. """ @inline function randn(rng::AbstractRNG=GLOBAL_RNG) @inbounds begin @@ -1217,7 +1218,7 @@ end Generate a random number of type `T` according to the exponential distribution with scale 1. Optionally generate an array of such random numbers. The `Base` module currently provides an implementation for the types -`Float16`, `Float32`, and `Float64` (the default). +[`Float16`](@ref), [`Float32`](@ref), and [`Float64`](@ref) (the default). """ @inline function randexp(rng::AbstractRNG=GLOBAL_RNG) @inbounds begin diff --git a/base/rational.jl b/base/rational.jl index 1fe97049be83f..b3f901300399e 100644 --- a/base/rational.jl +++ b/base/rational.jl @@ -27,7 +27,7 @@ end """ //(num, den) -Divide two integers or rational numbers, giving a `Rational` result. +Divide two integers or rational numbers, giving a [`Rational`](@ref) result. ```jldoctest julia> 3 // 5 @@ -109,7 +109,7 @@ widen(::Type{Rational{T}}) where {T} = Rational{widen(T)} """ rationalize([T<:Integer=Int,] x; tol::Real=eps(x)) -Approximate floating point number `x` as a `Rational` number with components +Approximate floating point number `x` as a [`Rational`](@ref) number with components of the given integer type. The result will differ from `x` by no more than `tol`. If `T` is not provided, it defaults to `Int`. diff --git a/base/reflection.jl b/base/reflection.jl index 58d9b67e19177..eb8e279e11977 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -219,8 +219,8 @@ isstructtype(x) = (@_pure_meta; false) isbits(T) Return `true` if `T` is a "plain data" type, meaning it is immutable and contains no -references to other values. Typical examples are numeric types such as `UInt8`, `Float64`, -and `Complex{Float64}`. +references to other values. Typical examples are numeric types such as [`UInt8`](@ref), +[`Float64`](@ref), and [`Complex{Float64}`](@ref). ```jldoctest julia> isbits(Complex{Float64}) diff --git a/base/rounding.jl b/base/rounding.jl index 67f71d9dda57d..bcb9b6328ac15 100644 --- a/base/rounding.jl +++ b/base/rounding.jl @@ -37,7 +37,7 @@ Currently supported rounding modes are: - [`RoundNearestTiesAway`](@ref) - [`RoundNearestTiesUp`](@ref) - [`RoundToZero`](@ref) -- `RoundFromZero` (`BigFloat` only) +- `RoundFromZero` ([`BigFloat`](@ref) only) - [`RoundUp`](@ref) - [`RoundDown`](@ref) """ @@ -118,9 +118,9 @@ arithmetic functions ([`+`](@ref), [`-`](@ref), [`*`](@ref), functions may give incorrect or invalid values when using rounding modes other than the default `RoundNearest`. -Note that this may affect other types, for instance changing the rounding mode of `Float64` -will change the rounding mode of `Float32`. See [`RoundingMode`](@ref) for -available modes. +Note that this may affect other types, for instance changing the rounding mode of +[`Float64`](@ref) will change the rounding mode of [`Float32`](@ref). +See [`RoundingMode`](@ref) for available modes. !!! warning diff --git a/base/show.jl b/base/show.jl index f21483c699771..cdf7450f5713f 100644 --- a/base/show.jl +++ b/base/show.jl @@ -1570,7 +1570,7 @@ end summary(x) Return a string giving a brief description of a value. By default returns -`string(typeof(x))`, e.g. `Int64`. +`string(typeof(x))`, e.g. [`Int64`](@ref). For arrays, returns a string of size and type info, e.g. `10-element Array{Int64,1}`. diff --git a/base/socket.jl b/base/socket.jl index ae4e055c91325..108624be54917 100644 --- a/base/socket.jl +++ b/base/socket.jl @@ -24,7 +24,7 @@ end """ IPv4(host::Integer) -> IPv4 -Returns an IPv4 object from ip address `host` formatted as an `Integer`. +Returns an IPv4 object from ip address `host` formatted as an [`Integer`](@ref). ```jldoctest julia> IPv4(3223256218) @@ -76,7 +76,7 @@ end """ IPv6(host::Integer) -> IPv6 -Returns an IPv6 object from ip address `host` formatted as an `Integer`. +Returns an IPv6 object from ip address `host` formatted as an [`Integer`](@ref). ```jldoctest julia> IPv6(3223256218) diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl index 58e363a2e299d..f3986e6b43b06 100644 --- a/base/sparse/sparsematrix.jl +++ b/base/sparse/sparsematrix.jl @@ -1357,7 +1357,7 @@ spones(S::SparseMatrixCSC{T}) where {T} = Create a sparse vector of length `m` or sparse matrix of size `m x n`. This sparse array will not contain any nonzero values. No storage will be allocated -for nonzero values during construction. The type defaults to `Float64` if not +for nonzero values during construction. The type defaults to [`Float64`](@ref) if not specified. ```jldoctest @@ -1411,7 +1411,7 @@ eye(S::SparseMatrixCSC) = speye(S) speye([type,]m[,n]) Create a sparse identity matrix of size `m x m`. When `n` is supplied, -create a sparse identity matrix of size `m x n`. The type defaults to `Float64` +create a sparse identity matrix of size `m x n`. The type defaults to [`Float64`](@ref) if not specified. `sparse(I, m, n)` is equivalent to `speye(Int, m, n)`, and diff --git a/base/sparse/umfpack.jl b/base/sparse/umfpack.jl index 5e44206760f0f..edb88f80304de 100644 --- a/base/sparse/umfpack.jl +++ b/base/sparse/umfpack.jl @@ -107,8 +107,8 @@ end Compute the LU factorization of a sparse matrix `A`. For sparse `A` with real or complex element type, the return type of `F` is -`UmfpackLU{Tv, Ti}`, with `Tv` = `Float64` or `Complex128` respectively and -`Ti` is an integer type (`Int32` or `Int64`). +`UmfpackLU{Tv, Ti}`, with `Tv` = [`Float64`](@ref) or `Complex128` respectively and +`Ti` is an integer type ([`Int32`](@ref) or [`Int64`](@ref)). The individual components of the factorization `F` can be accessed by indexing: @@ -133,7 +133,7 @@ The relation between `F` and `A` is !!! note `lufact(A::SparseMatrixCSC)` uses the UMFPACK library that is part of - SuiteSparse. As this library only supports sparse matrices with `Float64` or + SuiteSparse. As this library only supports sparse matrices with [`Float64`](@ref) or `Complex128` elements, `lufact` converts `A` into a copy that is of type `SparseMatrixCSC{Float64}` or `SparseMatrixCSC{Complex128}` as appropriate. """ diff --git a/base/special/gamma.jl b/base/special/gamma.jl index 479ab58adfc0a..7415200b409ce 100644 --- a/base/special/gamma.jl +++ b/base/special/gamma.jl @@ -37,7 +37,7 @@ lfact(x::Integer) = x < 0 ? throw(DomainError()) : lgamma(x + oneunit(x)) lgamma(x) Compute the logarithm of the absolute value of [`gamma`](@ref) for -`Real` `x`, while for `Complex` `x` it computes the +[`Real`](@ref) `x`, while for [`Complex`](@ref) `x` compute the principal branch cut of the logarithm of `gamma(x)` (defined for negative `real(x)` by analytic continuation from positive `real(x)`). """ diff --git a/base/test.jl b/base/test.jl index a64c9679b0264..9d7dc05bd553e 100644 --- a/base/test.jl +++ b/base/test.jl @@ -115,7 +115,7 @@ end Error The test condition couldn't be evaluated due to an exception, or -it evaluated to something other than a `Bool`. +it evaluated to something other than a [`Bool`](@ref). In the case of `@test_broken` it is used to indicate that an unexpected `Pass` `Result` occurred. """ diff --git a/doc/src/devdocs/offset-arrays.md b/doc/src/devdocs/offset-arrays.md index 9951c72231de9..689f856b48d62 100644 --- a/doc/src/devdocs/offset-arrays.md +++ b/doc/src/devdocs/offset-arrays.md @@ -108,8 +108,8 @@ Storage is often allocated with `Array{Int}(dims)` or `similar(A, args...)`. Whe to match the indices of some other array, this may not always suffice. The generic replacement for such patterns is to use `similar(storagetype, shape)`. `storagetype` indicates the kind of underlying "conventional" behavior you'd like, e.g., `Array{Int}` or `BitArray` or even `dims->zeros(Float32, dims)` -(which would allocate an all-zeros array). `shape` is a tuple of `Integer` or `AbstractUnitRange` -values, specifying the indices that you want the result to use. +(which would allocate an all-zeros array). `shape` is a tuple of [`Integer`](@ref) or +`AbstractUnitRange` values, specifying the indices that you want the result to use. Let's walk through a couple of explicit examples. First, if `A` has conventional indices, then `similar(Array{Int}, indices(A))` would end up calling `Array{Int}(size(A))`, and thus return diff --git a/doc/src/devdocs/reflection.md b/doc/src/devdocs/reflection.md index 9579a21eddaf6..d31188f80b9aa 100644 --- a/doc/src/devdocs/reflection.md +++ b/doc/src/devdocs/reflection.md @@ -50,7 +50,7 @@ of these fields is the `types` field observed in the example above. ## Subtypes The *direct* subtypes of any `DataType` may be listed using [`subtypes()`](@ref). For example, -the abstract `DataType``AbstractFloat` has four (concrete) subtypes: +the abstract `DataType` [`AbstractFloat`](@ref) has four (concrete) subtypes: ```jldoctest julia> subtypes(AbstractFloat) diff --git a/doc/src/devdocs/types.md b/doc/src/devdocs/types.md index 44a1a7480e4c5..5b3da02716a6c 100644 --- a/doc/src/devdocs/types.md +++ b/doc/src/devdocs/types.md @@ -14,8 +14,8 @@ have. A *concrete* type `T` describes the set of values whose direct tag, as returned by the `typeof` function, is `T`. An *abstract* type describes some possibly-larger set of values. -`Any` describes the entire universe of possible values. `Integer` is a subset of `Any` that includes -`Int`, `Int8`, and other concrete types. +`Any` describes the entire universe of possible values. [`Integer`](@ref) is a subset of +`Any` that includes `Int`, [`Int8`](@ref), and other concrete types. Internally, Julia also makes heavy use of another type known as `Bottom`, which can also be written as `Union{}`. This corresponds to the empty set. @@ -330,7 +330,7 @@ However, this interpretation causes some practical problems. First, a value of `T` needs to be available inside the method definition. For a call like `f(1, 1.0)`, it's not clear what `T` should be. -It could be `Union{Int,Float64}`, or perhaps `Real`. +It could be `Union{Int,Float64}`, or perhaps [`Real`](@ref). Intuitively, we expect the declaration `x::T` to mean `T === typeof(x)`. To make sure that invariant holds, we need `typeof(x) === typeof(y) === T` in this method. That implies the method should only be called for arguments of the exact same type. diff --git a/doc/src/manual/arrays.md b/doc/src/manual/arrays.md index 757ac1f384a77..b99ae2cb050df 100644 --- a/doc/src/manual/arrays.md +++ b/doc/src/manual/arrays.md @@ -10,7 +10,7 @@ on implementing a custom array type. An array is a collection of objects stored in a multi-dimensional grid. In the most general case, an array may contain objects of type `Any`. For most computational purposes, arrays should contain -objects of a more specific type, such as `Float64` or `Int32`. +objects of a more specific type, such as [`Float64`](@ref) or [`Int32`](@ref). In general, unlike many other technical computing languages, Julia does not expect programs to be written in a vectorized style for performance. Julia's compiler uses type inference and generates @@ -46,7 +46,7 @@ Many functions for constructing and initializing arrays are provided. In the fol such functions, calls with a `dims...` argument can either take a single tuple of dimension sizes or a series of dimension sizes passed as a variable number of arguments. Most of these functions also accept a first input `T`, which is the element type of the array. If the type `T` is -omitted it will default to `Float64`. +omitted it will default to [`Float64`](@ref). | Function | Description | |:---------------------------------- |:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | diff --git a/doc/src/manual/calling-c-and-fortran-code.md b/doc/src/manual/calling-c-and-fortran-code.md index b8164f86ad8da..30da54ac330ad 100644 --- a/doc/src/manual/calling-c-and-fortran-code.md +++ b/doc/src/manual/calling-c-and-fortran-code.md @@ -66,7 +66,7 @@ julia> typeof(ans) Int32 ``` -`clock` takes no arguments and returns an `Int32`. One common gotcha is that a 1-tuple must be +`clock` takes no arguments and returns an [`Int32`](@ref). One common gotcha is that a 1-tuple must be written with a trailing comma. For example, to call the `getenv` function to get a pointer to the value of an environment variable, one makes a call like this: @@ -192,8 +192,8 @@ julia> const mycompare_c = cfunction(mycompare, Cint, (Ref{Cdouble}, Ref{Cdouble ``` [`cfunction()`](@ref) accepts three arguments: the Julia function (`mycompare`), the return type -(`Cint`), and a tuple of the argument types, in this case to sort an array of `Cdouble` (`Float64`) -elements. +(`Cint`), and a tuple of the argument types, in this case to sort an array of `Cdouble` +([`Float64`](@ref)) elements. The final call to `qsort` looks like this: @@ -298,7 +298,7 @@ same: * `Signed` Exactly corresponds to the `signed` type annotation in C (or any `INTEGER` type in Fortran). - Any Julia type that is not a subtype of `Signed` is assumed to be unsigned. + Any Julia type that is not a subtype of [`Signed`](@ref) is assumed to be unsigned. * `Ref{T}` diff --git a/doc/src/manual/constructors.md b/doc/src/manual/constructors.md index 607e702671211..e9b46b392a443 100644 --- a/doc/src/manual/constructors.md +++ b/doc/src/manual/constructors.md @@ -313,10 +313,10 @@ Point{Float64}(1.0, 2.0) As you can see, for constructor calls with explicit type parameters, the arguments are converted to the implied field types: `Point{Int64}(1,2)` works, but `Point{Int64}(1.0,2.5)` raises an -[`InexactError`](@ref) when converting `2.5` to `Int64`. When the type is implied by the arguments to -the constructor call, as in `Point(1,2)`, then the types of the arguments must agree -- otherwise -the `T` cannot be determined -- but any pair of real arguments with matching type may be given -to the generic `Point` constructor. +[`InexactError`](@ref) when converting `2.5` to [`Int64`](@ref). When the type is implied +by the arguments to the constructor call, as in `Point(1,2)`, then the types of the +arguments must agree -- otherwise the `T` cannot be determined -- but any pair of real +arguments with matching type may be given to the generic `Point` constructor. What's really going on here is that `Point`, `Point{Float64}` and `Point{Int64}` are all different constructor functions. In fact, `Point{T}` is a distinct constructor function for each type `T`. @@ -551,10 +551,11 @@ SummedArray{Int32,Int32}(Int32[1, 2, 3], 6) ``` The problem is that we want `S` to be a larger type than `T`, so that we can sum many elements -with less information loss. For example, when `T` is `Int32`, we would like `S` to be `Int64`. -Therefore we want to avoid an interface that allows the user to construct instances of the type -`SummedArray{Int32,Int32}`. One way to do this is to provide a constructor only for `SummedArray`, -but inside the `type` definition block to suppress generation of default constructors: +with less information loss. For example, when `T` is [`Int32`](@ref), we would like `S` to +be [`Int64`](@ref). Therefore we want to avoid an interface that allows the user to construct +instances of the type `SummedArray{Int32,Int32}`. One way to do this is to provide a +constructor only for `SummedArray`, but inside the `type` definition block to suppress +generation of default constructors: ```jldoctest julia> struct SummedArray{T<:Number,S<:Number} diff --git a/doc/src/manual/control-flow.md b/doc/src/manual/control-flow.md index 1bf0923b6cb40..1dc395b2a31d5 100644 --- a/doc/src/manual/control-flow.md +++ b/doc/src/manual/control-flow.md @@ -173,8 +173,8 @@ julia> if 1 ERROR: TypeError: non-boolean (Int64) used in boolean context ``` -This error indicates that the conditional was of the wrong type: `Int64` rather than the required -`Bool`. +This error indicates that the conditional was of the wrong type: [`Int64`](@ref) rather +than the required [`Bool`](@ref). The so-called "ternary operator", `?:`, is closely related to the `if`-`elseif`-`else` syntax, but is used where a conditional choice between single expression values is required, as opposed diff --git a/doc/src/manual/conversion-and-promotion.md b/doc/src/manual/conversion-and-promotion.md index b72d2715b6aeb..3ffd6e2e33856 100644 --- a/doc/src/manual/conversion-and-promotion.md +++ b/doc/src/manual/conversion-and-promotion.md @@ -101,13 +101,14 @@ is to it. For example, the method to convert a real number to a boolean is this: convert(::Type{Bool}, x::Real) = x==0 ? false : x==1 ? true : throw(InexactError()) ``` -The type of the first argument of this method is a [singleton type](@ref man-singleton-types), `Type{Bool}`, the only -instance of which is `Bool`. Thus, this method is only invoked when the first argument is the -type value `Bool`. Notice the syntax used for the first argument: the argument name is omitted -prior to the `::` symbol, and only the type is given. This is the syntax in Julia for a function -argument whose type is specified but whose value is never used in the function body. In this -example, since the type is a singleton, there would never be any reason to use its value within -the body. When invoked, the method determines whether a numeric value is true or false as a boolean, +The type of the first argument of this method is a [singleton type](@ref man-singleton-types), +`Type{Bool}`, the only instance of which is [`Bool`](@ref). Thus, this method is only invoked +when the first argument is the type value `Bool`. Notice the syntax used for the first +argument: the argument name is omitted prior to the `::` symbol, and only the type is given. +This is the syntax in Julia for a function argument whose type is specified but whose value +is never used in the function body. In this example, since the type is a singleton, there +would never be any reason to use its value within the body. When invoked, the method +determines whether a numeric value is true or false as a boolean, by comparing it to one and zero: ```jldoctest @@ -137,7 +138,8 @@ convert(::Type{T}, z::Complex) where {T<:Real} = ### [Case Study: Rational Conversions](@id man-rational-conversion) -To continue our case study of Julia's `Rational` type, here are the conversions declared in [`rational.jl`](https://github.com/JuliaLang/julia/blob/master/base/rational.jl), +To continue our case study of Julia's [`Rational`](@ref) type, here are the conversions declared in +[`rational.jl`](https://github.com/JuliaLang/julia/blob/master/base/rational.jl), right after the declaration of the type and its constructors: ```julia @@ -187,8 +189,8 @@ since the values are converted to a "greater" type -- i.e. one which can represe input values in a single common type. It is important, however, not to confuse this with object-oriented (structural) super-typing, or Julia's notion of abstract super-types: promotion has nothing to do with the type hierarchy, and everything to do with converting between alternate representations. -For instance, although every `Int32` value can also be represented as a `Float64` value, `Int32` -is not a subtype of `Float64`. +For instance, although every [`Int32`](@ref) value can also be represented as a [`Float64`](@ref) value, +`Int32` is not a subtype of `Float64`. Promotion to a common "greater" type is performed in Julia by the `promote` function, which takes any number of arguments, and returns a tuple of the same number of values, converted to a common @@ -286,10 +288,11 @@ promote_rule(::Type{UInt8}, ::Type{Int8}) = Int promote_rule(::Type{BigInt}, ::Type{Int8}) = BigInt ``` -In the latter case, the result type is `BigInt` since `BigInt` is the only type large enough to -hold integers for arbitrary-precision integer arithmetic. Also note that one does not need to -define both `promote_rule(::Type{A}, ::Type{B})` and `promote_rule(::Type{B}, ::Type{A})` -- the -symmetry is implied by the way `promote_rule` is used in the promotion process. +In the latter case, the result type is [`BigInt`](@ref) since `BigInt` is the only type +large enough to hold integers for arbitrary-precision integer arithmetic. Also note that +one does not need to define both `promote_rule(::Type{A}, ::Type{B})` and +`promote_rule(::Type{B}, ::Type{A})` -- the symmetry is implied by the way `promote_rule` +is used in the promotion process. The `promote_rule` function is used as a building block to define a second function called `promote_type`, which, given any number of type objects, returns the common type to which those values, as arguments diff --git a/doc/src/manual/dates.md b/doc/src/manual/dates.md index 70645cacd1d93..476314407e6ab 100644 --- a/doc/src/manual/dates.md +++ b/doc/src/manual/dates.md @@ -12,10 +12,10 @@ For example, since the [`Date`](@ref) type only resolves to the precision of a s no hours, minutes, or seconds), normal considerations for time zones, daylight savings/summer time, and leap seconds are unnecessary and avoided. -Both [`Date`](@ref) and [`DateTime`](@ref) are basically immutable `Int64` wrappers. The single -`instant` field of either type is actually a `UTInstant{P}` type, which represents a continuously -increasing machine timeline based on the UT second [^1]. The [`DateTime`](@ref) -type is not aware of time zones (*naive*, in Python parlance), +Both [`Date`](@ref) and [`DateTime`](@ref) are basically immutable [`Int64`](@ref) wrappers. +The single `instant` field of either type is actually a `UTInstant{P}` type, which +represents a continuously increasing machine timeline based on the UT second [^1]. The +[`DateTime`](@ref) type is not aware of time zones (*naive*, in Python parlance), analogous to a *LocalDateTime* in Java 8. Additional time zone functionality can be added through the [TimeZones.jl package](https://github.com/JuliaTime/TimeZones.jl/), which compiles the [IANA time zone database](http://www.iana.org/time-zones). Both [`Date`](@ref) and @@ -133,7 +133,7 @@ Finding the length of time between two [`Date`](@ref) or [`DateTime`](@ref) is s given their underlying representation as `UTInstant{Day}` and `UTInstant{Millisecond}`, respectively. The difference between [`Date`](@ref) is returned in the number of [`Day`](@ref), and [`DateTime`](@ref) in the number of [`Millisecond`](@ref). Similarly, comparing [`TimeType`](@ref) is a simple matter -of comparing the underlying machine instants (which in turn compares the internal `Int64` values). +of comparing the underlying machine instants (which in turn compares the internal [`Int64`](@ref) values). ```jldoctest julia> dt = Date(2012,2,29) @@ -190,7 +190,7 @@ julia> dt - dt2 ## Accessor Functions -Because the [`Date`](@ref) and [`DateTime`](@ref) types are stored as single `Int64` values, date +Because the [`Date`](@ref) and [`DateTime`](@ref) types are stored as single [`Int64`](@ref) values, date parts or fields can be retrieved through accessor functions. The lowercase accessors return the field as an integer: @@ -454,7 +454,8 @@ julia> Dates.lastdayofquarter(Date(2014,7,16)) # Adjusts to the last day of the The next two higher-order methods, [`tonext()`](@ref), and [`toprev()`](@ref), generalize working with temporal expressions by taking a `DateFunction` as first argument, along with a starting [`TimeType`](@ref). A `DateFunction` is just a function, usually anonymous, that takes a single -[`TimeType`](@ref) as input and returns a `Bool`, `true` indicating a satisfied adjustment criterion. +[`TimeType`](@ref) as input and returns a [`Bool`](@ref), `true` indicating a satisfied +adjustment criterion. For example: ```jldoctest @@ -511,7 +512,7 @@ Additional examples and tests are available in [`test/dates/adjusters.jl`](https Periods are a human view of discrete, sometimes irregular durations of time. Consider 1 month; it could represent, in days, a value of 28, 29, 30, or 31 depending on the year and month context. Or a year could represent 365 or 366 days in the case of a leap year. [`Period`](@ref) types are -simple `Int64` wrappers and are constructed by wrapping any `Int64` convertible type, i.e. `Year(1)` +simple [`Int64`](@ref) wrappers and are constructed by wrapping any `Int64` convertible type, i.e. `Year(1)` or `Month(3.0)`. Arithmetic between [`Period`](@ref) of the same type behave like integers, and limited `Period-Real` arithmetic is available. diff --git a/doc/src/manual/documentation.md b/doc/src/manual/documentation.md index 59d1a23f2e43d..94499bf241f72 100644 --- a/doc/src/manual/documentation.md +++ b/doc/src/manual/documentation.md @@ -109,8 +109,8 @@ As in the example above, we recommend following some simple conventions when wri Calling `rand` and other RNG-related functions should be avoided in doctests since they will not produce consistent outputs during different Julia sessions. - Operating system word size (`Int32` or `Int64`) as well as path separator differences (`/` or - `\`) will also effect the reproducibility of some doctests. + Operating system word size ([`Int32`](@ref) or [`Int64`](@ref)) as well as path separator differences + (`/` or `\`) will also effect the reproducibility of some doctests. Note that whitespace in your doctest is significant! The doctest will fail if you misalign the output of pretty-printing an array, for example. diff --git a/doc/src/manual/embedding.md b/doc/src/manual/embedding.md index 77a132c5b3d20..032b57dcedc43 100644 --- a/doc/src/manual/embedding.md +++ b/doc/src/manual/embedding.md @@ -139,9 +139,9 @@ Now the build command is simply `make`. Real applications will not just need to execute expressions, but also return their values to the host program. `jl_eval_string` returns a `jl_value_t*`, which is a pointer to a heap-allocated -Julia object. Storing simple data types like `Float64` in this way is called `boxing`, and extracting -the stored primitive data is called `unboxing`. Our improved sample program that calculates the -square root of 2 in Julia and reads back the result in C looks as follows: +Julia object. Storing simple data types like [`Float64`](@ref) in this way is called `boxing`, +and extracting the stored primitive data is called `unboxing`. Our improved sample program that +calculates the square root of 2 in Julia and reads back the result in C looks as follows: ```c jl_value_t *ret = jl_eval_string("sqrt(2.0)"); @@ -157,9 +157,9 @@ else { In order to check whether `ret` is of a specific Julia type, we can use the `jl_isa`, `jl_typeis`, or `jl_is_...` functions. -By typing `typeof(sqrt(2.0))` into the Julia shell we can see that the return type is `Float64` -(`double` in C). To convert the boxed Julia value into a C double the `jl_unbox_float64` function -is used in the above code snippet. +By typing `typeof(sqrt(2.0))` into the Julia shell we can see that the return type is +[`Float64`](@ref) (`double` in C). To convert the boxed Julia value into a C double the +`jl_unbox_float64` function is used in the above code snippet. Corresponding `jl_box_...` functions are used to convert the other way: diff --git a/doc/src/manual/environment-variables.md b/doc/src/manual/environment-variables.md index bbb2c41e27a91..d2fe606136b76 100644 --- a/doc/src/manual/environment-variables.md +++ b/doc/src/manual/environment-variables.md @@ -175,7 +175,7 @@ logical CPU cores available. ### `JULIA_WORKER_TIMEOUT` -A `Float64` that sets the value of `Base.worker_timeout()` (default: `60.0`). +A [`Float64`](@ref) that sets the value of `Base.worker_timeout()` (default: `60.0`). This function gives the number of seconds a worker process will wait for a master process to establish a connection before dying. diff --git a/doc/src/manual/faq.md b/doc/src/manual/faq.md index e019cce47fa78..4ff850b44ea00 100644 --- a/doc/src/manual/faq.md +++ b/doc/src/manual/faq.md @@ -214,9 +214,10 @@ julia> function unstable(flag::Bool) unstable (generic function with 1 method) ``` -It returns either an `Int` or a `Float64` depending on the value of its argument. Since Julia -can't predict the return type of this function at compile-time, any computation that uses it will -have to guard against both types possibly occurring, making generation of fast machine code difficult. +It returns either an `Int` or a [`Float64`](@ref) depending on the value of its argument. +Since Julia can't predict the return type of this function at compile-time, any computation +that uses it will have to guard against both types possibly occurring, making generation of +fast machine code difficult. ### [Why does Julia give a `DomainError` for certain seemingly-sensible operations?](@id faq-domain-errors) @@ -281,7 +282,7 @@ ideal for a high-level programming language to expose this to the user. For nume efficiency and transparency are at a premium, however, the alternatives are worse. One alternative to consider would be to check each integer operation for overflow and promote -results to bigger integer types such as `Int128` or [`BigInt`](@ref) in the case of overflow. +results to bigger integer types such as [`Int128`](@ref) or [`BigInt`](@ref) in the case of overflow. Unfortunately, this introduces major overhead on every integer operation (think incrementing a loop counter) – it requires emitting code to perform run-time overflow checks after arithmetic instructions and branches to handle potential overflows. Worse still, this would cause every computation diff --git a/doc/src/manual/integers-and-floating-point-numbers.md b/doc/src/manual/integers-and-floating-point-numbers.md index 5e1c54347bd3f..1b819938cc625 100644 --- a/doc/src/manual/integers-and-floating-point-numbers.md +++ b/doc/src/manual/integers-and-floating-point-numbers.md @@ -18,25 +18,25 @@ The following are Julia's primitive numeric types: * **Integer types:** -| Type | Signed? | Number of bits | Smallest value | Largest value | -|:--------- |:------- |:-------------- |:-------------- |:------------- | -| `Int8` | ✓ | 8 | -2^7 | 2^7 - 1 | -| `UInt8` |   | 8 | 0 | 2^8 - 1 | -| `Int16` | ✓ | 16 | -2^15 | 2^15 - 1 | -| `UInt16` |   | 16 | 0 | 2^16 - 1 | -| `Int32` | ✓ | 32 | -2^31 | 2^31 - 1 | -| `UInt32` |   | 32 | 0 | 2^32 - 1 | -| `Int64` | ✓ | 64 | -2^63 | 2^63 - 1 | -| `UInt64` |   | 64 | 0 | 2^64 - 1 | -| `Int128` | ✓ | 128 | -2^127 | 2^127 - 1 | -| `UInt128` |   | 128 | 0 | 2^128 - 1 | -| `Bool` | N/A | 8 | `false` (0) | `true` (1) | +| Type | Signed? | Number of bits | Smallest value | Largest value | +|:----------------- |:------- |:-------------- |:-------------- |:------------- | +| [`Int8`](@ref) | ✓ | 8 | -2^7 | 2^7 - 1 | +| [`UInt8`](@ref) |   | 8 | 0 | 2^8 - 1 | +| [`Int16`](@ref) | ✓ | 16 | -2^15 | 2^15 - 1 | +| [`UInt16`](@ref) |   | 16 | 0 | 2^16 - 1 | +| [`Int32`](@ref) | ✓ | 32 | -2^31 | 2^31 - 1 | +| [`UInt32`](@ref) |   | 32 | 0 | 2^32 - 1 | +| [`Int64`](@ref) | ✓ | 64 | -2^63 | 2^63 - 1 | +| [`UInt64`](@ref) |   | 64 | 0 | 2^64 - 1 | +| [`Int128`](@ref) | ✓ | 128 | -2^127 | 2^127 - 1 | +| [`UInt128`](@ref) |   | 128 | 0 | 2^128 - 1 | +| [`Bool`](@ref) | N/A | 8 | `false` (0) | `true` (1) | * **Floating-point types:** | Type | Precision | Number of bits | |:----------------- |:------------------------------------------------------------------------------ |:-------------- | -| `Float16` | [half](https://en.wikipedia.org/wiki/Half-precision_floating-point_format) | 16 | +| [`Float16`](@ref) | [half](https://en.wikipedia.org/wiki/Half-precision_floating-point_format) | 16 | | [`Float32`](@ref) | [single](https://en.wikipedia.org/wiki/Single_precision_floating-point_format) | 32 | | [`Float64`](@ref) | [double](https://en.wikipedia.org/wiki/Double_precision_floating-point_format) | 64 | @@ -206,7 +206,7 @@ true Thus, arithmetic with Julia integers is actually a form of [modular arithmetic](https://en.wikipedia.org/wiki/Modular_arithmetic). This reflects the characteristics of the underlying arithmetic of integers as implemented on modern computers. In applications where overflow is possible, explicit checking for wraparound produced -by overflow is essential; otherwise, the `BigInt` type in [Arbitrary Precision Arithmetic](@ref) +by overflow is essential; otherwise, the [`BigInt`](@ref) type in [Arbitrary Precision Arithmetic](@ref) is recommended instead. ### Division errors @@ -243,8 +243,8 @@ julia> 2.5e-4 0.00025 ``` -The above results are all `Float64` values. Literal `Float32` values can be entered by writing -an `f` in place of `e`: +The above results are all [`Float64`](@ref) values. Literal [`Float32`](@ref) values can be +entered by writing an `f` in place of `e`: ```jldoctest julia> 0.5f0 @@ -257,7 +257,7 @@ julia> 2.5f-4 0.00025f0 ``` -Values can be converted to `Float32` easily: +Values can be converted to [`Float32`](@ref) easily: ```jldoctest julia> Float32(-1.5) @@ -267,7 +267,7 @@ julia> typeof(ans) Float32 ``` -Hexadecimal floating-point literals are also valid, but only as `Float64` values: +Hexadecimal floating-point literals are also valid, but only as [`Float64`](@ref) values: ```jldoctest julia> 0x1p0 @@ -283,8 +283,8 @@ julia> typeof(ans) Float64 ``` -Half-precision floating-point numbers are also supported (`Float16`), but they are -implemented in software and use `Float32` for calculations. +Half-precision floating-point numbers are also supported ([`Float16`](@ref)), but they are +implemented in software and use [`Float32`](@ref) for calculations. ```jldoctest julia> sizeof(Float16(4.)) @@ -404,11 +404,11 @@ julia> eps() # same as eps(Float64) 2.220446049250313e-16 ``` -These values are `2.0^-23` and `2.0^-52` as `Float32` and `Float64` values, respectively. The -[`eps()`](@ref) function can also take a floating-point value as an argument, and gives the absolute -difference between that value and the next representable floating point value. That is, `eps(x)` -yields a value of the same type as `x` such that `x + eps(x)` is the next representable floating-point -value larger than `x`: +These values are `2.0^-23` and `2.0^-52` as [`Float32`](@ref) and [`Float64`](@ref) values, +respectively. The [`eps()`](@ref) function can also take a floating-point value as an +argument, and gives the absolute difference between that value and the next representable +floating point value. That is, `eps(x)` yields a value of the same type as `x` such that +`x + eps(x)` is the next representable floating-point value larger than `x`: ```jldoctest julia> eps(1.0) diff --git a/doc/src/manual/mathematical-operations.md b/doc/src/manual/mathematical-operations.md index 2727ec20cd853..a6ff8bdea53f8 100644 --- a/doc/src/manual/mathematical-operations.md +++ b/doc/src/manual/mathematical-operations.md @@ -21,7 +21,7 @@ are supported on all primitive numeric types: | `x ^ y` | power | raises `x` to the `y`th power | | `x % y` | remainder | equivalent to `rem(x,y)` | -as well as the negation on `Bool` types: +as well as the negation on [`Bool`](@ref) types: | Expression | Name | Description | |:---------- |:-------- |:---------------------------------------- | diff --git a/doc/src/manual/metaprogramming.md b/doc/src/manual/metaprogramming.md index 445049ec3cf39..1804f39559b20 100644 --- a/doc/src/manual/metaprogramming.md +++ b/doc/src/manual/metaprogramming.md @@ -972,7 +972,7 @@ julia> foo(4) 16 ``` -Note that there is no printout of `Int64`. We can see that the body of the generated function +Note that there is no printout of [`Int64`](@ref). We can see that the body of the generated function was only executed once here, for the specific set of argument types, and the result was cached. After that, for this example, the expression returned from the generated function on the first invocation was re-used as the method body. However, the actual caching behavior is an implementation-defined diff --git a/doc/src/manual/methods.md b/doc/src/manual/methods.md index bc649bf4c2f35..c8843e18b0635 100644 --- a/doc/src/manual/methods.md +++ b/doc/src/manual/methods.md @@ -58,7 +58,8 @@ julia> f(x::Float64, y::Float64) = 2x + y f (generic function with 1 method) ``` -This function definition applies only to calls where `x` and `y` are both values of type `Float64`: +This function definition applies only to calls where `x` and `y` are both values of type +[`Float64`](@ref): ```jldoctest fofxy julia> f(2.0, 3.0) @@ -87,12 +88,12 @@ julia> f("2.0", "3.0") ERROR: MethodError: no method matching f(::String, ::String) ``` -As you can see, the arguments must be precisely of type `Float64`. Other numeric types, such as -integers or 32-bit floating-point values, are not automatically converted to 64-bit floating-point, -nor are strings parsed as numbers. Because `Float64` is a concrete type and concrete types cannot -be subclassed in Julia, such a definition can only be applied to arguments that are exactly of -type `Float64`. It may often be useful, however, to write more general methods where the declared -parameter types are abstract: +As you can see, the arguments must be precisely of type [`Float64`](@ref). Other numeric +types, such as integers or 32-bit floating-point values, are not automatically converted +to 64-bit floating-point, nor are strings parsed as numbers. Because `Float64` is a concrete +type and concrete types cannot be subclassed in Julia, such a definition can only be applied +to arguments that are exactly of type `Float64`. It may often be useful, however, to write +more general methods where the declared parameter types are abstract: ```jldoctest fofxy julia> f(x::Number, y::Number) = 2x - y @@ -102,9 +103,10 @@ julia> f(2.0, 3) 1.0 ``` -This method definition applies to any pair of arguments that are instances of `Number`. They need -not be of the same type, so long as they are each numeric values. The problem of handling disparate -numeric types is delegated to the arithmetic operations in the expression `2x - y`. +This method definition applies to any pair of arguments that are instances of [`Number`](@ref). +They need not be of the same type, so long as they are each numeric values. The problem of +handling disparate numeric types is delegated to the arithmetic operations in the +expression `2x - y`. To define a function with multiple methods, one simply defines the function multiple times, with different numbers and types of arguments. The first method definition for a function creates the @@ -112,9 +114,9 @@ function object, and subsequent method definitions add new methods to the existi The most specific method definition matching the number and types of the arguments will be executed when the function is applied. Thus, the two method definitions above, taken together, define the behavior for `f` over all pairs of instances of the abstract type `Number` -- but with a different -behavior specific to pairs of `Float64` values. If one of the arguments is a 64-bit float but -the other one is not, then the `f(Float64,Float64)` method cannot be called and the more general -`f(Number,Number)` method must be used: +behavior specific to pairs of [`Float64`](@ref) values. If one of the arguments is a 64-bit +float but the other one is not, then the `f(Float64,Float64)` method cannot be called and +the more general `f(Number,Number)` method must be used: ```jldoctest fofxy julia> f(2.0, 3.0) diff --git a/doc/src/manual/noteworthy-differences.md b/doc/src/manual/noteworthy-differences.md index 5457f201dbd6d..98740263fc364 100644 --- a/doc/src/manual/noteworthy-differences.md +++ b/doc/src/manual/noteworthy-differences.md @@ -239,11 +239,11 @@ For users coming to Julia from R, these are some noteworthy differences: unsigned and/or signed vs. unsigned. Decimal literals are always signed, and hexadecimal literals (which start with `0x` like C/C++), are unsigned. Hexadecimal literals also, unlike C/C++/Java and unlike decimal literals in Julia, have a type based on the *length* of the literal, including - leading 0s. For example, `0x0` and `0x00` have type UInt8, `0x000` and `0x0000` have type `UInt16`, - then literals with 5 to 8 hex digits have type `UInt32`, 9 to 16 hex digits type `UInt64` and - 17 to 32 hex digits type `UInt128`. This needs to be taken into account when defining hexadecimal - masks, for example `~0xf == 0xf0` is very different from `~0x000f == 0xfff0`. 64 bit `Float64` - and 32 bit `Float32` bit literals are expressed as `1.0` and `1.0f0` respectively. Floating point + leading 0s. For example, `0x0` and `0x00` have type [`UInt8`](@ref), `0x000` and `0x0000` have type + [`UInt16`](@ref), then literals with 5 to 8 hex digits have type `UInt32`, 9 to 16 hex digits type + `UInt64` and 17 to 32 hex digits type `UInt128`. This needs to be taken into account when defining + hexadecimal masks, for example `~0xf == 0xf0` is very different from `~0x000f == 0xfff0`. 64 bit `Float64` + and 32 bit [`Float32`](@ref) bit literals are expressed as `1.0` and `1.0f0` respectively. Floating point literals are rounded (and not promoted to the `BigFloat` type) if they can not be exactly represented. Floating point literals are closer in behavior to C/C++. Octal (prefixed with `0o`) and binary (prefixed with `0b`) literals are also treated as unsigned. @@ -251,7 +251,7 @@ For users coming to Julia from R, these are some noteworthy differences: `"` characters without quoting it like `"\""` String literals can have values of other variables or expressions interpolated into them, indicated by `$variablename` or `$(expression)`, which evaluates the variable name or the expression in the context of the function. - * `//` indicates a `Rational` number, and not a single-line comment (which is `#` in Julia) + * `//` indicates a [`Rational`](@ref) number, and not a single-line comment (which is `#` in Julia) * `#=` indicates the start of a multiline comment, and `=#` ends it. * Functions in Julia return values from their last expression(s) or the `return` keyword. Multiple values can be returned from functions and assigned as tuples, e.g. `(a, b) = myfunction()` or diff --git a/doc/src/manual/performance-tips.md b/doc/src/manual/performance-tips.md index 14c91c0d9e379..92fd3bc55aa30 100644 --- a/doc/src/manual/performance-tips.md +++ b/doc/src/manual/performance-tips.md @@ -137,10 +137,10 @@ if (f = rand()) < .8 end ``` -Because `a` is a an array of abstract type `Real`, it must be able to hold any `Real` value. Since -`Real` objects can be of arbitrary size and structure, `a` must be represented as an array of -pointers to individually allocated `Real` objects. Because `f` will always be a [`Float64`](@ref), -we should instead, use: +Because `a` is a an array of abstract type [`Real`](@ref), it must be able to hold any +`Real` value. Since `Real` objects can be of arbitrary size and structure, `a` must be +represented as an array of pointers to individually allocated `Real` objects. Because `f` +will always be a [`Float64`](@ref), we should instead, use: ```julia a = Float64[] # typeof(a) = Array{Float64,1} @@ -188,9 +188,9 @@ MyAmbiguousType `b` and `c` have the same type, yet their underlying representation of data in memory is very different. Even if you stored just numeric values in field `a`, the fact that the memory representation -of a `UInt8` differs from a `Float64` also means that the CPU needs to handle them using two different -kinds of instructions. Since the required information is not available in the type, such decisions -have to be made at run-time. This slows performance. +of a [`UInt8`](@ref) differs from a [`Float64`](@ref) also means that the CPU needs to handle +them using two different kinds of instructions. Since the required information is not available +in the type, such decisions have to be made at run-time. This slows performance. You can do better by declaring the type of `a`. Here, we are focused on the case where `a` might be any one of several types, in which case the natural solution is to use parameters. For example: @@ -473,9 +473,9 @@ function foo(a::Array{Any,1}) end ``` -Here, we happened to know that the first element of `a` would be an `Int32`. Making an annotation -like this has the added benefit that it will raise a run-time error if the value is not of the -expected type, potentially catching certain bugs earlier. +Here, we happened to know that the first element of `a` would be an [`Int32`](@ref). Making +an annotation like this has the added benefit that it will raise a run-time error if the +value is not of the expected type, potentially catching certain bugs earlier. ### Declare types of keyword arguments @@ -1388,7 +1388,7 @@ code defined in `pos`. Starting at `2:`, the variable `y` is defined, and again annotated as a `Union` type. Next, we see that the compiler created the temporary variable `_var1` to hold the result of `y*x`. Because -a [`Float64`](@ref) times *either* an `Int64` or [`Float64`](@ref) yields a [`Float64`](@ref), +a [`Float64`](@ref) times *either* an [`Int64`](@ref) or `Float64` yields a `Float64`, all type-instability ends here. The net result is that `f(x::Float64)` will not be type-unstable in its output, even if some of the intermediate computations are type-unstable. diff --git a/doc/src/manual/strings.md b/doc/src/manual/strings.md index 4d4b9d5a0f158..a1298af12de5b 100644 --- a/doc/src/manual/strings.md +++ b/doc/src/manual/strings.md @@ -64,8 +64,8 @@ julia> typeof(ans) Int64 ``` -On 32-bit architectures, [`typeof(ans)`](@ref) will be `Int32`. You can convert an integer value -back to a `Char` just as easily: +On 32-bit architectures, [`typeof(ans)`](@ref) will be [`Int32`](@ref). You can convert an +integer value back to a `Char` just as easily: ```jldoctest julia> Char(120) @@ -778,8 +778,8 @@ for regular expressions containing quotation marks or newlines). ## [Byte Array Literals](@id man-byte-array-literals) Another useful non-standard string literal is the byte-array string literal: `b"..."`. This form -lets you use string notation to express literal byte arrays -- i.e. arrays of `UInt8` values. -The rules for byte array literals are the following: +lets you use string notation to express literal byte arrays -- i.e. arrays of +[`UInt8`](@ref) values. The rules for byte array literals are the following: * ASCII characters and ASCII escapes produce a single byte. * `\x` and octal escape sequences produce the *byte* corresponding to the escape value. diff --git a/doc/src/manual/style-guide.md b/doc/src/manual/style-guide.md index c4ac88ffc20a6..fccb5559d9272 100644 --- a/doc/src/manual/style-guide.md +++ b/doc/src/manual/style-guide.md @@ -32,11 +32,12 @@ complex(float(x)) The second version will convert `x` to an appropriate type, instead of always the same type. This style point is especially relevant to function arguments. For example, don't declare an argument -to be of type `Int` or `Int32` if it really could be any integer, expressed with the abstract -type `Integer`. In fact, in many cases you can omit the argument type altogether, unless it is -needed to disambiguate from other method definitions, since a [`MethodError`](@ref) will be thrown -anyway if a type is passed that does not support any of the requisite operations. (This is known -as [duck typing](https://en.wikipedia.org/wiki/Duck_typing).) +to be of type `Int` or [`Int32`](@ref) if it really could be any integer, expressed with the abstract +type [`Integer`](@ref). In fact, in many cases you can omit the argument type altogether, +unless it is needed to disambiguate from other method definitions, since a +[`MethodError`](@ref) will be thrown anyway if a type is passed that does not support any +of the requisite operations. (This is known as +[duck typing](https://en.wikipedia.org/wiki/Duck_typing).) For example, consider the following definitions of a function `addone` that returns one plus its argument: @@ -356,7 +357,7 @@ julia> g(1) As you can see, the second version, where we used an `Int` literal, preserved the type of the input argument, while the first didn't. This is because e.g. `promote_type(Int, Float64) == Float64`, -and promotion happens with the multiplication. Similarly, `Rational` literals are less type disruptive +and promotion happens with the multiplication. Similarly, [`Rational`](@ref) literals are less type disruptive than [`Float64`](@ref) literals, but more disruptive than `Int`s: ```jldoctest diff --git a/doc/src/manual/types.md b/doc/src/manual/types.md index 633ba5b47fac7..da93e407f2cf2 100644 --- a/doc/src/manual/types.md +++ b/doc/src/manual/types.md @@ -133,18 +133,19 @@ system: they form the conceptual hierarchy which makes Julia's type system more of object implementations. Recall that in [Integers and Floating-Point Numbers](@ref), we introduced a variety of concrete -types of numeric values: `Int8`, `UInt8`, `Int16`, `UInt16`, `Int32`, `UInt32`, `Int64`, `UInt64`, -`Int128`, `UInt128`, `Float16`, [`Float32`](@ref), and [`Float64`](@ref). Although they have -different representation sizes, `Int8`, `Int16`, `Int32`, `Int64` and `Int128` all have in common -that they are signed integer types. Likewise `UInt8`, `UInt16`, `UInt32`, `UInt64` and `UInt128` -are all unsigned integer types, while `Float16`, [`Float32`](@ref) and [`Float64`](@ref) are distinct -in being floating-point types rather than integers. It is common for a piece of code to make sense, -for example, only if its arguments are some kind of integer, but not really depend on what particular -*kind* of integer. For example, the greatest common denominator algorithm works for all kinds -of integers, but will not work for floating-point numbers. Abstract types allow the construction -of a hierarchy of types, providing a context into which concrete types can fit. This allows you, -for example, to easily program to any type that is an integer, without restricting an algorithm -to a specific type of integer. +types of numeric values: [`Int8`](@ref), [`UInt8`](@ref), [`Int16`](@ref), [`UInt16`](@ref), +[`Int32`](@ref), [`UInt32`](@ref), [`Int64`](@ref), [`UInt64`](@ref), [`Int128`](@ref), +[`UInt128`](@ref), [`Float16`](@ref), [`Float32`](@ref), and [`Float64`](@ref). Although +they have different representation sizes, `Int8`, `Int16`, `Int32`, `Int64` and `Int128` +all have in common that they are signed integer types. Likewise `UInt8`, `UInt16`, `UInt32`, +`UInt64` and `UInt128` are all unsigned integer types, while `Float16`, `Float32` and +`Float64` are distinct in being floating-point types rather than integers. It is common for +a piece of code to make sense, for example, only if its arguments are some kind of integer, +but not really depend on what particular *kind* of integer. For example, the greatest common +denominator algorithm works for all kinds of integers, but will not work for floating-point +numbers. Abstract types allow the construction of a hierarchy of types, providing a context +into which concrete types can fit. This allows you, for example, to easily program to any type +that is an integer, without restricting an algorithm to a specific type of integer. Abstract types are declared using the `abstract type` keyword. The general syntaxes for declaring an abstract type are: @@ -175,13 +176,14 @@ abstract type Signed <: Integer end abstract type Unsigned <: Integer end ``` -The `Number` type is a direct child type of `Any`, and `Real` is its child. In turn, `Real` has -two children (it has more, but only two are shown here; we'll get to the others later): `Integer` -and `AbstractFloat`, separating the world into representations of integers and representations -of real numbers. Representations of real numbers include, of course, floating-point types, but -also include other types, such as rationals. Hence, `AbstractFloat` is a proper subtype of `Real`, -including only floating-point representations of real numbers. Integers are further subdivided -into `Signed` and `Unsigned` varieties. +The [`Number`](@ref) type is a direct child type of `Any`, and [`Real`](@ref) is its child. +In turn, `Real` has two children (it has more, but only two are shown here; we'll get to +the others later): [`Integer`](@ref) and [`AbstractFloat`](@ref), separating the world into +representations of integers and representations of real numbers. Representations of real +numbers include, of course, floating-point types, but also include other types, such as +rationals. Hence, `AbstractFloat` is a proper subtype of `Real`, including only +floating-point representations of real numbers. Integers are further subdivided into +[`Signed`](@ref) and [`Unsigned`](@ref) varieties. The `<:` operator in general means "is a subtype of", and, used in declarations like this, declares the right-hand type to be an immediate supertype of the newly declared type. It can also be used @@ -268,19 +270,21 @@ primitive type «name» <: «supertype» «bits» end The number of bits indicates how much storage the type requires and the name gives the new type a name. A primitive type can optionally be declared to be a subtype of some supertype. If a supertype is omitted, then the type defaults to having `Any` as its immediate supertype. The declaration -of `Bool` above therefore means that a boolean value takes eight bits to store, and has `Integer` -as its immediate supertype. Currently, only sizes that are multiples of 8 bits are supported. -Therefore, boolean values, although they really need just a single bit, cannot be declared to -be any smaller than eight bits. - -The types `Bool`, `Int8` and `UInt8` all have identical representations: they are eight-bit chunks -of memory. Since Julia's type system is nominative, however, they are not interchangeable despite -having identical structure. A fundamental difference between them is that they have different -supertypes: `Bool`'s direct supertype is `Integer`, `Int8`'s is `Signed`, and `UInt8`'s is `Unsigned`. -All other differences between `Bool`, `Int8`, and `UInt8` are matters of behavior -- the way functions -are defined to act when given objects of these types as arguments. This is why a nominative type -system is necessary: if structure determined type, which in turn dictates behavior, then it would -be impossible to make `Bool` behave any differently than `Int8` or `UInt8`. +of [`Bool`](@ref) above therefore means that a boolean value takes eight bits to store, and has +[`Integer`](@ref) as its immediate supertype. Currently, only sizes that are multiples of +8 bits are supported. Therefore, boolean values, although they really need just a single bit, +cannot be declared to be any smaller than eight bits. + +The types [`Bool`](@ref), [`Int8`](@ref) and [`UInt8`](@ref) all have identical representations: +they are eight-bit chunks of memory. Since Julia's type system is nominative, however, they +are not interchangeable despite having identical structure. A fundamental difference between +them is that they have different supertypes: [`Bool`](@ref)'s direct supertype is [`Integer`](@ref), +[`Int8`](@ref)'s is [`Signed`](@ref), and [`UInt8`](@ref)'s is [`Unsigned`](@ref). All other +differences between [`Bool`](@ref), [`Int8`](@ref), and [`UInt8`](@ref) are matters of +behavior -- the way functions are defined to act when given objects of these types as +arguments. This is why a nominative type system is necessary: if structure determined type, +which in turn dictates behavior, then it would be impossible to make [`Bool`](@ref) behave +any differently than [`Int8`](@ref) or [`UInt8`](@ref). ## Composite Types @@ -586,14 +590,16 @@ have different representations in memory: * An instance of `Point{Float64}` can be represented compactly and efficiently as an immediate pair of 64-bit values; - * An instance of `Point{Real}` must be able to hold any pair of instances of `Real`. Since objects - that are instances of `Real` can be of arbitrary size and structure, in practice an instance of - `Point{Real}` must be represented as a pair of pointers to individually allocated `Real` objects. + * An instance of `Point{Real}` must be able to hold any pair of instances of [`Real`](@ref). + Since objects that are instances of `Real` can be of arbitrary size and structure, in + practice an instance of `Point{Real}` must be represented as a pair of pointers to + individually allocated `Real` objects. The efficiency gained by being able to store `Point{Float64}` objects with immediate values is magnified enormously in the case of arrays: an `Array{Float64}` can be stored as a contiguous memory block of 64-bit floating-point values, whereas an `Array{Real}` must be an array of pointers -to individually allocated `Real` objects -- which may well be [boxed](https://en.wikipedia.org/wiki/Object_type_%28object-oriented_programming%29#Boxing) +to individually allocated [`Real`](@ref) objects -- which may well be +[boxed](https://en.wikipedia.org/wiki/Object_type_%28object-oriented_programming%29#Boxing) 64-bit floating-point values, but also might be arbitrarily large, complex objects, which are declared to be implementations of the `Real` abstract type. @@ -607,7 +613,7 @@ end ``` A correct way to define a method that accepts all arguments of type `Point{T}` where `T` is -a subtype of `Real` is: +a subtype of [`Real`](@ref) is: ```julia function norm(p::Point{<:Real}) @@ -784,8 +790,8 @@ possible types. In such situations, one can constrain the range of `T` like so: julia> abstract type Pointy{T<:Real} end ``` -With such a declaration, it is acceptable to use any type that is a subtype of `Real` in place -of `T`, but not types that are not subtypes of `Real`: +With such a declaration, it is acceptable to use any type that is a subtype of +[`Real`](@ref) in place of `T`, but not types that are not subtypes of `Real`: ```jldoctest realpointytype julia> Pointy{Float64} @@ -811,8 +817,8 @@ end ``` To give a real-world example of how all this parametric type machinery can be useful, here is -the actual definition of Julia's `Rational` immutable type (except that we omit the constructor -here for simplicity), representing an exact ratio of integers: +the actual definition of Julia's [`Rational`](@ref) immutable type (except that we omit the +constructor here for simplicity), representing an exact ratio of integers: ```julia struct Rational{T<:Integer} <: Real @@ -822,8 +828,8 @@ end ``` It only makes sense to take ratios of integer values, so the parameter type `T` is restricted -to being a subtype of `Integer`, and a ratio of integers represents a value on the real number -line, so any `Rational` is an instance of the `Real` abstraction. +to being a subtype of [`Integer`](@ref), and a ratio of integers represents a value on the +real number line, so any [`Rational`](@ref) is an instance of the [`Real`](@ref) abstraction. ### Tuple Types @@ -1008,21 +1014,22 @@ Using explicit `where` syntax, any subset of parameters can be fixed. For exampl 1-dimensional arrays can be written as `Array{T,1} where T`. Type variables can be restricted with subtype relations. -`Array{T} where T<:Integer` refers to all arrays whose element type is some kind of `Integer`. +`Array{T} where T<:Integer` refers to all arrays whose element type is some kind of +[`Integer`](@ref). The syntax `Array{<:Integer}` is a convenient shorthand for `Array{T} where T<:Integer`. Type variables can have both lower and upper bounds. -`Array{T} where Int<:T<:Number` refers to all arrays of `Number`s that are able to contain `Int`s -(since `T` must be at least as big as `Int`). +`Array{T} where Int<:T<:Number` refers to all arrays of [`Number`](@ref)s that are able to +contain `Int`s (since `T` must be at least as big as `Int`). The syntax `where T>:Int` also works to specify only the lower bound of a type variable, and `Array{>:Int}` is equivalent to `Array{T} where T>:Int`. Since `where` expressions nest, type variable bounds can refer to outer type variables. -For example `Tuple{T,Array{S}} where S<:AbstractArray{T} where T<:Real` refers to 2-tuples whose first -element is some `Real`, and whose second element is an `Array` of any kind of array whose element type -contains the type of the first tuple element. +For example `Tuple{T,Array{S}} where S<:AbstractArray{T} where T<:Real` refers to 2-tuples +whose first element is some [`Real`](@ref), and whose second element is an `Array` of any +kind of array whose element type contains the type of the first tuple element. -The `where` keyword itself can be nested inside a more complex declaration. For example, consider the -two types created by the following declarations: +The `where` keyword itself can be nested inside a more complex declaration. For example, +consider the two types created by the following declarations: ```jldoctest julia> const T1 = Array{Array{T,1} where T, 1} @@ -1056,8 +1063,8 @@ element type. Sometimes it is convenient to introduce a new name for an already expressible type. This can be done with a simple assignment statement. -For example, `UInt` is aliased to either `UInt32` or `UInt64` as is appropriate -for the size of pointers on the system: +For example, `UInt` is aliased to either [`UInt32`](@ref) or [`UInt64`](@ref) as is +appropriate for the size of pointers on the system: ```julia-repl # 32-bit system: @@ -1080,11 +1087,12 @@ end ``` Of course, this depends on what `Int` is aliased to -- but that is predefined to be the correct -type -- either `Int32` or `Int64`. +type -- either [`Int32`](@ref) or [`Int64`](@ref). -(Note that unlike `Int`, `Float` does not exist as a type alias for a specific sized `AbstractFloat`. -Unlike with integer registers, the floating point register sizes are specified by the IEEE-754 standard. -Whereas the size of `Int` reflects the size of a native pointer on that machine.) +(Note that unlike `Int`, `Float` does not exist as a type alias for a specific sized +[`AbstractFloat`](@ref). Unlike with integer registers, the floating point register sizes +are specified by the IEEE-754 standard. Whereas the size of `Int` reflects the size of a +native pointer on that machine.) ## Operations on Types @@ -1175,11 +1183,13 @@ julia> Polar(r::Real,Θ::Real) = Polar(promote(r,Θ)...) Polar ``` -Here, we've added a custom constructor function so that it can take arguments of different `Real` -types and promote them to a common type (see [Constructors](@ref man-constructors) and [Conversion and Promotion](@ref conversion-and-promotion)). -(Of course, we would have to define lots of other methods, too, to make it act like a `Number`, -e.g. `+`, `*`, `one`, `zero`, promotion rules and so on.) By default, instances of this type display -rather simply, with information about the type name and the field values, as e.g. `Polar{Float64}(3.0,4.0)`. +Here, we've added a custom constructor function so that it can take arguments of different +[`Real`](@ref) types and promote them to a common type (see [Constructors](@ref man-constructors) +and [Conversion and Promotion](@ref conversion-and-promotion)). +(Of course, we would have to define lots of other methods, too, to make it act like a +[`Number`](@ref), e.g. `+`, `*`, `one`, `zero`, promotion rules and so on.) By default, +instances of this type display rather simply, with information about the type name and +the field values, as e.g. `Polar{Float64}(3.0,4.0)`. If we want it to display instead as `3.0 * exp(4.0im)`, we would define the following method to print the object to a given output object `io` (representing a file, terminal, buffer, etcetera; @@ -1247,7 +1257,7 @@ julia> show(STDOUT, "text/html", Polar(3.0,4.0)) In Julia, you can't dispatch on a *value* such as `true` or `false`. However, you can dispatch on parametric types, and Julia allows you to include "plain bits" values (Types, Symbols, Integers, floating-point numbers, tuples, etc.) as type parameters. A common example is the dimensionality -parameter in `Array{T,N}`, where `T` is a type (e.g., `Float64`) but `N` is just an `Int`. +parameter in `Array{T,N}`, where `T` is a type (e.g., [`Float64`](@ref)) but `N` is just an `Int`. You can create your own custom types that take values as parameters, and use them to control dispatch of custom types. By way of illustration of this idea, let's introduce a parametric type, `Val{T}`, diff --git a/doc/src/stdlib/linalg.md b/doc/src/stdlib/linalg.md index bee85bb152227..0f415013c51dc 100644 --- a/doc/src/stdlib/linalg.md +++ b/doc/src/stdlib/linalg.md @@ -154,13 +154,13 @@ Base.At_rdiv_Bt In Julia (as in much of scientific computation), dense linear-algebra operations are based on the [LAPACK library](http://www.netlib.org/lapack/), which in turn is built on top of basic linear-algebra -building-blocks known as the [BLAS](http://www.netlib.org/blas/). There are highly optimized +building-blocks known as the [BLAS](http://www.netlib.org/blas/). There are highly optimized implementations of BLAS available for every computer architecture, and sometimes in high-performance linear algebra routines it is useful to call the BLAS functions directly. `Base.LinAlg.BLAS` provides wrappers for some of the BLAS functions. Those BLAS functions that overwrite one of the input arrays have names ending in `'!'`. Usually, a BLAS function has -four methods defined, for `Float64`, `Float32`, `Complex128`, and `Complex64` arrays. +four methods defined, for [`Float64`](@ref), [`Float32`](@ref), `Complex128`, and `Complex64` arrays. ### [BLAS Character Arguments](@id stdlib-blas-chars) Many BLAS functions accept arguments that determine whether to transpose an argument (`trans`), @@ -245,8 +245,8 @@ Base.LinAlg.I `Base.LinAlg.LAPACK` provides wrappers for some of the LAPACK functions for linear algebra. Those functions that overwrite one of the input arrays have names ending in `'!'`. -Usually a function has 4 methods defined, one each for `Float64`, `Float32`, `Complex128` and -`Complex64` arrays. +Usually a function has 4 methods defined, one each for [`Float64`](@ref), [`Float32`](@ref), +`Complex128` and `Complex64` arrays. Note that the LAPACK API provided by Julia can and will change in the future. Since this API is not user-facing, there is no commitment to support/deprecate this specific set of functions in diff --git a/doc/src/stdlib/numbers.md b/doc/src/stdlib/numbers.md index df3a4f63ce637..af00def34e64e 100644 --- a/doc/src/stdlib/numbers.md +++ b/doc/src/stdlib/numbers.md @@ -117,7 +117,8 @@ Base.iseven ## BigFloats -The `BigFloat` type implements arbitrary-precision floating-point arithmetic using the [GNU MPFR library](http://www.mpfr.org/). +The [`BigFloat`](@ref) type implements arbitrary-precision floating-point arithmetic using +the [GNU MPFR library](http://www.mpfr.org/). ```@docs Base.precision @@ -143,10 +144,12 @@ dimension specifications `dims...` (which can be given as a tuple) to generate a values. A `MersenneTwister` or `RandomDevice` RNG can generate random numbers of the following types: -`Float16`, `Float32`, `Float64`, `Bool`, `Int8`, `UInt8`, `Int16`, `UInt16`, `Int32`, `UInt32`, -`Int64`, `UInt64`, `Int128`, `UInt128`, `BigInt` (or complex numbers of those types). Random floating -point numbers are generated uniformly in ``[0, 1)``. As `BigInt` represents unbounded integers, -the interval must be specified (e.g. `rand(big(1:6))`). +[`Float16`](@ref), [`Float32`](@ref), [`Float64`](@ref), [`Bool`](@ref), [`Int8`](@ref), +[`UInt8`](@ref), [`Int16`](@ref), [`UInt16`](@ref), [`Int32`](@ref), [`UInt32`](@ref), +[`Int64`](@ref), [`UInt64`](@ref), [`Int128`](@ref), [`UInt128`](@ref), [`BigInt`](@ref) +(or complex numbers of those types). Random floating point numbers are generated uniformly +in ``[0, 1)``. As `BigInt` represents unbounded integers, the interval must be specified +(e.g. `rand(big(1:6))`). ```@docs Base.Random.srand From 3aa4db871f0bfcd586ebe12de2e50761a4050758 Mon Sep 17 00:00:00 2001 From: "Jane E. Herriman" Date: Sun, 28 May 2017 12:42:55 -0700 Subject: [PATCH 0932/1534] Fix failing doctests --- base/array.jl | 4 ++-- base/math.jl | 2 +- doc/src/devdocs/reflection.md | 3 ++- doc/src/manual/complex-and-rational-numbers.md | 6 +++--- doc/src/manual/control-flow.md | 2 +- doc/src/manual/conversion-and-promotion.md | 2 +- doc/src/manual/faq.md | 2 +- doc/src/manual/metaprogramming.md | 12 ++++++++---- 8 files changed, 19 insertions(+), 14 deletions(-) diff --git a/base/array.jl b/base/array.jl index 80c04a30903dc..e7adc6e67eb2b 100644 --- a/base/array.jl +++ b/base/array.jl @@ -860,8 +860,8 @@ julia> deleteat!([6, 5, 4, 3, 2, 1], [true, false, true, false, true, false]) julia> deleteat!([6, 5, 4, 3, 2, 1], (2, 2)) ERROR: ArgumentError: indices must be unique and sorted Stacktrace: - [1] _deleteat!(::Array{Int64,1}, ::Tuple{Int64,Int64}) at ./array.jl:873 - [2] deleteat!(::Array{Int64,1}, ::Tuple{Int64,Int64}) at ./array.jl:860 + [1] _deleteat!(::Array{Int64,1}, ::Tuple{Int64,Int64}) at ./array.jl:880 + [2] deleteat!(::Array{Int64,1}, ::Tuple{Int64,Int64}) at ./array.jl:867 ``` """ deleteat!(a::Vector, inds) = _deleteat!(a, inds) diff --git a/base/math.jl b/base/math.jl index 1956adf268260..c033f2d8e8efd 100644 --- a/base/math.jl +++ b/base/math.jl @@ -462,7 +462,7 @@ julia> √(a^2 + a^2) # a^2 overflows ERROR: DomainError: sqrt will only return a complex result if called with a complex argument. Try sqrt(complex(x)). Stacktrace: - [1] sqrt(::Int64) at ./math.jl:431 + [1] sqrt(::Int64) at ./math.jl:447 ``` """ hypot(x::Number, y::Number) = hypot(promote(x, y)...) diff --git a/doc/src/devdocs/reflection.md b/doc/src/devdocs/reflection.md index d31188f80b9aa..8baa61a222508 100644 --- a/doc/src/devdocs/reflection.md +++ b/doc/src/devdocs/reflection.md @@ -99,7 +99,8 @@ and variable assignments: julia> expand( :(f() = 1) ) :(begin $(Expr(:method, :f)) - $(Expr(:method, :f, :((Core.svec)((Core.svec)((Core.Typeof)(f)), (Core.svec)())), CodeInfo(:(begin # none, line 1: + $(Expr(:method, :f, :((Core.svec)((Core.svec)((Core.Typeof)(f)), (Core.svec)())), CodeInfo(:(begin + #= none:1 =# return 1 end)), false)) return f diff --git a/doc/src/manual/complex-and-rational-numbers.md b/doc/src/manual/complex-and-rational-numbers.md index d3245c27a9639..29636b4a2f139 100644 --- a/doc/src/manual/complex-and-rational-numbers.md +++ b/doc/src/manual/complex-and-rational-numbers.md @@ -143,7 +143,7 @@ julia> sqrt(-1) ERROR: DomainError: sqrt will only return a complex result if called with a complex argument. Try sqrt(complex(x)). Stacktrace: - [1] sqrt(::Int64) at ./math.jl:431 + [1] sqrt(::Int64) at ./math.jl:447 julia> sqrt(-1 + 0im) 0.0 + 1.0im @@ -283,8 +283,8 @@ Trying to construct a [`NaN`](@ref) rational value, however, is not: julia> 0//0 ERROR: ArgumentError: invalid rational: zero(Int64)//zero(Int64) Stacktrace: - [1] Rational{Int64}(::Int64, ::Int64) at ./rational.jl:8 - [2] //(::Int64, ::Int64) at ./rational.jl:35 + [1] Rational{Int64}(::Int64, ::Int64) at ./rational.jl:13 + [2] //(::Int64, ::Int64) at ./rational.jl:40 ``` As usual, the promotion system makes interactions with other numeric types effortless: diff --git a/doc/src/manual/control-flow.md b/doc/src/manual/control-flow.md index 1dc395b2a31d5..e06586239edd1 100644 --- a/doc/src/manual/control-flow.md +++ b/doc/src/manual/control-flow.md @@ -571,7 +571,7 @@ julia> sqrt(-1) ERROR: DomainError: sqrt will only return a complex result if called with a complex argument. Try sqrt(complex(x)). Stacktrace: - [1] sqrt(::Int64) at ./math.jl:431 + [1] sqrt(::Int64) at ./math.jl:447 ``` You may define your own exceptions in the following way: diff --git a/doc/src/manual/conversion-and-promotion.md b/doc/src/manual/conversion-and-promotion.md index 3ffd6e2e33856..5cc15a893ef4e 100644 --- a/doc/src/manual/conversion-and-promotion.md +++ b/doc/src/manual/conversion-and-promotion.md @@ -121,7 +121,7 @@ false julia> convert(Bool, 1im) ERROR: InexactError() Stacktrace: - [1] convert(::Type{Bool}, ::Complex{Int64}) at ./complex.jl:23 + [1] convert(::Type{Bool}, ::Complex{Int64}) at ./complex.jl:31 julia> convert(Bool, 0im) false diff --git a/doc/src/manual/faq.md b/doc/src/manual/faq.md index 4ff850b44ea00..39a03f30c13fd 100644 --- a/doc/src/manual/faq.md +++ b/doc/src/manual/faq.md @@ -228,7 +228,7 @@ julia> sqrt(-2.0) ERROR: DomainError: sqrt will only return a complex result if called with a complex argument. Try sqrt(complex(x)). Stacktrace: - [1] sqrt(::Float64) at ./math.jl:422 + [1] sqrt(::Float64) at ./math.jl:438 julia> 2^-5 ERROR: DomainError: diff --git a/doc/src/manual/metaprogramming.md b/doc/src/manual/metaprogramming.md index 1804f39559b20..a6d3fa57840e5 100644 --- a/doc/src/manual/metaprogramming.md +++ b/doc/src/manual/metaprogramming.md @@ -194,9 +194,12 @@ julia> ex = quote y = 2 x + y end -quote # none, line 2: - x = 1 # none, line 3: - y = 2 # none, line 4: +quote + #= none:2 =# + x = 1 + #= none:3 =# + y = 2 + #= none:4 =# x + y end @@ -521,13 +524,14 @@ The location information can be accessed by referencing `__source__.line` and `_ ```jldoctest julia> macro __LOCATION__(); return QuoteNode(__source__); end +@__LOCATION__ (macro with 1 method) julia> dump( @__LOCATION__( )) LineNumberNode line: Int64 2 - file: Symbol REPL[2] + file: Symbol none ``` ### Building an advanced macro From 55a7bea619ee1ed82c10c7b95c0763eeed215d24 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Fri, 19 May 2017 12:17:16 +0200 Subject: [PATCH 0933/1534] add rand(::IntSet) --- base/random.jl | 16 +++++++++++++++- test/random.jl | 7 ++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/base/random.jl b/base/random.jl index 847c61e2f9a1f..6357acccc8b2d 100644 --- a/base/random.jl +++ b/base/random.jl @@ -339,7 +339,7 @@ function rand(r::AbstractRNG, ::Type{Char}) (c < 0xd800) ? Char(c) : Char(c+0x800) end -# random values from Dict or Set (for efficiency) +# random values from Dict, Set, IntSet (for efficiency) function rand(r::AbstractRNG, t::Dict) isempty(t) && throw(ArgumentError("dict must be non-empty")) n = length(t.slots) @@ -352,6 +352,20 @@ rand(t::Dict) = rand(GLOBAL_RNG, t) rand(r::AbstractRNG, s::Set) = rand(r, s.dict).first rand(s::Set) = rand(GLOBAL_RNG, s) +function rand(r::AbstractRNG, s::IntSet) + isempty(s) && throw(ArgumentError("collection must be non-empty")) + # s can be empty while s.bits is not, so we cannot rely on the + # length check in RangeGenerator below + rg = RangeGenerator(1:length(s.bits)) + while true + n = rand(r, rg) + @inbounds b = s.bits[n] + b && return n + end +end + +rand(s::IntSet) = rand(GLOBAL_RNG, s) + ## Arrays of random numbers rand(r::AbstractRNG, dims::Dims) = rand(r, Float64, dims) diff --git a/test/random.jl b/test/random.jl index 0d54f0a426cc4..8a1a918167caf 100644 --- a/test/random.jl +++ b/test/random.jl @@ -53,11 +53,16 @@ let mt = MersenneTwister(0) rand(coll, 2, 3) end -# rand using Dict, Set +# rand using Dict, Set, IntSet adict = Dict(1=>2, 3=>4, 5=>6) @test rand(adict) in adict +@test_throws ArgumentError rand(Dict()) aset = Set(1:10) @test rand(aset) in aset +@test_throws ArgumentError rand(Set()) +anintset = IntSet(1:10) +@test rand(anintset) in anintset +@test_throws ArgumentError rand(IntSet()) # randn @test randn(MersenneTwister(42)) == -0.5560268761463861 From 97702900e19c65646d0b3a40cfc251e49ec5f410 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Fri, 19 May 2017 12:29:35 +0200 Subject: [PATCH 0934/1534] optimize rand(::Dict) And change "dict" -> "collection" in the exception, as it is also used from rand(::Set). --- base/random.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/base/random.jl b/base/random.jl index 6357acccc8b2d..3c63686376152 100644 --- a/base/random.jl +++ b/base/random.jl @@ -341,11 +341,11 @@ end # random values from Dict, Set, IntSet (for efficiency) function rand(r::AbstractRNG, t::Dict) - isempty(t) && throw(ArgumentError("dict must be non-empty")) - n = length(t.slots) + isempty(t) && throw(ArgumentError("collection must be non-empty")) + rg = RangeGenerator(1:length(t.slots)) while true - i = rand(r, 1:n) - Base.isslotfilled(t, i) && return (t.keys[i] => t.vals[i]) + i = rand(r, rg) + Base.isslotfilled(t, i) && @inbounds return (t.keys[i] => t.vals[i]) end end rand(t::Dict) = rand(GLOBAL_RNG, t) From 99f207d3a6701bba422ac23beccf4aa99f44c923 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Sat, 20 May 2017 16:08:39 +0200 Subject: [PATCH 0935/1534] complete the rand API with Dict, Set, IntSet --- base/random.jl | 29 ++++++++++++++++++++++++++++- test/random.jl | 30 +++++++++++++++++++----------- 2 files changed, 47 insertions(+), 12 deletions(-) diff --git a/base/random.jl b/base/random.jl index 3c63686376152..7d15e802b678a 100644 --- a/base/random.jl +++ b/base/random.jl @@ -257,11 +257,22 @@ globalRNG() = GLOBAL_RNG Pick a random element or array of random elements from the set of values specified by `S`; `S` can be * an indexable collection (for example `1:n` or `['x','y','z']`), or +* a `Dict`, a `Set` or an `IntSet`, or * a type: the set of values to pick from is then equivalent to `typemin(S):typemax(S)` for integers (this is not applicable to [`BigInt`](@ref)), and to ``[0, 1)`` for floating point numbers; `S` defaults to [`Float64`](@ref). + +```julia-repl +julia> rand(Int, 2) +2-element Array{Int64,1}: + 1339893410598768192 + 1575814717733606317 + +julia> rand(MersenneTwister(0), Dict(1=>2, 3=>4)) +1=>2 +``` """ @inline rand() = rand(GLOBAL_RNG, CloseOpen) @inline rand(T::Type) = rand(GLOBAL_RNG, T) @@ -276,7 +287,7 @@ rand(r::AbstractArray) = rand(GLOBAL_RNG, r) """ rand!([rng=GLOBAL_RNG], A, [coll]) -Populate the array `A` with random values. If the indexable collection `coll` is specified, +Populate the array `A` with random values. If the collection `coll` is specified, the values are picked randomly from `coll`. This is equivalent to `copy!(A, rand(rng, coll, size(A)))` or `copy!(A, rand(rng, eltype(A), size(A)))` but without allocating a new array. """ @@ -384,6 +395,22 @@ function rand!{T}(r::AbstractRNG, A::AbstractArray{T}) A end +function rand!(r::AbstractRNG, A::AbstractArray, s::Union{Dict,Set,IntSet}) + for i in eachindex(A) + @inbounds A[i] = rand(r, s) + end + A +end + +rand!(A::AbstractArray, s::Union{Dict,Set,IntSet}) = rand!(GLOBAL_RNG, A, s) + +rand(r::AbstractRNG, s::Dict{K,V}, dims::Dims) where {K,V} = rand!(r, Array{Pair{K,V}}(dims), s) +rand(r::AbstractRNG, s::Set{T}, dims::Dims) where {T} = rand!(r, Array{T}(dims), s) +rand(r::AbstractRNG, s::IntSet, dims::Dims) = rand!(r, Array{Int}(dims), s) +rand(r::AbstractRNG, s::Union{Dict,Set,IntSet}, dims::Integer...) = rand(r, s, convert(Dims, dims)) +rand(s::Union{Dict,Set,IntSet}, dims::Integer...) = rand(GLOBAL_RNG, s, dims) +rand(s::Union{Dict,Set,IntSet}, dims::Dims) = rand(GLOBAL_RNG, s, dims) + # MersenneTwister function rand_AbstractArray_Float64!{I<:FloatInterval}(r::MersenneTwister, A::AbstractArray{Float64}, n=length(A), ::Type{I}=CloseOpen) diff --git a/test/random.jl b/test/random.jl index 8a1a918167caf..79bbc7ecb2126 100644 --- a/test/random.jl +++ b/test/random.jl @@ -53,17 +53,6 @@ let mt = MersenneTwister(0) rand(coll, 2, 3) end -# rand using Dict, Set, IntSet -adict = Dict(1=>2, 3=>4, 5=>6) -@test rand(adict) in adict -@test_throws ArgumentError rand(Dict()) -aset = Set(1:10) -@test rand(aset) in aset -@test_throws ArgumentError rand(Set()) -anintset = IntSet(1:10) -@test rand(anintset) in anintset -@test_throws ArgumentError rand(IntSet()) - # randn @test randn(MersenneTwister(42)) == -0.5560268761463861 A = zeros(2, 2) @@ -320,6 +309,11 @@ for rng in ([], [MersenneTwister(0)], [RandomDevice()]) ftypes = [Float16, Float32, Float64] cftypes = [Complex32, Complex64, Complex128, ftypes...] types = [Bool, Char, Base.BitInteger_types..., ftypes...] + collections = [(IntSet(rand(1:100, 20)), Int), + (Set(rand(Int, 20)), Int), + (Dict(zip(rand(Int,10), rand(Int, 10))), Pair{Int,Int}), + (1:100, Int), + (rand(Int, 100), Int)] b2 = big(2) u3 = UInt(3) for f in [rand, randn, randexp] @@ -341,6 +335,20 @@ for rng in ([], [MersenneTwister(0)], [RandomDevice()]) end end end + for (C, T) in collections + a0 = rand(rng..., C) ::T + a1 = rand(rng..., C, 5) ::Vector{T} + a2 = rand(rng..., C, 2, 3) ::Array{T, 2} + a3 = rand!(rng..., Array{T}(5), C) ::Vector{T} + a4 = rand!(rng..., Array{T}(2, 3), C) ::Array{T, 2} + for a in [a0, a1..., a2..., a3..., a4...] + @test a in C + end + end + for C in [1:0, Dict(), Set(), IntSet(), Int[]] + @test_throws ArgumentError rand(rng..., C) + @test_throws ArgumentError rand(rng..., C, 5) + end for f! in [rand!, randn!, randexp!] for T in (f! === rand! ? types : f! === randn! ? cftypes : ftypes) X = T == Bool ? T[0,1] : T[0,1,2] From 15e736977bc94a8a8c0cb02465a00ede2fb71254 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 22 May 2017 16:06:48 -0400 Subject: [PATCH 0936/1534] improve inference of methods with Type{leaftype} parameters --- base/inference.jl | 4 +++- test/inference.jl | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/base/inference.jl b/base/inference.jl index 45c030af11efb..f0606e2e9e01a 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -220,6 +220,8 @@ mutable struct InferenceState if isa(atyp, DataType) && isdefined(atyp, :instance) # replace singleton types with their equivalent Const object atyp = Const(atyp.instance) + elseif isconstType(atyp) + atype = Const(atyp.parameters[1]) else atyp = rewrap_unionall(atyp, linfo.specTypes) end @@ -999,7 +1001,7 @@ function apply_type_tfunc(headtypetype::ANY, args::ANY...) ai = args[i] if isType(ai) aip1 = ai.parameters[1] - canconst &= isleaftype(aip1) + canconst &= (isleaftype(aip1) || aip1 === Union{}) push!(tparams, aip1) elseif isa(ai, Const) && (isa(ai.val, Type) || isa(ai.val, TypeVar) || valid_tparam(ai.val)) push!(tparams, ai.val) diff --git a/test/inference.jl b/test/inference.jl index c03636fb26198..33b5d4ba7d0af 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -828,3 +828,10 @@ end end @test length(code_typed(test_20902, (), optimize = false)) == 1 @test length(code_typed(test_20902, (), optimize = false)) == 1 + +# normalization of arguments with constant Types as parameters +g21771(T) = T +f21771(::Val{U}) where {U} = Tuple{g21771(U)} +@test @inferred(f21771(Val{Int}())) === Tuple{Int} +@test @inferred(f21771(Val{Union{}}())) === Tuple{Union{}} +@test Base.return_types(f21771, typeof((Val{Integer}(),))) == Any[Type{<:Tuple{Integer}}] # apply_type might be overly conservative here From 8ee2e062cabcfb5956386a25cc7c949c0efca1f4 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 22 May 2017 16:13:03 -0400 Subject: [PATCH 0937/1534] apply_type on Type{T} is valid whenever T is valid removes performance bug added by 0292c42c --- base/inference.jl | 9 +++++---- test/inference.jl | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index f0606e2e9e01a..24cb9f0bfcbae 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -1001,7 +1001,7 @@ function apply_type_tfunc(headtypetype::ANY, args::ANY...) ai = args[i] if isType(ai) aip1 = ai.parameters[1] - canconst &= (isleaftype(aip1) || aip1 === Union{}) + canconst &= !has_free_typevars(aip1) push!(tparams, aip1) elseif isa(ai, Const) && (isa(ai.val, Type) || isa(ai.val, TypeVar) || valid_tparam(ai.val)) push!(tparams, ai.val) @@ -1784,6 +1784,10 @@ function abstract_call(f::ANY, fargs::Union{Tuple{},Vector{Any}}, argtypes::Vect else return Any end + if !isa(body, Type) && !isa(body, TypeVar) + return Any + end + has_free_typevars(body) || return body if isa(argtypes[2], Const) tv = argtypes[2].val elseif isa(argtypes[2], PartialTypeVar) @@ -1794,9 +1798,6 @@ function abstract_call(f::ANY, fargs::Union{Tuple{},Vector{Any}}, argtypes::Vect return Any end !isa(tv, TypeVar) && return Any - if !isa(body, Type) && !isa(body, TypeVar) - return Any - end theunion = UnionAll(tv, body) ret = canconst ? abstract_eval_constant(theunion) : Type{theunion} return ret diff --git a/test/inference.jl b/test/inference.jl index 33b5d4ba7d0af..76917a3a4fef7 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -834,4 +834,4 @@ g21771(T) = T f21771(::Val{U}) where {U} = Tuple{g21771(U)} @test @inferred(f21771(Val{Int}())) === Tuple{Int} @test @inferred(f21771(Val{Union{}}())) === Tuple{Union{}} -@test Base.return_types(f21771, typeof((Val{Integer}(),))) == Any[Type{<:Tuple{Integer}}] # apply_type might be overly conservative here +@test @inferred(f21771(Val{Integer}())) === Tuple{Integer} From f97d9e85822b353b7e4b7a665514fab1f556f957 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 22 May 2017 16:08:11 -0400 Subject: [PATCH 0938/1534] handling Base printing of Expr.typ fields not containing a Type this allows printing of the Exprs flowing through inference (which might instead have the field set to something like a Const object) --- base/show.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/show.jl b/base/show.jl index cdf7450f5713f..5cfa8acdd032d 100644 --- a/base/show.jl +++ b/base/show.jl @@ -518,7 +518,7 @@ typeemphasize(io::IO) = get(io, :TYPEEMPHASIZE, false) === true const indent_width = 4 -function show_expr_type(io::IO, ty, emph) +function show_expr_type(io::IO, ty::ANY, emph::Bool) if ty === Function print(io, "::F") elseif ty === Core.IntrinsicFunction @@ -627,7 +627,7 @@ function show_unquoted(io::IO, ex::Slot, ::Int, ::Int) if isa(slottypes, Array) && slotid <= length(slottypes::Array) slottype = slottypes[slotid] # The Slot in assignment can somehow have an Any type - if slottype <: typ + if isa(slottype, Type) && isa(typ, Type) && slottype <: typ typ = slottype end end From 76a30fb4968dccab2adcdc3bb5eee00184df0eba Mon Sep 17 00:00:00 2001 From: Andy Ferris Date: Wed, 10 May 2017 21:42:30 +1000 Subject: [PATCH 0939/1534] remove many unneeded pure annotations Removing actually may enable inference to get a sharper result, since it is no longer being directed to ignore backedges and correctness assumptions Replaces pure annotations in promotion with inline --- base/inference.jl | 4 ++-- base/linalg/uniformscaling.jl | 4 ++-- base/promotion.jl | 41 +++++++++++++++++++---------------- base/sparse/abstractsparse.jl | 2 +- base/sparse/sparsevector.jl | 6 ++--- 5 files changed, 30 insertions(+), 27 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 24cb9f0bfcbae..99507b270f197 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -1865,8 +1865,8 @@ function abstract_call(f::ANY, fargs::Union{Tuple{},Vector{Any}}, argtypes::Vect t = pure_eval_call(f, argtypes, atype, sv) t !== false && return t - if istopfunction(tm, f, :promote_type) || istopfunction(tm, f, :typejoin) - return Type + if istopfunction(tm, f, :typejoin) || f === return_type + return Type # don't try to infer these function edges directly -- it won't actually come up with anything useful elseif length(argtypes) == 2 && istopfunction(tm, f, :typename) return typename_static(argtypes[2]) end diff --git a/base/linalg/uniformscaling.jl b/base/linalg/uniformscaling.jl index 92f1c81434d58..81a3ee1e6b29c 100644 --- a/base/linalg/uniformscaling.jl +++ b/base/linalg/uniformscaling.jl @@ -1,7 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license import Base: copy, ctranspose, getindex, show, transpose, one, zero, inv, - @_pure_meta, hcat, vcat, hvcat + hcat, vcat, hvcat import Base.LinAlg: SingularException struct UniformScaling{T<:Number} @@ -201,7 +201,7 @@ promote_to_arrays(n,k, ::Type{T}, A, B, C) where {T} = (promote_to_arrays_(n[k], T, A), promote_to_arrays_(n[k+1], T, B), promote_to_arrays_(n[k+2], T, C)) promote_to_arrays(n,k, ::Type{T}, A, B, Cs...) where {T} = (promote_to_arrays_(n[k], T, A), promote_to_arrays_(n[k+1], T, B), promote_to_arrays(n,k+2, T, Cs...)...) -promote_to_array_type(A::Tuple{Vararg{Union{AbstractVecOrMat,UniformScaling}}}) = (@_pure_meta; Matrix) +promote_to_array_type(A::Tuple{Vararg{Union{AbstractVecOrMat,UniformScaling}}}) = Matrix for (f,dim,name) in ((:hcat,1,"rows"), (:vcat,2,"cols")) @eval begin diff --git a/base/promotion.jl b/base/promotion.jl index 5c55b3d1e34d3..2972a7da99cce 100644 --- a/base/promotion.jl +++ b/base/promotion.jl @@ -122,14 +122,14 @@ end ## promotion mechanism ## -promote_type() = (@_pure_meta; Bottom) -promote_type(T) = (@_pure_meta; T) -promote_type(T, S, U, V...) = (@_pure_meta; promote_type(T, promote_type(S, U, V...))) +promote_type() = Bottom +promote_type(T) = T +promote_type(T, S, U, V...) = (@_inline_meta; promote_type(T, promote_type(S, U, V...))) -promote_type(::Type{Bottom}, ::Type{Bottom}) = (@_pure_meta; Bottom) -promote_type(::Type{T}, ::Type{T}) where {T} = (@_pure_meta; T) -promote_type(::Type{T}, ::Type{Bottom}) where {T} = (@_pure_meta; T) -promote_type(::Type{Bottom}, ::Type{T}) where {T} = (@_pure_meta; T) +promote_type(::Type{Bottom}, ::Type{Bottom}) = Bottom +promote_type(::Type{T}, ::Type{T}) where {T} = T +promote_type(::Type{T}, ::Type{Bottom}) where {T} = T +promote_type(::Type{Bottom}, ::Type{T}) where {T} = T """ promote_type(type1, type2) @@ -152,7 +152,7 @@ BigFloat ``` """ function promote_type(::Type{T}, ::Type{S}) where {T,S} - @_pure_meta + @_inline_meta # Try promote_rule in both orders. Typically only one is defined, # and there is a fallback returning Bottom below, so the common case is # promote_type(T, S) => @@ -161,26 +161,29 @@ function promote_type(::Type{T}, ::Type{S}) where {T,S} promote_result(T, S, promote_rule(T,S), promote_rule(S,T)) end -promote_rule(T, S) = (@_pure_meta; Bottom) +promote_rule(::Type{<:Any}, ::Type{<:Any}) = Bottom -promote_result(t,s,T,S) = (@_pure_meta; promote_type(T,S)) +promote_result(::Type{<:Any},::Type{<:Any},::Type{T},::Type{S}) where {T,S} = (@_inline_meta; promote_type(T,S)) # If no promote_rule is defined, both directions give Bottom. In that # case use typejoin on the original types instead. -promote_result(::Type{T},::Type{S},::Type{Bottom},::Type{Bottom}) where {T,S} = (@_pure_meta; typejoin(T, S)) +promote_result(::Type{T},::Type{S},::Type{Bottom},::Type{Bottom}) where {T,S} = (@_inline_meta; typejoin(T, S)) promote() = () promote(x) = (x,) function promote(x::T, y::S) where {T,S} + @_inline_meta (convert(promote_type(T,S),x), convert(promote_type(T,S),y)) end -promote_typeof(x) = (@_pure_meta; typeof(x)) -promote_typeof(x, xs...) = (@_pure_meta; promote_type(typeof(x), promote_typeof(xs...))) +promote_typeof(x) = typeof(x) +promote_typeof(x, xs...) = (@_inline_meta; promote_type(typeof(x), promote_typeof(xs...))) function promote(x, y, z) + @_inline_meta (convert(promote_typeof(x,y,z), x), convert(promote_typeof(x,y,z), y), convert(promote_typeof(x,y,z), z)) end function promote(x, y, zs...) + @_inline_meta (convert(promote_typeof(x,y,zs...), x), convert(promote_typeof(x,y,zs...), y), convert(Tuple{Vararg{promote_typeof(x,y,zs...)}}, zs)...) @@ -195,16 +198,16 @@ end # happens, and +(promote(x,y)...) is called again, causing a stack # overflow. function promote_result(::Type{T},::Type{S},::Type{Bottom},::Type{Bottom}) where {T<:Number,S<:Number} - @_pure_meta + @_inline_meta promote_to_supertype(T, S, typejoin(T,S)) end # promote numeric types T and S to typejoin(T,S) if T<:S or S<:T # for example this makes promote_type(Integer,Real) == Real without # promoting arbitrary pairs of numeric types to Number. -promote_to_supertype(::Type{T}, ::Type{T}, ::Type{T}) where {T<:Number} = (@_pure_meta; T) -promote_to_supertype(::Type{T}, ::Type{S}, ::Type{T}) where {T<:Number,S<:Number} = (@_pure_meta; T) -promote_to_supertype(::Type{T}, ::Type{S}, ::Type{S}) where {T<:Number,S<:Number} = (@_pure_meta; S) +promote_to_supertype(::Type{T}, ::Type{T}, ::Type{T}) where {T<:Number} = (@_inline_meta; T) +promote_to_supertype(::Type{T}, ::Type{S}, ::Type{T}) where {T<:Number,S<:Number} = (@_inline_meta; T) +promote_to_supertype(::Type{T}, ::Type{S}, ::Type{S}) where {T<:Number,S<:Number} = (@_inline_meta; S) promote_to_supertype(::Type{T}, ::Type{S}, ::Type) where {T<:Number,S<:Number} = error("no promotion exists for ", T, " and ", S) @@ -304,7 +307,7 @@ minmax(x::Real, y::Real) = minmax(promote(x, y)...) # "Promotion" that takes a function into account and tries to preserve # non-concrete types. These are meant to be used mainly by elementwise # operations, so it is advised against overriding them -_default_type(T::Type) = (@_pure_meta; T) +_default_type(T::Type) = (@_inline_meta; T) if isdefined(Core, :Inference) const _return_type = Core.Inference.return_type @@ -312,7 +315,7 @@ else _return_type(f::ANY, t::ANY) = Any end -promote_op(::Any...) = (@_pure_meta; Any) +promote_op(::Any...) = (@_inline_meta; Any) function promote_op{S}(f, ::Type{S}) @_inline_meta T = _return_type(f, Tuple{_default_type(S)}) diff --git a/base/sparse/abstractsparse.jl b/base/sparse/abstractsparse.jl index 6de3403b5d6de..e17d3be97dbcb 100644 --- a/base/sparse/abstractsparse.jl +++ b/base/sparse/abstractsparse.jl @@ -20,4 +20,4 @@ issparse(S::LinAlg.UnitLowerTriangular{<:Any,<:AbstractSparseMatrix}) = true issparse(S::UpperTriangular{<:Any,<:AbstractSparseMatrix}) = true issparse(S::LinAlg.UnitUpperTriangular{<:Any,<:AbstractSparseMatrix}) = true -indtype(S::AbstractSparseArray{<:Any,Ti}) where {Ti} = (Base.@_pure_meta; Ti) +indtype(S::AbstractSparseArray{<:Any,Ti}) where {Ti} = Ti diff --git a/base/sparse/sparsevector.jl b/base/sparse/sparsevector.jl index dd9e19d9bc729..d4f43de229667 100644 --- a/base/sparse/sparsevector.jl +++ b/base/sparse/sparsevector.jl @@ -2,7 +2,7 @@ ### Common definitions -import Base: scalarmax, scalarmin, sort, find, findnz, @_pure_meta +import Base: scalarmax, scalarmin, sort, find, findnz import Base.LinAlg: promote_to_array_type, promote_to_arrays_ ### The SparseVector @@ -962,8 +962,8 @@ function hvcat(rows::Tuple{Vararg{Int}}, X::_SparseConcatGroup...) end # make sure UniformScaling objects are converted to sparse matrices for concatenation -promote_to_array_type(A::Tuple{Vararg{Union{_SparseConcatGroup,UniformScaling}}}) = (@_pure_meta; SparseMatrixCSC) -promote_to_array_type(A::Tuple{Vararg{Union{_DenseConcatGroup,UniformScaling}}}) = (@_pure_meta; Matrix) +promote_to_array_type(A::Tuple{Vararg{Union{_SparseConcatGroup,UniformScaling}}}) = SparseMatrixCSC +promote_to_array_type(A::Tuple{Vararg{Union{_DenseConcatGroup,UniformScaling}}}) = Matrix promote_to_arrays_(n::Int, ::Type{SparseMatrixCSC}, J::UniformScaling) = sparse(J, n, n) # Concatenations strictly involving un/annotated dense matrices/vectors should yield dense arrays From 1c5cfb0c98004a42d44118ad2899c0ae5b5c10a3 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Mon, 29 May 2017 12:01:27 -0400 Subject: [PATCH 0940/1534] Fix new fallthrough warnings --- src/ast.c | 4 +++- src/method.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/ast.c b/src/ast.c index 9b3b8c124e6a6..ed44ab1509d09 100644 --- a/src/ast.c +++ b/src/ast.c @@ -190,11 +190,13 @@ value_t fl_invoke_julia_macro(fl_context_t *fl_ctx, value_t *args, uint32_t narg if (jl_is_expr(lno) && ((jl_expr_t*)lno)->head == line_sym) { jl_value_t *file = jl_nothing; jl_value_t *line = NULL; - switch (jl_expr_nargs(lno)) { // fall-through is intentional + switch (jl_expr_nargs(lno)) { case 2: file = jl_exprarg(lno, 1); // file + JL_FALLTHROUGH; case 1: line = jl_exprarg(lno, 0); // line + JL_FALLTHROUGH; default: ; } if (line == NULL) diff --git a/src/method.c b/src/method.c index 30e7a702823e2..4cd52b82776e9 100644 --- a/src/method.c +++ b/src/method.c @@ -430,11 +430,13 @@ static void jl_method_set_source(jl_method_t *m, jl_code_info_t *src) } else if (jl_is_expr(st) && ((jl_expr_t*)st)->head == line_sym) { if (!set_lineno) { - switch (jl_expr_nargs(st)) { // fall-through is intentional + switch (jl_expr_nargs(st)) { case 2: m->file = (jl_sym_t*)jl_exprarg(st, 1); + JL_FALLTHROUGH; case 1: m->line = jl_unbox_long(jl_exprarg(st, 0)); + JL_FALLTHROUGH; default: ; } st = jl_nothing; From 9116ec7dd81b0f9670400ee2e66f418f6e493dd6 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Sun, 28 May 2017 21:10:22 -0400 Subject: [PATCH 0941/1534] pass correct paths through to docstrings fix #22105 --- Makefile | 1 + base/boot.jl | 4 +-- base/docs/Docs.jl | 74 +++++++++++++++++++-------------------- base/docs/core.jl | 15 ++++---- base/markdown/Markdown.jl | 20 +++++------ base/precompile.jl | 6 ++-- test/docs.jl | 56 +++++++++++++++++++---------- 7 files changed, 96 insertions(+), 80 deletions(-) diff --git a/Makefile b/Makefile index f88264d5ed4fa..90b566fc828ed 100644 --- a/Makefile +++ b/Makefile @@ -186,6 +186,7 @@ $(build_private_libdir)/%.$(SHLIB_EXT): $(build_private_libdir)/%.o CORE_SRCS := $(addprefix $(JULIAHOME)/, \ base/boot.jl base/coreimg.jl \ + base/docs/core.jl \ base/abstractarray.jl \ base/array.jl \ base/bool.jl \ diff --git a/base/boot.jl b/base/boot.jl index c818bdfd0dead..23e803b81fe06 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -337,7 +337,7 @@ end # docsystem basics macro doc(x...) - atdoc(x...) + atdoc(__source__, x...) end macro __doc__(x) Expr(:escape, Expr(:block, Expr(:meta, :doc), x)) @@ -345,7 +345,7 @@ end macro doc_str(s) Expr(:escape, s) end -atdoc = (str, expr) -> Expr(:escape, expr) +atdoc = (source, str, expr) -> Expr(:escape, expr) atdoc!(λ) = global atdoc = λ diff --git a/base/docs/Docs.jl b/base/docs/Docs.jl index 40bbb74f42729..bd9af3efe71d7 100644 --- a/base/docs/Docs.jl +++ b/base/docs/Docs.jl @@ -169,10 +169,10 @@ _docstr(doc::DocStr, data) = (doc.data = merge(data, doc.data); doc) macro ref(x) binding = bindingexpr(namify(x)) typesig = signature(x) - esc(docexpr(binding, typesig)) + esc(docexpr(__source__, binding, typesig)) end -docexpr(args...) = Expr(:call, docstr, args...) +docexpr(__source__, args...) = Expr(:call, docstr, args...) function formatdoc(d::DocStr) buffer = IOBuffer() @@ -482,26 +482,27 @@ isfield(x) = isexpr(x, :.) && # ========================= """ - Docs.metadata(expr) + Docs.metadata(source, expr) Build a `Dict` expression containing metadata captured from the expression `expr`. Fields that may be included in the returned `Dict`: -- `:path`: String representing the file where `expr` is defined. +- `:path`: Symbol representing the file where `expr` is defined. - `:linenumber`: Linenumber where `expr` is defined. - `:module`: Module where the docstring is defined. - `:fields`: `Dict` of all field docs found in `expr`. Only for concrete types. """ -function metadata(expr) +function metadata(__source__, expr) args = [] # Filename and linenumber of the docstring. - push!(args, :($(Pair)(:path, $(Base).@__FILE__))) - push!(args, :($(Pair)(:linenumber, $(unsafe_load(cglobal(:jl_lineno, Cint)))))) + __file__ = isa(__source__.file, Symbol) ? String(__source__.file) : "" + push!(args, Pair(:path, __file__)) + push!(args, Pair(:linenumber, __source__.line)) # Module in which the docstring is defined. push!(args, :($(Pair)(:module, $(current_module)()))) - # Field docs for concrete types. if isexpr(expr, :type) + # Field docs for concrete types. fields = [] tmp = nothing for each in expr.args[3].args @@ -518,37 +519,36 @@ function metadata(expr) :($(Dict)($(args...))) end -function keyworddoc(str, def) - docstr = esc(docexpr(lazy_iterpolate(str), metadata(def))) - :($(keywords)[$(esc(quot(def.name)))] = $docstr) +function keyworddoc(__source__, str, def) + docstr = esc(docexpr(__source__, lazy_iterpolate(str), metadata(__source__, def))) + return :($(keywords)[$(esc(quot(def.name)))] = $docstr) end -function objectdoc(str, def, expr, sig = :(Union{})) +function objectdoc(__source__, str, def, expr, sig = :(Union{})) binding = esc(bindingexpr(namify(expr))) - docstr = esc(docexpr(lazy_iterpolate(str), metadata(expr))) + docstr = esc(docexpr(__source__, lazy_iterpolate(str), metadata(__source__, expr))) quote $(esc(def)) $(doc!)($binding, $docstr, $(esc(sig))) end end -function calldoc(str, def) +function calldoc(__source__, str, def) args = def.args[2:end] if isempty(args) || all(validcall, args) - objectdoc(str, nothing, def, signature(def)) + objectdoc(__source__, str, nothing, def, signature(def)) else docerror(def) end end validcall(x) = isa(x, Symbol) || isexpr(x, (:(::), :..., :kw, :parameters)) -function moduledoc(meta, def, def′) +function moduledoc(__source__, meta, def, def′) name = namify(def′) docex = Expr(:call, doc!, bindingexpr(name), - docexpr(lazy_iterpolate(meta), metadata(name)) - ) + docexpr(__source__, lazy_iterpolate(meta), metadata(__source__, name))) if def === nothing - esc(:(eval($name, $(quot(docex))))) + esc(:($eval($name, $(quot(docex))))) else def = unblock(def) block = def.args[3].args @@ -562,18 +562,18 @@ function moduledoc(meta, def, def′) end # Shares a single doc, `meta`, between several expressions from the tuple expression `ex`. -function multidoc(meta, ex, define) +function multidoc(__source__, meta, ex, define) out = Expr(:toplevel) - str = docexpr(lazy_iterpolate(meta), metadata(ex)) + str = docexpr(__source__, lazy_iterpolate(meta), metadata(__source__, ex)) ref = Ref{DocStr}() for (n, arg) in enumerate(ex.args) # The first `arg` to be documented needs to also create the docstring for the group. # Subsequent `arg`s just need `ref` to be able to find the docstring without having # to create an entirely new one each. docstr = n === 1 ? :($(ref)[] = $str) : :($(ref)[]) - push!(out.args, :(@doc($docstr, $arg, $define))) + push!(out.args, docm(__source__, docstr, arg, define)) end - esc(out) + return out end """ @@ -649,7 +649,7 @@ isquotedmacrocall(x) = isbasicdoc(x) = isexpr(x, :.) || isa(x, Union{QuoteNode, Symbol}) is_signature(x) = isexpr(x, :call) || (isexpr(x, :(::), 2) && isexpr(x.args[1], :call)) || isexpr(x, :where) -function docm(meta, ex, define = true) +function docm(source::LineNumberNode, meta, ex, define = true) # Some documented expressions may be decorated with macro calls which obscure the actual # expression. Expand the macro calls and remove extra blocks. x = unblock(macroexpand(ex)) @@ -665,7 +665,7 @@ function docm(meta, ex, define = true) # "..." # kw"if", kw"else" # - isa(x, Base.BaseDocs.Keyword) ? keyworddoc(meta, x) : + isa(x, Base.BaseDocs.Keyword) ? keyworddoc(source, meta, x) : # Method / macro definitions and "call" syntax. # @@ -675,9 +675,9 @@ function docm(meta, ex, define = true) # function f end # f(...) # - isexpr(x, FUNC_HEADS) && is_signature(x.args[1]) ? objectdoc(meta, def, x, signature(x)) : - isexpr(x, :function) && !isexpr(x.args[1], :call) ? objectdoc(meta, def, x) : - isexpr(x, :call) ? calldoc(meta, x) : + isexpr(x, FUNC_HEADS) && is_signature(x.args[1]) ? objectdoc(source, meta, def, x, signature(x)) : + isexpr(x, :function) && !isexpr(x.args[1], :call) ? objectdoc(source, meta, def, x) : + isexpr(x, :call) ? calldoc(source, meta, x) : # Type definitions. # @@ -685,7 +685,7 @@ function docm(meta, ex, define = true) # abstract T # bitstype N T # - isexpr(x, [:type, :abstract, :bitstype]) ? objectdoc(meta, def, x) : + isexpr(x, [:type, :abstract, :bitstype]) ? objectdoc(source, meta, def, x) : # "Bindings". Names that resolve to objects with different names, ie. # @@ -693,20 +693,20 @@ function docm(meta, ex, define = true) # T = S # global T = S # - isexpr(x, BINDING_HEADS) && !isexpr(x.args[1], :call) ? objectdoc(meta, def, x) : + isexpr(x, BINDING_HEADS) && !isexpr(x.args[1], :call) ? objectdoc(source, meta, def, x) : # Quoted macrocall syntax. `:@time` / `:(Base.@time)`. - isquotedmacrocall(x) ? objectdoc(meta, def, x) : + isquotedmacrocall(x) ? objectdoc(source, meta, def, x) : # Modules and baremodules. - isexpr(x, :module) ? moduledoc(meta, def, x) : + isexpr(x, :module) ? moduledoc(source, meta, def, x) : # Document several expressions with the same docstring. `a, b, c`. - isexpr(x, :tuple) ? multidoc(meta, x, define) : + isexpr(x, :tuple) ? multidoc(source, meta, x, define) : # Errors generated by calling `macroexpand` are passed back to the call site. isexpr(x, :error) ? esc(x) : # When documenting macro-generated code we look for embedded `@__doc__` calls. __doc__!(meta, x, define) ? esc(x) : # Any "basic" expression such as a bare function or module name or numeric literal. - isbasicdoc(x) ? objectdoc(meta, nothing, x) : + isbasicdoc(x) ? objectdoc(source, meta, nothing, x) : # All other expressions are undocumentable and should be handled on a case-by-case basis # with `@__doc__`. Unbound string literals are also undocumentable since they cannot be @@ -725,9 +725,9 @@ function docerror(ex) :($(error)($txt, "\n")) end -function docm(ex) +function docm(source::LineNumberNode, ex) if isexpr(ex, :->) - docm(ex.args...) + docm(source, ex.args...) elseif haskey(keywords, ex) parsedoc(keywords[ex]) elseif isa(ex, Union{Expr, Symbol}) @@ -764,7 +764,7 @@ function loaddocs(docs) for (mod, ex, str, file, line) in docs data = Dict(:path => string(file), :linenumber => line) doc = docstr(str, data) - docstring = eval(mod, Expr(:body, Expr(:return, Expr(:call, QuoteNode(docm), QuoteNode(doc), QuoteNode(ex), false)))) # expand the real @doc macro now (using a hack because macroexpand takes current-module as an implicit argument) + docstring = eval(mod, Expr(:body, Expr(:return, Expr(:call, QuoteNode(docm), QuoteNode(LineNumberNode(line, file)), QuoteNode(doc), QuoteNode(ex), false)))) # expand the real @doc macro now (using a hack because macroexpand takes current-module as an implicit argument) eval(mod, Expr(:macrocall, unescape, nothing, docstring)) end empty!(docs) diff --git a/base/docs/core.jl b/base/docs/core.jl index 9b8cf34c7f48a..747afab704aa3 100644 --- a/base/docs/core.jl +++ b/base/docs/core.jl @@ -4,12 +4,8 @@ module CoreDocs import ..esc, ..push!, ..getindex, ..current_module, ..unsafe_load, ..Csize_t -function doc!(str, ex) - ptr = unsafe_load(Core.Intrinsics.cglobal(:jl_filename, Ptr{UInt8})) - len = ccall(:strlen, Csize_t, (Ptr{UInt8},), ptr) - file = ccall(:jl_symbol_n, Any, (Ptr{UInt8}, Csize_t), ptr, len) - line = unsafe_load(Core.Intrinsics.cglobal(:jl_lineno, Int32)) # Cint - push!(DOCS, (current_module(), ex, str, file, line)) +function doc!(source::LineNumberNode, str, ex) + push!(DOCS, (current_module(), ex, str, source.file, source.line)) end const DOCS = Array{Any, 1}() @@ -18,11 +14,12 @@ isexpr(x, h) = isa(x, Expr) && x.head === h lazy_iterpolate(s::AbstractString) = Expr(:call, Core.svec, s) lazy_iterpolate(x) = isexpr(x, :string) ? Expr(:call, Core.svec, x.args...) : x -function docm(str, x) - out = esc(Expr(:call, doc!, lazy_iterpolate(str), Expr(:quote, x))) +function docm(source::LineNumberNode, str, x) + out = esc(Expr(:call, doc!, QuoteNode(source), lazy_iterpolate(str), Expr(:quote, x))) isexpr(x, :module) ? Expr(:toplevel, out, esc(x)) : isexpr(x, :call) ? out : Expr(:block, esc(x), out) end -docm(x) = isexpr(x, :->) ? docm(x.args[1], x.args[2].args[2]) : error("invalid '@doc'.") +docm(source::LineNumberNode, x) = + isexpr(x, :->) ? docm(source, x.args[1], x.args[2].args[2]) : error("invalid '@doc'.") end diff --git a/base/markdown/Markdown.jl b/base/markdown/Markdown.jl index d32ae9fa8d983..fff30da7fec3c 100644 --- a/base/markdown/Markdown.jl +++ b/base/markdown/Markdown.jl @@ -37,25 +37,23 @@ function mdexpr(s, flavor = :julia) esc(toexpr(md)) end -function docexpr(s, flavor = :julia) - quote - let md = $(mdexpr(s, flavor)) - md.meta[:path] = @__FILE__ - md.meta[:module] = current_module() - md - end - end +function docexpr(source::LineNumberNode, s, flavor = :julia) + :($doc_str($(mdexpr(s, flavor)), $(QuoteNode(source)))) end macro md_str(s, t...) mdexpr(s, t...) end -doc_str(md, file, mod) = (md.meta[:path] = file; md.meta[:module] = mod; md) -doc_str(md::AbstractString, file, mod) = doc_str(parse(md), file, mod) +function doc_str(md, source::LineNumberNode) + md.meta[:path] = isa(source.file, Symbol) ? String(source.file) : "" + md.meta[:module] = current_module() + md +end +doc_str(md::AbstractString, source::LineNumberNode) = doc_str(parse(md), source) macro doc_str(s::AbstractString, t...) - :($(doc_str)($(mdexpr(s, t...)), $(Base).@__FILE__, $(current_module)())) + docexpr(__source__, s, t...) end function Base.display(d::Base.REPL.REPLDisplay, md::Vector{MD}) diff --git a/base/precompile.jl b/base/precompile.jl index 9bd0f90f30572..5149aed65b332 100644 --- a/base/precompile.jl +++ b/base/precompile.jl @@ -743,7 +743,7 @@ precompile(Tuple{getfield(Base.Docs, Symbol("#@repl")), Base.TTY, Symbol}) precompile(Tuple{typeof(Base.Docs.repl), Base.TTY, Symbol}) precompile(Tuple{typeof(Base.Docs._repl), Symbol}) precompile(Tuple{getfield(Core, Symbol("#@doc")), Symbol}) -precompile(Tuple{typeof(Base.Docs.docm), Symbol}) +precompile(Tuple{typeof(Base.Docs.docm), LineNumberNode, Symbol}) precompile(Tuple{typeof(Base._setindex!), Base.Dict{Any, Any}, Base.Markdown.Config, Symbol, Int64}) precompile(Tuple{Type{Base.Markdown.MD}}) precompile(Tuple{typeof(Base.setindex!), Base.Dict{Any, Any}, Base.Markdown.Config, Symbol}) @@ -1720,8 +1720,8 @@ precompile(Tuple{typeof(Base.Distributed.send_msg), Base.Distributed.Worker, Bas precompile(Tuple{typeof(Base.Distributed.send_msg_), Base.Distributed.Worker, Base.Distributed.MsgHeader, Base.Distributed.RemoteDoMsg, Bool}) precompile(Tuple{typeof(Base.Distributed.terminate_all_workers)}) precompile(Tuple{typeof(Base.Distributed.test_existing_ref), Base.Distributed.Future}) -precompile(Tuple{typeof(Base.Docs.docm), String, Expr}) -precompile(Tuple{typeof(Base.Docs.docm), String, Expr, Bool}) +precompile(Tuple{typeof(Base.Docs.docm), LineNumberNode, String, Expr}) +precompile(Tuple{typeof(Base.Docs.docm), LineNumberNode, String, Expr, Bool}) precompile(Tuple{typeof(Base.Docs.keyworddoc), String, Base.BaseDocs.Keyword}) precompile(Tuple{typeof(Base.Docs.objectdoc), String, Expr, Expr, Expr}) precompile(Tuple{typeof(Base.FastMath.make_fastmath), Expr}) diff --git a/test/docs.jl b/test/docs.jl index d1d65d5615ae7..54bae5861ce2e 100644 --- a/test/docs.jl +++ b/test/docs.jl @@ -481,24 +481,26 @@ end # Issue #16359. Error message for invalid doc syntax. -for each in [ # valid syntax - :(f()), - :(f(x)), - :(f(x::Int)), - :(f(x...)), - :(f(x = 1)), - :(f(; x = 1)) - ] - @test Meta.isexpr(Docs.docm("...", each), :block) -end -for each in [ # invalid syntax - :(f("...")), - :(f(1, 2)), - :(f(() -> ())) - ] - result = Docs.docm("...", each) - @test Meta.isexpr(result, :call) - @test result.args[1] === error +let __source__ = LineNumberNode(0) + for each in [ # valid syntax + :(f()), + :(f(x)), + :(f(x::Int)), + :(f(x...)), + :(f(x = 1)), + :(f(; x = 1)) + ] + @test Meta.isexpr(Docs.docm(__source__, "...", each), :block) + end + for each in [ # invalid syntax + :(f("...")), + :(f(1, 2)), + :(f(() -> ())) + ] + result = Docs.docm(__source__, "...", each) + @test Meta.isexpr(result, :call) + @test result.args[1] === error + end end # Issue #15424. Non-markdown docstrings. @@ -1012,3 +1014,21 @@ end """ ) +# issue #22105 +module I22105 + lineno = @__LINE__ + """foo docs""" + function foo end +end + +let foo_docs = meta(I22105)[@var(I22105.foo)].docs + @test length(foo_docs) === 1 + @test isa(first(foo_docs), Pair) + local docstr = first(foo_docs).second + @test isa(docstr, DocStr) + @test docstr.data[:path] == Base.source_path() + @test docstr.data[:linenumber] == I22105.lineno + 1 + @test docstr.data[:module] === I22105 + @test docstr.data[:typesig] === Union{} + @test docstr.data[:binding] == Binding(I22105, :foo) +end From 753fbef68dd3f09fb0137d6a78606db098119099 Mon Sep 17 00:00:00 2001 From: Martin Holters Date: Tue, 9 May 2017 14:51:25 -0400 Subject: [PATCH 0942/1534] inference: remove hacks around type-system incorrectness infers a missing method (MethodError) as returning `Union{}` and fix tests that were wrong, but not detected previously! --- base/inference.jl | 15 +-------------- test/arrayops.jl | 6 +++--- test/inference.jl | 3 +++ test/strings/basic.jl | 2 +- 4 files changed, 8 insertions(+), 18 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 99507b270f197..7f5e66182ad18 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -36,8 +36,6 @@ struct InferenceParams end end -const UNION_SPLIT_MISMATCH_ERROR = false - # alloc_elim_pass! relies on `Slot_AssignedOnce | Slot_UsedUndef` being # SSA. This should be true now but can break if we start to track conditional # constants. e.g. @@ -1412,10 +1410,6 @@ function abstract_call_gf_by_type(f::ANY, atype::ANY, sv::InferenceState) add_mt_backedge(ftname.mt, argtype, sv) update_valid_age!(min_valid[1], max_valid[1], sv) end - if isempty(applicable) - # TODO: this is needed because type intersection is wrong in some cases - return Any - end #print("=> ", rettype, "\n") return rettype end @@ -1579,13 +1573,6 @@ function return_type_tfunc(argtypes::ANY, vtypes::VarTable, sv::InferenceState) if isa(af_argtype, DataType) && af_argtype <: Tuple argtypes_vec = Any[aft, af_argtype.parameters...] astype = argtypes_to_type(argtypes_vec) - if !(aft ⊑ Builtin) && - _methods_by_ftype(astype, 0, sv.params.world, - UInt[typemin(UInt)], UInt[typemax(UInt)]) !== false - # return_type returns Bottom if no methods match, even though - # inference doesn't necessarily. - return Const(Bottom) - end if isa(aft, Const) rt = abstract_call(aft.val, (), argtypes_vec, vtypes, sv) elseif isconstType(aft) @@ -3590,7 +3577,7 @@ function invoke_NF(argexprs, etype::ANY, atypes, sv, atype_unlimited::ANY, all = false end end - if UNION_SPLIT_MISMATCH_ERROR && all + if all error_label === nothing && (error_label = genlabel(sv)) push!(stmts, GotoNode(error_label.label)) else diff --git a/test/arrayops.jl b/test/arrayops.jl index 480ebca4d89c1..56a06f325628a 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -2082,12 +2082,12 @@ struct F21666{T <: Base.TypeArithmetic} x::Float32 end +Base.TypeArithmetic(::Type{F21666{T}}) where {T} = T() +Base.:+(x::F, y::F) where {F <: F21666} = F(x.x + y.x) +Base.convert(::Type{Float64}, x::F21666) = Float64(x.x) @testset "Exactness of cumsum # 21666" begin # test that cumsum uses more stable algorithm # for types with unknown/rounding arithmetic - Base.TypeArithmetic(::Type{F21666{T}}) where {T} = T - Base.:+(x::F, y::F) where {F <: F21666} = F(x.x + y.x) - Base.convert(::Type{Float64}, x::F21666) = Float64(x.x) # we make v pretty large, because stable algorithm may have a large base case v = zeros(300); v[1] = 2; v[200:end] = eps(Float32) diff --git a/test/inference.jl b/test/inference.jl index 76917a3a4fef7..5f62946ddde72 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -835,3 +835,6 @@ f21771(::Val{U}) where {U} = Tuple{g21771(U)} @test @inferred(f21771(Val{Int}())) === Tuple{Int} @test @inferred(f21771(Val{Union{}}())) === Tuple{Union{}} @test @inferred(f21771(Val{Integer}())) === Tuple{Integer} + +# missing method should be inferred as Union{}, ref https://github.com/JuliaLang/julia/issues/20033#issuecomment-282228948 +@test Base.return_types(f -> f(1), (typeof((x::String) -> x),)) == Any[Union{}] diff --git a/test/strings/basic.jl b/test/strings/basic.jl index 4c155f92b1b27..551d46305d0f8 100644 --- a/test/strings/basic.jl +++ b/test/strings/basic.jl @@ -194,7 +194,7 @@ gstr = GenericString("12") @test ind2chr(gstr,2)==2 # issue #10307 -@test typeof(map(Int16,AbstractString[])) == Vector{Int16} +@test typeof(map(x -> parse(Int16, x), AbstractString[])) == Vector{Int16} for T in [Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128] for i in [typemax(T), typemin(T)] From 7b22adb9e4f152305c91d894f6b81127e2ef070c Mon Sep 17 00:00:00 2001 From: Jeremy Date: Mon, 29 May 2017 16:59:11 -0400 Subject: [PATCH 0943/1534] Fix sparse type parameter (fixes #22110) (#22111) * Fix type sparse type parameter (fixes #22110) * No brackets for singular type param --- base/sparse/sparsematrix.jl | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl index f3986e6b43b06..af40843ddabe9 100644 --- a/base/sparse/sparsematrix.jl +++ b/base/sparse/sparsematrix.jl @@ -292,7 +292,10 @@ function copy!(A::SparseMatrixCSC, B::SparseMatrixCSC) return A end -similar(S::SparseMatrixCSC, Tv::Type = eltype(S)) = SparseMatrixCSC(S.m, S.n, copy(S.colptr), copy(S.rowval), Vector{Tv}(length(S.nzval))) +function similar(S::SparseMatrixCSC, ::Type{Tv} = eltype(S)) where Tv + SparseMatrixCSC(S.m, S.n, copy(S.colptr), copy(S.rowval), Vector{Tv}(length(S.nzval))) +end + function similar(S::SparseMatrixCSC, ::Type{Tv}, ::Type{Ti}) where {Tv,Ti} new_colptr = copy!(similar(S.colptr, Ti), S.colptr) new_rowval = copy!(similar(S.rowval, Ti), S.rowval) @@ -1369,16 +1372,18 @@ julia> spzeros(Float32, 4) ``` """ spzeros(m::Integer, n::Integer) = spzeros(Float64, m, n) -spzeros(Tv::Type, m::Integer, n::Integer) = spzeros(Tv, Int, m, n) -function spzeros(Tv::Type, Ti::Type, m::Integer, n::Integer) +spzeros(::Type{Tv}, m::Integer, n::Integer) where {Tv} = spzeros(Tv, Int, m, n) +function spzeros(::Type{Tv}, ::Type{Ti}, m::Integer, n::Integer) where {Tv, Ti} ((m < 0) || (n < 0)) && throw(ArgumentError("invalid Array dimensions")) SparseMatrixCSC(m, n, ones(Ti, n+1), Vector{Ti}(0), Vector{Tv}(0)) end # de-splatting variant -spzeros(Tv::Type, Ti::Type, sz::Tuple{Integer,Integer}) = spzeros(Tv, Ti, sz[1], sz[2]) +function spzeros(::Type{Tv}, ::Type{Ti}, sz::Tuple{Integer,Integer}) where {Tv, Ti} + spzeros(Tv, Ti, sz[1], sz[2]) +end speye(n::Integer) = speye(Float64, n) -speye(T::Type, n::Integer) = speye(T, n, n) +speye(::Type{T}, n::Integer) where {T} = speye(T, n, n) speye(m::Integer, n::Integer) = speye(Float64, m, n) """ @@ -1418,7 +1423,7 @@ if not specified. `sparse(α*I, m, n)` can be used to efficiently create a sparse multiple `α` of the identity matrix. """ -speye(T::Type, m::Integer, n::Integer) = speye_scaled(T, oneunit(T), m, n) +speye(::Type{T}, m::Integer, n::Integer) where {T} = speye_scaled(T, oneunit(T), m, n) function one(S::SparseMatrixCSC{T}) where T m,n = size(S) @@ -1428,7 +1433,7 @@ end speye_scaled(diag, m::Integer, n::Integer) = speye_scaled(typeof(diag), diag, m, n) -function speye_scaled(T, diag, m::Integer, n::Integer) +function speye_scaled(::Type{T}, diag, m::Integer, n::Integer) where T ((m < 0) || (n < 0)) && throw(ArgumentError("invalid array dimensions")) if iszero(diag) return SparseMatrixCSC(m, n, ones(Int, n+1), Vector{Int}(0), Vector{T}(0)) @@ -1509,7 +1514,7 @@ Base.reducedim_initarray0{R}(A::SparseMatrixCSC, region, v0, ::Type{R}) = fill!(similar(dims->Array{R}(dims), Base.reduced_indices0(A,region)), v0) # General mapreduce -function _mapreducezeros(f, op, T::Type, nzeros::Int, v0) +function _mapreducezeros(f, op, ::Type{T}, nzeros::Int, v0) where T nzeros == 0 && return v0 # Reduce over first zero @@ -1543,9 +1548,9 @@ function Base._mapreduce{T}(f, op, ::Base.IndexCartesian, A::SparseMatrixCSC{T}) end # Specialized mapreduce for +/* -_mapreducezeros(f, ::typeof(+), T::Type, nzeros::Int, v0) = +_mapreducezeros(f, ::typeof(+), ::Type{T}, nzeros::Int, v0) where {T} = nzeros == 0 ? v0 : f(zero(T))*nzeros + v0 -_mapreducezeros(f, ::typeof(*), T::Type, nzeros::Int, v0) = +_mapreducezeros(f, ::typeof(*), ::Type{T}, nzeros::Int, v0) where {T} = nzeros == 0 ? v0 : f(zero(T))^nzeros * v0 function Base._mapreduce{T}(f, op::typeof(*), A::SparseMatrixCSC{T}) From 2ba1c50e3815260e2b1f7488d230b7df2e3c30ac Mon Sep 17 00:00:00 2001 From: ScottPJones Date: Tue, 30 May 2017 01:25:57 -0400 Subject: [PATCH 0944/1534] Fix bug with nul at end when printing BigFloat with >322 precision --- base/printf.jl | 8 +++++--- test/printf.jl | 3 +++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/base/printf.jl b/base/printf.jl index f1f4515d3f798..b743ab6e05529 100644 --- a/base/printf.jl +++ b/base/printf.jl @@ -1128,10 +1128,12 @@ function bigfloat_printf(out, d, flags::String, width::Int, precision::Int, c::C write(fmt, UInt8(0)) printf_fmt = take!(fmt) @assert length(printf_fmt) == fmt_len - bufsiz = length(DIGITS) - 1 - lng = ccall((:mpfr_snprintf,:libmpfr), Int32, (Ptr{UInt8}, Culong, Ptr{UInt8}, Ptr{BigFloat}...), DIGITS, bufsiz, printf_fmt, &d) + bufsiz = length(DIGITS) + lng = ccall((:mpfr_snprintf,:libmpfr), Int32, + (Ptr{UInt8}, Culong, Ptr{UInt8}, Ptr{BigFloat}...), + DIGITS, bufsiz, printf_fmt, &d) lng > 0 || error("invalid printf formatting for BigFloat") - unsafe_write(out, pointer(DIGITS), min(lng,bufsiz)) + unsafe_write(out, pointer(DIGITS), min(lng, bufsiz-1)) return (false, ()) end diff --git a/test/printf.jl b/test/printf.jl index 89d0a7ee7ddf1..2885ddc8df3bd 100644 --- a/test/printf.jl +++ b/test/printf.jl @@ -256,3 +256,6 @@ end # @printf @test_throws ArgumentError eval(:(@printf 1)) + +# Check bug with trailing nul printing BigFloat +@test (@sprintf("%.330f", BigFloat(1)))[end] != '\0' From fdf97c1dfbc1a5b8f9ef2c9d73119a36009fcf4c Mon Sep 17 00:00:00 2001 From: Mus M Date: Tue, 30 May 2017 05:19:53 -0400 Subject: [PATCH 0945/1534] Use where syntax in sparsematrix.jl (#22112) * Use where syntax in sparsematrix.jl * Update sparsematrix.jl * Update sparsematrix.jl --- base/sparse/sparsematrix.jl | 82 ++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl index af40843ddabe9..bb18c058bb2b4 100644 --- a/base/sparse/sparsematrix.jl +++ b/base/sparse/sparsematrix.jl @@ -830,9 +830,9 @@ information. See also: `unchecked_aliasing_permute!` """ -function unchecked_noalias_permute!{Tv,Ti}(X::SparseMatrixCSC{Tv,Ti}, +function unchecked_noalias_permute!(X::SparseMatrixCSC{Tv,Ti}, A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, - q::AbstractVector{<:Integer}, C::SparseMatrixCSC{Tv,Ti}) + q::AbstractVector{<:Integer}, C::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} halfperm!(C, A, q) _computecolptrs_permute!(X, A, q, X.colptr) _distributevals_halfperm!(X, C, p, identity) @@ -850,9 +850,9 @@ for additional information; these methods are identical but for this method's re the additional `workcolptr`, `length(workcolptr) >= A.n + 1`, which enables efficient handling of the source-destination aliasing. """ -function unchecked_aliasing_permute!{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, +function unchecked_aliasing_permute!(A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, q::AbstractVector{<:Integer}, - C::SparseMatrixCSC{Tv,Ti}, workcolptr::Vector{Ti}) + C::SparseMatrixCSC{Tv,Ti}, workcolptr::Vector{Ti}) where {Tv,Ti} halfperm!(C, A, q) _computecolptrs_permute!(A, A, q, workcolptr) _distributevals_halfperm!(A, C, p, identity) @@ -864,8 +864,8 @@ Computes `PAQ`'s column pointers, storing them shifted one position forward in ` `_distributevals_halfperm!` fixes this shift. Saves some work relative to `_computecolptrs_halfperm!` as described in `uncheckednoalias_permute!`'s documentation. """ -function _computecolptrs_permute!{Tv,Ti}(X::SparseMatrixCSC{Tv,Ti}, - A::SparseMatrixCSC{Tv,Ti}, q::AbstractVector{<:Integer}, workcolptr::Vector{Ti}) +function _computecolptrs_permute!(X::SparseMatrixCSC{Tv,Ti}, + A::SparseMatrixCSC{Tv,Ti}, q::AbstractVector{<:Integer}, workcolptr::Vector{Ti}) where {Tv,Ti} # Compute `A[p,q]`'s column counts. Store shifted forward one position in workcolptr. @inbounds for k in 1:A.n workcolptr[k+1] = A.colptr[q[k] + 1] - A.colptr[q[k]] @@ -901,9 +901,9 @@ end Helper method for `permute` and `permute!` methods operating on `SparseMatrixCSC`s. Checks whether row- and column- permutation arguments `p` and `q` are valid permutations. """ -function _checkargs_permutationsvalid_permute!{Ti<:Integer}( +function _checkargs_permutationsvalid_permute!( p::AbstractVector{<:Integer}, pcheckspace::Vector{Ti}, - q::AbstractVector{<:Integer}, qcheckspace::Vector{Ti}) + q::AbstractVector{<:Integer}, qcheckspace::Vector{Ti}) where Ti<:Integer if !_ispermutationvalid_permute!(p, pcheckspace) throw(ArgumentError("row-permutation argument `p` must be a valid permutation")) elseif !_ispermutationvalid_permute!(q, qcheckspace) @@ -1003,42 +1003,42 @@ and `unchecked_aliasing_permute!`. See also: [`permute`](@ref) """ -function permute!{Tv,Ti}(X::SparseMatrixCSC{Tv,Ti}, A::SparseMatrixCSC{Tv,Ti}, - p::AbstractVector{<:Integer}, q::AbstractVector{<:Integer}) +function permute!(X::SparseMatrixCSC{Tv,Ti}, A::SparseMatrixCSC{Tv,Ti}, + p::AbstractVector{<:Integer}, q::AbstractVector{<:Integer}) where {Tv,Ti} _checkargs_sourcecompatdest_permute!(A, X) _checkargs_sourcecompatperms_permute!(A, p, q) C = SparseMatrixCSC(A.n, A.m, Vector{Ti}(A.m + 1), Vector{Ti}(nnz(A)), Vector{Tv}(nnz(A))) _checkargs_permutationsvalid_permute!(p, C.colptr, q, X.colptr) unchecked_noalias_permute!(X, A, p, q, C) end -function permute!{Tv,Ti}(X::SparseMatrixCSC{Tv,Ti}, A::SparseMatrixCSC{Tv,Ti}, +function permute!(X::SparseMatrixCSC{Tv,Ti}, A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, q::AbstractVector{<:Integer}, - C::SparseMatrixCSC{Tv,Ti}) + C::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} _checkargs_sourcecompatdest_permute!(A, X) _checkargs_sourcecompatperms_permute!(A, p, q) _checkargs_sourcecompatworkmat_permute!(A, C) _checkargs_permutationsvalid_permute!(p, C.colptr, q, X.colptr) unchecked_noalias_permute!(X, A, p, q, C) end -function permute!{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, - q::AbstractVector{<:Integer}) +function permute!(A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, + q::AbstractVector{<:Integer}) where {Tv,Ti} _checkargs_sourcecompatperms_permute!(A, p, q) C = SparseMatrixCSC(A.n, A.m, Vector{Ti}(A.m + 1), Vector{Ti}(nnz(A)), Vector{Tv}(nnz(A))) workcolptr = Vector{Ti}(A.n + 1) _checkargs_permutationsvalid_permute!(p, C.colptr, q, workcolptr) unchecked_aliasing_permute!(A, p, q, C, workcolptr) end -function permute!{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, - q::AbstractVector{<:Integer}, C::SparseMatrixCSC{Tv,Ti}) +function permute!(A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, + q::AbstractVector{<:Integer}, C::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} _checkargs_sourcecompatperms_permute!(A, p, q) _checkargs_sourcecompatworkmat_permute!(A, C) workcolptr = Vector{Ti}(A.n + 1) _checkargs_permutationsvalid_permute!(p, C.colptr, q, workcolptr) unchecked_aliasing_permute!(A, p, q, C, workcolptr) end -function permute!{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, +function permute!(A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, q::AbstractVector{<:Integer}, C::SparseMatrixCSC{Tv,Ti}, - workcolptr::Vector{Ti}) + workcolptr::Vector{Ti}) where {Tv,Ti} _checkargs_sourcecompatperms_permute!(A, p, q) _checkargs_sourcecompatworkmat_permute!(A, C) _checkargs_sourcecompatworkcolptr_permute!(A, workcolptr) @@ -1055,8 +1055,8 @@ row count (`length(p) == A.m`). For expert drivers and additional information, see [`permute!`](@ref). """ -function permute{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, - q::AbstractVector{<:Integer}) +function permute(A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, + q::AbstractVector{<:Integer}) where {Tv,Ti} _checkargs_sourcecompatperms_permute!(A, p, q) X = SparseMatrixCSC(A.m, A.n, Vector{Ti}(A.n + 1), Vector{Ti}(nnz(A)), Vector{Tv}(nnz(A))) C = SparseMatrixCSC(A.n, A.m, Vector{Ti}(A.m + 1), Vector{Ti}(nnz(A)), Vector{Tv}(nnz(A))) @@ -1276,8 +1276,8 @@ julia> sprand(rng, Float64, 3, 0.75) [3] = 0.298614 ``` """ -function sprand{T}(r::AbstractRNG, m::Integer, n::Integer, density::AbstractFloat, - rfn::Function, ::Type{T}=eltype(rfn(r,1))) +function sprand(r::AbstractRNG, m::Integer, n::Integer, density::AbstractFloat, + rfn::Function, ::Type{T}=eltype(rfn(r,1))) where T N = m*n N == 0 && return spzeros(T,m,n) N == 1 && return rand(r) <= density ? sparse([1], [1], rfn(r,1)) : spzeros(T,1,1) @@ -1286,8 +1286,8 @@ function sprand{T}(r::AbstractRNG, m::Integer, n::Integer, density::AbstractFloa sparse_IJ_sorted!(I, J, rfn(r,length(I)), m, n, +) # it will never need to combine end -function sprand{T}(m::Integer, n::Integer, density::AbstractFloat, - rfn::Function, ::Type{T}=eltype(rfn(1))) +function sprand(m::Integer, n::Integer, density::AbstractFloat, + rfn::Function, ::Type{T}=eltype(rfn(1))) where T N = m*n N == 0 && return spzeros(T,m,n) N == 1 && return rand() <= density ? sparse([1], [1], rfn(1)) : spzeros(T,1,1) @@ -1468,7 +1468,7 @@ imag(A::SparseMatrixCSC{Tv,Ti}) where {Tv<:Real,Ti} = spzeros(Tv, Ti, A.m, A.n) ## full equality function ==(A1::SparseMatrixCSC, A2::SparseMatrixCSC) - size(A1)!=size(A2) && return false + size(A1) != size(A2) && return false vals1, vals2 = nonzeros(A1), nonzeros(A2) rows1, rows2 = rowvals(A1), rowvals(A2) m, n = size(A1) @@ -1476,7 +1476,7 @@ function ==(A1::SparseMatrixCSC, A2::SparseMatrixCSC) nz1,nz2 = nzrange(A1,i), nzrange(A2,i) j1,j2 = first(nz1), first(nz2) # step through the rows of both matrices at once: - while j1<=last(nz1) && j2<=last(nz2) + while j1 <= last(nz1) && j2 <= last(nz2) r1,r2 = rows1[j1], rows2[j2] if r1==r2 vals1[j1]!=vals2[j2] && return false @@ -1508,9 +1508,9 @@ end # In general, output of sparse matrix reductions will not be sparse, # and computing reductions along columns into SparseMatrixCSC is # non-trivial, so use Arrays for output -Base.reducedim_initarray{R}(A::SparseMatrixCSC, region, v0, ::Type{R}) = +Base.reducedim_initarray(A::SparseMatrixCSC, region, v0, ::Type{R}) where {R} = fill!(similar(dims->Array{R}(dims), Base.reduced_indices(A,region)), v0) -Base.reducedim_initarray0{R}(A::SparseMatrixCSC, region, v0, ::Type{R}) = +Base.reducedim_initarray0(A::SparseMatrixCSC, region, v0, ::Type{R}) where {R} = fill!(similar(dims->Array{R}(dims), Base.reduced_indices0(A,region)), v0) # General mapreduce @@ -1533,7 +1533,7 @@ function _mapreducezeros(f, op, ::Type{T}, nzeros::Int, v0) where T v end -function Base._mapreduce{T}(f, op, ::Base.IndexCartesian, A::SparseMatrixCSC{T}) +function Base._mapreduce(f, op, ::Base.IndexCartesian, A::SparseMatrixCSC{T}) where T z = nnz(A) n = length(A) if z == 0 @@ -1553,7 +1553,7 @@ _mapreducezeros(f, ::typeof(+), ::Type{T}, nzeros::Int, v0) where {T} = _mapreducezeros(f, ::typeof(*), ::Type{T}, nzeros::Int, v0) where {T} = nzeros == 0 ? v0 : f(zero(T))^nzeros * v0 -function Base._mapreduce{T}(f, op::typeof(*), A::SparseMatrixCSC{T}) +function Base._mapreduce(f, op::typeof(*), A::SparseMatrixCSC{T}) where T nzeros = length(A)-nnz(A) if nzeros == 0 # No zeros, so don't compute f(0) since it might throw @@ -1566,7 +1566,7 @@ function Base._mapreduce{T}(f, op::typeof(*), A::SparseMatrixCSC{T}) end # General mapreducedim -function _mapreducerows!{T}(f, op, R::AbstractArray, A::SparseMatrixCSC{T}) +function _mapreducerows!(f, op, R::AbstractArray, A::SparseMatrixCSC{T}) where T colptr = A.colptr rowval = A.rowval nzval = A.nzval @@ -1581,7 +1581,7 @@ function _mapreducerows!{T}(f, op, R::AbstractArray, A::SparseMatrixCSC{T}) R end -function _mapreducecols!{Tv,Ti}(f, op, R::AbstractArray, A::SparseMatrixCSC{Tv,Ti}) +function _mapreducecols!(f, op, R::AbstractArray, A::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} colptr = A.colptr rowval = A.rowval nzval = A.nzval @@ -1600,7 +1600,7 @@ function _mapreducecols!{Tv,Ti}(f, op, R::AbstractArray, A::SparseMatrixCSC{Tv,T R end -function Base._mapreducedim!{T}(f, op, R::AbstractArray, A::SparseMatrixCSC{T}) +function Base._mapreducedim!(f, op, R::AbstractArray, A::SparseMatrixCSC{T}) where T lsiz = Base.check_reducedims(R,A) isempty(A) && return R @@ -1650,7 +1650,7 @@ end # Specialized mapreducedim for + cols to avoid allocating a # temporary array when f(0) == 0 -function _mapreducecols!{Tv,Ti}(f, op::typeof(+), R::AbstractArray, A::SparseMatrixCSC{Tv,Ti}) +function _mapreducecols!(f, op::typeof(+), R::AbstractArray, A::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} nzval = A.nzval m, n = size(A) if length(nzval) == m*n @@ -1690,7 +1690,7 @@ function _mapreducecols!{Tv,Ti}(f, op::typeof(+), R::AbstractArray, A::SparseMat end # findmax/min and indmax/min methods -function _findz{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, rows=1:A.m, cols=1:A.n) +function _findz(A::SparseMatrixCSC{Tv,Ti}, rows=1:A.m, cols=1:A.n) where {Tv,Ti} colptr = A.colptr; rowval = A.rowval; nzval = A.nzval zval = zero(Tv) col = cols[1]; row = 0 @@ -1895,7 +1895,7 @@ function getindex(A::SparseMatrixCSC{Tv,Ti}, I::Range, J::AbstractVector) where return SparseMatrixCSC(nI, nJ, colptrS, rowvalS, nzvalS) end -function getindex_I_sorted{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, I::AbstractVector, J::AbstractVector) +function getindex_I_sorted(A::SparseMatrixCSC{Tv,Ti}, I::AbstractVector, J::AbstractVector) where {Tv,Ti} # Sorted vectors for indexing rows. # Similar to getindex_general but without the transpose trick. (m, n) = size(A) @@ -1915,7 +1915,7 @@ function getindex_I_sorted{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, I::AbstractVector, getindex_I_sorted_linear(A, I, J) end -function getindex_I_sorted_bsearch_A{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, I::AbstractVector, J::AbstractVector) +function getindex_I_sorted_bsearch_A(A::SparseMatrixCSC{Tv,Ti}, I::AbstractVector, J::AbstractVector) where {Tv,Ti} const nI = length(I) const nJ = length(J) @@ -3258,7 +3258,7 @@ function next(d::SpDiagIterator{Tv}, j) where Tv (((r1 > r2) || (A.rowval[r1] != j)) ? zero(Tv) : A.nzval[r1], j+1) end -function trace{Tv}(A::SparseMatrixCSC{Tv}) +function trace(A::SparseMatrixCSC{Tv}) where Tv if size(A,1) != size(A,2) throw(DimensionMismatch("expected square matrix")) end @@ -3269,10 +3269,10 @@ function trace{Tv}(A::SparseMatrixCSC{Tv}) s end -diag{Tv}(A::SparseMatrixCSC{Tv}) = Tv[d for d in SpDiagIterator(A)] +diag(A::SparseMatrixCSC{Tv}) where {Tv} = Tv[d for d in SpDiagIterator(A)] -function diagm{Tv,Ti}(v::SparseMatrixCSC{Tv,Ti}) - if (size(v,1) != 1 && size(v,2) != 1) +function diagm(v::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} + if size(v,1) != 1 && size(v,2) != 1 throw(DimensionMismatch("input should be nx1 or 1xn")) end From 9b51302a295880bbcb1d2f1c6e098722c424d025 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Tue, 30 May 2017 11:30:32 +0200 Subject: [PATCH 0946/1534] Store info in Cholesky type (#21976) * add info field to Cholesky type and delay throwing for non-positive definiteness * comment update [ci skip] * remove comment [ci skip] --- base/linalg/cholesky.jl | 79 ++++++++++++++++++++++++++--------------- base/linalg/dense.jl | 8 +++-- base/linalg/lapack.jl | 4 +-- test/linalg/cholesky.jl | 24 +++++++++---- 4 files changed, 74 insertions(+), 41 deletions(-) diff --git a/base/linalg/cholesky.jl b/base/linalg/cholesky.jl index 0d09fa998028d..2b5c89cad03ef 100644 --- a/base/linalg/cholesky.jl +++ b/base/linalg/cholesky.jl @@ -18,6 +18,11 @@ # through the Hermitian and Symmetric views or exact symmetric or Hermitian elements which # is checked for and an error is thrown if the check fails. +# The internal structure is as follows +# - _chol! returns the factor and info without checking positive definiteness +# - chol/chol! returns the factor and checks for positive definiteness +# - cholfact/cholfact! returns Cholesky with checking positive definiteness + # FixMe? The dispatch below seems overly complicated. One simplification could be to # merge the two Cholesky types into one. It would remove the need for Val completely but # the cost would be extra unnecessary/unused fields for the unpivoted Cholesky and runtime @@ -27,9 +32,12 @@ struct Cholesky{T,S<:AbstractMatrix} <: Factorization{T} factors::S uplo::Char + info::BlasInt end -Cholesky{T}(A::AbstractMatrix{T}, uplo::Symbol) = Cholesky{T,typeof(A)}(A, char_uplo(uplo)) -Cholesky{T}(A::AbstractMatrix{T}, uplo::Char) = Cholesky{T,typeof(A)}(A, uplo) +Cholesky{T}(A::AbstractMatrix{T}, uplo::Symbol, info::BlasInt) = + Cholesky{T,typeof(A)}(A, char_uplo(uplo), info) +Cholesky{T}(A::AbstractMatrix{T}, uplo::Char, info::BlasInt) = + Cholesky{T,typeof(A)}(A, uplo, info) struct CholeskyPivoted{T,S<:AbstractMatrix} <: Factorization{T} factors::S @@ -49,11 +57,11 @@ end ## BLAS/LAPACK element types function _chol!(A::StridedMatrix{<:BlasFloat}, ::Type{UpperTriangular}) C, info = LAPACK.potrf!('U', A) - return @assertposdef UpperTriangular(C) info + return UpperTriangular(C), info end function _chol!(A::StridedMatrix{<:BlasFloat}, ::Type{LowerTriangular}) C, info = LAPACK.potrf!('L', A) - return @assertposdef LowerTriangular(C) info + return LowerTriangular(C), info end ## Non BLAS/LAPACK element types (generic) @@ -64,7 +72,10 @@ function _chol!(A::AbstractMatrix, ::Type{UpperTriangular}) for i = 1:k - 1 A[k,k] -= A[i,k]'A[i,k] end - Akk = _chol!(A[k,k], UpperTriangular) + Akk, info = _chol!(A[k,k], UpperTriangular) + if info != 0 + return UpperTriangular(A), info + end A[k,k] = Akk AkkInv = inv(Akk') for j = k + 1:n @@ -75,7 +86,7 @@ function _chol!(A::AbstractMatrix, ::Type{UpperTriangular}) end end end - return UpperTriangular(A) + return UpperTriangular(A), convert(BlasInt, 0) end function _chol!(A::AbstractMatrix, ::Type{LowerTriangular}) n = checksquare(A) @@ -84,7 +95,10 @@ function _chol!(A::AbstractMatrix, ::Type{LowerTriangular}) for i = 1:k - 1 A[k,k] -= A[k,i]*A[k,i]' end - Akk = _chol!(A[k,k], LowerTriangular) + Akk, info = _chol!(A[k,k], LowerTriangular) + if info != 0 + return LowerTriangular(A), info + end A[k,k] = Akk AkkInv = inv(Akk) for j = 1:k @@ -99,30 +113,33 @@ function _chol!(A::AbstractMatrix, ::Type{LowerTriangular}) end end end - return LowerTriangular(A) + return LowerTriangular(A), convert(BlasInt, 0) end ## Numbers function _chol!(x::Number, uplo) rx = real(x) - if rx != abs(x) - throw(ArgumentError("x must be positive semidefinite")) - end - rxr = sqrt(rx) - convert(promote_type(typeof(x), typeof(rxr)), rxr) + rxr = sqrt(abs(rx)) + rval = convert(promote_type(typeof(x), typeof(rxr)), rxr) + rx == abs(x) ? (rval, convert(BlasInt, 0)) : (rval, convert(BlasInt, 1)) end +chol!(x::Number, uplo) = ((C, info) = _chol!(x, uplo); @assertposdef C info) + non_hermitian_error(f) = throw(ArgumentError("matrix is not symmetric/" * "Hermitian. This error can be avoided by calling $f(Hermitian(A)) " * "which will ignore either the upper or lower triangle of the matrix.")) # chol!. Destructive methods for computing Cholesky factor of real symmetric or Hermitian # matrix -chol!(A::RealHermSymComplexHerm{<:Real,<:StridedMatrix}) = - _chol!(A.uplo == 'U' ? A.data : LinAlg.copytri!(A.data, 'L', true), UpperTriangular) +function chol!(A::RealHermSymComplexHerm{<:Real,<:StridedMatrix}) + C, info = _chol!(A.uplo == 'U' ? A.data : LinAlg.copytri!(A.data, 'L', true), UpperTriangular) + @assertposdef C info +end function chol!(A::StridedMatrix) ishermitian(A) || non_hermitian_error("chol!") - return _chol!(A, UpperTriangular) + C, info = _chol!(A, UpperTriangular) + @assertposdef C info end @@ -184,7 +201,7 @@ julia> chol(16) 4.0 ``` """ -chol(x::Number, args...) = _chol!(x, nothing) +chol(x::Number, args...) = ((C, info) = _chol!(x, nothing); @assertposdef C info) @@ -193,9 +210,11 @@ chol(x::Number, args...) = _chol!(x, nothing) ## No pivoting function cholfact!(A::RealHermSymComplexHerm, ::Type{Val{false}}) if A.uplo == 'U' - Cholesky(_chol!(A.data, UpperTriangular).data, 'U') + CU, info = _chol!(A.data, UpperTriangular) + Cholesky(CU.data, 'U', info) else - Cholesky(_chol!(A.data, LowerTriangular).data, 'L') + CL, info = _chol!(A.data, LowerTriangular) + Cholesky(CL.data, 'L', info) end end @@ -354,14 +373,15 @@ end ## Number function cholfact(x::Number, uplo::Symbol=:U) - xf = fill(chol(x), 1, 1) - Cholesky(xf, uplo) + C, info = _chol!(x, uplo) + xf = fill(C, 1, 1) + Cholesky(xf, uplo, info) end function convert(::Type{Cholesky{T}}, C::Cholesky) where T Cnew = convert(AbstractMatrix{T}, C.factors) - Cholesky{T, typeof(Cnew)}(Cnew, C.uplo) + Cholesky{T, typeof(Cnew)}(Cnew, C.uplo, C.info) end convert(::Type{Factorization{T}}, C::Cholesky{T}) where {T} = C convert(::Type{Factorization{T}}, C::Cholesky) where {T} = convert(Cholesky{T}, C) @@ -386,7 +406,7 @@ convert(::Type{Matrix}, F::CholeskyPivoted) = convert(Array, convert(AbstractArr convert(::Type{Array}, F::CholeskyPivoted) = convert(Matrix, F) full(F::CholeskyPivoted) = convert(AbstractArray, F) -copy(C::Cholesky) = Cholesky(copy(C.factors), C.uplo) +copy(C::Cholesky) = Cholesky(copy(C.factors), C.uplo, C.info) copy(C::CholeskyPivoted) = CholeskyPivoted(copy(C.factors), C.uplo, C.piv, C.rank, C.tol, C.info) size(C::Union{Cholesky, CholeskyPivoted}) = size(C.factors) @@ -417,7 +437,7 @@ show(io::IO, C::Cholesky{<:Any,<:AbstractMatrix}) = (println(io, "$(typeof(C)) with factor:");show(io,C[:UL])) A_ldiv_B!(C::Cholesky{T,<:AbstractMatrix}, B::StridedVecOrMat{T}) where {T<:BlasFloat} = - LAPACK.potrs!(C.uplo, C.factors, B) + @assertposdef LAPACK.potrs!(C.uplo, C.factors, B) C.info function A_ldiv_B!(C::Cholesky{<:Any,<:AbstractMatrix}, B::StridedVecOrMat) if C.uplo == 'L' @@ -465,16 +485,18 @@ function A_ldiv_B!(C::CholeskyPivoted, B::StridedMatrix) end function det(C::Cholesky) + C.info == 0 || throw(PosDefException(C.info)) dd = one(real(eltype(C))) - for i in 1:size(C.factors,1) + @inbounds for i in 1:size(C.factors,1) dd *= real(C.factors[i,i])^2 end dd end function logdet(C::Cholesky) + C.info == 0 || throw(PosDefException(C.info)) dd = zero(real(eltype(C))) - for i in 1:size(C.factors,1) + @inbounds for i in 1:size(C.factors,1) dd += log(real(C.factors[i,i])) end dd + dd # instead of 2.0dd which can change the type @@ -505,10 +527,9 @@ function logdet(C::CholeskyPivoted) end inv!(C::Cholesky{<:BlasFloat,<:StridedMatrix}) = - copytri!(LAPACK.potri!(C.uplo, C.factors), C.uplo, true) + @assertposdef copytri!(LAPACK.potri!(C.uplo, C.factors), C.uplo, true) C.info -inv(C::Cholesky{<:BlasFloat,<:StridedMatrix}) = - inv!(copy(C)) +inv(C::Cholesky{<:BlasFloat,<:StridedMatrix}) = inv!(copy(C)) function inv(C::CholeskyPivoted) chkfullrank(C) diff --git a/base/linalg/dense.jl b/base/linalg/dense.jl index 0f96ffc3ab5dd..c1dc43965e13b 100644 --- a/base/linalg/dense.jl +++ b/base/linalg/dense.jl @@ -770,10 +770,12 @@ function factorize(A::StridedMatrix{T}) where T return UpperTriangular(A) end if herm - try - return cholfact(A) + cf = cholfact(A) + if cf.info == 0 + return cf + else + return factorize(Hermitian(A)) end - return factorize(Hermitian(A)) end if sym return factorize(Symmetric(A)) diff --git a/base/linalg/lapack.jl b/base/linalg/lapack.jl index 14d8f76df34ae..1f9c71488a773 100644 --- a/base/linalg/lapack.jl +++ b/base/linalg/lapack.jl @@ -2963,10 +2963,10 @@ for (posv, potrf, potri, potrs, pstrf, elty, rtyp) in (Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), &uplo, &size(A,1), A, &lda, info) chkargsok(info[]) - #info[1]>0 means the leading minor of order info[i] is not positive definite + #info[] > 0 means the leading minor of order info[] is not positive definite #ordinarily, throw Exception here, but return error code here #this simplifies isposdef! and factorize - return A, info[] + return A, info[] # info stored in Cholesky end # SUBROUTINE DPOTRI( UPLO, N, A, LDA, INFO ) diff --git a/test/linalg/cholesky.jl b/test/linalg/cholesky.jl index e6aabd7f8ff17..b6d92d89ba9f7 100644 --- a/test/linalg/cholesky.jl +++ b/test/linalg/cholesky.jl @@ -4,7 +4,7 @@ debug = false using Base.Test -using Base.LinAlg: BlasComplex, BlasFloat, BlasReal, QRPivoted +using Base.LinAlg: BlasComplex, BlasFloat, BlasReal, QRPivoted, PosDefException n = 10 @@ -60,7 +60,7 @@ for eltya in (Float32, Float64, Complex64, Complex128, BigFloat, Int) apos = apd[1,1] # test chol(x::Number), needs x>0 @test all(x -> x ≈ √apos, cholfact(apos).factors) - @test_throws ArgumentError chol(-one(eltya)) + @test_throws PosDefException chol(-one(eltya)) if eltya <: Real capds = cholfact(apds) @@ -194,10 +194,9 @@ end begin # Cholesky factor of Matrix with non-commutative elements, here 2x2-matrices - X = Matrix{Float64}[0.1*rand(2,2) for i in 1:3, j = 1:3] - L = full(Base.LinAlg._chol!(X*X', LowerTriangular)) - U = full(Base.LinAlg._chol!(X*X', UpperTriangular)) + L = full(Base.LinAlg._chol!(X*X', LowerTriangular)[1]) + U = full(Base.LinAlg._chol!(X*X', UpperTriangular)[1]) XX = full(X*X') @test sum(sum(norm, L*L' - XX)) < eps() @@ -212,8 +211,8 @@ for elty in (Float32, Float64, Complex{Float32}, Complex{Float64}) A = randn(5,5) end A = convert(Matrix{elty}, A'A) - @test full(cholfact(A)[:L]) ≈ full(invoke(Base.LinAlg._chol!, Tuple{AbstractMatrix, Type{LowerTriangular}}, copy(A), LowerTriangular)) - @test full(cholfact(A)[:U]) ≈ full(invoke(Base.LinAlg._chol!, Tuple{AbstractMatrix, Type{UpperTriangular}}, copy(A), UpperTriangular)) + @test full(cholfact(A)[:L]) ≈ full(invoke(Base.LinAlg._chol!, Tuple{AbstractMatrix, Type{LowerTriangular}}, copy(A), LowerTriangular)[1]) + @test full(cholfact(A)[:U]) ≈ full(invoke(Base.LinAlg._chol!, Tuple{AbstractMatrix, Type{UpperTriangular}}, copy(A), UpperTriangular)[1]) end # Test up- and downdates @@ -272,3 +271,14 @@ end # Fail for non-BLAS element types @test_throws ArgumentError cholfact!(Hermitian(rand(Float16, 5,5)), Val{true}) + +@testset "throw for non positive matrix" begin + for T in (Float32, Float64, Complex64, Complex128) + A = T[1 2; 2 1]; B = T[1, 1] + C = cholfact(A) + @show typeof(A), typeof(B), typeof(C.factors) + @test_throws PosDefException C\B + @test_throws PosDefException det(C) + @test_throws PosDefException logdet(C) + end +end From 7c4edd36992924b61272b33aaee5dab5b3001c62 Mon Sep 17 00:00:00 2001 From: Rory Hartong-Redden Date: Tue, 30 May 2017 03:14:27 -0700 Subject: [PATCH 0947/1534] Update documentation.md (#22121) --- doc/src/manual/documentation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/manual/documentation.md b/doc/src/manual/documentation.md index 94499bf241f72..284fe75c49911 100644 --- a/doc/src/manual/documentation.md +++ b/doc/src/manual/documentation.md @@ -110,7 +110,7 @@ As in the example above, we recommend following some simple conventions when wri produce consistent outputs during different Julia sessions. Operating system word size ([`Int32`](@ref) or [`Int64`](@ref)) as well as path separator differences - (`/` or `\`) will also effect the reproducibility of some doctests. + (`/` or `\`) will also affect the reproducibility of some doctests. Note that whitespace in your doctest is significant! The doctest will fail if you misalign the output of pretty-printing an array, for example. From 9b9c93b13dd02602957ce396e57963d38514c2d9 Mon Sep 17 00:00:00 2001 From: Fengyang Wang Date: Tue, 30 May 2017 04:16:29 -0700 Subject: [PATCH 0948/1534] Generate instead of hard coding factorial tables (#22096) * Generate instead of hard coding factorial tables * Preallocate factorial tables * Add tests with old literal tables --- base/combinatorics.jl | 34 +++++++++++----------------------- test/combinatorics.jl | 30 ++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 23 deletions(-) diff --git a/base/combinatorics.jl b/base/combinatorics.jl index 920f6c23d944e..645a9499f1c63 100644 --- a/base/combinatorics.jl +++ b/base/combinatorics.jl @@ -2,29 +2,17 @@ # Factorials -const _fact_table64 = - Int64[1,2,6,24,120,720,5040,40320,362880,3628800,39916800,479001600,6227020800, - 87178291200,1307674368000,20922789888000,355687428096000,6402373705728000, - 121645100408832000,2432902008176640000] - -const _fact_table128 = - UInt128[0x00000000000000000000000000000001, 0x00000000000000000000000000000002, - 0x00000000000000000000000000000006, 0x00000000000000000000000000000018, - 0x00000000000000000000000000000078, 0x000000000000000000000000000002d0, - 0x000000000000000000000000000013b0, 0x00000000000000000000000000009d80, - 0x00000000000000000000000000058980, 0x00000000000000000000000000375f00, - 0x00000000000000000000000002611500, 0x0000000000000000000000001c8cfc00, - 0x0000000000000000000000017328cc00, 0x0000000000000000000000144c3b2800, - 0x00000000000000000000013077775800, 0x00000000000000000000130777758000, - 0x00000000000000000001437eeecd8000, 0x00000000000000000016beecca730000, - 0x000000000000000001b02b9306890000, 0x000000000000000021c3677c82b40000, - 0x0000000000000002c5077d36b8c40000, 0x000000000000003ceea4c2b3e0d80000, - 0x000000000000057970cd7e2933680000, 0x00000000000083629343d3dcd1c00000, - 0x00000000000cd4a0619fb0907bc00000, 0x00000000014d9849ea37eeac91800000, - 0x00000000232f0fcbb3e62c3358800000, 0x00000003d925ba47ad2cd59dae000000, - 0x0000006f99461a1e9e1432dcb6000000, 0x00000d13f6370f96865df5dd54000000, - 0x0001956ad0aae33a4560c5cd2c000000, 0x0032ad5a155c6748ac18b9a580000000, - 0x0688589cc0e9505e2f2fee5580000000, 0xde1bc4d19efcac82445da75b00000000] +const _fact_table64 = Vector{Int64}(20) +_fact_table64[1] = 1 +for n in 2:20 + _fact_table64[n] = _fact_table64[n-1] * n +end + +const _fact_table128 = Vector{UInt128}(34) +_fact_table128[1] = 1 +for n in 2:34 + _fact_table128[n] = _fact_table128[n-1] * n +end function factorial_lookup(n::Integer, table, lim) n < 0 && throw(DomainError()) diff --git a/test/combinatorics.jl b/test/combinatorics.jl index 95fc8c5046ddd..c8fdeedf6df95 100644 --- a/test/combinatorics.jl +++ b/test/combinatorics.jl @@ -67,4 +67,34 @@ end @test factorial(Int32(12)) === Int32(479001600) @test_throws OverflowError factorial(Int32(13)) end + + _fact_table64 = + Int64[1,2,6,24,120,720,5040,40320,362880,3628800,39916800,479001600,6227020800, + 87178291200,1307674368000,20922789888000,355687428096000,6402373705728000, + 121645100408832000,2432902008176640000] + + _fact_table128 = + UInt128[0x00000000000000000000000000000001, 0x00000000000000000000000000000002, + 0x00000000000000000000000000000006, 0x00000000000000000000000000000018, + 0x00000000000000000000000000000078, 0x000000000000000000000000000002d0, + 0x000000000000000000000000000013b0, 0x00000000000000000000000000009d80, + 0x00000000000000000000000000058980, 0x00000000000000000000000000375f00, + 0x00000000000000000000000002611500, 0x0000000000000000000000001c8cfc00, + 0x0000000000000000000000017328cc00, 0x0000000000000000000000144c3b2800, + 0x00000000000000000000013077775800, 0x00000000000000000000130777758000, + 0x00000000000000000001437eeecd8000, 0x00000000000000000016beecca730000, + 0x000000000000000001b02b9306890000, 0x000000000000000021c3677c82b40000, + 0x0000000000000002c5077d36b8c40000, 0x000000000000003ceea4c2b3e0d80000, + 0x000000000000057970cd7e2933680000, 0x00000000000083629343d3dcd1c00000, + 0x00000000000cd4a0619fb0907bc00000, 0x00000000014d9849ea37eeac91800000, + 0x00000000232f0fcbb3e62c3358800000, 0x00000003d925ba47ad2cd59dae000000, + 0x0000006f99461a1e9e1432dcb6000000, 0x00000d13f6370f96865df5dd54000000, + 0x0001956ad0aae33a4560c5cd2c000000, 0x0032ad5a155c6748ac18b9a580000000, + 0x0688589cc0e9505e2f2fee5580000000, 0xde1bc4d19efcac82445da75b00000000] + + for expected in Any[_fact_table64, _fact_table128] + for (n, factn) in enumerate(expected) + @test factorial(oftype(factn, n)) === factn + end + end end From 994f42c3efee2f5a82fef4cd78ed2cad980f47b4 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Tue, 30 May 2017 13:04:39 +0200 Subject: [PATCH 0949/1534] fix base(b, big(0), 0) == "0" --- base/gmp.jl | 32 +++++++++++++------------------- test/bigint.jl | 6 ++++++ 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/base/gmp.jl b/base/gmp.jl index 07926f9865042..f955c7b4a8f5f 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -575,27 +575,21 @@ oct(n::BigInt, pad::Int) = base( 8, n, pad) dec(n::BigInt, pad::Int) = base(10, n, pad) hex(n::BigInt, pad::Int) = base(16, n, pad) -function base(b::Integer, n::BigInt) - b < 0 && return base(Int(b), n, 1, (b>0) & (n.size<0)) - 2 <= b <= 62 || throw(ArgumentError("base must be 2 ≤ base ≤ 62, got $b")) - nd = ndigits(n, b) - str = Base._string_n(n < 0 ? nd+1 : nd) - MPZ.get_str!(str, b, n) -end - -function base(b::Integer, n::BigInt, pad::Integer) +function base(b::Integer, n::BigInt, pad::Integer=1) b < 0 && return base(Int(b), n, pad, (b>0) & (n.size<0)) - s = base(b, n) - buf = IOBuffer() - if n < 0 - s = s[2:end] - write(buf, '-') - end - for i in 1:pad-sizeof(s) # `s` is known to be ASCII, and `length` is slower - write(buf, '0') + 2 <= b <= 62 || throw(ArgumentError("base must be 2 ≤ base ≤ 62, got $b")) + nd1 = ndigits(n, b) + nd = max(nd1, pad) + str = Base._string_n(nd + isneg(n) + 1) # +1 for final '\0' + ptr = pointer(str) + MPZ.get_str!(ptr + nd - nd1, b, n) + for i = (0:nd-nd1-1) + isneg(n) + unsafe_store!(ptr+i, '0' % UInt8) end - write(buf, s) - String(buf) + isneg(n) && unsafe_store!(ptr, '-' % UInt8) + str.len -= 1 # final '\0' + iszero(n) && pad < 1 && (str.len -= 1) + str end function ndigits0zpb(x::BigInt, b::Integer) diff --git a/test/bigint.jl b/test/bigint.jl index 0e4650d1d7d1a..1ef6b713e56eb 100644 --- a/test/bigint.jl +++ b/test/bigint.jl @@ -339,6 +339,12 @@ let padding = 4, low = big(4), high = big(2^20) @test hex(-high, padding) == "-100000" end +# respect 0-padding on big(0) +for f in (bin, oct, dec, hex) + @test f(big(0), 0) == "" +end +@test base(rand(2:62), big(0), 0) == "" + @test isqrt(big(4)) == 2 @test isqrt(big(5)) == 2 From ca22001c01051374f3bd73aa26342f84a52d3e60 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Mon, 29 May 2017 20:37:45 -0400 Subject: [PATCH 0950/1534] Test if selfmem can write to RX page Also open only one `/proc/self/mem`. There are apparently two instances of `RTDyldMemoryManagerJL` created. Fix #22082 --- src/cgmemmgr.cpp | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/src/cgmemmgr.cpp b/src/cgmemmgr.cpp index ea59a6a3c42c7..6b2f43ebffdcf 100644 --- a/src/cgmemmgr.cpp +++ b/src/cgmemmgr.cpp @@ -264,9 +264,9 @@ static void *alloc_shared_page(size_t size, size_t *id, bool exec) #ifdef _OS_LINUX_ // Using `/proc/self/mem`, A.K.A. Keno's remote memory manager. -static int self_mem_fd = -1; - -static int init_self_mem() +// Do not call this directly. +// Use `get_self_mem_fd` which has a guard to call this only once. +static int _init_self_mem() { struct utsname kernel; uname(&kernel); @@ -288,22 +288,34 @@ static int init_self_mem() return -1; fcntl(fd, F_SETFD, FD_CLOEXEC); #endif - // buffer to check if write works; - volatile uint64_t buff = 0; - uint64_t v = 0x12345678; - int ret = pwrite(fd, (void*)&v, sizeof(uint64_t), (uintptr_t)&buff); - if (ret != sizeof(uint64_t) || buff != 0x12345678) { + + // Check if we can write to a RX page + void *test_pg = mmap(nullptr, jl_page_size, PROT_READ | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + // We can ignore this though failure to allocate executable memory would be a bigger problem. + assert(test_pg != MAP_FAILED && "Cannot allocate executable memory"); + + const uint64_t v = 0xffff000012345678u; + int ret = pwrite(fd, (const void*)&v, sizeof(uint64_t), (uintptr_t)test_pg); + if (ret != sizeof(uint64_t) || *(volatile uint64_t*)test_pg != v) { + munmap(test_pg, jl_page_size); close(fd); return -1; } - self_mem_fd = fd; + munmap(test_pg, jl_page_size); + return fd; +} + +static int get_self_mem_fd() +{ + static int fd = _init_self_mem(); return fd; } static void write_self_mem(void *dest, void *ptr, size_t size) { while (size > 0) { - ssize_t ret = pwrite(self_mem_fd, ptr, size, (uintptr_t)dest); + ssize_t ret = pwrite(get_self_mem_fd(), ptr, size, (uintptr_t)dest); if ((size_t)ret == size) return; if (ret == -1 && (errno == EAGAIN || errno == EINTR)) @@ -657,7 +669,7 @@ class SelfMemAllocator : public ROAllocator { : ROAllocator(), temp_buff() { - assert(self_mem_fd != -1); + assert(get_self_mem_fd() != -1); } void finalize() override { @@ -717,7 +729,7 @@ class RTDyldMemoryManagerJL : public SectionMemoryManager { code_allocated(false) { #ifdef _OS_LINUX_ - if (!ro_alloc && init_self_mem() != -1) { + if (!ro_alloc && get_self_mem_fd() != -1) { ro_alloc.reset(new SelfMemAllocator()); exe_alloc.reset(new SelfMemAllocator()); } From 6698ac40cc9023e55bdd14b817bf9177a23fe087 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 30 May 2017 12:59:17 -0400 Subject: [PATCH 0951/1534] inference: fix some cases of invalid age range updates ref #21653 --- base/REPLCompletions.jl | 2 +- base/inference.jl | 5 +++-- base/reflection.jl | 5 ++--- test/inference.jl | 5 +++++ 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/base/REPLCompletions.jl b/base/REPLCompletions.jl index f5626e5f5c57a..d58aebe5f9832 100644 --- a/base/REPLCompletions.jl +++ b/base/REPLCompletions.jl @@ -282,7 +282,7 @@ function get_type_call(expr::Expr) found ? push!(args, typ) : push!(args, Any) end # use _methods_by_ftype as the function is supplied as a type - world = typemax(UInt) + world = ccall(:jl_get_world_counter, UInt, ()) mt = Base._methods_by_ftype(Tuple{ft, args...}, -1, world) length(mt) == 1 || return (Any, false) m = first(mt) diff --git a/base/inference.jl b/base/inference.jl index 7f5e66182ad18..8ea12fd2b2eac 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -5415,7 +5415,8 @@ end # especially try to make sure any recursive and leaf functions have concrete signatures, # since we won't be able to specialize & infer them at runtime -let fs = Any[typeinf_ext, typeinf, typeinf_edge, occurs_outside_getfield, pure_eval_call] +let fs = Any[typeinf_ext, typeinf, typeinf_edge, occurs_outside_getfield, pure_eval_call], + world = ccall(:jl_get_world_counter, UInt, ()) for x in t_ffunc_val push!(fs, x[3]) end @@ -5434,7 +5435,7 @@ let fs = Any[typeinf_ext, typeinf, typeinf_edge, occurs_outside_getfield, pure_e typ[i] = typ[i].ub end end - typeinf_type(m[3], Tuple{typ...}, m[2], true, InferenceParams(typemax(UInt))) + typeinf_type(m[3], Tuple{typ...}, m[2], true, InferenceParams(world)) end end end diff --git a/base/reflection.jl b/base/reflection.jl index eb8e279e11977..e322a22dfe020 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -763,7 +763,6 @@ function func_for_method_checked(m::Method, types::ANY) return m end - """ code_typed(f, types; optimize=true) @@ -778,7 +777,7 @@ function code_typed(f::ANY, types::ANY=Tuple; optimize=true) end types = to_tuple_type(types) asts = [] - world = typemax(UInt) + world = ccall(:jl_get_world_counter, UInt, ()) params = Core.Inference.InferenceParams(world) for x in _methods(f, types, -1, world) meth = func_for_method_checked(x[3], types) @@ -796,7 +795,7 @@ function return_types(f::ANY, types::ANY=Tuple) end types = to_tuple_type(types) rt = [] - world = typemax(UInt) + world = ccall(:jl_get_world_counter, UInt, ()) params = Core.Inference.InferenceParams(world) for x in _methods(f, types, -1, world) meth = func_for_method_checked(x[3], types) diff --git a/test/inference.jl b/test/inference.jl index 5f62946ddde72..61d283c73368c 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -838,3 +838,8 @@ f21771(::Val{U}) where {U} = Tuple{g21771(U)} # missing method should be inferred as Union{}, ref https://github.com/JuliaLang/julia/issues/20033#issuecomment-282228948 @test Base.return_types(f -> f(1), (typeof((x::String) -> x),)) == Any[Union{}] + +# issue #21653 +# ensure that we don't try to resolve cycles using uncached edges +f21653() = f21653() +@test code_typed(f21653, Tuple{}, optimize=false)[1] isa Pair{CodeInfo, typeof(Union{})} From 95677b061cc654e911f2cca1727db238a27ac67a Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 30 May 2017 17:49:06 -0400 Subject: [PATCH 0952/1534] prevent Docs.apropos from breaking on random stuff interpolated into docs --- base/docs/utils.jl | 1 + test/docs.jl | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/base/docs/utils.jl b/base/docs/utils.jl index 4a3a8b1e7a479..895edf349e5be 100644 --- a/base/docs/utils.jl +++ b/base/docs/utils.jl @@ -414,6 +414,7 @@ Strip all Markdown markup from x, leaving the result in plain text. Used internally by apropos to make docstrings containing more than one markdown element searchable. """ +stripmd(x::ANY) = string(x) # for random objects interpolated into the docstring stripmd(x::AbstractString) = x # base case stripmd(x::Void) = " " stripmd(x::Vector) = string(map(stripmd, x)...) diff --git a/test/docs.jl b/test/docs.jl index 54bae5861ce2e..eadd59e65cad1 100644 --- a/test/docs.jl +++ b/test/docs.jl @@ -34,6 +34,20 @@ macro macro_doctest() end @test (@doc @macro_doctest) !== nothing +# test that random stuff interpolated into docstrings doesn't break search or other methods here +doc""" +break me: + + code + +$:asymbol # a symbol +$1 # a number +$string # a function +$$latex literal$$ +### header! +""" +function break_me_docs end + # issue #11548 module ModuleMacroDoc From 8e86be3e517f3b14064b93b9326e19202085f09f Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Mon, 22 May 2017 12:55:57 +0200 Subject: [PATCH 0953/1534] make flipsign(typemin(T), -1) == typemin(T) consistently Also, make `flipsign(::Bool, y)` typestable, and add `flipsign(x, Unsigned) = +x`. --- base/int.jl | 1 + base/number.jl | 4 ++-- base/sysimg.jl | 6 ++++++ test/int.jl | 21 ++++++++++++++++++--- 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/base/int.jl b/base/int.jl index bbbe846976f85..19b65d5ea8f94 100644 --- a/base/int.jl +++ b/base/int.jl @@ -71,6 +71,7 @@ signbit(x::Integer) = x < 0 signbit(x::Unsigned) = false flipsign(x::T, y::T) where {T<:BitSigned} = flipsign_int(x, y) +flipsign(x::BitSigned, y::BitSigned) = flipsign_int(promote(x, y)...) % typeof(x) flipsign(x::Signed, y::Signed) = convert(typeof(x), flipsign(promote_noncircular(x, y)...)) flipsign(x::Signed, y::Float16) = flipsign(x, bitcast(Int16, y)) diff --git a/base/number.jl b/base/number.jl index d34f3ba10a438..09cb9f67d74ca 100644 --- a/base/number.jl +++ b/base/number.jl @@ -93,8 +93,8 @@ abs2(x::Real) = x*x Return `x` with its sign flipped if `y` is negative. For example `abs(x) = flipsign(x,x)`. """ -flipsign(x::Real, y::Real) = ifelse(signbit(y), -x, x) -copysign(x::Real, y::Real) = ifelse(signbit(x)!=signbit(y), -x, x) +flipsign(x::Real, y::Real) = ifelse(signbit(y), -x, +x) # the + is for type-stability on Bool +copysign(x::Real, y::Real) = ifelse(signbit(x)!=signbit(y), -x, +x) conj(x::Real) = x transpose(x::Number) = x diff --git a/base/sysimg.jl b/base/sysimg.jl index 11a239a5f93bd..4ffc8f8ec29a2 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -286,6 +286,12 @@ function deepcopy_internal end # BigInts and BigFloats include("gmp.jl") importall .GMP + +for T in [Signed, Integer, BigInt, Float32, Float64, Real, Complex, Rational] + @eval flipsign(x::$T, ::Unsigned) = +x + @eval copysign(x::$T, ::Unsigned) = +x +end + include("mpfr.jl") importall .MPFR big(n::Integer) = convert(BigInt,n) diff --git a/test/int.jl b/test/int.jl index ad2e9a1e8f1f2..4108960fc6fc7 100644 --- a/test/int.jl +++ b/test/int.jl @@ -17,16 +17,31 @@ for y in (4, Float32(4), 4.0, big(4.0)) @test copysign(-3, y) == 3 end -# Result type must be type of first argument -for T in (Base.BitInteger_types..., BigInt, +# Result type must be type of first argument, except for Bool +for U in (Base.BitInteger_types..., BigInt, Rational{Int}, Rational{BigInt}, Float16, Float32, Float64) - for U in (Base.BitInteger_types..., BigInt, + for T in (Base.BitInteger_types..., BigInt, Rational{Int}, Rational{BigInt}, Float16, Float32, Float64) @test typeof(copysign(T(3), U(4))) === T @test typeof(flipsign(T(3), U(4))) === T end + # Bool promotes to Int + U <: Unsigned && continue + for x in [true, false] + @test flipsign(x, U(4)) === Int(x) + @test flipsign(x, U(-1)) === -Int(x) + @test copysign(x, U(4)) === Int(x) + @test copysign(x, U(-1)) === -Int(x) + end +end + +@testset "flipsign/copysign(typemin($T), -1)" for T in Base.BitInteger_types + for U in (Base.BitSigned_types..., BigInt, Float16, Float32, Float64) + @test flipsign(typemin(T), U(-1)) == typemin(T) + @test copysign(typemin(T), U(-1)) == typemin(T) + end end for s1 in (-1,+1), s2 in (-1,+1) From 5ecbae0563a219a35a4babb81129070a670121ca Mon Sep 17 00:00:00 2001 From: Amit Murthy Date: Wed, 31 May 2017 08:13:06 +0530 Subject: [PATCH 0954/1534] NEWS.md update : move getpeername to the correct section (#22141) --- NEWS.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/NEWS.md b/NEWS.md index 787a916a6c6d8..75dc3d9ff86e9 100644 --- a/NEWS.md +++ b/NEWS.md @@ -3,9 +3,6 @@ Julia v0.7.0 Release Notes New language features --------------------- - * `getpeername` on a `TCPSocket` returns the address and port of the remote - endpoint of the TCP connection ([#21825]). - Language changes ---------------- @@ -53,6 +50,9 @@ Library improvements method can be opened in an editor by entering the corresponding number in the REPL and pressing `^Q` ([#22007]). + * `getpeername` on a `TCPSocket` returns the address and port of the remote + endpoint of the TCP connection ([#21825]). + Compiler/Runtime improvements ----------------------------- From 422a7436653caa0cbbb5416d70711494204f8835 Mon Sep 17 00:00:00 2001 From: Mus M Date: Tue, 30 May 2017 23:05:28 -0400 Subject: [PATCH 0955/1534] make libllvm version const --- base/version.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/version.jl b/base/version.jl index 213f603ec53f8..08938b3f48af9 100644 --- a/base/version.jl +++ b/base/version.jl @@ -223,7 +223,7 @@ catch e VersionNumber(0) end -libllvm_version = convert(VersionNumber, libllvm_version_string) +const libllvm_version = convert(VersionNumber, libllvm_version_string) function banner(io::IO = STDOUT) if GIT_VERSION_INFO.tagged_commit From e839b0e20a70ff043f3548d0401b1f2900c913b9 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 30 May 2017 15:58:49 -0400 Subject: [PATCH 0956/1534] eliminate another turing machines from reshapedarray --- base/reshapedarray.jl | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/base/reshapedarray.jl b/base/reshapedarray.jl index 85c45e9e8739c..0684752fd55e9 100644 --- a/base/reshapedarray.jl +++ b/base/reshapedarray.jl @@ -96,7 +96,8 @@ reshape(parent::AbstractArray, dims::Int...) = reshape(parent, dims) reshape(parent::AbstractArray, dims::Union{Int,Colon}...) = reshape(parent, dims) reshape(parent::AbstractArray, dims::Tuple{Vararg{Union{Int,Colon}}}) = _reshape(parent, _reshape_uncolon(parent, dims)) @inline function _reshape_uncolon(A, dims) - pre, post = _split_at_colon((), dims...) + pre = _before_colon(dims...) + post = _after_colon(dims...) if any(d -> d isa Colon, post) throw(DimensionMismatch("new dimensions $(dims) may have at most one omitted dimension specified by Colon()")) end @@ -104,9 +105,11 @@ reshape(parent::AbstractArray, dims::Tuple{Vararg{Union{Int,Colon}}}) = _reshape remainder == 0 || _throw_reshape_colon_dimmismatch(A, dims) (pre..., sz, post...) end -@inline _split_at_colon(pre, dim::Any, tail...) = _split_at_colon((pre..., dim), tail...) -@inline _split_at_colon(pre, ::Colon, tail...) = (pre, tail) -_throw_reshape_colon_dimmismatch(A, dims) = +@inline _before_colon(dim::Any, tail...) = (dim, _before_colon(tail...)...) +@inline _before_colon(dim::Colon, tail...) = () +@inline _after_colon(dim::Any, tail...) = _after_colon(tail...) +@inline _after_colon(dim::Colon, tail...) = tail +@noinline _throw_reshape_colon_dimmismatch(A, dims) = throw(DimensionMismatch("array size $(length(A)) must be divisible by the product of the new dimensions $dims")) reshape(parent::AbstractArray{T,N}, ndims::Type{Val{N}}) where {T,N} = parent From 8ea4f16eb84562836be95e2a558c989bc47c9887 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 15 May 2017 17:56:42 -0400 Subject: [PATCH 0957/1534] reflection: move signature union-splitting logic under the control of inference --- base/inference.jl | 290 +++++++++++++++++++++++++++------------------ base/reflection.jl | 37 ------ 2 files changed, 175 insertions(+), 152 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 7f5e66182ad18..4915139ea24fc 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -1253,8 +1253,34 @@ end #### recursing into expression #### +# take a Tuple where one or more parameters are Unions +# and return an array such that those Unions are removed +# and `Union{return...} == ty` +function switchtupleunion(ty::ANY) + tparams = (unwrap_unionall(ty)::DataType).parameters + return _switchtupleunion(Any[tparams...], length(tparams), [], ty) +end + +function _switchtupleunion(t::Vector{Any}, i::Int, tunion::Vector{Any}, origt::ANY) + if i == 0 + tpl = rewrap_unionall(Tuple{t...}, origt) + push!(tunion, tpl) + else + ti = t[i] + if isa(ti, Union) + for ty in uniontypes(ti::Union) + t[i] = ty + _switchtupleunion(t, i - 1, tunion, origt) + end + t[i] = ti + else + _switchtupleunion(t, i - 1, tunion, origt) + end + end + return tunion +end + function abstract_call_gf_by_type(f::ANY, atype::ANY, sv::InferenceState) - tm = _topmod(sv) # don't consider more than N methods. this trades off between # compiler performance and generated code performance. # typically, considering many methods means spending lots of time @@ -1282,136 +1308,165 @@ function abstract_call_gf_by_type(f::ANY, atype::ANY, sv::InferenceState) end min_valid = UInt[typemin(UInt)] max_valid = UInt[typemax(UInt)] - applicable = _methods_by_ftype(argtype, sv.params.MAX_METHODS, sv.params.world, min_valid, max_valid) - rettype = Bottom - if applicable === false - # this means too many methods matched - return Any + splitunions = 1 < countunionsplit(argtypes) <= sv.params.MAX_UNION_SPLITTING + if splitunions + splitsigs = switchtupleunion(argtype) + applicable = Any[] + for sig_n in splitsigs + xapplicable = _methods_by_ftype(sig_n, sv.params.MAX_METHODS, sv.params.world, min_valid, max_valid) + xapplicable === false && return Any + append!(applicable, xapplicable) + end + else + applicable = _methods_by_ftype(argtype, sv.params.MAX_METHODS, sv.params.world, min_valid, max_valid) + if applicable === false + # this means too many methods matched + return Any + end end applicable = applicable::Array{Any,1} + napplicable = length(applicable) fullmatch = false - for (m::SimpleVector) in applicable - sig = m[1] - sigtuple = unwrap_unionall(sig)::DataType - method = m[3]::Method - sparams = m[2]::SimpleVector - recomputesvec = false + rettype = Bottom + for i in 1:napplicable + match = applicable[i]::SimpleVector + method = match[3]::Method if !fullmatch && (argtype <: method.sig) fullmatch = true end + sig = match[1] + sigtuple = unwrap_unionall(sig)::DataType + splitunions = false + # TODO: splitunions = 1 < countunionsplit(sigtuple.parameters) * napplicable <= sv.params.MAX_UNION_SPLITTING + # currently this triggers a bug in inference recursion detection + if splitunions + splitsigs = switchtupleunion(sig) + for sig_n in splitsigs + rt = abstract_call_method(method, f, sig_n, svec(), sv) + rettype = tmerge(rettype, rt) + rettype === Any && break + end + rettype === Any && break + else + rt = abstract_call_method(method, f, sig, match[2]::SimpleVector, sv) + rettype = tmerge(rettype, rt) + rettype === Any && break + end + end + if !(fullmatch || rettype === Any) + # also need an edge to the method table in case something gets + # added that did not intersect with any existing method + add_mt_backedge(ftname.mt, argtype, sv) + update_valid_age!(min_valid[1], max_valid[1], sv) + end + #print("=> ", rettype, "\n") + return rettype +end - # limit argument type tuple growth - msig = unwrap_unionall(method.sig) - lsig = length(msig.parameters) - ls = length(sigtuple.parameters) - td = type_depth(sig) - mightlimitlength = ls > lsig + 1 - mightlimitdepth = td > 2 - limitlength = false - if mightlimitlength || mightlimitdepth - # TODO: FIXME: this heuristic depends on non-local state making type-inference unpredictable - cyclei = 0 - infstate = sv - while infstate !== nothing - infstate = infstate::InferenceState - if isdefined(infstate.linfo, :def) && method === infstate.linfo.def - if mightlimitlength && ls > length(unwrap_unionall(infstate.linfo.specTypes).parameters) - limitlength = true - end - if mightlimitdepth && td > type_depth(infstate.linfo.specTypes) - # impose limit if we recur and the argument types grow beyond MAX_TYPE_DEPTH - if td > MAX_TYPE_DEPTH - sig = limit_type_depth(sig, 0) - sigtuple = unwrap_unionall(sig) - recomputesvec = true - break - else - p1, p2 = sigtuple.parameters, unwrap_unionall(infstate.linfo.specTypes).parameters - if length(p2) == ls - limitdepth = false - newsig = Vector{Any}(ls) - for i = 1:ls - if p1[i] <: Function && type_depth(p1[i]) > type_depth(p2[i]) && - isa(p1[i],DataType) - # if a Function argument is growing (e.g. nested closures) - # then widen to the outermost function type. without this - # inference fails to terminate on do_quadgk. - newsig[i] = p1[i].name.wrapper - limitdepth = true - else - newsig[i] = limit_type_depth(p1[i], 1) - end - end - if limitdepth - sigtuple = Tuple{newsig...} - sig = rewrap_unionall(sigtuple, sig) - recomputesvec = true - break +function abstract_call_method(method::Method, f::ANY, sig::ANY, sparams::SimpleVector, sv::InferenceState) + sigtuple = unwrap_unionall(sig)::DataType + recomputesvec = false + + # limit argument type tuple growth + msig = unwrap_unionall(method.sig) + lsig = length(msig.parameters) + ls = length(sigtuple.parameters) + td = type_depth(sig) + mightlimitlength = ls > lsig + 1 + mightlimitdepth = td > 2 + limitlength = false + if mightlimitlength || mightlimitdepth + # TODO: FIXME: this heuristic depends on non-local state making type-inference unpredictable + cyclei = 0 + infstate = sv + while infstate !== nothing + infstate = infstate::InferenceState + if isdefined(infstate.linfo, :def) && method === infstate.linfo.def + if mightlimitlength && ls > length(unwrap_unionall(infstate.linfo.specTypes).parameters) + limitlength = true + end + if mightlimitdepth && td > type_depth(infstate.linfo.specTypes) + # impose limit if we recur and the argument types grow beyond MAX_TYPE_DEPTH + if td > MAX_TYPE_DEPTH + sig = limit_type_depth(sig, 0) + sigtuple = unwrap_unionall(sig) + recomputesvec = true + break + else + p1, p2 = sigtuple.parameters, unwrap_unionall(infstate.linfo.specTypes).parameters + if length(p2) == ls + limitdepth = false + newsig = Vector{Any}(ls) + for i = 1:ls + if p1[i] <: Function && type_depth(p1[i]) > type_depth(p2[i]) && + isa(p1[i],DataType) + # if a Function argument is growing (e.g. nested closures) + # then widen to the outermost function type. without this + # inference fails to terminate on do_quadgk. + newsig[i] = p1[i].name.wrapper + limitdepth = true + else + newsig[i] = limit_type_depth(p1[i], 1) end end + if limitdepth + sigtuple = Tuple{newsig...} + sig = rewrap_unionall(sigtuple, sig) + recomputesvec = true + break + end end end end - # iterate through the cycle before walking to the parent - if cyclei < length(infstate.callers_in_cycle) - cyclei += 1 - infstate = infstate.callers_in_cycle[cyclei] - else - cyclei = 0 - infstate = infstate.parent - end end - end - - # limit length based on size of definition signature. - # for example, given function f(T, Any...), limit to 3 arguments - # instead of the default (MAX_TUPLETYPE_LEN) - if limitlength - if !istopfunction(tm, f, :promote_typeof) - fst = sigtuple.parameters[lsig + 1] - allsame = true - # allow specializing on longer arglists if all the trailing - # arguments are the same, since there is no exponential - # blowup in this case. - for i = (lsig + 2):ls - if sigtuple.parameters[i] != fst - allsame = false - break - end - end - if !allsame - sigtuple = limit_tuple_type_n(sigtuple, lsig + 1) - sig = rewrap_unionall(sigtuple, sig) - recomputesvec = true + # iterate through the cycle before walking to the parent + if cyclei < length(infstate.callers_in_cycle) + cyclei += 1 + infstate = infstate.callers_in_cycle[cyclei] + else + cyclei = 0 + infstate = infstate.parent + end + end + end + + # limit length based on size of definition signature. + # for example, given function f(T, Any...), limit to 3 arguments + # instead of the default (MAX_TUPLETYPE_LEN) + if limitlength + tm = _topmod(sv) + if !istopfunction(tm, f, :promote_typeof) + fst = sigtuple.parameters[lsig + 1] + allsame = true + # allow specializing on longer arglists if all the trailing + # arguments are the same, since there is no exponential + # blowup in this case. + for i = (lsig + 2):ls + if sigtuple.parameters[i] != fst + allsame = false + break end end - end - - # if sig changed, may need to recompute the sparams environment - if recomputesvec && !isempty(sparams) - recomputed = ccall(:jl_env_from_type_intersection, Ref{SimpleVector}, (Any, Any), sig, method.sig) - sig = recomputed[1] - if !isa(unwrap_unionall(sig), DataType) # probably Union{} - rettype = Any - break + if !allsame + sigtuple = limit_tuple_type_n(sigtuple, lsig + 1) + sig = rewrap_unionall(sigtuple, sig) + recomputesvec = true end - sparams = recomputed[2]::SimpleVector - end - rt, edge = typeinf_edge(method, sig, sparams, sv) - edge !== nothing && add_backedge!(edge::MethodInstance, sv) - rettype = tmerge(rettype, rt) - if rettype === Any - break end end - if !(fullmatch || rettype === Any) - # also need an edge to the method table in case something gets - # added that did not intersect with any existing method - add_mt_backedge(ftname.mt, argtype, sv) - update_valid_age!(min_valid[1], max_valid[1], sv) + + # if sig changed, may need to recompute the sparams environment + if isa(method.sig, UnionAll) && (recomputesvec || isempty(sparams)) + recomputed = ccall(:jl_env_from_type_intersection, Ref{SimpleVector}, (Any, Any), sig, method.sig) + sig = recomputed[1] + if !isa(unwrap_unionall(sig), DataType) # probably Union{} + return Any + end + sparams = recomputed[2]::SimpleVector end - #print("=> ", rettype, "\n") - return rettype + rt, edge = typeinf_edge(method, sig, sparams, sv) + edge !== nothing && add_backedge!(edge::MethodInstance, sv) + return rt end # determine whether `ex` abstractly evals to constant `c` @@ -1562,6 +1617,9 @@ function abstract_apply(aft::ANY, fargs::Vector{Any}, aargtypes::Vector{Any}, vt return res end +# TODO: this function is a very buggy and poor model of the return_type function +# since abstract_call_gf_by_type is a very inaccurate model of _method and of typeinf_type, +# while this assumes that it is a precisely accurate and exact model of both function return_type_tfunc(argtypes::ANY, vtypes::VarTable, sv::InferenceState) if length(argtypes) == 3 tt = argtypes[3] @@ -2112,8 +2170,10 @@ function issubconditional(a::Conditional, b::Conditional) end function ⊑(a::ANY, b::ANY) - a === NF && return true - b === NF && return false + (a === NF || b === Any) && return true + (a === Any || b === NF) && return false + a === Union{} && return true + b === Union{} && return false if isa(a, Conditional) if isa(b, Conditional) return issubconditional(a, b) @@ -3483,7 +3543,7 @@ function is_self_quoting(x::ANY) return isa(x,Number) || isa(x,AbstractString) || isa(x,Tuple) || isa(x,Type) end -function countunionsplit(atypes::Vector{Any}) +function countunionsplit(atypes) nu = 1 for ti in atypes if isa(ti, Union) diff --git a/base/reflection.jl b/base/reflection.jl index eb8e279e11977..410611b2161cf 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -507,46 +507,9 @@ function _methods_by_ftype(t::ANY, lim::Int, world::UInt) return _methods_by_ftype(t, lim, world, UInt[typemin(UInt)], UInt[typemax(UInt)]) end function _methods_by_ftype(t::ANY, lim::Int, world::UInt, min::Array{UInt,1}, max::Array{UInt,1}) - tp = unwrap_unionall(t).parameters::SimpleVector - nu = 1 - for ti in tp - if isa(ti, Union) - nu *= unionlen(ti::Union) - end - end - if 1 < nu <= 64 - return _methods_by_ftype(Any[tp...], t, length(tp), lim, [], world, min, max) - end - # XXX: the following can return incorrect answers that the above branch would have corrected return ccall(:jl_matching_methods, Any, (Any, Cint, Cint, UInt, Ptr{UInt}, Ptr{UInt}), t, lim, 0, world, min, max) end -function _methods_by_ftype(t::Array, origt::ANY, i, lim::Integer, matching::Array{Any,1}, - world::UInt, min::Array{UInt,1}, max::Array{UInt,1}) - if i == 0 - world = typemax(UInt) - new = ccall(:jl_matching_methods, Any, (Any, Cint, Cint, UInt, Ptr{UInt}, Ptr{UInt}), - rewrap_unionall(Tuple{t...}, origt), lim, 0, world, min, max) - new === false && return false - append!(matching, new::Array{Any,1}) - else - ti = t[i] - if isa(ti, Union) - for ty in uniontypes(ti::Union) - t[i] = ty - if _methods_by_ftype(t, origt, i - 1, lim, matching, world, min, max) === false - t[i] = ti - return false - end - end - t[i] = ti - else - return _methods_by_ftype(t, origt, i - 1, lim, matching, world, min, max) - end - end - return matching -end - # high-level, more convenient method lookup functions # type for reflecting and pretty-printing a subset of methods From eb67a56e8d187c80edb2ba0a75508f53e5497165 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 25 May 2017 00:28:29 -0400 Subject: [PATCH 0958/1534] windows readme: add automation tips --- README.windows.md | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/README.windows.md b/README.windows.md index 96ccc1a7f9f17..15278e2802f98 100644 --- a/README.windows.md +++ b/README.windows.md @@ -184,6 +184,12 @@ versions of the MinGW-w64 compilers available through Cygwin's package manager. either 32 or 64 bit Julia from either 32 or 64 bit Cygwin. 64 bit Cygwin has a slightly smaller but often more up-to-date selection of packages. + Advanced: you may skip steps 2-4 by running: + + setup-x86_64.exe -s -q -P cmake,gcc-g++,git,make,patch,curl,m4,python,p7zip,mingw64-i686-gcc-g++,mingw64-i686-gcc-fortran,mingw64-x86_64-gcc-g++,mingw64-x86_64-gcc-fortran + :: replace with a site from https://cygwin.com/mirrors.html + :: or run setup manually first and select a mirror + 2. Select installation location and download mirror. 3. At the '*Select Packages'* step, select the following: @@ -207,7 +213,7 @@ versions of the MinGW-w64 compilers available through Cygwin's package manager. 1. Get the Julia sources ```sh - git clone --recursive https://github.com/JuliaLang/julia.git + git clone https://github.com/JuliaLang/julia.git cd julia ``` Tip: If you get an `error: cannot fork() for fetch-pack: Resource @@ -219,7 +225,7 @@ versions of the MinGW-w64 compilers available through Cygwin's package manager. ```sh echo 'XC_HOST = i686-w64-mingw32' > Make.user # for 32 bit Julia # or - echo 'XC_HOST = x86_64-w64-mingw32' > Make.user #for 64 bit Julia + echo 'XC_HOST = x86_64-w64-mingw32' > Make.user # for 64 bit Julia ``` 3. Start the build @@ -227,6 +233,20 @@ versions of the MinGW-w64 compilers available through Cygwin's package manager. make -j 4 # Adjust the number of cores (4) to match your build environment. ``` + + > Protip: build both! + > ```sh + > make O=julia-win32 configure + > make O=julia-win64 configure + > echo 'XC_HOST = i686-w64-mingw32' > julia-win32/Make.user + > echo 'XC_HOST = x86_64-w64-mingw32' > julia-win64/Make.user + > echo 'ifeq ($(BUILDROOT),$(JULIAHOME)) + > $(error "in-tree build disabled") + > endif' >> Make.user + > make -C julia-win32 # build for Windows x86 in julia-win32 folder + > make -C julia-win64 # build for Windows x86-64 in julia-win64 folder + > ``` + 7. Run Julia using the Julia executables directly ```sh usr/bin/julia.exe From a2cdad895727d7ab3382c7aed251630e3ce29c8a Mon Sep 17 00:00:00 2001 From: Alexey Stukalov Date: Fri, 26 May 2017 16:00:09 +0200 Subject: [PATCH 0959/1534] add _grow/deletebeg/end!(a::Array) ccall wrappers --- base/array.jl | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/base/array.jl b/base/array.jl index e7adc6e67eb2b..858eef12fe343 100644 --- a/base/array.jl +++ b/base/array.jl @@ -597,11 +597,19 @@ setindex!(A::Array{T, N}, x::Number, ::Vararg{Colon, N}) where {T, N} = fill!(A, # efficiently grow an array +_growbeg!(a::Vector, delta::Integer) = + ccall(:jl_array_grow_beg, Void, (Any, UInt), a, delta) +_growend!(a::Vector, delta::Integer) = + ccall(:jl_array_grow_end, Void, (Any, UInt), a, delta) _growat!(a::Vector, i::Integer, delta::Integer) = ccall(:jl_array_grow_at, Void, (Any, Int, UInt), a, i - 1, delta) # efficiently delete part of an array +_deletebeg!(a::Vector, delta::Integer) = + ccall(:jl_array_del_beg, Void, (Any, UInt), a, delta) +_deleteend!(a::Vector, delta::Integer) = + ccall(:jl_array_del_end, Void, (Any, UInt), a, delta) _deleteat!(a::Vector, i::Integer, delta::Integer) = ccall(:jl_array_del_at, Void, (Any, Int, UInt), a, i - 1, delta) @@ -610,13 +618,13 @@ _deleteat!(a::Vector, i::Integer, delta::Integer) = function push!(a::Array{T,1}, item) where T # convert first so we don't grow the array if the assignment won't work itemT = convert(T, item) - ccall(:jl_array_grow_end, Void, (Any, UInt), a, 1) + _growend!(a, 1) a[end] = itemT return a end function push!(a::Array{Any,1}, item::ANY) - ccall(:jl_array_grow_end, Void, (Any, UInt), a, 1) + _growend!(a, 1) arrayset(a, item, length(a)) return a end @@ -624,7 +632,7 @@ end function append!(a::Array{<:Any,1}, items::AbstractVector) itemindices = eachindex(items) n = length(itemindices) - ccall(:jl_array_grow_end, Void, (Any, UInt), a, n) + _growend!(a, n) copy!(a, length(a)-n+1, items, first(itemindices), n) return a end @@ -666,7 +674,7 @@ function prepend! end function prepend!(a::Array{<:Any,1}, items::AbstractVector) itemindices = eachindex(items) n = length(itemindices) - ccall(:jl_array_grow_beg, Void, (Any, UInt), a, n) + _growbeg!(a, n) if a === items copy!(a, 1, items, n+1, n) else @@ -680,7 +688,7 @@ unshift!(a::Vector, iter...) = prepend!(a, iter) function _prepend!(a, ::Union{HasLength,HasShape}, iter) n = length(iter) - ccall(:jl_array_grow_beg, Void, (Any, UInt), a, n) + _growbeg!(a, n) i = 0 for item in iter @inbounds a[i += 1] = item @@ -734,7 +742,7 @@ function resize!(a::Vector, nl::Integer) if nl < 0 throw(ArgumentError("new length must be ≥ 0")) end - ccall(:jl_array_del_end, Void, (Any, UInt), a, l-nl) + _deleteend!(a, l-nl) end return a end @@ -749,7 +757,7 @@ function pop!(a::Vector) throw(ArgumentError("array must be non-empty")) end item = a[end] - ccall(:jl_array_del_end, Void, (Any, UInt), a, 1) + _deleteend!(a, 1) return item end @@ -771,7 +779,7 @@ julia> unshift!([1, 2, 3, 4], 5, 6) """ function unshift!(a::Array{T,1}, item) where T item = convert(T, item) - ccall(:jl_array_grow_beg, Void, (Any, UInt), a, 1) + _growbeg!(a, 1) a[1] = item return a end @@ -781,7 +789,7 @@ function shift!(a::Vector) throw(ArgumentError("array must be non-empty")) end item = a[1] - ccall(:jl_array_del_beg, Void, (Any, UInt), a, 1) + _deletebeg!(a, 1) return item end @@ -892,7 +900,7 @@ function _deleteat!(a::Vector, inds) @inbounds a[p] = a[q] p += 1; q += 1 end - ccall(:jl_array_del_end, Void, (Any, UInt), a, n-p+1) + _deleteend!(a, n-p+1) return a end @@ -905,7 +913,7 @@ function deleteat!(a::Vector, inds::AbstractVector{Bool}) @inbounds a[p] = a[q] p += !i end - ccall(:jl_array_del_end, Void, (Any, UInt), a, n-p+1) + _deleteend!(a, n-p+1) return a end @@ -1034,7 +1042,7 @@ function splice!(a::Vector, r::UnitRange{<:Integer}, ins=_default_splice) end function empty!(a::Vector) - ccall(:jl_array_del_end, Void, (Any, UInt), a, length(a)) + _deleteend!(a, length(a)) return a end From 66c9bbbcf4f17ea12a7479e22ad8471dd647d1c4 Mon Sep 17 00:00:00 2001 From: Alexey Stukalov Date: Wed, 31 May 2017 16:06:57 +0200 Subject: [PATCH 0960/1534] jl_array_grow_at_end(): exact resize for large inc If the requested size of array buffer is >=200% of its current size, grow exactly to the requested size, otherwise double the current size. This should make resize!() & sizehint!() allocate the exactly requested size in more situations (previously the exact resize was guaranteed for empty arrays only). This heuristic should reduce memory usage when arrays are growing non-incrementally (e.g. temporary buffers allocated by LAPACK wrappers). --- NEWS.md | 3 +++ src/array.c | 15 +++++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/NEWS.md b/NEWS.md index 75dc3d9ff86e9..5c415e6c703ee 100644 --- a/NEWS.md +++ b/NEWS.md @@ -53,6 +53,9 @@ Library improvements * `getpeername` on a `TCPSocket` returns the address and port of the remote endpoint of the TCP connection ([#21825]). + * `resize!` and `sizehint!` methods no longer over-reserve memory when the + requested array size is more than double of its current size ([#22038]). + Compiler/Runtime improvements ----------------------------- diff --git a/src/array.c b/src/array.c index 9cd3cd2dc0152..c1050609a7cd8 100644 --- a/src/array.c +++ b/src/array.c @@ -755,14 +755,17 @@ STATIC_INLINE void jl_array_grow_at_end(jl_array_t *a, size_t idx, size_t elsz = a->elsize; char *data = (char*)a->data; int has_gap = n > idx; - if (__unlikely((n + inc) > a->maxsize - a->offset)) { + size_t reqmaxsize = a->offset + n + inc; + if (__unlikely(reqmaxsize > a->maxsize)) { size_t nb1 = idx * elsz; size_t nbinc = inc * elsz; - size_t newlen = a->maxsize == 0 ? (inc < 4 ? 4 : inc) : a->maxsize * 2; - while ((n + inc) > newlen - a->offset) - newlen *= 2; - newlen = limit_overallocation(a, n, newlen, inc); - int newbuf = array_resize_buffer(a, newlen); + // if the requested size is more than 2x current maxsize, grow exactly + // otherwise double the maxsize + size_t newmaxsize = reqmaxsize >= a->maxsize * 2 + ? (reqmaxsize < 4 ? 4 : reqmaxsize) + : a->maxsize * 2; + newmaxsize = limit_overallocation(a, n, newmaxsize, inc); + int newbuf = array_resize_buffer(a, newmaxsize); char *newdata = (char*)a->data + a->offset * elsz; if (newbuf) { memcpy(newdata, data, nb1); From b11bc921b0922abbbdb6e66019de336df31b497a Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Wed, 31 May 2017 16:51:23 +0200 Subject: [PATCH 0961/1534] use testsets in cholesky test (#22138) --- test/linalg/cholesky.jl | 324 ++++++++++++++++++++-------------------- 1 file changed, 159 insertions(+), 165 deletions(-) diff --git a/test/linalg/cholesky.jl b/test/linalg/cholesky.jl index b6d92d89ba9f7..0364b4bfb9fa2 100644 --- a/test/linalg/cholesky.jl +++ b/test/linalg/cholesky.jl @@ -1,165 +1,157 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -debug = false - using Base.Test using Base.LinAlg: BlasComplex, BlasFloat, BlasReal, QRPivoted, PosDefException -n = 10 +@testset "core functionality" begin + n = 10 -# Split n into 2 parts for tests needing two matrices -n1 = div(n, 2) -n2 = 2*n1 + # Split n into 2 parts for tests needing two matrices + n1 = div(n, 2) + n2 = 2*n1 -srand(1234321) + srand(1234321) -areal = randn(n,n)/2 -aimg = randn(n,n)/2 -a2real = randn(n,n)/2 -a2img = randn(n,n)/2 -breal = randn(n,2)/2 -bimg = randn(n,2)/2 + areal = randn(n,n)/2 + aimg = randn(n,n)/2 + a2real = randn(n,n)/2 + a2img = randn(n,n)/2 + breal = randn(n,2)/2 + bimg = randn(n,2)/2 -for eltya in (Float32, Float64, Complex64, Complex128, BigFloat, Int) - a = eltya == Int ? rand(1:7, n, n) : convert(Matrix{eltya}, eltya <: Complex ? complex.(areal, aimg) : areal) - a2 = eltya == Int ? rand(1:7, n, n) : convert(Matrix{eltya}, eltya <: Complex ? complex.(a2real, a2img) : a2real) - apd = a'*a # symmetric positive-definite + for eltya in (Float32, Float64, Complex64, Complex128, BigFloat, Int) + a = eltya == Int ? rand(1:7, n, n) : convert(Matrix{eltya}, eltya <: Complex ? complex.(areal, aimg) : areal) + a2 = eltya == Int ? rand(1:7, n, n) : convert(Matrix{eltya}, eltya <: Complex ? complex.(a2real, a2img) : a2real) + apd = a'*a # symmetric positive-definite - apds = Symmetric(apd) - apdsL = Symmetric(apd, :L) - apdh = Hermitian(apd) - apdhL = Hermitian(apd, :L) - ε = εa = eps(abs(float(one(eltya)))) + apds = Symmetric(apd) + apdsL = Symmetric(apd, :L) + apdh = Hermitian(apd) + apdhL = Hermitian(apd, :L) + ε = εa = eps(abs(float(one(eltya)))) - @inferred cholfact(apd) - @inferred chol(apd) - capd = factorize(apd) - r = capd[:U] - κ = cond(apd, 1) #condition number + @inferred cholfact(apd) + @inferred chol(apd) + capd = factorize(apd) + r = capd[:U] + κ = cond(apd, 1) #condition number - #getindex - @test_throws KeyError capd[:Z] + #getindex + @test_throws KeyError capd[:Z] - #Test error bound on reconstruction of matrix: LAWNS 14, Lemma 2.1 + #Test error bound on reconstruction of matrix: LAWNS 14, Lemma 2.1 - #these tests were failing on 64-bit linux when inside the inner loop - #for eltya = Complex64 and eltyb = Int. The E[i,j] had NaN32 elements - #but only with srand(1234321) set before the loops. - E = abs.(apd - r'*r) - for i=1:n, j=1:n - @test E[i,j] <= (n+1)ε/(1-(n+1)ε)*real(sqrt(apd[i,i]*apd[j,j])) - end - E = abs.(apd - full(capd)) - for i=1:n, j=1:n - @test E[i,j] <= (n+1)ε/(1-(n+1)ε)*real(sqrt(apd[i,i]*apd[j,j])) - end - @test apd*inv(capd) ≈ eye(n) - @test abs((det(capd) - det(apd))/det(capd)) <= ε*κ*n # Ad hoc, but statistically verified, revisit - @test @inferred(logdet(capd)) ≈ log(det(capd)) # logdet is less likely to overflow - - apos = apd[1,1] # test chol(x::Number), needs x>0 - @test all(x -> x ≈ √apos, cholfact(apos).factors) - @test_throws PosDefException chol(-one(eltya)) - - if eltya <: Real - capds = cholfact(apds) - @test inv(capds)*apds ≈ eye(n) - @test abs((det(capds) - det(apd))/det(capds)) <= ε*κ*n - if eltya <: BlasReal - capds = cholfact!(copy(apds)) + #these tests were failing on 64-bit linux when inside the inner loop + #for eltya = Complex64 and eltyb = Int. The E[i,j] had NaN32 elements + #but only with srand(1234321) set before the loops. + E = abs.(apd - r'*r) + for i=1:n, j=1:n + @test E[i,j] <= (n+1)ε/(1-(n+1)ε)*real(sqrt(apd[i,i]*apd[j,j])) + end + E = abs.(apd - full(capd)) + for i=1:n, j=1:n + @test E[i,j] <= (n+1)ε/(1-(n+1)ε)*real(sqrt(apd[i,i]*apd[j,j])) + end + @test apd*inv(capd) ≈ eye(n) + @test abs((det(capd) - det(apd))/det(capd)) <= ε*κ*n # Ad hoc, but statistically verified, revisit + @test @inferred(logdet(capd)) ≈ log(det(capd)) # logdet is less likely to overflow + + apos = apd[1,1] # test chol(x::Number), needs x>0 + @test all(x -> x ≈ √apos, cholfact(apos).factors) + @test_throws PosDefException chol(-one(eltya)) + + if eltya <: Real + capds = cholfact(apds) @test inv(capds)*apds ≈ eye(n) @test abs((det(capds) - det(apd))/det(capds)) <= ε*κ*n + if eltya <: BlasReal + capds = cholfact!(copy(apds)) + @test inv(capds)*apds ≈ eye(n) + @test abs((det(capds) - det(apd))/det(capds)) <= ε*κ*n + end + ulstring = sprint(show,capds[:UL]) + @test sprint(show,capds) == "$(typeof(capds)) with factor:\n$ulstring" + else + capdh = cholfact(apdh) + @test inv(capdh)*apdh ≈ eye(n) + @test abs((det(capdh) - det(apd))/det(capdh)) <= ε*κ*n + capdh = cholfact!(copy(apdh)) + @test inv(capdh)*apdh ≈ eye(n) + @test abs((det(capdh) - det(apd))/det(capdh)) <= ε*κ*n + capdh = cholfact!(copy(apd)) + @test inv(capdh)*apdh ≈ eye(n) + @test abs((det(capdh) - det(apd))/det(capdh)) <= ε*κ*n + capdh = cholfact!(copy(apd), :L) + @test inv(capdh)*apdh ≈ eye(n) + @test abs((det(capdh) - det(apd))/det(capdh)) <= ε*κ*n + ulstring = sprint(show,capdh[:UL]) + @test sprint(show,capdh) == "$(typeof(capdh)) with factor:\n$ulstring" end - ulstring = sprint(show,capds[:UL]) - @test sprint(show,capds) == "$(typeof(capds)) with factor:\n$ulstring" - else - capdh = cholfact(apdh) - @test inv(capdh)*apdh ≈ eye(n) - @test abs((det(capdh) - det(apd))/det(capdh)) <= ε*κ*n - capdh = cholfact!(copy(apdh)) - @test inv(capdh)*apdh ≈ eye(n) - @test abs((det(capdh) - det(apd))/det(capdh)) <= ε*κ*n - capdh = cholfact!(copy(apd)) - @test inv(capdh)*apdh ≈ eye(n) - @test abs((det(capdh) - det(apd))/det(capdh)) <= ε*κ*n - capdh = cholfact!(copy(apd), :L) - @test inv(capdh)*apdh ≈ eye(n) - @test abs((det(capdh) - det(apd))/det(capdh)) <= ε*κ*n - ulstring = sprint(show,capdh[:UL]) - @test sprint(show,capdh) == "$(typeof(capdh)) with factor:\n$ulstring" - end - # test chol of 2x2 Strang matrix - S = convert(AbstractMatrix{eltya},full(SymTridiagonal([2,2],[-1]))) - U = Bidiagonal([2,sqrt(eltya(3))],[-1],true) / sqrt(eltya(2)) - @test full(chol(S)) ≈ full(U) - - #lower Cholesky factor - lapd = cholfact(apd, :L) - @test full(lapd) ≈ apd - l = lapd[:L] - @test l*l' ≈ apd - @test triu(capd.factors) ≈ lapd[:U] - @test tril(lapd.factors) ≈ capd[:L] - if eltya <: Real - capds = cholfact(apds) - lapds = cholfact(apdsL) - cl = chol(apdsL) - ls = lapds[:L] - @test ls*ls' ≈ apd - @test triu(capds.factors) ≈ lapds[:U] - @test tril(lapds.factors) ≈ capds[:L] - @test istriu(cl) - @test cl'cl ≈ apds - @test cl'cl ≈ apdsL - else - capdh = cholfact(apdh) - lapdh = cholfact(apdhL) - cl = chol(apdhL) - ls = lapdh[:L] - @test ls*ls' ≈ apd - @test triu(capdh.factors) ≈ lapdh[:U] - @test tril(lapdh.factors) ≈ capdh[:L] - @test istriu(cl) - @test cl'cl ≈ apdh - @test cl'cl ≈ apdhL - end + # test chol of 2x2 Strang matrix + S = convert(AbstractMatrix{eltya},full(SymTridiagonal([2,2],[-1]))) + U = Bidiagonal([2,sqrt(eltya(3))],[-1],true) / sqrt(eltya(2)) + @test full(chol(S)) ≈ full(U) + + #lower Cholesky factor + lapd = cholfact(apd, :L) + @test full(lapd) ≈ apd + l = lapd[:L] + @test l*l' ≈ apd + @test triu(capd.factors) ≈ lapd[:U] + @test tril(lapd.factors) ≈ capd[:L] + if eltya <: Real + capds = cholfact(apds) + lapds = cholfact(apdsL) + cl = chol(apdsL) + ls = lapds[:L] + @test ls*ls' ≈ apd + @test triu(capds.factors) ≈ lapds[:U] + @test tril(lapds.factors) ≈ capds[:L] + @test istriu(cl) + @test cl'cl ≈ apds + @test cl'cl ≈ apdsL + else + capdh = cholfact(apdh) + lapdh = cholfact(apdhL) + cl = chol(apdhL) + ls = lapdh[:L] + @test ls*ls' ≈ apd + @test triu(capdh.factors) ≈ lapdh[:U] + @test tril(lapdh.factors) ≈ capdh[:L] + @test istriu(cl) + @test cl'cl ≈ apdh + @test cl'cl ≈ apdhL + end - #pivoted upper Cholesky - if eltya != BigFloat - cz = cholfact(zeros(eltya,n,n), :U, Val{true}) - @test_throws Base.LinAlg.RankDeficientException Base.LinAlg.chkfullrank(cz) - cpapd = cholfact(apd, :U, Val{true}) - @test rank(cpapd) == n - @test all(diff(diag(real(cpapd.factors))).<=0.) # diagonal should be non-increasing - if isreal(apd) - @test apd*inv(cpapd) ≈ eye(n) + #pivoted upper Cholesky + if eltya != BigFloat + cz = cholfact(zeros(eltya,n,n), :U, Val{true}) + @test_throws Base.LinAlg.RankDeficientException Base.LinAlg.chkfullrank(cz) + cpapd = cholfact(apd, :U, Val{true}) + @test rank(cpapd) == n + @test all(diff(diag(real(cpapd.factors))).<=0.) # diagonal should be non-increasing + if isreal(apd) + @test apd*inv(cpapd) ≈ eye(n) + end + @test full(cpapd) ≈ apd + #getindex + @test_throws KeyError cpapd[:Z] + + @test size(cpapd) == size(apd) + @test full(copy(cpapd)) ≈ apd + @test det(cpapd) ≈ det(apd) + @test logdet(cpapd) ≈ logdet(apd) + @test cpapd[:P]*cpapd[:L]*cpapd[:U]*cpapd[:P]' ≈ apd end - @test full(cpapd) ≈ apd - #getindex - @test_throws KeyError cpapd[:Z] - @test size(cpapd) == size(apd) - @test full(copy(cpapd)) ≈ apd - @test det(cpapd) ≈ det(apd) - @test logdet(cpapd) ≈ logdet(apd) - @test cpapd[:P]*cpapd[:L]*cpapd[:U]*cpapd[:P]' ≈ apd - end + for eltyb in (Float32, Float64, Complex64, Complex128, Int) + b = eltyb == Int ? rand(1:5, n, 2) : convert(Matrix{eltyb}, eltyb <: Complex ? complex.(breal, bimg) : breal) + εb = eps(abs(float(one(eltyb)))) + ε = max(εa,εb) - for eltyb in (Float32, Float64, Complex64, Complex128, Int) - b = eltyb == Int ? rand(1:5, n, 2) : convert(Matrix{eltyb}, eltyb <: Complex ? complex.(breal, bimg) : breal) - εb = eps(abs(float(one(eltyb)))) - ε = max(εa,εb) - -debug && println("\ntype of a: ", eltya, " type of b: ", eltyb, "\n") - let Bs = b - for atype in ("Array", "SubArray") - if atype == "Array" - b = Bs - else - b = view(Bs, 1:n, 1) - end + for b in (b, view(b, 1:n, 1)) # Array and SubArray # Test error bound on linear solver: LAWNS 14, Theorem 2.1 # This is a surprisingly loose bound @@ -175,7 +167,6 @@ debug && println("\ntype of a: ", eltya, " type of b: ", eltyb, "\n") end @test_throws DimensionMismatch lapd\RowVector(ones(n)) -debug && println("pivoted Cholesky decomposition") if eltya != BigFloat && eltyb != BigFloat # Note! Need to implement pivoted Cholesky decomposition in julia @test norm(apd * (cpapd\b) - b)/norm(b) <= ε*κ*n # Ad hoc, revisit @@ -192,8 +183,7 @@ debug && println("pivoted Cholesky decomposition") end end -begin - # Cholesky factor of Matrix with non-commutative elements, here 2x2-matrices +@testset "Cholesky factor of Matrix with non-commutative elements, here 2x2-matrices" begin X = Matrix{Float64}[0.1*rand(2,2) for i in 1:3, j = 1:3] L = full(Base.LinAlg._chol!(X*X', LowerTriangular)[1]) U = full(Base.LinAlg._chol!(X*X', UpperTriangular)[1]) @@ -204,19 +194,22 @@ begin end # Test generic cholfact! -for elty in (Float32, Float64, Complex{Float32}, Complex{Float64}) - if elty <: Complex - A = complex.(randn(5,5), randn(5,5)) - else - A = randn(5,5) +@testset "generic cholfact!" begin + for elty in (Float32, Float64, Complex{Float32}, Complex{Float64}) + if elty <: Complex + A = complex.(randn(5,5), randn(5,5)) + else + A = randn(5,5) + end + A = convert(Matrix{elty}, A'A) + @test full(cholfact(A)[:L]) ≈ full(invoke(Base.LinAlg._chol!, Tuple{AbstractMatrix, Type{LowerTriangular}}, copy(A), LowerTriangular)[1]) + @test full(cholfact(A)[:U]) ≈ full(invoke(Base.LinAlg._chol!, Tuple{AbstractMatrix, Type{UpperTriangular}}, copy(A), UpperTriangular)[1]) end - A = convert(Matrix{elty}, A'A) - @test full(cholfact(A)[:L]) ≈ full(invoke(Base.LinAlg._chol!, Tuple{AbstractMatrix, Type{LowerTriangular}}, copy(A), LowerTriangular)[1]) - @test full(cholfact(A)[:U]) ≈ full(invoke(Base.LinAlg._chol!, Tuple{AbstractMatrix, Type{UpperTriangular}}, copy(A), UpperTriangular)[1]) end -# Test up- and downdates -let A = complex.(randn(10,5), randn(10, 5)), v = complex.(randn(5), randn(5)) +@testset "cholesky up- and downdates" begin + A = complex.(randn(10,5), randn(10, 5)) + v = complex.(randn(5), randn(5)) for uplo in (:U, :L) AcA = A'A BcB = AcA + v*v' @@ -230,8 +223,8 @@ let A = complex.(randn(10,5), randn(10, 5)), v = complex.(randn(5), randn(5)) end end -# issue #13243, unexpected nans in complex cholfact -let apd = [5.8525753f0 + 0.0f0im -0.79540455f0 + 0.7066077f0im 0.98274714f0 + 1.3824869f0im 2.619998f0 + 1.8532984f0im -1.8306153f0 - 1.2336911f0im 0.32275113f0 + 0.015575029f0im 2.1968813f0 + 1.0640624f0im 0.27894387f0 + 0.97911835f0im 3.0476584f0 + 0.18548489f0im 0.3842994f0 + 0.7050991f0im +@testset "issue #13243, unexpected nans in complex cholfact" begin + apd = [5.8525753f0 + 0.0f0im -0.79540455f0 + 0.7066077f0im 0.98274714f0 + 1.3824869f0im 2.619998f0 + 1.8532984f0im -1.8306153f0 - 1.2336911f0im 0.32275113f0 + 0.015575029f0im 2.1968813f0 + 1.0640624f0im 0.27894387f0 + 0.97911835f0im 3.0476584f0 + 0.18548489f0im 0.3842994f0 + 0.7050991f0im -0.79540455f0 - 0.7066077f0im 8.313246f0 + 0.0f0im -1.8076122f0 - 0.8882447f0im 0.47806996f0 + 0.48494184f0im 0.5096429f0 - 0.5395974f0im -0.7285097f0 - 0.10360408f0im -1.1760061f0 - 2.7146957f0im -0.4271084f0 + 0.042899966f0im -1.7228563f0 + 2.8335886f0im 1.8942566f0 + 0.6389735f0im 0.98274714f0 - 1.3824869f0im -1.8076122f0 + 0.8882447f0im 9.367975f0 + 0.0f0im -0.1838578f0 + 0.6468568f0im -1.8338387f0 + 0.7064959f0im 0.041852742f0 - 0.6556877f0im 2.5673025f0 + 1.9732997f0im -1.1148382f0 - 0.15693812f0im 2.4704504f0 - 1.0389464f0im 1.0858271f0 - 1.298006f0im 2.619998f0 - 1.8532984f0im 0.47806996f0 - 0.48494184f0im -0.1838578f0 - 0.6468568f0im 3.1117508f0 + 0.0f0im -1.956626f0 + 0.22825956f0im 0.07081801f0 - 0.31801307f0im 0.3698375f0 - 0.5400855f0im 0.80686307f0 + 1.5315914f0im 1.5649154f0 - 1.6229297f0im -0.112077385f0 + 1.2014246f0im @@ -261,22 +254,23 @@ let apd = [5.8525753f0 + 0.0f0im -0.79540455f0 + 0.7066077f0im 0.98274714f0 + 1. end end -# Fail if non-Hermitian -@test_throws ArgumentError cholfact(randn(5,5)) -@test_throws ArgumentError cholfact(complex.(randn(5,5), randn(5,5))) -@test_throws ArgumentError Base.LinAlg.chol!(randn(5,5)) -@test_throws ArgumentError Base.LinAlg.cholfact!(randn(5,5),:U,Val{false}) -@test_throws ArgumentError Base.LinAlg.cholfact!(randn(5,5),:U,Val{true}) -@test_throws ArgumentError cholfact(randn(5,5),:U,Val{false}) +@testset "throw if non-Hermitian" begin + @test_throws ArgumentError cholfact(randn(5,5)) + @test_throws ArgumentError cholfact(complex.(randn(5,5), randn(5,5))) + @test_throws ArgumentError Base.LinAlg.chol!(randn(5,5)) + @test_throws ArgumentError Base.LinAlg.cholfact!(randn(5,5),:U,Val{false}) + @test_throws ArgumentError Base.LinAlg.cholfact!(randn(5,5),:U,Val{true}) + @test_throws ArgumentError cholfact(randn(5,5),:U,Val{false}) +end -# Fail for non-BLAS element types -@test_throws ArgumentError cholfact!(Hermitian(rand(Float16, 5,5)), Val{true}) +@testset "fail for non-BLAS element types" begin + @test_throws ArgumentError cholfact!(Hermitian(rand(Float16, 5,5)), Val{true}) +end -@testset "throw for non positive matrix" begin +@testset "throw for non positive definite matrix" begin for T in (Float32, Float64, Complex64, Complex128) A = T[1 2; 2 1]; B = T[1, 1] C = cholfact(A) - @show typeof(A), typeof(B), typeof(C.factors) @test_throws PosDefException C\B @test_throws PosDefException det(C) @test_throws PosDefException logdet(C) From b5ac087664e90d4f69d80522cc48719c9f4f203f Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Wed, 31 May 2017 16:51:52 +0200 Subject: [PATCH 0962/1534] document order of svdvals (#22148) --- base/linalg/svd.jl | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/base/linalg/svd.jl b/base/linalg/svd.jl index 4ea9291873a89..639d528a1b812 100644 --- a/base/linalg/svd.jl +++ b/base/linalg/svd.jl @@ -15,10 +15,6 @@ SVD(U::AbstractArray{T}, S::Vector{Tr}, Vt::AbstractArray{T}) where {T,Tr} = SVD `svdfact!` is the same as [`svdfact`](@ref), but saves space by overwriting the input `A`, instead of creating a copy. - -If `thin=true` (default), a thin SVD is returned. For a ``M \\times N`` matrix -`A`, `U` is ``M \\times M`` for a full SVD (`thin=false`) and -``M \\times \\min(M, N)`` for a thin SVD. """ function svdfact!(A::StridedMatrix{T}; thin::Bool=true) where T<:BlasFloat m,n = size(A) @@ -38,6 +34,7 @@ Compute the singular value decomposition (SVD) of `A` and return an `SVD` object `U`, `S`, `V` and `Vt` can be obtained from the factorization `F` with `F[:U]`, `F[:S]`, `F[:V]` and `F[:Vt]`, such that `A = U*diagm(S)*Vt`. The algorithm produces `Vt` and hence `Vt` is more efficient to extract than `V`. +The singular values in `S` are sorted in descending order. If `thin=true` (default), a thin SVD is returned. For a ``M \\times N`` matrix `A`, `U` is ``M \\times M`` for a full SVD (`thin=false`) and @@ -74,7 +71,7 @@ svdfact(x::Integer; thin::Bool=true) = svdfact(float(x), thin=thin) svd(A, thin::Bool=true) -> U, S, V Computes the SVD of `A`, returning `U`, vector `S`, and `V` such that -`A == U*diagm(S)*V'`. +`A == U*diagm(S)*V'`. The singular values in `S` are sorted in descending order. If `thin=true` (default), a thin SVD is returned. For a ``M \\times N`` matrix `A`, `U` is ``M \\times M`` for a full SVD (`thin=false`) and @@ -136,7 +133,7 @@ svdvals(A::AbstractMatrix{<:BlasFloat}) = svdvals!(copy(A)) """ svdvals(A) -Returns the singular values of `A`. +Returns the singular values of `A` in descending order. # Example From 8f8c154aab466453bffa43a1b05faf01d915a3d9 Mon Sep 17 00:00:00 2001 From: Mus M Date: Wed, 31 May 2017 12:55:22 -0400 Subject: [PATCH 0963/1534] VersionNumber and return build in windows_version (#21837) --- base/sysimg.jl | 2 +- base/sysinfo.jl | 10 +++++----- test/osutils.jl | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/base/sysimg.jl b/base/sysimg.jl index 11a239a5f93bd..31b1a6132009e 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -162,7 +162,6 @@ include(string((length(Core.ARGS)>=2 ? Core.ARGS[2] : ""), "version_git.jl")) # include("osutils.jl") include("c.jl") -include("sysinfo.jl") if !isdefined(Core, :Inference) include("docs/core.jl") @@ -222,6 +221,7 @@ importall .Base64 include("version.jl") # system & environment +include("sysinfo.jl") include("libc.jl") using .Libc: getpid, gethostname, time include("libdl.jl") diff --git a/base/sysinfo.jl b/base/sysinfo.jl index 6c171d3649d76..95fc5ccb35f6b 100644 --- a/base/sysinfo.jl +++ b/base/sysinfo.jl @@ -193,19 +193,19 @@ maxrss() = ccall(:jl_maxrss, Csize_t, ()) if is_windows() function windows_version() verinfo = ccall(:GetVersion, UInt32, ()) - (Int(verinfo & 0xFF), Int((verinfo >> 8) & 0xFF)) + VersionNumber(verinfo & 0xFF, (verinfo >> 8) & 0xFF, verinfo >> 16) end else - windows_version() = (0, 0) + windows_version() = v"0.0" end """ Sys.windows_version() -Returns the version number for the Windows NT Kernel as a (major, minor) pair, -or `(0, 0)` if this is not running on Windows. +Returns the version number for the Windows NT Kernel as a `VersionNumber`, +i.e. `v"major.minor.build"`, or `v"0.0.0"` if this is not running on Windows. """ windows_version -const WINDOWS_VISTA_VER = (6, 0) +const WINDOWS_VISTA_VER = v"6.0" end # module Sys diff --git a/test/osutils.jl b/test/osutils.jl index 270680c54b601..b84688f55609b 100644 --- a/test/osutils.jl +++ b/test/osutils.jl @@ -13,9 +13,9 @@ @test Base.is_unix(:FreeBSD) @test_throws ArgumentError Base.is_unix(:BeOS) if !is_windows() - @test Sys.windows_version() === (0, 0) + @test Sys.windows_version() == v"0.0.0" else - @test (Sys.windows_version()::Tuple{Int,Int})[1] > 0 + @test Sys.windows_version() >= v"1.0.0-" end @test (@static true ? 1 : 2) === 1 From f611cfce82681a29f8487ed9fb2182d4c815c699 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Mon, 29 May 2017 23:53:06 -0400 Subject: [PATCH 0964/1534] Show failing instruction on SIGILL --- src/signal-handling.c | 126 ++++++++++++++++++++++++++++++++++++++++++ src/signals-unix.c | 2 + src/signals-win.c | 6 ++ 3 files changed, 134 insertions(+) diff --git a/src/signal-handling.c b/src/signal-handling.c index 75c551bcf1b38..e6edffd1f83d3 100644 --- a/src/signal-handling.c +++ b/src/signal-handling.c @@ -3,8 +3,13 @@ #include #include #include +#include #include "julia.h" #include "julia_internal.h" +#ifndef _OS_WINDOWS_ +#include +#include +#endif #ifdef __cplusplus extern "C" { @@ -88,12 +93,133 @@ JL_DLLEXPORT void jl_exit_on_sigint(int on) exit_on_sigint = on; } +static uintptr_t jl_get_pc_from_ctx(const void *_ctx); +void jl_show_sigill(void *_ctx); +static size_t jl_safe_read_mem(const volatile char *ptr, char *out, size_t len) +{ + jl_ptls_t ptls = jl_get_ptls_states(); + jl_jmp_buf *old_buf = ptls->safe_restore; + jl_jmp_buf buf; + ptls->safe_restore = &buf; + volatile size_t i = 0; + if (!jl_setjmp(buf, 0)) { + for (;i < len;i++) { + out[i] = ptr[i]; + } + } + ptls->safe_restore = old_buf; + return i; +} + #if defined(_WIN32) #include "signals-win.c" #else #include "signals-unix.c" #endif +static uintptr_t jl_get_pc_from_ctx(const void *_ctx) +{ +#if defined(_OS_LINUX_) && defined(_CPU_X86_64_) + return ((ucontext_t*)_ctx)->uc_mcontext.gregs[REG_RIP]; +#elif defined(_OS_FREEBSD_) && defined(_CPU_X86_64_) + return ((ucontext_t*)_ctx)->uc_mcontext.mc_rip; +#elif defined(_OS_LINUX_) && defined(_CPU_X86_) + return ((ucontext_t*)_ctx)->uc_mcontext.gregs[REG_EIP]; +#elif defined(_OS_FREEBSD_) && defined(_CPU_X86_) + return ((ucontext_t*)_ctx)->uc_mcontext.mc_eip; +#elif defined(_OS_DARWIN_) + return ((ucontext64_t*)_ctx)->uc_mcontext64->__ss.__rip; +#elif defined(_OS_WINDOWS_) && defined(_CPU_X86_) + return ((CONTEXT*)_ctx)->Eip; +#elif defined(_OS_WINDOWS_) && defined(_CPU_X86_64_) + return ((CONTEXT*)_ctx)->Rip; +#elif defined(_OS_LINUX_) && defined(_CPU_AARCH64_) + return ((ucontext_t*)_ctx)->uc_mcontext.pc; +#elif defined(_OS_LINUX_) && defined(_CPU_ARM_) + return ((ucontext_t*)_ctx)->uc_mcontext.arm_pc; +#else + // TODO for PPC + return 0; +#endif +} + +void jl_show_sigill(void *_ctx) +{ + char *pc = (char*)jl_get_pc_from_ctx(_ctx); + // unsupported platform + if (!pc) + return; +#if defined(_CPU_X86_64_) || defined(_CPU_X86_) + uint8_t inst[15]; // max length of x86 instruction + size_t len = jl_safe_read_mem(pc, (char*)inst, sizeof(inst)); + // ud2 + if (len >= 2 && inst[0] == 0x0f && inst[1] == 0x0b) { + jl_safe_printf("Unreachable reached at %p\n", (void*)pc); + } + else { + jl_safe_printf("Invalid instruction at %p: ", (void*)pc); + for (int i = 0;i < len;i++) { + if (i == 0) { + jl_safe_printf("0x%02" PRIx8, inst[i]); + } + else { + jl_safe_printf(", 0x%02" PRIx8, inst[i]); + } + } + jl_safe_printf("\n"); + } +#elif defined(_OS_LINUX_) && defined(_CPU_AARCH64_) + uint32_t inst = 0; + size_t len = jl_safe_read_mem(ptr, (char*)&inst, 4); + if (len < 4) + jl_safe_printf("Fault when reading instruction: %d bytes read\n". (int)len); + if (inst == 0xd4200020) { // brk #0x1 + // The signal might actually be SIGTRAP instead, doesn't hurt to handle it here though. + jl_safe_printf("Unreachable reached at %p\n", pc); + } + else { + jl_safe_printf("Invalid instruction at %p: 0x%08" PRIx32 "\n", pc, inst); + } +#elif defined(_OS_LINUX_) && defined(_CPU_ARM_) + ucontext_t *ctx = (ucontext_t*)_ctx; + if (ctx->uc_mcontext.arm_cpsr & (1 << 5)) { + // Thumb + uint16_t inst[2] = {0, 0}; + size_t len = jl_safe_read_mem(ptr, (char*)&inst, 4); + if (len < 2) + jl_safe_printf("Fault when reading Thumb instruction: %d bytes read\n". (int)len); + // LLVM and GCC uses different code for the trap... + if (inst[0] == 0xdefe || inst[0] == 0xdeff) { + // The signal might actually be SIGTRAP instead, doesn't hurt to handle it here though. + jl_safe_printf("Unreachable reached in Thumb mode at %p: 0x%04" PRIx16 "\n", + (void*)pc, inst[0]); + } + else { + jl_safe_printf("Invalid Thumb instruction at %p: 0x%04" PRIx16 ", 0x%04" PRIx16 "\n", + (void*)pc, inst[0], inst[1]); + } + } + else { + uint32_t inst = 0; + size_t len = jl_safe_read_mem(ptr, (char*)&inst, 4); + if (len < 4) + jl_safe_printf("Fault when reading instruction: %d bytes read\n". (int)len); + // LLVM and GCC uses different code for the trap... + if (inst == 0xe7ffdefe || inst == 0xe7f000f0) { + // The signal might actually be SIGTRAP instead, doesn't hurt to handle it here though. + jl_safe_printf("Unreachable reached in ARM mode at %p: 0x%08" PRIx32 "\n", + (void*)pc, inst); + } + else { + jl_safe_printf("Invalid ARM instruction at %p: 0x%08" PRIx32 "\n", (void*)pc, inst); + } + } +#else + // TODO for PPC + (void)_ctx; +#endif +} + // what to do on a critical error void jl_critical_error(int sig, bt_context_t *context, uintptr_t *bt_data, size_t *bt_size) { diff --git a/src/signals-unix.c b/src/signals-unix.c index 00beeb9babd90..9820dbc356df9 100644 --- a/src/signals-unix.c +++ b/src/signals-unix.c @@ -177,6 +177,8 @@ void sigdie_handler(int sig, siginfo_t *info, void *context) jl_ptls_t ptls = jl_get_ptls_states(); sigset_t sset; uv_tty_reset_mode(); + if (sig == SIGILL) + jl_show_sigill(context); jl_critical_error(sig, jl_to_bt_context(context), ptls->bt_data, &ptls->bt_size); sigfillset(&sset); diff --git a/src/signals-win.c b/src/signals-win.c index a54d7e5736d5c..6b056b340bd29 100644 --- a/src/signals-win.c +++ b/src/signals-win.c @@ -88,6 +88,8 @@ void __cdecl crt_sig_handler(int sig, int num) default: // SIGSEGV, (SSIGTERM, IGILL) memset(&Context, 0, sizeof(Context)); RtlCaptureContext(&Context); + if (sig == SIGILL) + jl_show_sigill(&Context); jl_critical_error(sig, &Context, ptls->bt_data, &ptls->bt_size); raise(sig); } @@ -226,6 +228,10 @@ static LONG WINAPI _exception_handler(struct _EXCEPTION_POINTERS *ExceptionInfo, return EXCEPTION_CONTINUE_EXECUTION; } } + if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_ILLEGAL_INSTRUCTION) { + jl_safe_printf("\n"); + jl_show_sigill(ExceptionInfo->ContextRecord); + } jl_safe_printf("\nPlease submit a bug report with steps to reproduce this fault, and any error messages that follow (in their entirety). Thanks.\nException: "); switch (ExceptionInfo->ExceptionRecord->ExceptionCode) { case EXCEPTION_ACCESS_VIOLATION: From e5983d77cd5bef4b7ff5f0cec22d008d0cb3922d Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Tue, 30 May 2017 22:47:24 -0400 Subject: [PATCH 0965/1534] Handle safe_restore on Windows and macOS on managed threads --- src/signal-handling.c | 12 ++++++------ src/signals-mach.c | 14 ++++++++++---- src/signals-win.c | 16 ++++++++++++---- 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/signal-handling.c b/src/signal-handling.c index e6edffd1f83d3..d8d0bf553889d 100644 --- a/src/signal-handling.c +++ b/src/signal-handling.c @@ -170,9 +170,9 @@ void jl_show_sigill(void *_ctx) } #elif defined(_OS_LINUX_) && defined(_CPU_AARCH64_) uint32_t inst = 0; - size_t len = jl_safe_read_mem(ptr, (char*)&inst, 4); + size_t len = jl_safe_read_mem(pc, (char*)&inst, 4); if (len < 4) - jl_safe_printf("Fault when reading instruction: %d bytes read\n". (int)len); + jl_safe_printf("Fault when reading instruction: %d bytes read\n", (int)len); if (inst == 0xd4200020) { // brk #0x1 // The signal might actually be SIGTRAP instead, doesn't hurt to handle it here though. jl_safe_printf("Unreachable reached at %p\n", pc); @@ -185,9 +185,9 @@ void jl_show_sigill(void *_ctx) if (ctx->uc_mcontext.arm_cpsr & (1 << 5)) { // Thumb uint16_t inst[2] = {0, 0}; - size_t len = jl_safe_read_mem(ptr, (char*)&inst, 4); + size_t len = jl_safe_read_mem(pc, (char*)&inst, 4); if (len < 2) - jl_safe_printf("Fault when reading Thumb instruction: %d bytes read\n". (int)len); + jl_safe_printf("Fault when reading Thumb instruction: %d bytes read\n", (int)len); // LLVM and GCC uses different code for the trap... if (inst[0] == 0xdefe || inst[0] == 0xdeff) { // The signal might actually be SIGTRAP instead, doesn't hurt to handle it here though. @@ -201,9 +201,9 @@ void jl_show_sigill(void *_ctx) } else { uint32_t inst = 0; - size_t len = jl_safe_read_mem(ptr, (char*)&inst, 4); + size_t len = jl_safe_read_mem(pc, (char*)&inst, 4); if (len < 4) - jl_safe_printf("Fault when reading instruction: %d bytes read\n". (int)len); + jl_safe_printf("Fault when reading instruction: %d bytes read\n", (int)len); // LLVM and GCC uses different code for the trap... if (inst == 0xe7ffdefe || inst == 0xe7f000f0) { // The signal might actually be SIGTRAP instead, doesn't hurt to handle it here though. diff --git a/src/signals-mach.c b/src/signals-mach.c index eb88e187b7505..8534eb6e8bafe 100644 --- a/src/signals-mach.c +++ b/src/signals-mach.c @@ -141,10 +141,12 @@ static void jl_throw_in_thread(int tid, mach_port_t thread, jl_value_t *exceptio kern_return_t ret = thread_get_state(thread, x86_THREAD_STATE64, (thread_state_t)&state, &count); HANDLE_MACH_ERROR("thread_get_state", ret); jl_ptls_t ptls2 = jl_all_tls_states[tid]; - - ptls2->bt_size = rec_backtrace_ctx(ptls2->bt_data, JL_MAX_BT_SIZE, - (bt_context_t*)&state); - ptls2->exception_in_transit = exception; + if (!ptls2->safe_restore) { + assert(exception); + ptls2->bt_size = rec_backtrace_ctx(ptls2->bt_data, JL_MAX_BT_SIZE, + (bt_context_t*)&state); + ptls2->exception_in_transit = exception; + } jl_call_in_state(ptls2, &state, &jl_rethrow); ret = thread_set_state(thread, x86_THREAD_STATE64, (thread_state_t)&state, count); @@ -214,6 +216,10 @@ kern_return_t catch_exception_raise(mach_port_t exception_port, } return KERN_SUCCESS; } + if (ptls2->safe_restore) { + jl_throw_in_thread(tid, thread, jl_stackovf_exception); + return KERN_SUCCESS; + } #ifdef SEGV_EXCEPTION if (1) { #else diff --git a/src/signals-win.c b/src/signals-win.c index 6b056b340bd29..0672da59a17cb 100644 --- a/src/signals-win.c +++ b/src/signals-win.c @@ -86,6 +86,8 @@ void __cdecl crt_sig_handler(int sig, int num) } break; default: // SIGSEGV, (SSIGTERM, IGILL) + if (ptls->safe_restore) + jl_rethrow(); memset(&Context, 0, sizeof(Context)); RtlCaptureContext(&Context); if (sig == SIGILL) @@ -107,7 +109,6 @@ void restore_signals(void) void jl_throw_in_ctx(jl_value_t *excpt, CONTEXT *ctxThread, int bt) { jl_ptls_t ptls = jl_get_ptls_states(); - assert(excpt != NULL); #if defined(_CPU_X86_64_) DWORD64 Rsp = (ctxThread->Rsp&(DWORD64)-16) - 8; #elif defined(_CPU_X86_) @@ -115,9 +116,12 @@ void jl_throw_in_ctx(jl_value_t *excpt, CONTEXT *ctxThread, int bt) #else #error WIN16 not supported :P #endif - ptls->bt_size = bt ? rec_backtrace_ctx(ptls->bt_data, JL_MAX_BT_SIZE, - ctxThread) : 0; - ptls->exception_in_transit = excpt; + if (!ptls->safe_restore) { + assert(excpt != NULL); + ptls->bt_size = bt ? rec_backtrace_ctx(ptls->bt_data, JL_MAX_BT_SIZE, + ctxThread) : 0; + ptls->exception_in_transit = excpt; + } #if defined(_CPU_X86_64_) *(DWORD64*)Rsp = 0; ctxThread->Rsp = Rsp; @@ -222,6 +226,10 @@ static LONG WINAPI _exception_handler(struct _EXCEPTION_POINTERS *ExceptionInfo, } return EXCEPTION_CONTINUE_EXECUTION; } + if (ptls->safe_restore) { + jl_throw_in_ctx(NULL, ExceptionInfo->ContextRecord, in_ctx); + return EXCEPTION_CONTINUE_EXECUTION; + } if (ExceptionInfo->ExceptionRecord->ExceptionInformation[0] == 1) { // writing to read-only memory (e.g. mmap) jl_throw_in_ctx(jl_readonlymemory_exception, ExceptionInfo->ContextRecord,in_ctx); From 0a37bbb559d467e79612867d77b66e56c0a3fae6 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Wed, 31 May 2017 22:00:10 -0400 Subject: [PATCH 0966/1534] Fix TLS variant def on AArch64 --- src/threading.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/threading.c b/src/threading.c index 369f7a45507de..528bdcfd47360 100644 --- a/src/threading.c +++ b/src/threading.c @@ -29,12 +29,10 @@ # if defined(_CPU_X86_64_) || defined(_CPU_X86_) # define JL_ELF_TLS_VARIANT 2 # define JL_ELF_TLS_INIT_SIZE 0 -# endif -# if defined(_CPU_AARCH64_) +# elif defined(_CPU_AARCH64_) # define JL_ELF_TLS_VARIANT 1 # define JL_ELF_TLS_INIT_SIZE 16 -# endif -# if defined(__ARM_ARCH) && __ARM_ARCH >= 7 +# elif defined(__ARM_ARCH) && __ARM_ARCH >= 7 # define JL_ELF_TLS_VARIANT 1 # define JL_ELF_TLS_INIT_SIZE 8 # endif From 051c0ddc228660928707c402d7637e3e653b34f8 Mon Sep 17 00:00:00 2001 From: Amit Murthy Date: Wed, 31 May 2017 15:09:36 +0530 Subject: [PATCH 0967/1534] Deserializing a SharedArray resulted in a copy of the container. Check and return existing SharedArray objects when deserializing on the node which created the array. --- base/sharedarray.jl | 35 +++++++++++++++++++++++++++++++++-- test/distributed_exec.jl | 12 ++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/base/sharedarray.jl b/base/sharedarray.jl index 62e1a546764d7..6ef164720b836 100644 --- a/base/sharedarray.jl +++ b/base/sharedarray.jl @@ -1,8 +1,10 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license import .Serializer: serialize_cycle_header, serialize_type, writetag, UNDEFREF_TAG +import .Distributed: RRID mutable struct SharedArray{T,N} <: DenseArray{T,N} + id::RRID dims::NTuple{N,Int} pids::Vector{Int} refs::Vector @@ -24,10 +26,14 @@ mutable struct SharedArray{T,N} <: DenseArray{T,N} loc_subarr_1d::SubArray{T,1,Array{T,1},Tuple{UnitRange{Int}},true} function SharedArray{T,N}(d,p,r,sn,s) where {T,N} - new(d,p,r,sn,s,0,view(Array{T}(ntuple(d->0,N)), 1:0)) + S = new(RRID(),d,p,r,sn,s,0,view(Array{T}(ntuple(d->0,N)), 1:0)) + sa_refs[S.id] = WeakRef(S) + S end end +const sa_refs = Dict{RRID, WeakRef}() + """ SharedArray{T}(dims::NTuple; init=false, pids=Int[]) SharedArray{T,N}(...) @@ -45,6 +51,9 @@ computation with the master process acting as a driver. If an `init` function of the type `initfn(S::SharedArray)` is specified, it is called on all the participating workers. +The shared array is valid as long as a reference to the `SharedArray` object exists on the node +which created the mapping. + SharedArray{T}(filename::AbstractString, dims::NTuple, [offset=0]; mode=nothing, init=false, pids=Int[]) SharedArray{T,N}(...) @@ -246,10 +255,12 @@ function finalize_refs(S::SharedArray{T,N}) where T where N empty!(S.refs) init_loc_flds(S) S.s = Array{T}(ntuple(d->0,N)) + delete!(sa_refs, S.id) end S end + const SharedVector{T} = SharedArray{T,1} const SharedMatrix{T} = SharedArray{T,2} @@ -402,6 +413,17 @@ end # pidx, which is relevant to the current process only function serialize(s::AbstractSerializer, S::SharedArray) serialize_cycle_header(s, S) && return + + destpid = worker_id_from_socket(s.io) + if S.id.whence == destpid + # The shared array was created from destpid, hence a reference to it + # must be available at destpid. + serialize(s, true) + serialize(s, S.id.whence) + serialize(s, S.id.id) + return + end + serialize(s, false) for n in fieldnames(SharedArray) if n in [:s, :pidx, :loc_subarr_1d] writetag(s.io, UNDEFREF_TAG) @@ -421,9 +443,18 @@ function serialize(s::AbstractSerializer, S::SharedArray) end function deserialize(s::AbstractSerializer, t::Type{<:SharedArray}) + ref_exists = deserialize(s) + if ref_exists + sref = sa_refs[RRID(deserialize(s), deserialize(s))] + if sref.value !== nothing + return sref.value + end + error("Expected reference to shared array instance not found") + end + S = invoke(deserialize, Tuple{AbstractSerializer,DataType}, s, t) init_loc_flds(S, true) - S + return S end function show(io::IO, S::SharedArray) diff --git a/test/distributed_exec.jl b/test/distributed_exec.jl index febc80d4301f6..be074fedc9998 100644 --- a/test/distributed_exec.jl +++ b/test/distributed_exec.jl @@ -547,6 +547,18 @@ d = SharedArray{Int}(10) finalize(d) @test_throws BoundsError d[1] +# Issue 22139 +aorig = a1 = SharedArray{Float64}((3, 3)) +a1 = remotecall_fetch(fill!, id_other, a1, 1.0) +@test object_id(aorig) == object_id(a1) +id = a1.id +aorig = nothing +a1 = remotecall_fetch(fill!, id_other, a1, 1.0) +gc(); gc() +a1 = remotecall_fetch(fill!, id_other, a1, 1.0) +@test haskey(Base.sa_refs, id) +finalize(a1) +@test !haskey(Base.sa_refs, id) # Test @parallel load balancing - all processors should get either M or M+1 # iterations out of the loop range for some M. From 60c0d9f88ae6ed6c955daa666fbcdfb3d2a7d0f0 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Thu, 1 Jun 2017 04:13:42 -0500 Subject: [PATCH 0968/1534] Generalize UnitRange->AbstractUnitRange in sparse indexing Fixes #22173 --- base/sparse/sparsevector.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/base/sparse/sparsevector.jl b/base/sparse/sparsevector.jl index d4f43de229667..05eca53334792 100644 --- a/base/sparse/sparsevector.jl +++ b/base/sparse/sparsevector.jl @@ -455,7 +455,7 @@ function getindex(x::SparseMatrixCSC, ::Colon, j::Integer) SparseVector(x.m, x.rowval[r1:r2], x.nzval[r1:r2]) end -function getindex(x::SparseMatrixCSC, I::UnitRange, j::Integer) +function getindex(x::SparseMatrixCSC, I::AbstractUnitRange, j::Integer) checkbounds(x, I, j) # Get the selected column c1 = convert(Int, x.colptr[j]) @@ -548,7 +548,7 @@ end # TODO: further optimizations are available for ::Colon and other types of Range getindex(A::SparseMatrixCSC, ::Colon) = A[1:end] -function getindex(A::SparseMatrixCSC{Tv}, I::UnitRange) where Tv +function getindex(A::SparseMatrixCSC{Tv}, I::AbstractUnitRange) where Tv checkbounds(A, I) szA = size(A) nA = szA[1]*szA[2] @@ -685,7 +685,7 @@ function getindex(x::AbstractSparseVector, i::Integer) _spgetindex(nnz(x), nonzeroinds(x), nonzeros(x), i) end -function getindex(x::AbstractSparseVector{Tv,Ti}, I::UnitRange) where {Tv,Ti} +function getindex(x::AbstractSparseVector{Tv,Ti}, I::AbstractUnitRange) where {Tv,Ti} checkbounds(x, I) xlen = length(x) i0 = first(I) From 6ae55fb34f0da8077bb44e1873d56cd885709281 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Sun, 21 May 2017 16:22:49 +0200 Subject: [PATCH 0969/1534] Fix Period objects hashing to match == == is supported between FixedPeriod and OtherPeriod objects, but equal periods were hashed to different values when their types were different. Overflows can happen when converting to a more precise period, and generate a hash collision, but only for really long periods. Collisions will only happen between periods which are congruent modulo a very large value (300,000 years or more), meaning this should not be a problem in practice. --- base/dates/periods.jl | 12 +++++++++++- test/dates/periods.jl | 21 +++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/base/dates/periods.jl b/base/dates/periods.jl index 27eafa5774ea1..b34517e3734c0 100644 --- a/base/dates/periods.jl +++ b/base/dates/periods.jl @@ -443,10 +443,20 @@ Base.promote_rule(::Type{Year}, ::Type{Month}) = Month (==)(x::FixedPeriod, y::OtherPeriod) = throw(MethodError(==, (x, y))) (==)(x::OtherPeriod, y::FixedPeriod) = throw(MethodError(==, (x, y))) +const fixedperiod_seed = UInt === UInt64 ? 0x5b7fc751bba97516 : 0xeae0fdcb +const otherperiod_seed = UInt === UInt64 ? 0xe1837356ff2d2ac9 : 0x170d1b00 +# tons() will overflow for periods longer than ~300,000 years, implying a hash collision +# which is relatively harmless given how infrequent such periods should appear +Base.hash(x::FixedPeriod, h::UInt) = hash(tons(x), h + fixedperiod_seed) +# Overflow can also happen here for really long periods (~8e17 years) +Base.hash(x::Year, h::UInt) = hash(12 * value(x), h + otherperiod_seed) +Base.hash(x::Month, h::UInt) = hash(value(x), h + otherperiod_seed) + Base.isless(x::FixedPeriod, y::OtherPeriod) = throw(MethodError(isless, (x, y))) Base.isless(x::OtherPeriod, y::FixedPeriod) = throw(MethodError(isless, (x, y))) -# truncating conversions to milliseconds and days: +# truncating conversions to milliseconds, nanoseconds and days: +# overflow can happen for periods longer than ~300,000 years toms(c::Nanosecond) = div(value(c), 1000000) toms(c::Microsecond) = div(value(c), 1000) toms(c::Millisecond) = value(c) diff --git a/test/dates/periods.jl b/test/dates/periods.jl index 72ce644003870..f8c068e39e032 100644 --- a/test/dates/periods.jl +++ b/test/dates/periods.jl @@ -394,3 +394,24 @@ cpa = [1y + 1s 1m + 1s 1w + 1s 1d + 1s; 1h + 1s 1mi + 1s 2m + 1s 1s + 1ms] @test [1y + 1s 1m + 1s; 1w + 1s 1d + 1s] + [1y + 1h 1y + 1mi; 1y + 1s 1y + 1ms] == [2y + 1h + 1s 1y + 1m + 1mi + 1s; 1y + 1w + 2s 1y + 1d + 1s + 1ms] @test [1y + 1s 1m + 1s; 1w + 1s 1d + 1s] - [1y + 1h 1y + 1mi; 1y + 1s 1y + 1ms] == [1s-1h 1m + 1s-1y-1mi; 1w-1y 1d + 1s-1y-1ms] + +# Equality and hashing between FixedPeriod types +let types = (Dates.Week, Dates.Day, Dates.Hour, Dates.Minute, + Dates.Second, Dates.Millisecond, Dates.Microsecond, Dates.Nanosecond) + for i in 1:length(types), j in i:length(types), x in (0, 1, 235, -4677, 15250) + T = types[i] + U = types[j] + y = T(x) + z = convert(U, y) + @test y == z + @test hash(y) == hash(z) + end +end + +# Equality and hashing between OtherPeriod types +for x in (0, 1, 235, -4677, 15250) + y = Dates.Year(x) + z = convert(Dates.Month, y) + @test y == z + @test hash(y) == hash(z) +end From 60675d27c656a1262c190da10036b8790fc185d6 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 31 May 2017 19:10:03 -0400 Subject: [PATCH 0970/1534] fix some macro expander issues with new 0.6 syntax fixes #22135, fixes #22122, fixes #22026, fixes #21581, fixes #16096, fixes #19351 --- base/essentials.jl | 10 +++- src/julia-parser.scm | 2 +- src/julia-syntax.scm | 24 +++++---- src/macroexpand.scm | 120 ++++++++++++++++++++++++++++++++++--------- test/core.jl | 62 ++++++++++++++++++++++ test/parse.jl | 20 ++++++++ test/staged.jl | 4 ++ 7 files changed, 206 insertions(+), 36 deletions(-) diff --git a/base/essentials.jl b/base/essentials.jl index c5322273ba4a5..200cd702c42d0 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -34,9 +34,17 @@ convert(::Type{Tuple{Vararg{T}}}, x::Tuple) where {T} = cnvt_all(T, x...) cnvt_all(T) = () cnvt_all(T, x, rest...) = tuple(convert(T,x), cnvt_all(T, rest...)...) +# test whether an assignment LHS is a function definition +function eventually_call(ex) + isa(ex, Expr) && (ex.head === :call || + ((ex.head === :where || ex.head === :(::)) && + eventually_call(ex.args[1]))) +end + macro generated(f) isa(f, Expr) || error("invalid syntax; @generated must be used with a function definition") - if f.head === :function || (isdefined(:length) && f.head === :(=) && length(f.args) == 2 && f.args[1].head == :call) + if f.head === :function || (isdefined(:length) && f.head === :(=) && length(f.args) == 2 && + eventually_call(f.args[1])) f.head = :stagedfunction return Expr(:escape, f) else diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 7e05db3f7ff89..264a9ca6d3e3e 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -613,7 +613,7 @@ (define (eventually-call ex) (and (pair? ex) (or (eq? (car ex) 'call) - (and (eq? (car ex) 'where) + (and (or (eq? (car ex) 'where) (eq? (car ex) '|::|)) (eventually-call (cadr ex)))))) ;; insert line/file for short-form function defs, otherwise leave alone diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 7f9a5085f2a97..ea07a40bae3d3 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -828,18 +828,18 @@ (pattern-replace (pattern-set ;; definitions without `where` - (pattern-lambda (function (call name . sig) body) + (pattern-lambda (function (-$ (call name . sig) (|::| (call name . sig) _t)) body) (ctor-def (car __) name Tname params bounds sig ctor-body body #f)) - (pattern-lambda (stagedfunction (call name . sig) body) + (pattern-lambda (stagedfunction (-$ (call name . sig) (|::| (call name . sig) _t)) body) (ctor-def (car __) name Tname params bounds sig ctor-body body #f)) - (pattern-lambda (= (call name . sig) body) + (pattern-lambda (= (-$ (call name . sig) (|::| (call name . sig) _t)) body) (ctor-def 'function name Tname params bounds sig ctor-body body #f)) ;; definitions with `where` - (pattern-lambda (function (where (call name . sig) . wheres) body) + (pattern-lambda (function (where (-$ (call name . sig) (|::| (call name . sig) _t)) . wheres) body) (ctor-def (car __) name Tname params bounds sig ctor-body body wheres)) - (pattern-lambda (stagedfunction (where (call name . sig) . wheres) body) + (pattern-lambda (stagedfunction (where (-$ (call name . sig) (|::| (call name . sig) _t)) . wheres) body) (ctor-def (car __) name Tname params bounds sig ctor-body body wheres)) - (pattern-lambda (= (where (call name . sig) . wheres) body) + (pattern-lambda (= (where (-$ (call name . sig) (|::| (call name . sig) _t)) . wheres) body) (ctor-def 'function name Tname params bounds sig ctor-body body wheres))) ;; flatten `where`s first @@ -1329,10 +1329,13 @@ e (expand-forms (expand-decls (car e) (cdr e) #f)))) +;; given a complex assignment LHS, return the symbol that will ultimately be assigned to (define (assigned-name e) - (if (and (pair? e) (memq (car e) '(call curly))) - (assigned-name (cadr e)) - e)) + (cond ((atom? e) e) + ((or (memq (car e) '(call curly where)) + (and (eq? (car e) '|::|) (eventually-call e))) + (assigned-name (cadr e))) + (else e))) ;; local x, y=2, z => local x;local y;local z;y = 2 (define (expand-decls what binds const?) @@ -2428,7 +2431,8 @@ (else '()))) (define (all-decl-vars e) ;; map decl-var over every level of an assignment LHS - (cond ((decl? e) (decl-var e)) + (cond ((eventually-call e) e) + ((decl? e) (decl-var e)) ((and (pair? e) (eq? (car e) 'tuple)) (cons 'tuple (map all-decl-vars (cdr e)))) (else e))) diff --git a/src/macroexpand.scm b/src/macroexpand.scm index 62d6b611bf097..8f2ad5784bb87 100644 --- a/src/macroexpand.scm +++ b/src/macroexpand.scm @@ -54,16 +54,15 @@ ;; function with static parameters (pattern-lambda (function (call (curly name . sparams) . argl) body) - (cons 'varlist (append (llist-vars (fix-arglist argl)) - (apply nconc - (map (lambda (v) (trycatch - (list (typevar-expr-name v)) - (lambda (e) '()))) - sparams))))) + (cons 'varlist (append (safe-llist-positional-args (fix-arglist argl)) + (typevar-names sparams)))) ;; function definition - (pattern-lambda (function (call name . argl) body) - (cons 'varlist (llist-vars (fix-arglist argl)))) + (pattern-lambda (function (-$ (call name . argl) (|::| (call name . argl) _t)) body) + (cons 'varlist (safe-llist-positional-args (fix-arglist argl)))) + (pattern-lambda (function (where (-$ (call name . argl) (|::| (call name . argl) _t)) . wheres) body) + (cons 'varlist (append (safe-llist-positional-args (fix-arglist argl)) + (typevar-names wheres)))) (pattern-lambda (function (tuple . args) body) `(-> (tuple ,@args) ,body)) @@ -71,8 +70,10 @@ ;; expression form function definition (pattern-lambda (= (call (curly name . sparams) . argl) body) `(function (call (curly ,name . ,sparams) . ,argl) ,body)) - (pattern-lambda (= (call name . argl) body) + (pattern-lambda (= (-$ (call name . argl) (|::| (call name . argl) _t)) body) `(function (call ,name ,@argl) ,body)) + (pattern-lambda (= (where (-$ (call name . argl) (|::| (call name . argl) _t)) . wheres) body) + (cons 'function (cdr __))) ;; anonymous function (pattern-lambda (-> a b) @@ -80,7 +81,11 @@ (eq? (car a) 'tuple)) (cdr a) (list a)))) - (cons 'varlist (llist-vars (fix-arglist a))))) + (cons 'varlist (safe-llist-positional-args (fix-arglist a))))) + + ;; where + (pattern-lambda (where ex . vars) + (cons 'varlist (typevar-names vars))) ;; let (pattern-lambda (let ex . binds) @@ -127,10 +132,10 @@ ;; type definition (pattern-lambda (type mut (<: (curly tn . tvars) super) body) (list* 'varlist (cons (unescape tn) (unescape tn)) '(new . new) - (map typevar-expr-name tvars))) + (typevar-names tvars))) (pattern-lambda (type mut (curly tn . tvars) body) (list* 'varlist (cons (unescape tn) (unescape tn)) '(new . new) - (map typevar-expr-name tvars))) + (typevar-names tvars))) (pattern-lambda (type mut (<: tn super) body) (list 'varlist (cons (unescape tn) (unescape tn)) '(new . new))) (pattern-lambda (type mut tn body) @@ -141,15 +146,19 @@ (define keywords-introduced-by-patterns (pattern-set (pattern-lambda (function (call (curly name . sparams) . argl) body) - (cons 'varlist (llist-keywords (fix-arglist argl)))) + (cons 'varlist (safe-llist-keyword-args (fix-arglist argl)))) - (pattern-lambda (function (call name . argl) body) - (cons 'varlist (llist-keywords (fix-arglist argl)))) + (pattern-lambda (function (-$ (call name . argl) (|::| (call name . argl) _t)) body) + (cons 'varlist (safe-llist-keyword-args (fix-arglist argl)))) + (pattern-lambda (function (where (-$ (call name . argl) (|::| (call name . argl) _t)) . wheres) body) + (cons 'varlist (safe-llist-keyword-args (fix-arglist argl)))) (pattern-lambda (= (call (curly name . sparams) . argl) body) `(function (call (curly ,name . ,sparams) . ,argl) ,body)) - (pattern-lambda (= (call name . argl) body) + (pattern-lambda (= (-$ (call name . argl) (|::| (call name . argl) _t)) body) `(function (call ,name ,@argl) ,body)) + (pattern-lambda (= (where (-$ (call name . argl) (|::| (call name . argl) _t)) . wheres) body) + (cons 'function (cdr __))) )) (define (pair-with-gensyms v) @@ -166,6 +175,70 @@ (define (typevar-expr-name e) (car (analyze-typevar e))) +;; get the list of names from a list of `where` variable expressions +(define (typevar-names lst) + (apply nconc + (map (lambda (v) (trycatch + (list (typevar-expr-name v)) + (lambda (e) '()))) + lst))) + +;; get the name from a function formal argument expression, allowing `(escape x)` +(define (try-arg-name v) + (cond ((and (symbol? v) (not (eq? v 'true)) (not (eq? v 'false))) + (list v)) + ((atom? v) '()) + (else + (case (car v) + ((... kw |::|) (try-arg-name (cadr v))) + ((escape) (list v)) + (else '()))))) + +;; get names from a formal argument list, specifying whether to include escaped ones +(define (safe-arg-names lst (escaped #f)) + (apply nconc + (map (lambda (v) + (let ((vv (try-arg-name v))) + (if (eq? escaped (and (pair? vv) (pair? (car vv)) (eq? (caar vv) 'escape))) + (if escaped (list (cadar vv)) vv) + '()))) + lst))) + +;; arg names, looking only at positional args +(define (safe-llist-positional-args lst (escaped #f)) + (safe-arg-names + (filter (lambda (a) (not (and (pair? a) + (eq? (car a) 'parameters)))) + lst) + escaped)) + +;; arg names from keyword arguments, and positional arguments with escaped names +(define (safe-llist-keyword-args lst) + (let ((kwargs (apply nconc + (map cdr + (filter (lambda (a) (and (pair? a) (eq? (car a) 'parameters))) + lst))))) + (append + (safe-arg-names kwargs #f) + (safe-arg-names kwargs #t) + ;; count escaped argument names as "keywords" to prevent renaming + (safe-llist-positional-args lst #t)))) + +;; resolve-expansion-vars-with-new-env, but turn on `inarg` once we get inside +;; the formal argument list. `e` in general might be e.g. `(f{T}(x)::T) where T`, +;; and we want `inarg` to be true for the `(x)` part. +(define (resolve-in-function-lhs e env m inarg) + (define (recur x) (resolve-in-function-lhs x env m inarg)) + (define (other x) (resolve-expansion-vars-with-new-env x env m inarg)) + (case (car e) + ((where) `(where ,(recur (cadr e)) ,@(map other (cddr e)))) + ((|::|) `(|::| ,(recur (cadr e)) ,(other (caddr e)))) + ((call) `(call ,(other (cadr e)) + ,@(map (lambda (x) + (resolve-expansion-vars-with-new-env x env m #t)) + (cddr e)))) + (else (other e)))) + (define (new-expansion-env-for x env (outermost #f)) (let ((introduced (pattern-expand1 vars-introduced-by-patterns x))) (if (or (atom? x) @@ -252,12 +325,9 @@ (cdr e)))) ((= function) - (if (and (pair? (cadr e)) (eq? (caadr e) 'call)) + (if (and (pair? (cadr e)) (function-def? e)) ;; in (kw x 1) inside an arglist, the x isn't actually a kwarg - `(,(car e) (call ,(resolve-expansion-vars-with-new-env (cadadr e) env m inarg) - ,@(map (lambda (x) - (resolve-expansion-vars-with-new-env x env m #t)) - (cddr (cadr e)))) + `(,(car e) ,(resolve-in-function-lhs (cadr e) env m inarg) ,(resolve-expansion-vars-with-new-env (caddr e) env m inarg)) `(,(car e) ,@(map (lambda (x) (resolve-expansion-vars-with-new-env x env m inarg)) @@ -308,6 +378,8 @@ ((eq? (car e) 'call) (decl-var* (cadr e))) ((eq? (car e) '=) (decl-var* (cadr e))) ((eq? (car e) 'curly) (decl-var* (cadr e))) + ((eq? (car e) '|::|) (decl-var* (cadr e))) + ((eq? (car e) 'where) (decl-var* (cadr e))) (else (decl-var e)))) (define (decl-vars* e) @@ -318,7 +390,7 @@ (define (function-def? e) (and (pair? e) (or (eq? (car e) 'function) (eq? (car e) '->) (and (eq? (car e) '=) (length= e 3) - (pair? (cadr e)) (eq? (caadr e) 'call))))) + (eventually-call (cadr e)))))) (define (find-declared-vars-in-expansion e decl (outer #t)) (cond ((or (not (pair? e)) (quoted? e)) '()) @@ -335,11 +407,11 @@ ((eq? (car e) 'escape) '()) ((and (not outer) (function-def? e)) ;; pick up only function name - (let ((fname (cond ((eq? (car e) '=) (cadr (cadr e))) + (let ((fname (cond ((eq? (car e) '=) (decl-var* (cadr e))) ((eq? (car e) 'function) (cond ((atom? (cadr e)) (cadr e)) ((eq? (car (cadr e)) 'tuple) #f) - (else (cadr (cadr e))))) + (else (decl-var* (cadr e))))) (else #f)))) (if (symbol? fname) (list fname) diff --git a/test/core.jl b/test/core.jl index 37afe6c68fb26..bf0d22504ddd5 100644 --- a/test/core.jl +++ b/test/core.jl @@ -5018,3 +5018,65 @@ for i in 1:10 @test ptr1 === ptr2 @test ptr1 % 16 == 0 end + +# issue #21581 +global function f21581()::Int + return 2.0 +end +@test f21581() === 2 +global g21581()::Int = 2.0 +@test g21581() === 2 +module M21581 +macro bar() + :(foo21581(x)::Int = x) +end +M21581.@bar +end +@test M21581.foo21581(1) === 1 + +module N21581 +macro foo(var) + quote + function f(x::T = 1) where T + ($(esc(var)), x) + end + f() + end +end +end +let x = 8 + @test @N21581.foo(x) === (8, 1) +end + +# issue #22122 +let + global @inline function f22122(x::T) where {T} + T + end +end +@test f22122(1) === Int + +# issue #22026 +module M22026 + +macro foo(TYP) + quote + global foofunction + foofunction(x::Type{T}) where {T<:Number} = x + end +end +struct Foo end +@foo Foo + +macro foo2() + quote + global foofunction2 + (foofunction2(x::T)::Float32) where {T<:Number} = 2x + end +end + +@foo2 + +end +@test M22026.foofunction(Int16) === Int16 +@test M22026.foofunction2(3) === 6.0f0 diff --git a/test/parse.jl b/test/parse.jl index c45e8e297a398..d1e335b9d7e30 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -762,6 +762,22 @@ end let ex = expand(:(@M16096.iter)) @test !(isa(ex,Expr) && ex.head === :error) end +macro f16096() + quote + g16096($(esc(:x))) = 2x + end +end +let g = @f16096 + @test g(3) == 6 +end +macro f16096_2() + quote + g16096_2(;$(esc(:x))=2) = 2x + end +end +let g = @f16096_2 + @test g() == 4 +end # issue #15838 module A15838 @@ -1195,3 +1211,7 @@ end # issue #16937 @test expand(:(f(2, a=1, w=3, c=3, w=4, b=2))) == Expr(:error, "keyword argument \"w\" repeated in call to \"f\"") + +# issue #19351 +# adding return type decl should not affect parse of function body +@test :(t(abc) = 3).args[2] == :(t(abc)::Int = 3).args[2] diff --git a/test/staged.jl b/test/staged.jl index 7d6a95ff8b145..ba62fc2d91816 100644 --- a/test/staged.jl +++ b/test/staged.jl @@ -224,3 +224,7 @@ g10178(x) = f10178(x) end g10178(x) = f10178(x) @test g10178(5) == 10 + +# issue #22135 +@generated f22135(x::T) where T = x +@test f22135(1) === Int From 03c5ad07f454ce5c644299289a9678ec95f413d7 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 31 May 2017 20:20:31 -0400 Subject: [PATCH 0971/1534] fix #22032, `for f() in 1:10 ...` --- src/julia-syntax.scm | 12 ++++++++++-- test/core.jl | 15 +++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 7f9a5085f2a97..d4d36af67e5b4 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -1404,8 +1404,16 @@ ,@(let loop ((lhs lhss) (i 1)) (if (null? lhs) '((null)) - (cons `(= ,(car lhs) - (call (core getfield) ,t ,i)) + (cons (if (eventually-call (car lhs)) + ;; if this is a function assignment, avoid putting our ssavalue + ;; inside the function and instead create a capture-able variable. + ;; issue #22032 + (let ((temp (gensy))) + `(block + (= ,temp (call (core getfield) ,t ,i)) + (= ,(car lhs) ,temp))) + `(= ,(car lhs) + (call (core getfield) ,t ,i))) (loop (cdr lhs) (+ i 1))))) ,t))) diff --git a/test/core.jl b/test/core.jl index 37afe6c68fb26..6f69e3b0273cf 100644 --- a/test/core.jl +++ b/test/core.jl @@ -539,6 +539,21 @@ end @test a[2](10) == 12 @test a[3](10) == 13 +# issue #22032 +let a = [], fs = [] + for f() in 1:3 + push!(a, f()) + push!(fs, f) + end + @test a == [1,2,3] + @test [f() for f in fs] == [1,2,3] +end +let t = (22,33) + (g(), x) = t + @test g() == 22 + @test x == 33 +end + # issue #21900 f21900_cnt = 0 function f21900() From ecc3a811311f3a5bf4f5f45c1c5959bb581d26c2 Mon Sep 17 00:00:00 2001 From: Amit Murthy Date: Thu, 1 Jun 2017 21:18:08 +0530 Subject: [PATCH 0972/1534] serialize global bindings to Types and Modules (#22172) --- base/distributed/clusterserialize.jl | 3 +-- test/distributed_exec.jl | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/base/distributed/clusterserialize.jl b/base/distributed/clusterserialize.jl index 0454e1e668bf5..163d8d9636284 100644 --- a/base/distributed/clusterserialize.jl +++ b/base/distributed/clusterserialize.jl @@ -89,8 +89,7 @@ function serialize(s::ClusterSerializer, g::GlobalRef) sym = g.name if g.mod === Main && isdefined(g.mod, sym) v = getfield(Main, sym) - if !isa(v, DataType) && !isa(v, Module) && - (binding_module(Main, sym) === Main) && (s.anonfunc_id != 0) + if (binding_module(Main, sym) === Main) && (s.anonfunc_id != 0) push!(get!(s.glbs_in_tnobj, s.anonfunc_id, []), sym) end end diff --git a/test/distributed_exec.jl b/test/distributed_exec.jl index be074fedc9998..4583fbf237d31 100644 --- a/test/distributed_exec.jl +++ b/test/distributed_exec.jl @@ -1424,6 +1424,27 @@ global v4 = v3 @test remotecall_fetch(()->isdefined(Main, :v3), id_other) @test remotecall_fetch(()->isdefined(Main, :v4), id_other) +# Global references to Types and Modules should work if they are locally defined +global v5 = Int +global v6 = Base.Distributed +@test remotecall_fetch(()->v5, id_other) === Int +@test remotecall_fetch(()->v6, id_other) === Base.Distributed + +struct FooStructLocal end +module FooModLocal end +v5 = FooStructLocal +v6 = FooModLocal +@test_throws RemoteException remotecall_fetch(()->v5, id_other) +@test_throws RemoteException remotecall_fetch(()->v6, id_other) + +@everywhere struct FooStructEverywhere end +@everywhere module FooModEverywhere end +v5 = FooStructEverywhere +v6 = FooModEverywhere +@test remotecall_fetch(()->v5, id_other) === FooStructEverywhere +@test remotecall_fetch(()->v6, id_other) === FooModEverywhere + + # Test that a global is not being repeatedly serialized when # a) referenced multiple times in the closure # b) hash value has not changed. From ab771ef3b4cfecf4bd4c899b87d613dab45f5040 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 1 Jun 2017 15:39:58 -0400 Subject: [PATCH 0973/1534] add help text for the `where` keyword (#22177) --- base/docs/basedocs.jl | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index ece074d231a1a..8cadb4d1d0b72 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -644,6 +644,36 @@ to be set after construction. See `struct` and the manual for more information. """ kw"mutable struct" +""" +The `where` keyword creates a type that is an iterated union of other types, over all +values of some variable. For example `Vector{T} where T<:Real` includes all `Vector`s +where the element type is some kind of `Real` number. + +The variable bound defaults to `Any` if it is omitted: + + Vector{T} where T # short for `where T<:Any` + +Variables can also have lower bounds: + + Vector{T} where T>:Int + Vector{T} where Int<:T<:Real + +There is also a concise syntax for nested `where` expressions. For example, this: + + Pair{T, S} where S<:Array{T} where T<:Number + +can be shortened to: + + Pair{T, S} where {T<:Number, S<:Array{T}} + +This form is often found on method signatures. + +Note that in this form, the variables are listed outermost-first. This matches the +order in which variables are substituted when a type is "applied" to parameter values +using the syntax `T{p1, p2, ...}`. +""" +kw"where" + """ ans From f1878c16d3e9d9d2a91aecf6b079032f5b294b7a Mon Sep 17 00:00:00 2001 From: Alexey Stukalov Date: Thu, 1 Jun 2017 22:31:28 +0200 Subject: [PATCH 0974/1534] LAPACK wrappers: use resize!(a) instead of a = Vector{T}() (#21938) * BLAS wrappers: resize!() instead of Vector{T}() - replace a = Vector{T}(n) with resize!(a, n) - add comments when BLAS API method is called twice * lapack.sygvd!(): fix rwork type --- base/linalg/lapack.jl | 266 +++++++++++++++++++++--------------------- 1 file changed, 133 insertions(+), 133 deletions(-) diff --git a/base/linalg/lapack.jl b/base/linalg/lapack.jl index 1f9c71488a773..aaec8c49d51fb 100644 --- a/base/linalg/lapack.jl +++ b/base/linalg/lapack.jl @@ -285,7 +285,7 @@ for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt, geqrt3, gerqf, getrf, elty, relty work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($gebrd), liblapack), Void, (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$relty}, Ptr{$relty}, Ptr{$elty}, Ptr{$elty}, @@ -296,7 +296,7 @@ for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt, geqrt3, gerqf, getrf, elty, relty chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end A, d, e, tauq, taup @@ -326,7 +326,7 @@ for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt, geqrt3, gerqf, getrf, elty, relty chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end A, tau @@ -356,7 +356,7 @@ for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt, geqrt3, gerqf, getrf, elty, relty chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end A, tau @@ -388,7 +388,7 @@ for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt, geqrt3, gerqf, getrf, elty, relty rwork = Vector{$relty}(2n) end info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] if cmplx ccall((@blasfunc($geqp3), liblapack), Void, (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, @@ -409,7 +409,7 @@ for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt, geqrt3, gerqf, getrf, elty, relty chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end return A, tau, jpvt @@ -485,7 +485,7 @@ for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt, geqrt3, gerqf, getrf, elty, relty chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end A, tau @@ -513,7 +513,7 @@ for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt, geqrt3, gerqf, getrf, elty, relty chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end A, tau @@ -761,7 +761,7 @@ for (tzrzf, ormrz, elty) in work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($tzrzf), liblapack), Void, (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), @@ -770,7 +770,7 @@ for (tzrzf, ormrz, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end A, tau @@ -798,7 +798,7 @@ for (tzrzf, ormrz, elty) in work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($ormrz), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, @@ -811,7 +811,7 @@ for (tzrzf, ormrz, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end C @@ -862,7 +862,7 @@ for (gels, gesv, getrs, getri, elty) in info = Ref{BlasInt}() work = Vector{$elty}(1) lwork = BlasInt(-1) - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($gels), liblapack), Void, (Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, @@ -872,7 +872,7 @@ for (gels, gesv, getrs, getri, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end k = min(m, n) @@ -951,7 +951,7 @@ for (gels, gesv, getrs, getri, elty) in lwork = BlasInt(-1) work = Vector{$elty}(1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($getri), liblapack), Void, (Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), @@ -959,7 +959,7 @@ for (gels, gesv, getrs, getri, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end A @@ -1211,7 +1211,7 @@ for (gelsd, gelsy, elty) in work = Vector{$elty}(1) lwork = BlasInt(-1) iwork = Vector{BlasInt}(1) - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] and iwork length as iwork[1] ccall((@blasfunc($gelsd), liblapack), Void, (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, @@ -1222,8 +1222,8 @@ for (gelsd, gelsy, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) - iwork = Vector{BlasInt}(iwork[1]) + resize!(work, lwork) + resize!(iwork, iwork[1]) end end subsetrows(B, newB, n), rnk[1] @@ -1255,7 +1255,7 @@ for (gelsd, gelsy, elty) in work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($gelsy), liblapack), Void, (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, @@ -1268,7 +1268,7 @@ for (gelsd, gelsy, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(work[1]) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end subsetrows(B, newB, n), rnk[1] @@ -1305,7 +1305,7 @@ for (gelsd, gelsy, elty, relty) in lwork = BlasInt(-1) rwork = Vector{$relty}(1) iwork = Vector{BlasInt}(1) - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1], rwork length as rwork[1] and iwork length as iwork[1] ccall((@blasfunc($gelsd), liblapack), Void, (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$relty}, @@ -1316,9 +1316,9 @@ for (gelsd, gelsy, elty, relty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) - rwork = Vector{$relty}(BlasInt(rwork[1])) - iwork = Vector{BlasInt}(iwork[1]) + resize!(work, lwork) + resize!(rwork, BlasInt(rwork[1])) + resize!(iwork, iwork[1]) end end subsetrows(B, newB, n), rnk[1] @@ -1351,7 +1351,7 @@ for (gelsd, gelsy, elty, relty) in lwork = BlasInt(-1) rwork = Vector{$relty}(2n) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($gelsy), liblapack), Void, (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, @@ -1364,7 +1364,7 @@ for (gelsd, gelsy, elty, relty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end subsetrows(B, newB, n), rnk[1] @@ -1425,7 +1425,7 @@ for (gglse, elty) in ((:dgglse_, :Float64), info = Ref{BlasInt}() work = Vector{$elty}(1) lwork = BlasInt(-1) - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($gglse), liblapack), Void, (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, @@ -1436,7 +1436,7 @@ for (gglse, elty) in ((:dgglse_, :Float64), chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end X, dot(view(c, n - p + 1:m), view(c, n - p + 1:m)) @@ -1487,7 +1487,7 @@ for (geev, gesvd, gesdd, ggsvd, elty, relty) in work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] if cmplx ccall((@blasfunc($geev), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, @@ -1508,7 +1508,7 @@ for (geev, gesvd, gesdd, ggsvd, elty, relty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end cmplx ? (W, VL, VR) : (WR, WI, VL, VR) @@ -1551,7 +1551,7 @@ for (geev, gesvd, gesdd, ggsvd, elty, relty) in end iwork = Vector{BlasInt}(8*minmn) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] if cmplx ccall((@blasfunc($gesdd), liblapack), Void, (Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, @@ -1577,7 +1577,7 @@ for (geev, gesvd, gesdd, ggsvd, elty, relty) in # and # https://github.com/scipy/scipy/issues/5401 lwork = round(BlasInt, nextfloat(real(work[1]))) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end if job == 'O' @@ -1619,7 +1619,7 @@ for (geev, gesvd, gesdd, ggsvd, elty, relty) in end lwork = BlasInt(-1) info = Ref{BlasInt}() - for i in 1:2 + for i in 1:2 # first call returns lwork as work[1] if cmplx ccall((@blasfunc($gesvd), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, @@ -1640,7 +1640,7 @@ for (geev, gesvd, gesdd, ggsvd, elty, relty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end if jobu == 'O' @@ -1818,7 +1818,7 @@ for (f, elty) in ((:dggsvd3_, :Float64), lwork = BlasInt(-1) iwork = Vector{BlasInt}(n) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($f), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ref{BlasInt}, Ref{BlasInt}, @@ -1875,7 +1875,7 @@ for (f, elty, relty) in ((:zggsvd3_, :Complex128, :Float64), rwork = Vector{$relty}(2n) iwork = Vector{BlasInt}(n) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($f), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, @@ -1894,7 +1894,7 @@ for (f, elty, relty) in ((:zggsvd3_, :Complex128, :Float64), chklapackerror(info[]) if i == 1 lwork = BlasInt(work[1]) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end if m - k[1] - l[1] >= 0 @@ -1983,7 +1983,7 @@ for (geevx, ggev, elty) in end iwork = Vector{BlasInt}(iworksize) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($geevx), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, @@ -2000,7 +2000,7 @@ for (geevx, ggev, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(work[1]) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end A, wr, wi, VL, VR, ilo[], ihi[], scale, abnrm[], rconde, rcondv @@ -2048,7 +2048,7 @@ for (geevx, ggev, elty) in work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($ggev), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, @@ -2063,7 +2063,7 @@ for (geevx, ggev, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(work[1]) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end alphar, alphai, beta, vl, vr @@ -2128,7 +2128,7 @@ for (geevx, ggev, elty, relty) in lwork = BlasInt(-1) rwork = Vector{$relty}(2n) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($geevx), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, @@ -2145,7 +2145,7 @@ for (geevx, ggev, elty, relty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(work[1]) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end A, w, VL, VR, ilo[], ihi[], scale, abnrm[], rconde, rcondv @@ -2194,7 +2194,7 @@ for (geevx, ggev, elty, relty) in lwork = BlasInt(-1) rwork = Vector{$relty}(8n) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($ggev), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, @@ -2209,7 +2209,7 @@ for (geevx, ggev, elty, relty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(work[1]) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end alpha, beta, vl, vr @@ -2464,7 +2464,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($orglq), liblapack), Void, (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), @@ -2472,7 +2472,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end if m < size(A,1) @@ -2497,7 +2497,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($orgqr), liblapack), Void, (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), @@ -2507,7 +2507,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end if n < size(A,2) @@ -2532,7 +2532,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($orgql), liblapack), Void, (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), @@ -2542,7 +2542,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end if n < size(A,2) @@ -2567,7 +2567,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($orgrq), liblapack), Void, (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), @@ -2577,7 +2577,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end if n < size(A,2) @@ -2617,7 +2617,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($ormlq), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, @@ -2627,7 +2627,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end C @@ -2663,7 +2663,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($ormqr), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, @@ -2676,7 +2676,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end C @@ -2712,7 +2712,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($ormql), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, @@ -2725,7 +2725,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end C @@ -2761,7 +2761,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($ormrq), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, @@ -2771,7 +2771,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end C @@ -3690,7 +3690,7 @@ for (stev, stebz, stegr, stein, elty) in iwork = Vector{BlasInt}(1) liwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] and liwork as iwork[1] ccall((@blasfunc($stegr), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, @@ -3705,9 +3705,9 @@ for (stev, stebz, stegr, stein, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(work[1]) - work = Vector{$elty}(lwork) + resize!(work, lwork) liwork = iwork[1] - iwork = Vector{BlasInt}(liwork) + resize!(iwork, liwork) end end m[] == length(w) ? w : w[1:m[]], m[] == size(Z, 2) ? Z : Z[:,1:m[]] @@ -3863,7 +3863,7 @@ for (syconv, sysv, sytrf, sytri, sytrs, elty) in work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($sysv), liblapack), Void, (Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), @@ -3873,7 +3873,7 @@ for (syconv, sysv, sytrf, sytri, sytrs, elty) in chknonsingular(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end B, A, ipiv @@ -3897,7 +3897,7 @@ for (syconv, sysv, sytrf, sytri, sytrs, elty) in work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($sytrf), liblapack), Void, (Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), @@ -3905,7 +3905,7 @@ for (syconv, sysv, sytrf, sytri, sytrs, elty) in chkargsok(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end return A, ipiv, info[] @@ -4013,7 +4013,7 @@ for (sysv, sytrf, sytri, sytrs, elty) in work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($sysv), liblapack), Void, (Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), @@ -4023,7 +4023,7 @@ for (sysv, sytrf, sytri, sytrs, elty) in chknonsingular(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end B, A, ipiv @@ -4047,7 +4047,7 @@ for (sysv, sytrf, sytri, sytrs, elty) in work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($sytrf), liblapack), Void, (Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), @@ -4055,7 +4055,7 @@ for (sysv, sytrf, sytri, sytrs, elty) in chkargsok(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end return A, ipiv, info[] @@ -4158,7 +4158,7 @@ for (syconv, hesv, hetrf, hetri, hetrs, elty, relty) in work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($hesv), liblapack), Void, (Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), @@ -4167,7 +4167,7 @@ for (syconv, hesv, hetrf, hetri, hetrs, elty, relty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end B, A, ipiv @@ -4189,7 +4189,7 @@ for (syconv, hesv, hetrf, hetri, hetrs, elty, relty) in work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i in 1:2 + for i in 1:2 # first call returns lwork as work[1] ccall((@blasfunc($hetrf), liblapack), Void, (Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), @@ -4197,7 +4197,7 @@ for (syconv, hesv, hetrf, hetri, hetrs, elty, relty) in chkargsok(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end A, ipiv, info[] @@ -4304,7 +4304,7 @@ for (hesv, hetrf, hetri, hetrs, elty, relty) in work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($hesv), liblapack), Void, (Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), @@ -4313,7 +4313,7 @@ for (hesv, hetrf, hetri, hetrs, elty, relty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end B, A, ipiv @@ -4335,7 +4335,7 @@ for (hesv, hetrf, hetri, hetrs, elty, relty) in work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i in 1:2 + for i in 1:2 # first call returns lwork as work[1] ccall((@blasfunc($hetrf), liblapack), Void, (Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), @@ -4343,7 +4343,7 @@ for (hesv, hetrf, hetri, hetrs, elty, relty) in chkargsok(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end A, ipiv, info[] @@ -4421,7 +4421,7 @@ for (sysv, sytrf, sytri, sytrs, elty, relty) in work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($sysv), liblapack), Void, (Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), @@ -4431,7 +4431,7 @@ for (sysv, sytrf, sytri, sytrs, elty, relty) in chknonsingular(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end B, A, ipiv @@ -4456,7 +4456,7 @@ for (sysv, sytrf, sytri, sytrs, elty, relty) in work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($sytrf), liblapack), Void, (Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), @@ -4464,7 +4464,7 @@ for (sysv, sytrf, sytri, sytrs, elty, relty) in chkargsok(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end A, ipiv, info[] @@ -4572,7 +4572,7 @@ for (sysv, sytrf, sytri, sytrs, elty, relty) in work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($sysv), liblapack), Void, (Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), @@ -4582,7 +4582,7 @@ for (sysv, sytrf, sytri, sytrs, elty, relty) in chknonsingular(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end B, A, ipiv @@ -4607,7 +4607,7 @@ for (sysv, sytrf, sytri, sytrs, elty, relty) in work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($sytrf), liblapack), Void, (Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), @@ -4615,7 +4615,7 @@ for (sysv, sytrf, sytri, sytrs, elty, relty) in chkargsok(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end A, ipiv, info[] @@ -4788,7 +4788,7 @@ for (syev, syevr, sygvd, elty) in work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($syev), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}), @@ -4796,7 +4796,7 @@ for (syev, syevr, sygvd, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end jobz == 'V' ? (W, A) : W @@ -4838,7 +4838,7 @@ for (syev, syevr, sygvd, elty) in iwork = Vector{BlasInt}(1) liwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] and liwork as iwork[1] ccall((@blasfunc($syevr), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, @@ -4855,9 +4855,9 @@ for (syev, syevr, sygvd, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) liwork = iwork[1] - iwork = Vector{BlasInt}(liwork) + resize!(iwork, liwork) end end w[1:m[]], Z[:,1:(jobz == 'V' ? m[] : 0)] @@ -4889,7 +4889,7 @@ for (syev, syevr, sygvd, elty) in iwork = Vector{BlasInt}(1) liwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] and liwork as iwork[1] ccall((@blasfunc($sygvd), liblapack), Void, (Ptr{BlasInt}, Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, @@ -4902,9 +4902,9 @@ for (syev, syevr, sygvd, elty) in chkargsok(info[]) if i == 1 lwork = BlasInt(work[1]) - work = Vector{$elty}(lwork) + resize!(work, lwork) liwork = iwork[1] - iwork = Vector{BlasInt}(liwork) + resize!(iwork, liwork) end end chkposdef(info[]) @@ -4933,7 +4933,7 @@ for (syev, syevr, sygvd, elty, relty) in lwork = BlasInt(-1) rwork = Vector{$relty}(max(1, 3n-2)) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($syev), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$relty}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$relty}, Ptr{BlasInt}), @@ -4941,7 +4941,7 @@ for (syev, syevr, sygvd, elty, relty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end jobz == 'V' ? (W, A) : W @@ -4988,7 +4988,7 @@ for (syev, syevr, sygvd, elty, relty) in iwork = Vector{BlasInt}(1) liwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1], lrwork as rwork[1] and liwork as iwork[1] ccall((@blasfunc($syevr), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, @@ -5005,11 +5005,11 @@ for (syev, syevr, sygvd, elty, relty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) lrwork = BlasInt(rwork[1]) - rwork = Vector{$relty}(lrwork) + resize!(rwork, lrwork) liwork = iwork[1] - iwork = Vector{BlasInt}(liwork) + resize!(iwork, liwork) end end w[1:m[]], Z[:,1:(jobz == 'V' ? m[] : 0)] @@ -5040,10 +5040,10 @@ for (syev, syevr, sygvd, elty, relty) in lwork = BlasInt(-1) iwork = Vector{BlasInt}(1) liwork = BlasInt(-1) - rwork = Array{$relty,0}() + rwork = Vector{$relty}(1) lrwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1], lrwork as rwork[1] and liwork as iwork[1] ccall((@blasfunc($sygvd), liblapack), Void, (Ptr{BlasInt}, Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, @@ -5056,11 +5056,11 @@ for (syev, syevr, sygvd, elty, relty) in chkargsok(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) liwork = iwork[1] - iwork = Vector{BlasInt}(liwork) + resize!(iwork, liwork) lrwork = BlasInt(rwork[1]) - rwork = Vector{$relty}(lrwork) + resize!(rwork, lrwork) end end chkposdef(info[]) @@ -5338,7 +5338,7 @@ for (gehrd, elty) in work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($gehrd), liblapack), Void, (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, @@ -5349,7 +5349,7 @@ for (gehrd, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end A, tau @@ -5388,7 +5388,7 @@ for (orghr, elty) in work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($orghr), liblapack), Void, (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{$elty}, Ptr{BlasInt}, @@ -5399,7 +5399,7 @@ for (orghr, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end A @@ -5444,7 +5444,7 @@ for (ormhr, elty) in work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($ormhr), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, @@ -5457,7 +5457,7 @@ for (ormhr, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end C @@ -5488,7 +5488,7 @@ for (gees, gges, elty) in work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($gees), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{Void}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, @@ -5501,7 +5501,7 @@ for (gees, gges, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end A, vs, iszero(wi) ? wr : complex.(wr, wi) @@ -5533,7 +5533,7 @@ for (gees, gges, elty) in work = Vector{$elty}(1) lwork = BlasInt(-1) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($gges), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{UInt8}, Ptr{Void}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, @@ -5550,7 +5550,7 @@ for (gees, gges, elty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end A, B, complex.(alphar, alphai), beta, vsl[1:(jobvsl == 'V' ? n : 0),:], vsr[1:(jobvsr == 'V' ? n : 0),:] @@ -5582,7 +5582,7 @@ for (gees, gges, elty, relty) in lwork = BlasInt(-1) rwork = Vector{$relty}(n) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($gees), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{Void}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, @@ -5595,7 +5595,7 @@ for (gees, gges, elty, relty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end A, vs, w @@ -5628,7 +5628,7 @@ for (gees, gges, elty, relty) in lwork = BlasInt(-1) rwork = Vector{$relty}(8n) info = Ref{BlasInt}() - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($gges), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{UInt8}, Ptr{Void}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, @@ -5645,7 +5645,7 @@ for (gees, gges, elty, relty) in chklapackerror(info[]) if i == 1 lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end A, B, alpha, beta, vsl[1:(jobvsl == 'V' ? n : 0),:], vsr[1:(jobvsr == 'V' ? n : 0),:] @@ -5733,7 +5733,7 @@ for (trexc, trsen, tgsen, elty) in liwork = BlasInt(-1) info = Ref{BlasInt}() select = convert(Array{BlasInt}, select) - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] and liwork as iwork[1] ccall((@blasfunc($trsen), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, @@ -5748,9 +5748,9 @@ for (trexc, trsen, tgsen, elty) in chklapackerror(info[]) if i == 1 # only estimated optimal lwork, liwork lwork = BlasInt(real(work[1])) + resize!(work, lwork) liwork = BlasInt(real(iwork[1])) - work = Vector{$elty}(lwork) - iwork = Vector{BlasInt}(liwork) + resize!(iwork, liwork) end end T, Q, iszero(wi) ? wr : complex.(wr, wi) @@ -5798,7 +5798,7 @@ for (trexc, trsen, tgsen, elty) in iwork = Vector{BlasInt}(1) info = Ref{BlasInt}() select = convert(Array{BlasInt}, select) - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] and liwork as iwork[1] ccall((@blasfunc($tgsen), liblapack), Void, (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, @@ -5817,9 +5817,9 @@ for (trexc, trsen, tgsen, elty) in chklapackerror(info[]) if i == 1 # only estimated optimal lwork, liwork lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) liwork = BlasInt(real(iwork[1])) - iwork = Vector{BlasInt}(liwork) + resize!(iwork, liwork) end end S, T, complex.(alphar, alphai), beta, Q, Z @@ -5878,7 +5878,7 @@ for (trexc, trsen, tgsen, elty) in lwork = BlasInt(-1) info = Ref{BlasInt}() select = convert(Array{BlasInt}, select) - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] ccall((@blasfunc($trsen), liblapack), Void, (Ptr{UInt8}, Ptr{UInt8}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, @@ -5893,7 +5893,7 @@ for (trexc, trsen, tgsen, elty) in chklapackerror(info[]) if i == 1 # only estimated optimal lwork, liwork lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) end end T, Q, w @@ -5940,7 +5940,7 @@ for (trexc, trsen, tgsen, elty) in iwork = Vector{BlasInt}(1) info = Ref{BlasInt}() select = convert(Array{BlasInt}, select) - for i = 1:2 + for i = 1:2 # first call returns lwork as work[1] and liwork as iwork[1] ccall((@blasfunc($tgsen), liblapack), Void, (Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{BlasInt}, Ptr{$elty}, Ptr{BlasInt}, Ptr{$elty}, @@ -5959,9 +5959,9 @@ for (trexc, trsen, tgsen, elty) in chklapackerror(info[]) if i == 1 # only estimated optimal lwork, liwork lwork = BlasInt(real(work[1])) - work = Vector{$elty}(lwork) + resize!(work, lwork) liwork = BlasInt(real(iwork[1])) - iwork = Vector{BlasInt}(liwork) + resize!(iwork, liwork) end end S, T, alpha, beta, Q, Z From 8758659d2be65edc8c1c45aa21963e94c532e1d6 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Thu, 1 Jun 2017 15:38:51 -0500 Subject: [PATCH 0975/1534] Fix calculation of displayed time, show UTC offset (#22136) * Fix calculation of displayed time, show UTC offset Fixes #22103. * add space to argument --- base/libgit2/signature.jl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/base/libgit2/signature.jl b/base/libgit2/signature.jl index 2e6395c3758d5..fb099efb07d38 100644 --- a/base/libgit2/signature.jl +++ b/base/libgit2/signature.jl @@ -35,7 +35,12 @@ function Base.convert(::Type{GitSignature}, sig::Signature) return GitSignature(sig_ptr_ptr[]) end -Base.show(io::IO, sig::Signature) = print(io, "Name: $(sig.name), Email: $(sig.email), Time: $(Dates.unix2datetime(sig.time + sig.time_offset))") +function Base.show(io::IO, sig::Signature) + print(io, "Name: ", sig.name, ", ") + print(io, "Email: ", sig.email, ", ") + print(io, "Time: ", Dates.unix2datetime(sig.time + 60*sig.time_offset)) + @printf(io, "%+03i:%02i", divrem(sig.time_offset, 60)...) +end """Return signature object. Free it after use.""" function default_signature(repo::GitRepo) From fb81c34af8cda41c1f4294182ce817135e064b33 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Thu, 1 Jun 2017 22:54:26 +0200 Subject: [PATCH 0976/1534] Fix broadcast_indices (#22130) This fixes a regression introduced in 4f1b479d. broadcast_indices() needs to be overloaded by packages for custom types, so it cannot be hidden under _broadcast_indices(). Also, ::Type is incorrect since the method only applies to scalars. Make the tests more complex to be closer to actual implementations in packages so that regressions like this will be noticed in the future. --- base/broadcast.jl | 10 +++++----- base/sparse/higherorderfns.jl | 7 +++---- test/broadcast.jl | 9 +++++++-- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/base/broadcast.jl b/base/broadcast.jl index 44acd0569de02..b4fd9126727c4 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -45,12 +45,12 @@ promote_containertype(::Type{T}, ::Type{T}) where {T} = T ## Calculate the broadcast indices of the arguments, or error if incompatible # array inputs broadcast_indices() = () -broadcast_indices(A) = _broadcast_indices(containertype(A), A) +broadcast_indices(A) = broadcast_indices(containertype(A), A) @inline broadcast_indices(A, B...) = broadcast_shape(broadcast_indices(A), broadcast_indices(B...)) -_broadcast_indices(::Type, A) = () -_broadcast_indices(::Type{Tuple}, A) = (OneTo(length(A)),) -_broadcast_indices(::Type{Array}, A::Ref) = () -_broadcast_indices(::Type{Array}, A) = indices(A) +broadcast_indices(::ScalarType, A) = () +broadcast_indices(::Type{Tuple}, A) = (OneTo(length(A)),) +broadcast_indices(::Type{Array}, A::Ref) = () +broadcast_indices(::Type{Array}, A) = indices(A) # shape (i.e., tuple-of-indices) inputs broadcast_shape(shape::Tuple) = shape diff --git a/base/sparse/higherorderfns.jl b/base/sparse/higherorderfns.jl index 87c83069e3299..a51a606b2f13e 100644 --- a/base/sparse/higherorderfns.jl +++ b/base/sparse/higherorderfns.jl @@ -6,8 +6,7 @@ module HigherOrderFns # particularly map[!]/broadcast[!] for SparseVectors and SparseMatrixCSCs at present. import Base: map, map!, broadcast, broadcast! import Base.Broadcast: _containertype, promote_containertype, - broadcast_indices, _broadcast_indices, - broadcast_c, broadcast_c! + broadcast_indices, broadcast_c, broadcast_c! using Base: front, tail, to_shape using ..SparseArrays: SparseVector, SparseMatrixCSC, AbstractSparseVector, @@ -901,7 +900,7 @@ end # (10) broadcast[!] over combinations of broadcast scalars and sparse vectors/matrices # broadcast shape promotion for combinations of sparse arrays and other types -_broadcast_indices(::Type{AbstractSparseArray}, A) = indices(A) +broadcast_indices(::Type{AbstractSparseArray}, A) = indices(A) # broadcast container type promotion for combinations of sparse arrays and other types _containertype(::Type{<:SparseVecOrMat}) = AbstractSparseArray # combinations of sparse arrays with broadcast scalars should yield sparse arrays @@ -985,7 +984,7 @@ struct PromoteToSparse end # broadcast containertype definitions for structured matrices StructuredMatrix = Union{Diagonal,Bidiagonal,Tridiagonal,SymTridiagonal} _containertype(::Type{<:StructuredMatrix}) = PromoteToSparse -_broadcast_indices(::Type{PromoteToSparse}, A) = indices(A) +broadcast_indices(::Type{PromoteToSparse}, A) = indices(A) # combinations explicitly involving Tuples and PromoteToSparse collections # divert to the generic AbstractArray broadcast code diff --git a/test/broadcast.jl b/test/broadcast.jl index bb7fdeaf3db1c..4368462f4e7b5 100644 --- a/test/broadcast.jl +++ b/test/broadcast.jl @@ -419,6 +419,7 @@ struct Array19745{T,N} <: AbstractArray{T,N} data::Array{T,N} end Base.getindex(A::Array19745, i::Integer...) = A.data[i...] +Base.setindex!(A::Array19745, v::Any, i::Integer...) = setindex!(A.data, v, i...) Base.size(A::Array19745) = size(A.data) Base.Broadcast._containertype{T<:Array19745}(::Type{T}) = Array19745 @@ -435,8 +436,12 @@ Base.Broadcast.broadcast_indices(::Type{Array19745}, A::Ref) = () getfield19745(x::Array19745) = x.data getfield19745(x) = x -Base.Broadcast.broadcast_c(f, ::Type{Array19745}, A, Bs...) = - Array19745(Base.Broadcast.broadcast_c(f, Array, getfield19745(A), map(getfield19745, Bs)...)) +function Base.Broadcast.broadcast_c(f, ::Type{Array19745}, A, Bs...) + T = Base.Broadcast._broadcast_eltype(f, A, Bs...) + shape = Base.Broadcast.broadcast_indices(A, Bs...) + dest = Array19745(Array{T}(Base.index_lengths(shape...))) + return broadcast!(f, dest, A, Bs...) +end @testset "broadcasting for custom AbstractArray" begin a = randn(10) From f7a23d9c63dafc873a4ad0a77b0464a771b2fd0b Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Thu, 1 Jun 2017 15:55:29 -0500 Subject: [PATCH 0977/1534] Add note on lightweight tags. (#22117) * Add note on lightweight tags. Address #22102. * make note --- base/libgit2/reference.jl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/base/libgit2/reference.jl b/base/libgit2/reference.jl index bb193345fc246..da6f26baf132d 100644 --- a/base/libgit2/reference.jl +++ b/base/libgit2/reference.jl @@ -162,10 +162,14 @@ end peel([T,] ref::GitReference) Recursively peel `ref` until an object of type `T` is obtained. If no `T` is provided, -then `ref` will be peeled until an object other than a `GitTag` is obtained. +then `ref` will be peeled until an object other than a [`GitTag`](@ref) is obtained. - A `GitTag` will be peeled to the object it references. -- A `GitCommit` will be peeled to a `GitTree`. +- A [`GitCommit`](@ref) will be peeled to a [`GitTree`](@ref). + +!!! note + Only annotated tags can be peeled to `GitTag` objects. Lightweight tags (the default) + are references under `refs/tags/` which point directly to `GitCommit` objects. """ function peel{T<:GitObject}(::Type{T}, ref::GitReference) obj_ptr_ptr = Ref{Ptr{Void}}(C_NULL) From cf5c063a233b3f0160c07e450bad64503a249601 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Thu, 1 Jun 2017 14:00:43 -0700 Subject: [PATCH 0978/1534] Add replacement suggestion to frexp(::Array{<:AbstractFloat}) deprecation. (#21991) --- base/deprecated.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index 5c844f33d238e..66d4af48e4cf8 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -847,7 +847,9 @@ end @deprecate ~(B::BitArray) .~B function frexp(A::Array{<:AbstractFloat}) - depwarn("`frexp(x::Array)` is discontinued.", :frexp) + depwarn(string("`frexp(x::Array)` is discontinued. Though not a direct replacement, ", + "consider using dot-syntax to `broadcast` scalar `frexp` over `Array`s ", + "instead, for example `frexp.(rand(4))`."), :frexp) F = similar(A) E = Array{Int}(size(A)) for (iF, iE, iA) in zip(eachindex(F), eachindex(E), eachindex(A)) From 2c73e9c3edb4fc0e6ae91031d3842cb1d7d88c35 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Thu, 1 Jun 2017 23:03:30 +0200 Subject: [PATCH 0979/1534] inline shift operators (#22083) inline some shift operators --- base/operators.jl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/base/operators.jl b/base/operators.jl index 47ac4b25de3ea..c38c2106278b0 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -480,6 +480,7 @@ julia> bits(Int8(12)) See also [`>>`](@ref), [`>>>`](@ref). """ function <<(x::Integer, c::Integer) + @_inline_meta typemin(Int) <= c <= typemax(Int) && return x << (c % Int) (x >= 0 || c >= 0) && return zero(x) oftype(x, -1) @@ -518,6 +519,7 @@ julia> bits(Int8(-4)) See also [`>>>`](@ref), [`<<`](@ref). """ function >>(x::Integer, c::Integer) + @_inline_meta typemin(Int) <= c <= typemax(Int) && return x >> (c % Int) (x >= 0 || c < 0) && return zero(x) oftype(x, -1) @@ -551,8 +553,10 @@ is equivalent to [`>>`](@ref). See also [`>>`](@ref), [`<<`](@ref). """ ->>>(x::Integer, c::Integer) = +function >>>(x::Integer, c::Integer) + @_inline_meta typemin(Int) <= c <= typemax(Int) ? x >>> (c % Int) : zero(x) +end >>>(x::Integer, c::Unsigned) = c <= typemax(UInt) ? x >>> (c % UInt) : zero(x) >>>(x::Integer, c::Int) = c >= 0 ? x >>> unsigned(c) : x << unsigned(-c) From 5c90d2e637c8b69d78b9ec0ca03a3b4897cdaa9c Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 1 Jun 2017 17:39:15 -0400 Subject: [PATCH 0980/1534] workspace command: fix for missing incremental support (#21714) * workspace command: fix for missing incremental support * Add a test for #22101 --- src/toplevel.c | 4 +++- test/workspace.jl | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/toplevel.c b/src/toplevel.c index 18ac6021b3ec2..50f3673d243be 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -54,8 +54,10 @@ JL_DLLEXPORT jl_module_t *jl_new_main_module(void) jl_main_module = jl_new_module(jl_symbol("Main")); jl_main_module->parent = jl_main_module; - if (old_main) // don't block continued loading of incremental caches + if (old_main) { // don't block continued loading of incremental caches + jl_main_module->primary_world = old_main->primary_world; jl_main_module->uuid = old_main->uuid; + } ptls->current_module = jl_main_module; jl_core_module->parent = jl_main_module; diff --git a/test/workspace.jl b/test/workspace.jl index bf6dd461b35fa..44a315c6fbf5d 100644 --- a/test/workspace.jl +++ b/test/workspace.jl @@ -1,5 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license +using Base.Test + script = """ # Issue #11948 f(x) = x+1 @@ -24,3 +26,35 @@ mutable struct Foo end @assert Tuple{Type{LastMain.Foo}} !== Tuple{Type{Main.Foo}} """ run(`$exename --startup-file=no -e $script2`) + +# Issue #22101 +mktempdir() do dir + withenv("JULIA_DEBUG_LOADING" => nothing) do + # We need to ensure that the module does a nontrivial amount of work during precompilation + write(joinpath(dir, "Test22101.jl"), """ + __precompile__() + module Test22101 + export f22101 + f22101() = collect(1:10) + f22101() + end + """) + write(joinpath(dir, "testdriver.jl"), """ + insert!(LOAD_PATH, 1, $(repr(dir))) + insert!(Base.LOAD_CACHE_PATH, 1, $(repr(dir))) + try + using Test22101 + f22101() + workspace() + using Test22101 + finally + splice!(LOAD_PATH, 1) + splice!(Base.LOAD_CACHE_PATH, 1) + end + exit(isdefined(Main, :f22101) ? 0 : 1) + """) + # Ensure that STDIO doesn't get swallowed (helps with debugging) + cmd = `$(Base.julia_cmd()) --startup-file=no --precompiled=yes --compilecache=yes $(joinpath(dir, "testdriver.jl"))` + @test success(pipeline(cmd, stdout=STDOUT, stderr=STDERR)) + end +end From ef9ab602b0307afb9fa21f2323e2abf4b244ad41 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Fri, 2 Jun 2017 00:14:11 +0200 Subject: [PATCH 0981/1534] fix at-[no]inline with short func. def with return type annotation (#22174) --- base/essentials.jl | 11 +---------- base/expr.jl | 2 +- test/inline.jl | 12 ++++++++++++ 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/base/essentials.jl b/base/essentials.jl index 200cd702c42d0..6e06e23302d1d 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -34,17 +34,8 @@ convert(::Type{Tuple{Vararg{T}}}, x::Tuple) where {T} = cnvt_all(T, x...) cnvt_all(T) = () cnvt_all(T, x, rest...) = tuple(convert(T,x), cnvt_all(T, rest...)...) -# test whether an assignment LHS is a function definition -function eventually_call(ex) - isa(ex, Expr) && (ex.head === :call || - ((ex.head === :where || ex.head === :(::)) && - eventually_call(ex.args[1]))) -end - macro generated(f) - isa(f, Expr) || error("invalid syntax; @generated must be used with a function definition") - if f.head === :function || (isdefined(:length) && f.head === :(=) && length(f.args) == 2 && - eventually_call(f.args[1])) + if isa(f, Expr) && (f.head === :function || is_short_function_def(f)) f.head = :stagedfunction return Expr(:escape, f) else diff --git a/base/expr.jl b/base/expr.jl index d23a1909701f6..5eb7fa814eaa7 100644 --- a/base/expr.jl +++ b/base/expr.jl @@ -240,7 +240,7 @@ function is_short_function_def(ex) ex.head == :(=) || return false while length(ex.args) >= 1 && isa(ex.args[1], Expr) (ex.args[1].head == :call) && return true - (ex.args[1].head == :where) || return false + (ex.args[1].head == :where || ex.args[1].head == :(::)) || return false ex = ex.args[1] end return false diff --git a/test/inline.jl b/test/inline.jl index 2defba2f3852f..3a7d7cc76ac8b 100644 --- a/test/inline.jl +++ b/test/inline.jl @@ -111,3 +111,15 @@ end let a = read21311() @test a[] == 1 end + +@testset "issue #19122: [no]inline of short func. def. with return type annotation" begin + exf19122 = macroexpand(:(@inline f19122()::Bool = true)) + exg19122 = macroexpand(:(@noinline g19122()::Bool = true)) + @test exf19122.args[2].args[1].args[1] == :inline + @test exg19122.args[2].args[1].args[1] == :noinline + + @inline f19122()::Bool = true + @noinline g19122()::Bool = true + @test f19122() + @test g19122() +end From a692b2a09a3f8740b080b658744b1d8c5d7fd214 Mon Sep 17 00:00:00 2001 From: arghhhh Date: Fri, 2 Jun 2017 09:35:02 -0400 Subject: [PATCH 0982/1534] Removing requirement for promotions from 0,1 in lufact (#22146) * Removing requirement for promotions from 0,1 * Using iszero() and added test * Tidy up spaces, tabs etc --- base/linalg/generic.jl | 4 ++-- base/linalg/lu.jl | 4 ++-- test/linalg/generic.jl | 30 ++++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/base/linalg/generic.jl b/base/linalg/generic.jl index b1da7e74b24e2..142164194439e 100644 --- a/base/linalg/generic.jl +++ b/base/linalg/generic.jl @@ -957,7 +957,7 @@ true function istriu(A::AbstractMatrix) m, n = size(A) for j = 1:min(n,m-1), i = j+1:m - if A[i,j] != 0 + if !iszero(A[i,j]) return false end end @@ -992,7 +992,7 @@ true function istril(A::AbstractMatrix) m, n = size(A) for j = 2:n, i = 1:min(j-1,m) - if A[i,j] != 0 + if !iszero(A[i,j]) return false end end diff --git a/base/linalg/lu.jl b/base/linalg/lu.jl index bb11de6f77fd4..8d2558b9cb9a2 100644 --- a/base/linalg/lu.jl +++ b/base/linalg/lu.jl @@ -39,7 +39,7 @@ function generic_lufact!(A::StridedMatrix{T}, ::Type{Val{Pivot}} = Val{true}) wh # find index max kp = k if Pivot - amax = real(zero(T)) + amax = abs(zero(T)) for i = k:m absi = abs(A[i,k]) if absi > amax @@ -49,7 +49,7 @@ function generic_lufact!(A::StridedMatrix{T}, ::Type{Val{Pivot}} = Val{true}) wh end end ipiv[k] = kp - if A[kp,k] != 0 + if !iszero(A[kp,k]) if k != kp # Interchange for i = 1:n diff --git a/test/linalg/generic.jl b/test/linalg/generic.jl index 89fa70944225b..8683aba20e98b 100644 --- a/test/linalg/generic.jl +++ b/test/linalg/generic.jl @@ -310,3 +310,33 @@ end @test [[1, 2], [3, 4]] ≈ [[1.0-eps(), 2.0+eps()], [3.0+2eps(), 4.0-1e8eps()]] @test [[1, 2], [3, 4]] ≉ [[1.0-eps(), 2.0+eps()], [3.0+2eps(), 4.0-1e9eps()]] @test [[1,2, [3,4]], 5.0, [6im, [7.0, 8.0]]] ≈ [[1,2, [3,4]], 5.0, [6im, [7.0, 8.0]]] + +# Issue 22042 +# Minimal modulo number type - but not subtyping Number +struct ModInt{n} + k + ModInt{n}(k) where {n} = new(mod(k,n)) +end + +Base.:+(a::ModInt{n}, b::ModInt{n}) where {n} = ModInt{n}(a.k + b.k) +Base.:-(a::ModInt{n}, b::ModInt{n}) where {n} = ModInt{n}(a.k - b.k) +Base.:*(a::ModInt{n}, b::ModInt{n}) where {n} = ModInt{n}(a.k * b.k) +Base.:-(a::ModInt{n}) where {n} = ModInt{n}(-a.k) +Base.inv(a::ModInt{n}) where {n} = ModInt{n}(invmod(a.k, n)) +Base.:/(a::ModInt{n}, b::ModInt{n}) where {n} = a*inv(b) + +Base.zero(::Type{ModInt{n}}) where {n} = ModInt{n}(0) +Base.zero(::ModInt{n}) where {n} = ModInt{n}(0) +Base.one(::Type{ModInt{n}}) where {n} = ModInt{n}(1) +Base.one(::ModInt{n}) where {n} = ModInt{n}(1) + +# Needed for pivoting: +Base.abs(a::ModInt{n}) where {n} = a +Base.:<(a::ModInt{n}, b::ModInt{n}) where {n} = a.k < b.k +Base.transpose(a::ModInt{n}) where {n} = a # see Issue 20978 + +A = [ ModInt{2}(1) ModInt{2}(0) ; ModInt{2}(1) ModInt{2}(1) ] +b = [ ModInt{2}(1), ModInt{2}(0) ] + +@test A*(A\b) == b +@test_nowarn lufact( A, Val{true} ) From 7ee1038b8e3c91a13a38041a0308f9e4c11b9841 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Fri, 2 Jun 2017 17:49:08 +0200 Subject: [PATCH 0983/1534] actually test solving ModInt example with lufact --- test/linalg/generic.jl | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/test/linalg/generic.jl b/test/linalg/generic.jl index 8683aba20e98b..b4a8017f9d945 100644 --- a/test/linalg/generic.jl +++ b/test/linalg/generic.jl @@ -316,6 +316,7 @@ end struct ModInt{n} k ModInt{n}(k) where {n} = new(mod(k,n)) + ModInt{n}(k::ModInt{n}) where {n} = k end Base.:+(a::ModInt{n}, b::ModInt{n}) where {n} = ModInt{n}(a.k + b.k) @@ -329,14 +330,15 @@ Base.zero(::Type{ModInt{n}}) where {n} = ModInt{n}(0) Base.zero(::ModInt{n}) where {n} = ModInt{n}(0) Base.one(::Type{ModInt{n}}) where {n} = ModInt{n}(1) Base.one(::ModInt{n}) where {n} = ModInt{n}(1) +Base.transpose(a::ModInt{n}) where {n} = a # see Issue 20978 + +A = [ModInt{2}(1) ModInt{2}(0); ModInt{2}(1) ModInt{2}(1)] +b = [ModInt{2}(1), ModInt{2}(0)] + +@test A*(lufact(A, Val{false})\b) == b # Needed for pivoting: Base.abs(a::ModInt{n}) where {n} = a Base.:<(a::ModInt{n}, b::ModInt{n}) where {n} = a.k < b.k -Base.transpose(a::ModInt{n}) where {n} = a # see Issue 20978 - -A = [ ModInt{2}(1) ModInt{2}(0) ; ModInt{2}(1) ModInt{2}(1) ] -b = [ ModInt{2}(1), ModInt{2}(0) ] -@test A*(A\b) == b -@test_nowarn lufact( A, Val{true} ) +@test A*(lufact(A, Val{true})\b) == b From f1c95ac98f980e76849883ac73d58354a8294739 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Fri, 2 Jun 2017 13:21:48 -0400 Subject: [PATCH 0984/1534] Add a test for #22021, jl_gc_realloc_string issue with join --- test/strings/io.jl | 74 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/test/strings/io.jl b/test/strings/io.jl index 1634e7f7cfa8a..061c744ae4192 100644 --- a/test/strings/io.jl +++ b/test/strings/io.jl @@ -200,3 +200,77 @@ s2 = """ """ @test s1 == s2 + +# issue #22021, string realloc bug with join +s22021 = String["\"\"\" + non_max_suppression(boxes, scores, max_output_size; iou_threshold=nothing) + +Greedily selects a subset of bounding boxes in descending order of score, + +pruning away boxes that have high intersection-over-union (IOU) overlap +with previously selected boxes. Bounding boxes are supplied as +[y1, x1, y2, x2], where (y1, x1) and (y2, x2) are the coordinates of any +diagonal pair of box corners and the coordinates can be provided as normalized +(i.e., lying in the interval [0, 1]) or absolute. Note that this algorithm +is agnostic to where the origin is in the coordinate system. Note that this +algorithm is invariant to orthogonal transformations and translations +of the coordinate system; thus translating or reflections of the coordinate +system result in the same boxes being selected by the algorithm. + +The output of this operation is a set of integers indexing into the input +collection of bounding boxes representing the selected boxes. The bounding +box coordinates corresponding to the selected indices can then be obtained +using the `tf.gather operation`. For example: + + selected_indices = tf.image.non_max_suppression( + boxes, scores, max_output_size, iou_threshold) + selected_boxes = tf.gather(boxes, selected_indices) +\"\"\"", + " tf.@op function non_max_suppression(v13566, v13567, v13568; name=nothing, iou_threshold=nothing) ", + " local desc ", + " tf.with_op_name((()->begin ", + " desc = tf.NodeDescription(\"NonMaxSuppression\") ", + " begin ", + " begin ", + " v13566 = convert(TensorFlow.Tensor{Float32}, v13566) ", + " begin ", + " end", + " end", + " begin ", + " v13567 = convert(TensorFlow.Tensor{Float32}, v13567) ", + " begin ", + " end", + " end", + " begin ", + " v13568 = convert(TensorFlow.Tensor{Int32}, v13568) ", + " begin ", + " end", + " end", + " end ", + " begin ", + " begin ", + " tf.add_input(desc, v13566)", + " end", + " begin ", + " tf.add_input(desc, v13567)", + " end", + " begin ", + " tf.add_input(desc, v13568)", + " end", + " end ", + " begin ", + " begin ", + " if iou_threshold !== nothing ", + " desc[\"iou_threshold\"] = Base.identity(iou_threshold)", + " end", + " end", + " end", + " end), name, \"NonMaxSuppression\") ", + " tf.Tensor(tf.Operation(desc))", + " end"] + +for i = 1:10 + buf = IOBuffer() + print(buf, join(s22021, "\n")) + @test isvalid(String, take!(buf)) +end From 9a22471b8019693cedd0502fd3e4ae2b4c7e4bc9 Mon Sep 17 00:00:00 2001 From: Morten Piibeleht Date: Sat, 3 Jun 2017 14:13:37 +1200 Subject: [PATCH 0985/1534] Deploy docs with clean URLs (#22048) * Move deps .PHONY together with others * Remove duplicate page from manual The "Interacting with Julia" page was listed twice in the sidebar. * Build docs with clean URLs Documenter has to be bumped to v0.11.1 for this. Also change two absolute URLs that will become outdated with this change to the more appropriate relative URLs. Also bump Compat to get rid of deprecation warnings. * Remove duplicate symm docstring reference There is only one 5-argument docstring: symm(side, ul, alpha, A, B) --- .travis.yml | 2 ++ doc/Makefile | 12 ++++++++---- doc/REQUIRE | 4 ++-- doc/make.jl | 2 +- doc/src/manual/dates.md | 4 ++-- doc/src/stdlib/linalg.md | 1 - 6 files changed, 15 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index c6cc7166c9918..66afbebdd48c8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -147,3 +147,5 @@ script: rm -f julia/deps/scratch/libgit2-*/CMakeFiles/CMakeOutput.log # uncomment the following if failures are suspected to be due to the out-of-memory killer # - dmesg +after_success: + - cd julia && make -C doc deploy diff --git a/doc/Makefile b/doc/Makefile index 791f095b6162c..743804d8b6968 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -8,7 +8,7 @@ JULIAHOME := $(abspath $(SRCDIR)/..) include $(JULIAHOME)/Make.inc JULIA_EXECUTABLE := $(call spawn,$(build_bindir)/julia) -.PHONY: help clean cleanall html pdf linkcheck doctest check +.PHONY: help clean cleanall html pdf linkcheck doctest check deps deploy help: @echo "Please use 'make ' where is one of" @@ -32,10 +32,10 @@ cleanall: clean html: deps @echo "Building HTML documentation." ifneq ($(OS),WINNT) - $(JULIA_EXECUTABLE) $(call cygpath_w,$(SRCDIR)/make.jl) -- deploy + $(JULIA_EXECUTABLE) $(call cygpath_w,$(SRCDIR)/make.jl) else # work around issue #11727, windows output redirection breaking on buildbot - $(JULIA_EXECUTABLE) $(call cygpath_w,$(SRCDIR)/make.jl) -- deploy > docbuild.log 2>&1 + $(JULIA_EXECUTABLE) $(call cygpath_w,$(SRCDIR)/make.jl) > docbuild.log 2>&1 @cat docbuild.log endif @echo "Build finished. The HTML pages are in _build/html." @@ -60,4 +60,8 @@ check: deps $(JULIA_EXECUTABLE) --color=yes $(call cygpath_w,$(SRCDIR)/make.jl) -- doctest linkcheck @echo "Checks finished." -.PHONY: deps +# The deploy target should only be called in Travis builds +deploy: deps + @echo "Deploying HTML documentation." + $(JULIA_EXECUTABLE) $(call cygpath_w,$(SRCDIR)/make.jl) -- deploy + @echo "Build & deploy of docs finished." diff --git a/doc/REQUIRE b/doc/REQUIRE index aed1a491d5225..bf1f123f9e2da 100644 --- a/doc/REQUIRE +++ b/doc/REQUIRE @@ -1,3 +1,3 @@ -Compat 0.25.0 0.25.0+ +Compat 0.25.2 0.25.2+ DocStringExtensions 0.3.3 0.3.3+ -Documenter 0.10.3 0.10.3+ +Documenter 0.11.1 0.11.1+ diff --git a/doc/make.jl b/doc/make.jl index dc931c98ca9bb..faf093091bedc 100644 --- a/doc/make.jl +++ b/doc/make.jl @@ -47,7 +47,6 @@ const PAGES = [ "manual/calling-c-and-fortran-code.md", "manual/handling-operating-system-variation.md", "manual/environment-variables.md", - "manual/interacting-with-julia.md", "manual/embedding.md", "manual/packages.md", "manual/profile.md", @@ -130,6 +129,7 @@ makedocs( authors = "The Julia Project", analytics = "UA-28835595-6", pages = PAGES, + html_prettyurls = ("deploy" in ARGS), ) if "deploy" in ARGS diff --git a/doc/src/manual/dates.md b/doc/src/manual/dates.md index 476314407e6ab..448b3abc6653f 100644 --- a/doc/src/manual/dates.md +++ b/doc/src/manual/dates.md @@ -561,7 +561,7 @@ julia> round(DateTime(2016, 8, 6, 20, 15), Dates.Day) Unlike the numeric [`round()`](@ref) method, which breaks ties toward the even number by default, the [`TimeType`](@ref)[`round()`](@ref) method uses the `RoundNearestTiesUp` rounding mode. (It's difficult to guess what breaking ties to nearest "even" [`TimeType`](@ref) would entail.) Further -details on the available `RoundingMode` s can be found in the [API reference](https://docs.julialang.org/en/latest/stdlib/dates.html). +details on the available `RoundingMode` s can be found in the [API reference](../stdlib/dates.md). Rounding should generally behave as expected, but there are a few cases in which the expected behaviour is not obvious. @@ -626,5 +626,5 @@ will result in the months field having an odd value. Because both months and yea an irregular number of days, whether rounding to an even number of days will result in an even value in the days field is uncertain. -See the [API reference](https://docs.julialang.org/en/latest/stdlib/dates.html) for additional information +See the [API reference](../stdlib/dates.md) for additional information on methods exported from the `Dates` module. diff --git a/doc/src/stdlib/linalg.md b/doc/src/stdlib/linalg.md index 0f415013c51dc..66dde6330d3e8 100644 --- a/doc/src/stdlib/linalg.md +++ b/doc/src/stdlib/linalg.md @@ -224,7 +224,6 @@ Base.LinAlg.BLAS.gemv(::Any, ::Any, ::Any) Base.LinAlg.BLAS.symm! Base.LinAlg.BLAS.symm(::Any, ::Any, ::Any, ::Any, ::Any) Base.LinAlg.BLAS.symm(::Any, ::Any, ::Any, ::Any) -Base.LinAlg.BLAS.symm(::Char, ::Char, ::Any, ::Any, ::Any) Base.LinAlg.BLAS.symv! Base.LinAlg.BLAS.symv(::Any, ::Any, ::Any, ::Any) Base.LinAlg.BLAS.symv(::Any, ::Any, ::Any) From 2728a50bc3269503fe39401c844679988a3598df Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Mon, 1 Dec 2014 20:49:29 +0530 Subject: [PATCH 0986/1534] merge 2 versions (for GMP 5 & 6) of rand(::UnitRange{BigInt}) As a consequence, using dynamically a version of GMP which does not match the compile time version is no longer an error (this patch makes this a warming). The code is shorter, but we break the MPZ API boundary; this also allows to put allocating pointer_to_array out of the loop, and get slightly better performances. --- base/gmp.jl | 14 +++++++++--- base/random.jl | 59 ++++++++++++++++---------------------------------- 2 files changed, 30 insertions(+), 43 deletions(-) diff --git a/base/gmp.jl b/base/gmp.jl index 07926f9865042..f44be43fd568e 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -46,6 +46,7 @@ mutable struct BigInt <: Integer alloc::Cint size::Cint d::Ptr{Limb} + function BigInt() b = new(zero(Cint), zero(Cint), C_NULL) MPZ.init!(b) @@ -77,9 +78,10 @@ BigInt(x) function __init__() try if gmp_version().major != GMP_VERSION.major || gmp_bits_per_limb() != GMP_BITS_PER_LIMB - error(string("The dynamically loaded GMP library (version $(gmp_version()) with __gmp_bits_per_limb == $(gmp_bits_per_limb()))\n", - "does not correspond to the compile time version (version $GMP_VERSION with __gmp_bits_per_limb == $GMP_BITS_PER_LIMB).\n", - "Please rebuild Julia.")) + msg = gmp_bits_per_limb() != GMP_BITS_PER_LIMB ? error : warn + msg(string("The dynamically loaded GMP library (version $(gmp_version()) with __gmp_bits_per_limb == $(gmp_bits_per_limb()))\n", + "does not correspond to the compile time version (version $GMP_VERSION with __gmp_bits_per_limb == $GMP_BITS_PER_LIMB).\n", + "Please rebuild Julia.")) end ccall((:__gmp_set_memory_functions, :libgmp), Void, @@ -114,6 +116,9 @@ gmpz(op::Symbol) = (Symbol(:__gmpz_, op), :libgmp) init!(x::BigInt) = (ccall((:__gmpz_init, :libgmp), Void, (mpz_t,), &x); x) init2!(x::BigInt, a) = (ccall((:__gmpz_init2, :libgmp), Void, (mpz_t, bitcnt_t), &x, a); x) +realloc2!(x, a) = (ccall((:__gmpz_realloc2, :libgmp), Void, (mpz_t, bitcnt_t), &x, a); x) +realloc2(a) = realloc2!(BigInt(), a) + sizeinbase(a::BigInt, b) = Int(ccall((:__gmpz_sizeinbase, :libgmp), Csize_t, (mpz_t, Cint), &a, b)) for op in (:add, :sub, :mul, :fdiv_q, :tdiv_q, :fdiv_r, :tdiv_r, :gcd, :lcm, :and, :ior, :xor) @@ -196,6 +201,9 @@ cmp_si(a::BigInt, b) = ccall((:__gmpz_cmp_si, :libgmp), Cint, (mpz_t, Clong), &a cmp_ui(a::BigInt, b) = ccall((:__gmpz_cmp_ui, :libgmp), Cint, (mpz_t, Culong), &a, b) % Int cmp_d(a::BigInt, b) = ccall((:__gmpz_cmp_d, :libgmp), Cint, (mpz_t, Cdouble), &a, b) % Int +mpn_cmp(a::Ptr{Limb}, b::Ptr{Limb}, c) = ccall((:__gmpn_cmp, :libgmp), Cint, (Ptr{Limb}, Ptr{Limb}, Clong), a, b, c) +mpn_cmp(a::BigInt, b::BigInt, c) = mpn_cmp(a.d, b.d, c) + get_str!(x, a, b::BigInt) = (ccall((:__gmpz_get_str,:libgmp), Ptr{Cchar}, (Ptr{Cchar}, Cint, mpz_t), x, a, &b); x) set_str!(x::BigInt, a, b) = ccall((:__gmpz_set_str, :libgmp), Cint, (mpz_t, Ptr{UInt8}, Cint), &x, a, b) % Int get_d(a::BigInt) = ccall((:__gmpz_get_d, :libgmp), Cdouble, (mpz_t,), &a) diff --git a/base/random.jl b/base/random.jl index 7d15e802b678a..6f21c9b283050 100644 --- a/base/random.jl +++ b/base/random.jl @@ -3,7 +3,7 @@ module Random using Base.dSFMT -using Base.GMP: GMP_VERSION, Limb, MPZ +using Base.GMP: Limb, MPZ import Base: copymutable, copy, copy!, == export srand, @@ -592,23 +592,11 @@ for (T, U) in [(UInt8, UInt32), (UInt16, UInt32), end end -if GMP_VERSION.major >= 6 - struct RangeGeneratorBigInt <: RangeGenerator - a::BigInt # first - m::BigInt # range length - 1 - nlimbs::Int # number of limbs in generated BigInt's - mask::Limb # applied to the highest limb - end - -else - struct RangeGeneratorBigInt <: RangeGenerator - a::BigInt # first - m::BigInt # range length - 1 - limbs::Vector{Limb} # buffer to be copied into generated BigInt's - mask::Limb # applied to the highest limb - - RangeGeneratorBigInt(a, m, nlimbs, mask) = new(a, m, Vector{Limb}(nlimbs), mask) - end +struct RangeGeneratorBigInt <: RangeGenerator + a::BigInt # first + m::BigInt # range length - 1 + nlimbs::Int # number of limbs in generated BigInt's + mask::Limb # applied to the highest limb end @@ -649,30 +637,21 @@ function rand{T<:Integer, U<:Unsigned}(rng::AbstractRNG, g::RangeGeneratorInt{T, (unsigned(g.a) + rem_knuth(x, g.k)) % T end -if GMP_VERSION.major >= 6 - # mpz_limbs_write and mpz_limbs_finish are available only in GMP version 6 - function rand(rng::AbstractRNG, g::RangeGeneratorBigInt) - x = BigInt() - while true - # note: on CRAY computers, the second argument may be of type Cint (48 bits) and not Clong - xd = MPZ.limbs_write!(x, g.nlimbs) - limbs = unsafe_wrap(Array, xd, g.nlimbs) - rand!(rng, limbs) - limbs[end] &= g.mask - MPZ.limbs_finish!(x, g.nlimbs) - x <= g.m && return MPZ.add!(x, g.a) - end +function rand(rng::AbstractRNG, g::RangeGeneratorBigInt) + x = MPZ.realloc2(g.nlimbs*8*sizeof(Limb)) + limbs = unsafe_wrap(Array, x.d, g.nlimbs) + while true + rand!(rng, limbs) + @inbounds limbs[end] &= g.mask + MPZ.mpn_cmp(x, g.m, g.nlimbs) <= 0 && break end -else - function rand(rng::AbstractRNG, g::RangeGeneratorBigInt) - x = BigInt() - while true - rand!(rng, g.limbs) - g.limbs[end] &= g.mask - MPZ.import!(x, length(g.limbs), -1, sizeof(Limb), 0, 0, g.limbs) - x <= g.m && return MPZ.add!(x, g.a) - end + # adjust x.size (normally done by mpz_limbs_finish, in GMP version >= 6) + x.size = g.nlimbs + while x.size > 0 + @inbounds limbs[x.size] != 0 && break + x.size -= 1 end + MPZ.add!(x, g.a) end rand(rng::AbstractRNG, r::UnitRange{<:Union{Signed,Unsigned,BigInt,Bool}}) = rand(rng, RangeGenerator(r)) From 141a8f4a15ea6f05eeb28a086dd344fba8156ded Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Thu, 29 Oct 2015 11:05:04 +0530 Subject: [PATCH 0987/1534] avoid re-allocations in rand(UnitRange(::BigInt)) for some cases --- base/random.jl | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/base/random.jl b/base/random.jl index 6f21c9b283050..29d2d842cc43d 100644 --- a/base/random.jl +++ b/base/random.jl @@ -593,10 +593,11 @@ for (T, U) in [(UInt8, UInt32), (UInt16, UInt32), end struct RangeGeneratorBigInt <: RangeGenerator - a::BigInt # first - m::BigInt # range length - 1 - nlimbs::Int # number of limbs in generated BigInt's - mask::Limb # applied to the highest limb + a::BigInt # first + m::BigInt # range length - 1 + nlimbs::Int # number of limbs in generated BigInt's (z ∈ [0, m]) + nlimbsmax::Int # max number of limbs for z+a + mask::Limb # applied to the highest limb end @@ -607,7 +608,8 @@ function RangeGenerator(r::UnitRange{BigInt}) nlimbs, highbits = divrem(nd, 8*sizeof(Limb)) highbits > 0 && (nlimbs += 1) mask = highbits == 0 ? ~zero(Limb) : one(Limb)< Date: Sat, 3 Jun 2017 13:42:07 -0400 Subject: [PATCH 0988/1534] Backport LLVM patches to fix AVX on i686 This fixes a bug in the patch that fixes #19976 causing encoding error on 32bit x86 and segfault when AVX/AVX2 is enabled. Ref LLVM bug report https://bugs.llvm.org//show_bug.cgi?id=29010 LLVM commit https://github.com/llvm-mirror/llvm/commit/83260f239481dfb40d325cf35005c20eeb767b6c Also ref where I saw this issue in https://github.com/JuliaLang/julia/pull/21849#issuecomment-305950641 --- deps/llvm.mk | 1 + deps/patches/llvm-PR29010-i386-xmm.patch | 80 ++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 deps/patches/llvm-PR29010-i386-xmm.patch diff --git a/deps/llvm.mk b/deps/llvm.mk index 5e530f4e2cd7e..e8ea59fcd72f4 100644 --- a/deps/llvm.mk +++ b/deps/llvm.mk @@ -499,6 +499,7 @@ $(eval $(call LLVM_PATCH,llvm-D28786-callclearance)) $(eval $(call LLVM_PATCH,llvm-rL293230-icc17-cmake)) # Remove for 4.0 $(eval $(call LLVM_PATCH,llvm-D32593)) $(eval $(call LLVM_PATCH,llvm-D33179)) +$(eval $(call LLVM_PATCH,llvm-PR29010-i386-xmm)) # Remove for 4.0 endif # LLVM_VER ifeq ($(LLVM_VER),3.7.1) diff --git a/deps/patches/llvm-PR29010-i386-xmm.patch b/deps/patches/llvm-PR29010-i386-xmm.patch new file mode 100644 index 0000000000000..b31f70d365cf0 --- /dev/null +++ b/deps/patches/llvm-PR29010-i386-xmm.patch @@ -0,0 +1,80 @@ +From 83260f239481dfb40d325cf35005c20eeb767b6c Mon Sep 17 00:00:00 2001 +From: Marina Yatsina +Date: Wed, 17 Aug 2016 19:07:40 +0000 +Subject: [PATCH] Fix for PR29010 + +This is a fix for https://llvm.org/bugs/show_bug.cgi?id=29010 +Root cause of the bug is that the register class of the machine instruction operand does not fully reflect if this registers that can be allocated. +Both for i386 and x86_64 the operand's register class is VR128RegClass and thus contains xmm0-xmm15, though in i386 we can only use xmm0-xmm8. +In order to get the actual allocable registers of the class we need to use RegisterClassInfo. + +Differential Revision: https://reviews.llvm.org/D23613 + + + +git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@278954 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + lib/CodeGen/ExecutionDepsFix.cpp | 6 +++++- + test/CodeGen/X86/pr29010.ll | 12 ++++++++++++ + 2 files changed, 17 insertions(+), 1 deletion(-) + create mode 100644 test/CodeGen/X86/pr29010.ll + +diff --git a/lib/CodeGen/ExecutionDepsFix.cpp b/lib/CodeGen/ExecutionDepsFix.cpp +index 213dd58a31d..2f173f84d73 100644 +--- a/lib/CodeGen/ExecutionDepsFix.cpp ++++ b/lib/CodeGen/ExecutionDepsFix.cpp +@@ -26,6 +26,7 @@ + #include "llvm/CodeGen/LivePhysRegs.h" + #include "llvm/CodeGen/MachineFunctionPass.h" + #include "llvm/CodeGen/MachineRegisterInfo.h" ++#include "llvm/CodeGen/RegisterClassInfo.h" + #include "llvm/Support/Allocator.h" + #include "llvm/Support/Debug.h" + #include "llvm/Support/raw_ostream.h" +@@ -137,6 +138,7 @@ class ExeDepsFix : public MachineFunctionPass { + MachineFunction *MF; + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; ++ RegisterClassInfo RegClassInfo; + std::vector> AliasMap; + const unsigned NumRegs; + LiveReg *LiveRegs; +@@ -509,7 +511,8 @@ void ExeDepsFix::pickBestRegisterForUndef(MachineInstr *MI, unsigned OpIdx, + // max clearance or clearance higher than Pref. + unsigned MaxClearance = 0; + unsigned MaxClearanceReg = OriginalReg; +- for (auto Reg : OpRC->getRegisters()) { ++ ArrayRef Order = RegClassInfo.getOrder(OpRC); ++ for (auto Reg : Order) { + assert(AliasMap[Reg].size() == 1 && + "Reg is expected to be mapped to a single index"); + int RCrx = *regIndices(Reg).begin(); +@@ -785,6 +788,7 @@ bool ExeDepsFix::runOnMachineFunction(MachineFunction &mf) { + MF = &mf; + TII = MF->getSubtarget().getInstrInfo(); + TRI = MF->getSubtarget().getRegisterInfo(); ++ RegClassInfo.runOnMachineFunction(mf); + LiveRegs = nullptr; + assert(NumRegs == RC->getNumRegs() && "Bad regclass"); + +diff --git a/test/CodeGen/X86/pr29010.ll b/test/CodeGen/X86/pr29010.ll +new file mode 100644 +index 00000000000..a2d5ff69a35 +--- /dev/null ++++ b/test/CodeGen/X86/pr29010.ll +@@ -0,0 +1,12 @@ ++; RUN: llc < %s -mtriple=i386-linux -mattr=+avx | FileCheck %s ++ ++; In i386 there are only 8 XMMs (xmm0-xmm7), make sure we we are not creating illegal XMM ++define float @only_xmm0_7(i32 %arg) { ++top: ++ tail call void asm sideeffect "", "~{xmm0},~{xmm1},~{xmm2},~{xmm3},~{dirflag},~{fpsr},~{flags}"() ++ tail call void asm sideeffect "", "~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{dirflag},~{fpsr},~{flags}"() ++ %tmp1 = sitofp i32 %arg to float ++ ret float %tmp1 ++;CHECK-LABEL:@only_xmm0_7 ++;CHECK: vcvtsi2ssl {{.*}}, {{%xmm[0-7]+}}, {{%xmm[0-7]+}} ++} +-- +2.13.0 + From 0cc329eb4b39a0f8aaab03ec59c3bf91e7240780 Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Sat, 3 Jun 2017 20:32:00 -0400 Subject: [PATCH 0989/1534] Implement svdx(Number, Number) (#22195) Make svd(x::Number) return numbers Implement hash, isequal, and == for Factorizations --- base/linalg/factorization.jl | 4 ++++ base/linalg/svd.jl | 9 ++++++++- test/linalg/svd.jl | 22 ++++++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/base/linalg/factorization.jl b/base/linalg/factorization.jl index 75e6c0a2db5f5..2a228d4948f0a 100644 --- a/base/linalg/factorization.jl +++ b/base/linalg/factorization.jl @@ -30,6 +30,10 @@ end convert(::Type{Factorization{T}}, F::Factorization{T}) where {T} = F inv(F::Factorization{T}) where {T} = A_ldiv_B!(F, eye(T, size(F,1))) +Base.hash(F::Factorization, h::UInt) = mapreduce(f -> hash(getfield(F, f)), hash, h, fieldnames(F)) +Base.:(==)( F::T, G::T) where {T<:Factorization} = all(f -> getfield(F, f) == getfield(G, f), fieldnames(F)) +Base.isequal(F::T, G::T) where {T<:Factorization} = all(f -> isequal(getfield(F, f), getfield(G, f)), fieldnames(F)) + # With a real lhs and complex rhs with the same precision, we can reinterpret # the complex rhs as a real rhs with twice the number of columns function (\){T<:BlasReal}(F::Factorization{T}, B::VecOrMat{Complex{T}}) diff --git a/base/linalg/svd.jl b/base/linalg/svd.jl index 639d528a1b812..a81105072d06c 100644 --- a/base/linalg/svd.jl +++ b/base/linalg/svd.jl @@ -102,10 +102,11 @@ julia> U*diagm(S)*V' 0.0 2.0 0.0 0.0 0.0 ``` """ -function svd(A::Union{Number, AbstractArray}; thin::Bool=true) +function svd(A::AbstractArray; thin::Bool=true) F = svdfact(A, thin=thin) F.U, F.S, F.Vt' end +svd(x::Number; thin::Bool=true) = first.(svd(fill(x, 1, 1))) function getindex(F::SVD, d::Symbol) if d == :U @@ -231,6 +232,10 @@ function svdfact(A::StridedMatrix{TA}, B::StridedMatrix{TB}) where {TA,TB} S = promote_type(Float32, typeof(one(TA)/norm(one(TA))),TB) return svdfact!(copy_oftype(A, S), copy_oftype(B, S)) end +# This method can be heavily optimized but it is probably not critical +# and might introduce bugs or inconsistencies relative to the 1x1 matrix +# version +svdfact(x::Number, y::Number) = svdfact(fill(x, 1, 1), fill(y, 1, 1)) """ svd(A, B) -> U, V, Q, D1, D2, R0 @@ -245,6 +250,7 @@ function svd(A::AbstractMatrix, B::AbstractMatrix) F = svdfact(A, B) F[:U], F[:V], F[:Q], F[:D1], F[:D2], F[:R0] end +svd(x::Number, y::Number) = first.(svd(fill(x, 1, 1), fill(y, 1, 1))) function getindex(obj::GeneralizedSVD{T}, d::Symbol) where T if d == :U @@ -305,6 +311,7 @@ function svdvals(A::StridedMatrix{TA}, B::StridedMatrix{TB}) where {TA,TB} S = promote_type(Float32, typeof(one(TA)/norm(one(TA))), TB) return svdvals!(copy_oftype(A, S), copy_oftype(B, S)) end +svdvals(x::Number, y::Number) = abs(x/y) # Conversion convert(::Type{AbstractMatrix}, F::SVD) = (F.U * Diagonal(F.S)) * F.Vt diff --git a/test/linalg/svd.jl b/test/linalg/svd.jl index f8d1611fc9a1a..ed9fb032beb66 100644 --- a/test/linalg/svd.jl +++ b/test/linalg/svd.jl @@ -79,3 +79,25 @@ a2img = randn(n,n)/2 end end end + +@testset "Number input" begin + x, y = randn(2) + @test svdfact(x) == svdfact( fill(x, 1, 1)) + @test svdvals(x) == first(svdvals(fill(x, 1, 1))) + @test svd(x) == first.(svd( fill(x, 1, 1))) + @test svdfact(x, y) == svdfact( fill(x, 1, 1), fill(y, 1, 1)) + @test svdvals(x, y) == first(svdvals(fill(x, 1, 1), fill(y, 1, 1))) + @test svd(x, y) == first.(svd( fill(x, 1, 1), fill(y, 1, 1))) +end + +@testset "isequal, ==, and hash" begin + x, y = rand(), NaN + Fx, Fy = svdfact(x), svdfact(y) + @test Fx == Fx + @test !(Fy == Fy) + @test isequal(Fy, Fy) + @test hash(Fx) == hash(Fx) + @test hash(Fx, UInt(1)) == hash(Fx, UInt(1)) + @test hash(Fy) == hash(Fy) + @test hash(Fy, UInt(1)) == hash(Fy, UInt(1)) +end From 39777e7fe1698f32ecd5b5ff4b6a3ee53808ccd8 Mon Sep 17 00:00:00 2001 From: Morten Piibeleht Date: Mon, 5 Jun 2017 06:15:48 +1200 Subject: [PATCH 0990/1534] Work around linkcheck errors in docs (#22201) --- doc/src/index.md | 2 +- doc/src/manual/dates.md | 4 ++-- doc/src/stdlib/dates.md | 2 +- doc/src/stdlib/index.md | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/src/index.md b/doc/src/index.md index 7434a4d78cfbc..567f3dd8964fd 100644 --- a/doc/src/index.md +++ b/doc/src/index.md @@ -57,7 +57,7 @@ * [Punctuation](@ref) * [Sorting and Related Functions](@ref) * [Package Manager Functions](@ref) - * [Dates and Time](@ref) + * [Dates and Time](@ref stdlib-dates) * [Iteration utilities](@ref) * [Unit Testing](@ref) * [C Interface](@ref) diff --git a/doc/src/manual/dates.md b/doc/src/manual/dates.md index 448b3abc6653f..ec2c5eb54ed1a 100644 --- a/doc/src/manual/dates.md +++ b/doc/src/manual/dates.md @@ -561,7 +561,7 @@ julia> round(DateTime(2016, 8, 6, 20, 15), Dates.Day) Unlike the numeric [`round()`](@ref) method, which breaks ties toward the even number by default, the [`TimeType`](@ref)[`round()`](@ref) method uses the `RoundNearestTiesUp` rounding mode. (It's difficult to guess what breaking ties to nearest "even" [`TimeType`](@ref) would entail.) Further -details on the available `RoundingMode` s can be found in the [API reference](../stdlib/dates.md). +details on the available `RoundingMode` s can be found in the [API reference](@ref stdlib-dates). Rounding should generally behave as expected, but there are a few cases in which the expected behaviour is not obvious. @@ -626,5 +626,5 @@ will result in the months field having an odd value. Because both months and yea an irregular number of days, whether rounding to an even number of days will result in an even value in the days field is uncertain. -See the [API reference](../stdlib/dates.md) for additional information +See the [API reference](@ref stdlib-dates) for additional information on methods exported from the `Dates` module. diff --git a/doc/src/stdlib/dates.md b/doc/src/stdlib/dates.md index 64b27a37c4b52..a7ebd9f3d64dd 100644 --- a/doc/src/stdlib/dates.md +++ b/doc/src/stdlib/dates.md @@ -1,4 +1,4 @@ -# Dates and Time +# [Dates and Time](@id stdlib-dates) ## Dates and Time Types diff --git a/doc/src/stdlib/index.md b/doc/src/stdlib/index.md index 0684e1964af16..c4b9d525c3b8e 100644 --- a/doc/src/stdlib/index.md +++ b/doc/src/stdlib/index.md @@ -14,7 +14,7 @@ * [Punctuation](@ref) * [Sorting and Related Functions](@ref) * [Package Manager Functions](@ref) - * [Dates and Time](@ref) + * [Dates and Time](@ref stdlib-dates) * [Iteration utilities](@ref) * [Unit Testing](@ref) * [C Interface](@ref) From 2c6273b161aef6b908bc69e854b6f25b447aaa5d Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Sun, 4 Jun 2017 20:50:29 +0200 Subject: [PATCH 0991/1534] special show for AbstractVector{Method} for ::MIMEtext/plain (#22068) which is currently done for text/html this enables the jump-to-method thingy from #22007 to be used with methodswith(Foo) also This also prevents large spacing in the printing, since the general vector output prints with equal spacing for all elements, and some methods have very long signatures --- base/methodshow.jl | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/base/methodshow.jl b/base/methodshow.jl index c6ef522b3261a..d6b223da5f1ab 100644 --- a/base/methodshow.jl +++ b/base/methodshow.jl @@ -289,7 +289,16 @@ end show(io::IO, mime::MIME"text/html", mt::MethodTable) = show(io, mime, MethodList(mt)) -# pretty-printing of Vector{Method} for output of methodswith: +# pretty-printing of AbstractVector{Method} for output of methodswith: +function show(io::IO, mime::MIME"text/plain", mt::AbstractVector{Method}) + resize!(LAST_SHOWN_LINE_INFOS, 0) + for (i, m) in enumerate(mt) + print(io, "[$(i)] ") + show(io, m) + println(io) + push!(LAST_SHOWN_LINE_INFOS, (string(m.file), m.line)) + end +end function show(io::IO, mime::MIME"text/html", mt::AbstractVector{Method}) print(io, summary(mt)) From a3c9bbdeb9a8d3721db3171c5df934db98b8140d Mon Sep 17 00:00:00 2001 From: Jim Garrison Date: Sun, 4 Jun 2017 22:17:15 -0400 Subject: [PATCH 0992/1534] Remove note for compatibility with Julia 0.3 (#22213) Julia 0.3 is no longer maintained, so I can't imagine this note is useful anymore. [av skip] --- base/loading.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/base/loading.jl b/base/loading.jl index 18c4765790531..b0a432d8e0df0 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -318,8 +318,7 @@ Specify whether the file calling this function is precompilable. If `isprecompil `true`, then `__precompile__` throws an exception when the file is loaded by `using`/`import`/`require` *unless* the file is being precompiled, and in a module file it causes the module to be automatically precompiled when it is imported. Typically, -`__precompile__()` should occur before the `module` declaration in the file, or better yet -`VERSION >= v"0.4" && __precompile__()` in order to be backward-compatible with Julia 0.3. +`__precompile__()` should occur before the `module` declaration in the file. If a module or file is *not* safely precompilable, it should call `__precompile__(false)` in order to throw an error if Julia attempts to precompile it. From 9f61fda67cf89c225d2ebdd0ec9903a7527d1ac6 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Mon, 5 Jun 2017 15:40:10 +0200 Subject: [PATCH 0993/1534] make the output of versioninfo() customizable with kwargs (#21974) and prettify the printing a bit --- CONTRIBUTING.md | 2 +- NEWS.md | 2 + base/deprecated.jl | 4 ++ base/interactiveutil.jl | 84 ++++++++++++++++++++++------------- doc/src/devdocs/backtraces.md | 4 +- test/pkg.jl | 4 +- 6 files changed, 63 insertions(+), 37 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bea8df3c44394..c5e9568b4c376 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -48,7 +48,7 @@ A useful bug report filed as a GitHub issue provides information about how to re 3. When filing a bug report, provide where possible: - The full error message, including the backtrace. - A minimal working example, i.e. the smallest chunk of code that triggers the error. Ideally, this should be code that can be pasted into a REPL or run from a source file. If the code is larger than (say) 50 lines, consider putting it in a [gist](https://gist.github.com). - - The version of Julia as provided by the `versioninfo()` command. Occasionally, the longer output produced by `versioninfo(true)` may be useful also, especially if the issue is related to a specific package. + - The version of Julia as provided by the `versioninfo()` command. Occasionally, the longer output produced by `versioninfo(verbose = true)` may be useful also, especially if the issue is related to a specific package. 4. When pasting code blocks or output, put triple backquotes (\`\`\`) around the text so GitHub will format it nicely. Code statements should be surrounded by single backquotes (\`). Be aware that the `@` sign tags users on GitHub, so references to macros should always be in single backquotes. See [GitHub's guide on Markdown](https://guides.github.com/features/mastering-markdown) for more formatting tricks. diff --git a/NEWS.md b/NEWS.md index 5c415e6c703ee..77a721906297f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -56,6 +56,8 @@ Library improvements * `resize!` and `sizehint!` methods no longer over-reserve memory when the requested array size is more than double of its current size ([#22038]). + * The output of `versioninfo()` is now controlled with keyword arguments ([#21974]). + Compiler/Runtime improvements ----------------------------- diff --git a/base/deprecated.jl b/base/deprecated.jl index 66d4af48e4cf8..580a587609c1b 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1350,6 +1350,10 @@ end @deprecate srand(filename::AbstractString, n::Integer=4) srand(read!(filename, Array{UInt32}(Int(n)))) @deprecate MersenneTwister(filename::AbstractString) srand(MersenneTwister(0), read!(filename, Array{UInt32}(Int(4)))) +# PR #21974 +@deprecate versioninfo(verbose::Bool) versioninfo(verbose=verbose) +@deprecate versioninfo(io::IO, verbose::Bool) versioninfo(io, verbose=verbose) + # END 0.7 deprecations # BEGIN 1.0 deprecations diff --git a/base/interactiveutil.jl b/base/interactiveutil.jl index 34f7724736493..144cd02e538ed 100644 --- a/base/interactiveutil.jl +++ b/base/interactiveutil.jl @@ -245,26 +245,26 @@ end """ - versioninfo(io::IO=STDOUT, verbose::Bool=false) + versioninfo(io::IO=STDOUT; verbose::Bool=false, packages::Bool=false) -Print information about the version of Julia in use. If the `verbose` argument is `true`, -detailed system information is shown as well. +Print information about the version of Julia in use. The output is +controlled with boolean keyword arguments: + +- `packages`: print information about installed packages +- `verbose`: print all additional information """ -function versioninfo(io::IO=STDOUT, verbose::Bool=false) - println(io, "Julia Version $VERSION") +function versioninfo(io::IO=STDOUT; verbose::Bool=false, packages::Bool=false) + println(io, "Julia Version $VERSION") if !isempty(GIT_VERSION_INFO.commit_short) - println(io, "Commit $(GIT_VERSION_INFO.commit_short) ($(GIT_VERSION_INFO.date_string))") + println(io, "Commit $(GIT_VERSION_INFO.commit_short) ($(GIT_VERSION_INFO.date_string))") end if ccall(:jl_is_debugbuild, Cint, ())!=0 println(io, "DEBUG build") end - println(io, "Platform Info:") - println(io, " OS: ", is_windows() ? "Windows" : is_apple() ? + println(io, "Platform Info:") + println(io, " OS: ", is_windows() ? "Windows" : is_apple() ? "macOS" : Sys.KERNEL, " (", Sys.MACHINE, ")") - cpu = Sys.cpu_info() - println(io, " CPU: ", cpu[1].model) - println(io, " WORD_SIZE: ", Sys.WORD_SIZE) if verbose lsb = "" if is_linux() @@ -274,45 +274,65 @@ function versioninfo(io::IO=STDOUT, verbose::Bool=false) try lsb = strip(readstring(`$(ENV["COMSPEC"]) /c ver`)) end end if !isempty(lsb) - println(io, " ", lsb) + println(io, " ", lsb) end if is_unix() - println(io, " uname: ", readchomp(`uname -mprsv`)) + println(io, " uname: ", readchomp(`uname -mprsv`)) + end + end + + if verbose + cpuio = IOBuffer() # print cpu_summary with correct alignment + Sys.cpu_summary(cpuio) + for (i, line) in enumerate(split(String(take!(cpuio)), "\n")) + prefix = i == 1 ? " CPU: " : " " + println(io, prefix, line) end - println(io, "Memory: $(Sys.total_memory()/2^30) GB ($(Sys.free_memory()/2^20) MB free)") - try println(io, "Uptime: $(Sys.uptime()) sec") end - print(io, "Load Avg: ") - print_matrix(io, Sys.loadavg()') - println(io ) - Sys.cpu_summary(io) - println(io ) + else + cpu = Sys.cpu_info() + println(io, " CPU: ", cpu[1].model) end + + if verbose + println(io, " Memory: $(Sys.total_memory()/2^30) GB ($(Sys.free_memory()/2^20) MB free)") + try println(io, " Uptime: $(Sys.uptime()) sec") end + print(io, " Load Avg: ") + print_matrix(io, Sys.loadavg()') + println(io) + end + println(io, " WORD_SIZE: ", Sys.WORD_SIZE) if Base.libblas_name == "libopenblas" || BLAS.vendor() == :openblas || BLAS.vendor() == :openblas64 openblas_config = BLAS.openblas_get_config() - println(io, " BLAS: libopenblas (", openblas_config, ")") + println(io, " BLAS: libopenblas (", openblas_config, ")") else - println(io, " BLAS: ",libblas_name) + println(io, " BLAS: ",libblas_name) + end + println(io, " LAPACK: ",liblapack_name) + println(io, " LIBM: ",libm_name) + println(io, " LLVM: libLLVM-",libllvm_version," (", Sys.JIT, ", ", Sys.cpu_name, ")") + + println(io, "Environment:") + for (k,v) in ENV + if ismatch(r"JULIA", String(k)) + println(io, " $(k) = $(v)") + end end - println(io, " LAPACK: ",liblapack_name) - println(io, " LIBM: ",libm_name) - println(io, " LLVM: libLLVM-",libllvm_version," (", Sys.JIT, ", ", Sys.cpu_name, ")") if verbose - println(io, "Environment:") for (k,v) in ENV - if match(r"JULIA|PATH|FLAG|^TERM$|HOME", String(k)) !== nothing + if ismatch(r"PATH|FLAG|^TERM$|HOME", String(k)) println(io, " $(k) = $(v)") end end - println(io ) - println(io, "Package Directory: ", Pkg.dir()) + end + if packages || verbose + println(io, "Packages:") + println(io, " Package Directory: ", Pkg.dir()) + println(io, " Package Status:") Pkg.status(io) end end -versioninfo(verbose::Bool) = versioninfo(STDOUT,verbose) # displaying type-ambiguity warnings - - """ code_warntype([io::IO], f, types) diff --git a/doc/src/devdocs/backtraces.md b/doc/src/devdocs/backtraces.md index 647530b5d8c66..d6f053f15fe35 100644 --- a/doc/src/devdocs/backtraces.md +++ b/doc/src/devdocs/backtraces.md @@ -15,8 +15,8 @@ and follow the instructions to generate the debugging information requested. Ta ## [Version/Environment info](@id dev-version-info) No matter the error, we will always need to know what version of Julia you are running. When Julia -first starts up, a header is printed out with a version number and date. If your version is -`0.2.0` or higher, please include the output of `versioninfo()` in any report you create: +first starts up, a header is printed out with a version number and date. Please also include the +output of `versioninfo()` in any report you create: ```@repl versioninfo() diff --git a/test/pkg.jl b/test/pkg.jl index 670d1dbcc42aa..4a2c813b46944 100644 --- a/test/pkg.jl +++ b/test/pkg.jl @@ -59,10 +59,10 @@ temp_pkg_dir() do @test_throws PkgError Pkg.installed("MyFakePackage") @test Pkg.installed("Example") === nothing - # check that versioninfo(io, true) doesn't error and produces some output + # check that versioninfo(io; verbose=true) doesn't error and produces some output # (done here since it calls Pkg.status which might error or clone metadata) buf = PipeBuffer() - versioninfo(buf, true) + versioninfo(buf, verbose=true) ver = readstring(buf) @test startswith(ver, "Julia Version $VERSION") @test contains(ver, "Environment:") From aab564a9fe2234ec2eee01368a87c5c1322eb7ea Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 5 Jun 2017 11:35:30 -0400 Subject: [PATCH 0994/1534] various improvements to parser (#22161) - move call to `short-form-function-loc` inside `parse-assignment` this is faster and fixes nested cases like `f(x)=g(x)=1` - fix a case where an `unexpected "foo"` message was missing quotes - optimize common case of arglists of comma-separated simple tokens - some other small optimizations - put code back in precedence order - separate parse-Nary and parse-comma so they're easier to read - cleaner code for parse-unary and parse-factor --- src/julia-parser.scm | 546 ++++++++++++++++++++++--------------------- test/parse.jl | 5 + 2 files changed, 285 insertions(+), 266 deletions(-) diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 264a9ca6d3e3e..e15e23d7fb016 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -45,6 +45,9 @@ ((not (length> l 8)) (eval `(lambda (x) (not (not (,(if (every symbol? l) 'memq 'memv) x (quote ,l))))))) + ((and (every symbol? l) (not (length> l 20))) + (eval `(lambda (x) + (not (not (memq x (quote ,l))))))) (else (let ((t (table))) (for-each (lambda (x) (put! t x #t)) l) @@ -70,6 +73,8 @@ (define unary-ops (append! '(|<:| |>:|) (add-dots '(+ - ! ~ ¬ √ ∛ ∜)))) +(define unary-op? (Set unary-ops)) + ; operators that are both unary and binary (define unary-and-binary-ops '(+ - $ & ~ |.+| |.-|)) @@ -126,6 +131,13 @@ (define reserved-word? (Set reserved-words)) +(define closing-token? + (let ((closer? (Set '(else elseif catch finally #\, #\) #\] #\} #\;)))) + (lambda (tok) + (or (and (eq? tok 'end) (not end-symbol)) + (closer? tok) + (eof-object? tok))))) + ;; Parser state variables ; disable range colon for parsing ternary conditional operator @@ -572,43 +584,94 @@ (list 'call t ex (,self ,s)))) ex))) -(define (parse-cond s) - (let ((ex (parse-arrow s))) - (cond ((eq? (peek-token s) '?) - (begin (take-token s) - (let ((then (without-range-colon (parse-eq* s)))) - (if (not (eq? (take-token s) ':)) - (error "colon expected in \"?\" expression") - (list 'if ex then (parse-eq* s)))))) - (else ex)))) +(define (line-number-node s) + `(line ,(input-port-line (ts:port s)) ,current-filename)) -(define (parse-where-chain s first) - (with-bindings ((where-enabled #f)) - (let loop ((ex first) - (t 'where)) - (if (eq? t 'where) - (begin (take-token s) - (let ((var (parse-comparison s))) - (loop (if (and (pair? var) (eq? (car var) 'cell1d)) - (list* 'where ex (cdr var)) ;; form `x where {T,S}` - (list 'where ex var)) - (peek-token s)))) - ex)))) +;; parse a@b@c@... as (@ a b c ...) for some operator @ +;; ops: operators to look for +;; head: the expression head to yield in the result, e.g. "a;b" => (block a b) +;; closer?: predicate to identify tokens that stop parsing +;; however, this doesn't consume the closing token, just looks at it +;; ow, my eyes!! +(define (parse-Nary s down ops head closer? add-linenums) + (let ((t (require-token s))) + (if (closer? t) + (if add-linenums ;; empty block + (list head (line-number-node s)) + (list head)) + (let loop ((ex + ;; skip leading runs of operator + (if (memv t ops) + (if add-linenums + (list (line-number-node s)) + '()) + (if add-linenums + (let ((loc (line-number-node s))) + ;; note: line-number must happen before (down s) + (list (down s) loc)) + (list (down s))))) + (first? #t) + (t (peek-token s))) + (if (not (memv t ops)) + (begin + (if (not (or (eof-object? t) (eqv? t #\newline) (closer? t))) + (error (string "extra token \"" t "\" after end of expression"))) + (if (or (null? ex) (pair? (cdr ex)) (not first?)) + ;; () => (head) + ;; (ex2 ex1) => (head ex1 ex2) + ;; (ex1) if operator appeared => (head ex1) (handles "x;") + (cons head (reverse! ex)) + ;; (ex1) => ex1 + (car ex))) + (begin (take-token s) + ;; allow input to end with the operator, as in a;b; + (if (or (eof-object? (peek-token s)) + (closer? (peek-token s)) + (memv (peek-token s) ops)) + (loop ex #f (peek-token s)) + (if (and add-linenums + (not (and (pair? (car ex)) + (eq? (caar ex) 'line)))) + (let ((loc (line-number-node s))) + (loop (list* (down s) loc ex) #f (peek-token s))) + (loop (cons (down s) ex) #f (peek-token s)))))))))) -(define (parse-where s down) - ;; `where` needs to be below unary for `+(x::T,y::T) where {T} = ...` to work - (let ((ex (down s))) - (if (and where-enabled - (eq? (peek-token s) 'where)) - (parse-where-chain s ex) - ex))) +;; the principal non-terminals follow, in increasing precedence order -(define (invalid-initial-token? tok) - (or (eof-object? tok) - (memv tok '(#\) #\] #\} else elseif catch finally =)))) +(define (parse-block s (down parse-eq)) + (parse-Nary s down '(#\newline #\;) 'block + (lambda (x) (memq x '(end else elseif catch finally))) #t)) -(define (line-number-node s) - `(line ,(input-port-line (ts:port s)) ,current-filename)) +;; ";" at the top level produces a sequence of top level expressions +(define (parse-stmts s) + (let ((ex (parse-Nary s (lambda (s) (parse-docstring s parse-eq)) + '(#\;) 'toplevel (lambda (x) (eqv? x #\newline)) #f))) + ;; check for unparsed junk after an expression + (let ((t (peek-token s))) + (if (not (or (eof-object? t) (eqv? t #\newline) (eq? t #f))) + (error (string "extra token \"" t "\" after end of expression")))) + ex)) + +(define (parse-eq s) (parse-assignment s parse-comma)) + +;; symbol tokens that do not simply parse to themselves when appearing alone as +;; an element of an argument list +(define non-standalone-symbol-token? + (Set (append operators reserved-words '(.... mutable primitive)))) + +; parse-eq* is used where commas are special, for example in an argument list +(define (parse-eq* s) + (let ((t (peek-token s))) + ;; optimization: skip checking the whole precedence stack if we have a simple + ;; token followed by a common closing token + (if (or (number? t) (and (symbol? t) (not (non-standalone-symbol-token? t)))) + (begin (take-token s) + (let ((nxt (peek-token s))) + (if (or (eqv? nxt #\,) (eqv? nxt #\) ) (eqv? nxt #\}) (eqv? nxt #\])) + t + (begin (ts:put-back! s t) + (parse-assignment s parse-cond))))) + (parse-assignment s parse-cond)))) (define (eventually-call ex) (and (pair? ex) @@ -616,69 +679,87 @@ (and (or (eq? (car ex) 'where) (eq? (car ex) '|::|)) (eventually-call (cadr ex)))))) -;; insert line/file for short-form function defs, otherwise leave alone (define (short-form-function-loc ex lno) - (if (and (pair? ex) - (eq? (car ex) '=) - (eventually-call (cadr ex))) + (if (eventually-call (cadr ex)) `(= ,(cadr ex) (block (line ,lno ,current-filename) ,(caddr ex))) ex)) -;; parse a@b@c@... as (@ a b c ...) for some operator @ -;; op: the operator to look for -;; head: the expression head to yield in the result, e.g. "a;b" => (block a b) -;; closers: a list of tokens that will stop the process -;; however, this doesn't consume the closing token, just looks at it -;; allow-empty: if true will ignore runs of the operator, like a@@@@b -;; ow, my eyes!! -(define (parse-Nary s down ops head closer? allow-empty add-linenums) - (let ((t (require-token s))) - (if (invalid-initial-token? t) - (error (string "unexpected \"" t "\""))) - (if (closer? t) - (if add-linenums ;; empty block - (list head (line-number-node s)) - (list head)) - (let loop ((ex - ;; in allow-empty mode skip leading runs of operator - (if (and allow-empty (memv t ops)) - (if add-linenums - (list (line-number-node s)) - '()) - (if add-linenums - (let ((loc (line-number-node s))) - ;; note: line-number must happen before (down s) - (list (down s) loc)) - (list (down s))))) - (first? #t) - (t (peek-token s))) - (if (not (memv t ops)) - (begin - (if (not (or (eof-object? t) (eqv? t #\newline) (memv #\, ops) - (closer? t))) - (error (string "extra token \"" t "\" after end of expression"))) - (if (or (null? ex) (pair? (cdr ex)) (not first?)) - ;; () => (head) - ;; (ex2 ex1) => (head ex1 ex2) - ;; (ex1) if operator appeared => (head ex1) (handles "x;") - (cons head (reverse! ex)) - ;; (ex1) => ex1 - (car ex))) - (begin (take-token s) - ;; allow input to end with the operator, as in a;b; - (if (or (eof-object? (peek-token s)) - (closer? (peek-token s)) - (and allow-empty - (memv (peek-token s) ops)) - (and (eqv? (car ops) #\,) - (eq? (peek-token s) '=))) - (loop ex #f (peek-token s)) - (if (and add-linenums - (not (and (pair? (car ex)) - (eq? (caar ex) 'line)))) - (let ((loc (line-number-node s))) - (loop (list* (down s) loc ex) #f (peek-token s))) - (loop (cons (down s) ex) #f (peek-token s)))))))))) +(define (parse-assignment s down) + (let loop ((ex (down s)) + (t (peek-token s))) + (if (not (is-prec-assignment? t)) + ex + (begin + (take-token s) + (cond ((eq? t '~) + (if (and space-sensitive (ts:space? s) + (not (eqv? (peek-char (ts:port s)) #\ ))) + (begin (ts:put-back! s t) + ex) + (list 'call t ex (parse-assignment s down)))) + ((eq? t '=>) ;; ~ and => are the only non-syntactic assignment-precedence operators + (list 'call t ex (parse-assignment s down))) + ((eq? t '=) + ;; insert line/file for short-form function defs, otherwise leave alone + (let ((lno (input-port-line (ts:port s)))) + (short-form-function-loc + (list t ex (parse-assignment s down)) lno))) + (else + (list t ex (parse-assignment s down)))))))) + +; parse-comma is needed for commas outside parens, for example a = b,c +(define (parse-comma s) + (let loop ((ex (list (parse-cond s))) + (first? #t) + (t (peek-token s))) + (if (not (eqv? t #\,)) + (if (or (pair? (cdr ex)) (not first?)) + ;; () => (tuple) + ;; (ex2 ex1) => (tuple ex1 ex2) + ;; (ex1,) => (tuple ex1) + (cons 'tuple (reverse! ex)) + ;; (ex1) => ex1 + (car ex)) + (begin (take-token s) + (if (or (eof-object? (peek-token s)) (eq? (peek-token s) '=)) + (loop ex #f (peek-token s)) + (loop (cons (parse-cond s) ex) #f (peek-token s))))))) + +(define (parse-cond s) + (let ((ex (parse-arrow s))) + (cond ((eq? (peek-token s) '?) + (begin (take-token s) + (let ((then (without-range-colon (parse-eq* s)))) + (if (not (eq? (take-token s) ':)) + (error "colon expected in \"?\" expression") + (list 'if ex then (parse-eq* s)))))) + (else ex)))) + +(define (parse-arrow s) (parse-RtoL s parse-or is-prec-arrow? (eq? t '-->) parse-arrow)) +(define (parse-or s) (parse-RtoL s parse-and is-prec-lazy-or? #t parse-or)) +(define (parse-and s) (parse-RtoL s parse-comparison is-prec-lazy-and? #t parse-and)) + +(define (parse-comparison s) + (let loop ((ex (parse-pipes s)) + (first #t)) + (let ((t (peek-token s))) + (cond ((is-prec-comparison? t) + (begin (take-token s) + (if first + (loop (list 'comparison ex t (parse-pipes s)) #f) + (loop (append ex (list t (parse-pipes s))) #f)))) + (first ex) + ((length= ex 4) + ;; only a single comparison; special chained syntax not required + (let ((op (caddr ex)) + (arg1 (cadr ex)) + (arg2 (cadddr ex))) + (if (or (eq? op '|<:|) (eq? op '|>:|)) + `(,op ,arg1 ,arg2) + `(call ,op ,arg1 ,arg2)))) + (else ex))))) + +(define (parse-pipes s) (parse-LtoR s parse-range is-prec-pipe?)) ; parse ranges and postfix ... ; colon is strange; 3 arguments with 2 colons yields one call: @@ -728,64 +809,14 @@ (list '... ex)) (else ex))))) -;; the principal non-terminals follow, in increasing precedence order - -(define (parse-block s (down parse-eq)) - (parse-Nary s down '(#\newline #\;) 'block - (lambda (x) (memq x '(end else elseif catch finally))) #t #t)) - -;; ";" at the top level produces a sequence of top level expressions -(define (parse-stmts s) - (let ((ex (parse-Nary s (lambda (s) (parse-docstring s parse-eq)) - '(#\;) 'toplevel (lambda (x) (eqv? x #\newline)) #t #f))) - ;; check for unparsed junk after an expression - (let ((t (peek-token s))) - (if (not (or (eof-object? t) (eqv? t #\newline) (eq? t #f))) - (error (string "extra token \"" t "\" after end of expression")))) - ex)) - -(define (parse-assignment s down) - (let loop ((ex (down s)) - (t (peek-token s))) - (if (not (is-prec-assignment? t)) - ex - (begin (take-token s) - (if (eq? t '~) - (if (and space-sensitive (ts:space? s) - (not (eqv? (peek-char (ts:port s)) #\ ))) - (begin (ts:put-back! s t) - ex) - (list 'call t ex (parse-assignment s down))) - (if (eq? t '=>) ;; ~ and => are the only non-syntactic assignment-precedence operators - (list 'call t ex (parse-assignment s down)) - (list t ex (parse-assignment s down)))))))) - -(define (parse-eq s) - (let ((lno (input-port-line (ts:port s)))) - (short-form-function-loc - (parse-assignment s parse-comma) lno))) - -; parse-eq* is used where commas are special, for example in an argument list -(define (parse-eq* s) - (let ((lno (input-port-line (ts:port s)))) - (short-form-function-loc - (parse-assignment s parse-cond) lno))) - -; parse-comma is needed for commas outside parens, for example a = b,c -(define (parse-comma s) (parse-Nary s parse-cond '(#\,) 'tuple (lambda (x) #f) #f #f)) -(define (parse-arrow s) (parse-RtoL s parse-or is-prec-arrow? (eq? t '-->) parse-arrow)) -(define (parse-or s) (parse-RtoL s parse-and is-prec-lazy-or? #t parse-or)) -(define (parse-and s) (parse-RtoL s parse-comparison is-prec-lazy-and? #t parse-and)) - ;; parse left to right chains of a certain binary operator ;; returns a list of arguments (define (parse-chain s down op) (let loop ((chain (list (down s)))) - (let* ((t (peek-token s)) - (spc (ts:space? s))) + (let ((t (peek-token s))) (if (not (eq? t op)) (reverse! chain) - (begin + (let ((spc (ts:space? s))) (take-token s) (cond ((and space-sensitive spc (memq t unary-and-binary-ops) (not (eqv? (peek-char (ts:port s)) #\ ))) @@ -799,11 +830,10 @@ ;; e.g. a+b+c => (call + a b c) (define (parse-with-chains s down ops chain-ops) (let loop ((ex (down s))) - (let* ((t (peek-token s)) - (spc (ts:space? s))) + (let ((t (peek-token s))) (if (not (ops t)) ex - (begin + (let ((spc (ts:space? s))) (take-token s) (cond ((and space-sensitive spc (memq t unary-and-binary-ops) (not (eqv? (peek-char (ts:port s)) #\ ))) @@ -816,42 +846,50 @@ (else (loop (list 'call t ex (down s)))))))))) -(define (parse-expr s) (parse-with-chains s parse-shift is-prec-plus? '(+ ++))) +(define (parse-expr s) (parse-with-chains s parse-shift is-prec-plus? '(+ ++))) +(define (parse-shift s) (parse-LtoR s parse-term is-prec-bitshift?)) +(define (parse-term s) (parse-with-chains s parse-rational is-prec-times? '(*))) +(define (parse-rational s) (parse-LtoR s parse-unary-subtype is-prec-rational?)) -(define (parse-shift s) (parse-LtoR s parse-term is-prec-bitshift?)) - -(define (parse-term s) (parse-with-chains s parse-rational is-prec-times? '(*))) - -(define (parse-rational s) (parse-LtoR s (lambda (s) (parse-unary-subtype s)) is-prec-rational?)) - -(define (parse-pipes s) (parse-LtoR s parse-range is-prec-pipe?)) +;; parse `<: A where B` as `<: (A where B)` (issue #21545) +(define (parse-unary-subtype s) + (let ((op (require-token s))) + (if (or (eq? op '|<:|) (eq? op '|>:|)) + (begin (take-token s) + (let ((next (peek-token s))) + (cond ((or (closing-token? next) (newline? next) (eq? next '=)) + op) ; return operator by itself, as in (<:) + ;; parse <:{T}(x::T) or <:(x::T) like other unary operators + ((or (eqv? next #\{) (eqv? next #\( )) + (ts:put-back! s op) + (parse-where s parse-unary)) + (else + (let ((arg (parse-where s parse-unary))) + (if (and (pair? arg) (eq? (car arg) 'tuple)) + (cons op (cdr arg)) + (list op arg))))))) + (parse-where s parse-unary)))) -(define (parse-comparison s) - (let loop ((ex (parse-pipes s)) - (first #t)) - (let ((t (peek-token s))) - (cond ((is-prec-comparison? t) - (begin (take-token s) - (if first - (loop (list 'comparison ex t (parse-pipes s)) #f) - (loop (append ex (list t (parse-pipes s))) #f)))) - (first ex) - ((length= ex 4) - ;; only a single comparison; special chained syntax not required - (let ((op (caddr ex)) - (arg1 (cadr ex)) - (arg2 (cadddr ex))) - (if (or (eq? op '|<:|) (eq? op '|>:|)) - `(,op ,arg1 ,arg2) - `(call ,op ,arg1 ,arg2)))) - (else ex))))) +(define (parse-where-chain s first) + (with-bindings ((where-enabled #f)) + (let loop ((ex first) + (t 'where)) + (if (eq? t 'where) + (begin (take-token s) + (let ((var (parse-comparison s))) + (loop (if (and (pair? var) (eq? (car var) 'cell1d)) + (list* 'where ex (cdr var)) ;; form `x where {T,S}` + (list 'where ex var)) + (peek-token s)))) + ex)))) -(define closing-token? - (let ((closer? (Set '(else elseif catch finally #\, #\) #\] #\} #\;)))) - (lambda (tok) - (or (and (eq? tok 'end) (not end-symbol)) - (closer? tok) - (eof-object? tok))))) +(define (parse-where s down) + ;; `where` needs to be below unary for `+(x::T,y::T) where {T} = ...` to work + (let ((ex (down s))) + (if (and where-enabled + (eq? (peek-token s) 'where)) + (parse-where-chain s ex) + ex))) (define (maybe-negate op num) (if (eq? op '-) @@ -864,6 +902,53 @@ (- num))) num)) +;; operators handled by parse-unary at the start of an expression +(define initial-operator? + ;; TODO: ? should probably not be listed here except for the syntax hack in osutils.jl + (Set (diff operators (append '(: |'| ?) syntactic-unary-operators syntactic-operators)))) + +(define (parse-unary s) + (let ((op (require-token s))) + (if (closing-token? op) + (error (string "unexpected \"" op "\""))) + (if (initial-operator? op) + (begin + (take-token s) + (if (or (eq? op '-) (eq? op '+)) + (let ((nch (peek-char (ts:port s)))) + (if (or (and (char? nch) (char-numeric? nch)) + (and (eqv? nch #\.) (read-char (ts:port s)))) + (let ((num (parse-juxtapose + (read-number (ts:port s) (eqv? nch #\.) (eq? op '-)) + s))) + (if (is-prec-power? (peek-token s)) + ;; -2^x parsed as (- (^ 2 x)) + (begin (ts:put-back! s (maybe-negate op num)) + (list 'call op (parse-factor s))) + num)) + (parse-unary-call s op #t))) + (parse-unary-call s op (unary-op? op)))) + (parse-juxtapose (parse-factor s) s)))) + +(define (parse-unary-call s op un) + (let ((next (peek-token s))) + (cond ((or (closing-token? next) (newline? next) (eq? next '=)) + op) ; return operator by itself, as in (+) + ((or (eqv? next #\{) ;; this case is +{T}(x::T) = ... + (and (not un) (eqv? next #\( ))) + (ts:put-back! s op) + (parse-factor s)) + ((not un) + (error (string "\"" op "\" is not a unary operator"))) + (else + (let* ((arg (parse-unary s)) + (args (if (and (pair? arg) (eq? (car arg) 'tuple)) + (cons op (cdr arg)) + (list op arg)))) + (if (or (eq? op '|<:|) (eq? op '|>:|)) + args + (cons 'call args))))))) + ;; given an expression and the next token, is there a juxtaposition ;; operator between them? (define (juxtapose? s expr t) @@ -899,83 +984,11 @@ `(call * ,ex ,(parse-unary s)))) (else ex)))) -(define (invalid-identifier-name? ex) - (or (syntactic-op? ex) (eq? ex '....))) - -;; parse `<: A where B` as `<: (A where B)` (issue #21545) -(define (parse-unary-subtype s) - (let ((op (require-token s))) - (if (or (eq? op '|<:|) (eq? op '|>:|)) - (begin (take-token s) - (let ((next (peek-token s))) - (cond ((or (closing-token? next) (newline? next) (eq? next '=)) - op) ; return operator by itself, as in (<:) - ;; parse <:{T}(x::T) or <:(x::T) like other unary operators - ((or (eqv? next #\{) (eqv? next #\( )) - (ts:put-back! s op) - (parse-where s parse-unary)) - (else - (let ((arg (parse-where s parse-unary))) - (if (and (pair? arg) (eq? (car arg) 'tuple)) - (cons op (cdr arg)) - (list op arg))))))) - (parse-where s parse-unary)))) - -(define (parse-unary s) - (let ((t (require-token s))) - (if (closing-token? t) - (error (string "unexpected " t))) - ;; TODO: ? should probably not be listed here except for the syntax hack in osutils.jl - (cond ((and (operator? t) (not (memq t '(: |'| ?))) (not (syntactic-unary-op? t)) - (not (invalid-identifier-name? t))) - (let* ((op (take-token s)) - (nch (peek-char (ts:port s)))) - (if (and (or (eq? op '-) (eq? op '+)) - (or (and (char? nch) (char-numeric? nch)) - (and (eqv? nch #\.) (read-char (ts:port s))))) - (let ((num (parse-juxtapose - (read-number (ts:port s) (eqv? nch #\.) (eq? op '-)) - s))) - (if (is-prec-power? (peek-token s)) - ;; -2^x parsed as (- (^ 2 x)) - (begin (ts:put-back! s (maybe-negate op num)) - (list 'call op (parse-factor s))) - num)) - (let ((next (peek-token s))) - (cond ((or (closing-token? next) (newline? next) (eq? next '=)) - op) ; return operator by itself, as in (+) - ((or (eqv? next #\{) ;; this case is +{T}(x::T) = ... - (and (not (memq op unary-ops)) - (eqv? next #\( ))) - (ts:put-back! s op) - (parse-factor s)) - ((not (memq op unary-ops)) - (error (string "\"" op "\" is not a unary operator"))) - (else - (let* ((arg (parse-unary s)) - (args (if (and (pair? arg) (eq? (car arg) 'tuple)) - (cons op (cdr arg)) - (list op arg)))) - (if (or (eq? op '|<:|) (eq? op '|>:|)) - args - (cons 'call args))))))))) - (else - (parse-juxtapose (parse-factor s) s))))) - ;; handle ^ and .^ -(define (parse-factor-h s down ops) - (let ((ex (down s)) - (t (peek-token s))) - (cond ((not (ops t)) - ex) - (else - (list 'call - (take-token s) ex (parse-factor-h s parse-unary ops)))))) - ;; -2^3 is parsed as -(2^3), so call parse-decl for the first argument, ;; and parse-unary from then on (to handle 2^-3) -(define (parse-factor s) - (parse-factor-h s parse-decl is-prec-power?)) +(define (parse-factor s) (parse-RtoL s parse-decl is-prec-power? #f parse-factor-after)) +(define (parse-factor-after s) (parse-RtoL s parse-unary is-prec-power? #f parse-factor-after)) (define (parse-decl s) (let loop ((ex (parse-call s))) @@ -991,24 +1004,25 @@ (else ex))))) +;; parse function call, indexing, dot, and transpose expressions +;; also handles looking for syntactic reserved words +(define (parse-call s) + (let ((ex (parse-unary-prefix s))) + (if (or (initial-reserved-word? ex) (eq? ex 'mutable) (eq? ex 'primitive)) + (parse-resword s ex) + (parse-call-chain s ex #f)))) + (define (parse-unary-prefix s) (let ((op (peek-token s))) (if (syntactic-unary-op? op) (begin (take-token s) (cond ((let ((next (peek-token s))) - (or (closing-token? next) (newline? next))) op) + (or (closing-token? next) (newline? next))) + op) ((memq op '(& |::|)) (list op (parse-where s parse-call))) (else (list op (parse-unary-prefix s))))) (parse-atom s)))) -;; parse function call, indexing, dot, and transpose expressions -;; also handles looking for syntactic reserved words -(define (parse-call s) - (let ((ex (parse-unary-prefix s))) - (if (or (initial-reserved-word? ex) (memq ex '(mutable primitive))) - (parse-resword s ex) - (parse-call-chain s ex #f)))) - (define (parse-def s is-func) (let* ((ex (parse-unary-prefix s)) (sig (if (or (and is-func (reserved-word? ex)) (initial-reserved-word? ex)) @@ -1973,9 +1987,9 @@ ;; process escape sequences using lisp read (read (open-input-string (string #\" s #\")))))) -(define (check-identifier ex) - (if (invalid-identifier-name? ex) - (error (string "invalid identifier name \"" ex "\"")))) +(define-macro (check-identifier ex) + `(if (or (syntactic-op? ,ex) (eq? ,ex '....)) + (error (string "invalid identifier name \"" ,ex "\"")))) ;; parse numbers, identifiers, parenthesized expressions, lists, vectors, etc. (define (parse-atom s (checked #t)) diff --git a/test/parse.jl b/test/parse.jl index d1e335b9d7e30..5fd78b99d476f 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -1212,6 +1212,11 @@ end @test expand(:(f(2, a=1, w=3, c=3, w=4, b=2))) == Expr(:error, "keyword argument \"w\" repeated in call to \"f\"") +let f(x) = + g(x) = 1 + @test functionloc(f(1))[2] > functionloc(f)[2] +end + # issue #19351 # adding return type decl should not affect parse of function body @test :(t(abc) = 3).args[2] == :(t(abc)::Int = 3).args[2] From 4634a3dfe21667575ee6a64bbe92841f3951f0e9 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 29 May 2017 23:36:52 -0400 Subject: [PATCH 0995/1534] improve specificity algorithm, add assertions and tests simplify tuple type specificity implementation fix specificity `A{B,B,C} < A{B,C,D}` --- src/subtype.c | 349 ++++++++++++++++++++------------------------ test/choosetests.jl | 2 +- test/core.jl | 106 -------------- test/specificity.jl | 144 ++++++++++++++++++ 4 files changed, 306 insertions(+), 295 deletions(-) create mode 100644 test/specificity.jl diff --git a/src/subtype.c b/src/subtype.c index 2cf56492a6d56..bcbf89909dd6e 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -2217,61 +2217,6 @@ JL_DLLEXPORT jl_svec_t *jl_env_from_type_intersection(jl_value_t *a, jl_value_t // specificity comparison -static jl_datatype_t *jl_fix_vararg_bound(jl_datatype_t *tt, int nfix) -{ - assert(jl_is_va_tuple(tt)); - assert(nfix >= 0); - jl_svec_t *tp = tt->parameters; - size_t ntp = jl_svec_len(tp); - jl_value_t *env[2] = { jl_tparam1(jl_unwrap_unionall(jl_tparam(tt, ntp-1))), jl_box_long(nfix) }; - JL_GC_PUSH2(&env[0], &env[1]); - jl_datatype_t *ret = (jl_datatype_t*)jl_instantiate_type_with((jl_value_t*)tt, env, 1); - JL_GC_POP(); - return ret; -} - -/* -Simplification of varargs tuple types: - JL_TUPLE_FIXED: tuples of known length (e.g., JL_VARARG_NONE or JL_VARARG_INT) - JL_TUPLE_VAR: tuples of unknown length (e.g., JL_VARARG_BOUND or JL_VARARG_UNBOUND) - -In some cases, JL_VARARG_BOUND tuples get described as JL_TUPLE_FIXED, -if the constraints on length are already known. - -lenr = "representation length" (the number of parameters) -lenf = "full length" (including the Vararg length, if known) - -In general, lenf >= lenr-1. The lower bound is achieved only for a Vararg of length 0. -*/ -typedef enum { - JL_TUPLE_FIXED = 0, - JL_TUPLE_VAR = 1 -} jl_tuple_lenkind_t; - -static size_t tuple_vararg_params(jl_svec_t *a, jl_vararg_kind_t *kind, jl_tuple_lenkind_t *lenkind) -{ - jl_value_t **data = jl_svec_data(a); size_t lenr = jl_svec_len(a); - size_t lenf = lenr; - if (lenr == 0) { - *kind = JL_VARARG_NONE; - *lenkind = JL_TUPLE_FIXED; - return lenf; - } - *lenkind = JL_TUPLE_VAR; - jl_value_t *last = data[lenr-1]; - *kind = jl_vararg_kind(last); - if (*kind == JL_VARARG_NONE || *kind == JL_VARARG_INT) - *lenkind = JL_TUPLE_FIXED; - if (*kind == JL_VARARG_INT || *kind == JL_VARARG_BOUND) { - jl_value_t *N = jl_tparam1(jl_unwrap_unionall(last)); - if (jl_is_long(N)) { - lenf += jl_unbox_long(N)-1; - *lenkind = JL_TUPLE_FIXED; - } - } - return lenf; -} - static int eq_msp(jl_value_t *a, jl_value_t *b, jl_typeenv_t *env) { // equate ANY and Any for specificity purposes, #16153 @@ -2293,116 +2238,142 @@ static int eq_msp(jl_value_t *a, jl_value_t *b, jl_typeenv_t *env) return eq; } +static int sub_msp(jl_value_t *a, jl_value_t *b, jl_typeenv_t *env) +{ + JL_GC_PUSH2(&a, &b); + while (env != NULL) { + a = jl_type_unionall(env->var, a); + b = jl_type_unionall(env->var, b); + env = env->prev; + } + int sub = jl_subtype(a, b); + JL_GC_POP(); + return sub; +} + static int type_morespecific_(jl_value_t *a, jl_value_t *b, int invariant, jl_typeenv_t *env); static int num_occurs(jl_tvar_t *v, jl_typeenv_t *env); +static jl_value_t *nth_tuple_elt(jl_datatype_t *t, size_t i) +{ + size_t len = jl_field_count(t); + if (len == 0) + return NULL; + if (i < len-1) + return jl_tparam(t, i); + jl_value_t *last = jl_unwrap_unionall(jl_tparam(t, len-1)); + if (jl_is_vararg_type(last)) { + jl_value_t *n = jl_tparam1(last); + if (jl_is_long(n) && i >= len-1+jl_unbox_long(n)) + return NULL; + return jl_tparam0(last); + } + if (i == len-1) + return jl_tparam(t, i); + return NULL; +} + static int tuple_morespecific(jl_datatype_t *cdt, jl_datatype_t *pdt, int invariant, jl_typeenv_t *env) { - size_t clenr = jl_nparams(cdt); - jl_value_t **child = jl_svec_data(cdt->parameters); - size_t plenr = jl_nparams(pdt); - jl_value_t **parent = jl_svec_data(pdt->parameters); - size_t plenf, clenf; - jl_vararg_kind_t ckind, pkind; - jl_tuple_lenkind_t clenkind, plenkind; - clenf = tuple_vararg_params(cdt->parameters, &ckind, &clenkind); - plenf = tuple_vararg_params(pdt->parameters, &pkind, &plenkind); - size_t ci=0, pi=0; - int cseq=0, pseq=0, cdiag=0, pdiag=0; + size_t plen = jl_nparams(pdt); + if (plen == 0) return 0; + size_t clen = jl_nparams(cdt); + if (clen == 0) return 1; + int i = 0; + int cva = jl_vararg_kind(jl_tparam(cdt,clen-1)) > JL_VARARG_INT; + int pva = jl_vararg_kind(jl_tparam(pdt,plen-1)) > JL_VARARG_INT; + int cdiag = 0, pdiag = 0; int some_morespecific = 0; - jl_value_t *ce=NULL, *pe=NULL; while (1) { - if (!cseq) - cseq = (ci= clenf && !cseq) { - if (pseq && plenr <= clenr+1) return 1; - // shorter tuples are more specific, to ensure transitivity with varargs - if (!pseq && clenr < plenr) return 1; + if (cva && pva && i >= clen && i >= plen) break; + + jl_value_t *ce = nth_tuple_elt(cdt, i); + jl_value_t *pe = nth_tuple_elt(pdt, i); + + if (ce == NULL) { + if (pe == NULL) break; + return 1; } - if (pi >= plenf && !pseq) { - if (!(cseq || clenf >= plenf)) return 0; + if (pe == NULL) { + if (!cva && !some_morespecific) + return 0; break; } - if (ci < clenr) { - ce = child[ci]; - if (jl_is_vararg_type(ce)) ce = jl_unwrap_vararg(ce); - } - if (pi < plenr) { - pe = parent[pi]; - if (jl_is_vararg_type(pe)) pe = jl_unwrap_vararg(pe); + if (type_morespecific_(pe, ce, invariant, env)) { + assert(!type_morespecific_(ce, pe, invariant, env)); + return 0; } - int cms = type_morespecific_(ce, pe, invariant, env); - int pms = type_morespecific_(pe, ce, invariant, env); - - if (!cms && pms) return 0; - if (!cdiag && jl_is_typevar(ce) && num_occurs((jl_tvar_t*)ce,env) > 1) cdiag = 1; if (!pdiag && jl_is_typevar(pe) && num_occurs((jl_tvar_t*)pe,env) > 1) pdiag = 1; // in Tuple{a,b...} and Tuple{c,d...} allow b and d to be disjoint - if (cseq && pseq && (some_morespecific || (cdiag && !pdiag))) return 1; - - int eqv = eq_msp(ce,pe,env); - - if (!cms && !eqv) return 0; + if (cva && pva && i >= clen-1 && i >= plen-1 && (some_morespecific || (cdiag && !pdiag))) + return 1; - if (cms && !pms) - some_morespecific = 1; + int cms = type_morespecific_(ce, pe, invariant, env); + int eqv = !cms && eq_msp(ce, pe, env); - if (cms && ci==clenr-1 && pi==plenr-1 && clenr == plenr && !cseq && pseq) { - // make Vararg{X, 1} more specific than Vararg{X, N} - if (jl_is_vararg_type(child[ci]) && eqv) - return 1; - } + if (!cms && !eqv) + return 0; - if (cseq && pseq) { - if (clenr > plenr && (!pdiag || cdiag)) - return 1; - break; - } - ci++; - pi++; + if (cms) some_morespecific = 1; + i++; } + if (cva && pva && clen > plen && (!pdiag || cdiag)) + return 1; return some_morespecific || (cdiag && !pdiag); } +static size_t tuple_full_length(jl_value_t *t) +{ + size_t n = jl_nparams(t); + if (n == 0) return 0; + jl_value_t *last = jl_unwrap_unionall(jl_tparam(t,n-1)); + if (jl_is_vararg_type(last)) { + jl_value_t *N = jl_tparam1(last); + if (jl_is_long(N)) + n += jl_unbox_long(N)-1; + } + return n; +} + // Called when a is a bound-vararg and b is not a vararg. Sets the vararg length // in a to match b, as long as this makes some earlier argument more specific. static int args_morespecific_fix1(jl_value_t *a, jl_value_t *b, int swap, jl_typeenv_t *env) { - jl_datatype_t *tta = (jl_datatype_t*)a; - jl_datatype_t *ttb = (jl_datatype_t*)b; - size_t n = jl_nparams(tta); - jl_datatype_t *newtta = jl_fix_vararg_bound(tta, jl_nparams(ttb)-n+1); + size_t n = jl_nparams(a); + int taillen = tuple_full_length(b)-n+1; + if (taillen <= 0) + return -1; + assert(jl_is_va_tuple((jl_datatype_t*)a)); + jl_datatype_t *new_a = NULL; + jl_value_t *e[2] = { jl_tparam1(jl_unwrap_unionall(jl_tparam(a, n-1))), jl_box_long(taillen) }; + JL_GC_PUSH2(&new_a, &e[1]); + new_a = (jl_datatype_t*)jl_instantiate_type_with((jl_value_t*)a, e, 1); int changed = 0; for (size_t i = 0; i < n-1; i++) { - if (jl_tparam(tta, i) != jl_tparam(newtta, i)) { + if (jl_tparam(a, i) != jl_tparam(new_a, i)) { changed = 1; break; } } + int ret = -1; if (changed) { - JL_GC_PUSH1(&newtta); - int ret; - if (jl_types_equal(b, (jl_value_t*)newtta)) + if (eq_msp(b, (jl_value_t*)new_a, env)) ret = swap; else if (swap) - ret = type_morespecific_(b, (jl_value_t*)newtta, 0, env); + ret = type_morespecific_(b, (jl_value_t*)new_a, 0, env); else - ret = type_morespecific_((jl_value_t*)newtta, b, 0, env); - JL_GC_POP(); - return ret; + ret = type_morespecific_((jl_value_t*)new_a, b, 0, env); } - return -1; + JL_GC_POP(); + return ret; } static int partially_morespecific(jl_value_t *a, jl_value_t *b, int invariant, jl_typeenv_t *env) @@ -2442,11 +2413,10 @@ static int count_occurs(jl_value_t *t, jl_tvar_t *v) static int num_occurs(jl_tvar_t *v, jl_typeenv_t *env) { - jl_typeenv_t *e = env; - while (e != NULL) { - if (e->var == v) - return (int)(ssize_t)e->val; - e = e->prev; + while (env != NULL) { + if (env->var == v) + return (int)(ssize_t)env->val; + env = env->prev; } return 0; } @@ -2455,6 +2425,7 @@ static int type_morespecific_(jl_value_t *a, jl_value_t *b, int invariant, jl_ty { if (a == b) return 0; + if (jl_is_unionall(a)) { jl_unionall_t *ua = (jl_unionall_t*)a; jl_typeenv_t newenv = { ua->var, 0x0, env }; @@ -2467,38 +2438,29 @@ static int type_morespecific_(jl_value_t *a, jl_value_t *b, int invariant, jl_ty newenv.val = (jl_value_t*)(intptr_t)count_occurs(ub->body, ub->var); return type_morespecific_(a, ub->body, invariant, &newenv); } - size_t i; + if (jl_is_tuple_type(a) && jl_is_tuple_type(b)) { - jl_datatype_t *tta = (jl_datatype_t*)a; - jl_datatype_t *ttb = (jl_datatype_t*)b; - size_t alenf, blenf; - jl_vararg_kind_t akind, bkind; - jl_tuple_lenkind_t alenkind, blenkind; - alenf = tuple_vararg_params(tta->parameters, &akind, &alenkind); - blenf = tuple_vararg_params(ttb->parameters, &bkind, &blenkind); // When one is JL_VARARG_BOUND and the other has fixed length, // allow the argument length to fix the tvar + jl_vararg_kind_t akind = jl_va_tuple_kind((jl_datatype_t*)a); + jl_vararg_kind_t bkind = jl_va_tuple_kind((jl_datatype_t*)b); int ans = -1; - if (akind == JL_VARARG_BOUND && blenkind == JL_TUPLE_FIXED && blenf >= alenf) + if (akind == JL_VARARG_BOUND && bkind < JL_VARARG_BOUND) ans = args_morespecific_fix1(a, b, 0, env); - if (bkind == JL_VARARG_BOUND && alenkind == JL_TUPLE_FIXED && alenf >= blenf) + if (bkind == JL_VARARG_BOUND && akind < JL_VARARG_BOUND) ans = args_morespecific_fix1(b, a, 1, env); - if (ans != -1) return ans; + if (ans != -1) + return ans; return tuple_morespecific((jl_datatype_t*)a, (jl_datatype_t*)b, invariant, env); } if (jl_is_uniontype(a)) { - if (jl_subtype(b, a)) { - // fixes issue #4413 - if (!jl_subtype(a, b)) - return 0; - } - else if (jl_subtype(a, b)) { + if (sub_msp(b, a, env)) + return 0; + else if (sub_msp(a, b, env)) return 1; - } - // Union a is more specific than b if some element of a is - // more specific than b, and b is not more specific than any - // element of a. + // Union a is more specific than b if some element of a is more specific than b, + // and b is not more specific than any element of a. jl_uniontype_t *u = (jl_uniontype_t*)a; if (partially_morespecific(u->a, b, invariant, env) && !type_morespecific_(b, u->a, invariant, env)) { if (partially_morespecific(b, a, invariant, env)) @@ -2519,63 +2481,77 @@ static int type_morespecific_(jl_value_t *a, jl_value_t *b, int invariant, jl_ty jl_value_t *tp0a = jl_tparam0(a); if (jl_is_typevar(tp0a)) { jl_value_t *ub = ((jl_tvar_t*)tp0a)->ub; - if (jl_is_kind(b) && !jl_subtype((jl_value_t*)jl_any_type, ub)) + if (jl_is_kind(b) && !sub_msp((jl_value_t*)jl_any_type, ub, env)) return 1; } else if (tp0a == jl_bottom_type) { - if (jl_subtype(b, (jl_value_t*)jl_type_type)) + if (sub_msp(b, (jl_value_t*)jl_type_type, env)) return 1; } - else { - if (b == (jl_value_t*)jl_datatype_type || b == (jl_value_t*)jl_unionall_type || - b == (jl_value_t*)jl_uniontype_type || jl_isa(tp0a, b)) - return 1; + else if (b == (jl_value_t*)jl_datatype_type || b == (jl_value_t*)jl_unionall_type || + b == (jl_value_t*)jl_uniontype_type) { + return 1; } } if (jl_is_uniontype(b)) { - if (invariant) - return 0; jl_uniontype_t *u = (jl_uniontype_t*)b; if (type_morespecific_(a, u->a, invariant, env) || type_morespecific_(a, u->b, invariant, env)) - return 1; + return !type_morespecific_(b, a, invariant, env); return 0; } - if (!invariant && (jl_datatype_t*)b == jl_any_type) return 1; + if (!invariant) { + if ((jl_datatype_t*)a == jl_any_type || a == jl_ANY_flag) return 0; + if ((jl_datatype_t*)b == jl_any_type || b == jl_ANY_flag) return 1; + } if (jl_is_datatype(a) && jl_is_datatype(b)) { - if ((jl_datatype_t*)a == jl_any_type) return 0; - jl_datatype_t *tta = (jl_datatype_t*)a; - jl_datatype_t *ttb = (jl_datatype_t*)b; - int super=0; - while (tta != (jl_datatype_t*)jl_any_type) { + jl_datatype_t *tta = (jl_datatype_t*)a, *ttb = (jl_datatype_t*)b; + int super = 0; + while (tta != jl_any_type) { if (tta->name == ttb->name) { - if (super && tta->name != jl_type_typename) - return 1; - if (super && ttb->name == jl_type_typename && jl_is_typevar(jl_tparam0(b))) { - if (type_morespecific_(a, jl_tparam0(b), 1, env)) - return 1; + if (super) { + if (tta->name != jl_type_typename) return 1; + jl_value_t *tp0 = jl_tparam0(b); + if (jl_is_typevar(tp0)) { + if (sub_msp((jl_value_t*)jl_any_type, ((jl_tvar_t*)tp0)->ub, env)) + return 1; + } } assert(jl_nparams(tta) == jl_nparams(ttb)); - int ascore=0, bscore=0, ascore1=0, bscore1=0; - for(i=0; i < jl_nparams(tta); i++) { + int ascore=0, bscore=0, ascore1=0, bscore1=0, adiag=0, bdiag=0; + for(size_t i=0; i < jl_nparams(tta); i++) { jl_value_t *apara = jl_tparam(tta,i); jl_value_t *bpara = jl_tparam(ttb,i); - int ams = type_morespecific_(apara, bpara, 1, env); - ascore += ams; - if (!ams) - bscore += type_morespecific_(bpara, apara, 1, env); + if (type_morespecific_(apara, bpara, 1, env)) + ascore += 1; + else if (type_morespecific_(bpara, apara, 1, env)) + bscore += 1; if (jl_is_typevar(bpara) && !jl_is_typevar(apara) && !jl_is_type(apara)) - ascore1 += 1; - if (jl_is_typevar(apara) && !jl_is_typevar(bpara) && !jl_is_type(bpara)) - bscore1 += 1; + ascore1 = 1; + else if (jl_is_typevar(apara) && !jl_is_typevar(bpara) && !jl_is_type(bpara)) + bscore1 = 1; + if (!adiag && jl_is_typevar(apara)) { + for(int j=i+1; j < jl_nparams(tta); j++) { + if (jl_has_typevar(jl_tparam(tta,j), (jl_tvar_t*)apara)) { + adiag = 1; break; + } + } + } + if (!bdiag && jl_is_typevar(bpara)) { + for(int j=i+1; j < jl_nparams(ttb); j++) { + if (jl_has_typevar(jl_tparam(ttb,j), (jl_tvar_t*)bpara)) { + bdiag = 1; break; + } + } + } } - if (bscore1 == 0 && ascore1 > 0) + if (ascore1 > bscore1) return 1; - if (ascore1 == 0 && bscore1 > 0) + if (bscore1 > ascore1 || bscore > ascore || bdiag > adiag) return 0; - return ascore > bscore; + return ascore > bscore || adiag > bdiag; } else if (invariant) { return 0; @@ -2610,14 +2586,11 @@ static int type_morespecific_(jl_value_t *a, jl_value_t *b, int invariant, jl_ty if (jl_is_typevar(b)) { if (!jl_is_type(a)) return 1; - if (invariant) - return type_morespecific_(a, (jl_value_t*)((jl_tvar_t*)b)->ub, 0, env); - if (!(jl_subtype(a, (jl_value_t*)((jl_tvar_t*)b)->ub) && - jl_subtype((jl_value_t*)((jl_tvar_t*)b)->lb, a))) - return 0; - if (eq_msp(a, b, env)) - return 0; - return 1; + if (invariant) { + if (eq_msp(((jl_tvar_t*)b)->ub, a, env)) + return num_occurs((jl_tvar_t*)b, env) < 2; + } + return type_morespecific_(a, (jl_value_t*)((jl_tvar_t*)b)->ub, 0, env); } return 0; diff --git a/test/choosetests.jl b/test/choosetests.jl index 7974eee36f60e..b8a88c16f2ee5 100644 --- a/test/choosetests.jl +++ b/test/choosetests.jl @@ -35,7 +35,7 @@ function choosetests(choices = []) "enums", "cmdlineargs", "i18n", "workspace", "libdl", "int", "checked", "intset", "floatfuncs", "compile", "distributed", "inline", "boundscheck", "error", "ambiguous", "cartesian", "asmvariant", "osutils", - "channels", "iostream" + "channels", "iostream", "specificity" ] profile_skipped = false if startswith(string(Sys.ARCH), "arm") diff --git a/test/core.jl b/test/core.jl index feaba7256fbef..a75ca32ee8b4c 100644 --- a/test/core.jl +++ b/test/core.jl @@ -20,84 +20,6 @@ f47{T}(x::Vector{Vector{T}}) = 0 @test_throws TypeError (Array{T} where T<:Vararg{Int}) @test_throws TypeError (Array{T} where T<:Vararg{Int,2}) -# issue #8652 -function args_morespecific(a, b) - sp = (ccall(:jl_type_morespecific, Cint, (Any,Any), a, b) != 0) - if sp # make sure morespecific(a,b) implies !morespecific(b,a) - @test ccall(:jl_type_morespecific, Cint, (Any,Any), b, a) == 0 - end - return sp -end -let - a = Tuple{Type{T1}, T1} where T1<:Integer - b2 = Tuple{Type{T2}, Integer} where T2<:Integer - @test args_morespecific(a, b2) - @test !args_morespecific(b2, a) - a = Tuple{Type{T1}, Ptr{T1}} where T1<:Integer - b2 = Tuple{Type{T2}, Ptr{Integer}} where T2<:Integer - @test args_morespecific(a, b2) - @test !args_morespecific(b2, a) -end - -# issue #11534 -let - t1 = Tuple{AbstractArray, Tuple{Vararg{RangeIndex}}} - t2 = Tuple{Array, T} where T<:Tuple{Vararg{RangeIndex}} - @test !args_morespecific(t1, t2) - @test args_morespecific(t2, t1) -end - -let - a = Tuple{Array{T,N}, Vararg{Int,N}} where T where N - b = Tuple{Array,Int} - @test args_morespecific(a, b) - @test !args_morespecific(b, a) - a = Tuple{Array, Vararg{Int,N}} where N - @test !args_morespecific(a, b) - @test args_morespecific(b, a) -end - -# another specificity issue -_z_z_z_(x, y) = 1 -_z_z_z_(::Int, ::Int, ::Vector) = 2 -_z_z_z_(::Int, c...) = 3 -@test _z_z_z_(1, 1, []) == 2 - -@test args_morespecific(Tuple{T,Vararg{T}} where T<:Number, Tuple{Number,Number,Vararg{Number}}) -@test !args_morespecific(Tuple{Number,Number,Vararg{Number}}, Tuple{T,Vararg{T}} where T<:Number) - -@test args_morespecific(Tuple{Array{T} where T<:Union{Float32,Float64,Complex64,Complex128}, Any}, - Tuple{Array{T} where T<:Real, Any}) - -@test args_morespecific(Tuple{1,T} where T, Tuple{Any}) - -# issue #21016 -@test args_morespecific(Tuple{IO, Core.TypeofBottom}, Tuple{IO, Type{T}} where T<:Number) - -# issue #21382 -@test args_morespecific(Tuple{Type{Pair{A,B} where B}} where A, Tuple{DataType}) -@test args_morespecific(Tuple{Union{Int,String},Type{Pair{A,B} where B}} where A, Tuple{Integer,UnionAll}) - -# PR #21750 -let A = Tuple{Any, Tuple{Vararg{Integer,N} where N}}, - B = Tuple{Any, Tuple{Any}}, - C = Tuple{Any, Tuple{}} - @test args_morespecific(A, B) - @test args_morespecific(C, A) - @test args_morespecific(C, B) -end - -# with bound varargs - -_bound_vararg_specificity_1{T,N}(::Type{Array{T,N}}, d::Vararg{Int, N}) = 0 -_bound_vararg_specificity_1{T}(::Type{Array{T,1}}, d::Int) = 1 -@test _bound_vararg_specificity_1(Array{Int,1}, 1) == 1 -@test _bound_vararg_specificity_1(Array{Int,2}, 1, 1) == 0 - -# issue #21710 -@test args_morespecific(Tuple{Array}, Tuple{AbstractVector}) -@test args_morespecific(Tuple{Matrix}, Tuple{AbstractVector}) - # issue #12939 module Issue12939 abstract type Abs; end @@ -728,21 +650,6 @@ let @test ===(g(a),a) end -# Method specificity -begin - local f, A - f{T}(dims::Tuple{}, A::AbstractArray{T,0}) = 1 - f{T,N}(dims::NTuple{N,Int}, A::AbstractArray{T,N}) = 2 - f{T,M,N}(dims::NTuple{M,Int}, A::AbstractArray{T,N}) = 3 - A = zeros(2,2) - @test f((1,2,3), A) == 3 - @test f((1,2), A) == 2 - @test f((), reshape([1])) == 1 - f{T,N}(dims::NTuple{N,Int}, A::AbstractArray{T,N}) = 4 - @test f((1,2), A) == 4 - @test f((1,2,3), A) == 3 -end - # dispatch using Val{T}. See discussion in #9452 for instances vs types let local firstlast @@ -2137,19 +2044,6 @@ let x = Issue2403(20) @test issue2403func(x) == 34 end -# a method specificity issue -c99991{T}(::Type{T},x::T) = 0 -c99991{T}(::Type{UnitRange{T}},x::StepRangeLen{T}) = 1 -c99991{T}(::Type{UnitRange{T}},x::Range{T}) = 2 -@test c99991(UnitRange{Float64}, 1.0:2.0) == 1 -@test c99991(UnitRange{Int}, 1:2) == 2 - -# issue #17016, method specificity involving vararg tuples -T_17016{N} = Tuple{Any,Any,Vararg{Any,N}} -f17016(f, t::T_17016) = 0 -f17016(f, t1::Tuple) = 1 -@test f17016(0, (1,2,3)) == 0 - # issue #8798 let const npy_typestrs = Dict("b1"=>Bool, diff --git a/test/specificity.jl b/test/specificity.jl new file mode 100644 index 0000000000000..10eb731b8000a --- /dev/null +++ b/test/specificity.jl @@ -0,0 +1,144 @@ +function args_morespecific(a, b) + sp = (ccall(:jl_type_morespecific, Cint, (Any,Any), a, b) != 0) + if sp # make sure morespecific(a,b) implies !morespecific(b,a) + @test ccall(:jl_type_morespecific, Cint, (Any,Any), b, a) == 0 + end + return sp +end + +# issue #8652 +let + a = Tuple{Type{T1}, T1} where T1<:Integer + b2 = Tuple{Type{T2}, Integer} where T2<:Integer + @test args_morespecific(a, b2) + @test !args_morespecific(b2, a) + a = Tuple{Type{T1}, Ptr{T1}} where T1<:Integer + b2 = Tuple{Type{T2}, Ptr{Integer}} where T2<:Integer + @test args_morespecific(a, b2) + @test !args_morespecific(b2, a) +end + +# issue #11534 +let + t1 = Tuple{AbstractArray, Tuple{Vararg{RangeIndex}}} + t2 = Tuple{Array, T} where T<:Tuple{Vararg{RangeIndex}} + @test !args_morespecific(t1, t2) + @test args_morespecific(t2, t1) +end + +let + a = Tuple{Array{T,N}, Vararg{Int,N}} where T where N + b = Tuple{Array,Int} + @test args_morespecific(a, b) + @test !args_morespecific(b, a) + a = Tuple{Array, Vararg{Int,N}} where N + @test !args_morespecific(a, b) + @test args_morespecific(b, a) +end + +# another specificity issue +_z_z_z_(x, y) = 1 +_z_z_z_(::Int, ::Int, ::Vector) = 2 +_z_z_z_(::Int, c...) = 3 +@test _z_z_z_(1, 1, []) == 2 + +@test args_morespecific(Tuple{T,Vararg{T}} where T<:Number, Tuple{Number,Number,Vararg{Number}}) +@test !args_morespecific(Tuple{Number,Number,Vararg{Number}}, Tuple{T,Vararg{T}} where T<:Number) + +@test args_morespecific(Tuple{Array{T} where T<:Union{Float32,Float64,Complex64,Complex128}, Any}, + Tuple{Array{T} where T<:Real, Any}) + +@test args_morespecific(Tuple{1,T} where T, Tuple{Any}) +@test args_morespecific(Tuple{T} where T, Tuple{T,T} where T) +@test !args_morespecific(Type{T} where T<:Integer, Type{Any}) + +# issue #21016 +@test args_morespecific(Tuple{IO, Core.TypeofBottom}, Tuple{IO, Type{T}} where T<:Number) + +# issue #21382 +@test args_morespecific(Tuple{Type{Pair{A,B} where B}} where A, Tuple{DataType}) +@test args_morespecific(Tuple{Union{Int,String},Type{Pair{A,B} where B}} where A, Tuple{Integer,UnionAll}) + +# PR #21750 +let A = Tuple{Any, Tuple{Vararg{Integer,N} where N}}, + B = Tuple{Any, Tuple{Any}}, + C = Tuple{Any, Tuple{}} + @test args_morespecific(A, B) + @test args_morespecific(C, A) + @test args_morespecific(C, B) +end + +# with bound varargs +_bound_vararg_specificity_1{T,N}(::Type{Array{T,N}}, d::Vararg{Int, N}) = 0 +_bound_vararg_specificity_1{T}(::Type{Array{T,1}}, d::Int) = 1 +@test _bound_vararg_specificity_1(Array{Int,1}, 1) == 1 +@test _bound_vararg_specificity_1(Array{Int,2}, 1, 1) == 0 + +# issue #21710 +@test args_morespecific(Tuple{Array}, Tuple{AbstractVector}) +@test args_morespecific(Tuple{Matrix}, Tuple{AbstractVector}) + +# Method specificity +begin + local f, A + f{T}(dims::Tuple{}, A::AbstractArray{T,0}) = 1 + f{T,N}(dims::NTuple{N,Int}, A::AbstractArray{T,N}) = 2 + f{T,M,N}(dims::NTuple{M,Int}, A::AbstractArray{T,N}) = 3 + A = zeros(2,2) + @test f((1,2,3), A) == 3 + @test f((1,2), A) == 2 + @test f((), reshape([1])) == 1 + f{T,N}(dims::NTuple{N,Int}, A::AbstractArray{T,N}) = 4 + @test f((1,2), A) == 4 + @test f((1,2,3), A) == 3 +end + +# a method specificity issue +c99991{T}(::Type{T},x::T) = 0 +c99991{T}(::Type{UnitRange{T}},x::StepRangeLen{T}) = 1 +c99991{T}(::Type{UnitRange{T}},x::Range{T}) = 2 +@test c99991(UnitRange{Float64}, 1.0:2.0) == 1 +@test c99991(UnitRange{Int}, 1:2) == 2 + +# issue #17016, method specificity involving vararg tuples +T_17016{N} = Tuple{Any,Any,Vararg{Any,N}} +f17016(f, t::T_17016) = 0 +f17016(f, t1::Tuple) = 1 +@test f17016(0, (1,2,3)) == 0 + +@test !args_morespecific(Tuple{Type{Any}, Any}, Tuple{Type{T}, Any} where T<:VecElement) +@test !args_morespecific((Tuple{Type{T}, Any} where T<:VecElement), Tuple{Type{Any}, Any}) + +@test !args_morespecific(Tuple{Type{T}, Tuple{Any, Vararg{Any, N} where N}} where T<:Tuple{Any, Vararg{Any, N} where N}, + Tuple{Type{Any}, Any}) +@test !args_morespecific(Tuple{Type{T}, Tuple{Any, Vararg{Any, N} where N}} where T<:Tuple{Any, Vararg{Any, N} where N}, + Tuple{Type{Tuple}, Tuple}) +@test !args_morespecific(Tuple{Type{T}, T} where T<:Tuple{Any, Vararg{Any, N} where N}, + Tuple{Type{T}, Any} where T<:VecElement) + +@test args_morespecific(Tuple{Any, Tuple{}, Tuple{}}, Tuple{Any, Tuple{Any}}) +@test args_morespecific(Tuple{Any, Tuple{Any}, Tuple{Any}}, Tuple{Any, Tuple{Any, Any}}) +@test args_morespecific(Tuple{Any, Vararg{Tuple{}, N} where N}, Tuple{Any, Tuple{Any}}) + +@test args_morespecific(Tuple{T, T} where T<:AbstractFloat, Tuple{T, T, T} where T<:AbstractFloat) +@test args_morespecific(Tuple{T, Real, T} where T<:AbstractFloat, Tuple{T, T} where T<:Real) +@test args_morespecific(Tuple{Real, Real}, Tuple{T, T, T} where T <: Real) +@test !args_morespecific(Tuple{Real, Real, Real}, Tuple{T, T, T} where T <: Real) +@test !args_morespecific(Tuple{Real, Real, Vararg{Real}}, Tuple{T, T, T} where T <: Real) +@test args_morespecific(Tuple{Real, Real, Vararg{Int}}, Tuple{T, T, T} where T <: Real) + +@test args_morespecific(Tuple{Type{Base.Nullable{T}}} where T, Tuple{Type{T}, Any} where T) +@test !args_morespecific(Tuple{Type{Base.Nullable{T}}, T} where T, Tuple{Type{Base.Nullable{T}}} where T) + +@test args_morespecific(Tuple{Union{Base.StepRange{T, S} where S, Base.StepRangeLen{T, T, S} where S}, + Union{Base.StepRange{T, S} where S, Base.StepRangeLen{T, T, S} where S}} where T, + Tuple{T, T} where T<:Union{Base.StepRangeLen, Base.LinSpace}) + +@test args_morespecific(Tuple{Type{Tuple}, Any, Any}, + Tuple{Type{Tuple{Vararg{E, N} where N}}, Any, Any} where E) + +@test args_morespecific(Tuple{Type{Tuple{}}, Tuple{}}, + Tuple{Type{T}, T} where T<:Tuple{Any, Vararg{Any, N} where N}) + +@test args_morespecific(Tuple{Type{CartesianIndex{N}}} where N, + Tuple{Type{CartesianIndex{N}},Vararg{Int,N}} where N) From e92eb584b692aabb731a23d0ab43596a4be45d2a Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 1 Jun 2017 13:50:50 -0400 Subject: [PATCH 0996/1534] fix #22164, specificity issue in ForwardDiff --- src/subtype.c | 5 ++--- test/specificity.jl | 9 +++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/subtype.c b/src/subtype.c index bcbf89909dd6e..bab38f4ebf443 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -2576,10 +2576,9 @@ static int type_morespecific_(jl_value_t *a, jl_value_t *b, int invariant, jl_ty if (!jl_is_type(b)) return 0; if (invariant) { - if (num_occurs((jl_tvar_t*)a, env) < 2) - return 0; if (eq_msp(((jl_tvar_t*)a)->ub, b, env)) - return 1; + return num_occurs((jl_tvar_t*)a, env) >= 2; + return 0; } return type_morespecific_((jl_value_t*)((jl_tvar_t*)a)->ub, b, 0, env); } diff --git a/test/specificity.jl b/test/specificity.jl index 10eb731b8000a..501b4a759ff0f 100644 --- a/test/specificity.jl +++ b/test/specificity.jl @@ -142,3 +142,12 @@ f17016(f, t1::Tuple) = 1 @test args_morespecific(Tuple{Type{CartesianIndex{N}}} where N, Tuple{Type{CartesianIndex{N}},Vararg{Int,N}} where N) + +# issue #22164 +let A = Tuple{Type{D},D} where D<:Pair, + B = Tuple{Type{Any}, Any}, + C = Tuple{Type{Pair}, Pair} + @test args_morespecific(C, A) + @test !args_morespecific(A, B) + @test !args_morespecific(C, B) +end From e01b1a7eaeea3cb165995ee2c7d3bdd7f8d61adb Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 29 May 2017 23:35:21 -0400 Subject: [PATCH 0997/1534] improve static_show of unparseable Symbols move static_show tests to test/show.jl --- src/rtutils.c | 17 +++++++++++++++-- test/show.jl | 22 ++++++++++++++++++++++ test/spawn.jl | 8 -------- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/rtutils.c b/src/rtutils.c index b04ad0228a28f..963485a926899 100644 --- a/src/rtutils.c +++ b/src/rtutils.c @@ -493,6 +493,20 @@ struct recur_list { static size_t jl_static_show_x(JL_STREAM *out, jl_value_t *v, struct recur_list *depth); JL_DLLEXPORT int jl_id_start_char(uint32_t wc); +JL_DLLEXPORT int jl_id_char(uint32_t wc); + +JL_DLLEXPORT int jl_is_identifier(char *str) +{ + size_t i = 0; + uint32_t wc = u8_nextchar(str, &i); + if (!jl_id_start_char(wc)) + return 0; + while ((wc = u8_nextchar(str, &i)) != 0) { + if (!jl_id_char(wc)) + return 0; + } + return 1; +} // `v` might be pointing to a field inlined in a structure therefore // `jl_typeof(v)` may not be the same with `vt` and only `vt` should be @@ -717,8 +731,7 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt } else if (vt == jl_sym_type) { char *sn = jl_symbol_name((jl_sym_t*)v); - // TODO check for valid identifier - int quoted = strchr(sn, '/') && strcmp(sn, "/") && strcmp(sn, "//") && strcmp(sn, "//="); + int quoted = !jl_is_identifier(sn) && jl_operator_precedence(sn) == 0; if (quoted) n += jl_printf(out, "Symbol(\""); else diff --git a/test/show.jl b/test/show.jl index ca12dd1c8d336..93018b809c20f 100644 --- a/test/show.jl +++ b/test/show.jl @@ -742,3 +742,25 @@ end @test sprint(Base.show_supertypes, Int64) == "Int64 <: Signed <: Integer <: Real <: Number <: Any" @test sprint(Base.show_supertypes, Vector{String}) == "Array{String,1} <: DenseArray{String,1} <: AbstractArray{String,1} <: Any" + +# static_show + +function static_shown(x) + p = Pipe() + Base.link_pipe(p; julia_only_read=true, julia_only_write=true) + ccall(:jl_static_show, Void, (Ptr{Void}, Any), p.in, x) + @async close(p.in) + return readstring(p.out) +end + +# Test for PR 17803 +@test static_shown(Int128(-1)) == "Int128(0xffffffffffffffffffffffffffffffff)" + +# PR #22160 +@test static_shown(:aa) == ":aa" +@test static_shown(:+) == ":+" +@test static_shown(://) == "://" +@test static_shown(://=) == "://=" +@test static_shown(Symbol("")) == "Symbol(\"\")" +@test static_shown(Symbol("a/b")) == "Symbol(\"a/b\")" +@test static_shown(Symbol("a-b")) == "Symbol(\"a-b\")" diff --git a/test/spawn.jl b/test/spawn.jl index d2bc79820ddf6..1a2bfaffabb8f 100644 --- a/test/spawn.jl +++ b/test/spawn.jl @@ -448,14 +448,6 @@ if is_unix() end end -# Test for PR 17803 -let p=Pipe() - Base.link_pipe(p; julia_only_read=true, julia_only_write=true) - ccall(:jl_static_show, Void, (Ptr{Void}, Any), p.in, Int128(-1)) - @async close(p.in) - @test readstring(p.out) == "Int128(0xffffffffffffffffffffffffffffffff)" -end - # readlines(::Cmd), accidentally broken in #20203 @test sort(readlines(`$lscmd -A`)) == sort(readdir()) From c7b8eb945e21454eefd6b138b520c0d113820a4f Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Mon, 5 Jun 2017 18:58:10 +0200 Subject: [PATCH 0998/1534] deprecate cholfact[!](A, uplo) (#22188) restructure the cholesky test --- NEWS.md | 3 ++ base/deprecated.jl | 8 ++++++ base/linalg/cholesky.jl | 61 +++++++++++++---------------------------- test/linalg/cholesky.jl | 55 ++++++++++++++++++------------------- 4 files changed, 57 insertions(+), 70 deletions(-) diff --git a/NEWS.md b/NEWS.md index 77a721906297f..8b3cd9626662d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -70,6 +70,9 @@ Deprecated or removed * The method `srand(rng, filename, n=4)` has been deprecated ([#21359]). + * The `cholfact`/`cholfact!` methods that accepted an `uplo` symbol have been deprecated + in favor of using `Hermitian` (or `Symmetric`) views ([#22187], [#22188]). + Julia v0.6.0 Release Notes ========================== diff --git a/base/deprecated.jl b/base/deprecated.jl index 580a587609c1b..0038126797536 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1354,6 +1354,14 @@ end @deprecate versioninfo(verbose::Bool) versioninfo(verbose=verbose) @deprecate versioninfo(io::IO, verbose::Bool) versioninfo(io, verbose=verbose) +# PR #22188 +@deprecate cholfact!(A::StridedMatrix, uplo::Symbol, ::Type{Val{false}}) cholfact!(Hermitian(A, uplo), Val{false}) +@deprecate cholfact!(A::StridedMatrix, uplo::Symbol) cholfact!(Hermitian(A, uplo)) +@deprecate cholfact(A::StridedMatrix, uplo::Symbol, ::Type{Val{false}}) cholfact(Hermitian(A, uplo), Val{false}) +@deprecate cholfact(A::StridedMatrix, uplo::Symbol) cholfact(Hermitian(A, uplo)) +@deprecate cholfact!(A::StridedMatrix, uplo::Symbol, ::Type{Val{true}}; tol = 0.0) cholfact!(Hermitian(A, uplo), Val{true}, tol = tol) +@deprecate cholfact(A::StridedMatrix, uplo::Symbol, ::Type{Val{true}}; tol = 0.0) cholfact(Hermitian(A, uplo), Val{true}, tol = tol) + # END 0.7 deprecations # BEGIN 1.0 deprecations diff --git a/base/linalg/cholesky.jl b/base/linalg/cholesky.jl index 2b5c89cad03ef..1e9fa98ea28a8 100644 --- a/base/linalg/cholesky.jl +++ b/base/linalg/cholesky.jl @@ -21,7 +21,7 @@ # The internal structure is as follows # - _chol! returns the factor and info without checking positive definiteness # - chol/chol! returns the factor and checks for positive definiteness -# - cholfact/cholfact! returns Cholesky with checking positive definiteness +# - cholfact/cholfact! returns Cholesky without checking positive definiteness # FixMe? The dispatch below seems overly complicated. One simplification could be to # merge the two Cholesky types into one. It would remove the need for Val completely but @@ -207,8 +207,8 @@ chol(x::Number, args...) = ((C, info) = _chol!(x, nothing); @assertposdef C info # cholfact!. Destructive methods for computing Cholesky factorization of real symmetric # or Hermitian matrix -## No pivoting -function cholfact!(A::RealHermSymComplexHerm, ::Type{Val{false}}) +## No pivoting (default) +function cholfact!(A::RealHermSymComplexHerm, ::Type{Val{false}}=Val{false}) if A.uplo == 'U' CU, info = _chol!(A.data, UpperTriangular) Cholesky(CU.data, 'U', info) @@ -220,7 +220,7 @@ end ### for StridedMatrices, check that matrix is symmetric/Hermitian """ - cholfact!(A, [uplo::Symbol,] Val{false}) -> Cholesky + cholfact!(A, Val{false}) -> Cholesky The same as [`cholfact`](@ref), but saves space by overwriting the input `A`, instead of creating a copy. An [`InexactError`](@ref) exception is thrown if @@ -239,18 +239,9 @@ julia> cholfact!(A) ERROR: InexactError() ``` """ -function cholfact!(A::StridedMatrix, uplo::Symbol, ::Type{Val{false}}) +function cholfact!(A::StridedMatrix, ::Type{Val{false}}=Val{false}) ishermitian(A) || non_hermitian_error("cholfact!") - return cholfact!(Hermitian(A, uplo), Val{false}) -end - -### Default to no pivoting (and storing of upper factor) when not explicit -cholfact!(A::RealHermSymComplexHerm) = cholfact!(A, Val{false}) - -#### for StridedMatrices, check that matrix is symmetric/Hermitian -function cholfact!(A::StridedMatrix, uplo::Symbol = :U) - ishermitian(A) || non_hermitian_error("cholfact!") - return cholfact!(Hermitian(A, uplo)) + return cholfact!(Hermitian(A), Val{false}) end @@ -270,37 +261,34 @@ cholfact!(A::RealHermSymComplexHerm{<:Real}, ::Type{Val{true}}; ### for StridedMatrices, check that matrix is symmetric/Hermitian """ - cholfact!(A, [uplo::Symbol,] Val{true}; tol = 0.0) -> CholeskyPivoted + cholfact!(A, Val{true}; tol = 0.0) -> CholeskyPivoted The same as [`cholfact`](@ref), but saves space by overwriting the input `A`, instead of creating a copy. An [`InexactError`](@ref) exception is thrown if the factorization produces a number not representable by the element type of `A`, e.g. for integer types. """ -function cholfact!(A::StridedMatrix, uplo::Symbol, ::Type{Val{true}}; tol = 0.0) +function cholfact!(A::StridedMatrix, ::Type{Val{true}}; tol = 0.0) ishermitian(A) || non_hermitian_error("cholfact!") - return cholfact!(Hermitian(A, uplo), Val{true}; tol = tol) + return cholfact!(Hermitian(A), Val{true}; tol = tol) end # cholfact. Non-destructive methods for computing Cholesky factorization of real symmetric # or Hermitian matrix -## No pivoting -cholfact(A::RealHermSymComplexHerm{<:Real,<:StridedMatrix}, ::Type{Val{false}}) = - cholfact!(copy_oftype(A, promote_type(typeof(chol(one(eltype(A)))),Float32)), Val{false}) +## No pivoting (default) +cholfact(A::RealHermSymComplexHerm{<:Real,<:StridedMatrix}, ::Type{Val{false}}=Val{false}) = + cholfact!(copy_oftype(A, promote_type(typeof(chol(one(eltype(A)))),Float32))) ### for StridedMatrices, check that matrix is symmetric/Hermitian """ - cholfact(A, [uplo::Symbol,] Val{false}) -> Cholesky + cholfact(A, Val{false}) -> Cholesky Compute the Cholesky factorization of a dense symmetric positive definite matrix `A` and return a `Cholesky` factorization. The matrix `A` can either be a [`Symmetric`](@ref) or [`Hermitian`](@ref) -`StridedMatrix` or a *perfectly* symmetric or Hermitian `StridedMatrix`. In the latter case, -the optional argument `uplo` may be `:L` for using the lower part or `:U` for the upper part of `A`. -The default is to use `:U`. +`StridedMatrix` or a *perfectly* symmetric or Hermitian `StridedMatrix`. The triangular Cholesky factor can be obtained from the factorization `F` with: `F[:L]` and `F[:U]`. The following functions are available for `Cholesky` objects: [`size`](@ref), [`\\`](@ref), [`inv`](@ref), and [`det`](@ref). -A `PosDefException` exception is thrown in case the matrix is not positive definite. # Example @@ -331,18 +319,9 @@ julia> C[:L] * C[:U] == A true ``` """ -function cholfact(A::StridedMatrix, uplo::Symbol, ::Type{Val{false}}) - ishermitian(A) || non_hermitian_error("cholfact") - return cholfact(Hermitian(A, uplo), Val{false}) -end - -### Default to no pivoting (and storing of upper factor) when not explicit -cholfact(A::RealHermSymComplexHerm{<:Real,<:StridedMatrix}) = cholfact(A, Val{false}) - -#### for StridedMatrices, check that matrix is symmetric/Hermitian -function cholfact(A::StridedMatrix, uplo::Symbol = :U) +function cholfact(A::StridedMatrix, ::Type{Val{false}}=Val{false}) ishermitian(A) || non_hermitian_error("cholfact") - return cholfact(Hermitian(A, uplo)) + return cholfact(Hermitian(A)) end @@ -353,22 +332,20 @@ cholfact(A::RealHermSymComplexHerm{<:Real,<:StridedMatrix}, ::Type{Val{true}}; t ### for StridedMatrices, check that matrix is symmetric/Hermitian """ - cholfact(A, [uplo::Symbol,] Val{true}; tol = 0.0) -> CholeskyPivoted + cholfact(A, Val{true}; tol = 0.0) -> CholeskyPivoted Compute the pivoted Cholesky factorization of a dense symmetric positive semi-definite matrix `A` and return a `CholeskyPivoted` factorization. The matrix `A` can either be a [`Symmetric`](@ref) or [`Hermitian`](@ref) `StridedMatrix` or a *perfectly* symmetric or Hermitian `StridedMatrix`. -In the latter case, the optional argument `uplo` may be `:L` for using the lower part or `:U` -for the upper part of `A`. The default is to use `:U`. The triangular Cholesky factor can be obtained from the factorization `F` with: `F[:L]` and `F[:U]`. The following functions are available for `PivotedCholesky` objects: [`size`](@ref), [`\\`](@ref), [`inv`](@ref), [`det`](@ref), and [`rank`](@ref). The argument `tol` determines the tolerance for determining the rank. For negative values, the tolerance is the machine precision. """ -function cholfact(A::StridedMatrix, uplo::Symbol, ::Type{Val{true}}; tol = 0.0) +function cholfact(A::StridedMatrix, ::Type{Val{true}}; tol = 0.0) ishermitian(A) || non_hermitian_error("cholfact") - return cholfact(Hermitian(A, uplo), Val{true}; tol = tol) + return cholfact(Hermitian(A), Val{true}; tol = tol) end ## Number diff --git a/test/linalg/cholesky.jl b/test/linalg/cholesky.jl index 0364b4bfb9fa2..531f19ee15230 100644 --- a/test/linalg/cholesky.jl +++ b/test/linalg/cholesky.jl @@ -23,14 +23,11 @@ using Base.LinAlg: BlasComplex, BlasFloat, BlasReal, QRPivoted, PosDefException for eltya in (Float32, Float64, Complex64, Complex128, BigFloat, Int) a = eltya == Int ? rand(1:7, n, n) : convert(Matrix{eltya}, eltya <: Complex ? complex.(areal, aimg) : areal) a2 = eltya == Int ? rand(1:7, n, n) : convert(Matrix{eltya}, eltya <: Complex ? complex.(a2real, a2img) : a2real) - apd = a'*a # symmetric positive-definite - apds = Symmetric(apd) - apdsL = Symmetric(apd, :L) - apdh = Hermitian(apd) - apdhL = Hermitian(apd, :L) ε = εa = eps(abs(float(one(eltya)))) + # Test of symmetric pos. def. strided matrix + apd = a'*a @inferred cholfact(apd) @inferred chol(apd) capd = factorize(apd) @@ -61,6 +58,11 @@ using Base.LinAlg: BlasComplex, BlasFloat, BlasReal, QRPivoted, PosDefException @test all(x -> x ≈ √apos, cholfact(apos).factors) @test_throws PosDefException chol(-one(eltya)) + # Test cholfact with Symmetric/Hermitian upper/lower + apds = Symmetric(apd) + apdsL = Symmetric(apd, :L) + apdh = Hermitian(apd) + apdhL = Hermitian(apd, :L) if eltya <: Real capds = cholfact(apds) @test inv(capds)*apds ≈ eye(n) @@ -82,9 +84,6 @@ using Base.LinAlg: BlasComplex, BlasFloat, BlasReal, QRPivoted, PosDefException capdh = cholfact!(copy(apd)) @test inv(capdh)*apdh ≈ eye(n) @test abs((det(capdh) - det(apd))/det(capdh)) <= ε*κ*n - capdh = cholfact!(copy(apd), :L) - @test inv(capdh)*apdh ≈ eye(n) - @test abs((det(capdh) - det(apd))/det(capdh)) <= ε*κ*n ulstring = sprint(show,capdh[:UL]) @test sprint(show,capdh) == "$(typeof(capdh)) with factor:\n$ulstring" end @@ -94,18 +93,13 @@ using Base.LinAlg: BlasComplex, BlasFloat, BlasReal, QRPivoted, PosDefException U = Bidiagonal([2,sqrt(eltya(3))],[-1],true) / sqrt(eltya(2)) @test full(chol(S)) ≈ full(U) - #lower Cholesky factor - lapd = cholfact(apd, :L) - @test full(lapd) ≈ apd - l = lapd[:L] - @test l*l' ≈ apd - @test triu(capd.factors) ≈ lapd[:U] - @test tril(lapd.factors) ≈ capd[:L] + # test extraction of factor and re-creating original matrix if eltya <: Real capds = cholfact(apds) lapds = cholfact(apdsL) cl = chol(apdsL) ls = lapds[:L] + @test full(capds) ≈ full(lapds) ≈ apd @test ls*ls' ≈ apd @test triu(capds.factors) ≈ lapds[:U] @test tril(lapds.factors) ≈ capds[:L] @@ -117,6 +111,7 @@ using Base.LinAlg: BlasComplex, BlasFloat, BlasReal, QRPivoted, PosDefException lapdh = cholfact(apdhL) cl = chol(apdhL) ls = lapdh[:L] + @test full(capdh) ≈ full(lapdh) ≈ apd @test ls*ls' ≈ apd @test triu(capdh.factors) ≈ lapdh[:U] @test tril(lapdh.factors) ≈ capdh[:L] @@ -127,9 +122,9 @@ using Base.LinAlg: BlasComplex, BlasFloat, BlasReal, QRPivoted, PosDefException #pivoted upper Cholesky if eltya != BigFloat - cz = cholfact(zeros(eltya,n,n), :U, Val{true}) + cz = cholfact(Hermitian(zeros(eltya,n,n)), Val{true}) @test_throws Base.LinAlg.RankDeficientException Base.LinAlg.chkfullrank(cz) - cpapd = cholfact(apd, :U, Val{true}) + cpapd = cholfact(apdh, Val{true}) @test rank(cpapd) == n @test all(diff(diag(real(cpapd.factors))).<=0.) # diagonal should be non-increasing if isreal(apd) @@ -162,17 +157,19 @@ using Base.LinAlg: BlasComplex, BlasFloat, BlasReal, QRPivoted, PosDefException @test norm(a*(capd\(a'*b)) - b,1)/norm(b,1) <= ε*κ*n # Ad hoc, revisit if eltya != BigFloat && eltyb != BigFloat + lapd = cholfact(apdhL) @test norm(apd * (lapd\b) - b)/norm(b) <= ε*κ*n @test norm(apd * (lapd\b[1:n]) - b[1:n])/norm(b[1:n]) <= ε*κ*n end - @test_throws DimensionMismatch lapd\RowVector(ones(n)) + @test_throws DimensionMismatch cholfact(apdhL)\RowVector(ones(n)) if eltya != BigFloat && eltyb != BigFloat # Note! Need to implement pivoted Cholesky decomposition in julia + cpapd = cholfact(apdh, Val{true}) @test norm(apd * (cpapd\b) - b)/norm(b) <= ε*κ*n # Ad hoc, revisit @test norm(apd * (cpapd\b[1:n]) - b[1:n])/norm(b[1:n]) <= ε*κ*n - lpapd = cholfact(apd, :L, Val{true}) + lpapd = cholfact(apdhL, Val{true}) @test norm(apd * (lpapd\b) - b)/norm(b) <= ε*κ*n # Ad hoc, revisit @test norm(apd * (lpapd\b[1:n]) - b[1:n])/norm(b[1:n]) <= ε*κ*n @@ -214,8 +211,8 @@ end AcA = A'A BcB = AcA + v*v' BcB = (BcB + BcB')/2 - F = cholfact(AcA, uplo) - G = cholfact(BcB, uplo) + F = cholfact(Hermitian(AcA, uplo)) + G = cholfact(Hermitian(BcB, uplo)) @test LinAlg.lowrankupdate(F, v)[uplo] ≈ G[uplo] @test_throws DimensionMismatch LinAlg.lowrankupdate(F, ones(eltype(v), length(v)+1)) @test LinAlg.lowrankdowndate(G, v)[uplo] ≈ F[uplo] @@ -244,7 +241,7 @@ end 0.25336108035924787 + 0.975317836492159im 0.0628393808469436 - 0.1253397353973715im 0.11192755545114 - 0.1603741874112385im 0.8439562576196216 + 1.0850814110398734im -1.0568488936791578 - 0.06025820467086475im 0.12696236014017806 - 0.09853584666755086im] - cholfact(apd, :L, Val{true}) \ b + cholfact(Hermitian(apd, :L), Val{true}) \ b r = factorize(apd)[:U] E = abs.(apd - r'*r) ε = eps(abs(float(one(Complex64)))) @@ -255,12 +252,14 @@ end end @testset "throw if non-Hermitian" begin - @test_throws ArgumentError cholfact(randn(5,5)) - @test_throws ArgumentError cholfact(complex.(randn(5,5), randn(5,5))) - @test_throws ArgumentError Base.LinAlg.chol!(randn(5,5)) - @test_throws ArgumentError Base.LinAlg.cholfact!(randn(5,5),:U,Val{false}) - @test_throws ArgumentError Base.LinAlg.cholfact!(randn(5,5),:U,Val{true}) - @test_throws ArgumentError cholfact(randn(5,5),:U,Val{false}) + R = randn(5, 5) + C = complex.(R, R) + for A in (R, C) + @test_throws ArgumentError cholfact(A) + @test_throws ArgumentError cholfact!(copy(A)) + @test_throws ArgumentError chol(A) + @test_throws ArgumentError Base.LinAlg.chol!(copy(A)) + end end @testset "fail for non-BLAS element types" begin From abf3bce8ba7ab7d76e654164481dc6a926046859 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Mon, 5 Jun 2017 12:13:08 -0500 Subject: [PATCH 0999/1534] Fix DomainError when parsing DateTime (#22198) * Fix DomainError when parsing DateTime * Converted tests into a testset --- base/dates/io.jl | 10 +++++++++- test/dates/io.jl | 13 +++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/base/dates/io.jl b/base/dates/io.jl index 7274425c1444d..f5eb0fed26fc2 100644 --- a/base/dates/io.jl +++ b/base/dates/io.jl @@ -111,7 +111,15 @@ end @inline function tryparsenext(d::DatePart{'s'}, str, i, len) ms, ii = tryparsenext_base10(str, i, len, min_width(d), max_width(d)) if !isnull(ms) - ms = Nullable{Int64}(get(ms) * 10 ^ (3 - (ii - i))) + val = get(ms) + len = ii - i + if len > 3 + val, r = divrem(val, Int64(10) ^ (len - 3)) + r == 0 || throw(InexactError()) + else + val *= Int64(10) ^ (3 - len) + end + ms = Nullable{Int64}(val) end return ms, ii end diff --git a/test/dates/io.jl b/test/dates/io.jl index 79961249dd844..b5090eef1086a 100644 --- a/test/dates/io.jl +++ b/test/dates/io.jl @@ -432,3 +432,16 @@ end # Issue #21504 @test isnull(tryparse(Dates.Date, "0-1000")) + +# Issue #22100 +@testset "parse milliseconds" begin + @test Dates.DateTime("2017-Mar-17 00:00:00.0000", "y-u-d H:M:S.s") == Dates.DateTime(2017, 3, 17) + @test Dates.parse_components(".1", Dates.DateFormat(".s")) == [Dates.Millisecond(100)] + @test Dates.parse_components(".12", Dates.DateFormat(".s")) == [Dates.Millisecond(120)] + @test Dates.parse_components(".123", Dates.DateFormat(".s")) == [Dates.Millisecond(123)] + @test Dates.parse_components(".1230", Dates.DateFormat(".s")) == [Dates.Millisecond(123)] + @test_throws InexactError Dates.parse_components(".1234", Dates.DateFormat(".s")) + + # Ensure that no overflow occurs when using Int32 literals: Int32(10)^10 + @test Dates.parse_components("." * rpad(999, 10, '0'), Dates.DateFormat(".s")) == [Dates.Millisecond(999)] +end From d31875307d9b8c3d3f6d76c47b7f93e10b55a74c Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Mon, 5 Jun 2017 19:49:39 +0200 Subject: [PATCH 1000/1534] use where syntax in most remaining files (#22211) --- base/abstractarray.jl | 4 +-- base/associative.jl | 2 +- base/atomics.jl | 20 +++++------ base/char.jl | 2 +- base/datafmt.jl | 10 +++--- base/dates/io.jl | 2 +- base/dates/periods.jl | 8 ++--- base/dict.jl | 2 +- base/distributed/remotecall.jl | 2 +- base/distributed/workerpool.jl | 2 +- base/docs/Docs.jl | 4 +-- base/env.jl | 2 +- base/essentials.jl | 2 +- base/fastmath.jl | 6 ++-- base/fft/FFTW.jl | 8 ++--- base/gmp.jl | 2 +- base/grisu/float.jl | 2 +- base/io.jl | 9 ++--- base/iostream.jl | 2 +- base/iterators.jl | 4 +-- base/libgit2/reference.jl | 2 +- base/libgit2/types.jl | 6 ++-- base/linalg/bitarray.jl | 2 +- base/linalg/bunchkaufman.jl | 4 +-- base/linalg/cholesky.jl | 8 ++--- base/linalg/factorization.jl | 2 +- base/linalg/generic.jl | 4 +-- base/linalg/givens.jl | 2 +- base/linalg/lq.jl | 2 +- base/linalg/qr.jl | 2 +- base/linalg/rowvector.jl | 2 +- base/linalg/schur.jl | 2 +- base/linalg/special.jl | 6 ++-- base/linalg/svd.jl | 2 +- base/markdown/render/html.jl | 2 +- base/markdown/render/latex.jl | 2 +- base/markdown/render/rst.jl | 2 +- base/markdown/render/terminal/render.jl | 2 +- base/mpfr.jl | 2 +- base/multidimensional.jl | 14 ++++---- base/multinverses.jl | 2 +- base/nullable.jl | 2 +- base/operators.jl | 16 ++++----- base/pair.jl | 2 +- base/pkg/resolve/versionweight.jl | 2 +- base/process.jl | 2 +- base/promotion.jl | 6 ++-- base/random.jl | 40 +++++++++++----------- base/range.jl | 32 +++++++++--------- base/reducedim.jl | 2 +- base/reshapedarray.jl | 2 +- base/set.jl | 2 +- base/socket.jl | 2 +- base/sparse/cholmod.jl | 18 +++++----- base/sparse/linalg.jl | 4 +-- base/sparse/sparsematrix.jl | 43 +++++++++++++----------- base/sparse/sparsevector.jl | 2 +- base/sparse/umfpack.jl | 22 ++++++------ base/special/trig.jl | 4 +-- base/statistics.jl | 2 +- base/twiceprecision.jl | 2 +- base/util.jl | 2 +- base/weakkeydict.jl | 10 +++--- doc/src/devdocs/functions.md | 2 +- doc/src/manual/interacting-with-julia.md | 4 +-- doc/src/manual/performance-tips.md | 2 +- doc/src/stdlib/sort.md | 2 +- 67 files changed, 202 insertions(+), 194 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index af3bfe47825dd..bc440caab8b09 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -870,7 +870,7 @@ end # to transform the indices such that we can call the only getindex method that # we require the type A{T,N} <: AbstractArray{T,N} to define; either: # getindex(::A, ::Int) # if IndexStyle(A) == IndexLinear() OR -# getindex{T,N}(::A{T,N}, ::Vararg{Int, N}) # if IndexCartesian() +# getindex(::A{T,N}, ::Vararg{Int, N}) where {T,N} # if IndexCartesian() # If the subtype hasn't defined the required method, it falls back to the # _getindex function again where an error is thrown to prevent stack overflows. @@ -1192,7 +1192,7 @@ end _cs(d, a, b) = (a == b ? a : throw(DimensionMismatch( "mismatch in dimension $d (expected $a got $b)"))) -dims2cat{n}(::Type{Val{n}}) = ntuple(i -> (i == n), Val{n}) +dims2cat(::Type{Val{n}}) where {n} = ntuple(i -> (i == n), Val{n}) dims2cat(dims) = ntuple(i -> (i in dims), maximum(dims)) cat(dims, X...) = cat_t(dims, promote_eltypeof(X...), X...) diff --git a/base/associative.jl b/base/associative.jl index 74f3fdd47a9f4..9ad7a431bb8ed 100644 --- a/base/associative.jl +++ b/base/associative.jl @@ -218,7 +218,7 @@ String ``` """ valtype(::Type{Associative{K,V}}) where {K,V} = V -valtype{A<:Associative}(::Type{A}) = valtype(supertype(A)) +valtype(::Type{A}) where {A<:Associative} = valtype(supertype(A)) valtype(a::Associative) = valtype(typeof(a)) """ diff --git a/base/atomics.jl b/base/atomics.jl index a2dfbef623b31..f44edbeb75527 100644 --- a/base/atomics.jl +++ b/base/atomics.jl @@ -70,7 +70,7 @@ end Atomic() = Atomic{Int}() """ - Threads.atomic_cas!{T}(x::Atomic{T}, cmp::T, newval::T) + Threads.atomic_cas!(x::Atomic{T}, cmp::T, newval::T) where T Atomically compare-and-set `x` @@ -104,7 +104,7 @@ Base.Threads.Atomic{Int64}(2) function atomic_cas! end """ - Threads.atomic_xchg!{T}(x::Atomic{T}, newval::T) + Threads.atomic_xchg!(x::Atomic{T}, newval::T) where T Atomically exchange the value in `x` @@ -127,7 +127,7 @@ julia> x[] function atomic_xchg! end """ - Threads.atomic_add!{T}(x::Atomic{T}, val::T) + Threads.atomic_add!(x::Atomic{T}, val::T) where T Atomically add `val` to `x` @@ -149,7 +149,7 @@ julia> x[] function atomic_add! end """ - Threads.atomic_sub!{T}(x::Atomic{T}, val::T) + Threads.atomic_sub!(x::Atomic{T}, val::T) where T Atomically subtract `val` from `x` @@ -171,7 +171,7 @@ julia> x[] function atomic_sub! end """ - Threads.atomic_and!{T}(x::Atomic{T}, val::T) + Threads.atomic_and!(x::Atomic{T}, val::T) where T Atomically bitwise-and `x` with `val` @@ -193,7 +193,7 @@ julia> x[] function atomic_and! end """ - Threads.atomic_nand!{T}(x::Atomic{T}, val::T) + Threads.atomic_nand!(x::Atomic{T}, val::T) where T Atomically bitwise-nand (not-and) `x` with `val` @@ -215,7 +215,7 @@ julia> x[] function atomic_nand! end """ - Threads.atomic_or!{T}(x::Atomic{T}, val::T) + Threads.atomic_or!(x::Atomic{T}, val::T) where T Atomically bitwise-or `x` with `val` @@ -237,7 +237,7 @@ julia> x[] function atomic_or! end """ - Threads.atomic_xor!{T}(x::Atomic{T}, val::T) + Threads.atomic_xor!(x::Atomic{T}, val::T) where T Atomically bitwise-xor (exclusive-or) `x` with `val` @@ -259,7 +259,7 @@ julia> x[] function atomic_xor! end """ - Threads.atomic_max!{T}(x::Atomic{T}, val::T) + Threads.atomic_max!(x::Atomic{T}, val::T) where T Atomically store the maximum of `x` and `val` in `x` @@ -281,7 +281,7 @@ julia> x[] function atomic_max! end """ - Threads.atomic_min!{T}(x::Atomic{T}, val::T) + Threads.atomic_min!(x::Atomic{T}, val::T) where T Atomically store the minimum of `x` and `val` in `x` diff --git a/base/char.jl b/base/char.jl index 6add31b91019a..ea7334eb0679e 100644 --- a/base/char.jl +++ b/base/char.jl @@ -5,7 +5,7 @@ convert(::Type{Char}, x::Number) = Char(UInt32(x)) convert(::Type{UInt32}, x::Char) = reinterpret(UInt32, x) convert(::Type{T}, x::Char) where {T<:Number} = convert(T, UInt32(x)) -rem{T<:Number}(x::Char, ::Type{T}) = rem(UInt32(x), T) +rem(x::Char, ::Type{T}) where {T<:Number} = rem(UInt32(x), T) typemax(::Type{Char}) = reinterpret(Char, typemax(UInt32)) typemin(::Type{Char}) = reinterpret(Char, typemin(UInt32)) diff --git a/base/datafmt.jl b/base/datafmt.jl index 9253c4bf236d4..e3d8867a4b649 100644 --- a/base/datafmt.jl +++ b/base/datafmt.jl @@ -208,8 +208,8 @@ mutable struct DLMStore{T} <: DLMHandler eol::Char end -function DLMStore{T}(::Type{T}, dims::NTuple{2,Integer}, - has_header::Bool, sbuff::String, auto::Bool, eol::Char) +function DLMStore(::Type{T}, dims::NTuple{2,Integer}, + has_header::Bool, sbuff::String, auto::Bool, eol::Char) where T (nrows,ncols) = dims nrows <= 0 && throw(ArgumentError("number of rows in dims must be > 0, got $nrows")) ncols <= 0 && throw(ArgumentError("number of columns in dims must be > 0, got $ncols")) @@ -223,7 +223,7 @@ _chrinstr(sbuff::String, chr::UInt8, startpos::Int, endpos::Int) = (Ptr{UInt8}, Int32, Csize_t), pointer(sbuff)+startpos-1, chr, endpos-startpos+1)) function store_cell(dlmstore::DLMStore{T}, row::Int, col::Int, - quoted::Bool, startpos::Int, endpos::Int) where T + quoted::Bool, startpos::Int, endpos::Int) where T drow = row - dlmstore.hdr_offset ncols = dlmstore.ncols @@ -408,7 +408,7 @@ function colval(sbuff::String, startpos::Int, endpos::Int, cells::Array{Bool,2}, isnull(n) || (cells[row, col] = get(n)) isnull(n) end -function colval{T<:Integer}(sbuff::String, startpos::Int, endpos::Int, cells::Array{T,2}, row::Int, col::Int) +function colval(sbuff::String, startpos::Int, endpos::Int, cells::Array{T,2}, row::Int, col::Int) where T<:Integer n = tryparse_internal(T, sbuff, startpos, endpos, 0, false) isnull(n) || (cells[row, col] = get(n)) isnull(n) @@ -620,7 +620,7 @@ readcsv(io, T::Type; opts...) = readdlm(io, ',', T; opts...) # todo: keyword argument for # of digits to print writedlm_cell(io::IO, elt::AbstractFloat, dlm, quotes) = print_shortest(io, elt) -function writedlm_cell{T}(io::IO, elt::AbstractString, dlm::T, quotes::Bool) +function writedlm_cell(io::IO, elt::AbstractString, dlm::T, quotes::Bool) where T if quotes && !isempty(elt) && (('"' in elt) || ('\n' in elt) || ((T <: Char) ? (dlm in elt) : contains(elt, dlm))) print(io, '"', replace(elt, r"\"", "\"\""), '"') else diff --git a/base/dates/io.jl b/base/dates/io.jl index f5eb0fed26fc2..b31e28c35fd33 100644 --- a/base/dates/io.jl +++ b/base/dates/io.jl @@ -439,7 +439,7 @@ Parse a date from a date string `dt` using a `DateFormat` object `df`. """ Date(dt::AbstractString,df::DateFormat=ISODateFormat) = parse(Date, dt, df) -@generated function format{S, T}(io::IO, dt::TimeType, fmt::DateFormat{S, T}) +@generated function format(io::IO, dt::TimeType, fmt::DateFormat{<:Any,T}) where T N = nfields(T) quote ts = fmt.tokens diff --git a/base/dates/periods.jl b/base/dates/periods.jl index b34517e3734c0..76754a4e67d10 100644 --- a/base/dates/periods.jl +++ b/base/dates/periods.jl @@ -89,7 +89,7 @@ end for (op, Ty, Tz) in ((:*, Real, :P), (:/, :P, Float64), (:/, Real, :P)) @eval begin - function ($op){P<:Period}(X::StridedArray{P}, y::$Ty) + function ($op)(X::StridedArray{P}, y::$Ty) where P<:Period Z = similar(X, $Tz) for (Idst, Isrc) in zip(eachindex(Z), eachindex(X)) @inbounds Z[Idst] = ($op)(X[Isrc], y) @@ -100,8 +100,8 @@ for (op, Ty, Tz) in ((:*, Real, :P), end # intfuncs -Base.gcdx{T<:Period}(a::T, b::T) = ((g, x, y) = gcdx(value(a), value(b)); return T(g), x, y) -Base.abs{T<:Period}(a::T) = T(abs(value(a))) +Base.gcdx(a::T, b::T) where {T<:Period} = ((g, x, y) = gcdx(value(a), value(b)); return T(g), x, y) +Base.abs(a::T) where {T<:Period} = T(abs(value(a))) periodisless(::Period,::Year) = true periodisless(::Period,::Month) = true @@ -136,7 +136,7 @@ periodisless(::Nanosecond,::Microsecond) = true periodisless(::Period,::Nanosecond) = false # return (next coarser period, conversion factor): -coarserperiod{P<:Period}(::Type{P}) = (P, 1) +coarserperiod(::Type{P}) where {P<:Period} = (P, 1) coarserperiod(::Type{Nanosecond}) = (Microsecond, 1000) coarserperiod(::Type{Microsecond}) = (Millisecond, 1000) coarserperiod(::Type{Millisecond}) = (Second, 1000) diff --git a/base/dict.jl b/base/dict.jl index 493340836405c..a1f98b92dd38f 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -680,5 +680,5 @@ function similar(t::ImmutableDict) return t end -_similar_for{P<:Pair}(c::Dict, ::Type{P}, itr, isz) = similar(c, P) +_similar_for(c::Dict, ::Type{P}, itr, isz) where {P<:Pair} = similar(c, P) _similar_for(c::Associative, T, itr, isz) = throw(ArgumentError("for Associatives, similar requires an element type of Pair;\n if calling map, consider a comprehension instead")) diff --git a/base/distributed/remotecall.jl b/base/distributed/remotecall.jl index ff1de61be8222..d621f9ada0654 100644 --- a/base/distributed/remotecall.jl +++ b/base/distributed/remotecall.jl @@ -271,7 +271,7 @@ function send_add_client(rr::AbstractRemoteRef, i) end end -channel_type{T}(rr::RemoteChannel{T}) = T +channel_type(rr::RemoteChannel{T}) where {T} = T serialize(s::AbstractSerializer, f::Future) = serialize(s, f, isnull(f.v)) serialize(s::AbstractSerializer, rr::RemoteChannel) = serialize(s, rr, true) diff --git a/base/distributed/workerpool.jl b/base/distributed/workerpool.jl index 72a4d52ab5f4b..2abee54e57ac8 100644 --- a/base/distributed/workerpool.jl +++ b/base/distributed/workerpool.jl @@ -52,7 +52,7 @@ function serialize(S::AbstractSerializer, pool::WorkerPool) serialize(S, pool.ref) end -deserialize{T<:WorkerPool}(S::AbstractSerializer, t::Type{T}) = T(deserialize(S)) +deserialize(S::AbstractSerializer, t::Type{T}) where {T<:WorkerPool} = T(deserialize(S)) wp_local_push!(pool::AbstractWorkerPool, w::Int) = (push!(pool.workers, w); put!(pool.channel, w); pool) wp_local_length(pool::AbstractWorkerPool) = length(pool.workers) diff --git a/base/docs/Docs.jl b/base/docs/Docs.jl index bd9af3efe71d7..742635d2386b4 100644 --- a/base/docs/Docs.jl +++ b/base/docs/Docs.jl @@ -206,7 +206,7 @@ by a `Union` of `Tuple` types. For example the following `Method` definition is stored as `Tuple{Any, Any}` in the `MultiDoc` while - f{T}(x::T, y = ?) = ... + f(x::T, y = ?) where {T} = ... is stored as `Union{Tuple{T, Any}, Tuple{T}} where T`. @@ -426,7 +426,7 @@ function summarize(io::IO, m::Module, binding) end end -function summarize{T}(io::IO, ::T, binding) +function summarize(io::IO, ::T, binding) where T println(io, "`", binding, "` is of type `", T, "`.\n") summarize(io, T, binding) end diff --git a/base/env.jl b/base/env.jl index 485987f1afddc..254f8633f6eef 100644 --- a/base/env.jl +++ b/base/env.jl @@ -148,7 +148,7 @@ by zero or more `"var"=>val` arguments `kv`. `withenv` is generally used via the environment variable (if it is set). When `withenv` returns, the original environment has been restored. """ -function withenv{T<:AbstractString}(f::Function, keyvals::Pair{T}...) +function withenv(f::Function, keyvals::Pair{T}...) where T<:AbstractString old = Dict{T,Any}() for (key,val) in keyvals old[key] = get(ENV,key,nothing) diff --git a/base/essentials.jl b/base/essentials.jl index 6e06e23302d1d..73bccc405f956 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -76,7 +76,7 @@ function tuple_type_tail(T::DataType) end tuple_type_cons(::Type, ::Type{Union{}}) = Union{} -function tuple_type_cons{S,T<:Tuple}(::Type{S}, ::Type{T}) +function tuple_type_cons(::Type{S}, ::Type{T}) where T<:Tuple where S @_pure_meta Tuple{S, T.parameters...} end diff --git a/base/fastmath.jl b/base/fastmath.jl index a66762c2eb6bb..4d55d3f7cd348 100644 --- a/base/fastmath.jl +++ b/base/fastmath.jl @@ -141,9 +141,9 @@ mul_fast(x::T, y::T) where {T<:FloatTypes} = mul_float_fast(x, y) div_fast(x::T, y::T) where {T<:FloatTypes} = div_float_fast(x, y) rem_fast(x::T, y::T) where {T<:FloatTypes} = rem_float_fast(x, y) -add_fast{T<:FloatTypes}(x::T, y::T, zs::T...) = +add_fast(x::T, y::T, zs::T...) where {T<:FloatTypes} = add_fast(add_fast(x, y), zs...) -mul_fast{T<:FloatTypes}(x::T, y::T, zs::T...) = +mul_fast(x::T, y::T, zs::T...) where {T<:FloatTypes} = mul_fast(mul_fast(x, y), zs...) @fastmath begin @@ -208,7 +208,7 @@ ComplexTypes = Union{Complex64, Complex128} eq_fast(a::T, y::Complex{T}) where {T<:FloatTypes} = (a==real(y)) & (T(0)==imag(y)) - ne_fast{T<:ComplexTypes}(x::T, y::T) = !(x==y) + ne_fast(x::T, y::T) where {T<:ComplexTypes} = !(x==y) end # fall-back implementations and type promotion diff --git a/base/fft/FFTW.jl b/base/fft/FFTW.jl index 4ef2f701e0c78..50cf8556b708d 100644 --- a/base/fft/FFTW.jl +++ b/base/fft/FFTW.jl @@ -76,8 +76,8 @@ size(a::FakeArray) = a.sz strides(a::FakeArray) = a.st unsafe_convert(::Type{Ptr{T}}, a::FakeArray{T}) where {T} = convert(Ptr{T}, C_NULL) pointer(a::FakeArray{T}) where {T} = convert(Ptr{T}, C_NULL) -FakeArray{T,N}(::Type{T}, sz::NTuple{N,Int}) = FakeArray{T,N}(sz, colmajorstrides(sz)) -FakeArray{T}(::Type{T}, sz::Int...) = FakeArray(T, sz) +FakeArray(::Type{T}, sz::NTuple{N,Int}) where {T,N} = FakeArray{T,N}(sz, colmajorstrides(sz)) +FakeArray(::Type{T}, sz::Int...) where {T} = FakeArray(T, sz) fakesimilar(flags, X, T) = flags & ESTIMATE != 0 ? FakeArray(T, size(X)) : Array{T}(size(X)) alignment_of(A::FakeArray) = Int32(0) @@ -194,9 +194,9 @@ if Base.libfftw_name == "libmkl_rt" alignment_of(A::StridedArray{<:fftwSingle}) = convert(Int32, convert(Int64, pointer(A)) % 16) else - alignment_of{T<:fftwDouble}(A::StridedArray{T}) = + alignment_of(A::StridedArray{T}) where {T<:fftwDouble} = ccall((:fftw_alignment_of, libfftw), Int32, (Ptr{T},), A) - alignment_of{T<:fftwSingle}(A::StridedArray{T}) = + alignment_of(A::StridedArray{T}) where {T<:fftwSingle} = ccall((:fftwf_alignment_of, libfftwf), Int32, (Ptr{T},), A) end diff --git a/base/gmp.jl b/base/gmp.jl index f44be43fd568e..54eee8340a590 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -305,7 +305,7 @@ end rem(x::BigInt, ::Type{Bool}) = ((x&1)!=0) -function rem{T<:Union{Unsigned,Signed}}(x::BigInt, ::Type{T}) +function rem(x::BigInt, ::Type{T}) where T<:Union{Unsigned,Signed} u = zero(T) for l = 1:min(abs(x.size), cld(sizeof(T),sizeof(Limb))) u += (unsafe_load(x.d,l)%T) << ((sizeof(Limb)<<3)*(l-1)) diff --git a/base/grisu/float.jl b/base/grisu/float.jl index 2adec178d2fd6..af95f941dd10f 100644 --- a/base/grisu/float.jl +++ b/base/grisu/float.jl @@ -113,7 +113,7 @@ function _significand(d::T) where T<:AbstractFloat s = uint_t(d) & SignificandMask(T) return !isdenormal(d) ? s + HiddenBit(T) : s end -isdenormal{T<:AbstractFloat}(d::T) = (uint_t(d) & ExponentMask(T)) == 0 +isdenormal(d::T) where {T<:AbstractFloat} = (uint_t(d) & ExponentMask(T)) == 0 function normalizedbound(f::AbstractFloat) v = Float(_significand(f),_exponent(f)) diff --git a/base/io.jl b/base/io.jl index be201e7680217..1d5e1651a0c51 100644 --- a/base/io.jl +++ b/base/io.jl @@ -290,9 +290,10 @@ function write(io::IO, xs...) return written end -@noinline unsafe_write{T}(s::IO, p::Ref{T}, n::Integer) = unsafe_write(s, unsafe_convert(Ref{T}, p)::Ptr, n) # mark noinline to ensure ref is gc-rooted somewhere (by the caller) +@noinline unsafe_write(s::IO, p::Ref{T}, n::Integer) where {T} = + unsafe_write(s, unsafe_convert(Ref{T}, p)::Ptr, n) # mark noinline to ensure ref is gc-rooted somewhere (by the caller) unsafe_write(s::IO, p::Ptr, n::Integer) = unsafe_write(s, convert(Ptr{UInt8}, p), convert(UInt, n)) -write{T}(s::IO, x::Ref{T}) = unsafe_write(s, x, Core.sizeof(T)) +write(s::IO, x::Ref{T}) where {T} = unsafe_write(s, x, Core.sizeof(T)) write(s::IO, x::Int8) = write(s, reinterpret(UInt8, x)) function write(s::IO, x::Union{Int16,UInt16,Int32,UInt32,Int64,UInt64,Int128,UInt128,Float16,Float32,Float64}) return write(s, Ref(x)) @@ -313,7 +314,7 @@ end return unsafe_write(s, pointer(a), sizeof(a)) end -@noinline function write{T}(s::IO, a::Array{T}) # mark noinline to ensure the array is gc-rooted somewhere (by the caller) +@noinline function write(s::IO, a::Array{T}) where T # mark noinline to ensure the array is gc-rooted somewhere (by the caller) if isbits(T) return unsafe_write(s, pointer(a), sizeof(a)) else @@ -437,7 +438,7 @@ function readuntil(s::IO, delim::Char) return String(take!(out)) end -function readuntil{T}(s::IO, delim::T) +function readuntil(s::IO, delim::T) where T out = T[] while !eof(s) c = read(s, T) diff --git a/base/iostream.jl b/base/iostream.jl index 7517fd1175934..c03de590113b4 100644 --- a/base/iostream.jl +++ b/base/iostream.jl @@ -166,7 +166,7 @@ function unsafe_write(s::IOStream, p::Ptr{UInt8}, nb::UInt) return Int(ccall(:ios_write, Csize_t, (Ptr{Void}, Ptr{Void}, Csize_t), s.ios, p, nb)) end -function write{T,N}(s::IOStream, a::SubArray{T,N,<:Array}) +function write(s::IOStream, a::SubArray{T,N,<:Array}) where {T,N} if !isbits(T) || stride(a,1)!=1 return invoke(write, Tuple{Any, AbstractArray}, s, a) end diff --git a/base/iterators.jl b/base/iterators.jl index 1c2ab13f8e113..49228be91a562 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -18,7 +18,7 @@ _diff_length(a, b, ::IsInfinite, ::IsInfinite) = 0 _diff_length(a, b, ::IsInfinite, B) = length(a) # inherit behaviour, error _diff_length(a, b, A, B) = max(length(a)-length(b), 0) -and_iteratorsize{T}(isz::T, ::T) = isz +and_iteratorsize(isz::T, ::T) where {T} = isz and_iteratorsize(::HasLength, ::HasShape) = HasLength() and_iteratorsize(::HasShape, ::HasLength) = HasLength() and_iteratorsize(a, b) = SizeUnknown() @@ -645,7 +645,7 @@ eltype(::Type{Prod{I1,I2}}) where {I1,I2} = tuple_type_cons(eltype(I1), eltype(I iteratoreltype(::Type{Prod{I1,I2}}) where {I1,I2} = and_iteratoreltype(iteratoreltype(I1),iteratoreltype(I2)) iteratorsize(::Type{Prod{I1,I2}}) where {I1,I2} = prod_iteratorsize(iteratorsize(I1),iteratorsize(I2)) -@inline function next{I1,I2}(p::Prod{I1,I2}, st) +@inline function next(p::Prod, st) x = prod_next(p, st) ((x[1][1],x[1][2]...), x[2]) end diff --git a/base/libgit2/reference.jl b/base/libgit2/reference.jl index da6f26baf132d..3a8c32929cc33 100644 --- a/base/libgit2/reference.jl +++ b/base/libgit2/reference.jl @@ -171,7 +171,7 @@ then `ref` will be peeled until an object other than a [`GitTag`](@ref) is obtai Only annotated tags can be peeled to `GitTag` objects. Lightweight tags (the default) are references under `refs/tags/` which point directly to `GitCommit` objects. """ -function peel{T<:GitObject}(::Type{T}, ref::GitReference) +function peel(::Type{T}, ref::GitReference) where T<:GitObject obj_ptr_ptr = Ref{Ptr{Void}}(C_NULL) @check ccall((:git_reference_peel, :libgit2), Cint, (Ptr{Ptr{Void}}, Ptr{Void}, Cint), obj_ptr_ptr, ref.ptr, Consts.OBJECT(T)) diff --git a/base/libgit2/types.jl b/base/libgit2/types.jl index e1a2690041384..0e7715c0bc2f6 100644 --- a/base/libgit2/types.jl +++ b/base/libgit2/types.jl @@ -639,9 +639,9 @@ function with(f::Function, obj) end end -with{T}(f::Function, ::Type{T}, args...) = with(f, T(args...)) +with(f::Function, ::Type{T}, args...) where {T} = with(f, T(args...)) -function with_warn{T}(f::Function, ::Type{T}, args...) +function with_warn(f::Function, ::Type{T}, args...) where T obj = T(args...) try with(f, obj) @@ -651,7 +651,7 @@ function with_warn{T}(f::Function, ::Type{T}, args...) end """ - LibGit2.Consts.OBJECT{T<:GitObject}(::Type{T}) + LibGit2.Consts.OBJECT(::Type{T}) where T<:GitObject The `OBJECT` enum value corresponding to type `T`. """ diff --git a/base/linalg/bitarray.jl b/base/linalg/bitarray.jl index 375f7ad67ce7a..b591b94d0e358 100644 --- a/base/linalg/bitarray.jl +++ b/base/linalg/bitarray.jl @@ -40,7 +40,7 @@ end #C #end -#aCb{T, S}(A::BitMatrix{T}, B::BitMatrix{S}) = aTb(A, B) +#aCb(A::BitMatrix{T}, B::BitMatrix{S}) where {T,S} = aTb(A, B) function triu(B::BitMatrix, k::Integer=0) m,n = size(B) diff --git a/base/linalg/bunchkaufman.jl b/base/linalg/bunchkaufman.jl index 224fb39ab6371..2161af6469bdc 100644 --- a/base/linalg/bunchkaufman.jl +++ b/base/linalg/bunchkaufman.jl @@ -12,8 +12,8 @@ struct BunchKaufman{T,S<:AbstractMatrix} <: Factorization{T} rook::Bool info::BlasInt end -BunchKaufman{T}(A::AbstractMatrix{T}, ipiv::Vector{BlasInt}, uplo::Char, symmetric::Bool, - rook::Bool, info::BlasInt) = +BunchKaufman(A::AbstractMatrix{T}, ipiv::Vector{BlasInt}, uplo::Char, symmetric::Bool, + rook::Bool, info::BlasInt) where {T} = BunchKaufman{T,typeof(A)}(A, ipiv, uplo, symmetric, rook, info) """ diff --git a/base/linalg/cholesky.jl b/base/linalg/cholesky.jl index 1e9fa98ea28a8..ca9f7c2be51c3 100644 --- a/base/linalg/cholesky.jl +++ b/base/linalg/cholesky.jl @@ -34,9 +34,9 @@ struct Cholesky{T,S<:AbstractMatrix} <: Factorization{T} uplo::Char info::BlasInt end -Cholesky{T}(A::AbstractMatrix{T}, uplo::Symbol, info::BlasInt) = +Cholesky(A::AbstractMatrix{T}, uplo::Symbol, info::BlasInt) where {T} = Cholesky{T,typeof(A)}(A, char_uplo(uplo), info) -Cholesky{T}(A::AbstractMatrix{T}, uplo::Char, info::BlasInt) = +Cholesky(A::AbstractMatrix{T}, uplo::Char, info::BlasInt) where {T} = Cholesky{T,typeof(A)}(A, uplo, info) struct CholeskyPivoted{T,S<:AbstractMatrix} <: Factorization{T} @@ -47,8 +47,8 @@ struct CholeskyPivoted{T,S<:AbstractMatrix} <: Factorization{T} tol::Real info::BlasInt end -function CholeskyPivoted{T}(A::AbstractMatrix{T}, uplo::Char, piv::Vector{BlasInt}, - rank::BlasInt, tol::Real, info::BlasInt) +function CholeskyPivoted(A::AbstractMatrix{T}, uplo::Char, piv::Vector{BlasInt}, + rank::BlasInt, tol::Real, info::BlasInt) where T CholeskyPivoted{T,typeof(A)}(A, uplo, piv, rank, tol, info) end diff --git a/base/linalg/factorization.jl b/base/linalg/factorization.jl index 2a228d4948f0a..ef5b69ad1575f 100644 --- a/base/linalg/factorization.jl +++ b/base/linalg/factorization.jl @@ -36,7 +36,7 @@ Base.isequal(F::T, G::T) where {T<:Factorization} = all(f -> isequal(getfield(F, # With a real lhs and complex rhs with the same precision, we can reinterpret # the complex rhs as a real rhs with twice the number of columns -function (\){T<:BlasReal}(F::Factorization{T}, B::VecOrMat{Complex{T}}) +function (\)(F::Factorization{T}, B::VecOrMat{Complex{T}}) where T<:BlasReal c2r = reshape(transpose(reinterpret(T, B, (2, length(B)))), size(B, 1), 2*size(B, 2)) x = A_ldiv_B!(F, c2r) return reinterpret(Complex{T}, transpose(reshape(x, div(length(x), 2), 2)), _ret_size(F, B)) diff --git a/base/linalg/generic.jl b/base/linalg/generic.jl index 142164194439e..9a020b5a0dece 100644 --- a/base/linalg/generic.jl +++ b/base/linalg/generic.jl @@ -304,7 +304,7 @@ gradient(F::AbstractVector, h::Real) = gradient(F, [h*(1:length(F));]) diag(A::AbstractVector) = throw(ArgumentError("use diagm instead of diag to construct a diagonal matrix")) -#diagm{T}(v::AbstractVecOrMat{T}) +#diagm(v::AbstractVecOrMat{T}) where {T} ########################################################################################### # Inner products and norms @@ -736,7 +736,7 @@ end trace(x::Number) = x #kron(a::AbstractVector, b::AbstractVector) -#kron{T,S}(a::AbstractMatrix{T}, b::AbstractMatrix{S}) +#kron(a::AbstractMatrix{T}, b::AbstractMatrix{S}) where {T,S} #det(a::AbstractMatrix) diff --git a/base/linalg/givens.jl b/base/linalg/givens.jl index ed1c967ca5212..d822499d94c43 100644 --- a/base/linalg/givens.jl +++ b/base/linalg/givens.jl @@ -233,7 +233,7 @@ end """ - givens{T}(f::T, g::T, i1::Integer, i2::Integer) -> (G::Givens, r::T) + givens(f::T, g::T, i1::Integer, i2::Integer) where {T} -> (G::Givens, r::T) Computes the Givens rotation `G` and scalar `r` such that for any vector `x` where ``` diff --git a/base/linalg/lq.jl b/base/linalg/lq.jl index a647550bcf9a4..b6b43289385fb 100644 --- a/base/linalg/lq.jl +++ b/base/linalg/lq.jl @@ -90,7 +90,7 @@ convert(::Type{LQPackedQ{T}}, Q::LQPackedQ) where {T} = LQPackedQ(convert(Abstra convert(::Type{AbstractMatrix{T}}, Q::LQPackedQ) where {T} = convert(LQPackedQ{T}, Q) convert(::Type{Matrix}, A::LQPackedQ) = LAPACK.orglq!(copy(A.factors),A.τ) convert(::Type{Array}, A::LQPackedQ) = convert(Matrix, A) -function full{T}(A::LQPackedQ{T}; thin::Bool = true) +function full(A::LQPackedQ{T}; thin::Bool = true) where T #= We construct the full eye here, even though it seems inefficient, because every element in the output matrix is a function of all the elements of the input matrix. The eye is modified by the elementary reflectors held diff --git a/base/linalg/qr.jl b/base/linalg/qr.jl index 13aa153575f1e..ca380455e4c84 100644 --- a/base/linalg/qr.jl +++ b/base/linalg/qr.jl @@ -472,7 +472,7 @@ rows of `R` in the QR factorization that are zero. The resulting matrix is the ` QR factorization (sometimes called the reduced QR factorization). If `false`, returns a `Q` that spans all rows of `R` in its corresponding QR factorization. """ -function full{T}(A::Union{QRPackedQ{T},QRCompactWYQ{T}}; thin::Bool = true) +function full(A::Union{QRPackedQ{T},QRCompactWYQ{T}}; thin::Bool = true) where T if thin convert(Array, A) else diff --git a/base/linalg/rowvector.jl b/base/linalg/rowvector.jl index e38111fd7e1d7..ae04639f505a2 100644 --- a/base/linalg/rowvector.jl +++ b/base/linalg/rowvector.jl @@ -28,7 +28,7 @@ end const ConjRowVector{T,CV<:ConjVector} = RowVector{T,CV} # The element type may be transformed as transpose is recursive -@inline transpose_type{T}(::Type{T}) = promote_op(transpose, T) +@inline transpose_type(::Type{T}) where {T} = promote_op(transpose, T) # Constructors that take a vector @inline RowVector(vec::AbstractVector{T}) where {T} = RowVector{transpose_type(T),typeof(vec)}(vec) diff --git a/base/linalg/schur.jl b/base/linalg/schur.jl index be0cc0188bfc4..656beabe74064 100644 --- a/base/linalg/schur.jl +++ b/base/linalg/schur.jl @@ -48,7 +48,7 @@ julia> F[:vectors] * F[:Schur] * F[:vectors]' ``` """ schurfact(A::StridedMatrix{<:BlasFloat}) = schurfact!(copy(A)) -function schurfact{T}(A::StridedMatrix{T}) +function schurfact(A::StridedMatrix{T}) where T S = promote_type(Float32, typeof(one(T)/norm(one(T)))) return schurfact!(copy_oftype(A, S)) end diff --git a/base/linalg/special.jl b/base/linalg/special.jl index fd1bd6bd6070e..d278d953514a5 100644 --- a/base/linalg/special.jl +++ b/base/linalg/special.jl @@ -94,9 +94,9 @@ function convert(::Type{Tridiagonal}, A::AbstractTriangular) end # Constructs two method definitions taking into account (assumed) commutativity -# e.g. @commutative f{S,T}(x::S, y::T) = x+y is the same is defining -# f{S,T}(x::S, y::T) = x+y -# f{S,T}(y::T, x::S) = f(x, y) +# e.g. @commutative f(x::S, y::T) where {S,T} = x+y is the same is defining +# f(x::S, y::T) where {S,T} = x+y +# f(y::T, x::S) where {S,T} = f(x, y) macro commutative(myexpr) @assert myexpr.head===:(=) || myexpr.head===:function # Make sure it is a function definition y = copy(myexpr.args[1].args[2:end]) diff --git a/base/linalg/svd.jl b/base/linalg/svd.jl index a81105072d06c..bd7a659efb1cc 100644 --- a/base/linalg/svd.jl +++ b/base/linalg/svd.jl @@ -162,7 +162,7 @@ svdvals(x::Number) = abs(x) svdvals(S::SVD{<:Any,T}) where {T} = (S[:S])::Vector{T} # SVD least squares -function A_ldiv_B!{T}(A::SVD{T}, B::StridedVecOrMat) +function A_ldiv_B!(A::SVD{T}, B::StridedVecOrMat) where T k = searchsortedlast(A.S, eps(real(T))*A.S[1], rev=true) view(A.Vt,1:k,:)' * (view(A.S,1:k) .\ (view(A.U,:,1:k)' * B)) end diff --git a/base/markdown/render/html.jl b/base/markdown/render/html.jl index ae74794168c35..6b9a9802b6c87 100644 --- a/base/markdown/render/html.jl +++ b/base/markdown/render/html.jl @@ -59,7 +59,7 @@ end html(io::IO, md::MD) = html(io, md.content) -function html{l}(io::IO, header::Header{l}) +function html(io::IO, header::Header{l}) where l withtag(io, "h$l") do htmlinline(io, header.text) end diff --git a/base/markdown/render/latex.jl b/base/markdown/render/latex.jl index e41f4b5e75844..fb0650c5d6603 100644 --- a/base/markdown/render/latex.jl +++ b/base/markdown/render/latex.jl @@ -24,7 +24,7 @@ function latex(io::IO, content::Vector) end end -function latex{l}(io::IO, header::Header{l}) +function latex(io::IO, header::Header{l}) where l tag = l < 4 ? "sub"^(l-1) * "section" : "sub"^(l-4) * "paragraph" wrapinline(io, tag) do latexinline(io, header.text) diff --git a/base/markdown/render/rst.jl b/base/markdown/render/rst.jl index 58269df48aaee..d9fadc4e7910e 100644 --- a/base/markdown/render/rst.jl +++ b/base/markdown/render/rst.jl @@ -13,7 +13,7 @@ end rst(io::IO, md::MD) = rst(io, md.content) -function rst{l}(io::IO, header::Header{l}) +function rst(io::IO, header::Header{l}) where l s = rstinline(header.text) println(io, s) println(io, string("*=-~:.^"[l])^length(s)) diff --git a/base/markdown/render/terminal/render.jl b/base/markdown/render/terminal/render.jl index 76be8ec471f8f..f7313dc36b23f 100644 --- a/base/markdown/render/terminal/render.jl +++ b/base/markdown/render/terminal/render.jl @@ -77,7 +77,7 @@ end const _header_underlines = collect("≡=–-⋅ ") # TODO settle on another option with unicode e.g. "≡=≃–∼⋅" ? -function term{l}(io::IO, md::Header{l}, columns) +function term(io::IO, md::Header{l}, columns) where l underline = _header_underlines[l] _term_header(io, md, underline, columns) end diff --git a/base/mpfr.jl b/base/mpfr.jl index 40e0fd59cf0ac..d37061d35a1d0 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -201,7 +201,7 @@ unsafe_cast(::Type{T}, x::BigFloat, r::RoundingMode) where {T<:Integer} = unsafe unsafe_trunc(::Type{T}, x::BigFloat) where {T<:Integer} = unsafe_cast(T,x,RoundToZero) -function trunc{T<:Union{Signed,Unsigned}}(::Type{T}, x::BigFloat) +function trunc(::Type{T}, x::BigFloat) where T<:Union{Signed,Unsigned} (typemin(T) <= x <= typemax(T)) || throw(InexactError()) unsafe_cast(T,x,RoundToZero) end diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 09fb0757562d5..a78d5adcac241 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -119,8 +119,8 @@ module IteratorsMD CartesianRange(index::CartesianIndex) = CartesianRange(one(index), index) CartesianRange(::Tuple{}) = CartesianRange{CartesianIndex{0}}(CartesianIndex{0}(()),CartesianIndex{0}(())) - CartesianRange{N}(sz::NTuple{N,Int}) = CartesianRange(CartesianIndex(sz)) - CartesianRange{N}(rngs::NTuple{N,Union{Integer,AbstractUnitRange}}) = + CartesianRange(sz::NTuple{N,Int}) where {N} = CartesianRange(CartesianIndex(sz)) + CartesianRange(rngs::NTuple{N,Union{Integer,AbstractUnitRange}}) where {N} = CartesianRange(CartesianIndex(map(first, rngs)), CartesianIndex(map(last, rngs))) convert(::Type{NTuple{N,UnitRange{Int}}}, R::CartesianRange{CartesianIndex{N}}) where {N} = @@ -813,10 +813,10 @@ function copy!(dest::AbstractArray{T,N}, src::AbstractArray{T,N}) where {T,N} dest end -@generated function copy!{T1,T2,N}(dest::AbstractArray{T1,N}, - Rdest::CartesianRange{CartesianIndex{N}}, - src::AbstractArray{T2,N}, - Rsrc::CartesianRange{CartesianIndex{N}}) +@generated function copy!(dest::AbstractArray{T1,N}, + Rdest::CartesianRange{CartesianIndex{N}}, + src::AbstractArray{T2,N}, + Rsrc::CartesianRange{CartesianIndex{N}}) where {T1,T2,N} quote isempty(Rdest) && return dest if size(Rdest) != size(Rsrc) @@ -1249,7 +1249,7 @@ function permutedims(B::StridedArray, perm) permutedims!(P, B, perm) end -function checkdims_perm{TP,TB,N}(P::AbstractArray{TP,N}, B::AbstractArray{TB,N}, perm) +function checkdims_perm(P::AbstractArray{TP,N}, B::AbstractArray{TB,N}, perm) where {TP,TB,N} indsB = indices(B) length(perm) == N || throw(ArgumentError("expected permutation of size $N, but length(perm)=$(length(perm))")) isperm(perm) || throw(ArgumentError("input is not a permutation")) diff --git a/base/multinverses.jl b/base/multinverses.jl index 5b60e76e40a29..d436860f14506 100644 --- a/base/multinverses.jl +++ b/base/multinverses.jl @@ -11,7 +11,7 @@ unsigned(::Type{Int16}) = UInt16 unsigned(::Type{Int32}) = UInt32 unsigned(::Type{Int64}) = UInt64 unsigned(::Type{Int128}) = UInt128 -unsigned{T<:Unsigned}(::Type{T}) = T +unsigned(::Type{T}) where {T<:Unsigned} = T abstract type MultiplicativeInverse{T} end diff --git a/base/nullable.jl b/base/nullable.jl index 9762cfdaa57d6..e4f16b9639cd4 100644 --- a/base/nullable.jl +++ b/base/nullable.jl @@ -31,7 +31,7 @@ Nullable{Int64} value: Int64 1 ``` """ -Nullable{T}(value::T, hasvalue::Bool=true) = Nullable{T}(value, hasvalue) +Nullable(value::T, hasvalue::Bool=true) where {T} = Nullable{T}(value, hasvalue) Nullable() = Nullable{Union{}}() eltype(::Type{Nullable{T}}) where {T} = T diff --git a/base/operators.jl b/base/operators.jl index c38c2106278b0..8785134cf8571 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -563,7 +563,7 @@ end # fallback div, fld, and cld implementations # NOTE: C89 fmod() and x87 FPREM implicitly provide truncating float division, # so it is used here as the basis of float div(). -div{T<:Real}(x::T, y::T) = convert(T,round((x-rem(x,y))/y)) +div(x::T, y::T) where {T<:Real} = convert(T,round((x-rem(x,y))/y)) """ fld(x, y) @@ -575,7 +575,7 @@ julia> fld(7.3,5.5) 1.0 ``` """ -fld{T<:Real}(x::T, y::T) = convert(T,round((x-mod(x,y))/y)) +fld(x::T, y::T) where {T<:Real} = convert(T,round((x-mod(x,y))/y)) """ cld(x, y) @@ -586,10 +586,10 @@ julia> cld(5.5,2.2) 3.0 ``` """ -cld{T<:Real}(x::T, y::T) = convert(T,round((x-modCeil(x,y))/y)) -#rem{T<:Real}(x::T, y::T) = convert(T,x-y*trunc(x/y)) -#mod{T<:Real}(x::T, y::T) = convert(T,x-y*floor(x/y)) -modCeil{T<:Real}(x::T, y::T) = convert(T,x-y*ceil(x/y)) +cld(x::T, y::T) where {T<:Real} = convert(T,round((x-modCeil(x,y))/y)) +#rem(x::T, y::T) where {T<:Real} = convert(T,x-y*trunc(x/y)) +#mod(x::T, y::T) where {T<:Real} = convert(T,x-y*floor(x/y)) +modCeil(x::T, y::T) where {T<:Real} = convert(T,x-y*ceil(x/y)) # operator alias @@ -644,9 +644,9 @@ julia> mod1(4, 3) 1 ``` """ -mod1{T<:Real}(x::T, y::T) = (m = mod(x, y); ifelse(m == 0, y, m)) +mod1(x::T, y::T) where {T<:Real} = (m = mod(x, y); ifelse(m == 0, y, m)) # efficient version for integers -mod1{T<:Integer}(x::T, y::T) = (@_inline_meta; mod(x + y - T(1), y) + T(1)) +mod1(x::T, y::T) where {T<:Integer} = (@_inline_meta; mod(x + y - T(1), y) + T(1)) """ diff --git a/base/pair.jl b/base/pair.jl index 338f5547c1269..3b04bdf91ce34 100644 --- a/base/pair.jl +++ b/base/pair.jl @@ -23,7 +23,7 @@ isless(p::Pair, q::Pair) = ifelse(!isequal(p.first,q.first), isless(p.first,q.fi isless(p.second,q.second)) getindex(p::Pair,i::Int) = getfield(p,i) getindex(p::Pair,i::Real) = getfield(p, convert(Int, i)) -reverse{A,B}(p::Pair{A,B}) = Pair{B,A}(p.second, p.first) +reverse(p::Pair{A,B}) where {A,B} = Pair{B,A}(p.second, p.first) endof(p::Pair) = 2 length(p::Pair) = 2 diff --git a/base/pkg/resolve/versionweight.jl b/base/pkg/resolve/versionweight.jl index 5c787dbce69b6..596377c55bf9a 100644 --- a/base/pkg/resolve/versionweight.jl +++ b/base/pkg/resolve/versionweight.jl @@ -11,7 +11,7 @@ struct HierarchicalValue{T} rest::T end -HierarchicalValue{T}(v::Vector{T}) = HierarchicalValue{T}(v, zero(T)) +HierarchicalValue(v::Vector{T}) where {T} = HierarchicalValue{T}(v, zero(T)) HierarchicalValue(T::Type) = HierarchicalValue(T[]) Base.zero(::Type{HierarchicalValue{T}}) where {T} = HierarchicalValue(T) diff --git a/base/process.jl b/base/process.jl index 4bbeee16d796f..ac85813c5f551 100644 --- a/base/process.jl +++ b/base/process.jl @@ -208,7 +208,7 @@ byteenv(env::AbstractArray{<:AbstractString}) = byteenv(env::Associative) = String[cstr(string(k)*"="*string(v)) for (k,v) in env] byteenv(env::Void) = nothing -byteenv{T<:AbstractString}(env::Union{AbstractVector{Pair{T}}, Tuple{Vararg{Pair{T}}}}) = +byteenv(env::Union{AbstractVector{Pair{T}}, Tuple{Vararg{Pair{T}}}}) where {T<:AbstractString} = String[cstr(k*"="*string(v)) for (k,v) in env] """ diff --git a/base/promotion.jl b/base/promotion.jl index 2972a7da99cce..e5f2bdd6f80de 100644 --- a/base/promotion.jl +++ b/base/promotion.jl @@ -188,7 +188,7 @@ function promote(x, y, zs...) convert(promote_typeof(x,y,zs...), y), convert(Tuple{Vararg{promote_typeof(x,y,zs...)}}, zs)...) end -# TODO: promote{T}(x::T, ys::T...) here to catch all circularities? +# TODO: promote(x::T, ys::T...) where {T} here to catch all circularities? ## promotions in arithmetic, etc. ## @@ -316,13 +316,13 @@ else end promote_op(::Any...) = (@_inline_meta; Any) -function promote_op{S}(f, ::Type{S}) +function promote_op(f, ::Type{S}) where S @_inline_meta T = _return_type(f, Tuple{_default_type(S)}) isleaftype(S) && return isleaftype(T) ? T : Any return typejoin(S, T) end -function promote_op{R,S}(f, ::Type{R}, ::Type{S}) +function promote_op(f, ::Type{R}, ::Type{S}) where {R,S} @_inline_meta T = _return_type(f, Tuple{_default_type(R), _default_type(S)}) isleaftype(R) && isleaftype(S) && return isleaftype(T) ? T : Any diff --git a/base/random.jl b/base/random.jl index 29d2d842cc43d..bac84d93c24ba 100644 --- a/base/random.jl +++ b/base/random.jl @@ -36,12 +36,12 @@ if is_windows() RandomDevice() = new(Vector{UInt128}(1)) end - function rand{T<:Union{Bool, Base.BitInteger}}(rd::RandomDevice, ::Type{T}) + function rand(rd::RandomDevice, ::Type{T}) where T<:Union{Bool,Base.BitInteger} win32_SystemFunction036!(rd.buffer) @inbounds return rd.buffer[1] % T end - rand!(rd::RandomDevice, A::Array{<:Union{Bool, Base.BitInteger}}) = (win32_SystemFunction036!(A); A) + rand!(rd::RandomDevice, A::Array{<:Union{Bool,Base.BitInteger}}) = (win32_SystemFunction036!(A); A) else # !windows struct RandomDevice <: AbstractRNG file::IOStream @@ -50,8 +50,8 @@ else # !windows RandomDevice(unlimited::Bool=true) = new(open(unlimited ? "/dev/urandom" : "/dev/random"), unlimited) end - rand{T<:Union{Bool, Base.BitInteger}}(rd::RandomDevice, ::Type{T}) = read( rd.file, T) - rand!(rd::RandomDevice, A::Array{<:Union{Bool, Base.BitInteger}}) = read!(rd.file, A) + rand(rd::RandomDevice, ::Type{T}) where {T<:Union{Bool,Base.BitInteger}} = read( rd.file, T) + rand!(rd::RandomDevice, A::Array{<:Union{Bool,Base.BitInteger}}) = read!(rd.file, A) end # os-test @@ -135,7 +135,7 @@ end @inline rand_inbounds(r::MersenneTwister) = rand_inbounds(r, CloseOpen) # produce Float64 values -@inline rand{I<:FloatInterval}(r::MersenneTwister, ::Type{I}) = (reserve_1(r); rand_inbounds(r, I)) +@inline rand(r::MersenneTwister, ::Type{I}) where {I<:FloatInterval} = (reserve_1(r); rand_inbounds(r, I)) @inline rand_ui52_raw_inbounds(r::MersenneTwister) = reinterpret(UInt64, rand_inbounds(r, Close1Open2)) @inline rand_ui52_raw(r::MersenneTwister) = (reserve_1(r); rand_ui52_raw_inbounds(r)) @@ -239,7 +239,7 @@ function srand() dsfmt_gv_srand() end -function srand(seed::Union{Integer, Vector{UInt32}}) +function srand(seed::Union{Integer,Vector{UInt32}}) srand(GLOBAL_RNG, seed) dsfmt_gv_srand() end @@ -322,7 +322,8 @@ rand(r::Union{RandomDevice,MersenneTwister}, ::Type{Float32}) = # MersenneTwister -@inline rand{T<:Union{Bool, Int8, UInt8, Int16, UInt16, Int32, UInt32}}(r::MersenneTwister, ::Type{T}) = rand_ui52_raw(r) % T +@inline rand(r::MersenneTwister, ::Type{T}) where {T<:Union{Bool,Int8,UInt8,Int16,UInt16,Int32,UInt32}} = + rand_ui52_raw(r) % T function rand(r::MersenneTwister, ::Type{UInt64}) reserve(r, 2) @@ -341,7 +342,7 @@ rand(r::MersenneTwister, ::Type{Int128}) = reinterpret(Int128, rand(r, UInt128) ## random Complex values -rand{T<:Real}(r::AbstractRNG, ::Type{Complex{T}}) = complex(rand(r, T), rand(r, T)) +rand(r::AbstractRNG, ::Type{Complex{T}}) where {T<:Real} = complex(rand(r, T), rand(r, T)) # random Char values # returns a random valid Unicode scalar value (i.e. 0 - 0xd7ff, 0xe000 - # 0x10ffff) @@ -388,7 +389,7 @@ rand(r::AbstractRNG, T::Type, d1::Integer, dims::Integer...) = rand(r, T, tuple( # rand(r, ()) would match both this method and rand(r, dims::Dims) # moreover, a call like rand(r, NotImplementedType()) would be an infinite loop -function rand!{T}(r::AbstractRNG, A::AbstractArray{T}) +function rand!(r::AbstractRNG, A::AbstractArray{T}) where T for i in eachindex(A) @inbounds A[i] = rand(r, T) end @@ -413,7 +414,8 @@ rand(s::Union{Dict,Set,IntSet}, dims::Dims) = rand(GLOBAL_RNG, s, dims) # MersenneTwister -function rand_AbstractArray_Float64!{I<:FloatInterval}(r::MersenneTwister, A::AbstractArray{Float64}, n=length(A), ::Type{I}=CloseOpen) +function rand_AbstractArray_Float64!(r::MersenneTwister, A::AbstractArray{Float64}, + n=length(A), ::Type{I}=CloseOpen) where I<:FloatInterval # what follows is equivalent to this simple loop but more efficient: # for i=1:n # @inbounds A[i] = rand(r, I) @@ -439,7 +441,7 @@ rand!(r::MersenneTwister, A::AbstractArray{Float64}) = rand_AbstractArray_Float6 fill_array!(s::DSFMT_state, A::Ptr{Float64}, n::Int, ::Type{CloseOpen}) = dsfmt_fill_array_close_open!(s, A, n) fill_array!(s::DSFMT_state, A::Ptr{Float64}, n::Int, ::Type{Close1Open2}) = dsfmt_fill_array_close1_open2!(s, A, n) -function rand!{I<:FloatInterval}(r::MersenneTwister, A::Array{Float64}, n::Int=length(A), ::Type{I}=CloseOpen) +function rand!(r::MersenneTwister, A::Array{Float64}, n::Int=length(A), ::Type{I}=CloseOpen) where I<:FloatInterval # depending on the alignment of A, the data written by fill_array! may have # to be left-shifted by up to 15 bytes (cf. unsafe_copy! below) for # reproducibility purposes; @@ -472,7 +474,7 @@ end @inline mask128(u::UInt128, ::Type{Float16}) = (u & 0x03ff03ff03ff03ff03ff03ff03ff03ff) | 0x3c003c003c003c003c003c003c003c00 @inline mask128(u::UInt128, ::Type{Float32}) = (u & 0x007fffff007fffff007fffff007fffff) | 0x3f8000003f8000003f8000003f800000 -function rand!{T<:Union{Float16, Float32}}(r::MersenneTwister, A::Array{T}, ::Type{Close1Open2}) +function rand!(r::MersenneTwister, A::Array{T}, ::Type{Close1Open2}) where T<:Union{Float16,Float32} n = length(A) n128 = n * sizeof(T) ÷ 16 rand!(r, unsafe_wrap(Array, convert(Ptr{Float64}, pointer(A)), 2*n128), 2*n128, Close1Open2) @@ -496,7 +498,7 @@ function rand!{T<:Union{Float16, Float32}}(r::MersenneTwister, A::Array{T}, ::Ty A end -function rand!{T<:Union{Float16, Float32}}(r::MersenneTwister, A::Array{T}, ::Type{CloseOpen}) +function rand!(r::MersenneTwister, A::Array{T}, ::Type{CloseOpen}) where T<:Union{Float16,Float32} rand!(r, A, Close1Open2) I32 = one(Float32) for i in eachindex(A) @@ -505,7 +507,7 @@ function rand!{T<:Union{Float16, Float32}}(r::MersenneTwister, A::Array{T}, ::Ty A end -rand!(r::MersenneTwister, A::Array{<:Union{Float16, Float32}}) = rand!(r, A, CloseOpen) +rand!(r::MersenneTwister, A::Array{<:Union{Float16,Float32}}) = rand!(r, A, CloseOpen) function rand!(r::MersenneTwister, A::Array{UInt128}, n::Int=length(A)) @@ -536,7 +538,7 @@ function rand!(r::MersenneTwister, A::Array{UInt128}, n::Int=length(A)) A end -function rand!{T<:Union{Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128}}(r::MersenneTwister, A::Array{T}) +function rand!(r::MersenneTwister, A::Array{T}) where T<:Union{Base.BitInteger64,Int128} n=length(A) n128 = n * sizeof(T) ÷ 16 rand!(r, unsafe_wrap(Array, convert(Ptr{UInt128}, pointer(A)), n128)) @@ -615,7 +617,7 @@ end # this function uses 32 bit entropy for small ranges of length <= typemax(UInt32) + 1 # RangeGeneratorInt is responsible for providing the right value of k -function rand{T<:Union{UInt64, Int64}}(rng::AbstractRNG, g::RangeGeneratorInt{T,UInt64}) +function rand(rng::AbstractRNG, g::RangeGeneratorInt{T,UInt64}) where T<:Union{UInt64,Int64} local x::UInt64 if (g.k - 1) >> 32 == 0 x = rand(rng, UInt32) @@ -631,7 +633,7 @@ function rand{T<:Union{UInt64, Int64}}(rng::AbstractRNG, g::RangeGeneratorInt{T, return reinterpret(T, reinterpret(UInt64, g.a) + rem_knuth(x, g.k)) end -function rand{T<:Integer, U<:Unsigned}(rng::AbstractRNG, g::RangeGeneratorInt{T,U}) +function rand(rng::AbstractRNG, g::RangeGeneratorInt{T,U}) where U<:Unsigned where T<:Integer x = rand(rng, U) while x > g.u x = rand(rng, U) @@ -680,7 +682,7 @@ function rand!(rng::AbstractRNG, A::AbstractArray, r::AbstractArray) return A end -rand{T}(rng::AbstractRNG, r::AbstractArray{T}, dims::Dims) = rand!(rng, Array{T}(dims), r) +rand(rng::AbstractRNG, r::AbstractArray{T}, dims::Dims) where {T} = rand!(rng, Array{T}(dims), r) rand(rng::AbstractRNG, r::AbstractArray, dims::Int...) = rand(rng, r, dims) ## random BitArrays (AbstractRNG) @@ -1311,7 +1313,7 @@ end # complex randn Base.@irrational SQRT_HALF 0.7071067811865475244008 sqrt(big(0.5)) -randn(rng::AbstractRNG, ::Type{Complex{T}}) where {T <: AbstractFloat} = +randn(rng::AbstractRNG, ::Type{Complex{T}}) where {T<:AbstractFloat} = Complex{T}(SQRT_HALF * randn(rng, T), SQRT_HALF * randn(rng, T)) ## random UUID generation diff --git a/base/range.jl b/base/range.jl index eded200e7ce2b..dafa655c2054e 100644 --- a/base/range.jl +++ b/base/range.jl @@ -46,7 +46,7 @@ is also used in indexing to select whole dimensions. colon(start::T, step, stop::T) where {T} = _colon(start, step, stop) colon(start::T, step, stop::T) where {T<:Real} = _colon(start, step, stop) # without the second method above, the first method above is ambiguous with -# colon{A<:Real,C<:Real}(start::A, step, stop::C) +# colon(start::A, step, stop::C) where {A<:Real,C<:Real} function _colon(start::T, step, stop::T) where T T′ = typeof(start+step) StepRange(convert(T′,start), step, convert(T′,stop)) @@ -176,17 +176,19 @@ struct OneTo{T<:Integer} <: AbstractUnitRange{T} end OneTo(stop::T) where {T<:Integer} = OneTo{T}(stop) -## Step ranges parametrized by length +## Step ranges parameterized by length """ - StepRangeLen{T,R,S}(ref::R, step::S, len, [offset=1]) - -A range `r` where `r[i]` produces values of type `T`, parametrized by -a `ref`erence value, a `step`, and the `len`gth. By default `ref` is -the starting value `r[1]`, but alternatively you can supply it as the -value of `r[offset]` for some other index `1 <= offset <= len`. In -conjunction with `TwicePrecision` this can be used to implement ranges -that are free of roundoff error. + StepRangeLen{T,R,S}(ref::R, step::S, len, [offset=1]) where {T,R,S} + StepRangeLen( ref::R, step::S, len, [offset=1]) where { R,S} + +A range `r` where `r[i]` produces values of type `T` (in the second +form, `T` is deduced automatically), parameterized by a `ref`erence +value, a `step`, and the `len`gth. By default `ref` is the starting +value `r[1]`, but alternatively you can supply it as the value of +`r[offset]` for some other index `1 <= offset <= len`. In conjunction +with `TwicePrecision` this can be used to implement ranges that are +free of roundoff error. """ struct StepRangeLen{T,R,S} <: Range{T} ref::R # reference value (might be smallest-magnitude value in the range) @@ -377,7 +379,7 @@ length(r::OneTo) = unsafe_length(r) length(r::StepRangeLen) = r.len length(r::LinSpace) = r.len -function length{T<:Union{Int,UInt,Int64,UInt64}}(r::StepRange{T}) +function length(r::StepRange{T}) where T<:Union{Int,UInt,Int64,UInt64} isempty(r) && return zero(T) if r.step > 1 return checked_add(convert(T, div(unsigned(r.stop - r.start), r.step)), one(T)) @@ -388,13 +390,13 @@ function length{T<:Union{Int,UInt,Int64,UInt64}}(r::StepRange{T}) end end -function length{T<:Union{Int,Int64}}(r::AbstractUnitRange{T}) +function length(r::AbstractUnitRange{T}) where T<:Union{Int,Int64} @_inline_meta checked_add(checked_sub(last(r), first(r)), one(T)) end -length{T<:Union{Int,Int64}}(r::OneTo{T}) = T(r.stop) +length(r::OneTo{T}) where {T<:Union{Int,Int64}} = T(r.stop) -length{T<:Union{UInt,UInt64}}(r::AbstractUnitRange{T}) = +length(r::AbstractUnitRange{T}) where {T<:Union{UInt,UInt64}} = r.stop < r.start ? zero(T) : checked_add(last(r) - first(r), one(T)) # some special cases to favor default Int type @@ -510,7 +512,7 @@ function unsafe_getindex(r::LinSpace, i::Integer) lerpi.(i-1, r.lendiv, r.start, r.stop) end -function lerpi{T}(j::Integer, d::Integer, a::T, b::T) +function lerpi(j::Integer, d::Integer, a::T, b::T) where T @_inline_meta t = j/d T((1-t)*a + t*b) diff --git a/base/reducedim.jl b/base/reducedim.jl index a2ba674ee6d64..50e4e24c3b95c 100644 --- a/base/reducedim.jl +++ b/base/reducedim.jl @@ -63,7 +63,7 @@ end ## initialization for (Op, initfun) in ((:(typeof(+)), :zero), (:(typeof(*)), :one), (:(typeof(scalarmax)), :typemin), (:(typeof(scalarmin)), :typemax), (:(typeof(max)), :typemin), (:(typeof(min)), :typemax)) - @eval initarray!{T}(a::AbstractArray{T}, ::$(Op), init::Bool) = (init && fill!(a, $(initfun)(T)); a) + @eval initarray!(a::AbstractArray{T}, ::$(Op), init::Bool) where {T} = (init && fill!(a, $(initfun)(T)); a) end for (Op, initval) in ((:(typeof(&)), true), (:(typeof(|)), false)) diff --git a/base/reshapedarray.jl b/base/reshapedarray.jl index 0684752fd55e9..a0faae35cea02 100644 --- a/base/reshapedarray.jl +++ b/base/reshapedarray.jl @@ -7,7 +7,7 @@ struct ReshapedArray{T,N,P<:AbstractArray,MI<:Tuple{Vararg{SignedMultiplicativeI dims::NTuple{N,Int} mi::MI end -ReshapedArray{T,N}(parent::AbstractArray{T}, dims::NTuple{N,Int}, mi) = ReshapedArray{T,N,typeof(parent),typeof(mi)}(parent, dims, mi) +ReshapedArray(parent::AbstractArray{T}, dims::NTuple{N,Int}, mi) where {T,N} = ReshapedArray{T,N,typeof(parent),typeof(mi)}(parent, dims, mi) # IndexLinear ReshapedArray const ReshapedArrayLF{T,N,P<:AbstractArray} = ReshapedArray{T,N,P,Tuple{}} diff --git a/base/set.jl b/base/set.jl index 38665b5f55d94..bb61541997ffa 100644 --- a/base/set.jl +++ b/base/set.jl @@ -153,7 +153,7 @@ function unique(itr) end _unique_from(itr, out, seen, i) = unique_from(itr, out, seen, i) -@inline function unique_from{T}(itr, out::Vector{T}, seen, i) +@inline function unique_from(itr, out::Vector{T}, seen, i) where T while !done(itr, i) x, i = next(itr, i) S = typeof(x) diff --git a/base/socket.jl b/base/socket.jl index 108624be54917..d5af99ca9c57e 100644 --- a/base/socket.jl +++ b/base/socket.jl @@ -3,7 +3,7 @@ ## IP ADDRESS HANDLING ## abstract type IPAddr end -Base.isless{T<:IPAddr}(a::T, b::T) = isless(a.host, b.host) +Base.isless(a::T, b::T) where {T<:IPAddr} = isless(a.host, b.host) Base.convert(dt::Type{<:Integer}, ip::IPAddr) = dt(ip.host) struct IPv4 <: IPAddr diff --git a/base/sparse/cholmod.jl b/base/sparse/cholmod.jl index 2d812d07bba85..ba5b34b109407 100644 --- a/base/sparse/cholmod.jl +++ b/base/sparse/cholmod.jl @@ -565,7 +565,7 @@ function check_factor(F::Factor{Tv}) where Tv<:VTypes get(F.p), common())!=0 end -function nnz{Tv<:VTypes}(A::Sparse{Tv}) +function nnz(A::Sparse{Tv}) where Tv<:VTypes ccall((@cholmod_name("nnz", SuiteSparse_long),:libcholmod), Int, (Ptr{C_Sparse{Tv}}, Ptr{UInt8}), get(A.p), common()) @@ -749,7 +749,7 @@ end # cholmod_cholesky.h # For analyze, analyze_p, and factorize_p!, the Common argument must be # supplied in order to control if the factorization is LLt or LDLt -function analyze{Tv<:VTypes}(A::Sparse{Tv}, cmmn::Vector{UInt8}) +function analyze(A::Sparse{Tv}, cmmn::Vector{UInt8}) where Tv<:VTypes f = Factor(ccall((@cholmod_name("analyze", SuiteSparse_long),:libcholmod), Ptr{C_Factor{Tv}}, (Ptr{C_Sparse{Tv}}, Ptr{UInt8}), @@ -757,8 +757,8 @@ function analyze{Tv<:VTypes}(A::Sparse{Tv}, cmmn::Vector{UInt8}) finalizer(f, free!) f end -function analyze_p{Tv<:VTypes}(A::Sparse{Tv}, perm::Vector{SuiteSparse_long}, - cmmn::Vector{UInt8}) +function analyze_p(A::Sparse{Tv}, perm::Vector{SuiteSparse_long}, + cmmn::Vector{UInt8}) where Tv<:VTypes length(perm) != size(A,1) && throw(BoundsError()) f = Factor(ccall((@cholmod_name("analyze_p", SuiteSparse_long),:libcholmod), Ptr{C_Factor{Tv}}, @@ -952,11 +952,11 @@ convert(::Type{Sparse}, A::Symmetric{Float64,SparseMatrixCSC{Float64,SuiteSparse Sparse(A.data, A.uplo == 'L' ? -1 : 1) convert(::Type{Sparse}, A::Hermitian{Tv,SparseMatrixCSC{Tv,SuiteSparse_long}}) where {Tv<:VTypes} = Sparse(A.data, A.uplo == 'L' ? -1 : 1) -function convert{Ti<:ITypes}(::Type{Sparse}, - A::Union{SparseMatrixCSC{BigFloat,Ti}, - Symmetric{BigFloat,SparseMatrixCSC{BigFloat,Ti}}, - Hermitian{Complex{BigFloat},SparseMatrixCSC{Complex{BigFloat},Ti}}}, - args...) +function convert(::Type{Sparse}, + A::Union{SparseMatrixCSC{BigFloat,Ti}, + Symmetric{BigFloat,SparseMatrixCSC{BigFloat,Ti}}, + Hermitian{Complex{BigFloat},SparseMatrixCSC{Complex{BigFloat},Ti}}}, + args...) where Ti<:ITypes throw(MethodError(convert, (Sparse, A))) end function convert(::Type{Sparse}, diff --git a/base/sparse/linalg.jl b/base/sparse/linalg.jl index 695f25fd8619f..23590f216bf60 100644 --- a/base/sparse/linalg.jl +++ b/base/sparse/linalg.jl @@ -903,7 +903,7 @@ function factorize(A::SparseMatrixCSC) end end -function factorize{Ti}(A::Symmetric{Float64,SparseMatrixCSC{Float64,Ti}}) +function factorize(A::Symmetric{Float64,SparseMatrixCSC{Float64,Ti}}) where Ti try return cholfact(A) catch e @@ -911,7 +911,7 @@ function factorize{Ti}(A::Symmetric{Float64,SparseMatrixCSC{Float64,Ti}}) return ldltfact(A) end end -function factorize{Ti}(A::Hermitian{Complex{Float64}, SparseMatrixCSC{Complex{Float64},Ti}}) +function factorize(A::Hermitian{Complex{Float64}, SparseMatrixCSC{Complex{Float64},Ti}}) where Ti try return cholfact(A) catch e diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl index bb18c058bb2b4..0e6bef6e51a29 100644 --- a/base/sparse/sparsematrix.jl +++ b/base/sparse/sparsematrix.jl @@ -174,7 +174,9 @@ function reinterpret(::Type{T}, a::SparseMatrixCSC{Tv}) where {T,Tv} return SparseMatrixCSC(mA, nA, colptr, rowval, nzval) end -function sparse_compute_reshaped_colptr_and_rowval{Ti}(colptrS::Vector{Ti}, rowvalS::Vector{Ti}, mS::Int, nS::Int, colptrA::Vector{Ti}, rowvalA::Vector{Ti}, mA::Int, nA::Int) +function sparse_compute_reshaped_colptr_and_rowval(colptrS::Vector{Ti}, rowvalS::Vector{Ti}, + mS::Int, nS::Int, colptrA::Vector{Ti}, + rowvalA::Vector{Ti}, mA::Int, nA::Int) where Ti lrowvalA = length(rowvalA) maxrowvalA = (lrowvalA > 0) ? maximum(rowvalA) : zero(Ti) ((length(colptrA) == (nA+1)) && (maximum(colptrA) <= (lrowvalA+1)) && (maxrowvalA <= mA)) || throw(BoundsError()) @@ -514,11 +516,10 @@ sparse(I::AbstractVector, J::AbstractVector, V::AbstractVector, m::Integer, n::I sparse(AbstractVector{Int}(I), AbstractVector{Int}(J), V, m, n, combine) """ - sparse!{Tv,Ti<:Integer}( - I::AbstractVector{Ti}, J::AbstractVector{Ti}, V::AbstractVector{Tv}, - m::Integer, n::Integer, combine, klasttouch::Vector{Ti}, - csrrowptr::Vector{Ti}, csrcolval::Vector{Ti}, csrnzval::Vector{Tv}, - [csccolptr::Vector{Ti}], [cscrowval::Vector{Ti}, cscnzval::Vector{Tv}] ) + sparse!(I::AbstractVector{Ti}, J::AbstractVector{Ti}, V::AbstractVector{Tv}, + m::Integer, n::Integer, combine, klasttouch::Vector{Ti}, + csrrowptr::Vector{Ti}, csrcolval::Vector{Ti}, csrnzval::Vector{Tv}, + [csccolptr::Vector{Ti}], [cscrowval::Vector{Ti}, cscnzval::Vector{Tv}] ) where {Tv,Ti<:Integer} Parent of and expert driver for [`sparse`](@ref); see [`sparse`](@ref) for basic usage. This method @@ -713,8 +714,8 @@ end ## Transposition and permutation methods """ - halfperm!{Tv,Ti}(X::SparseMatrixCSC{Tv,Ti}, A::SparseMatrixCSC{Tv,Ti}, - q::AbstractVector{<:Integer}, f::Function = identity) + halfperm!(X::SparseMatrixCSC{Tv,Ti}, A::SparseMatrixCSC{Tv,Ti}, + q::AbstractVector{<:Integer}, f::Function = identity) where {Tv,Ti} Column-permute and transpose `A`, simultaneously applying `f` to each entry of `A`, storing the result `(f(A)Q)^T` (`map(f, transpose(A[:,q]))`) in `X`. @@ -809,9 +810,9 @@ transpose(A::SparseMatrixCSC) = ftranspose(A, identity) ctranspose(A::SparseMatrixCSC) = ftranspose(A, conj) """ - unchecked_noalias_permute!{Tv,Ti}(X::SparseMatrixCSC{Tv,Ti}, + unchecked_noalias_permute!(X::SparseMatrixCSC{Tv,Ti}, A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, - q::AbstractVector{<:Integer}, C::SparseMatrixCSC{Tv,Ti}) + q::AbstractVector{<:Integer}, C::SparseMatrixCSC{Tv,Ti}) where {Tv,Ti} See [`permute!`](@ref) for basic usage. Parent of `permute[!]` methods operating on `SparseMatrixCSC`s that assume none of `X`, `A`, and `C` alias each @@ -839,9 +840,9 @@ function unchecked_noalias_permute!(X::SparseMatrixCSC{Tv,Ti}, return X end """ - unchecked_aliasing_permute!{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, + unchecked_aliasing_permute!(A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, q::AbstractVector{<:Integer}, - C::SparseMatrixCSC{Tv,Ti}, workcolptr::Vector{Ti}) + C::SparseMatrixCSC{Tv,Ti}, workcolptr::Vector{Ti}) where {Tv,Ti} See [`permute!`](@ref) for basic usage. Parent of `permute!` methods operating on `SparseMatrixCSC`s where the source and destination matrices are the @@ -976,16 +977,18 @@ function _checkargs_sourcecompatworkcolptr_permute!(A::SparseMatrixCSC{Tv,Ti}, end end """ - permute!{Tv,Ti}(X::SparseMatrixCSC{Tv,Ti}, A::SparseMatrixCSC{Tv,Ti}, - p::AbstractVector{<:Integer}, q::AbstractVector{<:Integer}[, C::SparseMatrixCSC{Tv,Ti}]) + permute!(X::SparseMatrixCSC{Tv,Ti}, A::SparseMatrixCSC{Tv,Ti}, + p::AbstractVector{<:Integer}, q::AbstractVector{<:Integer}, + [C::SparseMatrixCSC{Tv,Ti}]) where {Tv,Ti} Bilaterally permute `A`, storing result `PAQ` (`A[p,q]`) in `X`. Stores intermediate result `(AQ)^T` (`transpose(A[:,q])`) in optional argument `C` if present. Requires that none of `X`, `A`, and, if present, `C` alias each other; to store result `PAQ` back into `A`, use the following method lacking `X`: - permute!{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, - q::AbstractVector{<:Integer}[, C::SparseMatrixCSC{Tv,Ti}[, workcolptr::Vector{Ti}]]) + permute!(A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, + q::AbstractVector{<:Integer}[, C::SparseMatrixCSC{Tv,Ti}, + [workcolptr::Vector{Ti}]]) where {Tv,Ti} `X`'s dimensions must match those of `A` (`X.m == A.m` and `X.n == A.n`), and `X` must have enough storage to accommodate all allocated entries in `A` (`length(X.rowval) >= nnz(A)` @@ -1046,8 +1049,8 @@ function permute!(A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, unchecked_aliasing_permute!(A, p, q, C, workcolptr) end """ - permute{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, - q::AbstractVector{<:Integer}) + permute(A::SparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer}, + q::AbstractVector{<:Integer}) where {Tv,Ti} Bilaterally permute `A`, returning `PAQ` (`A[p,q]`). Column-permutation `q`'s length must match `A`'s column count (`length(q) == A.n`). Row-permutation `p`'s length must match `A`'s @@ -2258,8 +2261,8 @@ setindex!(A::SparseMatrixCSC, x, ::Colon, ::Colon) = setindex!(A, x, 1:size(A, 1 setindex!(A::SparseMatrixCSC, x, ::Colon, j::Union{Integer, AbstractVector}) = setindex!(A, x, 1:size(A, 1), j) setindex!(A::SparseMatrixCSC, x, i::Union{Integer, AbstractVector}, ::Colon) = setindex!(A, x, i, 1:size(A, 2)) -function setindex!{Tv}(A::SparseMatrixCSC{Tv}, x::Number, - I::AbstractVector{<:Integer}, J::AbstractVector{<:Integer}) +function setindex!(A::SparseMatrixCSC{Tv}, x::Number, + I::AbstractVector{<:Integer}, J::AbstractVector{<:Integer}) where Tv if isempty(I) || isempty(J); return A; end # lt=≤ to check for strict sorting if !issorted(I, lt=≤); I = sort!(unique(I)); end diff --git a/base/sparse/sparsevector.jl b/base/sparse/sparsevector.jl index 05eca53334792..f9c9d38d1b624 100644 --- a/base/sparse/sparsevector.jl +++ b/base/sparse/sparsevector.jl @@ -1856,7 +1856,7 @@ function _densifystarttolastnz!(x::SparseVector) end #sorting -function sort{Tv,Ti}(x::SparseVector{Tv,Ti}; kws...) +function sort(x::SparseVector{Tv,Ti}; kws...) where {Tv,Ti} allvals = push!(copy(nonzeros(x)),zero(Tv)) sinds = sortperm(allvals;kws...) n,k = length(x),length(allvals) diff --git a/base/sparse/umfpack.jl b/base/sparse/umfpack.jl index edb88f80304de..d123ffe04581b 100644 --- a/base/sparse/umfpack.jl +++ b/base/sparse/umfpack.jl @@ -146,11 +146,11 @@ function lufact(S::SparseMatrixCSC{<:UMFVTypes,<:UMFITypes}) finalizer(res, umfpack_free_symbolic) umfpack_numeric!(res) end -lufact{Ti<:UMFITypes}(A::SparseMatrixCSC{<:Union{Float16,Float32},Ti}) = +lufact(A::SparseMatrixCSC{<:Union{Float16,Float32},Ti}) where {Ti<:UMFITypes} = lufact(convert(SparseMatrixCSC{Float64,Ti}, A)) -lufact{Ti<:UMFITypes}(A::SparseMatrixCSC{<:Union{Complex32,Complex64},Ti}) = +lufact(A::SparseMatrixCSC{<:Union{Complex32,Complex64},Ti}) where {Ti<:UMFITypes} = lufact(convert(SparseMatrixCSC{Complex128,Ti}, A)) -lufact{T<:AbstractFloat}(A::Union{SparseMatrixCSC{T},SparseMatrixCSC{Complex{T}}}) = +lufact(A::Union{SparseMatrixCSC{T},SparseMatrixCSC{Complex{T}}}) where {T<:AbstractFloat} = throw(ArgumentError(string("matrix type ", typeof(A), "not supported. ", "Try lufact(convert(SparseMatrixCSC{Float64/Complex128,Int}, A)) for ", "sparse floating point LU using UMFPACK or lufact(Array(A)) for generic ", @@ -409,25 +409,25 @@ function _Aq_ldiv_B!(X::StridedVecOrMat, lu::UmfpackLU, B::StridedVecOrMat, tran _AqldivB_kernel!(X, lu, B, transposeoptype) return X end -function _AqldivB_kernel!{T<:UMFVTypes}(x::StridedVector{T}, lu::UmfpackLU{T}, - b::StridedVector{T}, transposeoptype) +function _AqldivB_kernel!(x::StridedVector{T}, lu::UmfpackLU{T}, + b::StridedVector{T}, transposeoptype) where T<:UMFVTypes solve!(x, lu, b, transposeoptype) end -function _AqldivB_kernel!{T<:UMFVTypes}(X::StridedMatrix{T}, lu::UmfpackLU{T}, - B::StridedMatrix{T}, transposeoptype) +function _AqldivB_kernel!(X::StridedMatrix{T}, lu::UmfpackLU{T}, + B::StridedMatrix{T}, transposeoptype) where T<:UMFVTypes for col in 1:size(X, 2) solve!(view(X, :, col), lu, view(B, :, col), transposeoptype) end end -function _AqldivB_kernel!{Tb<:Complex}(x::StridedVector{Tb}, lu::UmfpackLU{Float64}, - b::StridedVector{Tb}, transposeoptype) +function _AqldivB_kernel!(x::StridedVector{Tb}, lu::UmfpackLU{Float64}, + b::StridedVector{Tb}, transposeoptype) where Tb<:Complex r, i = similar(b, Float64), similar(b, Float64) solve!(r, lu, Vector{Float64}(real(b)), transposeoptype) solve!(i, lu, Vector{Float64}(imag(b)), transposeoptype) map!(complex, x, r, i) end -function _AqldivB_kernel!{Tb<:Complex}(X::StridedMatrix{Tb}, lu::UmfpackLU{Float64}, - B::StridedMatrix{Tb}, transposeoptype) +function _AqldivB_kernel!(X::StridedMatrix{Tb}, lu::UmfpackLU{Float64}, + B::StridedMatrix{Tb}, transposeoptype) where Tb<:Complex r = similar(B, Float64, size(B, 1)) i = similar(B, Float64, size(B, 1)) for j in 1:size(B, 2) diff --git a/base/special/trig.jl b/base/special/trig.jl index 4e19371b65931..49224a222a64b 100644 --- a/base/special/trig.jl +++ b/base/special/trig.jl @@ -326,10 +326,10 @@ for (tfa, tfainv, hfa, hfainv, fn) in ((:asec, :acos, :asech, :acosh, "secant"), @eval begin @doc """ $($tname)(x) - Compute the inverse $($fn) of `x`, where the output is in radians. """ ($tfa){T<:Number}(y::T) = ($tfainv)(one(T) / y) + Compute the inverse $($fn) of `x`, where the output is in radians. """ ($tfa)(y::T) where {T<:Number} = ($tfainv)(one(T) / y) @doc """ $($hname)(x) - Compute the inverse hyperbolic $($fn) of `x`. """ ($hfa){T<:Number}(y::T) = ($hfainv)(one(T) / y) + Compute the inverse hyperbolic $($fn) of `x`. """ ($hfa)(y::T) where {T<:Number} = ($hfainv)(one(T) / y) end end diff --git a/base/statistics.jl b/base/statistics.jl index 0eff0d321f4c5..6e9f9dfc42ee7 100644 --- a/base/statistics.jl +++ b/base/statistics.jl @@ -602,7 +602,7 @@ function median!(v::AbstractVector) end end median!(v::AbstractArray) = median!(vec(v)) -median{T}(v::AbstractArray{T}) = median!(copy!(Array{T,1}(_length(v)), v)) +median(v::AbstractArray{T}) where {T} = median!(copy!(Array{T,1}(_length(v)), v)) """ median(v[, region]) diff --git a/base/twiceprecision.jl b/base/twiceprecision.jl index 38f027013e3da..3cfc2b89854b5 100644 --- a/base/twiceprecision.jl +++ b/base/twiceprecision.jl @@ -462,7 +462,7 @@ function +(x::TwicePrecision{T}, y::TwicePrecision{T}) where T TwicePrecision(r, s) end +(x::TwicePrecision, y::TwicePrecision) = _add2(promote(x, y)...) -_add2{T<:TwicePrecision}(x::T, y::T) = x + y +_add2(x::T, y::T) where {T<:TwicePrecision} = x + y _add2(x::TwicePrecision, y::TwicePrecision) = TwicePrecision(x.hi+y.hi, x.lo+y.lo) function *(x::TwicePrecision, v::Integer) diff --git a/base/util.jl b/base/util.jl index 66972107def5b..187bc416c4ba3 100644 --- a/base/util.jl +++ b/base/util.jl @@ -638,7 +638,7 @@ will always be called. function securezero! end @noinline securezero!(a::AbstractArray{<:Number}) = fill!(a, 0) securezero!(s::String) = unsafe_securezero!(pointer(s), sizeof(s)) -@noinline unsafe_securezero!{T}(p::Ptr{T}, len::Integer=1) = +@noinline unsafe_securezero!(p::Ptr{T}, len::Integer=1) where T = ccall(:memset, Ptr{T}, (Ptr{T}, Cint, Csize_t), p, 0, len*sizeof(T)) unsafe_securezero!(p::Ptr{Void}, len::Integer=1) = Ptr{Void}(unsafe_securezero!(Ptr{UInt8}(p), len)) diff --git a/base/weakkeydict.jl b/base/weakkeydict.jl index 9c1c5279553d0..1097eba93e770 100644 --- a/base/weakkeydict.jl +++ b/base/weakkeydict.jl @@ -48,10 +48,10 @@ WeakKeyDict() = WeakKeyDict{Any,Any}() WeakKeyDict(kv::Tuple{}) = WeakKeyDict() copy(d::WeakKeyDict) = WeakKeyDict(d) -WeakKeyDict{K,V}(ps::Pair{K,V}...) = WeakKeyDict{K,V}(ps) -WeakKeyDict{K }(ps::Pair{K}...,) = WeakKeyDict{K,Any}(ps) -WeakKeyDict{V }(ps::(Pair{K,V} where K)...,) = WeakKeyDict{Any,V}(ps) -WeakKeyDict( ps::Pair...) = WeakKeyDict{Any,Any}(ps) +WeakKeyDict(ps::Pair{K,V}...) where {K,V} = WeakKeyDict{K,V}(ps) +WeakKeyDict(ps::Pair{K}...) where {K } = WeakKeyDict{K,Any}(ps) +WeakKeyDict(ps::(Pair{K,V} where K)...) where {V } = WeakKeyDict{Any,V}(ps) +WeakKeyDict(ps::Pair...) = WeakKeyDict{Any,Any}(ps) function WeakKeyDict(kv) try @@ -110,7 +110,7 @@ get!(wkh::WeakKeyDict{K}, key, default) where {K} = lock(() -> get!(wkh.ht, key, get!(default::Callable, wkh::WeakKeyDict{K}, key) where {K} = lock(() -> get!(default, wkh.ht, key), wkh) pop!(wkh::WeakKeyDict{K}, key) where {K} = lock(() -> pop!(wkh.ht, key), wkh) pop!(wkh::WeakKeyDict{K}, key, default) where {K} = lock(() -> pop!(wkh.ht, key, default), wkh) -delete!{K}(wkh::WeakKeyDict{K}, key) = lock(() -> delete!(wkh.ht, key), wkh) +delete!(wkh::WeakKeyDict, key) = lock(() -> delete!(wkh.ht, key), wkh) empty!(wkh::WeakKeyDict) = (lock(() -> empty!(wkh.ht), wkh); wkh) haskey(wkh::WeakKeyDict{K}, key) where {K} = lock(() -> haskey(wkh.ht, key), wkh) getindex(wkh::WeakKeyDict{K}, key) where {K} = lock(() -> getindex(wkh.ht, key), wkh) diff --git a/doc/src/devdocs/functions.md b/doc/src/devdocs/functions.md index 456f09b218056..f693d692f9499 100644 --- a/doc/src/devdocs/functions.md +++ b/doc/src/devdocs/functions.md @@ -98,7 +98,7 @@ table for `DataType` contains most constructor definitions. One wrinkle is the f that makes all types callable via `convert`: ```julia -(::Type{T}){T}(args...) = convert(T, args...)::T +(::Type{T})(args...) where {T} = convert(T, args...)::T ``` In this definition the function type is abstract, which is not normally supported. To make this diff --git a/doc/src/manual/interacting-with-julia.md b/doc/src/manual/interacting-with-julia.md index a939e62aa68e6..7cd36431a3328 100644 --- a/doc/src/manual/interacting-with-julia.md +++ b/doc/src/manual/interacting-with-julia.md @@ -286,8 +286,8 @@ and `keep` are keyword arguments: ```julia-repl julia> split("1 1 1", [TAB] -split(str::AbstractString) in Base at strings/util.jl:278 -split{T<:AbstractString}(str::T, splitter; limit, keep) in Base at strings/util.jl:254 +split(str::AbstractString) in Base at strings/util.jl:302 +split(str::T, splitter; limit, keep) where T<:AbstractString in Base at strings/util.jl:277 ``` The completion of the methods uses type inference and can therefore see if the arguments match diff --git a/doc/src/manual/performance-tips.md b/doc/src/manual/performance-tips.md index 92fd3bc55aa30..d171cbf67c332 100644 --- a/doc/src/manual/performance-tips.md +++ b/doc/src/manual/performance-tips.md @@ -409,7 +409,7 @@ myfunc (generic function with 3 methods) Because we can only define `MyContainer` for `A<:AbstractArray`, and any unspecified parameters are arbitrary, the first function above could have been written more succinctly as - `function myfunc{T<:Integer}(c::MyContainer{T})` + `function myfunc(c::MyContainer{<:Integer})` ```jldoctest containers2 diff --git a/doc/src/stdlib/sort.md b/doc/src/stdlib/sort.md index 3397d772bdda8..65bfd0e70bbc9 100644 --- a/doc/src/stdlib/sort.md +++ b/doc/src/stdlib/sort.md @@ -178,7 +178,7 @@ for specific arrays. For example, here are the two default methods from [`sort.j ```julia defalg(v::AbstractArray) = MergeSort -defalg{T<:Number}(v::AbstractArray{T}) = QuickSort +defalg(v::AbstractArray{<:Number}) = QuickSort ``` As for numeric arrays, choosing a non-stable default algorithm for array types for which the notion From e9b73ec18c6bb5ef2b8d552461368355996bd194 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=82=B9=E3=83=8E=E3=83=AB?= Date: Tue, 6 Jun 2017 08:13:41 +0800 Subject: [PATCH 1001/1534] fix #22168, `im*I+I` should be shown as `(1+1im)*I` (#22169) * fix #22168, `im*I+I` should be shown as `(1+1im)*I` * add test for `show(UniformScaling)` * check the number of terms in `show(::UniformScaling)` * fix the misuse of `|` --- base/linalg/uniformscaling.jl | 8 +++++++- test/linalg/uniformscaling.jl | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/base/linalg/uniformscaling.jl b/base/linalg/uniformscaling.jl index 81a3ee1e6b29c..bbb1dfa46e793 100644 --- a/base/linalg/uniformscaling.jl +++ b/base/linalg/uniformscaling.jl @@ -31,7 +31,13 @@ eltype(::Type{UniformScaling{T}}) where {T} = T ndims(J::UniformScaling) = 2 getindex(J::UniformScaling, i::Integer,j::Integer) = ifelse(i==j,J.λ,zero(J.λ)) -show(io::IO, J::UniformScaling) = print(io, "$(typeof(J))\n$(J.λ)*I") +function show(io::IO, J::UniformScaling) + s = "$(J.λ)" + if ismatch(r"\w+\s*[\+\-]\s*\w+", s) + s = "($s)" + end + print(io, "$(typeof(J))\n$s*I") +end copy(J::UniformScaling) = UniformScaling(J.λ) transpose(J::UniformScaling) = J diff --git a/test/linalg/uniformscaling.jl b/test/linalg/uniformscaling.jl index 4049a44f79284..f61bdef3f4dad 100644 --- a/test/linalg/uniformscaling.jl +++ b/test/linalg/uniformscaling.jl @@ -38,6 +38,7 @@ end end @test copy(UniformScaling(one(Float64))) == UniformScaling(one(Float64)) +@test sprint(show,UniformScaling(one(Complex128))) == "UniformScaling{Complex{Float64}}\n(1.0 + 0.0im)*I" @test sprint(show,UniformScaling(one(Float32))) == "UniformScaling{Float32}\n1.0*I" λ = complex(randn(),randn()) From 5aa15ffe248457245db57cd6edc8f06b9d4d04f6 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Mon, 5 Jun 2017 18:21:30 -0700 Subject: [PATCH 1002/1534] Use libgcc dlls from build system compiler (#22197) instead of opensuse --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 90b566fc828ed..e30685efe3f9b 100644 --- a/Makefile +++ b/Makefile @@ -461,7 +461,7 @@ endif ifeq ($(OS), WINNT) [ ! -d $(JULIAHOME)/dist-extras ] || ( cd $(JULIAHOME)/dist-extras && \ - cp 7z.exe 7z.dll libexpat-1.dll zlib1.dll libgfortran-3.dll libquadmath-0.dll libstdc++-6.dll libgcc_s_s*-1.dll libssp-0.dll libwinpthread-1.dll $(BUILDROOT)/julia-$(JULIA_COMMIT)/bin ) + cp 7z.exe 7z.dll libexpat-1.dll zlib1.dll $(BUILDROOT)/julia-$(JULIA_COMMIT)/bin ) ifeq ($(USE_GPL_LIBS), 1) [ ! -d $(JULIAHOME)/dist-extras ] || ( cd $(JULIAHOME)/dist-extras && \ cp busybox.exe $(BUILDROOT)/julia-$(JULIA_COMMIT)/bin ) @@ -592,7 +592,7 @@ ifneq (,$(filter $(ARCH), i386 i486 i586 i686)) $(JLDOWNLOAD) http://downloads.sourceforge.net/sevenzip/7z920.exe && \ 7z x -y 7z920.exe 7z.exe 7z.dll && \ ../contrib/windows/winrpm.sh http://download.opensuse.org/repositories/windows:/mingw:/win32/openSUSE_Leap_42.2 \ - "mingw32-libgfortran3 mingw32-libquadmath0 mingw32-libstdc++6 mingw32-libgcc_s_sjlj1 mingw32-libssp0 mingw32-libwinpthread1 mingw32-libexpat1 mingw32-zlib1" && \ + "mingw32-libexpat1 mingw32-zlib1" && \ cp usr/i686-w64-mingw32/sys-root/mingw/bin/*.dll . else ifeq ($(ARCH),x86_64) cd $(JULIAHOME)/dist-extras && \ @@ -601,7 +601,7 @@ else ifeq ($(ARCH),x86_64) mv _7z.dll 7z.dll && \ mv _7z.exe 7z.exe && \ ../contrib/windows/winrpm.sh http://download.opensuse.org/repositories/windows:/mingw:/win64/openSUSE_Leap_42.2 \ - "mingw64-libgfortran3 mingw64-libquadmath0 mingw64-libstdc++6 mingw64-libgcc_s_seh1 mingw64-libssp0 mingw64-libwinpthread1 mingw64-libexpat1 mingw64-zlib1" && \ + "mingw64-libexpat1 mingw64-zlib1" && \ cp usr/x86_64-w64-mingw32/sys-root/mingw/bin/*.dll . else $(error no win-extras target for ARCH=$(ARCH)) From 3c3ced4153cdc2c75319b41155c38ad1f2545fc2 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 10 May 2017 15:57:32 -0400 Subject: [PATCH 1003/1534] replace current_module() with @__MODULE__ passes macros a __module__ argument, like the __source__ argument, allowing them to inspect and configure themselves based on their evaluation context remove current_module dependence from `include`: instead, we use the same trick as for `eval` (they are basically the same function after all) to create a module-relative function in each non-bare module now puts Module in MethodInstance.def for toplevel thunks to make it convenient to pass around this contextual information --- NEWS.md | 5 + base/Enums.jl | 18 +- base/REPLCompletions.jl | 10 +- base/boot.jl | 8 +- base/client.jl | 22 +- base/coreimg.jl | 6 +- base/deprecated.jl | 49 ++- base/docs/Docs.jl | 89 +++--- base/docs/bindings.jl | 2 +- base/docs/core.jl | 14 +- base/docs/helpdb/Base.jl | 5 +- base/docs/utils.jl | 8 +- base/essentials.jl | 11 +- base/exports.jl | 3 +- base/expr.jl | 26 +- base/inference.jl | 41 +-- base/int.jl | 2 +- base/interactiveutil.jl | 37 ++- base/loading.jl | 44 +-- base/markdown/Markdown.jl | 12 +- base/operators.jl | 2 +- base/osutils.jl | 7 +- base/precompile.jl | 6 +- base/reflection.jl | 31 +- base/serialize.jl | 12 +- base/show.jl | 33 +- base/stacktraces.jl | 5 +- base/sysimg.jl | 48 ++- base/test.jl | 2 +- base/util.jl | 9 +- doc/src/devdocs/ast.md | 4 +- doc/src/manual/calling-c-and-fortran-code.md | 18 +- doc/src/manual/metaprogramming.md | 13 +- doc/src/manual/modules.md | 4 +- doc/src/manual/parallel-computing.md | 4 +- doc/src/stdlib/base.md | 3 +- src/ast.c | 114 +++---- src/builtins.c | 12 +- src/ccall.cpp | 6 +- src/cgutils.cpp | 6 +- src/codegen.cpp | 133 ++++---- src/datatype.c | 40 ++- src/dump.c | 28 +- src/gf.c | 73 ++--- src/init.c | 10 +- src/interpreter.c | 67 ++-- src/jlapi.c | 2 +- src/jlfrontend.scm | 30 +- src/jltypes.c | 315 ++++++++++--------- src/julia-syntax.scm | 1 + src/julia.h | 37 ++- src/julia_internal.h | 33 +- src/method.c | 77 ++--- src/module.c | 9 +- src/rtutils.c | 12 +- src/task.c | 1 + src/toplevel.c | 126 ++++---- test/broadcast.jl | 12 +- test/cmdlineargs.jl | 4 +- test/core.jl | 28 +- test/distributed_exec.jl | 2 +- test/docs.jl | 13 +- test/fastmath.jl | 12 +- test/inline.jl | 4 +- test/loading.jl | 4 +- test/misc.jl | 4 +- test/parse.jl | 79 ++--- test/reflection.jl | 57 ++-- test/repl.jl | 2 +- test/replutil.jl | 8 +- test/stacktraces.jl | 3 +- test/strings/basic.jl | 2 +- test/testenv.jl | 4 +- test/threads.jl | 12 +- test/workspace.jl | 30 +- ui/repl.c | 2 +- 76 files changed, 1106 insertions(+), 921 deletions(-) diff --git a/NEWS.md b/NEWS.md index 8b3cd9626662d..849dda108f0fb 100644 --- a/NEWS.md +++ b/NEWS.md @@ -73,6 +73,11 @@ Deprecated or removed * The `cholfact`/`cholfact!` methods that accepted an `uplo` symbol have been deprecated in favor of using `Hermitian` (or `Symmetric`) views ([#22187], [#22188]). + * The function `current_module` is deprecated and replaced with `@__MODULE__` ([#22064]). + This caused the deprecation of some reflection methods (such as `macroexpand` and `isconst`), + which now require a module argument. + And it caused the bugfix of other default arguments to use the Main module (including `whos`, `which`). + Julia v0.6.0 Release Notes ========================== diff --git a/base/Enums.jl b/base/Enums.jl index 13976a72d8e5f..ea58302001046 100644 --- a/base/Enums.jl +++ b/base/Enums.jl @@ -49,19 +49,19 @@ julia> f(apple) Member values can be converted between the enum type and `BaseType`. `read` and `write` perform these conversions automatically. """ -macro enum(T,syms...) +macro enum(T, syms...) if isempty(syms) throw(ArgumentError("no arguments given for Enum $T")) end basetype = Int32 typename = T - if isa(T,Expr) && T.head == :(::) && length(T.args) == 2 && isa(T.args[1], Symbol) + if isa(T, Expr) && T.head == :(::) && length(T.args) == 2 && isa(T.args[1], Symbol) typename = T.args[1] - basetype = eval(current_module(),T.args[2]) + basetype = eval(__module__, T.args[2]) if !isa(basetype, DataType) || !(basetype <: Integer) || !isbits(basetype) throw(ArgumentError("invalid base type for Enum $typename, $T=::$basetype; base type must be an integer primitive type")) end - elseif !isa(T,Symbol) + elseif !isa(T, Symbol) throw(ArgumentError("invalid type expression for enum $T")) end vals = Vector{Tuple{Symbol,Integer}}(0) @@ -69,14 +69,14 @@ macro enum(T,syms...) i = zero(basetype) hasexpr = false for s in syms - if isa(s,Symbol) + if isa(s, Symbol) if i == typemin(basetype) && !isempty(vals) throw(ArgumentError("overflow in value \"$s\" of Enum $typename")) end - elseif isa(s,Expr) && + elseif isa(s, Expr) && (s.head == :(=) || s.head == :kw) && - length(s.args) == 2 && isa(s.args[1],Symbol) - i = eval(current_module(),s.args[2]) # allow exprs, e.g. uint128"1" + length(s.args) == 2 && isa(s.args[1], Symbol) + i = eval(__module__, s.args[2]) # allow exprs, e.g. uint128"1" if !isa(i, Integer) throw(ArgumentError("invalid value for Enum $typename, $s=$i; values must be integers")) end @@ -144,7 +144,7 @@ macro enum(T,syms...) end end end - if isa(typename,Symbol) + if isa(typename, Symbol) for (sym,i) in vals push!(blk.args, :(const $(esc(sym)) = $(esc(typename))($i))) end diff --git a/base/REPLCompletions.jl b/base/REPLCompletions.jl index d58aebe5f9832..2ba4b24a4c446 100644 --- a/base/REPLCompletions.jl +++ b/base/REPLCompletions.jl @@ -292,9 +292,10 @@ function get_type_call(expr::Expr) return_type === nothing && return (Any, false) return (return_type, true) end -# Returns the return type. example: get_type(:(Base.strip("",' ')),Main) returns (String,true) -function get_type(sym::Expr, fn) - sym=expand(sym) + +# Returns the return type. example: get_type(:(Base.strip("", ' ')), Main) returns (String, true) +function get_type(sym::Expr, fn::Module) + sym = expand(fn, sym) val, found = get_value(sym, fn) found && return Base.typesof(val).parameters[1], found if sym.head === :call @@ -310,10 +311,11 @@ function get_type(sym::Expr, fn) end return (Any, false) end -function get_type(sym, fn) +function get_type(sym, fn::Module) val, found = get_value(sym, fn) return found ? Base.typesof(val).parameters[1] : Any, found end + # Method completion on function call expression that look like :(max(1)) function complete_methods(ex_org::Expr) args_ex = Any[] diff --git a/base/boot.jl b/base/boot.jl index 23e803b81fe06..31255bea909a5 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -230,7 +230,7 @@ String(s::String) = s # no constructor yet # This should always be inlined getptls() = ccall(:jl_get_ptls_states, Ptr{Void}, ()) -include(fname::String) = ccall(:jl_load_, Any, (Any,), fname) +include(m::Module, fname::String) = ccall(:jl_load_, Any, (Any, Any), m, fname) eval(e::ANY) = eval(Main, e) eval(m::Module, e::ANY) = ccall(:jl_toplevel_eval_in, Any, (Any, Any), m, e) @@ -337,7 +337,7 @@ end # docsystem basics macro doc(x...) - atdoc(__source__, x...) + atdoc(__source__, __module__, x...) end macro __doc__(x) Expr(:escape, Expr(:block, Expr(:meta, :doc), x)) @@ -345,7 +345,7 @@ end macro doc_str(s) Expr(:escape, s) end -atdoc = (source, str, expr) -> Expr(:escape, expr) +atdoc = (source, mod, str, expr) -> Expr(:escape, expr) atdoc!(λ) = global atdoc = λ @@ -382,4 +382,4 @@ show(a::ANY) = show(STDOUT, a) print(a::ANY...) = print(STDOUT, a...) println(a::ANY...) = println(STDOUT, a...) -ccall(:jl_set_istopmod, Void, (Bool,), true) +ccall(:jl_set_istopmod, Void, (Any, Bool), Core, true) diff --git a/base/client.jl b/base/client.jl index 2f22a24ca6e7e..1b2f6506911a8 100644 --- a/base/client.jl +++ b/base/client.jl @@ -153,7 +153,7 @@ function eval_user_input(ast::ANY, show_value) display_error(lasterr,bt) errcount, lasterr = 0, () else - ast = expand(ast) + ast = expand(Main, ast) value = eval(Main, ast) eval(Main, Expr(:body, Expr(:(=), :ans, QuoteNode(value)), Expr(:return, nothing))) if !(value === nothing) && show_value @@ -210,7 +210,7 @@ function parse_input_line(s::String; filename::String="none") s, sizeof(s), filename, sizeof(filename)) if ex === :_ # remove with 0.6 deprecation - expand(ex) # to get possible warning about using _ as an rvalue + expand(Main, ex) # to get possible warning about using _ as an rvalue end return ex end @@ -243,7 +243,7 @@ function incomplete_tag(ex::Expr) end # try to include() a file, ignoring if not found -try_include(path::AbstractString) = isfile(path) && include(path) +try_include(mod::Module, path::AbstractString) = isfile(path) && include(mod, path) function process_options(opts::JLOptions) if !isempty(ARGS) @@ -279,7 +279,7 @@ function process_options(opts::JLOptions) # load file immediately on all processors if opts.load != C_NULL @sync for p in procs() - @async remotecall_fetch(include, p, unsafe_string(opts.load)) + @async remotecall_fetch(include, p, Main, unsafe_string(opts.load)) end end # eval expression @@ -304,7 +304,7 @@ function process_options(opts::JLOptions) if !is_interactive ccall(:jl_exit_on_sigint, Void, (Cint,), 1) end - include(PROGRAM_FILE) + include(Main, PROGRAM_FILE) end break end @@ -315,12 +315,13 @@ end function load_juliarc() # If the user built us with a specific Base.SYSCONFDIR, check that location first for a juliarc.jl file # If it is not found, then continue on to the relative path based on JULIA_HOME - if !isempty(Base.SYSCONFDIR) && isfile(joinpath(JULIA_HOME,Base.SYSCONFDIR,"julia","juliarc.jl")) - include(abspath(JULIA_HOME,Base.SYSCONFDIR,"julia","juliarc.jl")) + if !isempty(Base.SYSCONFDIR) && isfile(joinpath(JULIA_HOME, Base.SYSCONFDIR, "julia", "juliarc.jl")) + include(Main, abspath(JULIA_HOME, Base.SYSCONFDIR, "julia", "juliarc.jl")) else - try_include(abspath(JULIA_HOME,"..","etc","julia","juliarc.jl")) + try_include(Main, abspath(JULIA_HOME, "..", "etc", "julia", "juliarc.jl")) end - try_include(abspath(homedir(),".juliarc.jl")) + try_include(Main, abspath(homedir(), ".juliarc.jl")) + nothing end function load_machine_file(path::AbstractString) @@ -363,12 +364,13 @@ function __atreplinit(repl) end end end -_atreplinit(repl) = @eval Main $__atreplinit($repl) +_atreplinit(repl) = invokelatest(__atreplinit, repl) function _start() empty!(ARGS) append!(ARGS, Core.ARGS) opts = JLOptions() + @eval Main include(x) = $include(Main, x) try (quiet,repl,startup,color_set,history_file) = process_options(opts) diff --git a/base/coreimg.jl b/base/coreimg.jl index 8b552d51252e7..5739e8136084f 100644 --- a/base/coreimg.jl +++ b/base/coreimg.jl @@ -4,12 +4,14 @@ Main.Core.eval(Main.Core, :(baremodule Inference using Core.Intrinsics import Core: print, println, show, write, unsafe_write, STDOUT, STDERR -ccall(:jl_set_istopmod, Void, (Bool,), false) +ccall(:jl_set_istopmod, Void, (Any, Bool), Inference, false) eval(x) = Core.eval(Inference, x) eval(m, x) = Core.eval(m, x) -const include = Core.include +include(x) = Core.include(Inference, x) +include(mod, x) = Core.include(mod, x) + # conditional to allow redefining Core.Inference after base exists isdefined(Main, :Base) || ((::Type{T})(arg) where {T} = convert(T, arg)::T) diff --git a/base/deprecated.jl b/base/deprecated.jl index 0038126797536..062456c7146b4 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -103,14 +103,13 @@ function firstcaller(bt::Array{Ptr{Void},1}, funcsyms) return lkup end -deprecate(s::Symbol) = deprecate(current_module(), s) deprecate(m::Module, s::Symbol) = ccall(:jl_deprecate_binding, Void, (Any, Any), m, s) macro deprecate_binding(old, new, export_old=true) - Expr(:toplevel, + return Expr(:toplevel, export_old ? Expr(:export, esc(old)) : nothing, Expr(:const, Expr(:(=), esc(old), esc(new))), - Expr(:call, :deprecate, Expr(:quote, old))) + Expr(:call, :deprecate, __module__, Expr(:quote, old))) end # BEGIN 0.6-alpha deprecations (delete when 0.6 is released) @@ -630,7 +629,7 @@ for (Bsig, A1sig, A2sig, gbb, funcname) in func = @get! cache f gen_broadcast_function_sparse($gbb, f, ($A1sig) <: SparseMatrixCSC) # need eval because func was just created by gen_broadcast_function_sparse # TODO: convert this to a generated function - eval(current_module(), Expr(:body, Expr(:return, Expr(:call, QuoteNode(func), QuoteNode(B), QuoteNode(A1), QuoteNode(A2))))) + eval(_current_module(), Expr(:body, Expr(:return, Expr(:call, QuoteNode(func), QuoteNode(B), QuoteNode(A1), QuoteNode(A2))))) return B end end # let broadcast_cache @@ -1362,6 +1361,48 @@ end @deprecate cholfact!(A::StridedMatrix, uplo::Symbol, ::Type{Val{true}}; tol = 0.0) cholfact!(Hermitian(A, uplo), Val{true}, tol = tol) @deprecate cholfact(A::StridedMatrix, uplo::Symbol, ::Type{Val{true}}; tol = 0.0) cholfact(Hermitian(A, uplo), Val{true}, tol = tol) +# also remove all support machinery in src for current_module when removing this deprecation +# and make Base.include an error +_current_module() = ccall(:jl_get_current_module, Ref{Module}, ()) +@noinline function binding_module(s::Symbol) + depwarn("binding_module(symbol) is deprecated, use `binding_module(module, symbol)` instead.", :binding_module) + return binding_module(_current_module(), s) +end +@noinline function expand(x::ANY) + depwarn("expand(x) is deprecated, use `expand(module, x)` instead.", :expand) + return expand(_current_module(), x) +end +@noinline function macroexpand(x::ANY) + depwarn("macroexpand(x) is deprecated, use `macroexpand(module, x)` instead.", :macroexpand) + return macroexpand(_current_module(), x) +end +@noinline function isconst(s::Symbol) + depwarn("isconst(symbol) is deprecated, use `isconst(module, symbol)` instead.", :isconst) + return isconst(_current_module(), s) +end +@noinline function include_string(txt::AbstractString, fname::AbstractString) + depwarn("include_string(string, fname) is deprecated, use `include_string(module, string, fname)` instead.", :include_string) + return include_string(_current_module(), txt, fname) +end +@noinline function include_string(txt::AbstractString) + depwarn("include_string(string) is deprecated, use `include_string(module, string)` instead.", :include_string) + return include_string(_current_module(), txt, "string") +end + +""" + current_module() -> Module + +Get the *dynamically* current `Module`, which is the `Module` code is currently being read +from. In general, this is not the same as the module containing the call to this function. + +DEPRECATED: use @__MODULE__ instead +""" +@noinline function current_module() + depwarn("current_module() is deprecated, use `@__MODULE__` instead.", :current_module) + return _current_module() +end +export current_module + # END 0.7 deprecations # BEGIN 1.0 deprecations diff --git a/base/docs/Docs.jl b/base/docs/Docs.jl index 742635d2386b4..4ea4867bda60a 100644 --- a/base/docs/Docs.jl +++ b/base/docs/Docs.jl @@ -72,9 +72,9 @@ export doc const modules = Module[] const META = gensym(:meta) -meta(m::Module = current_module()) = isdefined(m, META) ? getfield(m, META) : ObjectIdDict() +meta(m::Module) = isdefined(m, META) ? getfield(m, META) : ObjectIdDict() -function initmeta(m::Module = current_module()) +function initmeta(m::Module) if !isdefined(m, META) eval(m, :(const $META = $(ObjectIdDict()))) push!(modules, m) @@ -169,10 +169,10 @@ _docstr(doc::DocStr, data) = (doc.data = merge(data, doc.data); doc) macro ref(x) binding = bindingexpr(namify(x)) typesig = signature(x) - esc(docexpr(__source__, binding, typesig)) + esc(docexpr(__source__, __module__, binding, typesig)) end -docexpr(__source__, args...) = Expr(:call, docstr, args...) +docexpr(__source__, __module__, args...) = Expr(:call, docstr, args...) function formatdoc(d::DocStr) buffer = IOBuffer() @@ -225,18 +225,17 @@ end # ======================= """ - Docs.doc!(binding, str, sig) + Docs.doc!(__module__, binding, str, sig) -Adds a new docstring `str` to the docsystem for `binding` and signature `sig`. +Adds a new docstring `str` to the docsystem of `__module__` for `binding` and signature `sig`. """ -function doc!(b::Binding, str::DocStr, sig::ANY = Union{}) - initmeta() - m = get!(meta(), b, MultiDoc()) +function doc!(__module__::Module, b::Binding, str::DocStr, sig::ANY = Union{}) + initmeta(__module__) + m = get!(meta(__module__), b, MultiDoc()) if haskey(m.docs, sig) # We allow for docstrings to be updated, but print a warning since it is possible # that over-writing a docstring *may* have been accidental. - s = "replacing docs for '$b :: $sig' in module '$(current_module())'." - isdefined(Base, :STDERR) ? warn(s) : ccall(:jl_, Void, (Any,), "WARNING: $s") + warn("replacing docs for '$b :: $sig' in module '$(__module__)'.") else # The ordering of docstrings for each Binding is defined by the order in which they # are initially added. Replacing a specific docstring does not change it's ordering. @@ -482,7 +481,7 @@ isfield(x) = isexpr(x, :.) && # ========================= """ - Docs.metadata(source, expr) + Docs.metadata(source, module, expr, ismodule) Build a `Dict` expression containing metadata captured from the expression `expr`. @@ -493,14 +492,18 @@ Fields that may be included in the returned `Dict`: - `:module`: Module where the docstring is defined. - `:fields`: `Dict` of all field docs found in `expr`. Only for concrete types. """ -function metadata(__source__, expr) +function metadata(__source__, __module__, expr, ismodule) args = [] # Filename and linenumber of the docstring. __file__ = isa(__source__.file, Symbol) ? String(__source__.file) : "" push!(args, Pair(:path, __file__)) push!(args, Pair(:linenumber, __source__.line)) # Module in which the docstring is defined. - push!(args, :($(Pair)(:module, $(current_module)()))) + if ismodule # Module docs go inside the module with name `expr` + push!(args, :($Pair(:module, $expr))) + else + push!(args, Pair(:module, __module__)) + end if isexpr(expr, :type) # Field docs for concrete types. fields = [] @@ -519,34 +522,34 @@ function metadata(__source__, expr) :($(Dict)($(args...))) end -function keyworddoc(__source__, str, def) - docstr = esc(docexpr(__source__, lazy_iterpolate(str), metadata(__source__, def))) +function keyworddoc(__source__, __module__, str, def) + docstr = esc(docexpr(__source__, __module__, lazy_iterpolate(str), metadata(__source__, __module__, def, false))) return :($(keywords)[$(esc(quot(def.name)))] = $docstr) end -function objectdoc(__source__, str, def, expr, sig = :(Union{})) +function objectdoc(__source__, __module__, str, def, expr, sig = :(Union{})) binding = esc(bindingexpr(namify(expr))) - docstr = esc(docexpr(__source__, lazy_iterpolate(str), metadata(__source__, expr))) + docstr = esc(docexpr(__source__, __module__, lazy_iterpolate(str), metadata(__source__, __module__, expr, false))) quote $(esc(def)) - $(doc!)($binding, $docstr, $(esc(sig))) + $(doc!)($__module__, $binding, $docstr, $(esc(sig))) end end -function calldoc(__source__, str, def) +function calldoc(__source__, __module__, str, def) args = def.args[2:end] if isempty(args) || all(validcall, args) - objectdoc(__source__, str, nothing, def, signature(def)) + objectdoc(__source__, __module__, str, nothing, def, signature(def)) else docerror(def) end end validcall(x) = isa(x, Symbol) || isexpr(x, (:(::), :..., :kw, :parameters)) -function moduledoc(__source__, meta, def, def′) +function moduledoc(__source__, __module__, meta, def, def′) name = namify(def′) - docex = Expr(:call, doc!, bindingexpr(name), - docexpr(__source__, lazy_iterpolate(meta), metadata(__source__, name))) + docex = Expr(:call, doc!, name, bindingexpr(name), + docexpr(__source__, name, lazy_iterpolate(meta), metadata(__source__, __module__, name, true))) if def === nothing esc(:($eval($name, $(quot(docex))))) else @@ -562,16 +565,16 @@ function moduledoc(__source__, meta, def, def′) end # Shares a single doc, `meta`, between several expressions from the tuple expression `ex`. -function multidoc(__source__, meta, ex, define) +function multidoc(__source__, __module__, meta, ex, define) out = Expr(:toplevel) - str = docexpr(__source__, lazy_iterpolate(meta), metadata(__source__, ex)) + str = docexpr(__source__, __module__, lazy_iterpolate(meta), metadata(__source__, __module__, ex, false)) ref = Ref{DocStr}() for (n, arg) in enumerate(ex.args) # The first `arg` to be documented needs to also create the docstring for the group. # Subsequent `arg`s just need `ref` to be able to find the docstring without having # to create an entirely new one each. docstr = n === 1 ? :($(ref)[] = $str) : :($(ref)[]) - push!(out.args, docm(__source__, docstr, arg, define)) + push!(out.args, docm(__source__, __module__, docstr, arg, define)) end return out end @@ -649,14 +652,14 @@ isquotedmacrocall(x) = isbasicdoc(x) = isexpr(x, :.) || isa(x, Union{QuoteNode, Symbol}) is_signature(x) = isexpr(x, :call) || (isexpr(x, :(::), 2) && isexpr(x.args[1], :call)) || isexpr(x, :where) -function docm(source::LineNumberNode, meta, ex, define = true) +function docm(source::LineNumberNode, mod::Module, meta, ex, define = true) # Some documented expressions may be decorated with macro calls which obscure the actual # expression. Expand the macro calls and remove extra blocks. - x = unblock(macroexpand(ex)) + x = unblock(macroexpand(mod, ex)) # Don't try to redefine expressions. This is only needed for `Base` img gen since # otherwise calling `loaddocs` would redefine all documented functions and types. def = define ? x : nothing - if isa(x, GlobalRef) && (x::GlobalRef).mod == current_module() + if isa(x, GlobalRef) && (x::GlobalRef).mod == mod x = (x::GlobalRef).name end @@ -665,7 +668,7 @@ function docm(source::LineNumberNode, meta, ex, define = true) # "..." # kw"if", kw"else" # - isa(x, Base.BaseDocs.Keyword) ? keyworddoc(source, meta, x) : + isa(x, Base.BaseDocs.Keyword) ? keyworddoc(source, mod, meta, x) : # Method / macro definitions and "call" syntax. # @@ -675,9 +678,9 @@ function docm(source::LineNumberNode, meta, ex, define = true) # function f end # f(...) # - isexpr(x, FUNC_HEADS) && is_signature(x.args[1]) ? objectdoc(source, meta, def, x, signature(x)) : - isexpr(x, :function) && !isexpr(x.args[1], :call) ? objectdoc(source, meta, def, x) : - isexpr(x, :call) ? calldoc(source, meta, x) : + isexpr(x, FUNC_HEADS) && is_signature(x.args[1]) ? objectdoc(source, mod, meta, def, x, signature(x)) : + isexpr(x, :function) && !isexpr(x.args[1], :call) ? objectdoc(source, mod, meta, def, x) : + isexpr(x, :call) ? calldoc(source, mod, meta, x) : # Type definitions. # @@ -685,7 +688,7 @@ function docm(source::LineNumberNode, meta, ex, define = true) # abstract T # bitstype N T # - isexpr(x, [:type, :abstract, :bitstype]) ? objectdoc(source, meta, def, x) : + isexpr(x, [:type, :abstract, :bitstype]) ? objectdoc(source, mod, meta, def, x) : # "Bindings". Names that resolve to objects with different names, ie. # @@ -693,20 +696,20 @@ function docm(source::LineNumberNode, meta, ex, define = true) # T = S # global T = S # - isexpr(x, BINDING_HEADS) && !isexpr(x.args[1], :call) ? objectdoc(source, meta, def, x) : + isexpr(x, BINDING_HEADS) && !isexpr(x.args[1], :call) ? objectdoc(source, mod, meta, def, x) : # Quoted macrocall syntax. `:@time` / `:(Base.@time)`. - isquotedmacrocall(x) ? objectdoc(source, meta, def, x) : + isquotedmacrocall(x) ? objectdoc(source, mod, meta, def, x) : # Modules and baremodules. - isexpr(x, :module) ? moduledoc(source, meta, def, x) : + isexpr(x, :module) ? moduledoc(source, mod, meta, def, x) : # Document several expressions with the same docstring. `a, b, c`. - isexpr(x, :tuple) ? multidoc(source, meta, x, define) : + isexpr(x, :tuple) ? multidoc(source, mod, meta, x, define) : # Errors generated by calling `macroexpand` are passed back to the call site. isexpr(x, :error) ? esc(x) : # When documenting macro-generated code we look for embedded `@__doc__` calls. __doc__!(meta, x, define) ? esc(x) : # Any "basic" expression such as a bare function or module name or numeric literal. - isbasicdoc(x) ? objectdoc(source, meta, nothing, x) : + isbasicdoc(x) ? objectdoc(source, mod, meta, nothing, x) : # All other expressions are undocumentable and should be handled on a case-by-case basis # with `@__doc__`. Unbound string literals are also undocumentable since they cannot be @@ -725,9 +728,9 @@ function docerror(ex) :($(error)($txt, "\n")) end -function docm(source::LineNumberNode, ex) +function docm(source::LineNumberNode, mod::Module, ex) if isexpr(ex, :->) - docm(source, ex.args...) + docm(source, mod, ex.args...) elseif haskey(keywords, ex) parsedoc(keywords[ex]) elseif isa(ex, Union{Expr, Symbol}) @@ -764,7 +767,7 @@ function loaddocs(docs) for (mod, ex, str, file, line) in docs data = Dict(:path => string(file), :linenumber => line) doc = docstr(str, data) - docstring = eval(mod, Expr(:body, Expr(:return, Expr(:call, QuoteNode(docm), QuoteNode(LineNumberNode(line, file)), QuoteNode(doc), QuoteNode(ex), false)))) # expand the real @doc macro now (using a hack because macroexpand takes current-module as an implicit argument) + docstring = docm(LineNumberNode(line, file), mod, doc, ex, false) # expand the real @doc macro now eval(mod, Expr(:macrocall, unescape, nothing, docstring)) end empty!(docs) diff --git a/base/docs/bindings.jl b/base/docs/bindings.jl index ac7fbab7f6bfd..f0c73997c7b63 100644 --- a/base/docs/bindings.jl +++ b/base/docs/bindings.jl @@ -24,7 +24,7 @@ function splitexpr(x::Expr) isexpr(x, :.) ? (x.args[1], x.args[2]) : error("Invalid @var syntax `$x`.") end -splitexpr(s::Symbol) = Expr(:call, current_module), quot(s) +splitexpr(s::Symbol) = Expr(:macrocall, getfield(Base, Symbol("@__MODULE__")), nothing), quot(s) splitexpr(other) = error("Invalid @var syntax `$other`.") macro var(x) diff --git a/base/docs/core.jl b/base/docs/core.jl index 747afab704aa3..b096bf13173aa 100644 --- a/base/docs/core.jl +++ b/base/docs/core.jl @@ -2,10 +2,10 @@ module CoreDocs -import ..esc, ..push!, ..getindex, ..current_module, ..unsafe_load, ..Csize_t +import ..esc, ..push!, ..getindex, ..unsafe_load, ..Csize_t -function doc!(source::LineNumberNode, str, ex) - push!(DOCS, (current_module(), ex, str, source.file, source.line)) +function doc!(source::LineNumberNode, mod::Module, str, ex) + push!(DOCS, (mod, ex, str, source.file, source.line)) end const DOCS = Array{Any, 1}() @@ -14,12 +14,12 @@ isexpr(x, h) = isa(x, Expr) && x.head === h lazy_iterpolate(s::AbstractString) = Expr(:call, Core.svec, s) lazy_iterpolate(x) = isexpr(x, :string) ? Expr(:call, Core.svec, x.args...) : x -function docm(source::LineNumberNode, str, x) - out = esc(Expr(:call, doc!, QuoteNode(source), lazy_iterpolate(str), Expr(:quote, x))) +function docm(source::LineNumberNode, mod::Module, str, x) + out = esc(Expr(:call, doc!, QuoteNode(source), mod, lazy_iterpolate(str), Expr(:quote, x))) isexpr(x, :module) ? Expr(:toplevel, out, esc(x)) : isexpr(x, :call) ? out : Expr(:block, esc(x), out) end -docm(source::LineNumberNode, x) = - isexpr(x, :->) ? docm(source, x.args[1], x.args[2].args[2]) : error("invalid '@doc'.") +docm(source::LineNumberNode, mod::Module, x) = + isexpr(x, :->) ? docm(source, mod, x.args[1], x.args[2].args[2]) : error("invalid '@doc'.") end diff --git a/base/docs/helpdb/Base.jl b/base/docs/helpdb/Base.jl index a3f2530e4fef3..42239e9eb79e5 100644 --- a/base/docs/helpdb/Base.jl +++ b/base/docs/helpdb/Base.jl @@ -1286,13 +1286,12 @@ Run a command object asynchronously, returning the resulting `Process` object. spawn """ - isdefined([m::Module,] s::Symbol) + isdefined(m::Module, s::Symbol) isdefined(object, s::Symbol) isdefined(object, index::Int) Tests whether an assignable location is defined. The arguments can be a module and a symbol -or a composite object and field name (as a symbol) or index. With a single symbol argument, -tests whether a global variable with that name is defined in [`current_module()`](@ref). +or a composite object and field name (as a symbol) or index. """ isdefined diff --git a/base/docs/utils.jl b/base/docs/utils.jl index 895edf349e5be..220f5db5626ab 100644 --- a/base/docs/utils.jl +++ b/base/docs/utils.jl @@ -186,7 +186,9 @@ function repl(io::IO, s::Symbol) quote repl_latex($io, $str) repl_search($io, $str) - ($(isdefined(s) || haskey(keywords, s))) || repl_corrections($io, $str) + $(if !isdefined(Main, s) && !haskey(keywords, s) + :(repl_corrections($io, $str)) + end) $(_repl(s)) end end @@ -336,7 +338,7 @@ end print_joined_cols(args...; cols = displaysize(STDOUT)[2]) = print_joined_cols(STDOUT, args...; cols=cols) function print_correction(io, word) - cors = levsort(word, accessible(current_module())) + cors = levsort(word, accessible(Main)) pre = "Perhaps you meant " print(io, pre) print_joined_cols(io, cors, ", ", " or "; cols = displaysize(io)[2] - length(pre)) @@ -364,7 +366,7 @@ accessible(mod::Module) = map(names, moduleusings(mod))...; builtins] |> unique |> filtervalid -completions(name) = fuzzysort(name, accessible(current_module())) +completions(name) = fuzzysort(name, accessible(Main)) completions(name::Symbol) = completions(string(name)) diff --git a/base/essentials.jl b/base/essentials.jl index 73bccc405f956..d16e1ed107204 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -34,15 +34,6 @@ convert(::Type{Tuple{Vararg{T}}}, x::Tuple) where {T} = cnvt_all(T, x...) cnvt_all(T) = () cnvt_all(T, x, rest...) = tuple(convert(T,x), cnvt_all(T, rest...)...) -macro generated(f) - if isa(f, Expr) && (f.head === :function || is_short_function_def(f)) - f.head = :stagedfunction - return Expr(:escape, f) - else - error("invalid syntax; @generated must be used with a function definition") - end -end - """ @eval [mod,] ex @@ -50,7 +41,7 @@ Evaluate an expression with values interpolated into it using `eval`. If two arguments are provided, the first is the module to evaluate in. """ macro eval(ex) - :(eval($(current_module()), $(Expr(:quote,ex)))) + :(eval($__module__, $(Expr(:quote,ex)))) end macro eval(mod, ex) :(eval($(esc(mod)), $(Expr(:quote,ex)))) diff --git a/base/exports.jl b/base/exports.jl index b9bd9ecebe427..d88133ca324d7 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -1005,7 +1005,6 @@ export # help and reflection apropos, - current_module, edit, code_typed, code_warntype, @@ -1027,6 +1026,7 @@ export which, whos, workspace, + @isdefined, # loading source files __precompile__, @@ -1250,6 +1250,7 @@ export @__FILE__, @__DIR__, @__LINE__, + @__MODULE__, @int128_str, @uint128_str, @big_str, diff --git a/base/expr.jl b/base/expr.jl index 5eb7fa814eaa7..dd41b6b38b363 100644 --- a/base/expr.jl +++ b/base/expr.jl @@ -46,19 +46,21 @@ copy_exprargs(x::Array{Any,1}) = Any[copy_exprs(a) for a in x] ==(x::QuoteNode, y::QuoteNode) = isequal(x.value, y.value) """ - expand(x) + expand(m, x) -Takes the expression `x` and returns an equivalent expression in lowered form. +Takes the expression `x` and returns an equivalent expression in lowered form +for executing in module `m`. See also [`code_lowered`](@ref). """ -expand(x::ANY) = ccall(:jl_expand, Any, (Any,), x) +expand(m::Module, x::ANY) = ccall(:jl_expand, Any, (Any, Any), x, m) """ - macroexpand(x) + macroexpand(m, x) -Takes the expression `x` and returns an equivalent expression with all macros removed (expanded). +Takes the expression `x` and returns an equivalent expression with all macros removed (expanded) +for executing in module `m`. """ -macroexpand(x::ANY) = ccall(:jl_macroexpand, Any, (Any,), x) +macroexpand(m::Module, x::ANY) = ccall(:jl_macroexpand, Any, (Any, Any), x, m) """ @macroexpand @@ -93,8 +95,7 @@ the code was finally called (REPL in the example). Note that when calling `macroexpand` or `@macroexpand` directly from the REPL, both of these contexts coincide, hence there is no difference. """ macro macroexpand(code) - code_expanded = macroexpand(code) - QuoteNode(code_expanded) + return :(macroexpand($__module__, $(QuoteNode(code)))) end ## misc syntax ## @@ -289,3 +290,12 @@ function remove_linenums!(ex::Expr) end return ex end + +macro generated(f) + if isa(f, Expr) && (f.head === :function || is_short_function_def(f)) + f.head = :stagedfunction + return Expr(:escape, f) + else + error("invalid syntax; @generated must be used with a function definition") + end +end diff --git a/base/inference.jl b/base/inference.jl index ee6d044ffb23f..5ef16364df4b5 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -152,7 +152,7 @@ mutable struct InferenceState optimize::Bool, cached::Bool, params::InferenceParams) code = src.code::Array{Any,1} nl = label_counter(code) + 1 - toplevel = !isdefined(linfo, :def) + toplevel = !isa(linfo.def, Method) if !toplevel && isempty(linfo.sparam_vals) && !isempty(linfo.def.sparam_syms) # linfo is unspecialized @@ -250,7 +250,7 @@ mutable struct InferenceState meth = linfo.def inmodule = meth.module else - inmodule = current_module() # toplevel thunks are inferred in the current module + inmodule = linfo.def::Module end if cached && !toplevel @@ -279,7 +279,8 @@ function InferenceState(linfo::MethodInstance, optimize::Bool, cached::Bool, params::InferenceParams) # prepare an InferenceState object for inferring lambda # create copies of the CodeInfo definition, and any fields that type-inference might modify - if linfo.def.isstaged + m = linfo.def::Method + if m.isstaged try # user code might throw errors – ignore them src = get_staged(linfo) @@ -288,10 +289,10 @@ function InferenceState(linfo::MethodInstance, end else # TODO: post-inference see if we can swap back to the original arrays? - if isa(linfo.def.source, Array{UInt8,1}) - src = ccall(:jl_uncompress_ast, Any, (Any, Any), linfo.def, linfo.def.source) + if isa(m.source, Array{UInt8,1}) + src = ccall(:jl_uncompress_ast, Any, (Any, Any), m, m.source) else - src = ccall(:jl_copy_code_info, Ref{CodeInfo}, (Any,), linfo.def.source) + src = ccall(:jl_copy_code_info, Ref{CodeInfo}, (Any,), m.source) src.code = copy_exprargs(src.code) src.slotnames = copy(src.slotnames) src.slotflags = copy(src.slotflags) @@ -1381,7 +1382,7 @@ function abstract_call_method(method::Method, f::ANY, sig::ANY, sparams::SimpleV infstate = sv while infstate !== nothing infstate = infstate::InferenceState - if isdefined(infstate.linfo, :def) && method === infstate.linfo.def + if method === infstate.linfo.def if mightlimitlength && ls > length(unwrap_unionall(infstate.linfo.specTypes).parameters) limitlength = true end @@ -2001,7 +2002,7 @@ function abstract_eval(e::ANY, vtypes::VarTable, sv::InferenceState) t = Any elseif e.head === :foreigncall rt = e.args[2] - if isdefined(sv.linfo, :def) + if isa(sv.linfo.def, Method) spsig = sv.linfo.def.sig if isa(spsig, UnionAll) if !isempty(sv.linfo.sparam_vals) @@ -2391,7 +2392,7 @@ coverage_enabled() = (JLOptions().code_coverage != 0) function update_valid_age!(min_valid::UInt, max_valid::UInt, sv::InferenceState) sv.min_valid = max(sv.min_valid, min_valid) sv.max_valid = min(sv.max_valid, max_valid) - @assert !isdefined(sv.linfo, :def) || !sv.cached || sv.min_valid <= sv.params.world <= sv.max_valid "invalid age range update" + @assert !isa(sv.linfo.def, Method) || !sv.cached || sv.min_valid <= sv.params.world <= sv.max_valid "invalid age range update" nothing end update_valid_age!(edge::InferenceState, sv::InferenceState) = update_valid_age!(edge.min_valid, edge.max_valid, sv) @@ -2399,7 +2400,7 @@ update_valid_age!(li::MethodInstance, sv::InferenceState) = update_valid_age!(mi # temporarily accumulate our edges to later add as backedges in the callee function add_backedge!(li::MethodInstance, caller::InferenceState) - isdefined(caller.linfo, :def) || return # don't add backedges to toplevel exprs + isa(caller.linfo.def, Method) || return # don't add backedges to toplevel exprs if caller.stmt_edges[caller.currpc] === () caller.stmt_edges[caller.currpc] = [] end @@ -2410,7 +2411,7 @@ end # temporarily accumulate our no method errors to later add as backedges in the callee method table function add_mt_backedge(mt::MethodTable, typ::ANY, caller::InferenceState) - isdefined(caller.linfo, :def) || return # don't add backedges to toplevel exprs + isa(caller.linfo.def, Method) || return # don't add backedges to toplevel exprs if caller.stmt_edges[caller.currpc] === () caller.stmt_edges[caller.currpc] = [] end @@ -2421,7 +2422,7 @@ end # add the real backedges now function finalize_backedges(frame::InferenceState) - toplevel = !isdefined(frame.linfo, :def) + toplevel = !isa(frame.linfo.def, Method) if !toplevel && frame.cached && frame.max_valid == typemax(UInt) caller = frame.linfo for edges in frame.stmt_edges @@ -2602,7 +2603,7 @@ function typeinf_code(linfo::MethodInstance, optimize::Bool, cached::Bool, if min_world(linfo) <= params.world <= max_world(linfo) inf = linfo.inferred if linfo.jlcall_api == 2 - method = linfo.def + method = linfo.def::Method tree = ccall(:jl_new_code_info_uninit, Ref{CodeInfo}, ()) tree.code = Any[ Expr(:return, QuoteNode(linfo.inferred_const)) ] tree.slotnames = Any[ compiler_temp_sym for i = 1:method.nargs ] @@ -2660,7 +2661,7 @@ function typeinf_type(method::Method, atypes::ANY, sparams::SimpleVector, end function typeinf_ext(linfo::MethodInstance, world::UInt) - if isdefined(linfo, :def) + if isa(linfo.def, Method) # method lambda - infer this specialization via the method cache return typeinf_code(linfo, true, true, InferenceParams(world)) else @@ -3019,10 +3020,11 @@ function optimize(me::InferenceState) force_noinline = true end end + def = me.linfo.def if force_noinline me.src.inlineable = false - elseif !me.src.inlineable && isdefined(me.linfo, :def) - me.src.inlineable = isinlineable(me.linfo.def, me.src) + elseif !me.src.inlineable && isa(def, Method) + me.src.inlineable = isinlineable(def, me.src) end me.src.inferred = true nothing @@ -3033,7 +3035,7 @@ end function finish(me::InferenceState) me.currpc = 1 # used by add_backedge if me.cached - toplevel = !isdefined(me.linfo, :def) + toplevel = !isa(me.linfo.def, Method) if !toplevel min_valid = me.min_valid max_valid = me.max_valid @@ -3075,13 +3077,14 @@ function finish(me::InferenceState) if !toplevel if !me.const_api + def = me.linfo.def::Method keeptree = me.src.inlineable || ccall(:jl_is_cacheable_sig, Int32, (Any, Any, Any), - me.linfo.specTypes, me.linfo.def.sig, me.linfo.def) != 0 + me.linfo.specTypes, def.sig, def) != 0 if !keeptree inferred_result = nothing else # compress code for non-toplevel thunks - inferred_result = ccall(:jl_compress_ast, Any, (Any, Any), me.linfo.def, inferred_result) + inferred_result = ccall(:jl_compress_ast, Any, (Any, Any), def, inferred_result) end end end diff --git a/base/int.jl b/base/int.jl index 19b65d5ea8f94..a610205e42286 100644 --- a/base/int.jl +++ b/base/int.jl @@ -363,7 +363,7 @@ end # @doc isn't available when running in Core at this point. # Tuple syntax for documention two function signatures at the same time # doesn't work either at this point. -if module_name(current_module()) === :Base +if module_name(@__MODULE__) === :Base for fname in (:mod, :rem) @eval @doc (""" rem(x::Integer, T::Type{<:Integer}) -> T diff --git a/base/interactiveutil.jl b/base/interactiveutil.jl index 144cd02e538ed..32cfb81047023 100644 --- a/base/interactiveutil.jl +++ b/base/interactiveutil.jl @@ -371,8 +371,7 @@ code_warntype(f, t::ANY) = code_warntype(STDOUT, f, t) typesof(args...) = Tuple{Any[ Core.Typeof(a) for a in args ]...} -gen_call_with_extracted_types(fcn, ex0::Symbol) = Expr(:call, fcn, Meta.quot(ex0)) -function gen_call_with_extracted_types(fcn, ex0) +function gen_call_with_extracted_types(__module__, fcn, ex0) if isa(ex0, Expr) if any(a->(Meta.isexpr(a, :kw) || Meta.isexpr(a, :parameters)), ex0.args) # remove keyword args, but call the kwfunc @@ -390,10 +389,10 @@ function gen_call_with_extracted_types(fcn, ex0) end exret = Expr(:none) is_macro = false - ex = expand(ex0) + ex = expand(__module__, ex0) if isa(ex0, Expr) && ex0.head == :macrocall # Make @edit @time 1+2 edit the macro by using the types of the *expressions* is_macro = true - exret = Expr(:call, fcn, esc(ex0.args[1]), Tuple{#=__source__=#LineNumberNode, Any[ Core.Typeof(a) for a in ex0.args[3:end] ]...}) + exret = Expr(:call, fcn, esc(ex0.args[1]), Tuple{#=__source__=#LineNumberNode, #=__module__=#Module, Any[ Core.Typeof(a) for a in ex0.args[3:end] ]...}) elseif !isa(ex, Expr) exret = Expr(:call, :error, "expression is not a function call or symbol") elseif ex.head == :call @@ -430,15 +429,19 @@ for fname in [:which, :less, :edit, :functionloc, :code_warntype, :code_llvm, :code_llvm_raw, :code_native] @eval begin macro ($fname)(ex0) - gen_call_with_extracted_types($(Expr(:quote,fname)), ex0) + gen_call_with_extracted_types(__module__, $(Expr(:quote, fname)), ex0) end end end +macro which(ex0::Symbol) + ex0 = QuoteNode(ex0) + return :(which_module($__module__, $ex0)) +end for fname in [:code_typed, :code_lowered] @eval begin macro ($fname)(ex0) - thecall = gen_call_with_extracted_types($(Expr(:quote,fname)), ex0) + thecall = gen_call_with_extracted_types(__module__, $(Expr(:quote, fname)), ex0) quote results = $thecall length(results) == 1 ? results[1] : results @@ -654,15 +657,15 @@ accessed using a statement such as `using LastMain.Package`. This function should only be used interactively. """ function workspace() - last = Core.Main - b = last.Base - ccall(:jl_new_main_module, Any, ()) - m = Core.Main + last = Core.Main # ensure to reference the current Main module + b = Base # this module + ccall(:jl_new_main_module, Any, ()) # make Core.Main a new baremodule + m = Core.Main # now grab a handle to the new Main module ccall(:jl_add_standard_imports, Void, (Any,), m) - eval(m, - Expr(:toplevel, - :(const Base = $(Expr(:quote, b))), - :(const LastMain = $(Expr(:quote, last))))) + eval(m, Expr(:toplevel, + :(const Base = $b), + :(const LastMain = $last), + :(include(x) = $include($m, x)))) empty!(package_locks) nothing end @@ -696,13 +699,13 @@ end """ - whos(io::IO=STDOUT, m::Module=current_module(), pattern::Regex=r"") + whos(io::IO=STDOUT, m::Module=Main, pattern::Regex=r"") Print information about exported global variables in a module, optionally restricted to those matching `pattern`. The memory consumption estimate is an approximate lower bound on the size of the internal structure of the object. """ -function whos(io::IO=STDOUT, m::Module=current_module(), pattern::Regex=r"") +function whos(io::IO=STDOUT, m::Module=Main, pattern::Regex=r"") maxline = displaysize(io)[2] line = zeros(UInt8, maxline) head = PipeBuffer(maxline + 1) @@ -746,4 +749,4 @@ function whos(io::IO=STDOUT, m::Module=current_module(), pattern::Regex=r"") end end whos(m::Module, pat::Regex=r"") = whos(STDOUT, m, pat) -whos(pat::Regex) = whos(STDOUT, current_module(), pat) +whos(pat::Regex) = whos(STDOUT, Main, pat) diff --git a/base/loading.jl b/base/loading.jl index b0a432d8e0df0..67d4b08b80557 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -466,20 +466,19 @@ function _require(mod::Symbol) # just load the file normally via include # for unknown dependencies try - if last && myid() == 1 && nprocs() > 1 - # include on node 1 first to check for PrecompilableErrors - eval(Main, :(Base.include_from_node1($path))) + # include on node 1 first to check for PrecompilableErrors + Base.include_from_node1(Main, path) + if last && myid() == 1 && nprocs() > 1 # broadcast top-level import/using from node 1 (only) @sync begin for p in filter(x -> x != 1, procs()) @async remotecall_fetch(p) do - eval(Main, :(Base.include_from_node1($path); nothing)) + Base.include_from_node1(Main, path) + nothing end end end - else - eval(Main, :(Base.include_from_node1($path))) end catch ex if doneprecompile === true || JLOptions().use_compilecache == 0 || !precompilableerror(ex, true) @@ -506,17 +505,17 @@ end # remote/parallel load """ - include_string(code::AbstractString, filename::AbstractString="string") + include_string(m::Module, code::AbstractString, filename::AbstractString="string") Like `include`, except reads code from the given string rather than from a file. Since there is no file path involved, no path processing or fetching from node 1 is done. """ -include_string(txt::String, fname::String) = - ccall(:jl_load_file_string, Any, (Ptr{UInt8},Csize_t,Cstring), - txt, sizeof(txt), fname) +include_string(m::Module, txt::String, fname::String) = + ccall(:jl_load_file_string, Any, (Ptr{UInt8}, Csize_t, Cstring, Any), + txt, sizeof(txt), fname, m) -include_string(txt::AbstractString, fname::AbstractString="string") = - include_string(String(txt), String(fname)) +include_string(m::Module, txt::AbstractString, fname::AbstractString="string") = + include_string(m, String(txt), String(fname)) function source_path(default::Union{AbstractString,Void}="") t = current_task() @@ -537,8 +536,8 @@ function source_dir() p === nothing ? pwd() : dirname(p) end -include_from_node1(path::AbstractString) = include_from_node1(String(path)) -function include_from_node1(_path::String) +include_from_node1(mod::Module, path::AbstractString) = include_from_node1(mod, String(path)) +function include_from_node1(mod::Module, _path::String) path, prev = _include_dependency(_path) tls = task_local_storage() tls[:SOURCE_PATH] = path @@ -547,10 +546,10 @@ function include_from_node1(_path::String) if myid()==1 # sleep a bit to process file requests from other nodes nprocs()>1 && sleep(0.005) - result = Core.include(path) + result = Core.include(mod, path) nprocs()>1 && sleep(0.005) else - result = include_string(remotecall_fetch(readstring, 1, path), path) + result = include_string(mod, remotecall_fetch(readstring, 1, path), path) end finally if prev === nothing @@ -563,9 +562,9 @@ function include_from_node1(_path::String) end """ - include(path::AbstractString) + include(m::Module, path::AbstractString) -Evaluate the contents of the input source file in the current context. Returns the result +Evaluate the contents of the input source file into module `m`. Returns the result of the last evaluated expression of the input file. During including, a task-local include path is set to the directory containing the file. Nested calls to `include` will search relative to that path. All paths refer to files on node 1 when running in parallel, and @@ -584,9 +583,10 @@ function evalfile(path::AbstractString, args::Vector{String}=String[]) return eval(Module(:__anon__), Expr(:toplevel, :(const ARGS = $args), - :(eval(x) = Main.Core.eval(__anon__,x)), - :(eval(m,x) = Main.Core.eval(m,x)), - :(Main.Base.include($path)))) + :(eval(x) = $(Expr(:core, :eval))(__anon__, x)), + :(eval(m, x) = $(Expr(:core, :eval))(m, x)), + :(include(x) = $(Expr(:top, :include))(__anon__, x)), + :(include($path)))) end evalfile(path::AbstractString, args::Vector) = evalfile(path, String[args...]) @@ -622,7 +622,7 @@ function create_expr_cache(input::String, output::String, concrete_deps::Vector{ task_local_storage()[:SOURCE_PATH] = $(source) end) end - serialize(in, :(Base.include($(abspath(input))))) + serialize(in, :(Base.include(Main, $(abspath(input))))) if source !== nothing serialize(in, :(delete!(task_local_storage(), :SOURCE_PATH))) end diff --git a/base/markdown/Markdown.jl b/base/markdown/Markdown.jl index fff30da7fec3c..93fb7a045f04c 100644 --- a/base/markdown/Markdown.jl +++ b/base/markdown/Markdown.jl @@ -37,23 +37,23 @@ function mdexpr(s, flavor = :julia) esc(toexpr(md)) end -function docexpr(source::LineNumberNode, s, flavor = :julia) - :($doc_str($(mdexpr(s, flavor)), $(QuoteNode(source)))) +function docexpr(source::LineNumberNode, mod::Module, s, flavor = :julia) + :($doc_str($(mdexpr(s, flavor)), $(QuoteNode(source)), $mod)) end macro md_str(s, t...) mdexpr(s, t...) end -function doc_str(md, source::LineNumberNode) +function doc_str(md, source::LineNumberNode, mod::Module) md.meta[:path] = isa(source.file, Symbol) ? String(source.file) : "" - md.meta[:module] = current_module() + md.meta[:module] = mod md end -doc_str(md::AbstractString, source::LineNumberNode) = doc_str(parse(md), source) +doc_str(md::AbstractString, source::LineNumberNode, mod::Module) = doc_str(parse(md), source, mod) macro doc_str(s::AbstractString, t...) - docexpr(__source__, s, t...) + docexpr(__source__, __module__, s, t...) end function Base.display(d::Base.REPL.REPLDisplay, md::Vector{MD}) diff --git a/base/operators.jl b/base/operators.jl index 8785134cf8571..fbb99958f67e9 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -906,7 +906,7 @@ julia> filter(!isalpha, str) # some operators not defined yet global //, >:, <|, hcat, hvcat, ⋅, ×, ∈, ∉, ∋, ∌, ⊆, ⊈, ⊊, ∩, ∪, √, ∛ -this_module = current_module() +this_module = @__MODULE__ baremodule Operators export diff --git a/base/osutils.jl b/base/osutils.jl index 4a133a4bd9a7f..a37f51c5f0db2 100644 --- a/base/osutils.jl +++ b/base/osutils.jl @@ -61,7 +61,7 @@ such as a `ccall` to a non-existent function. macro static(ex) if isa(ex, Expr) if ex.head === :if || ex.head === :&& || ex.head === :|| - cond = eval(current_module(), ex.args[1]) + cond = eval(__module__, ex.args[1]) if xor(cond, ex.head === :||) return esc(ex.args[2]) elseif length(ex.args) == 3 @@ -76,11 +76,12 @@ macro static(ex) throw(ArgumentError("invalid @static macro")) end -let KERNEL = ccall(:jl_get_UNAME, Any, ()) +let KERNEL = ccall(:jl_get_UNAME, Any, ()), + __module__ = @__MODULE__ # evaluate the zero-argument form of each of these functions # as a function returning a static constant based on the build-time # operating-system kernel for f in (:is_unix, :is_linux, :is_bsd, :is_apple, :is_windows) - @eval $f() = $(getfield(current_module(),f)(KERNEL)) + @eval $f() = $(getfield(__module__, f)(KERNEL)) end end diff --git a/base/precompile.jl b/base/precompile.jl index 5149aed65b332..2587bec08e738 100644 --- a/base/precompile.jl +++ b/base/precompile.jl @@ -743,7 +743,7 @@ precompile(Tuple{getfield(Base.Docs, Symbol("#@repl")), Base.TTY, Symbol}) precompile(Tuple{typeof(Base.Docs.repl), Base.TTY, Symbol}) precompile(Tuple{typeof(Base.Docs._repl), Symbol}) precompile(Tuple{getfield(Core, Symbol("#@doc")), Symbol}) -precompile(Tuple{typeof(Base.Docs.docm), LineNumberNode, Symbol}) +precompile(Tuple{typeof(Base.Docs.docm), LineNumberNode, Module, Symbol}) precompile(Tuple{typeof(Base._setindex!), Base.Dict{Any, Any}, Base.Markdown.Config, Symbol, Int64}) precompile(Tuple{Type{Base.Markdown.MD}}) precompile(Tuple{typeof(Base.setindex!), Base.Dict{Any, Any}, Base.Markdown.Config, Symbol}) @@ -1720,8 +1720,8 @@ precompile(Tuple{typeof(Base.Distributed.send_msg), Base.Distributed.Worker, Bas precompile(Tuple{typeof(Base.Distributed.send_msg_), Base.Distributed.Worker, Base.Distributed.MsgHeader, Base.Distributed.RemoteDoMsg, Bool}) precompile(Tuple{typeof(Base.Distributed.terminate_all_workers)}) precompile(Tuple{typeof(Base.Distributed.test_existing_ref), Base.Distributed.Future}) -precompile(Tuple{typeof(Base.Docs.docm), LineNumberNode, String, Expr}) -precompile(Tuple{typeof(Base.Docs.docm), LineNumberNode, String, Expr, Bool}) +precompile(Tuple{typeof(Base.Docs.docm), LineNumberNode, Module, String, Expr}) +precompile(Tuple{typeof(Base.Docs.docm), LineNumberNode, Module, String, Expr, Bool}) precompile(Tuple{typeof(Base.Docs.keyworddoc), String, Base.BaseDocs.Keyword}) precompile(Tuple{typeof(Base.Docs.objectdoc), String, Expr, Expr, Expr}) precompile(Tuple{typeof(Base.FastMath.make_fastmath), Expr}) diff --git a/base/reflection.jl b/base/reflection.jl index e5db516ec27df..63eb16d12ecf0 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -30,12 +30,14 @@ Base.LinAlg module_parent(m::Module) = ccall(:jl_module_parent, Ref{Module}, (Any,), m) """ - current_module() -> Module + @__MODULE__ -> Module -Get the *dynamically* current `Module`, which is the `Module` code is currently being read -from. In general, this is not the same as the module containing the call to this function. +Get the `Module` of the toplevel eval, +which is the `Module` code is currently being read from. """ -current_module() = ccall(:jl_get_current_module, Ref{Module}, ()) +macro __MODULE__() + return __module__ +end """ fullname(m::Module) @@ -90,7 +92,6 @@ isexported(m::Module, s::Symbol) = ccall(:jl_module_exports_p, Cint, (Any, Any), isdeprecated(m::Module, s::Symbol) = ccall(:jl_is_binding_deprecated, Cint, (Any, Any), m, s) != 0 isbindingresolved(m::Module, var::Symbol) = ccall(:jl_binding_resolved_p, Cint, (Any, Any), m, var) != 0 -binding_module(s::Symbol) = binding_module(current_module(), s) function binding_module(m::Module, s::Symbol) p = ccall(:jl_get_module_of_binding, Ptr{Void}, (Any, Any), m, s) p == C_NULL && return m @@ -159,17 +160,23 @@ Determine the module containing the definition of a `DataType`. """ datatype_module(t::DataType) = t.name.module -isconst(s::Symbol) = ccall(:jl_is_const, Cint, (Ptr{Void}, Any), C_NULL, s) != 0 - """ - isconst([m::Module], s::Symbol) -> Bool + isconst(m::Module, s::Symbol) -> Bool -Determine whether a global is declared `const` in a given `Module`. The default `Module` -argument is [`current_module()`](@ref). +Determine whether a global is declared `const` in a given `Module`. """ isconst(m::Module, s::Symbol) = ccall(:jl_is_const, Cint, (Any, Any), m, s) != 0 +""" + @isdefined s -> Bool + +Tests whether symbol `s` is defined in the current scope. +""" +macro isdefined(s::Symbol) + return :(isdefined($__module__, $(QuoteNode(s)))) +end + # return an integer such that object_id(x)==object_id(y) if x===y object_id(x::ANY) = ccall(:jl_object_id, UInt, (Any,), x) @@ -804,9 +811,9 @@ end """ which(symbol) -Return the module in which the binding for the variable referenced by `symbol` was created. +Return the module in which the binding for the variable referenced by `symbol` in module `Main` was created. """ -which(s::Symbol) = which_module(current_module(), s) +which(s::Symbol) = which_module(Main, s) # TODO: making this a method of which() causes a strange error function which_module(m::Module, s::Symbol) if !isdefined(m, s) diff --git a/base/serialize.jl b/base/serialize.jl index d453e9e0a33f9..b8e2387e98d00 100644 --- a/base/serialize.jl +++ b/base/serialize.jl @@ -404,7 +404,7 @@ end function serialize(s::AbstractSerializer, linfo::Core.MethodInstance) serialize_cycle(s, linfo) && return - isdefined(linfo, :def) && error("can only serialize toplevel MethodInstance objects") + isa(linfo.def, Module) || error("can only serialize toplevel MethodInstance objects") writetag(s.io, METHODINSTANCE_TAG) serialize(s, linfo.inferred) if isdefined(linfo, :inferred_const) @@ -415,6 +415,8 @@ function serialize(s::AbstractSerializer, linfo::Core.MethodInstance) serialize(s, linfo.sparam_vals) serialize(s, linfo.rettype) serialize(s, linfo.specTypes) + serialize(s, linfo.def) + nothing end function serialize(s::AbstractSerializer, t::Task) @@ -765,7 +767,7 @@ function deserialize(s::AbstractSerializer, ::Type{Method}) meth = meth::Method makenew = false else - meth = ccall(:jl_new_method_uninit, Ref{Method}, ()) + meth = ccall(:jl_new_method_uninit, Ref{Method}, (Any,), Main) makenew = true end deserialize_cycle(s, meth) @@ -798,6 +800,7 @@ function deserialize(s::AbstractSerializer, ::Type{Method}) linfo = ccall(:jl_new_method_instance_uninit, Ref{Core.MethodInstance}, ()) linfo.specTypes = Tuple linfo.inferred = template + linfo.def = meth meth.generator = linfo end ftype = ccall(:jl_first_argument_datatype, Any, (Any,), sig)::DataType @@ -820,6 +823,7 @@ function deserialize(s::AbstractSerializer, ::Type{Core.MethodInstance}) linfo.sparam_vals = deserialize(s)::SimpleVector linfo.rettype = deserialize(s) linfo.specTypes = deserialize(s) + linfo.def = deserialize(s)::Module return linfo end @@ -920,8 +924,8 @@ function deserialize_typename(s::AbstractSerializer, number) # TODO: there's an unhanded cycle in the dependency graph at this point: # while deserializing super and/or types, we may have encountered # tn.wrapper and throw UndefRefException before we get to this point - ndt = ccall(:jl_new_datatype, Any, (Any, Any, Any, Any, Any, Cint, Cint, Cint), - tn, super, parameters, names, types, + ndt = ccall(:jl_new_datatype, Any, (Any, Any, Any, Any, Any, Any, Cint, Cint, Cint), + tn, tn.module, super, parameters, names, types, abstr, mutabl, ninitialized) tn.wrapper = ndt.name.wrapper ccall(:jl_set_const, Void, (Any, Any, Any), tn.module, tn.name, tn.wrapper) diff --git a/base/show.jl b/base/show.jl index 5cfa8acdd032d..cd58087312bbc 100644 --- a/base/show.jl +++ b/base/show.jl @@ -317,13 +317,14 @@ function sourceinfo_slotnames(src::CodeInfo) end function show(io::IO, l::Core.MethodInstance) - if isdefined(l, :def) - if l.def.isstaged && l === l.def.generator + def = l.def + if isa(def, Method) + if def.isstaged && l === def.generator print(io, "MethodInstance generator for ") - show(io, l.def) + show(io, def) else print(io, "MethodInstance for ") - show_tuple_as_call(io, l.def.name, l.specTypes) + show_tuple_as_call(io, def.name, l.specTypes) end else print(io, "Toplevel MethodInstance thunk") @@ -1097,12 +1098,30 @@ function show_tuple_as_call(io::IO, name::Symbol, sig::Type) nothing end +resolvebinding(ex::ANY) = ex +resolvebinding(ex::QuoteNode) = ex.value +resolvebinding(ex::Symbol) = resolvebinding(GlobalRef(Main, ex)) +function resolvebinding(ex::Expr) + if ex.head == :. && isa(ex.args[2], Symbol) + parent = resolvebinding(ex.args[1]) + if isa(parent, Module) + return resolvebinding(GlobalRef(parent, ex.args[2])) + end + end + return nothing +end +function resolvebinding(ex::GlobalRef) + isdefined(ex.mod, ex.name) || return nothing + isconst(ex.mod, ex.name) || return nothing + m = getfield(ex.mod, ex.name) + isa(m, Module) || return nothing + return m +end + function ismodulecall(ex::Expr) return ex.head == :call && (ex.args[1] === GlobalRef(Base,:getfield) || ex.args[1] === GlobalRef(Core,:getfield)) && - isa(ex.args[2], Symbol) && - isdefined(current_module(), ex.args[2]) && - isa(getfield(current_module(), ex.args[2]), Module) + isa(resolvebinding(ex.args[2]), Module) end function show(io::IO, tv::TypeVar) diff --git a/base/stacktraces.jl b/base/stacktraces.jl index 82a30cbf12f0c..8fbe116a6270c 100644 --- a/base/stacktraces.jl +++ b/base/stacktraces.jl @@ -213,7 +213,7 @@ function show_spec_linfo(io::IO, frame::StackFrame) end else linfo = get(frame.linfo) - if isdefined(linfo, :def) + if isa(linfo.def, Method) Base.show_tuple_as_call(io, linfo.def.name, linfo.specTypes) else Base.show(io, linfo) @@ -250,7 +250,8 @@ function from(frame::StackFrame, m::Module) result = false if !isnull(finfo) - frame_m = get(finfo).def.module + frame_m = get(finfo).def + isa(frame_m, Method) && (frame_m = frame_m.module) result = module_name(frame_m) === module_name(m) end diff --git a/base/sysimg.jl b/base/sysimg.jl index efaa3570fad1c..5431dd9706392 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -3,18 +3,43 @@ baremodule Base using Core.Intrinsics -ccall(:jl_set_istopmod, Void, (Bool,), true) -function include(path::AbstractString) +ccall(:jl_set_istopmod, Void, (Any, Bool), Base, true) +function include(mod::Module, path::AbstractString) local result if INCLUDE_STATE === 1 - result = Core.include(path) + result = Core.include(mod, path) elseif INCLUDE_STATE === 2 - result = _include(path) + result = _include(mod, path) elseif INCLUDE_STATE === 3 - result = include_from_node1(path) + result = include_from_node1(mod, path) + end + result +end +function include(path::AbstractString) + local result + if INCLUDE_STATE === 1 + result = Core.include(Base, path) + elseif INCLUDE_STATE === 2 + result = _include(Base, path) + else + # to help users avoid error (accidentally evaluating into Base), this is deprecated + depwarn("Base.include(string) is deprecated, use `include(fname)` or `Base.include(@__MODULE__, fname)` instead.", :include) + result = include_from_node1(_current_module(), path) end result end +let SOURCE_PATH = "" + # simple, race-y TLS, relative include + global _include + function _include(mod::Module, path) + prev = SOURCE_PATH + path = joinpath(dirname(prev), path) + SOURCE_PATH = path + result = Core.include(mod, path) + SOURCE_PATH = prev + result + end +end INCLUDE_STATE = 1 # include = Core.include include("coreio.jl") @@ -255,15 +280,6 @@ importall .Math const (√)=sqrt const (∛)=cbrt -let SOURCE_PATH = "" - global function _include(path) - prev = SOURCE_PATH - path = joinpath(dirname(prev),path) - SOURCE_PATH = path - Core.include(path) - SOURCE_PATH = prev - end -end INCLUDE_STATE = 2 # include = _include (from lines above) # reduction along dims @@ -426,11 +442,11 @@ function __init__() end INCLUDE_STATE = 3 # include = include_from_node1 -include("precompile.jl") +include(Base, "precompile.jl") end # baremodule Base using Base importall Base.Operators -Base.isfile("userimg.jl") && Base.include("userimg.jl") +Base.isfile("userimg.jl") && Base.include(Main, "userimg.jl") diff --git a/base/test.jl b/base/test.jl index 9d7dc05bd553e..9180f27061f01 100644 --- a/base/test.jl +++ b/base/test.jl @@ -1073,7 +1073,7 @@ macro inferred(ex) kwargs = gensym() quote $(esc(args)), $(esc(kwargs)), result = $(esc(Expr(:call, _args_and_call, ex.args[2:end]..., ex.args[1]))) - inftypes = $(Base.gen_call_with_extracted_types(Base.return_types, :($(ex.args[1])($(args)...; $(kwargs)...)))) + inftypes = $(Base.gen_call_with_extracted_types(__module__, Base.return_types, :($(ex.args[1])($(args)...; $(kwargs)...)))) end else # No keywords diff --git a/base/util.jl b/base/util.jl index 187bc416c4ba3..ec2cdc660ed01 100644 --- a/base/util.jl +++ b/base/util.jl @@ -431,7 +431,8 @@ const log_error_to = Dict{Tuple{Union{Module,Void},Union{Symbol,Void}},IO}() function _redirect(io::IO, log_to::Dict, sf::StackTraces.StackFrame) isnull(sf.linfo) && return io - mod = get(sf.linfo).def.module + mod = get(sf.linfo).def + isa(mod, Method) && (mod = mod.module) fun = sf.func if haskey(log_to, (mod,fun)) return log_to[(mod,fun)] @@ -456,7 +457,9 @@ function _redirect(io::IO, log_to::Dict, fun::Symbol) isnull(frame.linfo) && continue sf = frame break_next_frame && (@goto skip) - get(frame.linfo).def.module == Base || continue + mod = get(frame.linfo).def + isa(mod, Method) && (mod = mod.module) + mod === Base || continue sff = string(frame.func) if frame.func == fun || startswith(sff, clos) || startswith(sff, kw) break_next_frame = true @@ -792,7 +795,7 @@ end ``` """ macro kwdef(expr) - expr = macroexpand(expr) # to expand @static + expr = macroexpand(__module__, expr) # to expand @static T = expr.args[2] params_ex = Expr(:parameters) call_ex = Expr(:call, T) diff --git a/doc/src/devdocs/ast.md b/doc/src/devdocs/ast.md index 157dd60a624c0..bcde2617b7b1d 100644 --- a/doc/src/devdocs/ast.md +++ b/doc/src/devdocs/ast.md @@ -242,8 +242,8 @@ for important details on how to modify these fields safely. * `def` - The `Method` that this function describes a specialization of. Or `#undef`, if this is - a top-level Lambda that is not part of a Method. + The `Method` that this function describes a specialization of. Or a `Module`, + if this is a top-level Lambda expanded in Module, and which is not part of a Method. * `sparam_vals` diff --git a/doc/src/manual/calling-c-and-fortran-code.md b/doc/src/manual/calling-c-and-fortran-code.md index 30da54ac330ad..5a98756ca8e15 100644 --- a/doc/src/manual/calling-c-and-fortran-code.md +++ b/doc/src/manual/calling-c-and-fortran-code.md @@ -847,21 +847,19 @@ case, the expression must evaluate to a `Ptr`, which will be used as the address function to call. This behavior occurs when the first [`ccall`](@ref) argument contains references to non-constants, such as local variables, function arguments, or non-constant globals. -For example, you might look up the function via `dlsym`, then cache it in a global -variable for that session. For example: +For example, you might look up the function via `dlsym`, +then cache it in a shared reference for that session. For example: ```julia macro dlsym(func, lib) - z, zlocal = gensym(string(func)), gensym() - eval(current_module(), :(global $z = C_NULL)) - z = esc(z) + z = Ref{Ptr{Void}}(C_NULL) quote - let $zlocal::Ptr{Void} = $z::Ptr{Void} - if $zlocal == C_NULL - $zlocal = dlsym($(esc(lib))::Ptr{Void}, $(esc(func))) - global $z = $zlocal + let zlocal = $z[] + if zlocal == C_NULL + zlocal = dlsym($(esc(lib))::Ptr{Void}, $(esc(func)))::Ptr{Void} + $z[] = $zlocal end - $zlocal + zlocal end end end diff --git a/doc/src/manual/metaprogramming.md b/doc/src/manual/metaprogramming.md index a6d3fa57840e5..031f93fdacf52 100644 --- a/doc/src/manual/metaprogramming.md +++ b/doc/src/manual/metaprogramming.md @@ -512,10 +512,10 @@ julia> @showarg(println("Yo!")) :(println("Yo!")) ``` -In addition to the given argument list, every macro is passed an extra argument named `__source__` -providing information (in the form of a `LineNumberNode` object) about the parser location -of the `@` sign from the macro invocation. +In addition to the given argument list, every macro is passed extra arguments named `__source__` and `__module__`. +The argument `__source__` provides information (in the form of a `LineNumberNode` object) about the parser location +of the `@` sign from the macro invocation. This allows macros to include better error diagnostic information, and is commonly used by logging, string-parser macros, and docs, for example, as well as to implement the `@__LINE__`, `@__FILE__`, and `@__DIR__` macros. @@ -534,6 +534,13 @@ LineNumberNode file: Symbol none ``` +The argument `__module__` provides information (in the form of a `Module` object) +about the expansion context of the macro invocation. +This allows macros to look up contextual information, such as existing bindings, +or to insert the value as an extra argument to a runtime function call doing self-reflection +in the current module. + + ### Building an advanced macro Here is a simplified definition of Julia's `@assert` macro: diff --git a/doc/src/manual/modules.md b/doc/src/manual/modules.md index bbd6b4248b1f6..3063b1d45c41c 100644 --- a/doc/src/manual/modules.md +++ b/doc/src/manual/modules.md @@ -336,8 +336,8 @@ Other known potential failure scenarios include: Note that `object_id` (which works by hashing the memory pointer) has similar issues (see notes on `Dict` usage below). - One alternative is to store both [`current_module()`](@ref) and the current `counter` value, however, - it may be better to redesign the code to not depend on this global state. + One alternative is to use a macro to capture [`@__MODULE__`](@ref) and store it alone with the current `counter` value, + however, it may be better to redesign the code to not depend on this global state. 2. Associative collections (such as `Dict` and `Set`) need to be re-hashed in `__init__`. (In the future, a mechanism may be provided to register an initializer function.) 3. Depending on compile-time side-effects persisting through load-time. Example include: modifying diff --git a/doc/src/manual/parallel-computing.md b/doc/src/manual/parallel-computing.md index 0108eb0097060..b29445132d2b7 100644 --- a/doc/src/manual/parallel-computing.md +++ b/doc/src/manual/parallel-computing.md @@ -152,8 +152,8 @@ end Starting Julia with `julia -p 2`, you can use this to verify the following: - * [`include("DummyModule.jl")`](@ref) loads the file on just a single process (whichever one executes - the statement). + * `include("DummyModule.jl")` loads the file on just a single process + (whichever one executes the statement). * `using DummyModule` causes the module to be loaded on all processes; however, the module is brought into scope only on the one executing the statement. * As long as `DummyModule` is loaded on process 2, commands like diff --git a/doc/src/stdlib/base.md b/doc/src/stdlib/base.md index 9af89439bcc8f..d17eb625344be 100644 --- a/doc/src/stdlib/base.md +++ b/doc/src/stdlib/base.md @@ -76,6 +76,7 @@ Base.finalize Base.copy Base.deepcopy Core.isdefined +Base.@isdefined Base.convert Base.promote Base.oftype @@ -250,7 +251,7 @@ Base.AsyncCondition(::Function) ```@docs Base.module_name Base.module_parent -Base.current_module +Base.@__MODULE__ Base.fullname Base.names Core.nfields diff --git a/src/ast.c b/src/ast.c index ed44ab1509d09..0b286de277d5b 100644 --- a/src/ast.c +++ b/src/ast.c @@ -97,6 +97,7 @@ typedef struct _jl_ast_context_t { jl_ast_context_list_t list; int ref; jl_task_t *task; + jl_module_t *module; // use a pointer to a stack slot so that we can detect if // `jl_ast_preserve` is called in the wrong context. // If `roots` is not NULL, it always points to a rooted stack slot. @@ -109,14 +110,19 @@ static jl_ast_context_t jl_ast_main_ctx; #define jl_ast_context_list_item(node) \ container_of(node, jl_ast_context_t, list) -#define JL_AST_PRESERVE_PUSH(ctx, _roots, old_roots) \ - jl_array_t *_roots = NULL; \ - jl_array_t **old_roots = ctx->roots; \ - ctx->roots = &_roots; \ - JL_GC_PUSH1(&_roots) -#define JL_AST_PRESERVE_POP(ctx, old_roots) \ +#define JL_AST_PRESERVE_PUSH(ctx, _roots, old, inmodule) \ + jl_array_t *(_roots) = NULL; \ + struct { jl_array_t **roots; \ + jl_module_t *module; } (old); \ + old.roots = ctx->roots; \ + old.module = ctx->module; \ + ctx->roots = &(_roots); \ + ctx->module = (inmodule); \ + JL_GC_PUSH2(&(_roots), &(inmodule)) +#define JL_AST_PRESERVE_POP(ctx, old) \ JL_GC_POP(); \ - ctx->roots = old_roots + ctx->roots = (old).roots; \ + ctx->module = (old).module static void jl_ast_preserve(fl_context_t *fl_ctx, jl_value_t *obj) { @@ -137,10 +143,10 @@ static value_t julia_to_scm(fl_context_t *fl_ctx, jl_value_t *v); value_t fl_defined_julia_global(fl_context_t *fl_ctx, value_t *args, uint32_t nargs) { - jl_ptls_t ptls = jl_get_ptls_states(); + jl_ast_context_t *ctx = jl_ast_ctx(fl_ctx); // tells whether a var is defined in and *by* the current module argcount(fl_ctx, "defined-julia-global", nargs, 1); - jl_module_t *mod = ptls->current_module; + jl_module_t *mod = ctx->module; jl_sym_t *sym = (jl_sym_t*)scm_to_julia(fl_ctx, args[0], 0); if (jl_is_globalref(sym)) { mod = jl_globalref_mod(sym); @@ -154,30 +160,21 @@ value_t fl_defined_julia_global(fl_context_t *fl_ctx, value_t *args, uint32_t na return (b != HT_NOTFOUND && b->owner == mod) ? fl_ctx->T : fl_ctx->F; } -value_t fl_current_julia_module(fl_context_t *fl_ctx, value_t *args, uint32_t nargs) -{ - jl_ptls_t ptls = jl_get_ptls_states(); - value_t opaque = cvalue(fl_ctx, jl_ast_ctx(fl_ctx)->jvtype, sizeof(void*)); - *(jl_value_t**)cv_data((cvalue_t*)ptr(opaque)) = (jl_value_t*)ptls->current_module; - return opaque; -} - value_t fl_current_module_counter(fl_context_t *fl_ctx, value_t *args, uint32_t nargs) { - jl_ptls_t ptls = jl_get_ptls_states(); - static uint32_t fallback_counter = 0; - if (ptls->current_module == NULL) - return fixnum(++fallback_counter); - else - return fixnum(jl_module_next_counter(ptls->current_module)); + jl_ast_context_t *ctx = jl_ast_ctx(fl_ctx); + assert(ctx->module); + return fixnum(jl_module_next_counter(ctx->module)); } value_t fl_invoke_julia_macro(fl_context_t *fl_ctx, value_t *args, uint32_t nargs) { JL_TIMING(MACRO_INVOCATION); jl_ptls_t ptls = jl_get_ptls_states(); + jl_ast_context_t *ctx = jl_ast_ctx(fl_ctx); if (nargs < 2) // macro name and location argcount(fl_ctx, "invoke-julia-macro", nargs, 2); + nargs++; // add __module__ argument jl_method_instance_t *mfunc = NULL; jl_value_t **margs; // Reserve one more slot for the result @@ -206,13 +203,14 @@ value_t fl_invoke_julia_macro(fl_context_t *fl_ctx, value_t *args, uint32_t narg else if (!jl_typeis(lno, jl_linenumbernode_type)) { margs[1] = jl_new_struct(jl_linenumbernode_type, jl_box_long(0), jl_nothing); } - for (i = 2; i < nargs; i++) - margs[i] = scm_to_julia(fl_ctx, args[i], 1); + margs[2] = (jl_value_t*)ctx->module; + for (i = 3; i < nargs; i++) + margs[i] = scm_to_julia(fl_ctx, args[i - 1], 1); jl_value_t *result = NULL; size_t world = jl_get_ptls_states()->world_age; JL_TRY { - margs[0] = jl_toplevel_eval(margs[0]); + margs[0] = jl_toplevel_eval(ctx->module, margs[0]); mfunc = jl_method_lookup(jl_gf_mtable(margs[0]), margs, nargs, 1, world); if (mfunc == NULL) { jl_method_error((jl_function_t*)margs[0], margs, nargs, world); @@ -236,15 +234,10 @@ value_t fl_invoke_julia_macro(fl_context_t *fl_ctx, value_t *args, uint32_t narg value_t scm = julia_to_scm(fl_ctx, result); fl_gc_handle(fl_ctx, &scm); value_t scmresult; - jl_module_t *defmod = mfunc->def->module; - /* if (defmod == NULL || defmod == ptls->current_module) { */ - /* scmresult = fl_cons(fl_ctx, scm, fl_ctx->F); */ - /* } */ - /* else { */ + jl_module_t *defmod = mfunc->def.method->module; value_t opaque = cvalue(fl_ctx, jl_ast_ctx(fl_ctx)->jvtype, sizeof(void*)); *(jl_value_t**)cv_data((cvalue_t*)ptr(opaque)) = (jl_value_t*)defmod; scmresult = fl_cons(fl_ctx, scm, opaque); - /* } */ fl_free_gc_handles(fl_ctx, 1); JL_GC_POP(); @@ -270,7 +263,6 @@ value_t fl_julia_scalar(fl_context_t *fl_ctx, value_t *args, uint32_t nargs) static const builtinspec_t julia_flisp_ast_ext[] = { { "defined-julia-global", fl_defined_julia_global }, { "invoke-julia-macro", fl_invoke_julia_macro }, - { "current-julia-module", fl_current_julia_module }, { "current-julia-module-counter", fl_current_module_counter }, { "julia-scalar?", fl_julia_scalar }, { NULL, NULL } @@ -291,14 +283,17 @@ static void jl_init_ast_ctx(jl_ast_context_t *ast_ctx) fl_applyn(fl_ctx, 0, symbol_value(symbol(fl_ctx, "__init_globals"))); - jl_ast_ctx(fl_ctx)->jvtype = define_opaque_type(fl_ctx->jl_sym, sizeof(void*), NULL, NULL); + jl_ast_context_t *ctx = jl_ast_ctx(fl_ctx); + ctx->jvtype = define_opaque_type(fl_ctx->jl_sym, sizeof(void*), NULL, NULL); assign_global_builtins(fl_ctx, julia_flisp_ast_ext); - jl_ast_ctx(fl_ctx)->true_sym = symbol(fl_ctx, "true"); - jl_ast_ctx(fl_ctx)->false_sym = symbol(fl_ctx, "false"); - jl_ast_ctx(fl_ctx)->error_sym = symbol(fl_ctx, "error"); - jl_ast_ctx(fl_ctx)->null_sym = symbol(fl_ctx, "null"); - jl_ast_ctx(fl_ctx)->ssavalue_sym = symbol(fl_ctx, "ssavalue"); - jl_ast_ctx(fl_ctx)->slot_sym = symbol(fl_ctx, "slot"); + ctx->true_sym = symbol(fl_ctx, "true"); + ctx->false_sym = symbol(fl_ctx, "false"); + ctx->error_sym = symbol(fl_ctx, "error"); + ctx->null_sym = symbol(fl_ctx, "null"); + ctx->ssavalue_sym = symbol(fl_ctx, "ssavalue"); + ctx->slot_sym = symbol(fl_ctx, "slot"); + ctx->task = NULL; + ctx->module = NULL; // Enable / disable syntax deprecation warnings if (jl_options.depwarn == JL_OPTIONS_DEPWARN_ERROR) @@ -336,6 +331,7 @@ static jl_ast_context_t *jl_ast_ctx_enter(void) ctx->ref = 1; ctx->task = ptls->current_task; ctx->roots = NULL; + ctx->module = NULL; JL_UNLOCK_NOGC(&flisp_lock); return ctx; } @@ -444,7 +440,7 @@ JL_DLLEXPORT void jl_lisp_prompt(void) JL_SIGATOMIC_BEGIN(); jl_init_frontend(); jl_ast_context_t *ctx = jl_ast_ctx_enter(); - JL_AST_PRESERVE_PUSH(ctx, roots, old_roots); + JL_AST_PRESERVE_PUSH(ctx, roots, old_roots, jl_main_module); fl_context_t *fl_ctx = &ctx->fl; fl_applyn(fl_ctx, 1, symbol_value(symbol(fl_ctx, "__start")), fl_cons(fl_ctx, fl_ctx->NIL,fl_ctx->NIL)); JL_AST_PRESERVE_POP(ctx, old_roots); @@ -512,7 +508,7 @@ extern int64_t conv_to_int64(void *data, numerictype_t tag); static jl_value_t *scm_to_julia_(fl_context_t *fl_ctx, value_t e, int eo) { - jl_ptls_t ptls = jl_get_ptls_states(); + jl_ast_context_t *ctx = jl_ast_ctx(fl_ctx); if (fl_isnumber(fl_ctx, e)) { int64_t i64; if (isfixnum(e)) { @@ -616,7 +612,7 @@ static jl_value_t *scm_to_julia_(fl_context_t *fl_ctx, value_t e, int eo) if (sym == top_sym) { scmv = scm_to_julia_(fl_ctx,car_(e),0); assert(jl_is_symbol(scmv)); - temp = jl_module_globalref(jl_base_relative_to(ptls->current_module), (jl_sym_t*)scmv); + temp = jl_module_globalref(jl_base_relative_to(ctx->module), (jl_sym_t*)scmv); JL_GC_POP(); return temp; } @@ -839,7 +835,8 @@ JL_DLLEXPORT jl_value_t *jl_parse_string(const char *str, size_t len, // parse and eval a whole file, possibly reading from a string (`content`) jl_value_t *jl_parse_eval_all(const char *fname, - const char *content, size_t contentlen) + const char *content, size_t contentlen, + jl_module_t *inmodule) { jl_ptls_t ptls = jl_get_ptls_states(); if (ptls->in_pure_callback) @@ -876,10 +873,12 @@ jl_value_t *jl_parse_eval_all(const char *fname, jl_filename = fname; jl_array_t *roots = NULL; jl_array_t **old_roots = ctx->roots; + jl_module_t *old_module = ctx->module; ctx->roots = &roots; + ctx->module = inmodule; jl_value_t *form=NULL, *result=jl_nothing; int err = 0; - JL_GC_PUSH3(&roots, &form, &result); + JL_GC_PUSH4(&roots, &form, &result, &inmodule); JL_TRY { assert(iscons(ast) && car_(ast) == symbol(fl_ctx,"toplevel")); ast = cdr_(ast); @@ -896,15 +895,15 @@ jl_value_t *jl_parse_eval_all(const char *fname, JL_SIGATOMIC_END(); jl_get_ptls_states()->world_age = jl_world_counter; if (head == jl_incomplete_sym) - jl_errorf("syntax: %s", jl_string_data(jl_exprarg(form,0))); + jl_errorf("syntax: %s", jl_string_data(jl_exprarg(form, 0))); else if (head == error_sym) - jl_interpret_toplevel_expr(form); + jl_interpret_toplevel_expr_in(inmodule, form, NULL, NULL); else if (head == line_sym) - jl_lineno = jl_unbox_long(jl_exprarg(form,0)); + jl_lineno = jl_unbox_long(jl_exprarg(form, 0)); else if (jl_is_linenode(form)) jl_lineno = jl_linenode_line(form); else - result = jl_toplevel_eval_flex(form, 1, 1); + result = jl_toplevel_eval_flex(inmodule, form, 1, 1); JL_SIGATOMIC_BEGIN(); ast = cdr_(ast); } @@ -919,6 +918,7 @@ jl_value_t *jl_parse_eval_all(const char *fname, jl_filename = last_filename; fl_free_gc_handles(fl_ctx, 1); ctx->roots = old_roots; + ctx->module = old_module; jl_ast_ctx_leave(ctx); if (err) { if (jl_loaderror_type == NULL) @@ -932,9 +932,9 @@ jl_value_t *jl_parse_eval_all(const char *fname, } JL_DLLEXPORT jl_value_t *jl_load_file_string(const char *text, size_t len, - char *filename) + char *filename, jl_module_t *inmodule) { - return jl_parse_eval_all(filename, text, len); + return jl_parse_eval_all(filename, text, len, inmodule); } JL_DLLEXPORT int jl_parse_depwarn(int warn) @@ -960,11 +960,11 @@ static int jl_parse_deperror(fl_context_t *fl_ctx, int err) } // returns either an expression or a thunk -jl_value_t *jl_call_scm_on_ast(const char *funcname, jl_value_t *expr) +jl_value_t *jl_call_scm_on_ast(const char *funcname, jl_value_t *expr, jl_module_t *inmodule) { jl_ast_context_t *ctx = jl_ast_ctx_enter(); fl_context_t *fl_ctx = &ctx->fl; - JL_AST_PRESERVE_PUSH(ctx, roots, old_roots); + JL_AST_PRESERVE_PUSH(ctx, roots, old_roots, inmodule); value_t arg = julia_to_scm(fl_ctx, expr); value_t e = fl_applyn(fl_ctx, 1, symbol_value(symbol(fl_ctx, funcname)), arg); jl_value_t *result = scm_to_julia(fl_ctx, e, 0); @@ -973,16 +973,16 @@ jl_value_t *jl_call_scm_on_ast(const char *funcname, jl_value_t *expr) return result; } -JL_DLLEXPORT jl_value_t *jl_expand(jl_value_t *expr) +JL_DLLEXPORT jl_value_t *jl_expand(jl_value_t *expr, jl_module_t *inmodule) { JL_TIMING(LOWERING); - return jl_call_scm_on_ast("jl-expand-to-thunk", expr); + return jl_call_scm_on_ast("jl-expand-to-thunk", expr, inmodule); } -JL_DLLEXPORT jl_value_t *jl_macroexpand(jl_value_t *expr) +JL_DLLEXPORT jl_value_t *jl_macroexpand(jl_value_t *expr, jl_module_t *inmodule) { JL_TIMING(LOWERING); - return jl_call_scm_on_ast("jl-macroexpand", expr); + return jl_call_scm_on_ast("jl-macroexpand", expr, inmodule); } // wrap expr in a thunk AST diff --git a/src/builtins.c b/src/builtins.c index e7f29e0051e73..70ca4262d1ba2 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -493,7 +493,7 @@ JL_DLLEXPORT jl_value_t *jl_toplevel_eval_in(jl_module_t *m, jl_value_t *ex) JL_TRY { ptls->current_task->current_module = ptls->current_module = m; ptls->world_age = jl_world_counter; - v = jl_toplevel_eval(ex); + v = jl_toplevel_eval(m, ex); } JL_CATCH { jl_lineno = last_lineno; @@ -511,9 +511,8 @@ JL_DLLEXPORT jl_value_t *jl_toplevel_eval_in(jl_module_t *m, jl_value_t *ex) JL_CALLABLE(jl_f_isdefined) { - jl_ptls_t ptls = jl_get_ptls_states(); - jl_module_t *m = ptls->current_module; - jl_sym_t *s=NULL; + jl_module_t *m = NULL; + jl_sym_t *s = NULL; JL_NARGSV(isdefined, 1); if (jl_is_array(args[0])) { return jl_array_isdefined(args, nargs) ? jl_true : jl_false; @@ -524,6 +523,11 @@ JL_CALLABLE(jl_f_isdefined) } if (nargs != 2) { JL_NARGS(isdefined, 1, 1); + jl_depwarn("`isdefined(:symbol)` is deprecated, " + "use `@isdefined symbol` instead", + (jl_value_t*)jl_symbol("isdefined")); + jl_ptls_t ptls = jl_get_ptls_states(); + m = ptls->current_module; } else { if (!jl_is_module(args[0])) { diff --git a/src/ccall.cpp b/src/ccall.cpp index eeb2bb2d833df..32058d0a47731 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -483,7 +483,7 @@ static Value *runtime_apply_type(jl_value_t *ty, jl_unionall_t *unionall, jl_cod // box if concrete type was not statically known Value *args[3]; args[0] = literal_pointer_val(ty); - args[1] = literal_pointer_val((jl_value_t*)ctx->linfo->def->sig); + args[1] = literal_pointer_val((jl_value_t*)ctx->linfo->def.method->sig); args[2] = builder.CreateInBoundsGEP( LLVM37_param(T_pjlvalue) emit_bitcast(ctx->spvals_ptr, T_ppjlvalue), @@ -1522,8 +1522,8 @@ static jl_cgval_t emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) return jl_cgval_t(); } - jl_unionall_t *unionall = (ctx->linfo->def && jl_is_unionall(ctx->linfo->def->sig)) - ? (jl_unionall_t*)ctx->linfo->def->sig + jl_unionall_t *unionall = (jl_is_method(ctx->linfo->def.method) && jl_is_unionall(ctx->linfo->def.method->sig)) + ? (jl_unionall_t*)ctx->linfo->def.method->sig : NULL; if (jl_is_abstract_ref_type(rt)) { diff --git a/src/cgutils.cpp b/src/cgutils.cpp index e9554702765fb..a14dff0ecfe91 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -299,8 +299,8 @@ static Value *literal_pointer_val_slot(jl_value_t *p) if (jl_is_method_instance(p)) { jl_method_instance_t *linfo = (jl_method_instance_t*)p; // Type-inferred functions are also prefixed with a - - if (linfo->def) - return julia_pgv("-", linfo->def->name, linfo->def->module, p); + if (jl_is_method(linfo->def.method)) + return julia_pgv("-", linfo->def.method->name, linfo->def.method->module, p); } if (jl_is_symbol(p)) { jl_sym_t *addr = (jl_sym_t*)p; @@ -1896,7 +1896,7 @@ static Value *_boxed_special(const jl_cgval_t &vinfo, Type *t, jl_codectx_t *ctx if (t == T_int1) return julia_bool(as_value(t, vinfo)); - if (ctx->linfo && ctx->linfo->def && !vinfo.ispointer()) { // don't bother codegen pre-boxing for toplevel + if (ctx->linfo && jl_is_method(ctx->linfo->def.method) && !vinfo.ispointer()) { // don't bother codegen pre-boxing for toplevel if (Constant *c = dyn_cast(vinfo.V)) { jl_value_t *s = static_constant_instance(c, jt); if (s) { diff --git a/src/codegen.cpp b/src/codegen.cpp index 82685cd2f57a9..d701a6181a66c 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1169,7 +1169,7 @@ jl_llvm_functions_t jl_compile_linfo(jl_method_instance_t **pli, jl_code_info_t jl_error("functions compiled with custom codegen params mustn't be cached"); // Fast path for the already-compiled case - if (li->def != NULL) { + if (jl_is_method(li->def.method)) { decls = li->functionObjectsDecls; bool already_compiled = params->cached && decls.functionObject != NULL; if (!src) { @@ -1190,10 +1190,8 @@ jl_llvm_functions_t jl_compile_linfo(jl_method_instance_t **pli, jl_code_info_t { // Step 1: Re-check if this was already compiled (it may have been while // we waited at the lock). - if (li->def == NULL) { + if (!jl_is_method(li->def.method)) { src = (jl_code_info_t*)li->inferred; - if (src && (jl_value_t*)src != jl_nothing) - src = jl_uncompress_ast(li->def, (jl_array_t*)src); if (decls.functionObject != NULL || !src || !jl_is_code_info(src) || li->jlcall_api == 2) { goto locked_out; } @@ -1209,7 +1207,7 @@ jl_llvm_functions_t jl_compile_linfo(jl_method_instance_t **pli, jl_code_info_t src = (jl_code_info_t*)li->inferred; if (src) { if ((jl_value_t*)src != jl_nothing) - src = jl_uncompress_ast(li->def, (jl_array_t*)src); + src = jl_uncompress_ast(li->def.method, (jl_array_t*)src); if (!jl_is_code_info(src)) { src = jl_type_infer(pli, world, 0); li = *pli; @@ -1229,7 +1227,7 @@ jl_llvm_functions_t jl_compile_linfo(jl_method_instance_t **pli, jl_code_info_t } else { if ((jl_value_t*)src != jl_nothing) - src = jl_uncompress_ast(li->def, (jl_array_t*)src); + src = jl_uncompress_ast(li->def.method, (jl_array_t*)src); } assert(jl_is_code_info(src)); @@ -1249,7 +1247,7 @@ jl_llvm_functions_t jl_compile_linfo(jl_method_instance_t **pli, jl_code_info_t pdecls = &decls; else if (li->min_world <= world && li->max_world >= world) pdecls = &li->functionObjectsDecls; - else if (li->def == NULL) + else if (!jl_is_method(li->def.method)) // toplevel thunk pdecls = &li->functionObjectsDecls; else pdecls = &decls; @@ -1267,7 +1265,8 @@ jl_llvm_functions_t jl_compile_linfo(jl_method_instance_t **pli, jl_code_info_t builder.restoreIP(old); builder.SetCurrentDebugLocation(olddl); JL_UNLOCK(&codegen_lock); // Might GC - jl_rethrow_with_add("error compiling %s", jl_symbol_name(li->def ? li->def->name : anonymous_sym)); + const char *mname = jl_symbol_name(jl_is_method(li->def.method) ? li->def.method->name : anonymous_sym); + jl_rethrow_with_add("error compiling %s", mname); } Function *f = (Function*)decls.functionObject; Function *specf = (Function*)decls.specFunctionObject; @@ -1278,7 +1277,7 @@ jl_llvm_functions_t jl_compile_linfo(jl_method_instance_t **pli, jl_code_info_t // Step 4. Prepare debug info to receive this function // record that this function name came from this linfo, // so we can build a reverse mapping for debug-info. - bool toplevel = li->def == NULL; + bool toplevel = !jl_is_method(li->def.method); if (!toplevel) { const DataLayout &DL = #if JL_LLVM_VERSION >= 30500 @@ -1301,13 +1300,13 @@ jl_llvm_functions_t jl_compile_linfo(jl_method_instance_t **pli, jl_code_info_t // don't delete code when debugging level >= 2 jl_options.debug_level <= 1 && // don't delete toplevel code - li->def && + jl_is_method(li->def.method) && // don't change inferred state li->inferred && // and there is something to delete (test this before calling jl_ast_flag_inlineable) li->inferred != jl_nothing && // don't delete the code for the generator - li != li->def->generator && + li != li->def.method->generator && // don't delete inlineable code, unless it is constant (li->jlcall_api == 2 || !jl_ast_flag_inlineable((jl_array_t*)li->inferred)) && // don't delete code when generating a precompile file @@ -1430,7 +1429,7 @@ uint64_t jl_get_llvm_fptr(llvm::Function *llvmf) static jl_method_instance_t *jl_get_unspecialized(jl_method_instance_t *method) { // one unspecialized version of a function can be shared among all cached specializations - jl_method_t *def = method->def; + jl_method_t *def = method->def.method; if (def->isstaged) { return method; } @@ -1469,9 +1468,9 @@ jl_generic_fptr_t jl_generate_fptr(jl_method_instance_t *li, void *_F, size_t wo return fptr; } jl_method_instance_t *unspec = NULL; - if (li->def) { - if (!li->def->isstaged && li->def->unspecialized) { - unspec = li->def->unspecialized; + if (jl_is_method(li->def.method)) { + if (!li->def.method->isstaged && li->def.method->unspecialized) { + unspec = li->def.method->unspecialized; } if (!F || !jl_can_finalize_function(F)) { // can't compile F in the JIT right now, @@ -1479,7 +1478,7 @@ jl_generic_fptr_t jl_generate_fptr(jl_method_instance_t *li, void *_F, size_t wo // and return its fptr instead if (!unspec) unspec = jl_get_unspecialized(li); // get-or-create the unspecialized version to cache the result - jl_code_info_t *src = unspec->def->isstaged ? jl_code_for_staged(unspec) : (jl_code_info_t*)unspec->def->source; + jl_code_info_t *src = unspec->def.method->isstaged ? jl_code_for_staged(unspec) : (jl_code_info_t*)unspec->def.method->source; fptr.fptr = unspec->fptr; fptr.jlcall_api = unspec->jlcall_api; if (fptr.fptr && fptr.jlcall_api) { @@ -1611,7 +1610,7 @@ void jl_extern_c(jl_function_t *f, jl_value_t *rt, jl_value_t *argt, char *name) extern "C" JL_DLLEXPORT void *jl_get_llvmf_defn(jl_method_instance_t *linfo, size_t world, bool getwrapper, bool optimize, const jl_cgparams_t params) { - if (linfo->def && linfo->def->source == NULL) { + if (jl_is_method(linfo->def.method) && linfo->def.method->source == NULL) { // not a generic function return NULL; } @@ -1620,12 +1619,17 @@ void *jl_get_llvmf_defn(jl_method_instance_t *linfo, size_t world, bool getwrapp JL_GC_PUSH1(&src); if (!src || (jl_value_t*)src == jl_nothing) { src = jl_type_infer(&linfo, world, 0); - if (!src) - src = linfo->def->isstaged ? jl_code_for_staged(linfo) : (jl_code_info_t*)linfo->def->source; - } - if (!src || (jl_value_t*)src == jl_nothing) + if (!src && jl_is_method(linfo->def.method)) + src = linfo->def.method->isstaged ? jl_code_for_staged(linfo) : (jl_code_info_t*)linfo->def.method->source; + } + if ((jl_value_t*)src == jl_nothing) + src = NULL; + if (src && !jl_is_code_info(src) && jl_is_method(linfo->def.method)) + src = jl_uncompress_ast(linfo->def.method, (jl_array_t*)src); + if (src && !jl_is_code_info(src)) + src = NULL; + if (!src) jl_error("source not found for function"); - src = jl_uncompress_ast(linfo->def, (jl_array_t*)src); // Backup the info for the nested compile JL_LOCK(&codegen_lock); @@ -1646,7 +1650,8 @@ void *jl_get_llvmf_defn(jl_method_instance_t *linfo, size_t world, bool getwrapp builder.restoreIP(old); builder.SetCurrentDebugLocation(olddl); JL_UNLOCK(&codegen_lock); // Might GC - jl_rethrow_with_add("error compiling %s", jl_symbol_name(linfo->def ? linfo->def->name : anonymous_sym)); + const char *mname = jl_symbol_name(jl_is_method(linfo->def.method) ? linfo->def.method->name : anonymous_sym); + jl_rethrow_with_add("error compiling %s", mname); } // Restore the previous compile context builder.restoreIP(old); @@ -1691,7 +1696,7 @@ void *jl_get_llvmf_defn(jl_method_instance_t *linfo, size_t world, bool getwrapp extern "C" JL_DLLEXPORT void *jl_get_llvmf_decl(jl_method_instance_t *linfo, size_t world, bool getwrapper, const jl_cgparams_t params) { - if (linfo->def && linfo->def->source == NULL) { + if (jl_is_method(linfo->def.method) && linfo->def.method->source == NULL) { // not a generic function return NULL; } @@ -1699,7 +1704,7 @@ void *jl_get_llvmf_decl(jl_method_instance_t *linfo, size_t world, bool getwrapp // compile this normally jl_llvm_functions_t decls = jl_compile_for_dispatch(&linfo, world); - if (decls.functionObject == NULL && linfo->jlcall_api == 2 && linfo->def) { + if (decls.functionObject == NULL && linfo->jlcall_api == 2 && jl_is_method(linfo->def.method)) { // normally we don't generate native code for these functions, so need an exception here // This leaks a bit of memory to cache native code that we'll never actually need JL_LOCK(&codegen_lock); @@ -1708,7 +1713,7 @@ void *jl_get_llvmf_decl(jl_method_instance_t *linfo, size_t world, bool getwrapp jl_code_info_t *src = NULL; src = jl_type_infer(&linfo, world, 0); if (!src) { - src = linfo->def->isstaged ? jl_code_for_staged(linfo) : (jl_code_info_t*)linfo->def->source; + src = linfo->def.method->isstaged ? jl_code_for_staged(linfo) : (jl_code_info_t*)linfo->def.method->source; } decls = jl_compile_linfo(&linfo, src, world, ¶ms); linfo->functionObjectsDecls = decls; @@ -3159,7 +3164,7 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, else if (f==jl_builtin_apply_type && nargs > 0) { size_t i; - if (ctx->linfo->def == NULL) { + if (jl_is_method(ctx->linfo->def.method)) { // don't bother codegen constant-folding for toplevel JL_GC_POP(); return false; @@ -4051,7 +4056,8 @@ static void emit_stmtpos(jl_value_t *expr, jl_codectx_t *ctx) ConstantInt::get(T_int32, jl_unbox_long(args[0]))); } else { - if (ctx->linfo->def == NULL) { + if (!jl_is_method(ctx->linfo->def.method)) { + // TODO: inference is invalid if this has an effect Value *world = builder.CreateLoad(prepare_global(jlgetworld_global)); builder.CreateStore(world, ctx->world_age_field); } @@ -4113,7 +4119,7 @@ static jl_cgval_t emit_expr(jl_value_t *expr, jl_codectx_t *ctx) expr = jl_box_int64(val); } } - if (needroot && ctx->linfo->def) { // toplevel exprs and some integers are already rooted + if (needroot && jl_is_method(ctx->linfo->def.method)) { // toplevel exprs and some integers are already rooted jl_add_method_root(ctx, expr); } return mark_julia_const(expr); @@ -4129,7 +4135,7 @@ static jl_cgval_t emit_expr(jl_value_t *expr, jl_codectx_t *ctx) return emit_invoke(ex, ctx); } else if (head == call_sym) { - if (ctx->linfo->def) { // don't bother codegen constant-folding for toplevel + if (jl_is_method(ctx->linfo->def.method)) { // don't bother codegen constant-folding for toplevel jl_value_t *c = static_eval(expr, ctx, true, true); if (c) { jl_add_method_root(ctx, c); @@ -4165,8 +4171,8 @@ static jl_cgval_t emit_expr(jl_value_t *expr, jl_codectx_t *ctx) jl_binding_t *bnd = NULL; bool issym = jl_is_symbol(mn); bool isglobalref = !issym && jl_is_globalref(mn); + jl_module_t *mod = ctx->module; if (issym || isglobalref) { - jl_module_t *mod = ctx->module; if (isglobalref) { mod = jl_globalref_mod(mn); mn = (jl_value_t*)jl_globalref_name(mn); @@ -4185,17 +4191,22 @@ static jl_cgval_t emit_expr(jl_value_t *expr, jl_codectx_t *ctx) name = literal_pointer_val((jl_value_t*)slot_symbol(sl, ctx)); } if (bp) { - Value *mdargs[4] = { name, bp, bp_owner, literal_pointer_val(bnd) }; + Value *mdargs[5] = { name, literal_pointer_val((jl_value_t*)mod), bp, bp_owner, literal_pointer_val(bnd) }; jl_cgval_t gf = mark_julia_type( - builder.CreateCall(prepare_call(jlgenericfunction_func), ArrayRef(&mdargs[0], 4)), + builder.CreateCall(prepare_call(jlgenericfunction_func), makeArrayRef(mdargs)), true, jl_function_type, ctx); if (jl_expr_nargs(ex) == 1) return gf; } Value *a1 = boxed(emit_expr(args[1], ctx), ctx); Value *a2 = boxed(emit_expr(args[2], ctx), ctx); - Value *mdargs[3] = { a1, a2, literal_pointer_val(args[3]) }; - builder.CreateCall(prepare_call(jlmethod_func), ArrayRef(&mdargs[0], 3)); + Value *mdargs[4] = { + /*argdata*/a1, + /*code*/a2, + /*module*/literal_pointer_val((jl_value_t*)ctx->module), + /*isstaged*/literal_pointer_val(args[3]) + }; + builder.CreateCall(prepare_call(jlmethod_func), makeArrayRef(mdargs)); return ghostValue(jl_void_type); } else if (head == const_sym) { @@ -4267,11 +4278,15 @@ static jl_cgval_t emit_expr(jl_value_t *expr, jl_codectx_t *ctx) if (!strcmp(jl_symbol_name(head), "$")) jl_error("syntax: prefix \"$\" in non-quoted expression"); if (jl_is_toplevel_only_expr(expr) && - ctx->linfo->def == NULL) { + !jl_is_method(ctx->linfo->def.method)) { JL_FEAT_REQUIRE(ctx, runtime); // call interpreter to run a toplevel expr from inside a // compiled toplevel thunk. - builder.CreateCall(prepare_call(jltopeval_func), literal_pointer_val(expr)); + Value *args[2] = { + literal_pointer_val((jl_value_t*)ctx->module), + literal_pointer_val(expr) + }; + builder.CreateCall(prepare_call(jltopeval_func), args); return ghostValue(jl_void_type); } if (head == abstracttype_sym || head == compositetype_sym || @@ -4330,7 +4345,7 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t jl_value_t *astrt = (jl_value_t*)jl_any_type; // infer it first, if necessary if (lam) { - name = jl_symbol_name(lam->def->name); + name = jl_symbol_name(lam->def.method->name); jl_code_info_t *src = NULL; if (!lam->inferred) // TODO: this isn't ideal to be unconditionally calling type inference from here src = jl_type_infer(&lam, world, 0); @@ -4946,7 +4961,7 @@ static Function *gen_jlcall_wrapper(jl_method_instance_t *lam, const jl_returnin allocate_gc_frame(b0, &ctx); FunctionType *ftype = f.decl->getFunctionType(); - size_t nargs = lam->def->nargs; + size_t nargs = lam->def.method->nargs; size_t nfargs = ftype->getNumParams(); Value **args = (Value**) alloca(nfargs*sizeof(Value*)); unsigned idx = 0; @@ -5143,7 +5158,6 @@ static std::unique_ptr emit_function( jl_llvm_functions_t *declarations, const jl_cgparams_t *params) { - jl_ptls_t ptls = jl_get_ptls_states(); assert(declarations && "Capturing declarations is always required"); // step 1. unpack AST and allocate codegen context for this function @@ -5156,18 +5170,18 @@ static std::unique_ptr emit_function( std::map arrayvars; std::map labels; ctx.arrayvars = &arrayvars; - ctx.module = lam->def ? lam->def->module : ptls->current_module; + ctx.module = jl_is_method(lam->def.method) ? lam->def.method->module : lam->def.module; ctx.linfo = lam; ctx.source = src; ctx.world = world; - ctx.name = jl_symbol_name(lam->def ? lam->def->name : anonymous_sym); + ctx.name = jl_symbol_name(jl_is_method(lam->def.method) ? lam->def.method->name : anonymous_sym); ctx.funcName = ctx.name; ctx.vaSlot = -1; ctx.vaStack = false; ctx.params = params; ctx.spvals_ptr = NULL; - ctx.nargs = lam->def ? lam->def->nargs : 0; - bool toplevel = lam->def == NULL; + ctx.nargs = jl_is_method(lam->def.method) ? lam->def.method->nargs : 0; + bool toplevel = !jl_is_method(lam->def.method); // step 1b. unpack debug information int coverage_mode = jl_options.code_coverage; @@ -5175,10 +5189,10 @@ static std::unique_ptr emit_function( StringRef filename = ""; StringRef dbgFuncName = ctx.name; int toplineno = -1; - if (lam->def) { - toplineno = lam->def->line; - if (lam->def->file != empty_sym) - filename = jl_symbol_name(lam->def->file); + if (jl_is_method(lam->def.method)) { + toplineno = lam->def.method->line; + if (lam->def.method->file != empty_sym) + filename = jl_symbol_name(lam->def.method->file); } ctx.file = filename; // jl_printf(JL_STDERR, "\n*** compiling %s at %s:%d\n\n", @@ -5204,7 +5218,7 @@ static std::unique_ptr emit_function( assert(lam->specTypes); // the specTypes field should always be assigned - if (nreq > 0 && lam->def->isva) { + if (nreq > 0 && lam->def.method->isva) { nreq--; va = 1; jl_sym_t *vn = (jl_sym_t*)jl_array_ptr_ref(src->slotnames, ctx.nargs - 1); @@ -5262,7 +5276,9 @@ static std::unique_ptr emit_function( jl_value_t *jlrettype = lam->rettype; bool specsig = false; - bool needsparams = lam->def ? jl_svec_len(lam->def->sparam_syms) != jl_svec_len(lam->sparam_vals) : false; + bool needsparams = jl_is_method(lam->def.method) + ? jl_svec_len(lam->def.method->sparam_syms) != jl_svec_len(lam->sparam_vals) + : false; for (i = 0; !needsparams && i < jl_svec_len(lam->sparam_vals); i++) { jl_value_t *e = jl_svecref(lam->sparam_vals, i); if (jl_is_typevar(e)) @@ -6257,7 +6273,7 @@ static std::unique_ptr emit_function( // copy ctx.roots into m->roots // if we created any new roots during codegen if (ctx.roots) { - jl_method_t *m = lam->def; + jl_method_t *m = lam->def.method; JL_LOCK(&m->writelock); if (m->roots == NULL) { m->roots = ctx.roots; @@ -6357,7 +6373,7 @@ extern "C" void jl_fptr_to_llvm(jl_fptr_t fptr, jl_method_instance_t *lam, int s funcName << "jlsysw_"; // it's a specsig wrapper else if (lam->jlcall_api == 1) funcName << "jsys1_"; // it's a jlcall without a specsig - const char* unadorned_name = jl_symbol_name(lam->def->name); + const char* unadorned_name = jl_symbol_name(lam->def.method->name); #if (defined(_OS_LINUX_) && JL_LLVM_VERSION < 30400) if (unadorned_name[0] == '@') unadorned_name++; @@ -6826,16 +6842,19 @@ static void init_julia_llvm_env(Module *m) exp_args.push_back(T_int1); expect_func = Intrinsic::getDeclaration(m, Intrinsic::expect, exp_args); - std::vector args3(0); - args3.push_back(T_pjlvalue); + std::vector args_topeval(0); + args_topeval.push_back(T_pjlvalue); + args_topeval.push_back(T_pjlvalue); jltopeval_func = - Function::Create(FunctionType::get(T_pjlvalue, args3, false), + Function::Create(FunctionType::get(T_pjlvalue, args_topeval, false), Function::ExternalLinkage, "jl_toplevel_eval", m); add_named_global(jltopeval_func, &jl_toplevel_eval); + std::vector args_copyast(0); + args_copyast.push_back(T_pjlvalue); jlcopyast_func = - Function::Create(FunctionType::get(T_pjlvalue, args3, false), + Function::Create(FunctionType::get(T_pjlvalue, args_copyast, false), Function::ExternalLinkage, "jl_copy_ast", m); add_named_global(jlcopyast_func, &jl_copy_ast); @@ -6852,6 +6871,7 @@ static void init_julia_llvm_env(Module *m) mdargs.push_back(T_pjlvalue); mdargs.push_back(T_pjlvalue); mdargs.push_back(T_pjlvalue); + mdargs.push_back(T_pjlvalue); jlmethod_func = Function::Create(FunctionType::get(T_void, mdargs, false), Function::ExternalLinkage, @@ -6860,6 +6880,7 @@ static void init_julia_llvm_env(Module *m) std::vector funcdefargs(0); funcdefargs.push_back(T_pjlvalue); + funcdefargs.push_back(T_pjlvalue); funcdefargs.push_back(T_ppjlvalue); funcdefargs.push_back(T_pjlvalue); funcdefargs.push_back(T_pjlvalue); diff --git a/src/datatype.c b/src/datatype.c index 746d3a1b762a2..1c2486414b840 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -66,17 +66,11 @@ JL_DLLEXPORT jl_typename_t *jl_new_typename_in(jl_sym_t *name, jl_module_t *modu return tn; } -JL_DLLEXPORT jl_typename_t *jl_new_typename(jl_sym_t *name) -{ - jl_ptls_t ptls = jl_get_ptls_states(); - return jl_new_typename_in(name, ptls->current_module); -} - // allocating DataTypes ----------------------------------------------------------- -jl_datatype_t *jl_new_abstracttype(jl_value_t *name, jl_datatype_t *super, jl_svec_t *parameters) +jl_datatype_t *jl_new_abstracttype(jl_value_t *name, jl_module_t *module, jl_datatype_t *super, jl_svec_t *parameters) { - return jl_new_datatype((jl_sym_t*)name, super, parameters, jl_emptysvec, jl_emptysvec, 1, 0, 0); + return jl_new_datatype((jl_sym_t*)name, module, super, parameters, jl_emptysvec, jl_emptysvec, 1, 0, 0); } jl_datatype_t *jl_new_uninitialized_datatype(void) @@ -330,15 +324,18 @@ void jl_compute_field_offsets(jl_datatype_t *st) extern int jl_boot_file_loaded; -JL_DLLEXPORT jl_datatype_t *jl_new_datatype(jl_sym_t *name, jl_datatype_t *super, - jl_svec_t *parameters, - jl_svec_t *fnames, jl_svec_t *ftypes, - int abstract, int mutabl, - int ninitialized) +JL_DLLEXPORT jl_datatype_t *jl_new_datatype( + jl_sym_t *name, + jl_module_t *module, + jl_datatype_t *super, + jl_svec_t *parameters, + jl_svec_t *fnames, + jl_svec_t *ftypes, + int abstract, int mutabl, + int ninitialized) { - jl_ptls_t ptls = jl_get_ptls_states(); - jl_datatype_t *t=NULL; - jl_typename_t *tn=NULL; + jl_datatype_t *t = NULL; + jl_typename_t *tn = NULL; JL_GC_PUSH2(&t, &tn); if (!jl_boot_file_loaded && jl_is_symbol(name)) { @@ -357,7 +354,7 @@ JL_DLLEXPORT jl_datatype_t *jl_new_datatype(jl_sym_t *name, jl_datatype_t *super t = jl_new_uninitialized_datatype(); else tn = t->name; - // init before possibly calling jl_new_typename + // init before possibly calling jl_new_typename_in t->super = super; if (super != NULL) jl_gc_wb(t, t->super); t->parameters = parameters; @@ -378,9 +375,9 @@ JL_DLLEXPORT jl_datatype_t *jl_new_datatype(jl_sym_t *name, jl_datatype_t *super tn = (jl_typename_t*)name; } else { - tn = jl_new_typename((jl_sym_t*)name); + tn = jl_new_typename_in((jl_sym_t*)name, module); if (!abstract) { - tn->mt = jl_new_method_table(name, ptls->current_module); + tn->mt = jl_new_method_table(name, module); jl_gc_wb(tn, tn->mt); } } @@ -412,10 +409,11 @@ JL_DLLEXPORT jl_datatype_t *jl_new_datatype(jl_sym_t *name, jl_datatype_t *super return t; } -JL_DLLEXPORT jl_datatype_t *jl_new_primitivetype(jl_value_t *name, jl_datatype_t *super, +JL_DLLEXPORT jl_datatype_t *jl_new_primitivetype(jl_value_t *name, jl_module_t *module, + jl_datatype_t *super, jl_svec_t *parameters, size_t nbits) { - jl_datatype_t *bt = jl_new_datatype((jl_sym_t*)name, super, parameters, + jl_datatype_t *bt = jl_new_datatype((jl_sym_t*)name, module, super, parameters, jl_emptysvec, jl_emptysvec, 0, 0, 0); uint32_t nbytes = (nbits + 7) / 8; uint32_t alignm = next_power_of_two(nbytes); diff --git a/src/dump.c b/src/dump.c index 601d73ec1d0f5..c020c554b29e6 100644 --- a/src/dump.c +++ b/src/dump.c @@ -442,7 +442,7 @@ static void jl_update_all_fptrs(void) jl_method_instance_t **linfos = (jl_method_instance_t**)malloc(sizeof(jl_method_instance_t*) * sysimg_fvars_max); for (i = 0; i < delayed_fptrs_n; i++) { jl_method_instance_t *li = delayed_fptrs[i].li; - assert(li->def && li->jlcall_api && li->jlcall_api != 2); + assert(jl_is_method(li->def.method) && li->jlcall_api && li->jlcall_api != 2); int32_t cfunc = delayed_fptrs[i].cfunc - 1; if (cfunc >= 0) { jl_fptr_to_llvm((jl_fptr_t)(uintptr_t)fvars[cfunc], li, 1); @@ -961,7 +961,7 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li if (li->max_world == 0 && li->min_world == 0) { internal = 1; // not world-tracked } - else if (!li->def || module_in_worklist(li->def->module)) { + else if (!jl_is_method(li->def.method) || module_in_worklist(li->def.method->module)) { if (li->max_world == ~(size_t)0) { internal = 2; // update world on deserialization } @@ -978,9 +978,9 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li } jl_serialize_value(s, (jl_value_t*)li->specTypes); if (s->mode == MODE_MODULE && !internal) - jl_serialize_value(s, (jl_value_t*)li->def->sig); + jl_serialize_value(s, (jl_value_t*)li->def.method->sig); else - jl_serialize_value(s, (jl_value_t*)li->def); + jl_serialize_value(s, li->def.value); if (s->mode == MODE_MODULE) { write_uint8(s->s, internal); if (!internal) @@ -995,7 +995,7 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li write_int32(s->s, li->min_world); write_int32(s->s, li->max_world); } - if (li->def) { + if (jl_is_method(li->def.method)) { uint16_t id = jl_fptr_id((void*)(uintptr_t)li->fptr); if (li->jlcall_api == 2) { write_int8(s->s, 2); @@ -1266,7 +1266,7 @@ static void jl_serialize_backedges(jl_serializer_state *s) for (i = 0; i < edges_map.size; i += 2) { jl_method_instance_t *caller = (jl_method_instance_t*)table[i]; jl_array_t *callee = (jl_array_t*)table[i + 1]; - if (callee != HT_NOTFOUND && module_in_worklist(caller->def->module)) { + if (callee != HT_NOTFOUND && module_in_worklist(caller->def.method->module)) { arraylist_push(&worklist, (void*)caller); } } @@ -1776,9 +1776,9 @@ static jl_value_t *jl_deserialize_value_method_instance(jl_serializer_state *s, li->specTypes = (jl_value_t*)jl_deserialize_value(s, (jl_value_t**)&li->specTypes); if (li->specTypes) jl_gc_wb(li, li->specTypes); - li->def = (jl_method_t*)jl_deserialize_value(s, (jl_value_t**)&li->def); - if (li->def) - jl_gc_wb(li, li->def); + li->def.value = jl_deserialize_value(s, &li->def.value); + if (li->def.value) + jl_gc_wb(li, li->def.value); int internal = 0; if (s->mode == MODE_MODULE) { @@ -1828,7 +1828,7 @@ static jl_value_t *jl_deserialize_value_method_instance(jl_serializer_state *s, li->functionObjectsDecls.specFunctionObject = NULL; li->inInference = 0; int8_t jlcall_api = read_int8(s->s); - if (jlcall_api == 2 || jlcall_api == 0 || li->def == NULL) { + if (jlcall_api == 2 || jlcall_api == 0 || !jl_is_method(li->def.method)) { li->fptr = NULL; li->jlcall_api = jlcall_api; } @@ -2204,12 +2204,12 @@ static void jl_insert_backedges(linkedlist_t *list) assert(jl_is_method_instance(caller)); jl_array_t *callees = list->def[i].callee; assert(jl_is_array(callees)); - if (!caller->inferred || module_in_worklist(caller->def->module)) { + if (!caller->inferred || module_in_worklist(caller->def.method->module)) { for (j = 0; j < jl_array_len(callees); j++) { jl_value_t *callee = jl_array_ptr_ref(callees, j); if (jl_is_method_instance(callee)) { jl_method_instance_t *callee_mi = (jl_method_instance_t*)callee; - if (!module_in_worklist(callee_mi->def->module)) { + if (!module_in_worklist(callee_mi->def.method->module)) { // verify that this MethodInstance is still the correct lookup for this callee sig jl_value_t *sig = callee_mi->specTypes; jl_method_t *m = NULL; @@ -2222,7 +2222,7 @@ static void jl_insert_backedges(linkedlist_t *list) if (entry != NULL) m = entry->func.method; } - if (m != callee_mi->def) { + if (m != callee_mi->def.method) { // probably no good, just invalidate everything now jl_method_instance_delete(caller); break; @@ -3169,7 +3169,7 @@ static jl_method_t *jl_recache_method(jl_method_t *m, size_t start, arraylist_t static jl_method_instance_t *jl_recache_method_instance(jl_method_instance_t *li, size_t start, arraylist_t *dependent_worlds) { - jl_datatype_t *sig = (jl_datatype_t*)li->def; + jl_datatype_t *sig = (jl_datatype_t*)li->def.value; assert(jl_is_datatype(sig) || jl_is_unionall(sig)); jl_datatype_t *ftype = jl_first_argument_datatype((jl_value_t*)sig); jl_methtable_t *mt = ftype->name->mt; diff --git a/src/gf.c b/src/gf.c index 683b11bc1d24c..3be37fce6fc59 100644 --- a/src/gf.c +++ b/src/gf.c @@ -214,14 +214,15 @@ void jl_mk_builtin_func(jl_datatype_t *dt, const char *name, jl_fptr_t fptr) li->max_world = ~(size_t)0; JL_GC_PUSH1(&li); - li->def = jl_new_method_uninit(); - jl_gc_wb(li, li->def); - li->def->name = sname; - li->def->module = jl_core_module; - li->def->isva = 1; - li->def->nargs = 2; - li->def->sig = (jl_value_t*)jl_anytuple_type; - li->def->sparam_syms = jl_emptysvec; + jl_method_t *m = jl_new_method_uninit(); + li->def.method = m; + jl_gc_wb(li, m); + m->name = sname; + m->module = jl_core_module; + m->isva = 1; + m->nargs = 2; + m->sig = (jl_value_t*)jl_anytuple_type; + m->sparam_syms = jl_emptysvec; jl_methtable_t *mt = dt->name->mt; jl_typemap_insert(&mt->cache, (jl_value_t*)mt, jl_anytuple_type, @@ -261,7 +262,7 @@ jl_code_info_t *jl_type_infer(jl_method_instance_t **pli, size_t world, int forc li->inInference = 1; jl_svec_t *linfo_src_rettype = (jl_svec_t*)jl_apply_with_saved_exception_state(fargs, 3, 0); ptls->world_age = last_age; - assert((li->def || li->inInference == 0) && "inference failed on a toplevel expr"); + assert((jl_is_method(li->def.method) || li->inInference == 0) && "inference failed on a toplevel expr"); jl_code_info_t *src = NULL; if (jl_is_svec(linfo_src_rettype) && jl_svec_len(linfo_src_rettype) == 3 && @@ -315,7 +316,7 @@ static void update_world_bound(jl_method_instance_t *replaced, jl_typemap_visito update.replaced = replaced; update.world = world; - jl_method_t *m = replaced->def; + jl_method_t *m = replaced->def.method; // update the world-valid in the specializations caches jl_typemap_visitor(m->specializations, fptr, (void*)&update); // update the world-valid in the invoke cache @@ -336,14 +337,14 @@ JL_DLLEXPORT jl_method_instance_t* jl_set_method_inferred( assert(min_world <= max_world && "attempting to set invalid world constraints"); assert(li->inInference && "shouldn't be caching an inference result for a MethodInstance that wasn't being inferred"); if (min_world != li->min_world || max_world != li->max_world) { - if (li->def == NULL) { + if (!jl_is_method(li->def.method)) { // thunks don't have multiple references, so just update in-place li->min_world = min_world; li->max_world = max_world; } else { - JL_LOCK(&li->def->writelock); - assert(min_world >= li->def->min_world); + JL_LOCK(&li->def.method->writelock); + assert(min_world >= li->def.method->min_world); int isinferred = jl_is_rettype_inferred(li); if (!isinferred && li->min_world >= min_world && li->max_world <= max_world) { // expand the current (uninferred) entry to cover the full inferred range @@ -354,12 +355,12 @@ JL_DLLEXPORT jl_method_instance_t* jl_set_method_inferred( if (li->min_world != min_world) { li->min_world = min_world; update.world = min_world; - jl_typemap_visitor(li->def->specializations, set_min_world2, (void*)&update); + jl_typemap_visitor(li->def.method->specializations, set_min_world2, (void*)&update); } if (li->max_world != max_world) { li->max_world = max_world; update.world = max_world; - jl_typemap_visitor(li->def->specializations, set_max_world2, (void*)&update); + jl_typemap_visitor(li->def.method->specializations, set_max_world2, (void*)&update); } } else { @@ -370,7 +371,7 @@ JL_DLLEXPORT jl_method_instance_t* jl_set_method_inferred( if (li->max_world >= min_world && li->min_world <= max_world) { // there is a non-zero overlap between [li->min, li->max] and [min, max] // there are now 4 regions left to consider - // TODO: also take into account li->def->world range when computing preferred division + // TODO: also take into account li->def.method->world range when computing preferred division if (li->max_world > max_world) { // prefer making it applicable to future ages, // as those are more likely to be useful @@ -388,15 +389,15 @@ JL_DLLEXPORT jl_method_instance_t* jl_set_method_inferred( } // build a new entry to describe the new (inferred) applicability - li = jl_get_specialized(li->def, li->specTypes, li->sparam_vals); + li = jl_get_specialized(li->def.method, li->specTypes, li->sparam_vals); li->min_world = min_world; li->max_world = max_world; - jl_typemap_insert(&li->def->specializations, (jl_value_t*)li->def, + jl_typemap_insert(&li->def.method->specializations, li->def.value, (jl_tupletype_t*)li->specTypes, NULL, jl_emptysvec, (jl_value_t*)li, 0, &tfunc_cache, li->min_world, li->max_world, NULL); } - JL_UNLOCK(&li->def->writelock); + JL_UNLOCK(&li->def.method->writelock); } } @@ -1247,7 +1248,7 @@ static int JL_DEBUG_METHOD_INVALIDATION = 0; // invalidate cached methods that had an edge to a replaced method static void invalidate_method_instance(jl_method_instance_t *replaced, size_t max_world, int depth) { - JL_LOCK_NOGC(&replaced->def->writelock); + JL_LOCK_NOGC(&replaced->def.method->writelock); jl_array_t *backedges = replaced->backedges; if (replaced->max_world > max_world) { // recurse to all backedges to update their valid range also @@ -1270,7 +1271,7 @@ static void invalidate_method_instance(jl_method_instance_t *replaced, size_t ma } } replaced->backedges = NULL; - JL_UNLOCK_NOGC(&replaced->def->writelock); + JL_UNLOCK_NOGC(&replaced->def.method->writelock); } // invalidate cached methods that overlap this definition @@ -1286,7 +1287,7 @@ static int invalidate_backedges(jl_typemap_entry_t *oldentry, struct typemap_int struct set_world def; def.replaced = oldentry->func.linfo; def.world = closure->max_world; - jl_method_t *m = def.replaced->def; + jl_method_t *m = def.replaced->def.method; // truncate the max-valid in the invoke cache if (m->invokes.unknown != NULL) @@ -1297,7 +1298,7 @@ static int invalidate_backedges(jl_typemap_entry_t *oldentry, struct typemap_int jl_typemap_visitor(gf->name->mt->cache, set_max_world2, (void*)&def); // invalidate backedges - JL_LOCK_NOGC(&def.replaced->def->writelock); + JL_LOCK_NOGC(&def.replaced->def.method->writelock); jl_array_t *backedges = def.replaced->backedges; if (backedges) { size_t i, l = jl_array_len(backedges); @@ -1308,7 +1309,7 @@ static int invalidate_backedges(jl_typemap_entry_t *oldentry, struct typemap_int } closure->invalidated = 1; def.replaced->backedges = NULL; - JL_UNLOCK_NOGC(&def.replaced->def->writelock); + JL_UNLOCK_NOGC(&def.replaced->def.method->writelock); } return 1; } @@ -1317,7 +1318,7 @@ static int invalidate_backedges(jl_typemap_entry_t *oldentry, struct typemap_int JL_DLLEXPORT void jl_method_instance_add_backedge(jl_method_instance_t *callee, jl_method_instance_t *caller) { assert(callee->min_world <= caller->min_world && callee->max_world >= caller->max_world); - JL_LOCK(&callee->def->writelock); + JL_LOCK(&callee->def.method->writelock); if (!callee->backedges) { // lazy-init the backedges array callee->backedges = jl_alloc_vec_any(1); @@ -1334,7 +1335,7 @@ JL_DLLEXPORT void jl_method_instance_add_backedge(jl_method_instance_t *callee, jl_array_ptr_1d_push(callee->backedges, (jl_value_t*)caller); } } - JL_UNLOCK(&callee->def->writelock); + JL_UNLOCK(&callee->def.method->writelock); } // add a backedge from a non-existent signature to caller @@ -1619,8 +1620,8 @@ jl_llvm_functions_t jl_compile_for_dispatch(jl_method_instance_t **pli, size_t w if (jl_options.compile_enabled == JL_OPTIONS_COMPILE_OFF || jl_options.compile_enabled == JL_OPTIONS_COMPILE_MIN) { // copy fptr from the template method definition - jl_method_t *def = li->def; - if (def && !def->isstaged && def->unspecialized) { + jl_method_t *def = li->def.method; + if (jl_is_method(def) && !def->isstaged && def->unspecialized) { if (def->unspecialized->jlcall_api == 2) { li->functionObjectsDecls.functionObject = NULL; li->functionObjectsDecls.specFunctionObject = NULL; @@ -1651,8 +1652,8 @@ jl_llvm_functions_t jl_compile_for_dispatch(jl_method_instance_t **pli, size_t w return decls; jl_code_info_t *src = NULL; - if (li->def && !jl_is_rettype_inferred(li) && - jl_symbol_name(li->def->name)[0] != '@') { + if (jl_is_method(li->def.method) && !jl_is_rettype_inferred(li) && + jl_symbol_name(li->def.method->name)[0] != '@') { // don't bother with typeinf on macros or toplevel thunks // but try to infer everything else src = jl_type_infer(pli, world, 0); @@ -1701,7 +1702,7 @@ jl_method_instance_t *jl_get_specialization1(jl_tupletype_t *types, size_t world jl_method_instance_t *sf = jl_method_lookup_by_type(mt, types, 1, 1, 1, world); assert(sf == NULL || (sf->min_world <= world && sf->max_world >= world)); JL_GC_PUSH1(&sf); - if (sf != NULL && jl_has_call_ambiguities(types, sf->def)) { + if (sf != NULL && jl_has_call_ambiguities(types, sf->def.method)) { sf = NULL; } JL_GC_POP(); @@ -1904,7 +1905,7 @@ STATIC_INLINE jl_method_instance_t *jl_lookup_generic_(jl_value_t **args, uint32 #ifdef JL_TRACE if (traceen) - jl_printf(JL_STDOUT, " at %s:%d\n", jl_symbol_name(mfunc->def->file), mfunc->def->line); + jl_printf(JL_STDOUT, " at %s:%d\n", jl_symbol_name(mfunc->def.method->file), mfunc->def.method->line); #endif return mfunc; } @@ -2100,12 +2101,12 @@ jl_function_t *jl_new_generic_function_with_supertype(jl_sym_t *name, jl_module_ } jl_sym_t *tname = jl_symbol(prefixed); free(prefixed); - jl_datatype_t *ftype = (jl_datatype_t*)jl_new_datatype(tname, st, jl_emptysvec, jl_emptysvec, jl_emptysvec, 0, 0, 0); + jl_datatype_t *ftype = (jl_datatype_t*)jl_new_datatype( + tname, module, st, jl_emptysvec, jl_emptysvec, jl_emptysvec, 0, 0, 0); assert(jl_is_datatype(ftype)); JL_GC_PUSH1(&ftype); - ftype->name->mt->name = name; jl_gc_wb(ftype->name->mt, name); - ftype->name->module = module; jl_gc_wb(ftype->name, module); - ftype->name->mt->module = module; jl_gc_wb(ftype->name->mt, module); + ftype->name->mt->name = name; + jl_gc_wb(ftype->name->mt, name); jl_set_const(module, tname, (jl_value_t*)ftype); jl_value_t *f = jl_new_struct(ftype); ftype->instance = f; jl_gc_wb(ftype, f); diff --git a/src/init.c b/src/init.c index 612f6b1e3c54f..1cdc0db222640 100644 --- a/src/init.c +++ b/src/init.c @@ -664,11 +664,11 @@ void _julia_init(JL_IMAGE_SEARCH rel) jl_internal_main_module = jl_main_module; ptls->current_module = jl_core_module; - for (int t = 0;t < jl_n_threads;t++) { - jl_all_tls_states[t]->root_task->current_module = ptls->current_module; + for (int t = 0; t < jl_n_threads; t++) { + jl_all_tls_states[t]->root_task->current_module = jl_core_module; } - jl_load("boot.jl"); + jl_load(jl_core_module, "boot.jl"); jl_get_builtin_hooks(); jl_boot_file_loaded = 1; jl_init_box_caches(); @@ -713,8 +713,8 @@ void _julia_init(JL_IMAGE_SEARCH rel) jl_add_standard_imports(jl_main_module); } ptls->current_module = jl_main_module; - for (int t = 0;t < jl_n_threads;t++) { - jl_all_tls_states[t]->root_task->current_module = ptls->current_module; + for (int t = 0; t < jl_n_threads; t++) { + jl_all_tls_states[t]->root_task->current_module = jl_main_module; } // This needs to be after jl_start_threads diff --git a/src/interpreter.c b/src/interpreter.c index 99fc01c7c7bb0..b78fd15686fd3 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -24,18 +24,9 @@ typedef struct { static jl_value_t *eval(jl_value_t *e, interpreter_state *s); static jl_value_t *eval_body(jl_array_t *stmts, interpreter_state *s, int start, int toplevel); -jl_value_t *jl_eval_module_expr(jl_expr_t *ex); +jl_value_t *jl_eval_module_expr(jl_module_t *m, jl_expr_t *ex); int jl_is_toplevel_only_expr(jl_value_t *e); -jl_value_t *jl_interpret_toplevel_expr(jl_value_t *e) -{ - size_t last_age = jl_get_ptls_states()->world_age; - jl_get_ptls_states()->world_age = jl_world_counter; - jl_value_t *ret = eval(e, NULL); - jl_get_ptls_states()->world_age = last_age; - return ret; -} - jl_value_t *jl_interpret_toplevel_expr_in(jl_module_t *m, jl_value_t *e, jl_code_info_t *src, jl_svec_t *sparam_vals) @@ -200,7 +191,7 @@ static int jl_source_nssavalues(jl_code_info_t *src) static jl_value_t *eval(jl_value_t *e, interpreter_state *s) { jl_ptls_t ptls = jl_get_ptls_states(); - jl_code_info_t *src = s==NULL ? NULL : s->src; + jl_code_info_t *src = s->src; if (jl_is_ssavalue(e)) { ssize_t id = ((jl_ssavalue_t*)e)->id; if (src == NULL || id >= jl_source_nssavalues(src) || id < 0 || s->locals == NULL) @@ -226,7 +217,7 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s) } if (jl_is_quotenode(e)) return jl_fieldref(e,0); - jl_module_t *modu = (s == NULL ? ptls->current_module : s->module); + jl_module_t *modu = s->module; if (jl_is_symbol(e)) { // bare symbols appear in toplevel exprs not wrapped in `thunk` jl_value_t *v = jl_get_global(modu, (jl_sym_t*)e); if (v == NULL) @@ -291,7 +282,7 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s) bp = &b->value; bp_owner = (jl_value_t*)modu; } - jl_value_t *gf = jl_generic_function_def(fname, bp, bp_owner, b); + jl_value_t *gf = jl_generic_function_def(fname, modu, bp, bp_owner, b); if (jl_expr_nargs(ex) == 1) return gf; } @@ -300,7 +291,7 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s) JL_GC_PUSH2(&atypes, &meth); atypes = eval(args[1], s); meth = eval(args[2], s); - jl_method_def((jl_svec_t*)atypes, (jl_code_info_t*)meth, args[3]); + jl_method_def((jl_svec_t*)atypes, (jl_code_info_t*)meth, s->module, args[3]); JL_GC_POP(); return jl_nothing; } @@ -347,7 +338,7 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s) name = (jl_value_t*)jl_globalref_name(name); } assert(jl_is_symbol(name)); - dt = jl_new_abstracttype(name, NULL, (jl_svec_t*)para); + dt = jl_new_abstracttype(name, modu, NULL, (jl_svec_t*)para); w = dt->name->wrapper; jl_binding_t *b = jl_get_binding_wr(modu, (jl_sym_t*)name); temp = b->value; @@ -395,7 +386,7 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s) if (nb < 1 || nb>=(1<<23) || (nb&7) != 0) jl_errorf("invalid number of bits in type %s", jl_symbol_name((jl_sym_t*)name)); - dt = jl_new_primitivetype(name, NULL, (jl_svec_t*)para, nb); + dt = jl_new_primitivetype(name, modu, NULL, (jl_svec_t*)para, nb); w = dt->name->wrapper; jl_binding_t *b = jl_get_binding_wr(modu, (jl_sym_t*)name); temp = b->value; @@ -437,7 +428,7 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s) assert(jl_is_symbol(name)); assert(jl_is_svec(para)); temp = eval(args[2], s); // field names - dt = jl_new_datatype((jl_sym_t*)name, NULL, (jl_svec_t*)para, + dt = jl_new_datatype((jl_sym_t*)name, modu, NULL, (jl_svec_t*)para, (jl_svec_t*)temp, NULL, 0, args[5]==jl_true ? 1 : 0, jl_unbox_long(args[6])); w = dt->name->wrapper; @@ -485,10 +476,10 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s) return (jl_value_t*)jl_nothing; } else if (ex->head == module_sym) { - return jl_eval_module_expr(ex); + return jl_eval_module_expr(s->module, ex); } else if (ex->head == thunk_sym) { - return jl_toplevel_eval((jl_value_t*)ex); + return jl_toplevel_eval(s->module, (jl_value_t*)ex); } else if (ex->head == error_sym || ex->head == jl_incomplete_sym) { if (nargs == 0) @@ -505,19 +496,24 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s) return (jl_value_t*)jl_nothing; } -jl_value_t *jl_toplevel_eval_body(jl_array_t *stmts) +jl_value_t *jl_toplevel_eval_body(jl_module_t *m, jl_array_t *stmts) { size_t last_age = jl_get_ptls_states()->world_age; - jl_value_t *ret = eval_body(stmts, NULL, 0, 1); + interpreter_state s; + s.src = NULL; + s.module = m; + s.locals = NULL; + s.sparam_vals = NULL; + jl_value_t *ret = eval_body(stmts, &s, 0, 1); jl_get_ptls_states()->world_age = last_age; return ret; } static jl_value_t *eval_body(jl_array_t *stmts, interpreter_state *s, int start, int toplevel) { - jl_ptls_t ptls = jl_get_ptls_states(); jl_handler_t __eh; - size_t i=start, ns = jl_array_len(stmts); + size_t i = start; + size_t ns = jl_array_len(stmts); while (1) { if (i >= ns) @@ -534,7 +530,7 @@ static jl_value_t *eval_body(jl_array_t *stmts, interpreter_state *s, int start, if (head == return_sym) { jl_value_t *ex = jl_exprarg(stmt, 0); if (toplevel && jl_is_toplevel_only_expr(ex)) - return jl_toplevel_eval(ex); + return jl_toplevel_eval(s->module, ex); else return eval(ex, s); } @@ -559,7 +555,7 @@ static jl_value_t *eval_body(jl_array_t *stmts, interpreter_state *s, int start, sym = (jl_value_t*)jl_globalref_name(sym); } else { - m = (s == NULL ? ptls->current_module : s->module); + m = s->module; } assert(jl_is_symbol(sym)); JL_GC_PUSH1(&rhs); @@ -590,7 +586,7 @@ static jl_value_t *eval_body(jl_array_t *stmts, interpreter_state *s, int start, } else { #ifdef _OS_WINDOWS_ - if (ptls->exception_in_transit == jl_stackovf_exception) + if (jl_get_ptls_states()->exception_in_transit == jl_stackovf_exception) _resetstkoflw(); #endif i = jl_unbox_long(jl_exprarg(stmt, 0)) - 1; @@ -602,7 +598,7 @@ static jl_value_t *eval_body(jl_array_t *stmts, interpreter_state *s, int start, jl_pop_handler(hand_n_leave); } else if (toplevel && jl_is_toplevel_only_expr(stmt)) { - jl_toplevel_eval(stmt); + jl_toplevel_eval(s->module, stmt); } else { eval(stmt, s); @@ -635,17 +631,17 @@ jl_value_t *jl_interpret_call(jl_method_instance_t *lam, jl_value_t **args, uint return lam->inferred_const; jl_code_info_t *src = (jl_code_info_t*)lam->inferred; if (!src || (jl_value_t*)src == jl_nothing) { - if (lam->def->isstaged) { + if (lam->def.method->isstaged) { src = jl_code_for_staged(lam); lam->inferred = (jl_value_t*)src; jl_gc_wb(lam, src); } else { - src = (jl_code_info_t*)lam->def->source; + src = (jl_code_info_t*)lam->def.method->source; } } if (src && (jl_value_t*)src != jl_nothing) { - src = jl_uncompress_ast(lam->def, (jl_array_t*)src); + src = jl_uncompress_ast(lam->def.method, (jl_array_t*)src); lam->inferred = (jl_value_t*)src; jl_gc_wb(lam, src); } @@ -661,12 +657,12 @@ jl_value_t *jl_interpret_call(jl_method_instance_t *lam, jl_value_t **args, uint locals[1] = (jl_value_t*)stmts; interpreter_state s; s.src = src; - s.module = lam->def->module; + s.module = lam->def.method->module; s.locals = locals + 2; s.sparam_vals = lam->sparam_vals; size_t i; - for (i = 0; i < lam->def->nargs; i++) { - if (lam->def->isva && i == lam->def->nargs - 1) + for (i = 0; i < lam->def.method->nargs; i++) { + if (lam->def.method->isva && i == lam->def.method->nargs - 1) s.locals[i] = jl_f_tuple(NULL, &args[i], nargs - i); else s.locals[i] = args[i]; @@ -676,9 +672,8 @@ jl_value_t *jl_interpret_call(jl_method_instance_t *lam, jl_value_t **args, uint return r; } -jl_value_t *jl_interpret_toplevel_thunk(jl_code_info_t *src) +jl_value_t *jl_interpret_toplevel_thunk(jl_module_t *m, jl_code_info_t *src) { - jl_ptls_t ptls = jl_get_ptls_states(); jl_array_t *stmts = src->code; assert(jl_typeis(stmts, jl_array_any_type)); jl_value_t **locals; @@ -686,7 +681,7 @@ jl_value_t *jl_interpret_toplevel_thunk(jl_code_info_t *src) interpreter_state s; s.src = src; s.locals = locals; - s.module = ptls->current_module; + s.module = m; s.sparam_vals = jl_emptysvec; size_t last_age = jl_get_ptls_states()->world_age; jl_value_t *r = eval_body(stmts, &s, 0, 1); diff --git a/src/jlapi.c b/src/jlapi.c index 703ec688aad8c..be3e74be8b578 100644 --- a/src/jlapi.c +++ b/src/jlapi.c @@ -74,7 +74,7 @@ JL_DLLEXPORT jl_value_t *jl_eval_string(const char *str) JL_GC_PUSH1(&ast); size_t last_age = jl_get_ptls_states()->world_age; jl_get_ptls_states()->world_age = jl_get_world_counter(); - r = jl_toplevel_eval(ast); + r = jl_toplevel_eval_in(jl_main_module, ast); jl_get_ptls_states()->world_age = last_age; JL_GC_POP(); jl_exception_clear(); diff --git a/src/jlfrontend.scm b/src/jlfrontend.scm index 28f62d2525fb0..59828a423173e 100644 --- a/src/jlfrontend.scm +++ b/src/jlfrontend.scm @@ -119,19 +119,23 @@ ;; called by jl_eval_module_expr (define (module-default-defs e) (jl-expand-to-thunk - (let ((name (caddr e)) - (body (cadddr e))) - (let ((loc (cadr body))) - `(block - ,(let ((x (if (eq? name 'x) 'y 'x))) - `(= (call eval ,x) - (block - ,loc - (call (core eval) ,name ,x)))) - (= (call eval m x) - (block - ,loc - (call (core eval) m x)))))))) + (let* ((name (caddr e)) + (body (cadddr e)) + (loc (cadr body)) + (x (if (eq? name 'x) 'y 'x))) + `(block + (= (call eval ,x) + (block + ,loc + (call (core eval) ,name ,x))) + (= (call eval m ,x) + (block + ,loc + (call (core eval) m ,x))) + (= (call include ,x) + (block + ,loc + (call (top include) ,name ,x))))))) ;; parse only, returning end position, no expansion. (define (jl-parse-one-string s pos0 greedy) diff --git a/src/jltypes.c b/src/jltypes.c index 91a579b36ae50..c292cae8e523e 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -1534,7 +1534,8 @@ extern void jl_init_int32_int64_cache(void); void jl_init_types(void) { - jl_ptls_t ptls = jl_get_ptls_states(); + jl_module_t *core = NULL; // will need to be assigned later + arraylist_new(&partial_inst, 0); // create base objects jl_datatype_type = jl_new_uninitialized_datatype(); @@ -1553,15 +1554,15 @@ void jl_init_types(void) jl_emptysvec = (jl_svec_t*)jl_gc_permobj(sizeof(void*), jl_simplevector_type); jl_svec_set_len_unsafe(jl_emptysvec, 0); - jl_any_type = (jl_datatype_t*)jl_new_abstracttype((jl_value_t*)jl_symbol("Any"), NULL, jl_emptysvec); + jl_any_type = (jl_datatype_t*)jl_new_abstracttype((jl_value_t*)jl_symbol("Any"), core, NULL, jl_emptysvec); jl_any_type->super = jl_any_type; - jl_type_type = (jl_unionall_t*)jl_new_abstracttype((jl_value_t*)jl_symbol("Type"), jl_any_type, jl_emptysvec); + jl_type_type = (jl_unionall_t*)jl_new_abstracttype((jl_value_t*)jl_symbol("Type"), core, jl_any_type, jl_emptysvec); jl_type_typename = ((jl_datatype_t*)jl_type_type)->name; - jl_type_type_mt = jl_new_method_table(jl_type_typename->name, ptls->current_module); + jl_type_type_mt = jl_new_method_table(jl_type_typename->name, core); jl_type_typename->mt = jl_type_type_mt; // initialize them. lots of cycles. - jl_datatype_type->name = jl_new_typename(jl_symbol("DataType")); + jl_datatype_type->name = jl_new_typename_in(jl_symbol("DataType"), core); jl_datatype_type->name->wrapper = (jl_value_t*)jl_datatype_type; jl_datatype_type->super = (jl_datatype_t*)jl_type_type; jl_datatype_type->parameters = jl_emptysvec; @@ -1601,9 +1602,9 @@ void jl_init_types(void) jl_datatype_type->mutabl = 1; jl_datatype_type->ninitialized = 4; - jl_typename_type->name = jl_new_typename(jl_symbol("TypeName")); + jl_typename_type->name = jl_new_typename_in(jl_symbol("TypeName"), core); jl_typename_type->name->wrapper = (jl_value_t*)jl_typename_type; - jl_typename_type->name->mt = jl_new_method_table(jl_typename_type->name->name, ptls->current_module); + jl_typename_type->name->mt = jl_new_method_table(jl_typename_type->name->name, core); jl_typename_type->super = jl_any_type; jl_typename_type->parameters = jl_emptysvec; jl_typename_type->name->names = jl_perm_symsvec(8, "name", "module", @@ -1621,9 +1622,9 @@ void jl_init_types(void) jl_typename_type->mutabl = 1; jl_typename_type->ninitialized = 2; - jl_methtable_type->name = jl_new_typename(jl_symbol("MethodTable")); + jl_methtable_type->name = jl_new_typename_in(jl_symbol("MethodTable"), core); jl_methtable_type->name->wrapper = (jl_value_t*)jl_methtable_type; - jl_methtable_type->name->mt = jl_new_method_table(jl_methtable_type->name->name, ptls->current_module); + jl_methtable_type->name->mt = jl_new_method_table(jl_methtable_type->name->name, core); jl_methtable_type->super = jl_any_type; jl_methtable_type->parameters = jl_emptysvec; jl_methtable_type->name->names = jl_perm_symsvec(9, "name", "defs", @@ -1641,9 +1642,9 @@ void jl_init_types(void) jl_methtable_type->mutabl = 1; jl_methtable_type->ninitialized = 4; - jl_sym_type->name = jl_new_typename(jl_symbol("Symbol")); + jl_sym_type->name = jl_new_typename_in(jl_symbol("Symbol"), core); jl_sym_type->name->wrapper = (jl_value_t*)jl_sym_type; - jl_sym_type->name->mt = jl_new_method_table(jl_sym_type->name->name, ptls->current_module); + jl_sym_type->name->mt = jl_new_method_table(jl_sym_type->name->name, core); jl_sym_type->super = jl_any_type; jl_sym_type->parameters = jl_emptysvec; jl_sym_type->name->names = jl_emptysvec; @@ -1657,9 +1658,9 @@ void jl_init_types(void) jl_sym_type->mutabl = 1; jl_sym_type->ninitialized = 0; - jl_simplevector_type->name = jl_new_typename(jl_symbol("SimpleVector")); + jl_simplevector_type->name = jl_new_typename_in(jl_symbol("SimpleVector"), core); jl_simplevector_type->name->wrapper = (jl_value_t*)jl_simplevector_type; - jl_simplevector_type->name->mt = jl_new_method_table(jl_simplevector_type->name->name, ptls->current_module); + jl_simplevector_type->name->mt = jl_new_method_table(jl_simplevector_type->name->name, core); jl_simplevector_type->super = jl_any_type; jl_simplevector_type->parameters = jl_emptysvec; jl_simplevector_type->name->names = jl_perm_symsvec(1, "length"); @@ -1673,29 +1674,28 @@ void jl_init_types(void) jl_simplevector_type->ninitialized = 1; // now they can be used to create the remaining base kinds and types - jl_void_type = jl_new_datatype(jl_symbol("Void"), jl_any_type, jl_emptysvec, + jl_void_type = jl_new_datatype(jl_symbol("Void"), core, jl_any_type, jl_emptysvec, jl_emptysvec, jl_emptysvec, 0, 0, 0); jl_astaggedvalue(jl_nothing)->header = ((uintptr_t)jl_void_type) | GC_OLD_MARKED; jl_void_type->instance = jl_nothing; jl_datatype_t *type_type = (jl_datatype_t*)jl_type_type; - jl_typeofbottom_type = jl_new_datatype(jl_symbol("TypeofBottom"), type_type, jl_emptysvec, + jl_typeofbottom_type = jl_new_datatype(jl_symbol("TypeofBottom"), core, type_type, jl_emptysvec, jl_emptysvec, jl_emptysvec, 0, 0, 0); jl_bottom_type = jl_new_struct(jl_typeofbottom_type); jl_typeofbottom_type->instance = jl_bottom_type; - jl_uniontype_type = jl_new_datatype(jl_symbol("Union"), type_type, jl_emptysvec, + jl_uniontype_type = jl_new_datatype(jl_symbol("Union"), core, type_type, jl_emptysvec, jl_perm_symsvec(2, "a", "b"), jl_svec(2, jl_any_type, jl_any_type), 0, 0, 2); - jl_tvar_type = jl_new_datatype(jl_symbol("TypeVar"), jl_any_type, jl_emptysvec, + jl_tvar_type = jl_new_datatype(jl_symbol("TypeVar"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(3, "name", "lb", "ub"), - jl_svec(3, jl_sym_type, - jl_any_type, jl_any_type), + jl_svec(3, jl_sym_type, jl_any_type, jl_any_type), 0, 1, 3); - jl_unionall_type = jl_new_datatype(jl_symbol("UnionAll"), type_type, jl_emptysvec, + jl_unionall_type = jl_new_datatype(jl_symbol("UnionAll"), core, type_type, jl_emptysvec, jl_perm_symsvec(2, "var", "body"), jl_svec(2, jl_tvar_type, jl_any_type), 0, 0, 2); @@ -1703,10 +1703,10 @@ void jl_init_types(void) vararg_sym = jl_symbol("Vararg"); jl_svec_t *tv; tv = jl_svec2(tvar("T"),tvar("N")); - jl_vararg_type = (jl_unionall_t*)jl_new_abstracttype((jl_value_t*)vararg_sym, jl_any_type, tv)->name->wrapper; + jl_vararg_type = (jl_unionall_t*)jl_new_abstracttype((jl_value_t*)vararg_sym, core, jl_any_type, tv)->name->wrapper; jl_vararg_typename = ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_vararg_type))->name; - jl_anytuple_type = jl_new_datatype(jl_symbol("Tuple"), jl_any_type, jl_emptysvec, + jl_anytuple_type = jl_new_datatype(jl_symbol("Tuple"), core, jl_any_type, jl_emptysvec, jl_emptysvec, jl_emptysvec, 0, 0, 0); jl_tuple_typename = jl_anytuple_type->name; jl_anytuple_type->uid = 0; @@ -1731,48 +1731,49 @@ void jl_init_types(void) // non-primitive definitions follow jl_int32_type = NULL; - jl_int32_type = jl_new_primitivetype((jl_value_t*)jl_symbol("Int32"), + jl_int32_type = jl_new_primitivetype((jl_value_t*)jl_symbol("Int32"), core, jl_any_type, jl_emptysvec, 32); jl_int64_type = NULL; - jl_int64_type = jl_new_primitivetype((jl_value_t*)jl_symbol("Int64"), + jl_int64_type = jl_new_primitivetype((jl_value_t*)jl_symbol("Int64"), core, jl_any_type, jl_emptysvec, 64); jl_uint8_type = NULL; - jl_uint8_type = jl_new_primitivetype((jl_value_t*)jl_symbol("UInt8"), + jl_uint8_type = jl_new_primitivetype((jl_value_t*)jl_symbol("UInt8"), core, jl_any_type, jl_emptysvec, 8); - jl_ssavalue_type = jl_new_datatype(jl_symbol("SSAValue"), jl_any_type, jl_emptysvec, + jl_ssavalue_type = jl_new_datatype(jl_symbol("SSAValue"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(1, "id"), jl_svec1(jl_long_type), 0, 0, 1); - jl_abstractslot_type = jl_new_abstracttype((jl_value_t*)jl_symbol("Slot"), jl_any_type, + jl_abstractslot_type = jl_new_abstracttype((jl_value_t*)jl_symbol("Slot"), core, jl_any_type, jl_emptysvec); - jl_slotnumber_type = jl_new_datatype(jl_symbol("SlotNumber"), jl_abstractslot_type, jl_emptysvec, + jl_slotnumber_type = jl_new_datatype(jl_symbol("SlotNumber"), core, jl_abstractslot_type, jl_emptysvec, jl_perm_symsvec(1, "id"), jl_svec1(jl_long_type), 0, 0, 1); - jl_typedslot_type = jl_new_datatype(jl_symbol("TypedSlot"), jl_abstractslot_type, jl_emptysvec, + jl_typedslot_type = jl_new_datatype(jl_symbol("TypedSlot"), core, jl_abstractslot_type, jl_emptysvec, jl_perm_symsvec(2, "id", "typ"), jl_svec(2, jl_long_type, jl_any_type), 0, 0, 2); jl_init_int32_int64_cache(); jl_bool_type = NULL; - jl_bool_type = jl_new_primitivetype((jl_value_t*)jl_symbol("Bool"), + jl_bool_type = jl_new_primitivetype((jl_value_t*)jl_symbol("Bool"), core, jl_any_type, jl_emptysvec, 8); jl_false = jl_permbox8(jl_bool_type, 0); jl_true = jl_permbox8(jl_bool_type, 1); jl_typemap_level_type = - jl_new_datatype(jl_symbol("TypeMapLevel"), jl_any_type, jl_emptysvec, - jl_perm_symsvec(7, "index_arg1", - "arg1", - "index_targ", - "targ", - "list", - "any", - "key"), + jl_new_datatype(jl_symbol("TypeMapLevel"), core, jl_any_type, jl_emptysvec, + jl_perm_symsvec(7, + "index_arg1", + "arg1", + "index_targ", + "targ", + "list", + "any", + "key"), jl_svec(7, jl_any_type, jl_any_type, @@ -1784,18 +1785,18 @@ void jl_init_types(void) 0, 1, 6); jl_typemap_entry_type = - jl_new_datatype(jl_symbol("TypeMapEntry"), jl_any_type, jl_emptysvec, + jl_new_datatype(jl_symbol("TypeMapEntry"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(10, - "next", - "sig", - "simplesig", - "guardsigs", - "min_world", - "max_world", - "func", - "isleafsig", - "issimplesig", - "va"), + "next", + "sig", + "simplesig", + "guardsigs", + "min_world", + "max_world", + "func", + "isleafsig", + "issimplesig", + "va"), jl_svec(10, jl_any_type, // Union{TypeMapEntry, Void} jl_type_type, // TupleType @@ -1809,23 +1810,23 @@ void jl_init_types(void) jl_bool_type), 0, 1, 4); - jl_function_type = jl_new_abstracttype((jl_value_t*)jl_symbol("Function"), jl_any_type, jl_emptysvec); - jl_builtin_type = jl_new_abstracttype((jl_value_t*)jl_symbol("Builtin"), jl_function_type, jl_emptysvec); + jl_function_type = jl_new_abstracttype((jl_value_t*)jl_symbol("Function"), core, jl_any_type, jl_emptysvec); + jl_builtin_type = jl_new_abstracttype((jl_value_t*)jl_symbol("Builtin"), core, jl_function_type, jl_emptysvec); tv = jl_svec2(tvar("T"), tvar("N")); jl_abstractarray_type = (jl_unionall_t*) - jl_new_abstracttype((jl_value_t*)jl_symbol("AbstractArray"), + jl_new_abstracttype((jl_value_t*)jl_symbol("AbstractArray"), core, jl_any_type, tv)->name->wrapper; tv = jl_svec2(tvar("T"), tvar("N")); jl_densearray_type = (jl_unionall_t*) - jl_new_abstracttype((jl_value_t*)jl_symbol("DenseArray"), + jl_new_abstracttype((jl_value_t*)jl_symbol("DenseArray"), core, (jl_datatype_t*)jl_apply_type((jl_value_t*)jl_abstractarray_type, jl_svec_data(tv), 2), tv)->name->wrapper; tv = jl_svec2(tvar("T"), tvar("N")); jl_array_type = (jl_unionall_t*) - jl_new_datatype(jl_symbol("Array"), + jl_new_datatype(jl_symbol("Array"), core, (jl_datatype_t*) jl_apply_type((jl_value_t*)jl_densearray_type, jl_svec_data(tv), 2), tv, @@ -1841,7 +1842,7 @@ void jl_init_types(void) jl_array_uint8_type = jl_apply_type2((jl_value_t*)jl_array_type, (jl_value_t*)jl_uint8_type, jl_box_long(1)); jl_expr_type = - jl_new_datatype(jl_symbol("Expr"), + jl_new_datatype(jl_symbol("Expr"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(3, "head", "args", "typ"), jl_svec(3, jl_sym_type, jl_array_any_type, @@ -1849,161 +1850,161 @@ void jl_init_types(void) 0, 1, 3); jl_linenumbernode_type = - jl_new_datatype(jl_symbol("LineNumberNode"), jl_any_type, jl_emptysvec, + jl_new_datatype(jl_symbol("LineNumberNode"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(2, "line", "file"), jl_svec(2, jl_long_type, jl_any_type), 0, 0, 2); jl_labelnode_type = - jl_new_datatype(jl_symbol("LabelNode"), jl_any_type, jl_emptysvec, + jl_new_datatype(jl_symbol("LabelNode"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(1, "label"), jl_svec(1, jl_long_type), 0, 0, 1); jl_gotonode_type = - jl_new_datatype(jl_symbol("GotoNode"), jl_any_type, jl_emptysvec, + jl_new_datatype(jl_symbol("GotoNode"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(1, "label"), jl_svec(1, jl_long_type), 0, 0, 1); jl_quotenode_type = - jl_new_datatype(jl_symbol("QuoteNode"), jl_any_type, jl_emptysvec, + jl_new_datatype(jl_symbol("QuoteNode"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(1, "value"), jl_svec(1, jl_any_type), 0, 0, 1); jl_newvarnode_type = - jl_new_datatype(jl_symbol("NewvarNode"), jl_any_type, jl_emptysvec, + jl_new_datatype(jl_symbol("NewvarNode"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(1, "slot"), jl_svec(1, jl_slotnumber_type), 0, 0, 1); jl_module_type = - jl_new_datatype(jl_symbol("Module"), jl_any_type, jl_emptysvec, + jl_new_datatype(jl_symbol("Module"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(2, "name", "parent"), jl_svec(2, jl_sym_type, jl_any_type), 0, 1, 2); jl_globalref_type = - jl_new_datatype(jl_symbol("GlobalRef"), jl_any_type, jl_emptysvec, + jl_new_datatype(jl_symbol("GlobalRef"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(2, "mod", "name"), jl_svec(2, jl_module_type, jl_sym_type), 0, 0, 2); jl_code_info_type = - jl_new_datatype(jl_symbol("CodeInfo"), + jl_new_datatype(jl_symbol("CodeInfo"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(9, - "code", - "slottypes", - "ssavaluetypes", - "slotflags", - "slotnames", - "inferred", - "inlineable", - "propagate_inbounds", - "pure"), + "code", + "slottypes", + "ssavaluetypes", + "slotflags", + "slotnames", + "inferred", + "inlineable", + "propagate_inbounds", + "pure"), jl_svec(9, - jl_array_any_type, - jl_any_type, - jl_any_type, - jl_array_uint8_type, - jl_array_any_type, - jl_bool_type, - jl_bool_type, - jl_bool_type, - jl_bool_type), + jl_array_any_type, + jl_any_type, + jl_any_type, + jl_array_uint8_type, + jl_array_any_type, + jl_bool_type, + jl_bool_type, + jl_bool_type, + jl_bool_type), 0, 1, 9); jl_method_type = - jl_new_datatype(jl_symbol("Method"), + jl_new_datatype(jl_symbol("Method"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(19, - "name", - "module", - "file", - "line", - "sig", - "min_world", - "ambig", - "specializations", - "sparam_syms", - "source", - "unspecialized", - "generator", - "roots", - "invokes", - "nargs", - "called", - "isva", - "isstaged", - "pure"), + "name", + "module", + "file", + "line", + "sig", + "min_world", + "ambig", + "specializations", + "sparam_syms", + "source", + "unspecialized", + "generator", + "roots", + "invokes", + "nargs", + "called", + "isva", + "isstaged", + "pure"), jl_svec(19, - jl_sym_type, - jl_module_type, - jl_sym_type, - jl_int32_type, - jl_type_type, - jl_long_type, - jl_any_type, // Union{Array, Void} - jl_any_type, // TypeMap - jl_simplevector_type, - jl_any_type, - jl_any_type, // jl_method_instance_type - jl_any_type, // jl_method_instance_type - jl_array_any_type, - jl_any_type, - jl_int32_type, - jl_int32_type, - jl_bool_type, - jl_bool_type, - jl_bool_type), + jl_sym_type, + jl_module_type, + jl_sym_type, + jl_int32_type, + jl_type_type, + jl_long_type, + jl_any_type, // Union{Array, Void} + jl_any_type, // TypeMap + jl_simplevector_type, + jl_any_type, + jl_any_type, // jl_method_instance_type + jl_any_type, // jl_method_instance_type + jl_array_any_type, + jl_any_type, + jl_int32_type, + jl_int32_type, + jl_bool_type, + jl_bool_type, + jl_bool_type), 0, 1, 9); jl_method_instance_type = - jl_new_datatype(jl_symbol("MethodInstance"), + jl_new_datatype(jl_symbol("MethodInstance"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(16, - "specTypes", - "rettype", - "sparam_vals", - "backedges", - "inferred", - "inferred_const", - "def", - "min_world", - "max_world", - "inInference", - "jlcall_api", - "", - "fptr", - "unspecialized_ducttape", - "", ""), + "def", + "specTypes", + "rettype", + "sparam_vals", + "backedges", + "inferred", + "inferred_const", + "min_world", + "max_world", + "inInference", + "jlcall_api", + "", + "fptr", + "unspecialized_ducttape", + "", ""), jl_svec(16, - jl_any_type, - jl_any_type, - jl_simplevector_type, - jl_any_type, - jl_any_type, - jl_any_type, - jl_method_type, - jl_long_type, - jl_long_type, - jl_bool_type, - jl_uint8_type, - jl_bool_type, - jl_any_type, // void* - jl_any_type, // void* - jl_any_type, jl_any_type), // void*, void* - 0, 1, 3); + jl_new_struct(jl_uniontype_type, jl_method_type, jl_module_type), + jl_any_type, + jl_any_type, + jl_simplevector_type, + jl_any_type, + jl_any_type, + jl_any_type, + jl_long_type, + jl_long_type, + jl_bool_type, + jl_uint8_type, + jl_bool_type, + jl_any_type, // void* + jl_any_type, // void* + jl_any_type, jl_any_type), // void*, void* + 0, 1, 4); // all kinds of types share a method table jl_unionall_type->name->mt = jl_uniontype_type->name->mt = jl_datatype_type->name->mt = jl_type_typename->mt; - jl_intrinsic_type = jl_new_primitivetype((jl_value_t*)jl_symbol("IntrinsicFunction"), + jl_intrinsic_type = jl_new_primitivetype((jl_value_t*)jl_symbol("IntrinsicFunction"), core, jl_builtin_type, jl_emptysvec, 32); tv = jl_svec1(tvar("T")); jl_ref_type = (jl_unionall_t*) - jl_new_abstracttype((jl_value_t*)jl_symbol("Ref"), jl_any_type, tv)->name->wrapper; + jl_new_abstracttype((jl_value_t*)jl_symbol("Ref"), core, jl_any_type, tv)->name->wrapper; tv = jl_svec1(tvar("T")); jl_pointer_type = (jl_unionall_t*) - jl_new_primitivetype((jl_value_t*)jl_symbol("Ptr"), + jl_new_primitivetype((jl_value_t*)jl_symbol("Ptr"), core, (jl_datatype_t*)jl_apply_type((jl_value_t*)jl_ref_type, jl_svec_data(tv), 1), tv, sizeof(void*)*8)->name->wrapper; jl_pointer_typename = ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_pointer_type))->name; @@ -2023,8 +2024,8 @@ void jl_init_types(void) jl_ANY_flag = (jl_value_t*)tvar("ANY"); - jl_abstractstring_type = jl_new_abstracttype((jl_value_t*)jl_symbol("AbstractString"), jl_any_type, jl_emptysvec); - jl_string_type = jl_new_datatype(jl_symbol("String"), jl_abstractstring_type, jl_emptysvec, + jl_abstractstring_type = jl_new_abstracttype((jl_value_t*)jl_symbol("AbstractString"), core, jl_any_type, jl_emptysvec); + jl_string_type = jl_new_datatype(jl_symbol("String"), core, jl_abstractstring_type, jl_emptysvec, jl_perm_symsvec(1, "len"), jl_svec1(jl_long_type), 0, 1, 1); diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index faee84d7c940b..123e44621140a 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -1163,6 +1163,7 @@ (expand-forms `(function (call ,(symbol (string #\@ (cadr (cadr e)))) (|::| __source__ (core LineNumberNode)) + (|::| __module__ (core Module)) ,@(map (lambda (v) (if (symbol? v) `(|::| ,v (core ANY)) diff --git a/src/julia.h b/src/julia.h index d25c67a3a2d2d..314feafc4dc1a 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1,5 +1,8 @@ // This file is a part of Julia. License is MIT: https://julialang.org/license +// TODO: add `@isdefined` +// + #ifndef JULIA_H #define JULIA_H @@ -264,13 +267,17 @@ typedef struct _jl_method_t { // This type caches the data for a specType signature specialization of a Method typedef struct _jl_method_instance_t { JL_DATA_TYPE + union { + jl_value_t *value; // generic accessor + struct _jl_module_t *module; // this is a toplevel thunk + jl_method_t *method; // method this is specialized from + } def; // context for this lambda definition jl_value_t *specTypes; // argument types this was specialized for jl_value_t *rettype; // return type for fptr - jl_svec_t *sparam_vals; // static parameter values, indexed by def->sparam_syms + jl_svec_t *sparam_vals; // static parameter values, indexed by def.method->sparam_syms jl_array_t *backedges; jl_value_t *inferred; // inferred jl_code_info_t, or value of the function if jlcall_api == 2, or null jl_value_t *inferred_const; // inferred constant return value, or null - jl_method_t *def; // method this is specialized from, null if this is a toplevel thunk size_t min_world; size_t max_world; uint8_t inInference; // flags to tell if inference is running on this function @@ -419,7 +426,7 @@ typedef struct _jl_typemap_entry_t { size_t min_world; size_t max_world; union { - jl_value_t *value; + jl_value_t *value; // generic accessor jl_method_instance_t *linfo; // [nullable] for guard entries jl_method_t *method; } func; @@ -997,7 +1004,7 @@ STATIC_INLINE int jl_is_leaf_type_(jl_value_t *v) #endif // type constructors -JL_DLLEXPORT jl_typename_t *jl_new_typename(jl_sym_t *name); +JL_DLLEXPORT jl_typename_t *jl_new_typename_in(jl_sym_t *name, jl_module_t *inmodule); JL_DLLEXPORT jl_tvar_t *jl_new_typevar(jl_sym_t *name, jl_value_t *lb, jl_value_t *ub); JL_DLLEXPORT jl_value_t *jl_instantiate_unionall(jl_unionall_t *u, jl_value_t *p); JL_DLLEXPORT jl_value_t *jl_apply_type(jl_value_t *tc, jl_value_t **params, size_t n); @@ -1005,14 +1012,19 @@ JL_DLLEXPORT jl_value_t *jl_apply_type1(jl_value_t *tc, jl_value_t *p1); JL_DLLEXPORT jl_value_t *jl_apply_type2(jl_value_t *tc, jl_value_t *p1, jl_value_t *p2); JL_DLLEXPORT jl_tupletype_t *jl_apply_tuple_type(jl_svec_t *params); JL_DLLEXPORT jl_tupletype_t *jl_apply_tuple_type_v(jl_value_t **p, size_t np); -JL_DLLEXPORT jl_datatype_t *jl_new_datatype(jl_sym_t *name, jl_datatype_t *super, +JL_DLLEXPORT jl_datatype_t *jl_new_datatype(jl_sym_t *name, + jl_module_t *module, + jl_datatype_t *super, jl_svec_t *parameters, jl_svec_t *fnames, jl_svec_t *ftypes, int abstract, int mutabl, int ninitialized); JL_DLLEXPORT jl_datatype_t *jl_new_primitivetype(jl_value_t *name, + jl_module_t *module, jl_datatype_t *super, jl_svec_t *parameters, size_t nbits); +jl_datatype_t *jl_new_abstracttype(jl_value_t *name, jl_module_t *module, + jl_datatype_t *super, jl_svec_t *parameters); // constructors JL_DLLEXPORT jl_value_t *jl_new_bits(jl_value_t *bt, void *data); @@ -1035,10 +1047,11 @@ JL_DLLEXPORT jl_sym_t *jl_symbol_n(const char *str, size_t len); JL_DLLEXPORT jl_sym_t *jl_gensym(void); JL_DLLEXPORT jl_sym_t *jl_tagged_gensym(const char *str, int32_t len); JL_DLLEXPORT jl_sym_t *jl_get_root_symbol(void); -JL_DLLEXPORT jl_value_t *jl_generic_function_def(jl_sym_t *name, jl_value_t **bp, - jl_value_t *bp_owner, +JL_DLLEXPORT jl_value_t *jl_generic_function_def(jl_sym_t *name, + jl_module_t *module, + jl_value_t **bp, jl_value_t *bp_owner, jl_binding_t *bnd); -JL_DLLEXPORT void jl_method_def(jl_svec_t *argdata, jl_code_info_t *f, jl_value_t *isstaged); +JL_DLLEXPORT void jl_method_def(jl_svec_t *argdata, jl_code_info_t *f, jl_module_t *module, jl_value_t *isstaged); JL_DLLEXPORT jl_code_info_t *jl_code_for_staged(jl_method_instance_t *linfo); JL_DLLEXPORT jl_code_info_t *jl_copy_code_info(jl_code_info_t *src); JL_DLLEXPORT size_t jl_get_world_counter(void); @@ -1343,8 +1356,8 @@ JL_DLLEXPORT jl_value_t *jl_parse_string(const char *str, size_t len, int pos0, int greedy); JL_DLLEXPORT int jl_parse_depwarn(int warn); JL_DLLEXPORT jl_value_t *jl_load_file_string(const char *text, size_t len, - char *filename); -JL_DLLEXPORT jl_value_t *jl_expand(jl_value_t *expr); + char *filename, jl_module_t *inmodule); +JL_DLLEXPORT jl_value_t *jl_expand(jl_value_t *expr, jl_module_t *inmodule); JL_DLLEXPORT jl_value_t *jl_eval_string(const char *str); // external libraries @@ -1376,9 +1389,9 @@ JL_DLLEXPORT const char *jl_lookup_soname(const char *pfx, size_t n); #endif // compiler -JL_DLLEXPORT jl_value_t *jl_toplevel_eval(jl_value_t *v); +JL_DLLEXPORT jl_value_t *jl_toplevel_eval(jl_module_t *m, jl_value_t *v); JL_DLLEXPORT jl_value_t *jl_toplevel_eval_in(jl_module_t *m, jl_value_t *ex); -JL_DLLEXPORT jl_value_t *jl_load(const char *fname); +JL_DLLEXPORT jl_value_t *jl_load(jl_module_t *module, const char *fname); JL_DLLEXPORT jl_module_t *jl_base_relative_to(jl_module_t *m); // tracing diff --git a/src/julia_internal.h b/src/julia_internal.h index 47b2b1365dd83..9337c784fcff6 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -294,17 +294,14 @@ jl_value_t *jl_gc_realloc_string(jl_value_t *s, size_t sz); jl_code_info_t *jl_type_infer(jl_method_instance_t **li, size_t world, int force); jl_generic_fptr_t jl_generate_fptr(jl_method_instance_t *li, void *F, size_t world); -jl_llvm_functions_t jl_compile_linfo(jl_method_instance_t **pli, jl_code_info_t *src, size_t world, const jl_cgparams_t *params); +jl_llvm_functions_t jl_compile_linfo( + jl_method_instance_t **pli, + jl_code_info_t *src, + size_t world, + const jl_cgparams_t *params); jl_llvm_functions_t jl_compile_for_dispatch(jl_method_instance_t **li, size_t world); JL_DLLEXPORT int jl_compile_hint(jl_tupletype_t *types); jl_code_info_t *jl_new_code_info_from_ast(jl_expr_t *ast); -jl_method_t *jl_new_method(jl_code_info_t *definition, - jl_sym_t *name, - jl_tupletype_t *sig, - size_t nargs, - int isva, - jl_svec_t *tvars, - int isstaged); STATIC_INLINE jl_value_t *jl_compile_method_internal(jl_generic_fptr_t *fptr, jl_method_instance_t *meth) @@ -326,11 +323,11 @@ STATIC_INLINE jl_value_t *jl_compile_method_internal(jl_generic_fptr_t *fptr, fptr->fptr = meth->unspecialized_ducttape; fptr->jlcall_api = 1; if (!fptr->fptr) { - if (meth->def && !meth->def->isstaged && meth->def->unspecialized) { - fptr->fptr = meth->def->unspecialized->fptr; - fptr->jlcall_api = meth->def->unspecialized->jlcall_api; + if (jl_is_method(meth->def.method) && !meth->def.method->isstaged && meth->def.method->unspecialized) { + fptr->fptr = meth->def.method->unspecialized->fptr; + fptr->jlcall_api = meth->def.method->unspecialized->jlcall_api; if (fptr->jlcall_api == 2) { - return jl_assume(meth->def->unspecialized->inferred_const); + return jl_assume(meth->def.method->unspecialized->inferred_const); } } } @@ -461,8 +458,6 @@ jl_svec_t *jl_outer_unionall_vars(jl_value_t *u); int jl_count_union_components(jl_value_t *v); jl_value_t *jl_nth_union_component(jl_value_t *v, int i); jl_datatype_t *jl_new_uninitialized_datatype(void); -jl_datatype_t *jl_new_abstracttype(jl_value_t *name, jl_datatype_t *super, - jl_svec_t *parameters); void jl_precompute_memoized_dt(jl_datatype_t *dt); jl_datatype_t *jl_wrap_Type(jl_value_t *t); // x -> Type{x} jl_value_t *jl_wrap_vararg(jl_value_t *t, jl_value_t *n); @@ -473,19 +468,19 @@ jl_function_t *jl_new_generic_function_with_supertype(jl_sym_t *name, jl_module_ jl_function_t *jl_module_call_func(jl_module_t *m); int jl_is_submodule(jl_module_t *child, jl_module_t *parent); -jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast, int expanded); +jl_value_t *jl_toplevel_eval_flex(jl_module_t *m, jl_value_t *e, int fast, int expanded); jl_code_info_t *jl_wrap_expr(jl_value_t *expr); jl_value_t *jl_eval_global_var(jl_module_t *m, jl_sym_t *e); jl_value_t *jl_parse_eval_all(const char *fname, - const char *content, size_t contentlen); -jl_value_t *jl_interpret_toplevel_thunk(jl_code_info_t *src); -jl_value_t *jl_interpret_toplevel_expr(jl_value_t *e); + const char *content, size_t contentlen, + jl_module_t *inmodule); +jl_value_t *jl_interpret_toplevel_thunk(jl_module_t *m, jl_code_info_t *src); jl_value_t *jl_interpret_toplevel_expr_in(jl_module_t *m, jl_value_t *e, jl_code_info_t *src, jl_svec_t *sparam_vals); int jl_is_toplevel_only_expr(jl_value_t *e); -jl_value_t *jl_call_scm_on_ast(const char *funcname, jl_value_t *expr); +jl_value_t *jl_call_scm_on_ast(const char *funcname, jl_value_t *expr, jl_module_t *inmodule); jl_method_instance_t *jl_method_lookup_by_type(jl_methtable_t *mt, jl_tupletype_t *types, int cache, int inexact, int allow_exec, size_t world); diff --git a/src/method.c b/src/method.c index 4cd52b82776e9..123ccd0007b14 100644 --- a/src/method.c +++ b/src/method.c @@ -210,7 +210,7 @@ JL_DLLEXPORT jl_method_instance_t *jl_new_method_instance_uninit(void) li->functionObjectsDecls.specFunctionObject = NULL; li->specTypes = NULL; li->inInference = 0; - li->def = NULL; + li->def.value = NULL; li->min_world = 0; li->max_world = 0; return li; @@ -252,11 +252,11 @@ STATIC_INLINE jl_value_t *jl_call_staged(jl_svec_t *sparam_vals, jl_method_insta fptr.fptr = generator->fptr; fptr.jlcall_api = generator->jlcall_api; if (__unlikely(fptr.fptr == NULL || fptr.jlcall_api == 0)) { - size_t world = generator->def->min_world; + size_t world = generator->def.method->min_world; void *F = jl_compile_linfo(&generator, (jl_code_info_t*)generator->inferred, world, &jl_default_cgparams).functionObject; fptr = jl_generate_fptr(generator, F, world); } - assert(jl_svec_len(generator->def->sparam_syms) == jl_svec_len(sparam_vals)); + assert(jl_svec_len(generator->def.method->sparam_syms) == jl_svec_len(sparam_vals)); if (fptr.jlcall_api == 1) return fptr.fptr1(args[0], &args[1], nargs-1); else if (fptr.jlcall_api == 3) @@ -275,9 +275,9 @@ JL_DLLEXPORT jl_code_info_t *jl_code_for_staged(jl_method_instance_t *linfo) jl_expr_t *ex = NULL; jl_value_t *linenum = NULL; jl_svec_t *sparam_vals = env; - jl_method_instance_t *generator = linfo->def->generator; + jl_method_instance_t *generator = linfo->def.method->generator; assert(linfo != generator); - assert(linfo->def->isstaged); + assert(linfo->def.method->isstaged); jl_code_info_t *func = NULL; JL_GC_PUSH4(&ex, &linenum, &sparam_vals, &func); jl_ptls_t ptls = jl_get_ptls_states(); @@ -286,19 +286,19 @@ JL_DLLEXPORT jl_code_info_t *jl_code_for_staged(jl_method_instance_t *linfo) jl_module_t *last_m = ptls->current_module; jl_module_t *task_last_m = ptls->current_task->current_module; size_t last_age = jl_get_ptls_states()->world_age; - assert(jl_svec_len(linfo->def->sparam_syms) == jl_svec_len(sparam_vals)); + assert(jl_svec_len(linfo->def.method->sparam_syms) == jl_svec_len(sparam_vals)); JL_TRY { ptls->in_pure_callback = 1; // need to eval macros in the right module - ptls->current_task->current_module = ptls->current_module = linfo->def->module; + ptls->current_task->current_module = ptls->current_module = linfo->def.method->module; // and the right world - ptls->world_age = generator->def->min_world; + ptls->world_age = generator->def.method->min_world; ex = jl_exprn(lambda_sym, 2); - jl_array_t *argnames = jl_alloc_vec_any(linfo->def->nargs); + jl_array_t *argnames = jl_alloc_vec_any(linfo->def.method->nargs); jl_array_ptr_set(ex->args, 0, argnames); - jl_fill_argnames((jl_array_t*)linfo->def->source, argnames); + jl_fill_argnames((jl_array_t*)linfo->def.method->source, argnames); // build the rest of the body to pass to expand jl_expr_t *scopeblock = jl_exprn(jl_symbol("scope-block"), 1); @@ -307,36 +307,36 @@ JL_DLLEXPORT jl_code_info_t *jl_code_for_staged(jl_method_instance_t *linfo) jl_array_ptr_set(((jl_expr_t*)jl_exprarg(ex, 1))->args, 0, body); // add location meta - linenum = jl_box_long(linfo->def->line); - jl_value_t *linenode = jl_new_struct(jl_linenumbernode_type, linenum, linfo->def->file); + linenum = jl_box_long(linfo->def.method->line); + jl_value_t *linenode = jl_new_struct(jl_linenumbernode_type, linenum, linfo->def.method->file); jl_array_ptr_set(body->args, 0, linenode); jl_expr_t *pushloc = jl_exprn(meta_sym, 3); jl_array_ptr_set(body->args, 1, pushloc); jl_array_ptr_set(pushloc->args, 0, jl_symbol("push_loc")); - jl_array_ptr_set(pushloc->args, 1, linfo->def->file); // file + jl_array_ptr_set(pushloc->args, 1, linfo->def.method->file); // file jl_array_ptr_set(pushloc->args, 2, jl_symbol("@generated body")); // function // invoke code generator assert(jl_nparams(tt) == jl_array_len(argnames) || - (linfo->def->isva && (jl_nparams(tt) >= jl_array_len(argnames) - 1))); + (linfo->def.method->isva && (jl_nparams(tt) >= jl_array_len(argnames) - 1))); jl_value_t *generated_body = jl_call_staged(sparam_vals, generator, jl_svec_data(tt->parameters), jl_nparams(tt)); jl_array_ptr_set(body->args, 2, generated_body); - if (linfo->def->sparam_syms != jl_emptysvec) { + if (linfo->def.method->sparam_syms != jl_emptysvec) { // mark this function as having the same static parameters as the generator - size_t i, nsp = jl_svec_len(linfo->def->sparam_syms); + size_t i, nsp = jl_svec_len(linfo->def.method->sparam_syms); jl_expr_t *newast = jl_exprn(jl_symbol("with-static-parameters"), nsp + 1); jl_exprarg(newast, 0) = (jl_value_t*)ex; // (with-static-parameters func_expr sp_1 sp_2 ...) for (i = 0; i < nsp; i++) - jl_exprarg(newast, i+1) = jl_svecref(linfo->def->sparam_syms, i); + jl_exprarg(newast, i+1) = jl_svecref(linfo->def.method->sparam_syms, i); ex = newast; } - func = (jl_code_info_t*)jl_expand((jl_value_t*)ex); + func = (jl_code_info_t*)jl_expand((jl_value_t*)ex, linfo->def.method->module); if (!jl_is_code_info(func)) { if (jl_is_expr(func) && ((jl_expr_t*)func)->head == error_sym) - jl_interpret_toplevel_expr((jl_value_t*)func); + jl_interpret_toplevel_expr_in(linfo->def.method->module, (jl_value_t*)func, NULL, NULL); jl_error("generated function body is not pure. this likely means it contains a closure or comprehension."); } @@ -344,7 +344,7 @@ JL_DLLEXPORT jl_code_info_t *jl_code_for_staged(jl_method_instance_t *linfo) size_t i, l; for (i = 0, l = jl_array_len(stmts); i < l; i++) { jl_value_t *stmt = jl_array_ptr_ref(stmts, i); - stmt = jl_resolve_globals(stmt, linfo->def->module, env); + stmt = jl_resolve_globals(stmt, linfo->def.method->module, env); jl_array_ptr_set(stmts, i, stmt); } @@ -386,7 +386,7 @@ jl_method_instance_t *jl_get_specialized(jl_method_t *m, jl_value_t *types, jl_s { assert(jl_svec_len(m->sparam_syms) == jl_svec_len(sp) || sp == jl_emptysvec); jl_method_instance_t *new_linfo = jl_new_method_instance_uninit(); - new_linfo->def = m; + new_linfo->def.method = m; new_linfo->specTypes = types; new_linfo->sparam_vals = sp; new_linfo->min_world = m->min_world; @@ -456,7 +456,7 @@ static void jl_method_set_source(jl_method_t *m, jl_code_info_t *src) JL_GC_POP(); } -JL_DLLEXPORT jl_method_t *jl_new_method_uninit(void) +JL_DLLEXPORT jl_method_t *jl_new_method_uninit(jl_module_t *module) { jl_ptls_t ptls = jl_get_ptls_states(); jl_method_t *m = @@ -466,7 +466,7 @@ JL_DLLEXPORT jl_method_t *jl_new_method_uninit(void) m->sparam_syms = NULL; m->ambig = jl_nothing; m->roots = NULL; - m->module = ptls->current_module; + m->module = module; m->source = NULL; m->unspecialized = NULL; m->generator = NULL; @@ -485,13 +485,15 @@ JL_DLLEXPORT jl_method_t *jl_new_method_uninit(void) } jl_array_t *jl_all_methods; -jl_method_t *jl_new_method(jl_code_info_t *definition, - jl_sym_t *name, - jl_tupletype_t *sig, - size_t nargs, - int isva, - jl_svec_t *tvars, - int isstaged) +static jl_method_t *jl_new_method( + jl_code_info_t *definition, + jl_sym_t *name, + jl_module_t *inmodule, + jl_tupletype_t *sig, + size_t nargs, + int isva, + jl_svec_t *tvars, + int isstaged) { size_t i, l = jl_svec_len(tvars); jl_svec_t *sparam_syms = jl_alloc_svec_uninit(l); @@ -502,7 +504,7 @@ jl_method_t *jl_new_method(jl_code_info_t *definition, jl_method_t *m = NULL; JL_GC_PUSH1(&root); - m = jl_new_method_uninit(); + m = jl_new_method_uninit(inmodule); m->sparam_syms = sparam_syms; root = (jl_value_t*)m; m->min_world = ++jl_world_counter; @@ -563,11 +565,12 @@ static void jl_check_static_parameter_conflicts(jl_method_t *m, jl_code_info_t * } // empty generic function def -JL_DLLEXPORT jl_value_t *jl_generic_function_def(jl_sym_t *name, jl_value_t **bp, jl_value_t *bp_owner, +JL_DLLEXPORT jl_value_t *jl_generic_function_def(jl_sym_t *name, + jl_module_t *module, + jl_value_t **bp, jl_value_t *bp_owner, jl_binding_t *bnd) { - jl_ptls_t ptls = jl_get_ptls_states(); - jl_value_t *gf=NULL; + jl_value_t *gf = NULL; assert(name && bp); if (bnd && bnd->value != NULL && !bnd->constp) @@ -580,7 +583,6 @@ JL_DLLEXPORT jl_value_t *jl_generic_function_def(jl_sym_t *name, jl_value_t **bp if (bnd) bnd->constp = 1; if (*bp == NULL) { - jl_module_t *module = (bnd ? bnd->owner : ptls->current_module); gf = (jl_value_t*)jl_new_generic_function(name, module); *bp = gf; if (bp_owner) jl_gc_wb(bp_owner, gf); @@ -633,6 +635,7 @@ jl_datatype_t *jl_argument_datatype(jl_value_t *argt) extern tracer_cb jl_newmeth_tracer; JL_DLLEXPORT void jl_method_def(jl_svec_t *argdata, jl_code_info_t *f, + jl_module_t *module, jl_value_t *isstaged) { // argdata is svec(svec(types...), svec(typevars...)) @@ -673,14 +676,14 @@ JL_DLLEXPORT void jl_method_def(jl_svec_t *argdata, jl_error("cannot add methods to a builtin function"); int j; - for(j=(int)jl_svec_len(tvars)-1; j >= 0 ; j--) { + for (j = (int)jl_svec_len(tvars) - 1; j >= 0 ; j--) { jl_value_t *tv = jl_svecref(tvars,j); if (!jl_is_typevar(tv)) jl_type_error_rt(jl_symbol_name(name), "method definition", (jl_value_t*)jl_tvar_type, tv); argtype = jl_new_struct(jl_unionall_type, tv, argtype); } - m = jl_new_method(f, name, (jl_tupletype_t*)argtype, nargs, isva, tvars, isstaged == jl_true); + m = jl_new_method(f, name, module, (jl_tupletype_t*)argtype, nargs, isva, tvars, isstaged == jl_true); if (jl_has_free_typevars(argtype)) { jl_exceptionf(jl_argumenterror_type, diff --git a/src/module.c b/src/module.c index dc9d7b8f1f601..9b518fb2637a8 100644 --- a/src/module.c +++ b/src/module.c @@ -61,12 +61,11 @@ JL_DLLEXPORT jl_value_t *jl_f_new_module(jl_sym_t *name, uint8_t std_imports) return (jl_value_t*)m; } -JL_DLLEXPORT void jl_set_istopmod(uint8_t isprimary) +JL_DLLEXPORT void jl_set_istopmod(jl_module_t *self, uint8_t isprimary) { - jl_ptls_t ptls = jl_get_ptls_states(); - ptls->current_module->istopmod = 1; + self->istopmod = 1; if (isprimary) { - jl_top_module = ptls->current_module; + jl_top_module = self; jl_append_any_func = NULL; } } @@ -457,8 +456,6 @@ JL_DLLEXPORT void jl_set_const(jl_module_t *m, jl_sym_t *var, jl_value_t *val) JL_DLLEXPORT int jl_is_const(jl_module_t *m, jl_sym_t *var) { - jl_ptls_t ptls = jl_get_ptls_states(); - if (m == NULL) m = ptls->current_module; jl_binding_t *b = jl_get_binding(m, var); return b && b->constp; } diff --git a/src/rtutils.c b/src/rtutils.c index 963485a926899..611a2df890664 100644 --- a/src/rtutils.c +++ b/src/rtutils.c @@ -532,19 +532,21 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt } else if (vt == jl_method_instance_type) { jl_method_instance_t *li = (jl_method_instance_t*)v; - if (li->def) { - n += jl_static_show_x(out, (jl_value_t*)li->def->module, depth); + if (jl_is_method(li->def.method)) { + jl_method_t *m = li->def.method; + n += jl_static_show_x(out, (jl_value_t*)m->module, depth); if (li->specTypes) { n += jl_printf(out, "."); n += jl_show_svec(out, ((jl_datatype_t*)jl_unwrap_unionall(li->specTypes))->parameters, - jl_symbol_name(li->def->name), "(", ")"); + jl_symbol_name(m->name), "(", ")"); } else { - n += jl_printf(out, ".%s(?)", jl_symbol_name(li->def->name)); + n += jl_printf(out, ".%s(?)", jl_symbol_name(m->name)); } } else { - n += jl_printf(out, " -> "); + n += jl_static_show_x(out, (jl_value_t*)li->def.module, depth); + n += jl_printf(out, ". -> "); n += jl_static_show_x(out, li->inferred, depth); } } diff --git a/src/task.c b/src/task.c index 37fedf3838eae..dd10b3f2129a9 100644 --- a/src/task.c +++ b/src/task.c @@ -658,6 +658,7 @@ void jl_init_tasks(void) _probe_arch(); jl_task_type = (jl_datatype_t*) jl_new_datatype(jl_symbol("Task"), + NULL, jl_any_type, jl_emptysvec, jl_perm_symsvec(9, diff --git a/src/toplevel.c b/src/toplevel.c index 50f3673d243be..c90f335ea8b11 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -121,7 +121,7 @@ static void jl_module_load_time_initialize(jl_module_t *m) } extern void jl_get_system_hooks(void); -jl_value_t *jl_eval_module_expr(jl_expr_t *ex) +jl_value_t *jl_eval_module_expr(jl_module_t *parent_module, jl_expr_t *ex) { jl_ptls_t ptls = jl_get_ptls_states(); static arraylist_t module_stack; @@ -141,7 +141,6 @@ jl_value_t *jl_eval_module_expr(jl_expr_t *ex) if (!jl_is_symbol(name)) { jl_type_error("module", (jl_value_t*)jl_sym_type, (jl_value_t*)name); } - jl_module_t *parent_module = ptls->current_module; jl_binding_t *b = jl_get_binding_wr(parent_module, name); jl_declare_constant(b); if (b->value != NULL) { @@ -191,18 +190,18 @@ jl_value_t *jl_eval_module_expr(jl_expr_t *ex) JL_TRY { if (std_imports) { // add `eval` function - defaultdefs = jl_call_scm_on_ast("module-default-defs", (jl_value_t*)ex); + defaultdefs = jl_call_scm_on_ast("module-default-defs", (jl_value_t*)ex, newm); ptls->world_age = jl_world_counter; - jl_toplevel_eval_flex(defaultdefs, 0, 1); + jl_toplevel_eval_flex(newm, defaultdefs, 0, 1); defaultdefs = NULL; } for (int i = 0; i < jl_array_len(exprs); i++) { // process toplevel form ptls->world_age = jl_world_counter; - form = jl_expand(jl_array_ptr_ref(exprs, i)); + form = jl_expand(jl_array_ptr_ref(exprs, i), newm); ptls->world_age = jl_world_counter; - (void)jl_toplevel_eval_flex(form, 1, 1); + (void)jl_toplevel_eval_flex(newm, form, 1, 1); } } JL_CATCH { @@ -241,7 +240,7 @@ jl_value_t *jl_eval_module_expr(jl_expr_t *ex) arraylist_push(&module_stack, newm); - if (outermost == NULL || ptls->current_module == jl_main_module) { + if (outermost == NULL || parent_module == jl_main_module) { JL_TRY { size_t i, l = module_stack.len; for (i = stackidx; i < l; i++) { @@ -343,25 +342,26 @@ static int jl_eval_expr_with_compiler_p(jl_value_t *e, int compileloops, jl_modu static jl_value_t *require_func=NULL; -static jl_module_t *eval_import_path_(jl_array_t *args, int retrying) +static jl_module_t *eval_import_path_(jl_module_t *from, jl_array_t *args, int retrying) { - jl_ptls_t ptls = jl_get_ptls_states(); // in .A.B.C, first find a binding for A in the chain of module scopes // following parent links. then evaluate the rest of the path from there. // in A.B, look for A in Main first. - jl_sym_t *var = (jl_sym_t*)jl_array_ptr_ref(args,0); - size_t i=1; - if (!jl_is_symbol(var)) jl_type_error("import or using", (jl_value_t*)jl_sym_type, (jl_value_t*)var); - jl_module_t *m; + jl_sym_t *var = (jl_sym_t*)jl_array_ptr_ref(args, 0); + size_t i = 1; + if (!jl_is_symbol(var)) + jl_type_error("import or using", (jl_value_t*)jl_sym_type, (jl_value_t*)var); + jl_module_t *m; if (var != dot_sym) { m = jl_main_module; } else { - m = ptls->current_module; + m = from; while (1) { - var = (jl_sym_t*)jl_array_ptr_ref(args,i); - if (!jl_is_symbol(var)) jl_type_error("import or using", (jl_value_t*)jl_sym_type, (jl_value_t*)var); + var = (jl_sym_t*)jl_array_ptr_ref(args, i); + if (!jl_is_symbol(var)) + jl_type_error("import or using", (jl_value_t*)jl_sym_type, (jl_value_t*)var); i++; if (var != dot_sym) { if (i == jl_array_len(args)) @@ -401,13 +401,14 @@ static jl_module_t *eval_import_path_(jl_array_t *args, int retrying) if (require_func != NULL) { jl_value_t *reqargs[2] = {require_func, (jl_value_t*)var}; jl_apply(reqargs, 2); - return eval_import_path_(args, 1); + return eval_import_path_(from, args, 1); } } } if (retrying && require_func) { - jl_printf(JL_STDERR, "WARNING: requiring \"%s\" in module \"%s\" did not define a corresponding module.\n", jl_symbol_name(var), - jl_symbol_name(ptls->current_module->name)); + jl_printf(JL_STDERR, "WARNING: requiring \"%s\" in module \"%s\" did not define a corresponding module.\n", + jl_symbol_name(var), + jl_symbol_name(from->name)); return NULL; } else { @@ -425,12 +426,12 @@ static jl_module_t *eval_import_path_(jl_array_t *args, int retrying) return m; } -static jl_module_t *eval_import_path(jl_array_t *args) +static jl_module_t *eval_import_path(jl_module_t *from, jl_array_t *args) { - return eval_import_path_(args, 0); + return eval_import_path_(from, args, 0); } -jl_value_t *jl_toplevel_eval_body(jl_array_t *stmts); +jl_value_t *jl_toplevel_eval_body(jl_module_t *m, jl_array_t *stmts); int jl_is_toplevel_only_expr(jl_value_t *e) { @@ -450,6 +451,7 @@ static jl_method_instance_t *jl_new_thunk(jl_code_info_t *src, jl_module_t *modu jl_method_instance_t *li = jl_new_method_instance_uninit(); li->inferred = (jl_value_t*)src; li->specTypes = (jl_value_t*)jl_emptytuple_type; + li->def.module = module; jl_array_t *stmts = (jl_array_t*)src->code; size_t i, l; JL_GC_PUSH1(&li); @@ -460,7 +462,7 @@ static jl_method_instance_t *jl_new_thunk(jl_code_info_t *src, jl_module_t *modu return li; } -jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast, int expanded) +jl_value_t *jl_toplevel_eval_flex(jl_module_t *m, jl_value_t *e, int fast, int expanded) { jl_ptls_t ptls = jl_get_ptls_states(); if (!jl_is_expr(e)) { @@ -468,59 +470,62 @@ jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast, int expanded) jl_lineno = jl_linenode_line(e); return jl_nothing; } - return jl_interpret_toplevel_expr(e); + return jl_interpret_toplevel_expr_in(m, e, NULL, NULL); } jl_expr_t *ex = (jl_expr_t*)e; if (ex->head == error_sym || ex->head == jl_incomplete_sym) { // expression types simple enough not to need expansion - return jl_interpret_toplevel_expr(e); + return jl_interpret_toplevel_expr_in(m, e, NULL, NULL); } else if (ex->head == module_sym) { - return jl_eval_module_expr(ex); + return jl_eval_module_expr(m, ex); } else if (ex->head == importall_sym) { - jl_module_t *m = eval_import_path(ex->args); - if (m==NULL) return jl_nothing; - jl_sym_t *name = (jl_sym_t*)jl_array_ptr_ref(ex->args, jl_array_len(ex->args)-1); + jl_module_t *import = eval_import_path(m, ex->args); + if (import == NULL) + return jl_nothing; + jl_sym_t *name = (jl_sym_t*)jl_array_ptr_ref(ex->args, jl_array_len(ex->args) - 1); if (!jl_is_symbol(name)) jl_error("syntax: malformed \"importall\" statement"); - m = (jl_module_t*)jl_eval_global_var(m, name); - if (!jl_is_module(m)) + import = (jl_module_t*)jl_eval_global_var(import, name); + if (!jl_is_module(import)) jl_errorf("invalid %s statement: name exists but does not refer to a module", jl_symbol_name(ex->head)); - jl_module_importall(ptls->current_module, m); + jl_module_importall(m, import); return jl_nothing; } else if (ex->head == using_sym) { - jl_module_t *m = eval_import_path(ex->args); - if (m==NULL) return jl_nothing; - jl_sym_t *name = (jl_sym_t*)jl_array_ptr_ref(ex->args, jl_array_len(ex->args)-1); + jl_module_t *import = eval_import_path(m, ex->args); + if (import == NULL) + return jl_nothing; + jl_sym_t *name = (jl_sym_t*)jl_array_ptr_ref(ex->args, jl_array_len(ex->args) - 1); if (!jl_is_symbol(name)) jl_error("syntax: malformed \"using\" statement"); - jl_module_t *u = (jl_module_t*)jl_eval_global_var(m, name); + jl_module_t *u = (jl_module_t*)jl_eval_global_var(import, name); if (jl_is_module(u)) { - jl_module_using(ptls->current_module, u); + jl_module_using(m, u); } else { - jl_module_use(ptls->current_module, m, name); + jl_module_use(m, import, name); } return jl_nothing; } else if (ex->head == import_sym) { - jl_module_t *m = eval_import_path(ex->args); - if (m==NULL) return jl_nothing; - jl_sym_t *name = (jl_sym_t*)jl_array_ptr_ref(ex->args, jl_array_len(ex->args)-1); + jl_module_t *import = eval_import_path(m, ex->args); + if (import == NULL) + return jl_nothing; + jl_sym_t *name = (jl_sym_t*)jl_array_ptr_ref(ex->args, jl_array_len(ex->args) - 1); if (!jl_is_symbol(name)) jl_error("syntax: malformed \"import\" statement"); - jl_module_import(ptls->current_module, m, name); + jl_module_import(m, import, name); return jl_nothing; } else if (ex->head == export_sym) { - for(size_t i=0; i < jl_array_len(ex->args); i++) { + for (size_t i = 0; i < jl_array_len(ex->args); i++) { jl_sym_t *name = (jl_sym_t*)jl_array_ptr_ref(ex->args, i); if (!jl_is_symbol(name)) jl_error("syntax: malformed \"export\" statement"); - jl_module_export(ptls->current_module, name); + jl_module_export(m, name); } return jl_nothing; } @@ -538,7 +543,7 @@ jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast, int expanded) if (!expanded && ex->head != body_sym && ex->head != thunk_sym && ex->head != return_sym && ex->head != method_sym && ex->head != toplevel_sym) { // not yet expanded - ex = (jl_expr_t*)jl_expand(e); + ex = (jl_expr_t*)jl_expand(e, m); } jl_sym_t *head = jl_is_expr(ex) ? ex->head : NULL; @@ -548,7 +553,7 @@ jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast, int expanded) int i; for (i = 0; i < jl_array_len(ex->args); i++) { ptls->world_age = jl_world_counter; // eval each statement in the newest world age - res = jl_toplevel_eval_flex(jl_array_ptr_ref(ex->args, i), fast, 0); + res = jl_toplevel_eval_flex(m, jl_array_ptr_ref(ex->args, i), fast, 0); } ptls->world_age = last_age; JL_GC_POP(); @@ -559,22 +564,22 @@ jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast, int expanded) thk = (jl_code_info_t*)jl_exprarg(ex,0); assert(jl_is_code_info(thk)); assert(jl_typeis(thk->code, jl_array_any_type)); - ewc = jl_eval_with_compiler_p(thk, (jl_array_t*)thk->code, fast, ptls->current_module); + ewc = jl_eval_with_compiler_p(thk, (jl_array_t*)thk->code, fast, m); } else { - if (head && jl_eval_expr_with_compiler_p((jl_value_t*)ex, fast, ptls->current_module)) { + if (head && jl_eval_expr_with_compiler_p((jl_value_t*)ex, fast, m)) { thk = jl_wrap_expr((jl_value_t*)ex); ewc = 1; } else { if (head == body_sym) { - result = jl_toplevel_eval_body(ex->args); + result = jl_toplevel_eval_body(m, ex->args); } else if (jl_is_toplevel_only_expr((jl_value_t*)ex)) { - result = jl_toplevel_eval((jl_value_t*)ex); + result = jl_toplevel_eval(m, (jl_value_t*)ex); } else { - result = jl_interpret_toplevel_expr((jl_value_t*)ex); + result = jl_interpret_toplevel_expr_in(m, (jl_value_t*)ex, NULL, NULL); } JL_GC_POP(); return result; @@ -582,28 +587,27 @@ jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast, int expanded) } if (ewc) { - li = jl_new_thunk(thk, ptls->current_module); + li = jl_new_thunk(thk, m); size_t world = jl_get_ptls_states()->world_age; jl_type_infer(&li, world, 0); jl_value_t *dummy_f_arg = NULL; result = jl_call_method_internal(li, &dummy_f_arg, 1); } else { - result = jl_interpret_toplevel_thunk(thk); + result = jl_interpret_toplevel_thunk(m, thk); } JL_GC_POP(); return result; } -JL_DLLEXPORT jl_value_t *jl_toplevel_eval(jl_value_t *v) +JL_DLLEXPORT jl_value_t *jl_toplevel_eval(jl_module_t *m, jl_value_t *v) { - return jl_toplevel_eval_flex(v, 1, 0); + return jl_toplevel_eval_flex(m, v, 1, 0); } -JL_DLLEXPORT jl_value_t *jl_load(const char *fname) +JL_DLLEXPORT jl_value_t *jl_load(jl_module_t *module, const char *fname) { - jl_ptls_t ptls = jl_get_ptls_states(); - if (ptls->current_module->istopmod) { + if (module->istopmod) { jl_printf(JL_STDOUT, "%s\r\n", fname); #ifdef _OS_WINDOWS_ uv_run(uv_default_loop(), (uv_run_mode)1); @@ -613,14 +617,14 @@ JL_DLLEXPORT jl_value_t *jl_load(const char *fname) if (jl_stat(fname, (char*)&stbuf) != 0 || (stbuf.st_mode & S_IFMT) != S_IFREG) { jl_errorf("could not open file %s", fname); } - return jl_parse_eval_all(fname, NULL, 0); + return jl_parse_eval_all(fname, NULL, 0, module); } // load from filename given as a String object -JL_DLLEXPORT jl_value_t *jl_load_(jl_value_t *str) +JL_DLLEXPORT jl_value_t *jl_load_(jl_module_t *module, jl_value_t *str) { // assume String has a hidden '\0' at the end - return jl_load((const char*)jl_string_data(str)); + return jl_load(module, (const char*)jl_string_data(str)); } #ifdef __cplusplus diff --git a/test/broadcast.jl b/test/broadcast.jl index 4368462f4e7b5..b9b07c11f54fc 100644 --- a/test/broadcast.jl +++ b/test/broadcast.jl @@ -312,12 +312,12 @@ end # make sure scalars are inlined, which causes f.(x,scalar) to lower to a "thunk" import Base.Meta: isexpr -@test isexpr(expand(:(f.(x,y))), :call) -@test isexpr(expand(:(f.(x,1))), :thunk) -@test isexpr(expand(:(f.(x,1.0))), :thunk) -@test isexpr(expand(:(f.(x,$π))), :thunk) -@test isexpr(expand(:(f.(x,"hello"))), :thunk) -@test isexpr(expand(:(f.(x,$("hello")))), :thunk) +@test isexpr(expand(Main, :(f.(x,y))), :call) +@test isexpr(expand(Main, :(f.(x,1))), :thunk) +@test isexpr(expand(Main, :(f.(x,1.0))), :thunk) +@test isexpr(expand(Main, :(f.(x,$π))), :thunk) +@test isexpr(expand(Main, :(f.(x,"hello"))), :thunk) +@test isexpr(expand(Main, :(f.(x,$("hello")))), :thunk) # PR #17623: Fused binary operators @test [true] .* [true] == [true] diff --git a/test/cmdlineargs.jl b/test/cmdlineargs.jl index 7278d6c214b41..7af3336c3fd98 100644 --- a/test/cmdlineargs.jl +++ b/test/cmdlineargs.jl @@ -406,9 +406,9 @@ for precomp in ("yes", "no") @test contains(bt, "include_from_node1") if ((is_windows() && Sys.WORD_SIZE == 32) || (is_bsd() && !is_apple())) && precomp == "yes" # FIXME: Issue #17251 (Windows), #20798 (FreeBSD) - @test_broken contains(bt, "include_from_node1(::String) at $(joinpath(".","loading.jl"))") + @test_broken contains(bt, "include_from_node1(::Module, ::String) at $(joinpath(".", "loading.jl"))") else - @test contains(bt, "include_from_node1(::String) at $(joinpath(".","loading.jl"))") + @test contains(bt, "include_from_node1(::Module, ::String) at $(joinpath(".", "loading.jl"))") end lno = match(r"at \.[\/\\]loading\.jl:(\d+)", bt) @test length(lno.captures) == 1 diff --git a/test/core.jl b/test/core.jl index a75ca32ee8b4c..32d0f73a1d23d 100644 --- a/test/core.jl +++ b/test/core.jl @@ -376,7 +376,7 @@ begin function f7234_b() global f7234_cnt += 1 glob_x2 += 1 - global f7235_cnt += -10000 + global f7234_cnt += -10000 end end @test_throws UndefVarError f7234_b() @@ -499,8 +499,8 @@ end bar21900 = foo21900 + 1 end end -@test !isdefined(:foo21900) -@test !isdefined(:bar21900) +@test !@isdefined(foo21900) +@test !@isdefined(bar21900) bar21900 = 0 @test_throws UndefVarError @eval begin for i21900 = 1:10 @@ -512,7 +512,7 @@ bar21900 = 0 end end @test bar21900 == -1 -@test !isdefined(:foo21900) +@test !@isdefined foo21900 foo21900 = 0 @test nothing === @eval begin for i21900 = 1:10 @@ -739,6 +739,7 @@ end let didthrow = try include_string( + @__MODULE__, """ module TestInitError __init__() = error() @@ -1413,7 +1414,8 @@ let g4505{X}(::X) = 0 @test g4505(0) == 0 end -@test !isdefined(:g4505) +@test !@isdefined g4505 +@test !isdefined(@__MODULE__, :g4505) # issue #4681 # ccall should error if convert() returns something of the wrong type @@ -1711,9 +1713,15 @@ test5536(a::Union{Real, AbstractArray}) = "Non-splatting" @test test5536(5) == "Non-splatting" # multiline comments (#6139 and others raised in #6128) and embedded NUL chars (#10994) -@test 3 == include_string("1 + 2") == include_string("1 + #==# 2") == include_string("1 + #===# 2") == include_string("1 + #= #= blah =# =# 2") == include_string("1 + #= #= #= nested =# =# =# 2") == include_string("1 + #= \0 =# 2") -@test_throws LoadError include_string("#=") -@test_throws LoadError include_string("#= #= #= =# =# =") +@test 3 == + include_string(@__MODULE__, "1 + 2") == + include_string(@__MODULE__, "1 + #==# 2") == + include_string(@__MODULE__, "1 + #===# 2") == + include_string(@__MODULE__, "1 + #= #= blah =# =# 2") == + include_string(@__MODULE__, "1 + #= #= #= nested =# =# =# 2") == + include_string(@__MODULE__, "1 + #= \0 =# 2") +@test_throws LoadError include_string(@__MODULE__, "#=") +@test_throws LoadError include_string(@__MODULE__, "#= #= #= =# =# =") # issue #6142 import Base: + @@ -1829,7 +1837,7 @@ macro m20524(ex) end @m20524 ((a,(b20524,c)) = (8,(1,5)); (a,b20524,c)) @test f20524() === (8,1,5) -@test !isdefined(:b20524) # should not assign to a global +@test !@isdefined b20524 # should not assign to a global # issue #6387 primitive type Date6387{C} 64 end @@ -3734,7 +3742,7 @@ let k15283 = j15283+=1 end @test j15283 == 1 -@test !isdefined(:k15283) +@test !@isdefined k15283 # issue #15264 module Test15264 diff --git a/test/distributed_exec.jl b/test/distributed_exec.jl index 4583fbf237d31..d54763101d6dd 100644 --- a/test/distributed_exec.jl +++ b/test/distributed_exec.jl @@ -1599,7 +1599,7 @@ function setup_syms(n, pids) eval(:(global $sym = rand())) for p in pids eval(:(@test $sym == remotecall_fetch(()->$sym, $p))) - eval(:(@test remotecall_fetch(isdefined, $p, Symbol($symstr)))) + eval(:(@test remotecall_fetch(isdefined, $p, Main, Symbol($symstr)))) end push!(syms, sym) end diff --git a/test/docs.jl b/test/docs.jl index eadd59e65cad1..e91238c2781d0 100644 --- a/test/docs.jl +++ b/test/docs.jl @@ -495,7 +495,8 @@ end # Issue #16359. Error message for invalid doc syntax. -let __source__ = LineNumberNode(0) +let __source__ = LineNumberNode(0), + __module__ = @__MODULE__ for each in [ # valid syntax :(f()), :(f(x)), @@ -504,14 +505,14 @@ let __source__ = LineNumberNode(0) :(f(x = 1)), :(f(; x = 1)) ] - @test Meta.isexpr(Docs.docm(__source__, "...", each), :block) + @test Meta.isexpr(Docs.docm(__source__, __module__, "...", each), :block) end for each in [ # invalid syntax :(f("...")), :(f(1, 2)), :(f(() -> ())) ] - result = Docs.docm(__source__, "...", each) + result = Docs.docm(__source__, __module__, "...", each) @test Meta.isexpr(result, :call) @test result.args[1] === error end @@ -705,7 +706,7 @@ end ) # Issue #13905. -@test macroexpand(:(@doc "" f() = @x)) == Expr(:error, UndefVarError(Symbol("@x"))) +@test @macroexpand(@doc "" f() = @x) == Expr(:error, UndefVarError(Symbol("@x"))) # Undocumented DataType Summaries. @@ -978,8 +979,8 @@ dynamic_test.x = "test 2" @test @doc(dynamic_test) == "test 2 Union{}" @test @doc(dynamic_test(::String)) == "test 2 Tuple{String}" -@test Docs._repl(:(dynamic_test(1.0))) == Expr(:macrocall, Symbol("@doc"), LineNumberNode(204, doc_util_path), esc(:(dynamic_test(::typeof(1.0))))) -@test Docs._repl(:(dynamic_test(::String))) == Expr(:macrocall, Symbol("@doc"), LineNumberNode(204, doc_util_path), esc(:(dynamic_test(::String)))) +@test Docs._repl(:(dynamic_test(1.0))) == Expr(:macrocall, Symbol("@doc"), LineNumberNode(206, doc_util_path), esc(:(dynamic_test(::typeof(1.0))))) +@test Docs._repl(:(dynamic_test(::String))) == Expr(:macrocall, Symbol("@doc"), LineNumberNode(206, doc_util_path), esc(:(dynamic_test(::String)))) # Equality testing diff --git a/test/fastmath.jl b/test/fastmath.jl index 80120e7c7b2fd..bac571c5bf2ab 100644 --- a/test/fastmath.jl +++ b/test/fastmath.jl @@ -4,12 +4,12 @@ # check expansions -@test macroexpand(:(@fastmath 1+2)) == :(Base.FastMath.add_fast(1,2)) -@test macroexpand(:(@fastmath +)) == :(Base.FastMath.add_fast) -@test macroexpand(:(@fastmath min(1))) == :(Base.FastMath.min_fast(1)) -@test macroexpand(:(@fastmath min)) == :(Base.FastMath.min_fast) -@test macroexpand(:(@fastmath x.min)) == :(x.min) -@test macroexpand(:(@fastmath sincos(x))) == :(Base.FastMath.sincos_fast(x)) +@test macroexpand(Main, :(@fastmath 1+2)) == :(Base.FastMath.add_fast(1,2)) +@test macroexpand(Main, :(@fastmath +)) == :(Base.FastMath.add_fast) +@test macroexpand(Main, :(@fastmath min(1))) == :(Base.FastMath.min_fast(1)) +@test macroexpand(Main, :(@fastmath min)) == :(Base.FastMath.min_fast) +@test macroexpand(Main, :(@fastmath x.min)) == :(x.min) +@test macroexpand(Main, :(@fastmath sincos(x))) == :(Base.FastMath.sincos_fast(x)) # basic arithmetic diff --git a/test/inline.jl b/test/inline.jl index 3a7d7cc76ac8b..769ea452d8a17 100644 --- a/test/inline.jl +++ b/test/inline.jl @@ -113,8 +113,8 @@ let a = read21311() end @testset "issue #19122: [no]inline of short func. def. with return type annotation" begin - exf19122 = macroexpand(:(@inline f19122()::Bool = true)) - exg19122 = macroexpand(:(@noinline g19122()::Bool = true)) + exf19122 = @macroexpand(@inline f19122()::Bool = true) + exg19122 = @macroexpand(@noinline g19122()::Bool = true) @test exf19122.args[2].args[1].args[1] == :inline @test exg19122.args[2].args[1].args[1] == :noinline diff --git a/test/loading.jl b/test/loading.jl index a39e094061859..a7d29f31cabc1 100644 --- a/test/loading.jl +++ b/test/loading.jl @@ -33,9 +33,9 @@ end include("test_sourcepath.jl") thefname = "the fname!//\\&\1*" -include_string_test_func = include_string("include_string_test() = @__FILE__", thefname) +include_string_test_func = include_string(@__MODULE__, "include_string_test() = @__FILE__", thefname) @test include_string_test_func() == thefname -@test include_string("Base.source_path()", thefname) == Base.source_path() +@test include_string(@__MODULE__, "Base.source_path()", thefname) == Base.source_path() @test basename(@__FILE__) == "loading.jl" @test isabspath(@__FILE__) diff --git a/test/misc.jl b/test/misc.jl index 599aadf854064..fd39d9f903e2c 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -269,7 +269,7 @@ end # test that they don't introduce global vars global v11801, t11801, names_before_timing -names_before_timing = names(current_module(), true) +names_before_timing = names(@__MODULE__, true) let t = @elapsed 1+1 @test isa(t, Real) && t >= 0 @@ -288,7 +288,7 @@ v11801, t11801 = @timed sin(1) @test v11801 == sin(1) @test isa(t11801,Real) && t11801 >= 0 -@test names(current_module(), true) == names_before_timing +@test names(@__MODULE__, true) == names_before_timing # interactive utilities diff --git a/test/parse.jl b/test/parse.jl index 5fd78b99d476f..d07c558179be9 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -495,7 +495,7 @@ test_parseerror("0x0.1", "hex float literal must contain \"p\" or \"P\"") test_parseerror("0x1.0p", "invalid numeric constant \"0x1.0\"") # issue #15798 -@test expand(Base.parse_input_line(""" +@test expand(Main, Base.parse_input_line(""" try = "No" """)) == Expr(:error, "unexpected \"=\"") @@ -524,10 +524,10 @@ test_parseerror("if\nfalse\nend", "missing condition in \"if\" at none:1") test_parseerror("if false\nelseif\nend", "missing condition in \"elseif\" at none:2") # issue #15828 -@test expand(parse("x...")) == Expr(:error, "\"...\" expression outside call") +@test expand(Main, parse("x...")) == Expr(:error, "\"...\" expression outside call") # issue #15830 -@test expand(parse("foo(y = (global x)) = y")) == Expr(:error, "misplaced \"global\" declaration") +@test expand(Main, parse("foo(y = (global x)) = y")) == Expr(:error, "misplaced \"global\" declaration") # issue #15844 function f15844(x) @@ -558,11 +558,11 @@ add_method_to_glob_fn!() @test_throws ParseError parse("function finally() end") # PR #16170 -@test expand(parse("true(x) = x")) == Expr(:error, "invalid function name \"true\"") -@test expand(parse("false(x) = x")) == Expr(:error, "invalid function name \"false\"") +@test expand(Main, parse("true(x) = x")) == Expr(:error, "invalid function name \"true\"") +@test expand(Main, parse("false(x) = x")) == Expr(:error, "invalid function name \"false\"") # issue #16355 -@test expand(:(f(d:Int...)=nothing)) == Expr(:error, "\"d:Int\" is not a valid function argument name") +@test expand(Main, :(f(d:Int...) = nothing)) == Expr(:error, "\"d:Int\" is not a valid function argument name") # issue #16517 @test (try error(); catch 0; end) === 0 @@ -642,7 +642,7 @@ end # issue #16720 let err = try - include_string("module A + include_string(@__MODULE__, "module A function broken() @@ -707,27 +707,27 @@ let m_error, error_out, filename = Base.source_path() end # issue #7272 -@test expand(parse("let +@test expand(Main, parse("let global x = 2 local x = 1 end")) == Expr(:error, "variable \"x\" declared both local and global") -@test expand(parse("let +@test expand(Main, parse("let local x = 2 local x = 1 end")) == Expr(:error, "local \"x\" declared twice") -@test expand(parse("let x +@test expand(Main, parse("let x local x = 1 end")) == Expr(:error, "local \"x\" declared twice") -@test expand(parse("let x = 2 +@test expand(Main, parse("let x = 2 local x = 1 end")) == Expr(:error, "local \"x\" declared twice") # make sure front end can correctly print values to error messages -let ex = expand(parse("\"a\"=1")) +let ex = expand(Main, parse("\"a\"=1")) @test ex == Expr(:error, "invalid assignment location \"\"a\"\"") end @@ -747,20 +747,23 @@ for (str, tag) in Dict("" => :none, "\"" => :string, "#=" => :comment, "'" => :c end # meta nodes for optional positional arguments -@test expand(:(@inline f(p::Int=2) = 3)).args[2].args[3].inlineable +@test expand(Main, :(@inline f(p::Int=2) = 3)).args[2].args[3].inlineable # issue #16096 module M16096 macro iter() - quote + return quote @inline function foo(sub) it = 1 end end end end -let ex = expand(:(@M16096.iter)) - @test !(isa(ex,Expr) && ex.head === :error) +let ex = expand(@__MODULE__, :(@M16096.iter)) + @test isa(ex, Expr) && ex.head === :thunk +end +let ex = expand(Main, :($M16096.@iter)) + @test isa(ex, Expr) && ex.head === :thunk end macro f16096() quote @@ -791,12 +794,12 @@ module B15838 end @test A15838.@f() === nothing @test A15838.@f(1) === :b -let nometh = expand(:(A15838.@f(1, 2))), __source__ = LineNumberNode(@__LINE__, Symbol(@__FILE__)) +let nometh = expand(@__MODULE__, :(A15838.@f(1, 2))), __source__ = LineNumberNode(@__LINE__, Symbol(@__FILE__)) @test (nometh::Expr).head === :error @test length(nometh.args) == 1 e = nometh.args[1]::MethodError @test e.f === getfield(A15838, Symbol("@f")) - @test e.args === (__source__, 1, 2) + @test e.args === (__source__, @__MODULE__, 1, 2) end # issue 10046 @@ -805,11 +808,11 @@ for op in ["+", "-", "\$", "|", ".+", ".-", "*", ".*"] end # issue #17701 -@test expand(:(i==3 && i+=1)) == Expr(:error, "invalid assignment location \"==(i,3)&&i\"") +@test expand(Main, :(i==3 && i+=1)) == Expr(:error, "invalid assignment location \"==(i,3)&&i\"") # issue #18667 -@test expand(:(true = 1)) == Expr(:error, "invalid assignment location \"true\"") -@test expand(:(false = 1)) == Expr(:error, "invalid assignment location \"false\"") +@test expand(Main, :(true = 1)) == Expr(:error, "invalid assignment location \"true\"") +@test expand(Main, :(false = 1)) == Expr(:error, "invalid assignment location \"false\"") # PR #15592 let str = "[1] [2]" @@ -869,7 +872,7 @@ macro m2() 1 end end -include_string(""" +include_string(@__MODULE__, """ macro m3() quote @m1 @@ -881,10 +884,10 @@ macro m4() end end """, "another_file.jl") -m1_exprs = get_expr_list(expand(:(@m1))) -m2_exprs = get_expr_list(expand(:(@m2))) -m3_exprs = get_expr_list(expand(:(@m3))) -m4_exprs = get_expr_list(expand(:(@m4))) +m1_exprs = get_expr_list(expand(@__MODULE__, :(@m1))) +m2_exprs = get_expr_list(expand(@__MODULE__, :(@m2))) +m3_exprs = get_expr_list(expand(@__MODULE__, :(@m3))) +m4_exprs = get_expr_list(expand(@__MODULE__, :(@m4))) # Check the expanded expresion has expected number of matching push/pop # and the return is handled correctly @@ -967,7 +970,7 @@ end @test parse("Foo{T} = Bar{T}") == Expr(:(=), Expr(:curly, :Foo, :T), Expr(:curly, :Bar, :T)) # don't insert push_loc for filename `none` at the top level -let ex = expand(parse(""" +let ex = expand(Main, parse(""" begin x = 1 end""")) @@ -1026,8 +1029,8 @@ end let global const (c8925, d8925) = (3, 4) end -@test c8925 == 3 && isconst(:c8925) -@test d8925 == 4 && isconst(:d8925) +@test c8925 == 3 && isconst(@__MODULE__, :c8925) +@test d8925 == 4 && isconst(@__MODULE__, :d8925) # issue #18754: parse ccall as a regular function @test parse("ccall([1], 2)[3]") == Expr(:ref, Expr(:call, :ccall, Expr(:vect, 1), 2), 3) @@ -1054,8 +1057,8 @@ end # issue #20541 @test parse("[a .!b]") == Expr(:hcat, :a, Expr(:call, :(.!), :b)) -@test expand(:(a{1} = b)) == Expr(:error, "invalid type parameter name \"1\"") -@test expand(:(a{2<:Any} = b)) == Expr(:error, "invalid type parameter name \"2\"") +@test expand(Main, :(a{1} = b)) == Expr(:error, "invalid type parameter name \"1\"") +@test expand(Main, :(a{2<:Any} = b)) == Expr(:error, "invalid type parameter name \"2\"") # issue #20653 @test_throws UndefVarError Base.call(::Int) = 1 @@ -1076,14 +1079,14 @@ macro m20729() return ex end -@test_throws ErrorException eval(:(@m20729)) -@test expand(:(@m20729)) == Expr(:error, "undefined reference in AST") +@test_throws ErrorException eval(@__MODULE__, :(@m20729)) +@test expand(@__MODULE__, :(@m20729)) == Expr(:error, "undefined reference in AST") macro err20000() return Expr(:error, "oops!") end -@test expand(:(@err20000)) == Expr(:error, "oops!") +@test expand(@__MODULE__, :(@err20000)) == Expr(:error, "oops!") # issue #20000 @test parse("@m(a; b=c)") == Expr(:macrocall, Symbol("@m"), LineNumberNode(1, :none), @@ -1101,8 +1104,8 @@ g21054(>:) = >:2 @test g21054(-) == -2 # issue #21168 -@test expand(:(a.[1])) == Expr(:error, "invalid syntax a.[1]") -@test expand(:(a.{1})) == Expr(:error, "invalid syntax a.{1}") +@test expand(Main, :(a.[1])) == Expr(:error, "invalid syntax a.[1]") +@test expand(Main, :(a.{1})) == Expr(:error, "invalid syntax a.{1}") # Issue #21225 let abstr = parse("abstract type X end") @@ -1209,8 +1212,8 @@ module Test21607 end # issue #16937 -@test expand(:(f(2, a=1, w=3, c=3, w=4, b=2))) == Expr(:error, - "keyword argument \"w\" repeated in call to \"f\"") +@test expand(Main, :(f(2, a=1, w=3, c=3, w=4, b=2))) == + Expr(:error, "keyword argument \"w\" repeated in call to \"f\"") let f(x) = g(x) = 1 diff --git a/test/reflection.jl b/test/reflection.jl index 0e00763f70c26..5a85bb31c729f 100644 --- a/test/reflection.jl +++ b/test/reflection.jl @@ -88,7 +88,7 @@ tag = Base.have_color ? Base.error_color() : "ARRAY{FLOAT64,N}" # Make sure emphasis is not used for other functions tag = Base.have_color ? Base.error_color() : "ANY" iob = IOBuffer() -show(iob, expand(:(x->x^2))) +show(iob, expand(Main, :(x -> x^2))) str = String(take!(iob)) @test isempty(search(str, tag)) @@ -151,11 +151,11 @@ i10165{T,n}(::Type{AbstractArray{T,n}}) = 1 const a_const = 1 not_const = 1 -@test isconst(:a_const) == true +@test isconst(@__MODULE__, :a_const) == true @test isconst(Base, :pi) == true -@test isconst(:pi) == true -@test isconst(:not_const) == false -@test isconst(:is_not_defined) == false +@test isconst(@__MODULE__, :pi) == true +@test isconst(@__MODULE__, :not_const) == false +@test isconst(@__MODULE__, :is_not_defined) == false @test isimmutable(1) == true @test isimmutable([]) == false @@ -188,22 +188,21 @@ module TestModSub9475 b9475 = 7 foo9475(x) = x let - @test Base.binding_module(:a9475) == current_module() - @test Base.binding_module(:c7648) == TestMod7648 - @test Base.module_name(current_module()) == :TestModSub9475 - @test Base.fullname(current_module()) == (curmod_name..., :TestMod7648, - :TestModSub9475) - @test Base.module_parent(current_module()) == TestMod7648 + @test Base.binding_module(@__MODULE__, :a9475) == @__MODULE__ + @test Base.binding_module(@__MODULE__, :c7648) == TestMod7648 + @test Base.module_name(@__MODULE__) == :TestModSub9475 + @test Base.fullname(@__MODULE__) == (curmod_name..., :TestMod7648, :TestModSub9475) + @test Base.module_parent(@__MODULE__) == TestMod7648 end end # module TestModSub9475 using .TestModSub9475 let - @test Base.binding_module(:d7648) == current_module() - @test Base.binding_module(:a9475) == TestModSub9475 - @test Base.module_name(current_module()) == :TestMod7648 - @test Base.module_parent(current_module()) == curmod + @test Base.binding_module(@__MODULE__, :d7648) == @__MODULE__ + @test Base.binding_module(@__MODULE__, :a9475) == TestModSub9475 + @test Base.module_name(@__MODULE__) == :TestMod7648 + @test Base.module_parent(@__MODULE__) == curmod end end # module TestMod7648 @@ -214,18 +213,19 @@ let @test Set(names(TestMod7648))==Set([:TestMod7648, :a9475, :foo9475, :c7648, :foo7648, :foo7648_nomethods, :Foo7648]) @test Set(names(TestMod7648, true)) == Set([:TestMod7648, :TestModSub9475, :a9475, :foo9475, :c7648, :d7648, :f7648, :foo7648, Symbol("#foo7648"), :foo7648_nomethods, Symbol("#foo7648_nomethods"), - :Foo7648, :eval, Symbol("#eval")]) + :Foo7648, :eval, Symbol("#eval"), :include, Symbol("#include")]) @test Set(names(TestMod7648, true, true)) == Set([:TestMod7648, :TestModSub9475, :a9475, :foo9475, :c7648, :d7648, :f7648, :foo7648, Symbol("#foo7648"), :foo7648_nomethods, Symbol("#foo7648_nomethods"), - :Foo7648, :eval, Symbol("#eval"), :convert, :curmod_name, :curmod]) + :Foo7648, :eval, Symbol("#eval"), :include, Symbol("#include"), + :convert, :curmod_name, :curmod]) @test isconst(TestMod7648, :c7648) @test !isconst(TestMod7648, :d7648) end let using .TestMod7648 - @test Base.binding_module(:a9475) == TestMod7648.TestModSub9475 - @test Base.binding_module(:c7648) == TestMod7648 + @test Base.binding_module(@__MODULE__, :a9475) == TestMod7648.TestModSub9475 + @test Base.binding_module(@__MODULE__, :c7648) == TestMod7648 @test Base.function_name(foo7648) == :foo7648 @test Base.function_module(foo7648, (Any,)) == TestMod7648 @test Base.function_module(foo7648) == TestMod7648 @@ -254,11 +254,14 @@ export this_is_not_defined @test_throws ErrorException which(:this_is_not_defined) @test_throws ErrorException @which this_is_not_defined @test_throws ErrorException which(:this_is_not_exported) -@test isexported(current_module(), :this_is_not_defined) -@test !isexported(current_module(), :this_is_not_exported) +@test isexported(@__MODULE__, :this_is_not_defined) +@test !isexported(@__MODULE__, :this_is_not_exported) const a_value = 1 -@test which(:a_value) == current_module() -@test !isexported(current_module(), :a_value) +@test Base.which_module(@__MODULE__, :a_value) === @__MODULE__ +@test @which(a_value) === @__MODULE__ +@test_throws ErrorException which(:a_value) +@test which(:Core) === Main +@test !isexported(@__MODULE__, :a_value) end # issue #13264 @@ -365,11 +368,11 @@ end let using .MacroTest a = 1 - m = getfield(current_module(), Symbol("@macrotest")) - @test which(m, Tuple{LineNumberNode, Int, Symbol}) == @which @macrotest 1 a - @test which(m, Tuple{LineNumberNode, Int, Int}) == @which @macrotest 1 1 + m = getfield(@__MODULE__, Symbol("@macrotest")) + @test which(m, Tuple{LineNumberNode, Module, Int, Symbol}) == @which @macrotest 1 a + @test which(m, Tuple{LineNumberNode, Module, Int, Int}) == @which @macrotest 1 1 - @test first(methods(m, Tuple{LineNumberNode, Int, Int})) == @which MacroTest.@macrotest 1 1 + @test first(methods(m, Tuple{LineNumberNode, Module, Int, Int})) == @which MacroTest.@macrotest 1 1 @test functionloc(@which @macrotest 1 1) == @functionloc @macrotest 1 1 end diff --git a/test/repl.jl b/test/repl.jl index 65b27398db249..028cc02540f37 100644 --- a/test/repl.jl +++ b/test/repl.jl @@ -592,7 +592,7 @@ end # let exename # issue #19864: mutable struct Error19864 <: Exception; end function test19864() - @eval current_module() Base.showerror(io::IO, e::Error19864) = print(io, "correct19864") + @eval Base.showerror(io::IO, e::Error19864) = print(io, "correct19864") buf = IOBuffer() REPL.print_response(buf, Error19864(), [], false, false, nothing) return String(take!(buf)) diff --git a/test/replutil.jl b/test/replutil.jl index ac4bec2258976..d8c63b3b276bc 100644 --- a/test/replutil.jl +++ b/test/replutil.jl @@ -375,8 +375,8 @@ let err_str, "(::Type{$(curmod_prefix)EightBitTypeT{T}})() where T in $curmod_str at $sp:$(method_defs_lineno + 5)" @test sprint(show, which(reinterpret(EightBitTypeT{Int32}, 0x54), Tuple{})) == "(::$(curmod_prefix)EightBitTypeT)() in $curmod_str at $sp:$(method_defs_lineno + 6)" - @test startswith(sprint(show, which(getfield(Base, Symbol("@doc")), Tuple{LineNumberNode, Vararg{Any}})), - "@doc(__source__::LineNumberNode, x...) in Core at boot.jl:") + @test startswith(sprint(show, which(getfield(Base, Symbol("@doc")), Tuple{LineNumberNode, Module, Vararg{Any}})), + "@doc(__source__::LineNumberNode, __module__::Module, x...) in Core at boot.jl:") @test startswith(sprint(show, which(FunctionLike(), Tuple{})), "(::$(curmod_prefix)FunctionLike)() in $curmod_str at $sp:$(method_defs_lineno + 7)") @test stringmime("text/plain", FunctionLike()) == "(::FunctionLike) (generic function with 1 method)" @@ -476,8 +476,8 @@ macro seven_dollar(ex) end let - @test (@macroexpand @macroexpand x) == macroexpand(:(@macroexpand x)) - @test (@macroexpand :(1+$y) ) == macroexpand(:( :(1+ $y))) + @test (@macroexpand @macroexpand x) == macroexpand(@__MODULE__, :(@macroexpand x)) + @test (@macroexpand :(1+$y) ) == macroexpand(@__MODULE__, :( :(1+ $y) )) @test (@macroexpand @fastmath 1+2 ) == :(Base.FastMath.add_fast(1,2)) @test (@macroexpand @fastmath + ) == :(Base.FastMath.add_fast) @test (@macroexpand @fastmath min(1) ) == :(Base.FastMath.min_fast(1)) diff --git a/test/stacktraces.jl b/test/stacktraces.jl index 19e23aa0f18f1..8ad2eed101095 100644 --- a/test/stacktraces.jl +++ b/test/stacktraces.jl @@ -98,12 +98,13 @@ for (frame, func, inlined) in zip(trace, [g,h,f], (can_inline, can_inline, false end end -let src = expand(quote let x = 1 end end).args[1]::CodeInfo, +let src = expand(Main, quote let x = 1 end end).args[1]::CodeInfo, li = ccall(:jl_new_method_instance_uninit, Ref{Core.MethodInstance}, ()), sf li.inferred = src li.specTypes = Tuple{} + li.def = @__MODULE__ sf = StackFrame(:a, :b, 3, li, false, false, 0) repr = string(sf) @test repr == "Toplevel MethodInstance thunk at b:3" diff --git a/test/strings/basic.jl b/test/strings/basic.jl index 551d46305d0f8..bf1fb7741c862 100644 --- a/test/strings/basic.jl +++ b/test/strings/basic.jl @@ -53,7 +53,7 @@ let sym = Symbol(Char(0xdcdb)) @test string(sym) == string(Char(0xdcdb)) @test String(sym) == string(Char(0xdcdb)) - @test expand(sym) === sym + @test expand(Main, sym) === sym res = string(parse(string(Char(0xdcdb)," = 1"),1,raise=false)[1]) @test res == """\$(Expr(:error, "invalid character \\\"\\udcdb\\\"\"))""" end diff --git a/test/testenv.jl b/test/testenv.jl index 871999c759536..6447d6e342d09 100644 --- a/test/testenv.jl +++ b/test/testenv.jl @@ -5,7 +5,7 @@ # This file can be included multiple times in the same module if necessary, # which can happen with unisolated test runs. -if !isdefined(:testenv_defined) +if !@isdefined(testenv_defined) const testenv_defined = true if haskey(ENV, "JULIA_TEST_EXEFLAGS") const test_exeflags = `$(Base.shell_split(ENV["JULIA_TEST_EXEFLAGS"]))` @@ -28,7 +28,7 @@ if !isdefined(:testenv_defined) addprocs_with_testenv(X; kwargs...) = addprocs(X; exename=test_exename, exeflags=test_exeflags, kwargs...) - const curmod = current_module() + const curmod = @__MODULE__ const curmod_name = fullname(curmod) const curmod_str = curmod === Main ? "Main" : join(curmod_name, ".") const curmod_prefix = "$(["$m." for m in curmod_name]...)" diff --git a/test/threads.jl b/test/threads.jl index 878db358f0456..a93c336795b29 100644 --- a/test/threads.jl +++ b/test/threads.jl @@ -136,7 +136,7 @@ threaded_gc_locked(Mutex) # Issue 14726 # Make sure that eval'ing in a different module doesn't mess up other threads -orig_curmodule14726 = current_module() +orig_curmodule14726 = @__MODULE__ main_var14726 = 1 module M14726 module_var14726 = 1 @@ -147,15 +147,15 @@ end @eval M14726 module_var14726 = $j end end -@test isdefined(:orig_curmodule14726) -@test isdefined(:main_var14726) -@test current_module() == orig_curmodule14726 +@test @isdefined(orig_curmodule14726) +@test @isdefined(main_var14726) +@test @__MODULE__() == orig_curmodule14726 @threads for i in 1:100 # Make sure current module is not null. # The @test might not be particularly meaningful currently since the # thread infrastructures swallows the error. (Same below) - @test current_module() == orig_curmodule14726 + @test @__MODULE__() == orig_curmodule14726 end module M14726_2 @@ -166,7 +166,7 @@ using Base.Threads # pushes the work onto the threads. # The @test might not be particularly meaningful currently since the # thread infrastructures swallows the error. (See also above) - @test current_module() == M14726_2 + @test @__MODULE__() == M14726_2 end end diff --git a/test/workspace.jl b/test/workspace.jl index 44a315c6fbf5d..3cd95121fbed0 100644 --- a/test/workspace.jl +++ b/test/workspace.jl @@ -6,26 +6,34 @@ script = """ # Issue #11948 f(x) = x+1 workspace() -@assert !isdefined(:f) -LastMain.f(2) +@assert @__MODULE__() === Main +@assert isdefined(Main, :f) +@assert !@isdefined LastMain +@eval Core.Main begin + @assert @__MODULE__() === Main + @assert !isdefined(Main, :f) + LastMain.f(2) -# PR #12990 -io = IOBuffer() -show(io, Pair) -@assert String(take!(io)) == "Pair" -@assert !Base.inbase(LastMain) + # PR #12990 + io = IOBuffer() + show(io, Pair) + @assert String(take!(io)) == "Pair" + @assert !Base.inbase(LastMain) +end """ exename = Base.julia_cmd() -run(`$exename --startup-file=no -e $script`) +@test success(pipeline(`$exename --startup-file=no -e $script`, stdout=STDOUT, stderr=STDERR)) # issue #17764 script2 = """ mutable struct Foo end workspace() -mutable struct Foo end -@assert Tuple{Type{LastMain.Foo}} !== Tuple{Type{Main.Foo}} +@eval Core.Main begin + mutable struct Foo end + @assert Tuple{Type{LastMain.Foo}} !== Tuple{Type{Main.Foo}} +end """ -run(`$exename --startup-file=no -e $script2`) +@test success(pipeline(`$exename --startup-file=no -e $script2`, stdout=STDOUT, stderr=STDERR)) # Issue #22101 mktempdir() do dir diff --git a/ui/repl.c b/ui/repl.c index 0ae1580f7cda0..2355675b2fa53 100644 --- a/ui/repl.c +++ b/ui/repl.c @@ -46,7 +46,7 @@ static int exec_program(char *program) { jl_ptls_t ptls = jl_get_ptls_states(); JL_TRY { - jl_load(program); + jl_load(jl_main_module, program); } JL_CATCH { jl_value_t *errs = jl_stderr_obj(); From eca9d071b7d3e13af218ddee64d1fea76c9103cb Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Fri, 2 Jun 2017 15:42:21 +0900 Subject: [PATCH 1004/1534] add libatomic as a std_dll --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index e30685efe3f9b..f1d243634d61f 100644 --- a/Makefile +++ b/Makefile @@ -328,6 +328,7 @@ $(eval $(call std_dll,gcc_s_seh-1)) endif $(eval $(call std_dll,ssp-0)) $(eval $(call std_dll,winpthread-1)) +$(eval $(call std_dll,atomic-1)) endif define stringreplace $(build_depsbindir)/stringreplace $$(strings -t x - $1 | grep '$2' | awk '{print $$1;}') '$3' 255 "$(call cygpath_w,$1)" From b30da43053c7cb619b645247039d7e3ac778a245 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Fri, 2 Jun 2017 15:47:00 +0900 Subject: [PATCH 1005/1534] use libatomic on mingw --- src/jitlayers.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index 54a950a4ec99d..6ee85dd8331c1 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -341,12 +341,17 @@ void NotifyDebugger(jit_code_entry *JITCodeEntry) } // ------------------------ END OF TEMPORARY COPY FROM LLVM ----------------- -#if defined(_OS_LINUX_) +#if defined(_OS_LINUX_) || defined(_OS_WINDOWS_) // Resolve non-lock free atomic functions in the libatomic library. // This is the library that provides support for c11/c++11 atomic operations. static uint64_t resolve_atomic(const char *name) { - static void *atomic_hdl = jl_load_dynamic_library_e("libatomic", +#if defined(_OS_LINUX_) + static const char *const libatomic = "libatomic"; +#elif defined(_OS_WINDOWS_) + static const char *const libatomic = "libatomic-1"; +#endif + static void *atomic_hdl = jl_load_dynamic_library_e(libatomic, JL_RTLD_LOCAL); static const char *const atomic_prefix = "__atomic_"; if (!atomic_hdl) @@ -578,7 +583,7 @@ void JuliaOJIT::addModule(std::unique_ptr M) // Step 2: Search the program symbols if (uint64_t addr = SectionMemoryManager::getSymbolAddressInProcess(Name)) return JL_SymbolInfo(addr, JITSymbolFlags::Exported); -#if defined(_OS_LINUX_) +#if defined(_OS_LINUX_) || defined(_OS_WINDOWS_) if (uint64_t addr = resolve_atomic(Name.c_str())) return JL_SymbolInfo(addr, JITSymbolFlags::Exported); #endif From eca1f1eb73289170dd89657c18b36d11e00f9921 Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Fri, 2 Jun 2017 15:52:07 +0900 Subject: [PATCH 1006/1534] Revert "Disable szclass 12 for i686 systems. (#19647)" This reverts commit 5f5c6bbf3eb2f3e1476f0de6795a18198f3eddc1. --- src/julia_internal.h | 9 +++------ src/julia_threads.h | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/julia_internal.h b/src/julia_internal.h index 47b2b1365dd83..e631a05bdbaf7 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -136,12 +136,9 @@ void *jl_gc_perm_alloc(size_t sz, int zero, unsigned align, unsigned offset); static const int jl_gc_sizeclasses[JL_GC_N_POOLS] = { #ifdef _P64 8, -#elif defined(_CPU_ARM_) || defined(_CPU_PPC_) || defined(_CPU_X86_) +#elif defined(_CPU_ARM_) || defined(_CPU_PPC_) // ARM and PowerPC have max alignment of 8, // make sure allocation of size 8 has that alignment. - // for x86 alignment is important for atomic ops and - // the corresponding platform ABI. Once we can use - // libatomic on Windows this is no longer necessary. 4, 8, #else 4, 8, 12, @@ -177,7 +174,7 @@ STATIC_INLINE int jl_gc_alignment(size_t sz) #ifdef _P64 (void)sz; return 16; -#elif defined(_CPU_ARM_) || defined(_CPU_PPC_) || defined(_CPU_X86_) +#elif defined(_CPU_ARM_) || defined(_CPU_PPC_) return sz <= 4 ? 8 : 16; #else // szclass 8 @@ -198,7 +195,7 @@ STATIC_INLINE int JL_CONST_FUNC jl_gc_szclass(size_t sz) if (sz <= 8) return 0; const int N = 0; -#elif defined(_CPU_ARM_) || defined(_CPU_PPC_) || defined(_CPU_X86_) +#elif defined(_CPU_ARM_) || defined(_CPU_PPC_) if (sz <= 8) return (sz + 3) / 4 - 1; const int N = 1; diff --git a/src/julia_threads.h b/src/julia_threads.h index 1051d740c8b85..cc4fd2479e2ae 100644 --- a/src/julia_threads.h +++ b/src/julia_threads.h @@ -62,7 +62,7 @@ typedef struct { // variables for allocating objects from pools #ifdef _P64 # define JL_GC_N_POOLS 41 -#elif defined(_CPU_ARM_) || defined(_CPU_PPC_) || defined(_CPU_X86_) +#elif defined(_CPU_ARM_) || defined(_CPU_PPC_) # define JL_GC_N_POOLS 42 #else # define JL_GC_N_POOLS 43 From 1946a1fc1c3ad69014567655644b4e27e622c8ca Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Mon, 5 Jun 2017 16:11:48 +0200 Subject: [PATCH 1007/1534] shuffle: allow multidimensional arrays --- base/random.jl | 16 ++++++++-------- test/random.jl | 2 ++ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/base/random.jl b/base/random.jl index bac84d93c24ba..ac646b6010d62 100644 --- a/base/random.jl +++ b/base/random.jl @@ -1482,12 +1482,12 @@ randsubseq(A::AbstractArray, p::Real) = randsubseq(GLOBAL_RNG, A, p) end """ - shuffle!([rng=GLOBAL_RNG,] v) + shuffle!([rng=GLOBAL_RNG,] v::AbstractArray) -In-place version of [`shuffle`](@ref): randomly permute the array `v` in-place, +In-place version of [`shuffle`](@ref): randomly permute `v` in-place, optionally supplying the random-number generator `rng`. """ -function shuffle!(r::AbstractRNG, a::AbstractVector) +function shuffle!(r::AbstractRNG, a::AbstractArray) n = length(a) @assert n <= Int64(2)^52 mask = nextpow2(n) - 1 @@ -1499,18 +1499,18 @@ function shuffle!(r::AbstractRNG, a::AbstractVector) return a end -shuffle!(a::AbstractVector) = shuffle!(GLOBAL_RNG, a) +shuffle!(a::AbstractArray) = shuffle!(GLOBAL_RNG, a) """ - shuffle([rng=GLOBAL_RNG,] v) + shuffle([rng=GLOBAL_RNG,] v::AbstractArray) Return a randomly permuted copy of `v`. The optional `rng` argument specifies a random number generator (see [Random Numbers](@ref)). -To permute `v` in-place, see [`shuffle!`](@ref). To obtain randomly permuted +To permute `v` in-place, see [`shuffle!`](@ref). To obtain randomly permuted indices, see [`randperm`](@ref). """ -shuffle(r::AbstractRNG, a::AbstractVector) = shuffle!(r, copymutable(a)) -shuffle(a::AbstractVector) = shuffle(GLOBAL_RNG, a) +shuffle(r::AbstractRNG, a::AbstractArray) = shuffle!(r, copymutable(a)) +shuffle(a::AbstractArray) = shuffle(GLOBAL_RNG, a) """ randperm([rng=GLOBAL_RNG,] n::Integer) diff --git a/test/random.jl b/test/random.jl index 79bbc7ecb2126..fcdc6867571fb 100644 --- a/test/random.jl +++ b/test/random.jl @@ -431,6 +431,8 @@ let mta = MersenneTwister(42), mtb = MersenneTwister(42) @test shuffle(mta,collect(1:10)) == shuffle(mtb,collect(1:10)) @test shuffle!(mta,collect(1:10)) == shuffle!(mtb,collect(1:10)) @test shuffle(mta,collect(2:11)) == shuffle(mtb,2:11) + @test shuffle!(mta, rand(mta, 2, 3)) == shuffle!(mtb, rand(mtb, 2, 3)) + @test shuffle(mta, rand(mta, 2, 3)) == shuffle(mtb, rand(mtb, 2, 3)) @test randperm(mta,10) == randperm(mtb,10) @test sort!(randperm(10)) == sort!(shuffle(1:10)) == collect(1:10) From c57494983924eab3a6dff19a917e50afc9147a3f Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Tue, 6 Jun 2017 11:30:32 -0400 Subject: [PATCH 1008/1534] Treat bounds check in isassigned as, well, bounds check The change to `isassigned(::SimpleVector, ...)` and `isassigned(::BitArray, ...)` are currently no op since they will unlikely be inlined. The `SimpleVector` version is also currently unsafe to inline. These might change with a better inlining heuristic (#22210) and a smarter GC frame allocation pass (#21888). --- base/array.jl | 2 +- base/essentials.jl | 2 +- base/multidimensional.jl | 2 +- test/boundscheck_exec.jl | 10 ++++++++++ 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/base/array.jl b/base/array.jl index 858eef12fe343..371f56059f668 100644 --- a/base/array.jl +++ b/base/array.jl @@ -96,7 +96,7 @@ sizeof(a::Array) = elsize(a) * length(a) function isassigned(a::Array, i::Int...) @_inline_meta ii = (sub2ind(size(a), i...) % UInt) - 1 - ii < length(a) % UInt || return false + @boundscheck ii < length(a) % UInt || return false ccall(:jl_array_isassigned, Cint, (Any, UInt), a, ii) == 1 end diff --git a/base/essentials.jl b/base/essentials.jl index d16e1ed107204..02e5a6815cad6 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -294,7 +294,7 @@ false function isassigned end function isassigned(v::SimpleVector, i::Int) - 1 <= i <= length(v) || return false + @boundscheck 1 <= i <= length(v) || return false x = unsafe_load(convert(Ptr{Ptr{Void}},data_pointer_from_objref(v)) + i*sizeof(Ptr)) return x != C_NULL end diff --git a/base/multidimensional.jl b/base/multidimensional.jl index a78d5adcac241..0f125757aca10 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -1229,7 +1229,7 @@ end @nexprs $N d->begin l = size(B,d) stride *= l - 1 <= I_{d-1} <= l || return false + @boundscheck 1 <= I_{d-1} <= l || return false index += (I_d - 1) * stride end return isassigned(B, index) diff --git a/test/boundscheck_exec.jl b/test/boundscheck_exec.jl index e6ec13fd2da41..df2deea73cb51 100644 --- a/test/boundscheck_exec.jl +++ b/test/boundscheck_exec.jl @@ -209,4 +209,14 @@ else @test_throws BoundsError V1() end +# This tests both the bounds check elision and the behavior of `jl_array_isassigned` +# For `isbits` array the `ccall` should return a constant `true` and does not access +# the array +inbounds_isassigned(a, i) = @inbounds return isassigned(a, i) +if bc_opt == bc_default || bc_opt == bc_off + @test inbounds_isassigned(Int[], 2) == true +else + @test inbounds_isassigned(Int[], 2) == false +end + end From 7cc752092d37ffa6ab74808868b0d9e9bcca3ff2 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 6 Jun 2017 12:23:35 -0400 Subject: [PATCH 1009/1534] fix #22239, stack overflow in type intersection --- src/subtype.c | 2 +- test/subtype.jl | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/subtype.c b/src/subtype.c index bab38f4ebf443..7ad25a92be3ab 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -1287,7 +1287,7 @@ static jl_value_t *intersect_var(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int return ub; } else if (bb->constraintkind == 0) { - if (!jl_is_typevar(a)) { + if (!jl_is_typevar(bb->ub) && !jl_is_typevar(a)) { if (try_subtype_in_env(bb->ub, a, e)) return (jl_value_t*)b; } diff --git a/test/subtype.jl b/test/subtype.jl index 2c74f70ffc4bd..4ca0b5b288566 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -1108,3 +1108,8 @@ end @testintersect(Tuple{Type{B21613{Tuple{L},L}} where L, Any}, Tuple{Type{SA}, Tuple} where SA<:(A21613{S} where S<:Tuple), Tuple{Type{B21613{Tuple{L},L}} where L, Tuple}) + +# issue #22239 +@testintersect(Val{Pair{T,T}} where T, + Val{Pair{Int,T}} where T, + Val{Pair{Int,Int}}) From 61124ca4a0c56976cef08d89817b884477bf9738 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Tue, 6 Jun 2017 15:17:23 -0400 Subject: [PATCH 1010/1534] use crc32c checksum to validate .ji cache files (#21240) * use crc32c checksum to validate .ji cache files (for #21154) --- base/loading.jl | 22 +++++++++++++++++++++- base/util.jl | 16 +++++++++++----- test/compile.jl | 6 ++++++ test/misc.jl | 7 +++++++ 4 files changed, 45 insertions(+), 6 deletions(-) diff --git a/base/loading.jl b/base/loading.jl index 67d4b08b80557..1a6b5671342d0 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -680,7 +680,15 @@ function compilecache(name::String) info("Precompiling module $name.") end end - if !success(create_expr_cache(path, cachefile, concrete_deps)) + if success(create_expr_cache(path, cachefile, concrete_deps)) + # append checksum to the end of the .ji file: + open(cachefile, "a+") do f + data = Mmap.mmap(f, Vector{UInt8}, filesize(f), 0) + checksum = crc32c(data) + finalize(data) + write(f, hton(checksum)) + end + else error("Failed to precompile $name to $cachefile.") end return cachefile @@ -799,6 +807,18 @@ function stale_cachefile(modpath::String, cachefile::String) return true end end + + # finally, verify that the cache file has a valid checksum + data = Mmap.mmap(io, Vector{UInt8}, filesize(io), 0) + # checksum = UInt32 read in bigendian format from the last 4 bytes: + checksum = UInt32(data[end]) + UInt32(data[end-1])<<8 + UInt32(data[end-2])<<16 + UInt32(data[end-3])<<24 + crc = crc32c(@view(data[1:end-4])) + finalize(data) + if checksum != crc + DEBUG_LOADING[] && info("JL_DEBUG_LOADING: Rejecting cache file $cachefile because it has an invalid checksum.") + return true + end + return false # fresh cachefile finally close(io) diff --git a/base/util.jl b/base/util.jl index ec2cdc660ed01..074e960bf3d6f 100644 --- a/base/util.jl +++ b/base/util.jl @@ -765,16 +765,22 @@ if is_windows() end +# compute sizeof correctly for strings, arrays, and subarrays of bytes +_sizeof(a) = sizeof(a) +_sizeof(a::FastContiguousSubArray{UInt8,N,<:Array{UInt8}} where N) = length(a) + """ crc32c(data, crc::UInt32=0x00000000) + Compute the CRC-32c checksum of the given `data`, which can be -an `Array{UInt8}` or a `String`. Optionally, you can pass -a starting `crc` integer to be mixed in with the checksum. +an `Array{UInt8}`, a contiguous subarray thereof, or a `String`. Optionally, you can pass +a starting `crc` integer to be mixed in with the checksum. The `crc` parameter +can be used to compute a checksum on data divided into chunks: performing +`crc32c(data2, crc32c(data1))` is equivalent to the checksum of `[data1; data2]`. (Technically, a little-endian checksum is computed.) """ -function crc32c end -crc32c(a::Union{Array{UInt8},String}, crc::UInt32=0x00000000) = - ccall(:jl_crc32c, UInt32, (UInt32, Ptr{UInt8}, Csize_t), crc, a, sizeof(a)) +crc32c(a::Union{Array{UInt8},FastContiguousSubArray{UInt8,N,<:Array{UInt8}} where N,String}, crc::UInt32=0x00000000) = + ccall(:jl_crc32c, UInt32, (UInt32, Ptr{UInt8}, Csize_t), crc, a, _sizeof(a)) """ @kwdef typedef diff --git a/test/compile.jl b/test/compile.jl index 2bfa971a00a60..acbf869a5b52c 100644 --- a/test/compile.jl +++ b/test/compile.jl @@ -310,6 +310,12 @@ try @test !Base.stale_cachefile(FooBar_file, joinpath(dir2, "FooBar.ji")) @test !Base.stale_cachefile(FooBar1_file, joinpath(dir2, "FooBar1.ji")) + # test checksum + open(joinpath(dir2, "FooBar1.ji"), "a") do f + write(f, 0x076cac96) # append 4 random bytes + end + @test Base.stale_cachefile(FooBar1_file, joinpath(dir2, "FooBar1.ji")) + # test behavior of precompile modules that throw errors write(FooBar_file, """ diff --git a/test/misc.jl b/test/misc.jl index fd39d9f903e2c..f6cc13c538f78 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -568,6 +568,13 @@ for force_software_crc in (1,0) for (n,crc) in [(0,0x00000000),(1,0xa016d052),(2,0x03f89f52),(3,0xf130f21e),(4,0x29308cf4),(5,0x53518fab),(6,0x4f4dfbab),(7,0xbd3a64dc),(8,0x46891f81),(9,0x5a14b9f9),(10,0xb219db69),(11,0xd232a91f),(12,0x51a15563),(13,0x9f92de41),(14,0x4d8ae017),(15,0xc8b74611),(16,0xa0de6714),(17,0x672c992a),(18,0xe8206eb6),(19,0xc52fd285),(20,0x327b0397),(21,0x318263dd),(22,0x08485ccd),(23,0xea44d29e),(24,0xf6c0cb13),(25,0x3969bba2),(26,0x6a8810ec),(27,0x75b3d0df),(28,0x82d535b1),(29,0xbdf7fc12),(30,0x1f836b7d),(31,0xd29f33af),(32,0x8e4acb3e),(33,0x1cbee2d1),(34,0xb25f7132),(35,0xb0fa484c),(36,0xb9d262b4),(37,0x3207fe27),(38,0xa024d7ac),(39,0x49a2e7c5),(40,0x0e2c157f),(41,0x25f7427f),(42,0x368c6adc),(43,0x75efd4a5),(44,0xa84c5c31),(45,0x0fc817b2),(46,0x8d99a881),(47,0x5cc3c078),(48,0x9983d5e2),(49,0x9267c2db),(50,0xc96d4745),(51,0x058d8df3),(52,0x453f9cf3),(53,0xb714ade1),(54,0x55d3c2bc),(55,0x495710d0),(56,0x3bddf494),(57,0x4f2577d0),(58,0xdae0f604),(59,0x3c57c632),(60,0xfe39bbb0),(61,0x6f5d1d41),(62,0x7d996665),(63,0x68c738dc),(64,0x8dfea7ae)] @test Base.crc32c(UInt8[1:n;]) == crc end + # test that crc parameter is equivalent to checksum of concatenated data, + # and test crc of subarrays: + a = UInt8[1:255;] + crc_256 = Base.crc32c(UInt8[1:255;]) + @views for n = 1:255 + @test Base.crc32c(a[n+1:end], Base.crc32c(a[1:n])) == crc_256 + end end let From 46f57d0f5e6069b7f4876f5c076900830f3e245d Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Tue, 6 Jun 2017 15:01:13 -0500 Subject: [PATCH 1011/1534] Add LibGit2 support for config iterator (#20752) * Add LibGit2 support for config iterator * Refactor if assignment --- base/libgit2/config.jl | 64 ++++++++++++++++++++++++++++++++++++++++++ base/libgit2/types.jl | 20 ++++++++++++- test/libgit2.jl | 50 +++++++++++++++++++++++++++++++++ 3 files changed, 133 insertions(+), 1 deletion(-) diff --git a/base/libgit2/config.jl b/base/libgit2/config.jl index 0abfa28244d0b..5cefdbfcc17c4 100644 --- a/base/libgit2/config.jl +++ b/base/libgit2/config.jl @@ -128,3 +128,67 @@ function set!(c::GitConfig, name::AbstractString, value::Int64) @check ccall((:git_config_set_int64, :libgit2), Cint, (Ptr{Void}, Cstring, Cintmax_t), c.ptr, name, value) end + +function GitConfigIter(cfg::GitConfig) + ci_ptr = Ref{Ptr{Void}}(C_NULL) + @check ccall((:git_config_iterator_new, :libgit2), Cint, + (Ptr{Ptr{Void}}, Ptr{Void}), ci_ptr, cfg.ptr) + return GitConfigIter(ci_ptr[]) +end + +function GitConfigIter(cfg::GitConfig, name::AbstractString) + ci_ptr = Ref{Ptr{Void}}(C_NULL) + @check ccall((:git_config_multivar_iterator_new, :libgit2), Cint, + (Ptr{Ptr{Void}}, Ptr{Void}, Cstring, Cstring), + ci_ptr, cfg.ptr, name, C_NULL) + return GitConfigIter(ci_ptr[]) +end + +function GitConfigIter(cfg::GitConfig, name::AbstractString, value::Regex) + ci_ptr = Ref{Ptr{Void}}(C_NULL) + @check ccall((:git_config_multivar_iterator_new, :libgit2), Cint, + (Ptr{Ptr{Void}}, Ptr{Void}, Cstring, Cstring), + ci_ptr, cfg.ptr, name, value.pattern) + return GitConfigIter(ci_ptr[]) +end + +function GitConfigIter(cfg::GitConfig, name::Regex) + ci_ptr = Ref{Ptr{Void}}(C_NULL) + @check ccall((:git_config_iterator_glob_new, :libgit2), Cint, + (Ptr{Ptr{Void}}, Ptr{Void}, Cstring), + ci_ptr, cfg.ptr, name.pattern) + return GitConfigIter(ci_ptr[]) +end + +function Base.start(ci::GitConfigIter) + entry_ptr_ptr = Ref{Ptr{ConfigEntry}}(C_NULL) + err = ccall((:git_config_next, :libgit2), Cint, + (Ptr{Ptr{ConfigEntry}}, Ptr{Void}), entry_ptr_ptr, ci.ptr) + if err == Cint(Error.GIT_OK) + state = Nullable{ConfigEntry}(unsafe_load(entry_ptr_ptr[])) + elseif err == Cint(Error.ITEROVER) + state = Nullable{ConfigEntry}() + else + throw(GitError(err)) + end + return state +end + +Base.done(ci::GitConfigIter, state) = isnull(state) + +function Base.next(ci::GitConfigIter, state) + entry = Base.get(state) + entry_ptr_ptr = Ref{Ptr{ConfigEntry}}(C_NULL) + err = ccall((:git_config_next, :libgit2), Cint, + (Ptr{Ptr{ConfigEntry}}, Ptr{Void}), entry_ptr_ptr, ci.ptr) + if err == Cint(Error.GIT_OK) + state = Nullable{ConfigEntry}(unsafe_load(entry_ptr_ptr[])) + elseif err == Cint(Error.ITEROVER) + state = Nullable{ConfigEntry}() + else + throw(GitError(err)) + end + return (entry, state) +end + +Base.iteratorsize(::Type{GitConfigIter}) = Base.SizeUnknown() diff --git a/base/libgit2/types.jl b/base/libgit2/types.jl index 0e7715c0bc2f6..60f0ca5c86457 100644 --- a/base/libgit2/types.jl +++ b/base/libgit2/types.jl @@ -1,7 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license import Base.@kwdef -import .Consts: GIT_SUBMODULE_IGNORE, GIT_MERGE_FILE_FAVOR, GIT_MERGE_FILE +import .Consts: GIT_SUBMODULE_IGNORE, GIT_MERGE_FILE_FAVOR, GIT_MERGE_FILE, GIT_CONFIG const OID_RAWSZ = 20 const OID_HEXSZ = OID_RAWSZ * 2 @@ -516,6 +516,23 @@ function Base.show(io::IO, fh::FetchHead) println(io, "Merged: $(fh.ismerge)") end +""" + LibGit2.ConfigEntry + +Matches the [`git_config_entry`](https://libgit2.github.com/libgit2/#HEAD/type/git_config_entry) struct. +""" +@kwdef struct ConfigEntry + name::Cstring + value::Cstring + level::GIT_CONFIG = Consts.CONFIG_LEVEL_DEFAULT + free::Ptr{Void} + payload::Ptr{Void} +end + +function Base.show(io::IO, ce::ConfigEntry) + print(io, "ConfigEntry(\"", unsafe_string(ce.name), "\", \"", unsafe_string(ce.value), "\")") +end + # Abstract object types abstract type AbstractGitObject end Base.isempty(obj::AbstractGitObject) = (obj.ptr == C_NULL) @@ -536,6 +553,7 @@ for (typ, owntyp, sup, cname) in [ (:GitRebase, :GitRepo, :AbstractGitObject, :git_rebase), (:GitStatus, :GitRepo, :AbstractGitObject, :git_status_list), (:GitBranchIter, :GitRepo, :AbstractGitObject, :git_branch_iterator), + (:GitConfigIter, nothing, :AbstractGitObject, :git_config_iterator), (:GitUnknownObject, :GitRepo, :GitObject, :git_object), (:GitCommit, :GitRepo, :GitObject, :git_commit), (:GitBlob, :GitRepo, :GitObject, :git_blob), diff --git a/test/libgit2.jl b/test/libgit2.jl index 18d0137a63555..b9ff2acb2c6b2 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -229,6 +229,56 @@ mktempdir() do dir @test LibGit2.get(cfg, "tmp.int32", Int32(0)) == Int32(1) @test LibGit2.get(cfg, "tmp.int64", Int64(0)) == Int64(1) @test LibGit2.get(cfg, "tmp.bool", false) == true + + # Ordering of entries appears random when using `LibGit2.set!` + count = 0 + for entry in LibGit2.GitConfigIter(cfg, r"tmp.*") + count += 1 + name, value = unsafe_string(entry.name), unsafe_string(entry.value) + if name == "tmp.str" + @test value == "AAAA" + elseif name == "tmp.int32" + @test value == "1" + elseif name == "tmp.int64" + @test value == "1" + elseif name == "tmp.bool" + @test value == "true" + else + error("Found unexpected entry: $name") + end + end + @test count == 4 + finally + close(cfg) + end + end + + @testset "Configuration Iteration" begin + config_path = joinpath(dir, config_file) + + # Write config entries with duplicate names + open(config_path, "a") do fp + write(fp, """ + [credential] + \thelper = store + [credential] + \thelper = cache + """) + end + + cfg = LibGit2.GitConfig(config_path, LibGit2.Consts.CONFIG_LEVEL_APP) + try + # Will only see the last entry + @test LibGit2.get(cfg, "credential.helper", "") == "cache" + + count = 0 + for entry in LibGit2.GitConfigIter(cfg, "credential.helper") + count += 1 + name, value = unsafe_string(entry.name), unsafe_string(entry.value) + @test name == "credential.helper" + @test value == (count == 1 ? "store" : "cache") + end + @test count == 2 finally close(cfg) end From 91f08bb0a5e0f5872d5e10baee3994f0dc62a201 Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Tue, 6 Jun 2017 15:33:13 -0500 Subject: [PATCH 1012/1534] NEWS for to_indices (#19730) (#22152) * NEWS for to_indices (#19730) --- NEWS.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/NEWS.md b/NEWS.md index 849dda108f0fb..aba5151988789 100644 --- a/NEWS.md +++ b/NEWS.md @@ -413,6 +413,22 @@ Library improvements that dimension's length will be computed such that its product with all the other dimensions is equal to the length of the original array ([#19919]). + * The new `to_indices` function provides a uniform interface for index conversions, + taking an array and a tuple of indices as arguments and returning a tuple of + integers and/or arrays of supported scalar indices. It will throw an `ArgumentError` + for any unsupported indices, and the returned arrays should be iterated over (and + not indexed into) to support more efficient logical indexing ([#19730]). + + + Using colons (`:`) to represent a collection of indices is deprecated. They now must be + explicitly converted to a specialized array of integers with the `to_indices` function. +    As a result, the type of `SubArray`s that represent views over colon indices has changed. + + + Logical indexing is now more efficient. Logical arrays are converted by `to_indices` to + a lazy, iterable collection of indices that doesn't support indexing. A deprecation + provides indexing support with O(n) lookup. + + + The performance of indexing with `CartesianIndex`es is also improved in many situations. + * A new `titlecase` function was added, to capitalize the first character of each word within a string ([#19469]). * `any` and `all` now always short-circuit, and `mapreduce` never short-circuits ([#19543]). From 97195d6d989ff92476b91c25aa0133c3e834ea2c Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Tue, 6 Jun 2017 22:59:06 +0200 Subject: [PATCH 1013/1534] where syntax: add few curly braces for short form functions (#22243) --- base/dict.jl | 8 ++++---- base/util.jl | 2 +- base/weakkeydict.jl | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/base/dict.jl b/base/dict.jl index a1f98b92dd38f..adaec0b8a6998 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -135,10 +135,10 @@ copy(d::Dict) = Dict(d) const AnyDict = Dict{Any,Any} -Dict(ps::Pair{K,V}...) where {K,V} = Dict{K,V}(ps) -Dict(ps::Pair{K}...,) where K = Dict{K,Any}(ps) -Dict(ps::(Pair{K,V} where K)...,) where V = Dict{Any,V}(ps) -Dict(ps::Pair...) = Dict{Any,Any}(ps) +Dict(ps::Pair{K,V}...) where {K,V} = Dict{K,V}(ps) +Dict(ps::Pair{K}...) where {K} = Dict{K,Any}(ps) +Dict(ps::(Pair{K,V} where K)...) where {V} = Dict{Any,V}(ps) +Dict(ps::Pair...) = Dict{Any,Any}(ps) function Dict(kv) try diff --git a/base/util.jl b/base/util.jl index 074e960bf3d6f..a909b8355cf7a 100644 --- a/base/util.jl +++ b/base/util.jl @@ -641,7 +641,7 @@ will always be called. function securezero! end @noinline securezero!(a::AbstractArray{<:Number}) = fill!(a, 0) securezero!(s::String) = unsafe_securezero!(pointer(s), sizeof(s)) -@noinline unsafe_securezero!(p::Ptr{T}, len::Integer=1) where T = +@noinline unsafe_securezero!(p::Ptr{T}, len::Integer=1) where {T} = ccall(:memset, Ptr{T}, (Ptr{T}, Cint, Csize_t), p, 0, len*sizeof(T)) unsafe_securezero!(p::Ptr{Void}, len::Integer=1) = Ptr{Void}(unsafe_securezero!(Ptr{UInt8}(p), len)) diff --git a/base/weakkeydict.jl b/base/weakkeydict.jl index 1097eba93e770..17712ebc2f9f6 100644 --- a/base/weakkeydict.jl +++ b/base/weakkeydict.jl @@ -49,8 +49,8 @@ WeakKeyDict(kv::Tuple{}) = WeakKeyDict() copy(d::WeakKeyDict) = WeakKeyDict(d) WeakKeyDict(ps::Pair{K,V}...) where {K,V} = WeakKeyDict{K,V}(ps) -WeakKeyDict(ps::Pair{K}...) where {K } = WeakKeyDict{K,Any}(ps) -WeakKeyDict(ps::(Pair{K,V} where K)...) where {V } = WeakKeyDict{Any,V}(ps) +WeakKeyDict(ps::Pair{K}...) where {K} = WeakKeyDict{K,Any}(ps) +WeakKeyDict(ps::(Pair{K,V} where K)...) where {V} = WeakKeyDict{Any,V}(ps) WeakKeyDict(ps::Pair...) = WeakKeyDict{Any,Any}(ps) function WeakKeyDict(kv) From 46ca257bfd93e81f6515f7453d4d5467a17c9126 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Sun, 4 Jun 2017 19:43:54 -0400 Subject: [PATCH 1014/1534] Add a Makefile option to disable libunwind There's been a request for a version of julia that does not depend on libunwind, for easier bring up on new architectures. This adds a makefile flag that can be put in Make.user (`DISABLE_LIBUNWIND`) and if set, will disable any dependency on libunwind. Backtraces and profiling won't work of course. --- Make.inc | 7 +++++++ deps/Makefile | 2 ++ src/debuginfo.cpp | 6 ++---- src/julia_internal.h | 6 +++++- src/signals-unix.c | 16 +++++++++++----- src/stackwalk.c | 18 ++++++++++++++++-- 6 files changed, 43 insertions(+), 12 deletions(-) diff --git a/Make.inc b/Make.inc index 06c3d17e29bff..eb4e92a010e89 100644 --- a/Make.inc +++ b/Make.inc @@ -26,6 +26,7 @@ OPENBLAS_USE_THREAD:=1 # Use libraries available on the system instead of building them USE_SYSTEM_LLVM:=0 USE_SYSTEM_LIBUNWIND:=0 +DISABLE_LIBUNWIND:=0 USE_SYSTEM_PCRE:=0 USE_SYSTEM_LIBM:=0 USE_SYSTEM_OPENLIBM:=0 @@ -737,6 +738,8 @@ endif ifeq ($(OS),WINNT) LIBUNWIND:= +else ifneq ($(DISABLE_LIBUNWIND), 0) +LIBUNWIND:= else ifeq ($(USE_SYSTEM_LIBUNWIND), 1) ifneq ($(OS),Darwin) @@ -985,6 +988,10 @@ ifeq ($(USE_OPROFILE_JITEVENTS), 1) JCPPFLAGS += -DJL_USE_OPROFILE_JITEVENTS endif +ifeq ($(DISABLE_LIBUNWIND), 1) +JCPPFLAGS += -DJL_DISABLE_LIBUNWIND +endif + # Intel libraries ifeq ($(USE_INTEL_LIBM), 1) diff --git a/deps/Makefile b/deps/Makefile index 12183252513cf..516266916fe73 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -48,6 +48,7 @@ ifeq ($(USE_SYSTEM_LIBUV), 0) DEP_LIBS += libuv endif +ifeq ($(DISABLE_LIBUNWIND), 0) ifeq ($(USE_SYSTEM_LIBUNWIND), 0) ifeq ($(OS), Linux) DEP_LIBS += unwind @@ -57,6 +58,7 @@ else ifeq ($(OS), Darwin) DEP_LIBS += osxunwind endif endif +endif ifneq (,$(findstring $(OS),Linux FreeBSD)) ifeq ($(USE_SYSTEM_PATCHELF), 0) diff --git a/src/debuginfo.cpp b/src/debuginfo.cpp index 11ac809029e56..6e219e0afd523 100644 --- a/src/debuginfo.cpp +++ b/src/debuginfo.cpp @@ -41,9 +41,7 @@ using namespace llvm; #include "julia.h" #include "julia_internal.h" #include "codegen_internal.h" -#ifdef _OS_LINUX_ -# define UNW_LOCAL_ONLY -# include +#if defined(_OS_LINUX_) # include #endif @@ -1400,7 +1398,7 @@ static int jl_getDylibFunctionInfo(jl_frame_t **frames, size_t pointer, int skip } frame0->fromC = !isSysImg; if (isSysImg && sysimg_fvars) { -#ifdef _OS_LINUX_ +#if defined(_OS_LINUX_) && !defined(JL_DISABLE_LIBUNWIND) unw_proc_info_t pip; if (!saddr && unw_get_proc_info_by_ip(unw_local_addr_space, pointer, &pip, NULL) == 0) diff --git a/src/julia_internal.h b/src/julia_internal.h index 47b2b1365dd83..a3e62756880b6 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -648,7 +648,7 @@ typedef struct { } bt_cursor_t; #endif extern volatile int jl_in_stackwalk; -#else +#elif !defined(JL_DISABLE_LIBUNWIND) // This gives unwind only local unwinding options ==> faster code # define UNW_LOCAL_ONLY # include @@ -660,6 +660,10 @@ typedef unw_cursor_t bt_cursor_t; // on a newer release # define JL_UNW_HAS_FORMAT_IP 1 # endif +#else +// Unwinding is disabled +typedef int bt_context_t; +typedef int bt_cursor_t; #endif size_t rec_backtrace(uintptr_t *data, size_t maxsize); size_t rec_backtrace_ctx(uintptr_t *data, size_t maxsize, bt_context_t *ctx); diff --git a/src/signals-unix.c b/src/signals-unix.c index 9820dbc356df9..2b69f43d6a972 100644 --- a/src/signals-unix.c +++ b/src/signals-unix.c @@ -284,6 +284,7 @@ static void allocate_segv_handler(void) } } +#if !defined(JL_DISABLE_LIBUNWIND) static unw_context_t *volatile signal_context; static pthread_mutex_t in_signal_lock; static pthread_cond_t exit_signal_cond; @@ -310,6 +311,7 @@ static void jl_thread_resume(int tid, int sig) assert(jl_atomic_load_acquire(&ptls2->signal_request) == 0); pthread_mutex_unlock(&in_signal_lock); } +#endif // Throw jl_interrupt_exception if the master thread is in a signal async region // or if SIGINT happens too often. @@ -360,6 +362,7 @@ void usr2_handler(int sig, siginfo_t *info, void *ctx) { jl_ptls_t ptls = jl_get_ptls_states(); sig_atomic_t request = jl_atomic_exchange(&ptls->signal_request, 0); +#if !defined(JL_DISABLE_LIBUNWIND) if (request == 1) { signal_context = jl_to_bt_context(ctx); @@ -372,7 +375,9 @@ void usr2_handler(int sig, siginfo_t *info, void *ctx) pthread_cond_broadcast(&signal_caught_cond); pthread_mutex_unlock(&in_signal_lock); } - else if (request == 2) { + else +#endif + if (request == 2) { jl_unblock_signal(sig); int force = jl_check_force_sigint(); if (force || (!ptls->defer_signal && ptls->io_wait)) { @@ -526,9 +531,7 @@ static void *signal_listener(void *arg) static uintptr_t bt_data[JL_MAX_BT_SIZE + 1]; static size_t bt_size = 0; sigset_t sset; - unw_context_t *signal_context; int sig, critical, profile; - int i; jl_sigsetset(&sset); while (1) { profile = 0; @@ -591,9 +594,11 @@ static void *signal_listener(void *arg) #endif bt_size = 0; +#if !defined(JL_DISABLE_LIBUNWIND) + unw_context_t *signal_context; // sample each thread, round-robin style in reverse order // (so that thread zero gets notified last) - for (i = jl_n_threads; i-- > 0; ) { + for (int i = jl_n_threads; i-- > 0; ) { // notify thread to stop jl_thread_suspend_and_get_state(i, &signal_context); @@ -624,6 +629,7 @@ static void *signal_listener(void *arg) // notify thread to resume jl_thread_resume(i, sig); } +#endif // this part is async with the running of the rest of the program // and must be thread-safe, but not necessarily signal-handler safe @@ -647,7 +653,7 @@ void restore_signals(void) jl_sigsetset(&sset); sigprocmask(SIG_SETMASK, &sset, 0); -#if !defined(HAVE_MACH) +#if !defined(HAVE_MACH) && !defined(JL_DISABLE_LIBUNWIND) if (pthread_mutex_init(&in_signal_lock, NULL) != 0 || pthread_cond_init(&exit_signal_cond, NULL) != 0 || pthread_cond_init(&signal_caught_cond, NULL) != 0) { diff --git a/src/stackwalk.c b/src/stackwalk.c index 85e85b3663de3..1f1cd043c4296 100644 --- a/src/stackwalk.c +++ b/src/stackwalk.c @@ -13,8 +13,10 @@ // returning from the callee function will invalidate the context #ifdef _OS_WINDOWS_ #define jl_unw_get(context) RtlCaptureContext(context) -#else +#elif !defined(JL_DISABLE_LIBUNWIND) #define jl_unw_get(context) unw_getcontext(context) +#else +void jl_unw_get(void *context) {}; #endif #ifdef __cplusplus @@ -302,7 +304,7 @@ static int jl_unw_step(bt_cursor_t *cursor, uintptr_t *ip, uintptr_t *sp) #endif } -#else +#elif !defined(JL_DISABLE_LIBUNWIND) // stacktrace using libunwind static int jl_unw_init(bt_cursor_t *cursor, bt_context_t *context) @@ -338,6 +340,18 @@ size_t rec_backtrace_ctx_dwarf(uintptr_t *data, size_t maxsize, return n > maxsize ? maxsize : n; } #endif + +#else +// stacktraces are disabled +static int jl_unw_init(bt_cursor_t *cursor, bt_context_t *context) +{ + return 0; +} + +static int jl_unw_step(bt_cursor_t *cursor, uintptr_t *ip, uintptr_t *sp) +{ + return 0; +} #endif JL_DLLEXPORT jl_value_t *jl_lookup_code_address(void *ip, int skipC) From 45c15682ffa1b0235e0708f2d4fbd535ca157e1b Mon Sep 17 00:00:00 2001 From: Michael Cawte Date: Wed, 7 Jun 2017 17:19:11 +1200 Subject: [PATCH 1015/1534] Fixed a minor typo in the docs. (#22260) --- doc/src/manual/methods.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/manual/methods.md b/doc/src/manual/methods.md index c8843e18b0635..65f5be740cd3d 100644 --- a/doc/src/manual/methods.md +++ b/doc/src/manual/methods.md @@ -189,7 +189,7 @@ Whoa there, Nelly. ``` This catch-all is less specific than any other possible method definition for a pair of parameter -values, so it is only be called on pairs of arguments to which no other method definition applies. +values, so it is only to be called on pairs of arguments to which no other method definition applies. Although it seems a simple concept, multiple dispatch on the types of values is perhaps the single most powerful and central feature of the Julia language. Core operations typically have dozens From 7ba4f0f3dc18033db1fdd85ae1e1bd6a6a463461 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Wed, 7 Jun 2017 15:54:49 +0200 Subject: [PATCH 1016/1534] allow passing a type in rand! --- base/random.jl | 16 ++++++++++------ test/random.jl | 18 ++++++++++++------ 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/base/random.jl b/base/random.jl index ac646b6010d62..74f91f7c4d76b 100644 --- a/base/random.jl +++ b/base/random.jl @@ -285,11 +285,13 @@ rand!(A::AbstractArray) = rand!(GLOBAL_RNG, A) rand(r::AbstractArray) = rand(GLOBAL_RNG, r) """ - rand!([rng=GLOBAL_RNG], A, [coll]) + rand!([rng=GLOBAL_RNG], A, [S=eltype(A)]) -Populate the array `A` with random values. If the collection `coll` is specified, -the values are picked randomly from `coll`. This is equivalent to `copy!(A, rand(rng, coll, size(A)))` -or `copy!(A, rand(rng, eltype(A), size(A)))` but without allocating a new array. +Populate the array `A` with random values. If `S` is specified +(`S` can be a type or a collection, cf. [`rand`](@ref) for details), +the values are picked randomly from `S`. +This is equivalent to `copy!(A, rand(rng, S, size(A)))` +but without allocating a new array. """ rand!(A::AbstractArray, r::AbstractArray) = rand!(GLOBAL_RNG, A, r) @@ -389,13 +391,15 @@ rand(r::AbstractRNG, T::Type, d1::Integer, dims::Integer...) = rand(r, T, tuple( # rand(r, ()) would match both this method and rand(r, dims::Dims) # moreover, a call like rand(r, NotImplementedType()) would be an infinite loop -function rand!(r::AbstractRNG, A::AbstractArray{T}) where T +function rand!(r::AbstractRNG, A::AbstractArray{T}, ::Type{X}=T) where {T,X} for i in eachindex(A) - @inbounds A[i] = rand(r, T) + @inbounds A[i] = rand(r, X) end A end +rand!(A::AbstractArray, ::Type{X}) where {X} = rand!(GLOBAL_RNG, A, X) + function rand!(r::AbstractRNG, A::AbstractArray, s::Union{Dict,Set,IntSet}) for i in eachindex(A) @inbounds A[i] = rand(r, s) diff --git a/test/random.jl b/test/random.jl index fcdc6867571fb..4c21e355bc45a 100644 --- a/test/random.jl +++ b/test/random.jl @@ -309,11 +309,13 @@ for rng in ([], [MersenneTwister(0)], [RandomDevice()]) ftypes = [Float16, Float32, Float64] cftypes = [Complex32, Complex64, Complex128, ftypes...] types = [Bool, Char, Base.BitInteger_types..., ftypes...] - collections = [(IntSet(rand(1:100, 20)), Int), - (Set(rand(Int, 20)), Int), - (Dict(zip(rand(Int,10), rand(Int, 10))), Pair{Int,Int}), - (1:100, Int), - (rand(Int, 100), Int)] + collections = [IntSet(rand(1:100, 20)) => Int, + Set(rand(Int, 20)) => Int, + Dict(zip(rand(Int,10), rand(Int, 10))) => Pair{Int,Int}, + 1:100 => Int, + rand(Int, 100) => Int, + Int => Int, + Float64 => Float64] b2 = big(2) u3 = UInt(3) for f in [rand, randn, randexp] @@ -342,7 +344,11 @@ for rng in ([], [MersenneTwister(0)], [RandomDevice()]) a3 = rand!(rng..., Array{T}(5), C) ::Vector{T} a4 = rand!(rng..., Array{T}(2, 3), C) ::Array{T, 2} for a in [a0, a1..., a2..., a3..., a4...] - @test a in C + if C isa Type + @test a isa C + else + @test a in C + end end end for C in [1:0, Dict(), Set(), IntSet(), Int[]] From 74b129346af75d8f8b2164b24a6cd0b2c72ef1e3 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Wed, 7 Jun 2017 11:54:24 -0400 Subject: [PATCH 1017/1534] Fix compilation on LLVM svn file_magic moved Ref https://github.com/llvm-mirror/llvm/commit/19ca2b0f9daed883c21730285d7f04424e5f5f88 --- src/debuginfo.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/debuginfo.cpp b/src/debuginfo.cpp index 11ac809029e56..46acb35a5369c 100644 --- a/src/debuginfo.cpp +++ b/src/debuginfo.cpp @@ -38,6 +38,12 @@ using namespace llvm; +#if JL_LLVM_VERSION >= 50000 +using llvm_file_magic = file_magic; +#else +using llvm_file_magic = sys::fs::file_magic; +#endif + #include "julia.h" #include "julia_internal.h" #include "codegen_internal.h" @@ -1009,7 +1015,7 @@ openDebugInfo(StringRef debuginfopath, const debug_link_info &info) auto error_splitobj = object::ObjectFile::createObjectFile( SplitFile.get().get()->getMemBufferRef(), - sys::fs::file_magic::unknown); + llvm_file_magic::unknown); if (!error_splitobj) { #if JL_LLVM_VERSION >= 30900 return error_splitobj.takeError(); @@ -1181,13 +1187,13 @@ bool jl_dylib_DI_for_fptr(size_t pointer, const llvm::object::ObjectFile **obj, std::unique_ptr membuf = MemoryBuffer::getMemBuffer( StringRef((const char *)fbase, msize), "", false); auto origerrorobj = llvm::object::ObjectFile::createObjectFile( - membuf->getMemBufferRef(), sys::fs::file_magic::unknown); + membuf->getMemBufferRef(), llvm_file_magic::unknown); #elif JL_LLVM_VERSION >= 30500 MemoryBuffer *membuf = MemoryBuffer::getMemBuffer( StringRef((const char *)fbase, msize), "", false); std::unique_ptr buf(membuf); auto origerrorobj = llvm::object::ObjectFile::createObjectFile( - buf, sys::fs::file_magic::unknown); + buf, llvm_file_magic::unknown); #else MemoryBuffer *membuf = MemoryBuffer::getMemBuffer( StringRef((const char *)fbase, msize), "", false); From 8dab956ea30793621b0842ba13223d61b3d0490e Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 7 Jun 2017 13:10:00 -0400 Subject: [PATCH 1018/1534] incremental serialize: restore recache order back to original the commit fix for #265 reshuffled this order, but that was wrong the correctness of jl_recache_other has since been fixed, permitting this to go back to the correct original order fix #22171 --- src/dump.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dump.c b/src/dump.c index c020c554b29e6..e8a42140db1ad 100644 --- a/src/dump.c +++ b/src/dump.c @@ -3280,10 +3280,10 @@ static jl_value_t *_jl_restore_incremental(ios_t *f) // at this point, the AST is fully reconstructed, but still completely disconnected // now all of the interconnects will be created jl_recache_types(); // make all of the types identities correct + jl_recache_other(&dependent_worlds); // make all of the other objects identities correct (needs to be after recache types) init_order = jl_finalize_deserializer(&s, tracee_list); // done with f and s (needs to be after recache types) - jl_insert_methods(&external_methods); // hook up methods of external generic functions (needs to be after recache types) - jl_recache_other(&dependent_worlds); // make all of the other objects identities correct (needs to be after insert methods) - jl_insert_backedges(&external_backedges); // restore external backedges (needs to be after recache other) + jl_insert_methods(&external_methods); // hook up methods of external generic functions (needs to be after recache other) + jl_insert_backedges(&external_backedges); // restore external backedges (needs to be after insert methods) free_linkedlist(external_methods.next); free_linkedlist(external_backedges.next); serializer_worklist = NULL; From 6836f75cc3cea932a31c3cdecf94334fc94ee2fd Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Fri, 26 May 2017 19:11:21 -0500 Subject: [PATCH 1019/1534] Standardize Pkg.build/Pkg.test flag order Flags given to subprocesses are now alphabetized. --- base/pkg/entry.jl | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/base/pkg/entry.jl b/base/pkg/entry.jl index 82bb1f5ab2fb9..d8fa73a8d04a2 100644 --- a/base/pkg/entry.jl +++ b/base/pkg/entry.jl @@ -604,14 +604,14 @@ function build(pkg::AbstractString, build_file::AbstractString, errfile::Abstrac serialize(f, err) end end - """ + """ cmd = ``` $(Base.julia_cmd()) -O0 + --color=$(Base.have_color ? "yes" : "no") --compilecache=$(Bool(Base.JLOptions().use_compilecache) ? "yes" : "no") --history-file=no - --color=$(Base.have_color ? "yes" : "no") --eval $code - ``` + ``` success(pipeline(cmd, stderr=STDERR)) end @@ -711,11 +711,15 @@ function test!(pkg::AbstractString, info("Testing $pkg") cd(dirname(test_path)) do try - color = Base.have_color? "--color=yes" : "--color=no" - codecov = coverage? ["--code-coverage=user"] : ["--code-coverage=none"] - compilecache = "--compilecache=" * (Bool(Base.JLOptions().use_compilecache) ? "yes" : "no") - julia_exe = Base.julia_cmd() - run(`$julia_exe --check-bounds=yes $codecov $color $compilecache $test_path`) + cmd = ``` + $(Base.julia_cmd()) + --code-coverage=$(coverage ? "user" : "none") + --color=$(Base.have_color ? "yes" : "no") + --compilecache=$(Bool(Base.JLOptions().use_compilecache) ? "yes" : "no") + --check-bounds=yes + $test_path + ``` + run(cmd) info("$pkg tests passed") catch err warnbanner(err, label="[ ERROR: $pkg ]") From fe2d49fb1e8304f5330812e54ade982bd5a38307 Mon Sep 17 00:00:00 2001 From: Matthieu Gomez Date: Wed, 7 Jun 2017 14:21:28 -0400 Subject: [PATCH 1020/1534] Use multi-line format in `@show` (#22253) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Use multi-line format in `@show` `@show` now uses a multi-line format (i.e. calls show(STDOUT, “text/plain”, …). Fix #15820 and this [Discourse issue](https://discourse.julialang.org/t/how-to-print-arrays-inside-func tions/4091). Also replaces pull request #22244 * enclose in do --- base/show.jl | 7 ++++--- test/show.jl | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/base/show.jl b/base/show.jl index cd58087312bbc..301fa3c9171a9 100644 --- a/base/show.jl +++ b/base/show.jl @@ -249,10 +249,11 @@ show_supertypes(typ::DataType) = show_supertypes(STDOUT, typ) macro show(exs...) blk = Expr(:block) for ex in exs - push!(blk.args, :(println($(sprint(show_unquoted,ex)*" = "), - repr(begin value=$(esc(ex)) end)))) + push!(blk.args, :(print($(sprint(show_unquoted,ex)*" = ")))) + push!(blk.args, :(show(STDOUT, "text/plain", begin value=$(esc(ex)) end))) + push!(blk.args, :(println())) end - if !isempty(exs); push!(blk.args, :value); end + isempty(exs) || push!(blk.args, :value) return blk end diff --git a/test/show.jl b/test/show.jl index 93018b809c20f..2c205c478a7a3 100644 --- a/test/show.jl +++ b/test/show.jl @@ -764,3 +764,18 @@ end @test static_shown(Symbol("")) == "Symbol(\"\")" @test static_shown(Symbol("a/b")) == "Symbol(\"a/b\")" @test static_shown(Symbol("a-b")) == "Symbol(\"a-b\")" + + +# Test @show +let fname = tempname() + try + open(fname, "w") do fout + redirect_stdout(fout) do + @show zeros(2, 2) + end + end + @test readstring(fname) == "zeros(2, 2) = 2×2 Array{Float64,2}:\n 0.0 0.0\n 0.0 0.0\n" + finally + rm(fname, force=true) + end +end \ No newline at end of file From 6f66019989f86df4eaf30a5cb8f66fd9c21d6139 Mon Sep 17 00:00:00 2001 From: Michael Cawte Date: Thu, 8 Jun 2017 07:58:44 +1200 Subject: [PATCH 1021/1534] Small change to documentation (#22265) I made a commit a few hours ago fixing a typo. It was pointed out that the meaning of the sentence was not right. This commit fixes that. --- doc/src/manual/methods.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/manual/methods.md b/doc/src/manual/methods.md index 65f5be740cd3d..21d782efbc9f9 100644 --- a/doc/src/manual/methods.md +++ b/doc/src/manual/methods.md @@ -189,7 +189,7 @@ Whoa there, Nelly. ``` This catch-all is less specific than any other possible method definition for a pair of parameter -values, so it is only to be called on pairs of arguments to which no other method definition applies. +values, so it will only be called on pairs of arguments to which no other method definition applies. Although it seems a simple concept, multiple dispatch on the types of values is perhaps the single most powerful and central feature of the Julia language. Core operations typically have dozens From c299dd0b3201db0d4acc6428649ea7cd160dcc8f Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Wed, 7 Jun 2017 22:12:14 +0200 Subject: [PATCH 1022/1534] unary minus for Hermitian (#22266) --- base/linalg/symmetric.jl | 3 ++- test/linalg/symmetric.jl | 10 ++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/base/linalg/symmetric.jl b/base/linalg/symmetric.jl index dab1eedd4c235..519c330ff3475 100644 --- a/base/linalg/symmetric.jl +++ b/base/linalg/symmetric.jl @@ -269,7 +269,8 @@ function triu(A::Symmetric, k::Integer=0) end end -(-)(A::Symmetric{Tv,S}) where {Tv,S<:AbstractMatrix} = Symmetric{Tv,S}(-A.data, A.uplo) +(-)(A::Symmetric{Tv,S}) where {Tv,S} = Symmetric{Tv,S}(-A.data, A.uplo) +(-)(A::Hermitian{Tv,S}) where {Tv,S} = Hermitian{Tv,S}(-A.data, A.uplo) ## Matvec A_mul_B!(y::StridedVector{T}, A::Symmetric{T,<:StridedMatrix}, x::StridedVector{T}) where {T<:BlasFloat} = diff --git a/test/linalg/symmetric.jl b/test/linalg/symmetric.jl index e6ce1449bd6fa..e72017ee5dba1 100644 --- a/test/linalg/symmetric.jl +++ b/test/linalg/symmetric.jl @@ -248,10 +248,12 @@ let A = [1.0+im 2.0; 2.0 0.0] @test_throws ArgumentError Hermitian(A) end -# Unary minus for Symmetric matrices -let A = Symmetric(randn(5,5)) - B = -A - @test A + B ≈ zeros(5,5) +# Unary minus for Symmetric/Hermitian matrices +let A = randn(5, 5) + for SH in (Symmetric(A), Hermitian(A)) + F = Matrix(SH) + @test (-SH)::typeof(SH) == -F + end end # 17780 From 13c18301b5d79ac463023c5f4eae0f862f774693 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Wed, 7 Jun 2017 15:22:01 -0500 Subject: [PATCH 1023/1534] Refactor `LibGit2.set_remote_url` (#22062) * Fix issue #21773 When using `LibGit2.set_remote_url` to specify a GitHub HTTP URL only the fetch URL would be modified to use HTTP and the push URL would always be set to SSH. * Allow setting the remote push/fetch URL separately Changes include: - Creating `set_remote_fetch_url`, `set_remote_push_url`, `remote_delete`, and `lookup_remote` - Updating `set_remote_url` to use LibGit2 calls - Deprecate `set_remote_url` which uses keyword and reorder arguments to match order of `GitRemote` constructor. - Update all existing calls to `set_remote_url` * Add NEWS entry --- NEWS.md | 4 ++ base/deprecated.jl | 14 +++++ base/libgit2/libgit2.jl | 43 ------------- base/libgit2/remote.jl | 136 +++++++++++++++++++++++++++++++++++++++- base/pkg/cache.jl | 2 +- base/pkg/dir.jl | 4 +- base/pkg/entry.jl | 2 +- base/pkg/write.jl | 2 +- test/libgit2.jl | 61 +++++++++++++++++- 9 files changed, 214 insertions(+), 54 deletions(-) diff --git a/NEWS.md b/NEWS.md index aba5151988789..0f62292db74c1 100644 --- a/NEWS.md +++ b/NEWS.md @@ -58,6 +58,10 @@ Library improvements * The output of `versioninfo()` is now controlled with keyword arguments ([#21974]). + * The function `LibGit2.set_remote_url` now always sets both the fetch and push URLs for a + git repo. Additionally, the argument order was changed to be consistent with the git + command line tool ([#22062]). + Compiler/Runtime improvements ----------------------------- diff --git a/base/deprecated.jl b/base/deprecated.jl index 062456c7146b4..555998ca6f546 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1403,6 +1403,20 @@ DEPRECATED: use @__MODULE__ instead end export current_module +# PR #22062 +function LibGit2.set_remote_url(repo::LibGit2.GitRepo, url::AbstractString; remote::AbstractString="origin") + Base.depwarn(string( + "`LibGit2.set_remote_url(repo, url; remote=remote)` is deprecated, use ", + "`LibGit2.set_remote_url(repo, remote, url)` instead."), :set_remote_url) + LibGit2.set_remote_url(repo, remote, url) +end +function LibGit2.set_remote_url(path::AbstractString, url::AbstractString; remote::AbstractString="origin") + Base.depwarn(string( + "`LibGit2.set_remote_url(path, url; remote=remote)` is deprecated, use ", + "`LibGit2.set_remote_url(path, remote, url)` instead."), :set_remote_url) + LibGit2.set_remote_url(path, remote, url) +end + # END 0.7 deprecations # BEGIN 1.0 deprecations diff --git a/base/libgit2/libgit2.jl b/base/libgit2/libgit2.jl index 164a895bfd706..554463406f68e 100644 --- a/base/libgit2/libgit2.jl +++ b/base/libgit2/libgit2.jl @@ -240,49 +240,6 @@ function is_ancestor_of(a::AbstractString, b::AbstractString, repo::GitRepo) merge_base(repo, a, b) == A end -""" - set_remote_url(repo::GitRepo, url::AbstractString; remote::AbstractString="origin") - -Set the `url` for `remote` for the git repository `repo`. -The default name of the remote is `"origin"`. - -# Examples - -```julia -repo_path = joinpath("test_directory", "Example") -repo = LibGit2.init(repo_path) -url1 = "https://github.com/JuliaLang/Example.jl" -LibGit2.set_remote_url(repo, url1, remote="upstream") -url2 = "https://github.com/JuliaLang/Example2.jl" -LibGit2.set_remote_url(repo_path, url2, remote="upstream2") -``` -""" -function set_remote_url(repo::GitRepo, url::AbstractString; remote::AbstractString="origin") - with(GitConfig, repo) do cfg - set!(cfg, "remote.$remote.url", url) - - m = match(GITHUB_REGEX,url) - if m !== nothing - push = "git@github.com:$(m.captures[1]).git" - if push != url - set!(cfg, "remote.$remote.pushurl", push) - end - end - end -end - -""" - set_remote_url(path::AbstractString, url::AbstractString; remote::AbstractString="origin") - -Set the `url` for `remote` for the git repository located at `path`. -The default name of the remote is `"origin"`. -""" -function set_remote_url(path::AbstractString, url::AbstractString; remote::AbstractString="origin") - with(GitRepo, path) do repo - set_remote_url(repo, url, remote=remote) - end -end - function make_payload(payload::Nullable{<:AbstractCredentials}) Ref{Nullable{AbstractCredentials}}(payload) end diff --git a/base/libgit2/remote.jl b/base/libgit2/remote.jl index d0d0d74ba8b25..cdc28ed26b4b9 100644 --- a/base/libgit2/remote.jl +++ b/base/libgit2/remote.jl @@ -63,6 +63,27 @@ function GitRemoteAnon(repo::GitRepo, url::AbstractString) return GitRemote(repo, rmt_ptr_ptr[]) end +""" + lookup_remote(repo::GitRepo, remote_name::AbstractString) -> Nullable{GitRemote} + +Determine if the `remote_name` specified exists within the `repo`. Returns a +[`Nullable`](@ref), which will be null if the requested remote does not exist. If the remote +does exist, the `Nullable` contains a `GitRemote` to the remote name. +""" +function lookup_remote(repo::GitRepo, remote_name::AbstractString) + rmt_ptr_ptr = Ref{Ptr{Void}}(C_NULL) + err = ccall((:git_remote_lookup, :libgit2), Cint, + (Ptr{Ptr{Void}}, Ptr{Void}, Cstring), + rmt_ptr_ptr, repo.ptr, remote_name) + if err == Int(Error.GIT_OK) + return Nullable{GitRemote}(GitRemote(repo, rmt_ptr_ptr[])) + elseif err == Int(Error.ENOTFOUND) + return Nullable{GitRemote}() + else + throw(Error.GitError(err)) + end +end + function get(::Type{GitRemote}, repo::GitRepo, rmt_name::AbstractString) rmt_ptr_ptr = Ref{Ptr{Void}}(C_NULL) @check ccall((:git_remote_lookup, :libgit2), Cint, @@ -74,18 +95,18 @@ end """ url(rmt::GitRemote) -Get the URL of a remote git repository. +Get the fetch URL of a remote git repository. # Example ```julia-repl julia> repo_url = "https://github.com/JuliaLang/Example.jl"; -julia> repo = LibGit2.clone(cache_repo, "test_directory"); +julia> repo = LibGit2.init(mktempdir()); julia> remote = LibGit2.GitRemote(repo, "origin", repo_url); -julia> url(remote) +julia> LibGit2.url(remote) "https://github.com/JuliaLang/Example.jl" ``` """ @@ -95,6 +116,30 @@ function url(rmt::GitRemote) return unsafe_string(url_ptr) end +""" + push_url(rmt::GitRemote) + +Get the push URL of a remote git repository. + +# Example + +```julia-repl +julia> repo_url = "https://github.com/JuliaLang/Example.jl"; + +julia> repo = LibGit2.init(mktempdir()); + +julia> LibGit2.set_remote_push_url(repo, "origin", repo_url); + +julia> LibGit2.push_url(LibGit2.get(LibGit2.GitRemote, repo, "origin")) +"https://github.com/JuliaLang/Example.jl" +``` +""" +function push_url(rmt::GitRemote) + url_ptr = ccall((:git_remote_pushurl, :libgit2), Cstring, (Ptr{Void},), rmt.ptr) + url_ptr == C_NULL && return "" + return unsafe_string(url_ptr) +end + """ name(rmt::GitRemote) @@ -240,4 +285,89 @@ function push(rmt::GitRemote, refspecs::Vector{<:AbstractString}; rmt.ptr, isempty(refspecs) ? C_NULL : refspecs, Ref(options)) end +""" + remote_delete(repo::GitRepo, remote_name::AbstractString) -> Void + +Delete the `remote_name` from the git `repo`. +""" +function remote_delete(repo::GitRepo, remote_name::AbstractString) + @check ccall((:git_remote_delete, :libgit2), Cint, + (Ptr{Void}, Cstring), + repo.ptr, remote_name) +end + Base.show(io::IO, rmt::GitRemote) = print(io, "GitRemote:\nRemote name: ", name(rmt), " url: ", url(rmt)) + + +""" + set_remote_fetch_url(repo::GitRepo, remote_name, url) + set_remote_fetch_url(path::String, remote_name, url) + +Set the fetch `url` for the specified `remote_name` for the GitRepo or the git repository +located at `path`. Typically git repos use "origin" as the remote name. +""" +function set_remote_fetch_url end + +function set_remote_fetch_url(repo::GitRepo, remote_name::AbstractString, url::AbstractString) + @check ccall((:git_remote_set_url, :libgit2), Cint, + (Ptr{Void}, Cstring, Cstring), + repo.ptr, remote_name, url) +end + +function set_remote_fetch_url(path::AbstractString, remote_name::AbstractString, url::AbstractString) + with(GitRepo, path) do repo + set_remote_fetch_url(repo, remote_name, url) + end +end + + +""" + set_remote_push_url(repo::GitRepo, remote_name, url) + set_remote_push_url(path::String, remote_name, url) + +Set the push `url` for the specified `remote_name` for the GitRepo or the git repository +located at `path`. Typically git repos use "origin" as the remote name. +""" +function set_remote_push_url end + +function set_remote_push_url(repo::GitRepo, remote_name::AbstractString, url::AbstractString) + @check ccall((:git_remote_set_pushurl, :libgit2), Cint, + (Ptr{Void}, Cstring, Cstring), + repo.ptr, remote_name, url) +end + +function set_remote_push_url(path::AbstractString, remote_name::AbstractString, url::AbstractString) + with(GitRepo, path) do repo + set_remote_push_url(repo, remote_name, url) + end +end + + +""" + set_remote_url(repo::GitRepo, remote_name, url) + set_remote_url(repo::String, remote_name, url) + +Set both the fetch and push `url` for `remote_name` for the GitRepo or the git repository +located at `path`. Typically git repos use "origin" as the remote name. + +# Examples + +```julia +repo_path = joinpath(tempdir(), "Example") +repo = LibGit2.init(repo_path) +LibGit2.set_remote_url(repo, "upstream", "https://github.com/JuliaLang/Example.jl") +LibGit2.set_remote_url(repo_path, "upstream2", "https://github.com/JuliaLang/Example2.jl") +``` +""" +function set_remote_url end + +function set_remote_url(repo::GitRepo, remote_name::AbstractString, url::AbstractString) + set_remote_fetch_url(repo, remote_name, url) + set_remote_push_url(repo, remote_name, url) +end + +function set_remote_url(path::AbstractString, remote_name::AbstractString, url::AbstractString) + with(GitRepo, path) do repo + set_remote_url(repo, remote_name, url) + end +end diff --git a/base/pkg/cache.jl b/base/pkg/cache.jl index b4535579cd636..1a1a766f9cddc 100644 --- a/base/pkg/cache.jl +++ b/base/pkg/cache.jl @@ -57,7 +57,7 @@ function prefetch(pkg::AbstractString, url::AbstractString, sha1s::Vector) end end try - LibGit2.set_remote_url(repo, normalized_url) + LibGit2.set_remote_url(repo, "origin", normalized_url) in_cache = BitArray(map(sha1->LibGit2.iscommit(sha1, repo), sha1s)) if !all(in_cache) info("Updating cache of $pkg...") diff --git a/base/pkg/dir.jl b/base/pkg/dir.jl index 76b8b57d21bc4..4bcd8fcef7836 100644 --- a/base/pkg/dir.jl +++ b/base/pkg/dir.jl @@ -43,7 +43,7 @@ function init(meta::AbstractString=DEFAULT_META, branch::AbstractString=META_BRA metadata_dir = joinpath(dir, "METADATA") if isdir(metadata_dir) info("Package directory $dir is already initialized.") - LibGit2.set_remote_url(metadata_dir, meta) + LibGit2.set_remote_url(metadata_dir, "origin", meta) return end local temp_dir = "" @@ -53,7 +53,7 @@ function init(meta::AbstractString=DEFAULT_META, branch::AbstractString=META_BRA Base.cd(temp_dir) do info("Cloning METADATA from $meta") with(LibGit2.clone(meta, "METADATA", branch = branch)) do metadata_repo - LibGit2.set_remote_url(metadata_repo, meta) + LibGit2.set_remote_url(metadata_repo, "origin", meta) end touch("REQUIRE") touch("META_BRANCH") diff --git a/base/pkg/entry.jl b/base/pkg/entry.jl index 82bb1f5ab2fb9..91b03930e959d 100644 --- a/base/pkg/entry.jl +++ b/base/pkg/entry.jl @@ -193,7 +193,7 @@ function clone(url::AbstractString, pkg::AbstractString) ispath(pkg) && throw(PkgError("$pkg already exists")) try LibGit2.with(LibGit2.clone(url, pkg)) do repo - LibGit2.set_remote_url(repo, url) + LibGit2.set_remote_url(repo, "origin", url) end catch err isdir(pkg) && Base.rm(pkg, recursive=true) diff --git a/base/pkg/write.jl b/base/pkg/write.jl index 635ef6a677798..ffc2c6f84fb50 100644 --- a/base/pkg/write.jl +++ b/base/pkg/write.jl @@ -27,7 +27,7 @@ function fetch(repo::GitRepo, pkg::AbstractString, sha1::AbstractString) end function checkout(repo::GitRepo, pkg::AbstractString, sha1::AbstractString) - LibGit2.set_remote_url(repo, Cache.normalize_url(Read.url(pkg))) + LibGit2.set_remote_url(repo, "origin", Cache.normalize_url(Read.url(pkg))) LibGit2.checkout!(repo, sha1) end diff --git a/test/libgit2.jl b/test/libgit2.jl index b9ff2acb2c6b2..4451551789a2f 100644 --- a/test/libgit2.jl +++ b/test/libgit2.jl @@ -302,16 +302,21 @@ mktempdir() do dir remote = LibGit2.get(LibGit2.GitRemote, repo, branch) @test LibGit2.url(remote) == repo_url + @test LibGit2.push_url(remote) == "" @test LibGit2.name(remote) == "upstream" @test isa(remote, LibGit2.GitRemote) @test sprint(show, remote) == "GitRemote:\nRemote name: upstream url: $repo_url" @test LibGit2.isattached(repo) - LibGit2.set_remote_url(repo, "", remote="upstream") + LibGit2.set_remote_url(repo, "upstream", "unknown") remote = LibGit2.get(LibGit2.GitRemote, repo, branch) - @test sprint(show, remote) == "GitRemote:\nRemote name: upstream url: " + @test LibGit2.url(remote) == "unknown" + @test LibGit2.push_url(remote) == "unknown" + @test sprint(show, remote) == "GitRemote:\nRemote name: upstream url: unknown" close(remote) - LibGit2.set_remote_url(cache_repo, repo_url, remote="upstream") + LibGit2.set_remote_url(cache_repo, "upstream", repo_url) remote = LibGit2.get(LibGit2.GitRemote, repo, branch) + @test LibGit2.url(remote) == repo_url + @test LibGit2.push_url(remote) == repo_url @test sprint(show, remote) == "GitRemote:\nRemote name: upstream url: $repo_url" LibGit2.add_fetch!(repo, remote, "upstream") @test LibGit2.fetch_refspecs(remote) == String["+refs/heads/*:refs/remotes/upstream/*"] @@ -328,6 +333,7 @@ mktempdir() do dir remote = LibGit2.GitRemoteAnon(repo, repo_url) @test LibGit2.url(remote) == repo_url + @test LibGit2.push_url(remote) == "" @test LibGit2.name(remote) == "" @test isa(remote, LibGit2.GitRemote) close(remote) @@ -1123,6 +1129,55 @@ mktempdir() do dir end end + @testset "Modify remote" begin + path = test_repo + repo = LibGit2.GitRepo(path) + try + remote_name = "test" + url = "https://test.com/repo" + + @test isnull(LibGit2.lookup_remote(repo, remote_name)) + + for r in (repo, path) + # Set just the fetch URL + LibGit2.set_remote_fetch_url(r, remote_name, url) + remote = get(LibGit2.lookup_remote(repo, remote_name)) + @test LibGit2.name(remote) == remote_name + @test LibGit2.url(remote) == url + @test LibGit2.push_url(remote) == "" + + LibGit2.remote_delete(repo, remote_name) + @test isnull(LibGit2.lookup_remote(repo, remote_name)) + + # Set just the push URL + LibGit2.set_remote_push_url(r, remote_name, url) + remote = get(LibGit2.lookup_remote(repo, remote_name)) + @test LibGit2.name(remote) == remote_name + @test LibGit2.url(remote) == "" + @test LibGit2.push_url(remote) == url + + LibGit2.remote_delete(repo, remote_name) + @test isnull(LibGit2.lookup_remote(repo, remote_name)) + + # Set the fetch and push URL + LibGit2.set_remote_url(r, remote_name, url) + remote = get(LibGit2.lookup_remote(repo, remote_name)) + @test LibGit2.name(remote) == remote_name + @test LibGit2.url(remote) == url + @test LibGit2.push_url(remote) == url + + LibGit2.remote_delete(repo, remote_name) + @test isnull(LibGit2.lookup_remote(repo, remote_name)) + end + + # Invalid remote name + @test_throws LibGit2.GitError LibGit2.set_remote_url(repo, "", url) + @test_throws LibGit2.GitError LibGit2.set_remote_url(repo, remote_name, "") + finally + close(repo) + end + end + @testset "rebase" begin repo = LibGit2.GitRepo(test_repo) try From 72c9ea35409729ec6ec9fbff2457d405a37ae4d4 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 7 Jun 2017 16:03:43 -0400 Subject: [PATCH 1024/1534] ensure inference of apply (precise_container_type) will not be adversely affected by very-linear-mode --- base/inference.jl | 79 +++++++++++++++++++++++++++-------------------- test/inference.jl | 13 ++++++++ 2 files changed, 58 insertions(+), 34 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 5ef16364df4b5..118238a49a20a 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -122,7 +122,7 @@ mutable struct InferenceState bestguess #::Type # current active instruction pointers ip::IntSet - pc´´::Int + pc´´::LineNum nstmts::Int # current exception handler info cur_hand #::Tuple{LineNum, Tuple{LineNum, ...}} @@ -130,7 +130,7 @@ mutable struct InferenceState n_handlers::Int # ssavalue sparsity and restart info ssavalue_uses::Vector{IntSet} - ssavalue_init::Vector{Any} + ssavalue_defs::Vector{LineNum} backedges::Vector{Tuple{InferenceState, LineNum}} # call-graph backedges connecting from callee to caller callers_in_cycle::Vector{InferenceState} @@ -167,7 +167,8 @@ mutable struct InferenceState sp = linfo.sparam_vals end - src.ssavaluetypes = Any[ NF for i = 1:(src.ssavaluetypes::Int) ] + nssavalues = src.ssavaluetypes::Int + src.ssavaluetypes = Any[ NF for i = 1:nssavalues ] n = length(code) s_edges = Any[ () for i = 1:n ] @@ -235,8 +236,8 @@ mutable struct InferenceState @assert la == 0 # wrong number of arguments end - ssavalue_uses = find_ssavalue_uses(code) - ssavalue_init = copy(src.ssavaluetypes::Vector{Any}) + ssavalue_uses = find_ssavalue_uses(code, nssavalues) + ssavalue_defs = find_ssavalue_defs(code, nssavalues) # exception handlers cur_hand = () @@ -266,7 +267,7 @@ mutable struct InferenceState nargs, s_types, s_edges, Union{}, W, 1, n, cur_hand, handler_at, n_handlers, - ssavalue_uses, ssavalue_init, + ssavalue_uses, ssavalue_defs, Vector{Tuple{InferenceState,LineNum}}(), # backedges Vector{InferenceState}(), # callers_in_cycle #=parent=#nothing, @@ -1489,6 +1490,12 @@ function precise_container_type(arg::ANY, typ::ANY, vtypes::VarTable, sv::Infere end end + while isa(arg, SSAValue) + def = sv.ssavalue_defs[arg.id + 1] + stmt = sv.src.code[def]::Expr + arg = stmt.args[2] + end + tti0 = widenconst(typ) tti = unwrap_unionall(tti0) if isa(arg, Expr) && arg.head === :call && (abstract_evals_to_constant(arg.args[1], svec, vtypes, sv) || @@ -2334,49 +2341,53 @@ end #### helper functions for typeinf initialization and looping #### -function label_counter(body) +function label_counter(body::Vector{Any}) l = -1 for b in body - if isa(b,LabelNode) && (b::LabelNode).label > l - l = (b::LabelNode).label + if isa(b, LabelNode) && b.label > l + l = b.label end end return l end genlabel(sv) = LabelNode(sv.label_counter += 1) -function find_ssavalue_uses(body) - uses = IntSet[] - for line = 1:length(body) - find_ssavalue_uses(body[line], uses, line) +function find_ssavalue_uses(body::Vector{Any}, nvals::Int) + uses = IntSet[ IntSet() for i = 1:nvals ] + for line in 1:length(body) + e = body[line] + isa(e, Expr) && find_ssavalue_uses(e, uses, line) end return uses end -function find_ssavalue_uses(e::ANY, uses, line) - if isa(e,SSAValue) - id = (e::SSAValue).id + 1 - while length(uses) < id - push!(uses, IntSet()) + +function find_ssavalue_uses(e::Expr, uses::Vector{IntSet}, line::Int) + head = e.head + is_meta_expr_head(head) && return + skiparg = (head === :(=)) + for a in e.args + if skiparg + skiparg = false + elseif isa(a, SSAValue) + push!(uses[a.id + 1], line) + elseif isa(a, Expr) + find_ssavalue_uses(a, uses, line) end - push!(uses[id], line) - elseif isa(e,Expr) - b = e::Expr - head = b.head - is_meta_expr_head(head) && return - if head === :(=) - if isa(b.args[1],SSAValue) - id = (b.args[1]::SSAValue).id + 1 - while length(uses) < id - push!(uses, IntSet()) - end + end +end + +function find_ssavalue_defs(body::Vector{Any}, nvals::Int) + defs = zeros(Int, nvals) + for line in 1:length(body) + e = body[line] + if isa(e, Expr) && e.head === :(=) + lhs = e.args[1] + if isa(lhs, SSAValue) + defs[lhs.id + 1] = line end - find_ssavalue_uses(b.args[2], uses, line) - return - end - for a in b.args - find_ssavalue_uses(a, uses, line) end end + return defs end function newvar!(sv::InferenceState, typ::ANY) diff --git a/test/inference.jl b/test/inference.jl index 61d283c73368c..8bcd6bf4d4aae 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -843,3 +843,16 @@ f21771(::Val{U}) where {U} = Tuple{g21771(U)} # ensure that we don't try to resolve cycles using uncached edges f21653() = f21653() @test code_typed(f21653, Tuple{}, optimize=false)[1] isa Pair{CodeInfo, typeof(Union{})} + +# ensure _apply can "see-through" SSAValue to infer precise container types +let f, m + f() = 0 + m = first(methods(f)) + m.source = Base.uncompressed_ast(m)::CodeInfo + m.source.ssavaluetypes = 1 + m.source.code = Any[ + Expr(:(=), SSAValue(0), Expr(:call, GlobalRef(Core, :svec), 1, 2, 3)), + Expr(:return, Expr(:call, Core._apply, :+, SSAValue(0))) + ] + @test @inferred(f()) == 6 +end From d0f03947befef7e5a454f0781080ee2ff1df96cb Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 7 Jun 2017 16:04:13 -0400 Subject: [PATCH 1025/1534] prevent errors in running type-inference from breaking the program runtime --- src/gf.c | 7 ++++--- src/julia_internal.h | 2 +- src/rtutils.c | 21 +++++++++++---------- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/gf.c b/src/gf.c index 3be37fce6fc59..bea84f33f0f2e 100644 --- a/src/gf.c +++ b/src/gf.c @@ -265,9 +265,10 @@ jl_code_info_t *jl_type_infer(jl_method_instance_t **pli, size_t world, int forc assert((jl_is_method(li->def.method) || li->inInference == 0) && "inference failed on a toplevel expr"); jl_code_info_t *src = NULL; - if (jl_is_svec(linfo_src_rettype) && jl_svec_len(linfo_src_rettype) == 3 && - jl_is_method_instance(jl_svecref(linfo_src_rettype, 0)) && - jl_is_code_info(jl_svecref(linfo_src_rettype, 1))) { + if (linfo_src_rettype && + jl_is_svec(linfo_src_rettype) && jl_svec_len(linfo_src_rettype) == 3 && + jl_is_method_instance(jl_svecref(linfo_src_rettype, 0)) && + jl_is_code_info(jl_svecref(linfo_src_rettype, 1))) { *pli = (jl_method_instance_t*)jl_svecref(linfo_src_rettype, 0); src = (jl_code_info_t*)jl_svecref(linfo_src_rettype, 1); } diff --git a/src/julia_internal.h b/src/julia_internal.h index 9337c784fcff6..d767cd3e7e127 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -662,7 +662,7 @@ size_t rec_backtrace_ctx(uintptr_t *data, size_t maxsize, bt_context_t *ctx); size_t rec_backtrace_ctx_dwarf(uintptr_t *data, size_t maxsize, bt_context_t *ctx); #endif JL_DLLEXPORT jl_value_t *jl_get_backtrace(void); -JL_DLLEXPORT jl_value_t *jl_apply_with_saved_exception_state(jl_value_t **args, uint32_t nargs, int catch_exceptions); +JL_DLLEXPORT jl_value_t *jl_apply_with_saved_exception_state(jl_value_t **args, uint32_t nargs, int drop_exceptions); void jl_critical_error(int sig, bt_context_t *context, uintptr_t *bt_data, size_t *bt_size); JL_DLLEXPORT void jl_raise_debugger(void); int jl_getFunctionInfo(jl_frame_t **frames, uintptr_t pointer, int skipC, int noInline); diff --git a/src/rtutils.c b/src/rtutils.c index 611a2df890664..f6a1e4cb68083 100644 --- a/src/rtutils.c +++ b/src/rtutils.c @@ -236,7 +236,7 @@ JL_DLLEXPORT void jl_pop_handler(int n) jl_eh_restore_state(eh); } -JL_DLLEXPORT jl_value_t *jl_apply_with_saved_exception_state(jl_value_t **args, uint32_t nargs, int catch_exceptions) +JL_DLLEXPORT jl_value_t *jl_apply_with_saved_exception_state(jl_value_t **args, uint32_t nargs, int drop_exceptions) { jl_ptls_t ptls = jl_get_ptls_states(); jl_value_t *exc = ptls->exception_in_transit; @@ -245,17 +245,18 @@ JL_DLLEXPORT jl_value_t *jl_apply_with_saved_exception_state(jl_value_t **args, if (ptls->bt_size > 0) bt = (jl_array_t*)jl_get_backtrace(); jl_value_t *v; - if (catch_exceptions) { - JL_TRY { - v = jl_apply(args, nargs); - } - JL_CATCH { - v = NULL; - } - } - else { + JL_TRY { v = jl_apply(args, nargs); } + JL_CATCH { + if (!drop_exceptions) { + jl_printf(JL_STDERR, "Internal error: encountered unexpected error in runtime:\n"); + jl_static_show(JL_STDERR, ptls->exception_in_transit); + jl_printf(JL_STDERR, "\n"); + jlbacktrace(); // written to STDERR_FILENO + } + v = NULL; + } ptls->exception_in_transit = exc; if (bt != NULL) { ptls->bt_size = jl_array_len(bt); From 4e6ccf683084ed282c9837cf39ba02ed2910608e Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Wed, 7 Jun 2017 22:33:20 +0200 Subject: [PATCH 1026/1534] add constructors for Symmetric(::Hermitian) and Hermitian(::Symmetric) (#22264) --- base/linalg/symmetric.jl | 33 +++++++++++++++++++-------------- test/linalg/symmetric.jl | 7 +++++++ 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/base/linalg/symmetric.jl b/base/linalg/symmetric.jl index 519c330ff3475..a3c2aa39c435e 100644 --- a/base/linalg/symmetric.jl +++ b/base/linalg/symmetric.jl @@ -41,14 +41,6 @@ julia> Slower = Symmetric(A, :L) Note that `Supper` will not be equal to `Slower` unless `A` is itself symmetric (e.g. if `A == A.'`). """ Symmetric(A::AbstractMatrix, uplo::Symbol=:U) = (checksquare(A); Symmetric{eltype(A),typeof(A)}(A, char_uplo(uplo))) -Symmetric(A::Symmetric) = A -function Symmetric(A::Symmetric, uplo::Symbol) - if A.uplo == char_uplo(uplo) - return A - else - throw(ArgumentError("Cannot construct Symmetric; uplo doesn't match")) - end -end struct Hermitian{T,S<:AbstractMatrix} <: AbstractMatrix{T} data::S @@ -91,12 +83,25 @@ function Hermitian(A::AbstractMatrix, uplo::Symbol=:U) end Hermitian{eltype(A),typeof(A)}(A, char_uplo(uplo)) end -Hermitian(A::Hermitian) = A -function Hermitian(A::Hermitian, uplo::Symbol) - if A.uplo == char_uplo(uplo) - return A - else - throw(ArgumentError("Cannot construct Hermitian; uplo doesn't match")) + +for (S, H) in ((:Symmetric, :Hermitian), (:Hermitian, :Symmetric)) + @eval begin + $S(A::$S) = A + function $S(A::$S, uplo::Symbol) + if A.uplo == char_uplo(uplo) + return A + else + throw(ArgumentError("Cannot construct $($S); uplo doesn't match")) + end + end + $S(A::$H) = $S(A.data, Symbol(A.uplo)) + function $S(A::$H, uplo::Symbol) + if A.uplo == char_uplo(uplo) + return $S(A.data, Symbol(A.uplo)) + else + throw(ArgumentError("Cannot construct $($S); uplo doesn't match")) + end + end end end diff --git a/test/linalg/symmetric.jl b/test/linalg/symmetric.jl index e72017ee5dba1..17e457d8c1082 100644 --- a/test/linalg/symmetric.jl +++ b/test/linalg/symmetric.jl @@ -53,6 +53,13 @@ let n=10 @test Hermitian(Hermitian(asym, :U), :U) === Hermitian(asym, :U) @test_throws ArgumentError Symmetric(Symmetric(asym, :U), :L) @test_throws ArgumentError Hermitian(Hermitian(asym, :U), :L) + # mixed cases with Hermitian/Symmetric + @test Symmetric(Hermitian(asym, :U)) === Symmetric(asym, :U) + @test Hermitian(Symmetric(asym, :U)) === Hermitian(asym, :U) + @test Symmetric(Hermitian(asym, :U), :U) === Symmetric(asym, :U) + @test Hermitian(Symmetric(asym, :U), :U) === Hermitian(asym, :U) + @test_throws ArgumentError Symmetric(Hermitian(asym, :U), :L) + @test_throws ArgumentError Hermitian(Symmetric(asym, :U), :L) # similar @test isa(similar(Symmetric(asym)), Symmetric{eltya}) From dfd7be03753d2b4037a22b496c15874ed702c210 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 7 Jun 2017 17:08:18 -0400 Subject: [PATCH 1027/1534] windows readme: winbind is needed for TLS --- README.windows.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.windows.md b/README.windows.md index 15278e2802f98..ef78b48890f6b 100644 --- a/README.windows.md +++ b/README.windows.md @@ -275,7 +275,7 @@ export BITS=64 zypper addrepo http://download.opensuse.org/repositories/windows:mingw:win$BITS/openSUSE_13.2/windows:mingw:win$BITS.repo zypper --gpg-auto-import-keys refresh zypper -n install --no-recommends git make cmake tar wine which curl \ - python python-xml patch gcc-c++ m4 p7zip.i586 libxml2-tools + python python-xml patch gcc-c++ m4 p7zip.i586 libxml2-tools winbind zypper -n install mingw$BITS-cross-gcc-c++ mingw$BITS-cross-gcc-fortran \ mingw$BITS-libstdc++6 mingw$BITS-libgfortran3 mingw$BITS-libssp0 # opensuse packages the mingw runtime dlls under sys-root/mingw/bin, not /usr/lib64/gcc @@ -310,9 +310,7 @@ need wine (>=1.7.5), a system compiler, and some downloaders. **On Ubuntu** (on other linux systems, the dependency names are likely to be similar): ```sh -apt-add-repository ppa:ubuntu-wine/ppa -apt-get update -apt-get install wine1.7 subversion cvs gcc wget p7zip-full +apt-get install wine subversion cvs gcc wget p7zip-full winbind ``` **On Mac**: Install XCode, XCode command line tools, X11 (now [XQuartz]( From 1e9fb818a6ace68b91d9c5aafa7b9be9fa4a01b9 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Wed, 7 Jun 2017 23:19:40 +0200 Subject: [PATCH 1028/1534] fix alignment in complex numbers with exponents (#22223) * fix alignment in complex numbers with exponents * indent * indent v2 --- base/show.jl | 2 +- test/complex.jl | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/base/show.jl b/base/show.jl index 301fa3c9171a9..b7b1a77032257 100644 --- a/base/show.jl +++ b/base/show.jl @@ -1363,7 +1363,7 @@ function alignment(io::IO, x::Real) end "`alignment(1 + 10im)` yields (3,5) for `1 +` and `_10im` (plus sign on left, space on right)" function alignment(io::IO, x::Complex) - m = match(r"^(.*[\+\-])(.*)$", sprint(0, show, x, env=io)) + m = match(r"^(.*[^e][\+\-])(.*)$", sprint(0, show, x, env=io)) m === nothing ? (length(sprint(0, show, x, env=io)), 0) : (length(m.captures[1]), length(m.captures[2])) end diff --git a/test/complex.jl b/test/complex.jl index 161222835a686..40171cd00a602 100644 --- a/test/complex.jl +++ b/test/complex.jl @@ -963,3 +963,14 @@ end x = @inferred expm1(0.1f0im) @test x isa Complex64 end + +@testset "array printing with exponent format" begin + a = [1.0 + 1e-10im, 2.0e-15 - 2.0e-5im, 1.0e-15 + 2im, 1.0 + 2e-15im] + @test sprint((io, x) -> show(io, MIME("text/plain"), x), a) == + join([ + "4-element Array{Complex{Float64},1}:", + " 1.0+1.0e-10im", + " 2.0e-15-2.0e-5im ", + " 1.0e-15+2.0im ", + " 1.0+2.0e-15im"], "\n") +end From ef030bd32a06b8c92c1bfe4079ec5f32887cc34e Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 7 Jun 2017 19:12:25 -0400 Subject: [PATCH 1029/1534] handle scope correctly for @isdefined this allows testing whether a variable is defined, and may be especially useful for emitting from a macro (which may want to conditionally initialize a variable) --- NEWS.md | 3 ++ base/inference.jl | 38 +++++++++++++++++-- base/reflection.jl | 4 +- src/ast.c | 2 + src/ccall.cpp | 2 +- src/codegen.cpp | 88 ++++++++++++++++++++++++++++++++++++++++---- src/dump.c | 2 +- src/interpreter.c | 35 ++++++++++++------ src/jitlayers.cpp | 2 +- src/jitlayers.h | 2 +- src/julia-syntax.scm | 19 ++++++++++ src/julia_internal.h | 1 + test/core.jl | 54 +++++++++++++++++++++++++++ 13 files changed, 223 insertions(+), 29 deletions(-) diff --git a/NEWS.md b/NEWS.md index 0f62292db74c1..08dc34e3e8d72 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,6 +4,9 @@ Julia v0.7.0 Release Notes New language features --------------------- + * Local variables can be tested for being defined + using the new `@isdefined variable` macro ([#TBD]). + Language changes ---------------- diff --git a/base/inference.jl b/base/inference.jl index 5ef16364df4b5..73fc121884c44 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -542,7 +542,7 @@ add_tfunc(===, 2, 2, end return Bool end) -add_tfunc(isdefined, 1, IInf, (args...)->Bool) +add_tfunc(isdefined, 1, 2, (args...)->Bool) add_tfunc(Core.sizeof, 1, 1, x->Int) add_tfunc(nfields, 1, 1, function (x::ANY) @@ -2064,6 +2064,25 @@ function abstract_eval(e::ANY, vtypes::VarTable, sv::InferenceState) return abstract_eval_constant(e.args[1]) elseif e.head === :invoke error("type inference data-flow error: tried to double infer a function") + elseif e.head === :isdefined + sym = e.args[1] + t = Bool + if isa(sym, Slot) + vtyp = vtypes[slot_id(sym)] + if vtyp.typ === Bottom + t = Const(false) # never assigned previously + elseif !vtyp.undef + t = Const(true) # definitely assigned previously + end + elseif isa(sym, Symbol) + if isdefined(sv.mod, sym.name) + t = Const(true) + end + elseif isa(sym, GlobalRef) + if isdefined(sym.mod, sym.name) + t = Const(true) + end + end else t = Any end @@ -4342,6 +4361,10 @@ const corenumtype = Union{Int32, Int64, Float32, Float64} # return inlined replacement for `e`, inserting new needed statements # at index `ins` in `stmts`. function inlining_pass(e::Expr, sv::InferenceState, stmts, ins) + if e.head === :isdefined + isa(e.typ, Const) && return e.typ.val + return e + end if e.head === :method # avoid running the inlining pass on function definitions return e @@ -4654,15 +4677,22 @@ function replace_vars!(src::CodeInfo, r::ObjectIdDict) end function _replace_vars!(e::ANY, r::ObjectIdDict) - if isa(e,SSAValue) || isa(e,Slot) + if isa(e, SSAValue) || isa(e, Slot) v = normvar(e) if haskey(r, v) return r[v] end end - if isa(e,Expr) + if isa(e, Expr) for i = 1:length(e.args) - e.args[i] = _replace_vars!(e.args[i], r) + a = e.args[i] + if e.head === :isdefined + if e.args[i] !== _replace_vars!(a, r) + return true + end + else + e.args[i] = _replace_vars!(a, r) + end end end return e diff --git a/base/reflection.jl b/base/reflection.jl index 63eb16d12ecf0..a13fc7e9bdb4a 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -171,10 +171,10 @@ isconst(m::Module, s::Symbol) = """ @isdefined s -> Bool -Tests whether symbol `s` is defined in the current scope. +Tests whether variable `s` is defined in the current scope. """ macro isdefined(s::Symbol) - return :(isdefined($__module__, $(QuoteNode(s)))) + return Expr(:isdefined, esc(s)) end # return an integer such that object_id(x)==object_id(y) if x===y diff --git a/src/ast.c b/src/ast.c index 0b286de277d5b..aa1e5f3eee975 100644 --- a/src/ast.c +++ b/src/ast.c @@ -56,6 +56,7 @@ jl_sym_t *inert_sym; jl_sym_t *vararg_sym; jl_sym_t *unused_sym; jl_sym_t *static_parameter_sym; jl_sym_t *polly_sym; jl_sym_t *inline_sym; jl_sym_t *propagate_inbounds_sym; +jl_sym_t *isdefined_sym; static uint8_t flisp_system_image[] = { #include @@ -431,6 +432,7 @@ void jl_init_frontend(void) polly_sym = jl_symbol("polly"); inline_sym = jl_symbol("inline"); propagate_inbounds_sym = jl_symbol("propagate_inbounds"); + isdefined_sym = jl_symbol("isdefined"); } JL_DLLEXPORT void jl_lisp_prompt(void) diff --git a/src/ccall.cpp b/src/ccall.cpp index 32058d0a47731..c50f0bb20e8e8 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -95,7 +95,7 @@ static bool runtime_sym_gvs(const char *f_lib, const char *f_name, MT &&M, } } if (libsym == NULL) { - libsym = *(void**)jl_get_global(libptrgv); + libsym = *(void**)jl_get_globalvar(libptrgv); } assert(libsym != NULL); diff --git a/src/codegen.cpp b/src/codegen.cpp index d701a6181a66c..b7d16107a67e2 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -357,6 +357,7 @@ static Function *jlboundserrorv_func; static Function *jlcheckassign_func; static Function *jldeclareconst_func; static Function *jlgetbindingorerror_func; +static Function *jlboundp_func; static Function *jltopeval_func; static Function *jlcopyast_func; static Function *jltuple_func; @@ -2325,7 +2326,6 @@ static void simple_escape_analysis(jl_value_t *expr, bool esc, jl_codectx_t *ctx } } else if (e->head == foreigncall_sym) { - esc = true; simple_escape_analysis(jl_exprarg(e, 0), esc, ctx); // 2nd and 3d arguments are static size_t alen = jl_array_dim0(e->args); @@ -2334,20 +2334,22 @@ static void simple_escape_analysis(jl_value_t *expr, bool esc, jl_codectx_t *ctx } } else if (e->head == method_sym) { - simple_escape_analysis(jl_exprarg(e,0), esc, ctx); + simple_escape_analysis(jl_exprarg(e, 0), esc, ctx); if (jl_expr_nargs(e) > 1) { - simple_escape_analysis(jl_exprarg(e,1), esc, ctx); - simple_escape_analysis(jl_exprarg(e,2), esc, ctx); + simple_escape_analysis(jl_exprarg(e, 1), esc, ctx); + simple_escape_analysis(jl_exprarg(e, 2), esc, ctx); } } else if (e->head == assign_sym) { // don't consider assignment LHS as a variable "use" - simple_escape_analysis(jl_exprarg(e,1), esc, ctx); + simple_escape_analysis(jl_exprarg(e, 1), esc, ctx); } else if (e->head != line_sym) { + if (e->head == isdefined_sym) + esc = false; size_t elen = jl_array_dim0(e->args); - for(i=0; i < elen; i++) { - simple_escape_analysis(jl_exprarg(e,i), esc, ctx); + for (i = 0; i < elen; i++) { + simple_escape_analysis(jl_exprarg(e, i), esc, ctx); } } return; @@ -3603,6 +3605,67 @@ static jl_cgval_t emit_global(jl_sym_t *sym, jl_codectx_t *ctx) return emit_checked_var(bp, sym, ctx, false, tbaa_binding); } +static jl_cgval_t emit_isdefined(jl_value_t *sym, jl_codectx_t *ctx) +{ + Value *isnull; + if (jl_is_slot(sym)) { + size_t sl = jl_slot_number(sym) - 1; + jl_varinfo_t &vi = ctx->slots[sl]; + if (!vi.usedUndef) + return mark_julia_const(jl_true); + if (vi.boxroot == NULL || vi.pTIndex != NULL) { + assert(vi.defFlag); + isnull = builder.CreateLoad(vi.defFlag, vi.isVolatile); + } + if (vi.boxroot != NULL) { + Value *boxed = builder.CreateLoad(vi.boxroot, vi.isVolatile); + Value *box_isnull = builder.CreateICmpNE(boxed, V_null); + if (vi.pTIndex) { + // value is either boxed in the stack slot, or unboxed in value + // as indicated by testing (pTIndex & 0x80) + Value *tindex = builder.CreateLoad(vi.pTIndex, vi.isVolatile); + Value *load_unbox = builder.CreateICmpEQ( + builder.CreateAnd(tindex, ConstantInt::get(T_int8, 0x80)), + ConstantInt::get(T_int8, 0)); + isnull = builder.CreateSelect(load_unbox, isnull, box_isnull); + } + else { + isnull = box_isnull; + } + } + } + else { + jl_module_t *modu; + jl_sym_t *name; + if (jl_is_globalref(sym)) { + modu = jl_globalref_mod(sym); + name = jl_globalref_name(sym); + } + else { + assert(jl_is_symbol(sym) && "malformed isdefined expression"); + modu = ctx->module; + name = (jl_sym_t*)sym; + } + jl_binding_t *bnd = jl_get_binding(modu, name); + if (bnd) { + if (bnd->value != NULL) + return mark_julia_const(jl_true); + Value *bp = julia_binding_gv(bnd); + Instruction *v = builder.CreateLoad(bp); + tbaa_decorate(tbaa_binding, v); + isnull = builder.CreateICmpNE(v, V_null); + } + else { + Value *v = builder.CreateCall(prepare_call(jlboundp_func), { + literal_pointer_val((jl_value_t*)modu), + literal_pointer_val((jl_value_t*)name) + }); + isnull = builder.CreateICmpNE(v, V_null); + } + } + return mark_julia_type(isnull, false, jl_bool_type, ctx); +} + static jl_cgval_t emit_local(jl_value_t *slotload, jl_codectx_t *ctx) { size_t sl = jl_slot_number(slotload) - 1; @@ -4131,7 +4194,10 @@ static jl_cgval_t emit_expr(jl_value_t *expr, jl_codectx_t *ctx) // this is object-disoriented. // however, this is a good way to do it because it should *not* be easy // to add new node types. - if (head == invoke_sym) { + if (head == isdefined_sym) { + return emit_isdefined(args[0], ctx); + } + else if (head == invoke_sym) { return emit_invoke(ex, ctx); } else if (head == call_sym) { @@ -6774,6 +6840,12 @@ static void init_julia_llvm_env(Module *m) "jl_get_binding_or_error", m); add_named_global(jlgetbindingorerror_func, &jl_get_binding_or_error); + jlboundp_func = + Function::Create(FunctionType::get(T_pjlvalue, args_2ptrs, false), + Function::ExternalLinkage, + "jl_boundp", m); + add_named_global(jlboundp_func, &jl_boundp); + builtin_func_map[jl_f_is] = jlcall_func_to_llvm("jl_f_is", &jl_f_is, m); builtin_func_map[jl_f_typeof] = jlcall_func_to_llvm("jl_f_typeof", &jl_f_typeof, m); builtin_func_map[jl_f_sizeof] = jlcall_func_to_llvm("jl_f_sizeof", &jl_f_sizeof, m); diff --git a/src/dump.c b/src/dump.c index c020c554b29e6..b5a46e0d843f2 100644 --- a/src/dump.c +++ b/src/dump.c @@ -3347,7 +3347,7 @@ void jl_init_serializer(void) jl_emptysvec, jl_emptytuple, jl_false, jl_true, jl_nothing, jl_any_type, call_sym, invoke_sym, goto_ifnot_sym, return_sym, body_sym, line_sym, - lambda_sym, jl_symbol("tuple"), assign_sym, + lambda_sym, jl_symbol("tuple"), assign_sym, isdefined_sym, // empirical list of very common symbols #include "common_symbols1.inc" diff --git a/src/interpreter.c b/src/interpreter.c index b78fd15686fd3..55ac7b7b819a3 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -203,33 +203,46 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s) ssize_t n = jl_slot_number(e); if (src == NULL || n > jl_source_nslots(src) || n < 1 || s->locals == NULL) jl_error("access to invalid slot number"); - jl_value_t *v = s->locals[n-1]; + jl_value_t *v = s->locals[n - 1]; if (v == NULL) jl_undefined_var_error((jl_sym_t*)jl_array_ptr_ref(src->slotnames, n - 1)); return v; } if (jl_is_globalref(e)) { - jl_sym_t *s = jl_globalref_name(e); - jl_value_t *v = jl_get_global(jl_globalref_mod(e), s); - if (v == NULL) - jl_undefined_var_error(s); - return v; + return jl_eval_global_var(jl_globalref_mod(e), jl_globalref_name(e)); } if (jl_is_quotenode(e)) return jl_fieldref(e,0); jl_module_t *modu = s->module; if (jl_is_symbol(e)) { // bare symbols appear in toplevel exprs not wrapped in `thunk` - jl_value_t *v = jl_get_global(modu, (jl_sym_t*)e); - if (v == NULL) - jl_undefined_var_error((jl_sym_t*)e); - return v; + return jl_eval_global_var(modu, (jl_sym_t*)e); } if (!jl_is_expr(e)) return e; jl_expr_t *ex = (jl_expr_t*)e; jl_value_t **args = (jl_value_t**)jl_array_data(ex->args); size_t nargs = jl_array_len(ex->args); - if (ex->head == call_sym) { + if (ex->head == isdefined_sym) { + jl_value_t *sym = args[0]; + int defined = 0; + if (jl_is_slot(sym)) { + ssize_t n = jl_slot_number(sym); + if (src == NULL || n > jl_source_nslots(src) || n < 1 || s->locals == NULL) + jl_error("access to invalid slot number"); + defined = s->locals[n - 1] != NULL; + } + else if (jl_is_globalref(sym)) { + defined = jl_boundp(jl_globalref_mod(sym), jl_globalref_name(sym)); + } + else if (jl_is_symbol(sym)) { + defined = jl_boundp(modu, (jl_sym_t*)sym); + } + else { + assert(0 && "malformed isdefined expression"); + } + return defined ? jl_true : jl_false; + } + else if (ex->head == call_sym) { return do_call(args, nargs, s); } else if (ex->head == invoke_sym) { diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index 54a950a4ec99d..e6ae9474d9c9c 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -1048,7 +1048,7 @@ GlobalVariable *jl_emit_sysimg_slot(Module *m, Type *typ, const char *name, return gv; } -void* jl_get_global(GlobalVariable *gv) +void* jl_get_globalvar(GlobalVariable *gv) { #if defined(USE_MCJIT) || defined(USE_ORCJIT) void *p = (void*)(intptr_t)jl_ExecutionEngine->getPointerToGlobalIfAvailable(gv); diff --git a/src/jitlayers.h b/src/jitlayers.h index 92a318c2e3fbf..972867f0ebda6 100644 --- a/src/jitlayers.h +++ b/src/jitlayers.h @@ -68,7 +68,7 @@ void addOptimizationPasses(PassManager *PM); void* jl_emit_and_add_to_shadow(GlobalVariable *gv, void *gvarinit = NULL); GlobalVariable *jl_emit_sysimg_slot(Module *m, Type *typ, const char *name, uintptr_t init, size_t &idx); -void* jl_get_global(GlobalVariable *gv); +void* jl_get_globalvar(GlobalVariable *gv); GlobalVariable *jl_get_global_for(const char *cname, void *addr, Module *M); void jl_add_to_shadow(Module *m); void jl_init_function(Function *f); diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 123e44621140a..bb4226f56b4c4 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -3073,6 +3073,24 @@ f(x) = yt(x) (assq (cadr e) (cadr (lam:vinfo lam)))) '(null) e)) + ((isdefined) ;; convert isdefined expr to function for closure converted variables + (let* ((sym (cadr e)) + (vi (and (symbol? sym) (assq sym (car (lam:vinfo lam))))) + (cv (and (symbol? sym) (assq sym (cadr (lam:vinfo lam)))))) + (cond ((eq? sym fname) e) + ((memq sym (lam:sp lam)) e) + (cv + (if (and (vinfo:asgn cv) (vinfo:capt cv)) + (let ((access (if interp + `($ (call (core QuoteNode) ,sym)) + `(call (core getfield) ,fname (inert ,sym))))) + `(call (core isdefined) ,access (inert contents))) + 'true)) + (vi + (if (and (vinfo:asgn vi) (vinfo:capt vi)) + `(call (core isdefined) ,sym (inert contents)) + e)) + (else e)))) ((method) (let* ((name (method-expr-name e)) (short (length= e 2)) ;; function f end @@ -3597,6 +3615,7 @@ f(x) = yt(x) ((local) #f) ((implicit-global) #f) ((const) (emit e)) + ((isdefined) (if tail (emit-return e) e)) ;; top level expressions returning values ((abstract_type bits_type composite_type thunk toplevel module) diff --git a/src/julia_internal.h b/src/julia_internal.h index 9337c784fcff6..877ddb4400d58 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -975,6 +975,7 @@ extern jl_sym_t *meta_sym; extern jl_sym_t *list_sym; extern jl_sym_t *inert_sym; extern jl_sym_t *static_parameter_sym; extern jl_sym_t *polly_sym; extern jl_sym_t *inline_sym; extern jl_sym_t *propagate_inbounds_sym; +extern jl_sym_t *isdefined_sym; #ifdef __cplusplus } diff --git a/test/core.jl b/test/core.jl index 32d0f73a1d23d..e83a4fb885897 100644 --- a/test/core.jl +++ b/test/core.jl @@ -4997,3 +4997,57 @@ end end @test M22026.foofunction(Int16) === Int16 @test M22026.foofunction2(3) === 6.0f0 + +# tests for isdefined behavior and code generation +global undefined_variable +@test @isdefined Test +@test !@isdefined undefined_variable +@test !@isdefined undefined_variable2 +@test let local_undef, local_def = 1 + !@isdefined local_undef + @isdefined local_def +end +f_isdefined_latedef() = @isdefined f_isdefined_def +@test !f_isdefined_latedef() +f_isdefined(x) = @isdefined x +f_isdefined_undef() = @isdefined x_isundef +f_isdefined_def() = @isdefined f_isdefined_def +@test f_isdefined(1) +@test f_isdefined("") +@test !f_isdefined_undef() +@test f_isdefined_def() +@test f_isdefined_latedef() +f_isdefined_defvarI() = (x = rand(Int); @isdefined x) +f_isdefined_defvarS() = (x = randstring(1); @isdefined x) +@test f_isdefined_defvarI() +@test f_isdefined_defvarS() +f_isdefined_undefvar() = (local x; @isdefined x) +@test !f_isdefined_undefvar() +f_isdefined_unionvar(y, t) = (t > 0 && (x = (t == 1 ? 1 : y)); @isdefined x) +@test f_isdefined_unionvar(nothing, 1) +@test f_isdefined_unionvar("", 1) +@test f_isdefined_unionvar(1.0, 1) +@test f_isdefined_unionvar(1, 1) +@test !f_isdefined_unionvar(nothing, 0) +@test !f_isdefined_unionvar("", 0) +@test !f_isdefined_unionvar(1.0, 0) +@test !f_isdefined_unionvar(1, 0) +f_isdefined_splat(x...) = @isdefined x +@test f_isdefined_splat(1, 2, 3) +@test let err = @macroexpand @isdefined :x + isa(err, Expr) && err.head === :error && isa(err.args[1], MethodError) +end +f_isdefined_cl_1(y) = (local x; for i = 1:y; x = 2; end; () -> x; @isdefined x) +f_isdefined_cl_2(y) = (local x; for i = 1:y; x = 2; end; () -> @isdefined x) +f_isdefined_cl_3() = (x = 2; () -> x; @isdefined x) +f_isdefined_cl_4() = (local x; () -> x; @isdefined x) +f_isdefined_cl_5() = (x = 2; () -> @isdefined x) +f_isdefined_cl_6() = (local x; () -> @isdefined x) +@test f_isdefined_cl_1(1) +@test !f_isdefined_cl_1(0) +@test f_isdefined_cl_2(1)() +@test !f_isdefined_cl_2(0)() +@test f_isdefined_cl_3() +@test !f_isdefined_cl_4() +@test f_isdefined_cl_5()() +@test !f_isdefined_cl_6()() From 7495f445feebb1ccb835832ce2d16b3e66e685ed Mon Sep 17 00:00:00 2001 From: Nathan Smith Date: Wed, 7 Jun 2017 22:27:27 -0700 Subject: [PATCH 1030/1534] loosen skipchars signature (#22234) * closes #21354 --- base/io.jl | 31 +++++++++++++++++++++++++++++++ base/iostream.jl | 13 ------------- test/iobuffer.jl | 26 ++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 13 deletions(-) diff --git a/base/io.jl b/base/io.jl index 1d5e1651a0c51..244165b37c73d 100644 --- a/base/io.jl +++ b/base/io.jl @@ -645,3 +645,34 @@ ismarked(io::IO) = io.mark >= 0 Commit all currently buffered writes to the given stream. """ flush(io::IO) = nothing + +""" + skipchars(io::IO, predicate; linecomment=nothing) + +Skip forward in `io` until `predicate` returns `false`. If `linecomment` +is defined, all characters after the `linecomment` character are ignored +until the next line. + +```jldoctext +julia> buf = IOBuffer(" text") +IOBuffer(data=UInt8[...], readable=true, writable=false, seekable=true, append=false, size=8, maxsize=Inf, ptr=1, mark=-1) + +julia> skipchars(buf, isspace) +IOBuffer(data=UInt8[...], readable=true, writable=false, seekable=true, append=false, size=8, maxsize=Inf, ptr=5, mark=-1) + +julia> String(readavailable(buf)) +"text" +``` +""" +function skipchars(io::IO, pred; linecomment=nothing) + while !eof(io) + c = read(io, Char) + if c === linecomment + readline(io) + elseif !pred(c) + skip(io, -codelen(c)) + break + end + end + return io +end diff --git a/base/iostream.jl b/base/iostream.jl index c03de590113b4..cbd96a95f7fb0 100644 --- a/base/iostream.jl +++ b/base/iostream.jl @@ -320,16 +320,3 @@ end function peek(s::IOStream) ccall(:ios_peekc, Cint, (Ptr{Void},), s) end - -function skipchars(io::IOStream, pred; linecomment=nothing) - while !eof(io) - c = read(io, Char) - if c === linecomment - readline(io) - elseif !pred(c) - skip(io, -codelen(c)) - break - end - end - return io -end diff --git a/test/iobuffer.jl b/test/iobuffer.jl index 5921b3714b4be..d8b3a19d80c8f 100644 --- a/test/iobuffer.jl +++ b/test/iobuffer.jl @@ -232,3 +232,29 @@ end let io = IOBuffer() @test Base.buffer_writes(io) === io end + +# skipchars +let + io = IOBuffer("") + @test eof(skipchars(io, isspace)) + + io = IOBuffer(" ") + @test eof(skipchars(io, isspace)) + + io = IOBuffer("# \n ") + @test eof(skipchars(io, isspace, linecomment='#')) + + io = IOBuffer(" text") + skipchars(io, isspace) + @test String(readavailable(io)) == "text" + + io = IOBuffer(" # comment \n text") + skipchars(io, isspace, linecomment='#') + @test String(readavailable(io)) == "text" + + for char in ['@','߷','࿊','𐋺'] + io = IOBuffer("alphabeticalstuff$char") + @test !eof(skipchars(io, isalpha)) + @test read(io, Char) == char + end +end From a32ba7138e74f9a66a18de0228c9f2702edb7714 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 8 Jun 2017 13:08:04 -0400 Subject: [PATCH 1031/1534] fix #18755, bug in updating IOStream position when writing --- src/support/ios.c | 1 + test/iostream.jl | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/src/support/ios.c b/src/support/ios.c index 9dffebc8c808d..70af4078f6e9e 100644 --- a/src/support/ios.c +++ b/src/support/ios.c @@ -426,6 +426,7 @@ size_t ios_write(ios_t *s, const char *data, size_t n) else { ios_flush(s); if (n > MOST_OF(s->maxsize)) { + s->fpos = -1; _os_write_all(s->fd, data, n, &wrote); return wrote; } diff --git a/test/iostream.jl b/test/iostream.jl index 2eb307f6536b9..31026b753d173 100644 --- a/test/iostream.jl +++ b/test/iostream.jl @@ -39,3 +39,10 @@ mktemp() do path, file end end +# issue #18755 +mktemp() do path, io + write(io, zeros(UInt8, 131073)) + @test position(io) == 131073 + write(io, zeros(UInt8, 131073)) + @test position(io) == 262146 +end From 2d8c0f9160812dba14c08b3602d907f561e843fe Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Thu, 8 Jun 2017 22:32:57 +0200 Subject: [PATCH 1032/1534] add a missing method for transpose(A::Hermitian{<:Real}) (#22280) --- base/linalg/symmetric.jl | 1 + test/linalg/symmetric.jl | 16 +++++++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/base/linalg/symmetric.jl b/base/linalg/symmetric.jl index a3c2aa39c435e..9dc5bc9a083a0 100644 --- a/base/linalg/symmetric.jl +++ b/base/linalg/symmetric.jl @@ -210,6 +210,7 @@ issymmetric(A::Hermitian{<:Real}) = true issymmetric(A::Hermitian{<:Complex}) = isreal(A) issymmetric(A::Symmetric) = true transpose(A::Symmetric) = A +transpose(A::Hermitian{<:Real}) = A ctranspose(A::Symmetric{<:Real}) = A function ctranspose(A::Symmetric) AC = ctranspose(A.data) diff --git a/test/linalg/symmetric.jl b/test/linalg/symmetric.jl index 17e457d8c1082..3d686a037d09f 100644 --- a/test/linalg/symmetric.jl +++ b/test/linalg/symmetric.jl @@ -93,14 +93,20 @@ let n=10 @test ishermitian(Symmetric(b + b')) end - #transpose, ctranspose + # transpose, ctranspose + S = Symmetric(asym) + H = Hermitian(asym) if eltya <: Real - @test transpose(Symmetric(asym)) == asym + @test transpose(S) === S == asym + @test ctranspose(S) === S == asym + @test transpose(H) === H == asym + @test ctranspose(H) === H == asym else - @test transpose(Hermitian(asym)) == transpose(asym) + @test transpose(S) === S + @test ctranspose(S) == Symmetric(conj(asym)) + @test transpose(H) == Hermitian(transpose(asym)) + @test ctranspose(H) === H == asym end - @test ctranspose(Symmetric(asym)) == Symmetric(conj(asym)) - @test ctranspose(Hermitian(asym)) == asym #tril/triu for di in -n:n From dde6ff61c30f7d5edf8f488608b7cb0823bb5e81 Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Thu, 8 Jun 2017 14:51:52 -0700 Subject: [PATCH 1033/1534] Add fastly purging to contrib/prepare_release.sh (#22277) * Add fastly purging to cotnrib/prepare_release.sh Fastly caches our files for a long time; we need to explicitly ask it to purge the -latest files. * Add `+` character for osx fastly purge --- contrib/prepare_release.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/contrib/prepare_release.sh b/contrib/prepare_release.sh index 77e67de189e78..cf12e7444c3b7 100755 --- a/contrib/prepare_release.sh +++ b/contrib/prepare_release.sh @@ -83,19 +83,25 @@ for plat in x86_64 i686 arm ppc64le; do s3://julialang/bin/linux/$platshort/$majmin/ aws s3 cp --acl public-read julia-$majmin-latest-linux-$plat.tar.gz \ s3://julialang/bin/linux/$platshort/$majmin/ + curl -X PURGE -L "https://julialang-s3.julialang.org/bin/linux/$platshort/$majmin/julia-$majmin-latest-linux-$plat.tar.gz" done aws s3 cp --acl public-read "julia-$version-osx10.7 .dmg" \ s3://julialang/bin/osx/x64/$majmin/ aws s3 cp --acl public-read "julia-$majmin-latest-osx10.7 .dmg" \ s3://julialang/bin/osx/x64/$majmin/ +curl -X PURGE -L "https://julialang-s3.julialang.org/bin/osx/x64/$majmin/julia-$majmin-latest-osx10.7 .dmg" +curl -X PURGE -L "https://julialang-s3.julialang.org/bin/osx/x64/$majmin/julia-$majmin-latest-osx10.7+.dmg" aws s3 cp --acl public-read "julia-$version-win64.exe" \ s3://julialang/bin/winnt/x64/$majmin/ aws s3 cp --acl public-read "julia-$majmin-latest-win64.exe" \ s3://julialang/bin/winnt/x64/$majmin/ +curl -X PURGE -L "https://julialang-s3.julialang.org/bin/winnt/x64/$majmin/julia-$majmin-latest-win64.exe" aws s3 cp --acl public-read "julia-$version-win32.exe" \ s3://julialang/bin/winnt/x86/$majmin/ aws s3 cp --acl public-read "julia-$majmin-latest-win32.exe" \ s3://julialang/bin/winnt/x86/$majmin/ +curl -X PURGE -L "https://julialang-s3.julialang.org/bin/winnt/x86/$majmin/julia-$majmin-latest-win32.exe" + echo "All files prepared. Attach julia-$version.tar.gz" echo "and julia-$version-full.tar.gz to github releases." From 37395031a782292d926da6eeef7d44cd77c32183 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 9 Jun 2017 01:39:51 -0400 Subject: [PATCH 1034/1534] slight improvements to make static compilation easier --- doc/src/manual/embedding.md | 1 + examples/embedding/embedding.c | 2 ++ src/julia.h | 26 +++++++++++++++++++++++--- ui/repl.c | 16 +--------------- 4 files changed, 27 insertions(+), 18 deletions(-) diff --git a/doc/src/manual/embedding.md b/doc/src/manual/embedding.md index 032b57dcedc43..eadfdf96a8099 100644 --- a/doc/src/manual/embedding.md +++ b/doc/src/manual/embedding.md @@ -13,6 +13,7 @@ We start with a simple C program that initializes Julia and calls some Julia cod ```c #include +JULIA_DEFINE_FAST_TLS() // only define this once, in an executable (not in a shared library) if you want fast code. int main(int argc, char *argv[]) { diff --git a/examples/embedding/embedding.c b/examples/embedding/embedding.c index 5bb70aadc04c2..9eb299449ec4b 100644 --- a/examples/embedding/embedding.c +++ b/examples/embedding/embedding.c @@ -4,6 +4,8 @@ #include #include +JULIA_DEFINE_FAST_TLS() // only define this once, in an executable + #ifdef _OS_WINDOWS_ __declspec(dllexport) __cdecl #endif diff --git a/src/julia.h b/src/julia.h index 314feafc4dc1a..c6d63d1f3517c 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1,8 +1,5 @@ // This file is a part of Julia. License is MIT: https://julialang.org/license -// TODO: add `@isdefined` -// - #ifndef JULIA_H #define JULIA_H @@ -1328,6 +1325,12 @@ typedef enum { JL_IMAGE_JULIA_HOME = 1, //JL_IMAGE_LIBJULIA = 2, } JL_IMAGE_SEARCH; +#ifdef JULIA_ENABLE_THREADING +// this helps turn threading compilation mismatches into linker errors +#define julia_init julia_init__threading +#define jl_init jl_init__threading +#define jl_init_with_image jl_init_with_image__threading +#endif JL_DLLEXPORT void julia_init(JL_IMAGE_SEARCH rel); JL_DLLEXPORT void jl_init(void); JL_DLLEXPORT void jl_init_with_image(const char *julia_home_dir, @@ -1850,6 +1853,23 @@ typedef struct { } jl_cgparams_t; extern JL_DLLEXPORT jl_cgparams_t jl_default_cgparams; +#if defined(JULIA_ENABLE_THREADING) && !defined(_OS_DARWIN_) && !defined(_OS_WINDOWS_) +#define JULIA_DEFINE_FAST_TLS() \ +JL_DLLEXPORT JL_CONST_FUNC jl_ptls_t jl_get_ptls_states_static(void) \ +{ \ + static __attribute__((tls_model("local-exec"))) __thread jl_tls_states_t tls_states; \ + return &tls_states; \ +} \ +__attribute__((constructor)) void jl_register_ptls_states_getter(void) \ +{ \ + /* We need to make sure this function is called before any reference to */ \ + /* TLS variables. */ \ + jl_set_ptls_states_getter(jl_get_ptls_states_static); \ +} +#else +#define JULIA_DEFINE_FAST_TLS() +#endif + #ifdef __cplusplus } #endif diff --git a/ui/repl.c b/ui/repl.c index 2355675b2fa53..cba286bd1cf9a 100644 --- a/ui/repl.c +++ b/ui/repl.c @@ -21,27 +21,13 @@ #include #include "uv.h" -#define WHOLE_ARCHIVE #include "../src/julia.h" +JULIA_DEFINE_FAST_TLS() #ifdef __cplusplus extern "C" { #endif -#if defined(JULIA_ENABLE_THREADING) && !defined(_OS_DARWIN_) && !defined(_OS_WINDOWS_) -JL_DLLEXPORT JL_CONST_FUNC jl_ptls_t jl_get_ptls_states_static(void) -{ - static __attribute__((tls_model("local-exec"))) __thread jl_tls_states_t tls_states; - return &tls_states; -} -__attribute__((constructor)) void jl_register_ptls_states_getter(void) -{ - // We need to make sure this function is called before any reference to - // TLS variables. - jl_set_ptls_states_getter(jl_get_ptls_states_static); -} -#endif - static int exec_program(char *program) { jl_ptls_t ptls = jl_get_ptls_states(); From f2805a596f7d9bbe63f78d997e22410df84e2525 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Thu, 8 Jun 2017 22:59:12 -0500 Subject: [PATCH 1035/1534] Correct `@test` using chained comparison --- base/test.jl | 5 +---- test/test.jl | 7 +++++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/base/test.jl b/base/test.jl index 9180f27061f01..45ac74eee39eb 100644 --- a/base/test.jl +++ b/base/test.jl @@ -300,10 +300,7 @@ function get_test_result(ex) $(esc(ex.args[2])), $(esc(ex.args[1])), $(esc(ex.args[3]))))) elseif isa(ex, Expr) && ex.head == :comparison # pass all terms of the comparison to `eval_comparison`, as an Expr - terms = ex.args - for i = 1:length(terms) - terms[i] = esc(terms[i]) - end + terms = [esc(arg) for arg in ex.args] testret = :(eval_comparison(Expr(:comparison, $(terms...)))) else testret = :(Returned($(esc(ex)), nothing)) diff --git a/test/test.jl b/test/test.jl index 01898c234e93c..0bc69fb52c869 100644 --- a/test/test.jl +++ b/test/test.jl @@ -60,16 +60,19 @@ fails = @testset NoThrowTestSet begin @test_throws OverflowError 1 + 1 # Fail - comparison @test 1+1 == 2+2 + # Fail - chained comparison + @test 1+0 == 2+0 == 3+0 # Error - unexpected pass @test_broken true end -for i in 1:3 +for i in 1:length(fails) - 1 @test isa(fails[i], Base.Test.Fail) end @test contains(sprint(show, fails[1]), "Thrown: ErrorException") @test contains(sprint(show, fails[2]), "No exception thrown") @test contains(sprint(show, fails[3]), "Evaluated: 2 == 4") -@test contains(sprint(show, fails[4]), "Unexpected Pass") +@test contains(sprint(show, fails[4]), "Evaluated: 1 == 2 == 3") +@test contains(sprint(show, fails[5]), "Unexpected Pass") # Test printing of a TestSetException tse_str = sprint(show, Test.TestSetException(1,2,3,4,Vector{Union{Base.Test.Error, Base.Test.Fail}}())) From a7ba25bc4c6f54d18b6ea93d3eda0b974909a7a1 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Fri, 9 Jun 2017 08:42:01 -0500 Subject: [PATCH 1036/1534] =?UTF-8?q?Revise=20`get=5Ftest=5Fresult`=20to?= =?UTF-8?q?=20work=20correctly=20with=20=E2=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Escaping the ≈ operator would result in the displayed evaluated expression appearing as `x isapprox y` instead of `x ≈ y`. Additionally, the code was written to ensure that the arguments of `@test` are only evaluated once. --- base/test.jl | 33 ++++++++++++++++++++------------- test/test.jl | 13 +++++++++++-- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/base/test.jl b/base/test.jl index 45ac74eee39eb..7f6152119aa84 100644 --- a/base/test.jl +++ b/base/test.jl @@ -186,19 +186,22 @@ struct Threw <: ExecutionResult backtrace end -function eval_comparison(ex::Expr) +function eval_comparison(evaluated::Expr, quoted::Expr) res = true i = 1 - a = ex.args - n = length(a) + args = evaluated.args + quoted_args = quoted.args + n = length(args) while i < n - res = a[i+1](a[i], a[i+2]) - if !isa(res,Bool) || !res - break + a, op, b = args[i], args[i+1], args[i+2] + if res + res = op(a, b) === true # Keep `res` type stable end + quoted_args[i] = a + quoted_args[i+2] = b i += 2 end - Returned(res, ex) + Returned(res, quoted) end const comparison_prec = Base.operator_precedence(:(==)) @@ -293,15 +296,19 @@ end function get_test_result(ex) orig_ex = Expr(:inert, ex) # Normalize non-dot comparison operator calls to :comparison expressions - if isa(ex, Expr) && ex.head == :call && length(ex.args)==3 && + if isa(ex, Expr) && ex.head == :call && length(ex.args) == 3 && first(string(ex.args[1])) != '.' && (ex.args[1] === :(==) || Base.operator_precedence(ex.args[1]) == comparison_prec) - testret = :(eval_comparison(Expr(:comparison, - $(esc(ex.args[2])), $(esc(ex.args[1])), $(esc(ex.args[3]))))) - elseif isa(ex, Expr) && ex.head == :comparison + ex = Expr(:comparison, ex.args[2], ex.args[1], ex.args[3]) + end + if isa(ex, Expr) && ex.head == :comparison # pass all terms of the comparison to `eval_comparison`, as an Expr - terms = [esc(arg) for arg in ex.args] - testret = :(eval_comparison(Expr(:comparison, $(terms...)))) + escaped_terms = [esc(arg) for arg in ex.args] + quoted_terms = [QuoteNode(arg) for arg in ex.args] + testret = :(eval_comparison( + Expr(:comparison, $(escaped_terms...)), + Expr(:comparison, $(quoted_terms...)), + )) else testret = :(Returned($(esc(ex)), nothing)) end diff --git a/test/test.jl b/test/test.jl index 0bc69fb52c869..bd81cd37279d9 100644 --- a/test/test.jl +++ b/test/test.jl @@ -7,6 +7,12 @@ @test strip("\t hi \n") == "hi" @test strip("\t this should fail \n") != "hi" +# @test should only evaluate the arguments once +let g = Int[], f = (x) -> (push!(g, x); x) + @test f(1) == 1 + @test g == [1] +end + # Test @test_broken with fail @test_broken false @test_broken 1 == 2 @@ -60,6 +66,8 @@ fails = @testset NoThrowTestSet begin @test_throws OverflowError 1 + 1 # Fail - comparison @test 1+1 == 2+2 + # Fail - approximate comparison + @test 1/1 ≈ 2/1 # Fail - chained comparison @test 1+0 == 2+0 == 3+0 # Error - unexpected pass @@ -71,8 +79,9 @@ end @test contains(sprint(show, fails[1]), "Thrown: ErrorException") @test contains(sprint(show, fails[2]), "No exception thrown") @test contains(sprint(show, fails[3]), "Evaluated: 2 == 4") -@test contains(sprint(show, fails[4]), "Evaluated: 1 == 2 == 3") -@test contains(sprint(show, fails[5]), "Unexpected Pass") +@test contains(sprint(show, fails[4]), "Evaluated: 1.0 ≈ 2.0") +@test contains(sprint(show, fails[5]), "Evaluated: 1 == 2 == 3") +@test contains(sprint(show, fails[6]), "Unexpected Pass") # Test printing of a TestSetException tse_str = sprint(show, Test.TestSetException(1,2,3,4,Vector{Union{Base.Test.Error, Base.Test.Fail}}())) From 2a37b808b38162d1e52e378f0f8a20ea439c68a4 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Fri, 9 Jun 2017 09:18:39 -0500 Subject: [PATCH 1037/1534] Update tests to check expression output --- test/test.jl | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/test/test.jl b/test/test.jl index bd81cd37279d9..a916906be340d 100644 --- a/test/test.jl +++ b/test/test.jl @@ -76,12 +76,30 @@ end for i in 1:length(fails) - 1 @test isa(fails[i], Base.Test.Fail) end -@test contains(sprint(show, fails[1]), "Thrown: ErrorException") -@test contains(sprint(show, fails[2]), "No exception thrown") -@test contains(sprint(show, fails[3]), "Evaluated: 2 == 4") -@test contains(sprint(show, fails[4]), "Evaluated: 1.0 ≈ 2.0") -@test contains(sprint(show, fails[5]), "Evaluated: 1 == 2 == 3") -@test contains(sprint(show, fails[6]), "Unexpected Pass") + +str = sprint(show, fails[1]) +@test contains(str, "Expression: error()") +@test contains(str, "Thrown: ErrorException") + +str = sprint(show, fails[2]) +@test contains(str, "Expression: 1 + 1") +@test contains(str, "No exception thrown") + +str = sprint(show, fails[3]) +@test contains(str, "Expression: 1 + 1 == 2 + 2") +@test contains(str, "Evaluated: 2 == 4") + +str = sprint(show, fails[4]) +@test contains(str, "Expression: 1 / 1 ≈ 2 / 1") +@test contains(str, "Evaluated: 1.0 ≈ 2.0") + +str = sprint(show, fails[5]) +@test contains(str, "Expression: 1 + 0 == 2 + 0 == 3 + 0") +@test contains(str, "Evaluated: 1 == 2 == 3") + +str = sprint(show, fails[6]) +@test contains(str, "Unexpected Pass") +@test contains(str, "Expression: true") # Test printing of a TestSetException tse_str = sprint(show, Test.TestSetException(1,2,3,4,Vector{Union{Base.Test.Error, Base.Test.Fail}}())) From d4e2b5754589b9ccca3ab06f0ad8172bc071f3ba Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Fri, 9 Jun 2017 09:48:37 -0500 Subject: [PATCH 1038/1534] Add test for comparison calls --- test/test.jl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/test.jl b/test/test.jl index a916906be340d..6b63c30b9ccb0 100644 --- a/test/test.jl +++ b/test/test.jl @@ -70,6 +70,8 @@ fails = @testset NoThrowTestSet begin @test 1/1 ≈ 2/1 # Fail - chained comparison @test 1+0 == 2+0 == 3+0 + # Fail - comparison call + @test ==(1 - 2, 2 - 1) # Error - unexpected pass @test_broken true end @@ -98,6 +100,10 @@ str = sprint(show, fails[5]) @test contains(str, "Evaluated: 1 == 2 == 3") str = sprint(show, fails[6]) +@test contains(str, "Expression: 1 - 2 == 2 - 1") +@test contains(str, "Evaluated: -1 == 1") + +str = sprint(show, fails[7]) @test contains(str, "Unexpected Pass") @test contains(str, "Expression: true") From 4f127f457fae74b4884324116edd5cbb519cf4c3 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Fri, 26 May 2017 19:12:55 -0500 Subject: [PATCH 1039/1534] Respect startup-file during Pkg.build and Pkg.test --- base/pkg/entry.jl | 2 ++ test/pkg.jl | 55 +++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/base/pkg/entry.jl b/base/pkg/entry.jl index d8fa73a8d04a2..afdad513031e7 100644 --- a/base/pkg/entry.jl +++ b/base/pkg/entry.jl @@ -610,6 +610,7 @@ function build(pkg::AbstractString, build_file::AbstractString, errfile::Abstrac --color=$(Base.have_color ? "yes" : "no") --compilecache=$(Bool(Base.JLOptions().use_compilecache) ? "yes" : "no") --history-file=no + --startup-file=$(Base.JLOptions().startupfile != 2 ? "yes" : "no") --eval $code ``` @@ -717,6 +718,7 @@ function test!(pkg::AbstractString, --color=$(Base.have_color ? "yes" : "no") --compilecache=$(Bool(Base.JLOptions().use_compilecache) ? "yes" : "no") --check-bounds=yes + --startup-file=$(Base.JLOptions().startupfile != 2 ? "yes" : "no") $test_path ``` run(cmd) diff --git a/test/pkg.jl b/test/pkg.jl index 4a2c813b46944..abd04ea9d59f7 100644 --- a/test/pkg.jl +++ b/test/pkg.jl @@ -39,6 +39,12 @@ function temp_pkg_dir(fn::Function, tmp_dir=joinpath(tempdir(), randstring()), end end +function write_build(pkg, content) + build_filename = Pkg.dir(pkg, "deps", "build.jl") + mkpath(dirname(build_filename)) + write(build_filename, content) +end + # Test basic operations: adding or removing a package, status, free # Also test for the existence of REQUIRE and META_BRANCH temp_pkg_dir() do @@ -531,6 +537,49 @@ temp_pkg_dir() do "redirect_stderr(STDOUT); using Example; Pkg.update(\"$package\")"`)) @test contains(msg, "- $package\nRestart Julia to use the updated versions.") end + + # Verify that the --startup-file flag is respected by Pkg.build / Pkg.test + let package = "StartupFile" + content = """ + info("JULIA_RC_LOADED defined \$(isdefined(@__MODULE__, :JULIA_RC_LOADED))") + info("Main.JULIA_RC_LOADED defined \$(isdefined(Main, :JULIA_RC_LOADED))") + """ + + write_build(package, content) + + test_filename = Pkg.dir(package, "test", "runtests.jl") + mkpath(dirname(test_filename)) + write(test_filename, content) + + # Make a .juliarc.jl + home = Pkg.dir(".home") + mkdir(home) + write(joinpath(home, ".juliarc.jl"), "const JULIA_RC_LOADED = true") + + withenv((is_windows() ? "USERPROFILE" : "HOME") => home) do + code = "redirect_stderr(STDOUT); Pkg.build(\"$package\")" + + msg = readstring(`$(Base.julia_cmd()) --startup-file=no -e $code`) + @test contains(msg, "INFO: JULIA_RC_LOADED defined false") + @test contains(msg, "INFO: Main.JULIA_RC_LOADED defined false") + + msg = readstring(`$(Base.julia_cmd()) --startup-file=yes -e $code`) + @test contains(msg, "INFO: JULIA_RC_LOADED defined false") + @test contains(msg, "INFO: Main.JULIA_RC_LOADED defined true") + + code = "redirect_stderr(STDOUT); Pkg.test(\"$package\")" + + msg = readstring(`$(Base.julia_cmd()) --startup-file=no -e $code`) + @test contains(msg, "INFO: JULIA_RC_LOADED defined false") + @test contains(msg, "INFO: Main.JULIA_RC_LOADED defined false") + + # Note: Since both the startup-file and "runtests.jl" are run in the Main + # module any global variables created in the .juliarc.jl can be referenced. + msg = readstring(`$(Base.julia_cmd()) --startup-file=yes -e $code`) + @test contains(msg, "INFO: JULIA_RC_LOADED defined true") + @test contains(msg, "INFO: Main.JULIA_RC_LOADED defined true") + end + end end @testset "Pkg functions with .jl extension" begin @@ -594,12 +643,6 @@ end end temp_pkg_dir(initialize=false) do - function write_build(pkg, content) - build_filename = Pkg.dir(pkg, "deps", "build.jl") - mkpath(dirname(build_filename)) - write(build_filename, content) - end - write_build("Normal", "") write_build("Error", "error(\"An error has occurred while building a package\")") write_build("Exit", "exit()") From 6ab0f0af722c2cec30d419a42d4dc3ddcbfe1f72 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 7 Jun 2017 20:51:47 -0400 Subject: [PATCH 1040/1534] implement setfield! case correctly of PR to optimize field access when field types don't depend on parameters fixes the bug in PR #21620 correctly --- src/codegen.cpp | 10 +++++----- test/core.jl | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index d701a6181a66c..510a558890a2c 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3050,10 +3050,10 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, } else if (f==jl_builtin_setfield && nargs==3) { - jl_datatype_t *sty = (jl_datatype_t*)expr_type(args[1], ctx); - rt1 = (jl_value_t*)sty; - jl_datatype_t *uty = (jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)sty); - if (jl_is_structtype(uty) && uty != jl_module_type && ((jl_datatype_t*)uty)->layout) { + jl_value_t *sty = expr_type(args[1], ctx); + rt1 = sty; + jl_datatype_t *uty = (jl_datatype_t*)jl_unwrap_unionall(sty); + if (jl_is_structtype(uty) && uty != jl_module_type && uty->layout) { size_t idx = (size_t)-1; if (jl_is_quotenode(args[2]) && jl_is_symbol(jl_fieldref(args[2],0))) { idx = jl_field_index(uty, (jl_sym_t*)jl_fieldref(args[2],0), 0); @@ -3075,7 +3075,7 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, // TODO: attempt better codegen for approximate types jl_cgval_t strct = emit_expr(args[1], ctx); // emit lhs *ret = emit_expr(args[3], ctx); - emit_setfield(sty, strct, idx, *ret, ctx, true, true); + emit_setfield(uty, strct, idx, *ret, ctx, true, true); JL_GC_POP(); return true; } diff --git a/test/core.jl b/test/core.jl index 32d0f73a1d23d..9a3ff96b23fb8 100644 --- a/test/core.jl +++ b/test/core.jl @@ -4973,6 +4973,20 @@ let end @test f22122(1) === Int +# issue #22256 +mutable struct Bar22256{AParameter} + inner::Int +end +mutable struct Foo22256 + bar::Bar22256 +end +setbar22256_inner(a) = (a.bar.inner = 3; nothing) +let a_foo = Foo22256(Bar22256{true}(2)) + @test a_foo.bar.inner == 2 + setbar22256_inner(a_foo) + @test a_foo.bar.inner == 3 +end + # issue #22026 module M22026 From ff2ad4e997ce2a83d6eac316d84ecbca08b72f38 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Fri, 9 Jun 2017 13:33:18 -0700 Subject: [PATCH 1041/1534] fix test case to use 4 space indent instead of 3 --- test/core.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/core.jl b/test/core.jl index 9a3ff96b23fb8..c6bddb164cfca 100644 --- a/test/core.jl +++ b/test/core.jl @@ -4982,9 +4982,9 @@ mutable struct Foo22256 end setbar22256_inner(a) = (a.bar.inner = 3; nothing) let a_foo = Foo22256(Bar22256{true}(2)) - @test a_foo.bar.inner == 2 - setbar22256_inner(a_foo) - @test a_foo.bar.inner == 3 + @test a_foo.bar.inner == 2 + setbar22256_inner(a_foo) + @test a_foo.bar.inner == 3 end # issue #22026 From 9588cef42ca7c45b8d07e8fa900cb7c87ee99009 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 9 Jun 2017 17:18:00 -0400 Subject: [PATCH 1042/1534] make `@ccallable` work with return type declarations allow return type declarations, and use them as the C return type if a C return type is not explicitly passed. --- base/c.jl | 18 +++++++++++++++++- test/llvmcall.jl | 16 ++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/base/c.jl b/base/c.jl index 80c58a4640614..3385e18b4e9d2 100644 --- a/base/c.jl +++ b/base/c.jl @@ -344,9 +344,18 @@ function ccallable(f::Function, rt::Type, argt::Type, name::Union{AbstractString ccall(:jl_extern_c, Void, (Any, Any, Any, Cstring), f, rt, argt, name) end -macro ccallable(rt, def) +function expand_ccallable(rt, def) if isa(def,Expr) && (def.head === :(=) || def.head === :function) sig = def.args[1] + if sig.head === :(::) + if rt === nothing + rt = sig.args[2] + end + sig = sig.args[1] + end + if rt === nothing + error("@ccallable requires a return type") + end if sig.head === :call name = sig.args[1] at = map(sig.args[2:end]) do a @@ -364,3 +373,10 @@ macro ccallable(rt, def) end error("expected method definition in @ccallable") end + +macro ccallable(def) + expand_ccallable(nothing, def) +end +macro ccallable(rt, def) + expand_ccallable(rt, def) +end diff --git a/test/llvmcall.jl b/test/llvmcall.jl index fc59bd025939f..302d3950e75e2 100644 --- a/test/llvmcall.jl +++ b/test/llvmcall.jl @@ -191,3 +191,19 @@ if Base.libllvm_version >= v"3.6" # llvm 3.6 changed the syntax for a gep, so ju else println("INFO: skipping gep parentage test on llvm < 3.6") end + +module CcallableRetTypeTest + using Base: Test, llvmcall, @ccallable + @ccallable function jl_test_returns_float()::Float64 + return 42 + end + function do_the_call() + llvmcall( + (""" declare double @jl_test_returns_float()""", + """ + %1 = call double @jl_test_returns_float() + ret double %1 + """),Float64,Tuple{}) + end + @test do_the_call() === 42.0 +end From 70915de338274c4d88197599e21f831b6b8b07b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20F=C3=A4lt?= Date: Fri, 9 Jun 2017 14:35:09 -0700 Subject: [PATCH 1043/1534] RFC: Added sparse low rank cholesky updates (#21426) * Added sparse low rank cholesky updates * Fixed bug in sparse cholesky rank update tests * Typos in sparse rank update * Tiny typo * Nicer description of sparserankupdate --- base/sparse/cholmod.jl | 82 ++++++++++++++++++++++++++++++++++++++++++ test/sparse/cholmod.jl | 37 +++++++++++++++++++ 2 files changed, 119 insertions(+) diff --git a/base/sparse/cholmod.jl b/base/sparse/cholmod.jl index ba5b34b109407..08eec5cdac939 100644 --- a/base/sparse/cholmod.jl +++ b/base/sparse/cholmod.jl @@ -1541,6 +1541,88 @@ ldltfact(A::Union{SparseMatrixCSC{T},SparseMatrixCSC{Complex{T}}, Hermitian{T,SparseMatrixCSC{T,SuiteSparse_long}}}; kws...) where {T<:Real} = ldltfact(Sparse(A); kws...) +## Rank updates + +""" + lowrankupdowndate!(F::Factor, C::Sparse, update::Cint) + +Update an `LDLt` or `LLt` Factorization `F` of `A` to a factorization of `A ± C*C'`. + +If sparsity preserving factorization is used, i.e. `L*L' == P*A*P'` then the new +factor will be `L*L' == P*A*P' + C'*C` + +update: `Cint(1)` for `A + CC'`, `Cint(0)` for `A - CC'` +""" +function lowrankupdowndate!{Tv<:VTypes}(F::Factor{Tv}, C::Sparse{Tv}, update::Cint) + lF = unsafe_load(get(F.p)) + lC = unsafe_load(get(C.p)) + if lF.n != lC.nrow + throw(DimensionMismatch("matrix dimensions do not fit")) + end + @isok ccall((:cholmod_l_updown, :libcholmod), Cint, + (Cint, Ptr{C_Sparse{Tv}}, Ptr{C_Factor{Tv}}, Ptr{Void}), + update, get(C.p), get(F.p), common()) + F +end + +#Helper functions for rank updates +lowrank_reorder(V::AbstractArray,p) = Sparse(sparse(V[p,:])) +lowrank_reorder(V::AbstractSparseArray,p) = Sparse(V[p,:]) + +""" + lowrankupdate!(F::Factor, C) + +Update an `LDLt` or `LLt` Factorization `F` of `A` to a factorization of `A + C*C'`. + +`LLt` factorizations are converted to `LDLt`. + +See also [`lowrankupdate`](@ref), [`lowrankdowndate`](@ref), [`lowrankdowndate!`](@ref). +""" +function lowrankupdate!{Tv<:VTypes}(F::Factor{Tv}, V::AbstractArray{Tv}) + #Reorder and copy V to account for permutation + C = lowrank_reorder(V, get_perm(F)) + lowrankupdowndate!(F, C, Cint(1)) +end + +""" + lowrankdowndate!(F::Factor, C) + +Update an `LDLt` or `LLt` Factorization `F` of `A` to a factorization of `A - C*C'`. + +`LLt` factorizations are converted to `LDLt`. + +See also [`lowrankdowndate`](@ref), [`lowrankupdate`](@ref), [`lowrankupdate!`](@ref). +""" +function lowrankdowndate!{Tv<:VTypes}(F::Factor{Tv}, V::AbstractArray{Tv}) + #Reorder and copy V to account for permutation + C = lowrank_reorder(V, get_perm(F)) + lowrankupdowndate!(F, C, Cint(0)) +end + +""" + lowrankupdate(F::Factor, C) -> FF::Factor + +Get an `LDLt` Factorization of `A + C*C'` given an `LDLt` or `LLt` factorization `F` of `A`. + +The returned factor is always an `LDLt` factorization. + +See also [`lowrankupdate!`](@ref), [`lowrankdowndate`](@ref), [`lowrankdowndate!`](@ref). +""" +lowrankupdate{Tv<:VTypes}(F::Factor{Tv}, V::AbstractArray{Tv}) = + lowrankupdate!(copy(F), V) + +""" + lowrankupdate(F::Factor, C) -> FF::Factor + +Get an `LDLt` Factorization of `A + C*C'` given an `LDLt` or `LLt` factorization `F` of `A`. + +The returned factor is always an `LDLt` factorization. + +See also [`lowrankdowndate!`](@ref), [`lowrankupdate`](@ref), [`lowrankupdate!`](@ref). +""" +lowrankdowndate{Tv<:VTypes}(F::Factor{Tv}, V::AbstractArray{Tv}) = + lowrankdowndate!(copy(F), V) + ## Solvers for (T, f) in ((:Dense, :solve), (:Sparse, :spsolve)) diff --git a/test/sparse/cholmod.jl b/test/sparse/cholmod.jl index 233472d287680..014fd6317b38c 100644 --- a/test/sparse/cholmod.jl +++ b/test/sparse/cholmod.jl @@ -701,3 +701,40 @@ end @test issparse((speye(2)*T(speye(2)))*speye(2)) end end + +#Test sparse low rank update for cholesky decomposion +A = SparseMatrixCSC{Float64,CHOLMOD.SuiteSparse_long}(10, 5, [1,3,6,8,10,13], [6,7,1,2,9,3,5,1,7,6,7,9], + [-0.138843, 2.99571, -0.556814, 0.669704, -1.39252, 1.33814, + 1.02371, -0.502384, 1.10686, 0.262229, -1.6935, 0.525239]) +AtA = A'*A; +C0 = [1., 2., 0, 0, 0] +#Test both cholfact and LDLt with and without automatic permutations +for F in (cholfact(AtA), cholfact(AtA, perm=1:5), ldltfact(AtA), ldltfact(AtA, perm=1:5)) + B0 = F\ones(5) + #Test both sparse/dense and vectors/matrices + for Ctest in (C0, sparse(C0), [C0 2*C0], sparse([C0 2*C0])) + C = copy(Ctest) + F1 = copy(F) + B = (AtA+C*C')\ones(5) + + #Test update + F11 = CHOLMOD.lowrankupdate(F1, C) + @test full(sparse(F11)) ≈ AtA+C*C' + @test F11\ones(5) ≈ B + #Make sure we get back the same factor again + F10 = CHOLMOD.lowrankdowndate(F11, C) + @test full(sparse(F10)) ≈ AtA + @test F10\ones(5) ≈ B0 + + #Test in-place update + CHOLMOD.lowrankupdate!(F1, C) + @test full(sparse(F1)) ≈ AtA+C*C' + @test F1\ones(5) ≈ B + #Test in-place downdate + CHOLMOD.lowrankdowndate!(F1, C) + @test full(sparse(F1)) ≈ AtA + @test F1\ones(5) ≈ B0 + + @test C == Ctest #Make sure C didn't change + end +end From 90ddad8323ee37de5f92f74e008ca243df131d7b Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Fri, 9 Jun 2017 16:50:53 -0700 Subject: [PATCH 1044/1534] Update the build logic for LLVM libcxx (#21792) This allows libc++ and libc++abi to be built on FreeBSD. However, these libraries still cannot be built with GCC nor on macOS, though that condition predates this change. --- Make.inc | 10 +++++-- deps/llvm.mk | 81 +++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 69 insertions(+), 22 deletions(-) diff --git a/Make.inc b/Make.inc index 06c3d17e29bff..4eb2e688f8661 100644 --- a/Make.inc +++ b/Make.inc @@ -1069,8 +1069,14 @@ endif # Custom libcxx ifeq ($(BUILD_CUSTOM_LIBCXX),1) LDFLAGS += -L$(build_libdir) -CXXLDFLAGS += -L$(build_libdir) -lc++abi -stdlib=libc++ -lc++ -CPPFLAGS += -I$(build_includedir)/c++/v1 +CXXLDFLAGS += -L$(build_libdir) -lc++abi -lc++ +ifeq ($(USECLANG),1) +CXXLDFLAGS += -stdlib=libc++ +else +ifeq ($(USEGCC),1) +$(error BUILD_CUSTOM_LIBCXX is currently only supported with Clang. Try setting BUILD_CUSTOM_LIBCXX=0) +endif +endif # Clang CUSTOM_LD_LIBRARY_PATH := LD_LIBRARY_PATH="$(build_libdir)" ifeq ($(USEICC),1) CXXFLAGS += -cxxlib-nostd -static-intel diff --git a/deps/llvm.mk b/deps/llvm.mk index e8ea59fcd72f4..6a8b8ad2ce380 100644 --- a/deps/llvm.mk +++ b/deps/llvm.mk @@ -179,6 +179,19 @@ LLVM_CPPFLAGS += -flto LLVM_LDFLAGS += -flto endif # LLVM_LTO +ifeq ($(BUILD_CUSTOM_LIBCXX),1) +LLVM_LDFLAGS += -Wl,-rpath,$(build_libdir) +LLVM_CPPFLAGS += -I$(build_includedir) +# We don't want to link to libc++ while trying to build it, so we define these +# flags separately so that we can still pass them to the main LLVM build +LLVM_LIBCXX_LDFLAGS := -lc++ -lc++abi +ifeq ($(USEICC),1) +LLVM_LDFLAGS += -no_cpprt +endif # USEICC +else +LLVM_LIBCXX_LDFLAGS := +endif # BUILD_CUSTOM_LIBCXX + ifneq ($(LLVM_CXXFLAGS),) LLVM_FLAGS += CXXFLAGS="$(LLVM_CXXFLAGS)" LLVM_MFLAGS += CXXFLAGS="$(LLVM_CXXFLAGS)" @@ -188,25 +201,16 @@ LLVM_FLAGS += CFLAGS="$(LLVM_CFLAGS)" LLVM_MFLAGS += CFLAGS="$(LLVM_CFLAGS)" endif # LLVM_CFLAGS -ifeq ($(BUILD_CUSTOM_LIBCXX),1) -LLVM_LDFLAGS += -Wl,-R$(build_libdir) -lc++ -lc++abi -ifeq ($(USEICC),1) -LLVM_LDFLAGS += -no_cpprt -endif # USEICC -endif # BUILD_CUSTOM_LIBCXX - ifneq ($(LLVM_CPPFLAGS),) LLVM_FLAGS += CPPFLAGS="$(LLVM_CPPFLAGS)" LLVM_MFLAGS += CPPFLAGS="$(LLVM_CPPFLAGS)" endif ifneq ($(LLVM_LDFLAGS),) -LLVM_FLAGS += LDFLAGS="$(LLVM_LDFLAGS)" -LLVM_MFLAGS += LDFLAGS="$(LLVM_LDFLAGS)" +LLVM_FLAGS += LDFLAGS="$(LLVM_LDFLAGS) $(LLVM_LIBCXX_LDFLAGS)" +LLVM_MFLAGS += LDFLAGS="$(LLVM_LDFLAGS) $(LLVM_LIBCXX_LDFLAGS)" endif LLVM_CMAKE += -DCMAKE_C_FLAGS="$(LLVM_CPPFLAGS) $(LLVM_CFLAGS)" \ - -DCMAKE_CXX_FLAGS="$(LLVM_CPPFLAGS) $(LLVM_CXXFLAGS)" \ - -DCMAKE_EXE_LINKER_FLAGS="$(LLVM_LDFLAGS)" \ - -DCMAKE_SHARED_LINKER_FLAGS="$(LLVM_LDFLAGS)" + -DCMAKE_CXX_FLAGS="$(LLVM_CPPFLAGS) $(LLVM_CXXFLAGS)" ifeq ($(BUILD_LLVM_CLANG),1) LLVM_MFLAGS += OPTIONAL_PARALLEL_DIRS=clang @@ -275,46 +279,83 @@ LLVM_FLAGS += --with-python="$(shell $(SRCDIR)/tools/find_python2)" ifeq ($(BUILD_CUSTOM_LIBCXX),1) +# Take a snapshot of the CMake flags before linking to -lc++ and -lc++abi +# These are added to the LLVM CMake flags further down +LLVM_CMAKE_LIBCXX := $(LLVM_CMAKE) \ + -DCMAKE_EXE_LINKER_FLAGS="$(LLVM_LDFLAGS)" \ + -DCMAKE_SHARED_LINKER_FLAGS="$(LLVM_LDFLAGS)" + ifeq ($(USEICC),1) LIBCXX_EXTRA_FLAGS := -Bstatic -lirc -Bdynamic endif +# These libraries require unwind.h from the libunwind dependency +ifeq ($(USE_SYSTEM_LIBUNWIND),0) +ifeq ($(OS),Darwin) +BUILT_UNWIND := $(build_prefix)/manifest/osxunwind +else +BUILT_UNWIND := $(build_prefix)/manifest/unwind +endif # Darwin +else +BUILT_UNWIND := +endif # Building libunwind + $(LLVM_SRC_DIR)/projects/libcxx: $(LLVM_LIBCXX_TAR) | $(LLVM_SRC_DIR)/source-extracted ([ ! -d $@ ] && \ git clone $(LLVM_GIT_URL_LIBCXX) $@ ) || \ (cd $@ && \ git pull --ff-only) -$(LLVM_SRC_DIR)/projects/libcxx/.git/HEAD: | $(LLVM_SRC_DIR)/projects/libcxx/.git/HEAD +$(LLVM_SRC_DIR)/projects/libcxx/.git/HEAD: | $(LLVM_SRC_DIR)/projects/libcxx $(LLVM_SRC_DIR)/projects/libcxxabi: $(LLVM_LIBCXXABI_TAR) | $(LLVM_SRC_DIR)/source-extracted ([ ! -d $@ ] && \ git clone $(LLVM_GIT_URL_LIBCXXABI) $@ ) || \ (cd $@ && \ git pull --ff-only) $(LLVM_SRC_DIR)/projects/libcxxabi/.git/HEAD: | $(LLVM_SRC_DIR)/projects/libcxxabi -$(LLVM_BUILD_DIR)/libcxx-build/Makefile: | $(LLVM_SRC_DIR)/projects/libcxx $(LLVM_SRC_DIR)/projects/libcxxabi +$(LLVM_BUILD_DIR)/libcxx-build/Makefile: | $(LLVM_SRC_DIR)/projects/libcxx $(LLVM_SRC_DIR)/projects/libcxxabi $(BUILT_UNWIND) mkdir -p $(dir $@) cd $(dir $@) && \ - $(CMAKE) -G "Unix Makefiles" $(CMAKE_COMMON) $(LLVM_CMAKE) -DLIBCXX_CXX_ABI=libcxxabi -DLIBCXX_CXX_ABI_INCLUDE_PATHS="$(LLVM_SRC_DIR)/projects/libcxxabi/include" $(LLVM_SRC_DIR)/projects/libcxx -DCMAKE_SHARED_LINKER_FLAGS="$(LDFLAGS) -L$(build_libdir) $(LIBCXX_EXTRA_FLAGS)" -$(LLVM_BUILD_DIR)/libcxxabi-build/Makefile: | $(LLVM_SRC_DIR)/projects/libcxxabi $(LLVM_SRC_DIR)/projects/libcxx + $(CMAKE) -G "Unix Makefiles" $(CMAKE_COMMON) $(LLVM_CMAKE_LIBCXX) -DLIBCXX_CXX_ABI=libcxxabi -DLIBCXX_CXX_ABI_INCLUDE_PATHS="$(LLVM_SRC_DIR)/projects/libcxxabi/include" $(LLVM_SRC_DIR)/projects/libcxx -DCMAKE_SHARED_LINKER_FLAGS="$(LDFLAGS) -L$(build_libdir) $(LIBCXX_EXTRA_FLAGS)" +$(LLVM_BUILD_DIR)/libcxxabi-build/Makefile: | $(LLVM_SRC_DIR)/projects/libcxxabi $(LLVM_SRC_DIR)/projects/libcxx $(BUILT_UNWIND) mkdir -p $(dir $@) cd $(dir $@) && \ - $(CMAKE) -G "Unix Makefiles" $(CMAKE_COMMON) $(LLVM_CMAKE) -DLLVM_ABI_BREAKING_CHECKS="WITH_ASSERTS" -DLLVM_PATH="$(LLVM_SRC_DIR)" $(LLVM_SRC_DIR)/projects/libcxxabi -DLIBCXXABI_CXX_ABI_LIBRARIES="$(LIBCXX_EXTRA_FLAGS)" -DCMAKE_CXX_FLAGS="$(LLVM_CPPFLAGS) $(LLVM_CXXFLAGS) -std=c++11" + $(CMAKE) -G "Unix Makefiles" $(CMAKE_COMMON) $(LLVM_CMAKE_LIBCXX) -DLLVM_ABI_BREAKING_CHECKS="WITH_ASSERTS" -DLLVM_PATH="$(LLVM_SRC_DIR)" $(LLVM_SRC_DIR)/projects/libcxxabi -DLIBCXXABI_CXX_ABI_LIBRARIES="$(LIBCXX_EXTRA_FLAGS)" -DCMAKE_CXX_FLAGS="$(LLVM_CPPFLAGS) $(LLVM_CXXFLAGS) -std=c++11" $(LLVM_BUILD_DIR)/libcxxabi-build/lib/libc++abi.so.1.0: $(LLVM_BUILD_DIR)/libcxxabi-build/Makefile $(LLVM_SRC_DIR)/projects/libcxxabi/.git/HEAD $(MAKE) -C $(LLVM_BUILD_DIR)/libcxxabi-build touch -c $@ $(build_libdir)/libc++abi.so.1.0: $(LLVM_BUILD_DIR)/libcxxabi-build/lib/libc++abi.so.1.0 $(MAKE) -C $(LLVM_BUILD_DIR)/libcxxabi-build install touch -c $@ + # Building this library installs these headers, which breaks other dependencies + -rm -rf $(build_includedir)/c++ $(LLVM_BUILD_DIR)/libcxx-build/lib/libc++.so.1.0: $(build_libdir)/libc++abi.so.1.0 $(LLVM_BUILD_DIR)/libcxx-build/Makefile $(LLVM_SRC_DIR)/projects/libcxx/.git/HEAD $(MAKE) -C $(LLVM_BUILD_DIR)/libcxx-build $(build_libdir)/libc++.so.1.0: $(LLVM_BUILD_DIR)/libcxx-build/lib/libc++.so.1.0 $(MAKE) -C $(LLVM_BUILD_DIR)/libcxx-build install touch -c $@ + # Building this library installs these headers, which breaks other dependencies + -rm -rf $(build_includedir)/c++ get-libcxx: $(LLVM_SRC_DIR)/projects/libcxx get-libcxxabi: $(LLVM_SRC_DIR)/projects/libcxxabi install-libcxxabi: $(build_libdir)/libc++abi.so.1.0 install-libcxx: $(build_libdir)/libc++.so.1.0 -endif +endif # BUILD_CUSTOM_LIBCXX + +# We want to be able to clean without having to pass BUILD_CUSTOM_LIBCXX=1, so define these +# outside of the conditional above +clean-libcxx: + -$(MAKE) -C $(LLVM_BUILD_DIR)/libcxx-build clean +clean-libcxxabi: + -$(MAKE) -C $(LLVM_BUILD_DIR)/libcxxabi-build clean +distclean-libcxx: + -rm -rf $(LLVM_LIBCXX_TAR) $(LLVM_SRC_DIR)/projects/libcxx $(LLVM_BUILD_DIR)/libcxx-build +distclean-libcxxabi: + -rm -rf $(LLVM_LIBCXXABI_TAR) $(LLVM_SRC_DIR)/projects/libcxxabi $(LLVM_BUILD_DIR)/libcxxabi-build + +# We want to ensure that the libcxx linking flags don't get passed to the libcxx build, since it will +# error on a fresh build +LLVM_CMAKE += -DCMAKE_EXE_LINKER_FLAGS="$(LLVM_LDFLAGS) $(LLVM_LIBCXX_LDFLAGS)" \ + -DCMAKE_SHARED_LINKER_FLAGS="$(LLVM_LDFLAGS) $(LLVM_LIBCXX_LDFLAGS)" ifeq ($(BUILD_CUSTOM_LIBCXX),1) LIBCXX_DEPENDENCY := $(build_libdir)/libc++abi.so.1.0 $(build_libdir)/libc++.so.1.0 @@ -573,11 +614,11 @@ endif # LLVM_USE_CMAKE $(eval $(call staged-install,llvm,llvm-$$(LLVM_VER)/build_$$(LLVM_BUILDTYPE), \ LLVM_INSTALL,,,)) -clean-llvm: +clean-llvm: clean-libcxx clean-libcxxabi -rm $(LLVM_BUILDDIR_withtype)/build-configured $(LLVM_BUILDDIR_withtype)/build-compiled -$(MAKE) -C $(LLVM_BUILDDIR_withtype) clean -distclean-llvm: +distclean-llvm: distclean-libcxx distclean-libcxxabi -rm -rf $(LLVM_TAR) $(LLVM_CLANG_TAR) \ $(LLVM_COMPILER_RT_TAR) $(LLVM_LIBCXX_TAR) $(LLVM_LLDB_TAR) \ $(LLVM_SRC_DIR) $(LLVM_BUILDDIR_withtype) From ff3a9aae6f847c9355e053d9b053140ce023a651 Mon Sep 17 00:00:00 2001 From: Simon Date: Sat, 10 Jun 2017 07:49:40 +0200 Subject: [PATCH 1045/1534] convert twiceprecision to arbitrary number (#22270) --- base/twiceprecision.jl | 2 +- test/ranges.jl | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/base/twiceprecision.jl b/base/twiceprecision.jl index 3cfc2b89854b5..1736db0abf23f 100644 --- a/base/twiceprecision.jl +++ b/base/twiceprecision.jl @@ -71,7 +71,7 @@ convert(::Type{TwicePrecision{T}}, x::TwicePrecision{T}) where {T} = x convert(::Type{TwicePrecision{T}}, x::TwicePrecision) where {T} = TwicePrecision{T}(convert(T, x.hi), convert(T, x.lo)) -convert(::Type{T}, x::TwicePrecision{T}) where {T<:Number} = convert(T, x.hi + x.lo) +convert(::Type{T}, x::TwicePrecision) where {T<:Number} = convert(T, x.hi + x.lo) convert(::Type{TwicePrecision{T}}, x::Number) where {T} = TwicePrecision{T}(convert(T, x), zero(T)) float(x::TwicePrecision{<:AbstractFloat}) = x diff --git a/test/ranges.jl b/test/ranges.jl index a45018f44bbba..506c030db9a33 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -911,3 +911,10 @@ using TestHelpers.Furlong @test collect(Furlong(2):Furlong(1):Furlong(10)) == collect(range(Furlong(2),Furlong(1),9)) == Furlong.(2:10) @test collect(Furlong(1.0):Furlong(0.5):Furlong(10.0)) == collect(Furlong(1):Furlong(0.5):Furlong(10)) == Furlong.(1:0.5:10) + +# issue #22270 +let linsp = linspace(1.0, 2.0, 10) + @test typeof(linsp.ref) == Base.TwicePrecision{Float64} + @test Float32(linsp.ref) === convert(Float32, linsp.ref) + @test Float32(linsp.ref) ≈ linsp.ref.hi + linsp.ref.lo +end From f91d54fd92ae4093780f319d3adbb8a436ed0a2e Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 9 Jun 2017 09:28:07 +0200 Subject: [PATCH 1046/1534] Fix inInference state corruption. This led to non-idempotent irgen. --- src/gf.c | 2 +- test/inference.jl | 7 +++++++ test/staged.jl | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/gf.c b/src/gf.c index bea84f33f0f2e..800901649870b 100644 --- a/src/gf.c +++ b/src/gf.c @@ -262,7 +262,7 @@ jl_code_info_t *jl_type_infer(jl_method_instance_t **pli, size_t world, int forc li->inInference = 1; jl_svec_t *linfo_src_rettype = (jl_svec_t*)jl_apply_with_saved_exception_state(fargs, 3, 0); ptls->world_age = last_age; - assert((jl_is_method(li->def.method) || li->inInference == 0) && "inference failed on a toplevel expr"); + li->inInference = 0; jl_code_info_t *src = NULL; if (linfo_src_rettype && diff --git a/test/inference.jl b/test/inference.jl index 8bcd6bf4d4aae..54a77e4737cfd 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -856,3 +856,10 @@ let f, m ] @test @inferred(f()) == 6 end + +# issue #22290 +f22290() = return nothing +for i in 1:3 + ir = sprint(io->code_llvm(io, f22290, Tuple{})) + @test contains(ir, "julia_f22290") +end diff --git a/test/staged.jl b/test/staged.jl index ba62fc2d91816..e81f4b42a6cb4 100644 --- a/test/staged.jl +++ b/test/staged.jl @@ -174,7 +174,7 @@ let gf_err, tsk = @async nothing # create a Task for yield to try to run end @test_throws ErrorException gf_err() @test_throws ErrorException gf_err() - @test gf_err_ref[] == 3 + @test gf_err_ref[] == 4 end gf_err_ref[] = 0 From ee9d28b199be88bafb69feacc887d4a8464d4376 Mon Sep 17 00:00:00 2001 From: Antoine Levitt Date: Sat, 10 Jun 2017 04:17:19 -0700 Subject: [PATCH 1047/1534] isapprox between matrices and UniformScaling (#22237) * isapprox between matrices and UniformScaling --- base/linalg/uniformscaling.jl | 9 +++++++++ test/linalg/uniformscaling.jl | 6 ++++++ 2 files changed, 15 insertions(+) diff --git a/base/linalg/uniformscaling.jl b/base/linalg/uniformscaling.jl index bbb1dfa46e793..bb1c3d679434a 100644 --- a/base/linalg/uniformscaling.jl +++ b/base/linalg/uniformscaling.jl @@ -144,6 +144,7 @@ function (-)(J::UniformScaling{TJ}, A::AbstractMatrix{TA}) where {TA,TJ<:Number} end inv(J::UniformScaling) = UniformScaling(inv(J.λ)) +norm(J::UniformScaling, p::Real=2) = abs(J.λ) *(J1::UniformScaling, J2::UniformScaling) = UniformScaling(J1.λ*J2.λ) *(B::BitArray{2}, J::UniformScaling) = *(Array(B), J::UniformScaling) @@ -177,6 +178,14 @@ function isapprox(J1::UniformScaling{T}, J2::UniformScaling{S}; rtol::Real=Base.rtoldefault(T,S), atol::Real=0, nans::Bool=false) where {T<:Number,S<:Number} isapprox(J1.λ, J2.λ, rtol=rtol, atol=atol, nans=nans) end +function isapprox(J::UniformScaling,A::AbstractMatrix; + rtol::Real=rtoldefault(promote_leaf_eltypes(A),eltype(J)), + atol::Real=0, nans::Bool=false, norm::Function=vecnorm) + n = checksquare(A) + Jnorm = norm === vecnorm ? abs(J.λ)*sqrt(n) : (norm === Base.norm ? abs(J.λ) : norm(diagm(fill(J.λ, n)))) + return norm(A - J) <= atol + rtol*max(norm(A), Jnorm) +end +isapprox(A::AbstractMatrix,J::UniformScaling;kwargs...) = isapprox(J,A;kwargs...) function copy!(A::AbstractMatrix, J::UniformScaling) size(A,1)==size(A,2) || throw(DimensionMismatch("a UniformScaling can only be copied to a square matrix")) diff --git a/test/linalg/uniformscaling.jl b/test/linalg/uniformscaling.jl index f61bdef3f4dad..2eba997a031ad 100644 --- a/test/linalg/uniformscaling.jl +++ b/test/linalg/uniformscaling.jl @@ -18,6 +18,7 @@ srand(123) @test -one(UniformScaling(2)) == UniformScaling(-1) @test sparse(3I,4,5) == spdiagm(fill(3,4),0,4,5) @test sparse(3I,5,4) == spdiagm(fill(3,4),0,5,4) + @test norm(UniformScaling(1+im)) ≈ sqrt(2) end @testset "istriu, istril, issymmetric, ishermitian, isapprox" begin @@ -29,6 +30,11 @@ end @test !ishermitian(UniformScaling(complex(1.0,1.0))) @test UniformScaling(4.00000000000001) ≈ UniformScaling(4.0) @test UniformScaling(4.32) ≈ UniformScaling(4.3) rtol=0.1 atol=0.01 + @test UniformScaling(4.32) ≈ 4.3*eye(2) rtol=0.1 atol=0.01 + @test UniformScaling(4.32) ≈ 4.3*eye(2) rtol=0.1 atol=0.01 norm=norm + @test 4.3*eye(2) ≈ UniformScaling(4.32) rtol=0.1 atol=0.01 + @test [4.3201 0.002;0.001 4.32009] ≈ UniformScaling(4.32) rtol=0.1 atol=0. + @test UniformScaling(4.32) ≉ 4.3*ones(2,2) rtol=0.1 atol=0.01 end @testset "* and / with number" begin From 3f3d8b338b25ea68eadc073e883850a8d252ecd8 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Wed, 7 Jun 2017 10:05:00 -0400 Subject: [PATCH 1048/1534] Treat sub and div as induction in simd loop lowering This makes sure induction like ```julia s -= a[i] ``` in an at-simd loop can be vectorized without fastmath annotation. LLVM currently support at least sub in the vectorizer. I don't see why it can't handle div so let's first make sure we are ready for that. --- src/llvm-simdloop.cpp | 34 ++++++++++++++++++++++++++++------ test/llvmpasses/simdloop.ll | 22 ++++++++++++++++++++-- 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/src/llvm-simdloop.cpp b/src/llvm-simdloop.cpp index 14305a1db28eb..58da4b57163a8 100644 --- a/src/llvm-simdloop.cpp +++ b/src/llvm-simdloop.cpp @@ -67,13 +67,15 @@ struct LowerSIMDLoop: public LoopPass { LowerSIMDLoop() : LoopPass(ID) {} private: - /*override*/ bool runOnLoop(Loop *, LPPassManager &LPM); + bool runOnLoop(Loop *, LPPassManager &LPM) override; /// Check if loop has "simd_loop" annotation. /// If present, the annotation is an MDNode attached to an instruction in the loop's latch. bool hasSIMDLoopMetadata( Loop *L) const; - /// If Phi is part of a reduction cycle of FAdd or FMul, mark the ops as permitting reassociation/commuting. + /// If Phi is part of a reduction cycle of FAdd, FSub, FMul or FDiv, + /// mark the ops as permitting reassociation/commuting. + /// As of LLVM 4.0, FDiv is not handled by the loop vectorizer void enableUnsafeAlgebraIfReduction(PHINode *Phi, Loop *L) const; }; @@ -87,6 +89,26 @@ bool LowerSIMDLoop::hasSIMDLoopMetadata(Loop *L) const return false; } +static unsigned getReduceOpcode(Instruction *J, Instruction *operand) +{ + switch (J->getOpcode()) { + case Instruction::FSub: + if (J->getOperand(0) != operand) + return 0; + JL_FALLTHROUGH; + case Instruction::FAdd: + return Instruction::FAdd; + case Instruction::FDiv: + if (J->getOperand(0) != operand) + return 0; + JL_FALLTHROUGH; + case Instruction::FMul: + return Instruction::FMul; + default: + return 0; + } +} + void LowerSIMDLoop::enableUnsafeAlgebraIfReduction(PHINode *Phi, Loop *L) const { typedef SmallVector chainVector; @@ -115,21 +137,21 @@ void LowerSIMDLoop::enableUnsafeAlgebraIfReduction(PHINode *Phi, Loop *L) const DEBUG(dbgs() << "LSL: chain prematurely terminated at " << *I << "\n"); return; } - if (J==Phi) { + if (J == Phi) { // Found the entire chain. break; } if (opcode) { // Check that arithmetic op matches prior arithmetic ops in the chain. - if (J->getOpcode()!=opcode) { + if (getReduceOpcode(J, I) != opcode) { DEBUG(dbgs() << "LSL: chain broke at " << *J << " because of wrong opcode\n"); return; } } else { // First arithmetic op in the chain. - opcode = J->getOpcode(); - if (opcode!=Instruction::FAdd && opcode!=Instruction::FMul) { + opcode = getReduceOpcode(J, I); + if (!opcode) { DEBUG(dbgs() << "LSL: first arithmetic op in chain is uninteresting" << *J << "\n"); return; } diff --git a/test/llvmpasses/simdloop.ll b/test/llvmpasses/simdloop.ll index 812e71f154895..50b7a132a6a74 100644 --- a/test/llvmpasses/simdloop.ll +++ b/test/llvmpasses/simdloop.ll @@ -8,8 +8,8 @@ loop: %aptr = getelementptr double, double *%a, i64 %i %bptr = getelementptr double, double *%b, i64 %i ; CHECK: llvm.mem.parallel_loop_access - %aval = load double, double *%aptr - %bval = load double, double *%aptr + %aval = load double, double *%aptr + %bval = load double, double *%aptr %cval = fadd double %aval, %bval store double %cval, double *%bptr %nexti = add i64 %i, 1, !simd_loop !1 @@ -19,4 +19,22 @@ loopdone: ret void } +define double @simd_test_sub(double *%a) { +top: + br label %loop +loop: + %i = phi i64 [0, %top], [%nexti, %loop] + %v = phi double [0.000000e+00, %top], [%nextv, %loop] + %aptr = getelementptr double, double *%a, i64 %i +; CHECK: llvm.mem.parallel_loop_access + %aval = load double, double *%aptr + %nextv = fsub double %v, %aval +; CHECK: fsub fast double %v, %aval + %nexti = add i64 %i, 1, !simd_loop !1 + %done = icmp sgt i64 %nexti, 500 + br i1 %done, label %loopdone, label %loop +loopdone: + ret double %nextv +} + !1 = !{} From c656333ca7ed0b2dfe191830915f261e42b4ca51 Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sat, 10 Jun 2017 12:48:10 -0700 Subject: [PATCH 1049/1534] Make vcat of Vectors with SparseVectors yield SparseVector (#22225). (#22299) --- base/sparse/sparsevector.jl | 6 ++++++ test/linalg/special.jl | 3 +++ 2 files changed, 9 insertions(+) diff --git a/base/sparse/sparsevector.jl b/base/sparse/sparsevector.jl index f9c9d38d1b624..65372a911e20a 100644 --- a/base/sparse/sparsevector.jl +++ b/base/sparse/sparsevector.jl @@ -906,6 +906,12 @@ end hcat(Xin::Union{Vector, AbstractSparseVector}...) = hcat(map(sparse, Xin)...) vcat(Xin::Union{Vector, AbstractSparseVector}...) = vcat(map(sparse, Xin)...) +# Without the following method, vertical concatenations of SparseVectors with Vectors +# fall back to the vertical concatenation method that ensures that combinations of +# sparse/special/dense matrix/vector types concatenate to SparseMatrixCSCs (because +# the vcat method immediately above is less specific, being defined in AbstractSparseVector +# rather than SparseVector). +vcat(X::Union{Vector,SparseVector}...) = vcat(map(sparse, X)...) ### Concatenation of un/annotated sparse/special/dense vectors/matrices diff --git a/test/linalg/special.jl b/test/linalg/special.jl index 3d58d5f89cc2a..2301ce9cdc22d 100644 --- a/test/linalg/special.jl +++ b/test/linalg/special.jl @@ -247,3 +247,6 @@ let end end end +@testset "vcat of Vectors with SparseVectors should yield SparseVector (#22225)" begin + @test isa((@inferred vcat(Float64[], spzeros(1))), SparseVector) +end From 0b2f6de87ea950c7511048239df4688ccc24b5ed Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 9 Jun 2017 10:28:19 -0400 Subject: [PATCH 1050/1534] fix bug in setting `ninitialized` of vararg tuples --- src/jltypes.c | 4 +++- test/tuple.jl | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/jltypes.c b/src/jltypes.c index c292cae8e523e..34ef0c3160547 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -1058,7 +1058,9 @@ static jl_value_t *inst_datatype(jl_datatype_t *dt, jl_svec_t *p, jl_value_t **i JL_GC_PUSH2(&p, &ndt); jl_value_t *last = iparams[ntp - 1]; + int isvatuple = 0; if (istuple && ntp > 0 && jl_is_vararg_type(last)) { + isvatuple = 1; // normalize Tuple{..., Vararg{Int, 3}} to Tuple{..., Int, Int, Int} jl_value_t *va = jl_unwrap_unionall(last); jl_value_t *va0 = jl_tparam0(va), *va1 = jl_tparam1(va); @@ -1185,7 +1187,7 @@ static jl_value_t *inst_datatype(jl_datatype_t *dt, jl_svec_t *p, jl_value_t **i } } if (istuple) - ndt->ninitialized = ntp; + ndt->ninitialized = ntp - isvatuple; else ndt->ninitialized = dt->ninitialized; diff --git a/test/tuple.jl b/test/tuple.jl index 2385e52a9ef4f..cbe3ccd205e3f 100644 --- a/test/tuple.jl +++ b/test/tuple.jl @@ -260,3 +260,9 @@ end for n = 0:15 @test ntuple(identity, Val{n}) == ntuple(identity, n) end + +# Tuple type ninitialized +@test Tuple{Int,Any}.ninitialized == 2 +@test Tuple.ninitialized == 0 +@test Tuple{Int,Vararg{Any}}.ninitialized == 1 +@test Tuple{Any,Any,Vararg{Any}}.ninitialized == 2 From 2d1d1ae1c5a41b45d1d489dcf10a24aaeb0cd61d Mon Sep 17 00:00:00 2001 From: Oscar Blumberg Date: Thu, 8 Jun 2017 21:57:46 -0400 Subject: [PATCH 1051/1534] add constant inference of `isdefined` --- base/inference.jl | 44 ++++++++++++++++++++++++++++++++++++++++++-- test/inference.jl | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 2 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index cfc4205e02931..a9829626bed31 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -543,7 +543,47 @@ add_tfunc(===, 2, 2, end return Bool end) -add_tfunc(isdefined, 1, 2, (args...)->Bool) +function isdefined_tfunc(args...) + arg1 = args[1] + if isa(arg1, Const) + a1 = typeof(arg1.val) + else + a1 = widenconst(arg1) + end + if isType(a1) + return Bool + end + a1 = unwrap_unionall(a1) + if isa(a1, DataType) && !a1.abstract + if a1 <: Array # TODO update when deprecation is removed + elseif a1 === Module + length(args) == 2 || return Bottom + sym = args[2] + Symbol <: widenconst(sym) || return Bottom + if isa(sym, Const) && isa(sym.val, Symbol) && isa(arg1, Const) && isdefined(arg1.val, sym.val) + return Const(true) + end + elseif length(args) == 2 && isa(args[2], Const) + val = args[2].val + idx::Int = 0 + if isa(val, Symbol) + idx = fieldindex(a1, val, false) + elseif isa(val, Int) + idx = val + else + return Bottom + end + if 1 <= idx <= a1.ninitialized + return Const(true) + elseif idx <= 0 || (idx > nfields(a1) && !isvatuple(a1)) + return Const(false) + end + end + end + Bool +end +# TODO change IInf to 2 when deprecation is removed +add_tfunc(isdefined, 1, IInf, isdefined_tfunc) add_tfunc(Core.sizeof, 1, 1, x->Int) add_tfunc(nfields, 1, 1, function (x::ANY) @@ -3419,7 +3459,7 @@ end const _pure_builtins = Any[tuple, svec, fieldtype, apply_type, ===, isa, typeof, UnionAll, nfields] # known effect-free calls (might not be affect-free) -const _pure_builtins_volatile = Any[getfield, arrayref] +const _pure_builtins_volatile = Any[getfield, arrayref, isdefined] function is_pure_intrinsic(f::IntrinsicFunction) return !(f === Intrinsics.pointerref || # this one is volatile diff --git a/test/inference.jl b/test/inference.jl index 54a77e4737cfd..542f5fb032e3e 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -863,3 +863,50 @@ for i in 1:3 ir = sprint(io->code_llvm(io, f22290, Tuple{})) @test contains(ir, "julia_f22290") end + +# constant inference of isdefined +let f(x) = isdefined(x, 2) ? 1 : "" + @test Base.return_types(f, (Tuple{Int,Int},)) == Any[Int] + @test Base.return_types(f, (Tuple{Int,},)) == Any[String] +end +let f(x) = isdefined(x, :re) ? 1 : "" + @test Base.return_types(f, (Complex64,)) == Any[Int] + @test Base.return_types(f, (Complex,)) == Any[Int] +end +let f(x) = isdefined(x, :NonExistentField) ? 1 : "" + @test Base.return_types(f, (Complex64,)) == Any[String] + @test Union{Int,String} <: Base.return_types(f, (AbstractArray,))[1] +end +import Core.Inference: Const, isdefined_tfunc, ⊑ +@test isdefined_tfunc(Complex64, Const(())) === Union{} +@test isdefined_tfunc(Complex64, Const(1)) === Const(true) +@test isdefined_tfunc(Complex64, Const(2)) === Const(true) +@test isdefined_tfunc(Complex64, Const(3)) === Const(false) +@test isdefined_tfunc(Complex64, Const(0)) === Const(false) +mutable struct SometimesDefined + x + function SometimesDefined() + v = new() + if rand(Bool) + v.x = 0 + end + return v + end +end +@test isdefined_tfunc(SometimesDefined, Const(:x)) == Bool +@test isdefined_tfunc(SometimesDefined, Const(:y)) === Const(false) +@test isdefined_tfunc(Const(Base), Const(:length)) === Const(true) +@test isdefined_tfunc(Const(Base), Symbol) == Bool +@test isdefined_tfunc(Const(Base), Const(:NotCurrentlyDefinedButWhoKnows)) == Bool +@test isdefined_tfunc(SimpleVector, Const(1)) === Const(true) +@test isdefined_tfunc(SimpleVector, Const(:length)) === Const(true) +@test Const(false) ⊑ isdefined_tfunc(Const(:x), Symbol) +@test Const(false) ⊑ isdefined_tfunc(Const(:x), Const(:y)) +@test isdefined_tfunc(Vector{Int}, Const(1)) == Bool +@test isdefined_tfunc(Vector{Any}, Const(1)) == Bool +@test isdefined_tfunc(Module, Any, Any) === Union{} +@test isdefined_tfunc(Module, Int) === Union{} +@test isdefined_tfunc(Tuple{Any,Vararg{Any}}, Const(0)) === Const(false) +@test isdefined_tfunc(Tuple{Any,Vararg{Any}}, Const(1)) === Const(true) +@test isdefined_tfunc(Tuple{Any,Vararg{Any}}, Const(2)) === Bool +@test isdefined_tfunc(Tuple{Any,Vararg{Any}}, Const(3)) === Bool From b1de9e5cbe69c777b72ff52afdcc915487d9ab9e Mon Sep 17 00:00:00 2001 From: Sacha Verweij Date: Sat, 10 Jun 2017 14:18:17 -0700 Subject: [PATCH 1052/1534] Make vcat of SparseVectors with different el- and/or ind-type yield SparseVector (#22225). (#22301) --- base/sparse/sparsevector.jl | 5 +++++ test/sparse/sparsevector.jl | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/base/sparse/sparsevector.jl b/base/sparse/sparsevector.jl index 65372a911e20a..0a540f21d4252 100644 --- a/base/sparse/sparsevector.jl +++ b/base/sparse/sparsevector.jl @@ -876,6 +876,11 @@ end # of _absspvec_vcat below. The <:Integer qualifications are necessary for correct dispatch. vcat(X::SparseVector{Tv,Ti}...) where {Tv,Ti<:Integer} = _absspvec_vcat(X...) vcat(X::AbstractSparseVector{Tv,Ti}...) where {Tv,Ti<:Integer} = _absspvec_vcat(X...) +function vcat(X::SparseVector...) + commeltype = promote_type(map(eltype, X)...) + commindtype = promote_type(map(indtype, X)...) + vcat(map(x -> SparseVector{commeltype,commindtype}(x), X)...) +end function _absspvec_vcat(X::AbstractSparseVector{Tv,Ti}...) where {Tv,Ti} # check sizes n = length(X) diff --git a/test/sparse/sparsevector.jl b/test/sparse/sparsevector.jl index 77024341a19ba..4ea50dc01a367 100644 --- a/test/sparse/sparsevector.jl +++ b/test/sparse/sparsevector.jl @@ -474,7 +474,12 @@ let N = 4 @test issparse(cat((1,2), densemat, diagmat, spmat, densevec, spvec)) @test issparse(cat((1,2), spvec, diagmat, densevec, spmat, densemat)) end - +@testset "vertical concatenation of SparseVectors with different el- and ind-type (#22225)" begin + spv6464 = SparseVector(0, Int64[], Int64[]) + @test isa(vcat(spv6464, SparseVector(0, Int64[], Int32[])), SparseVector{Int64,Int64}) + @test isa(vcat(spv6464, SparseVector(0, Int32[], Int64[])), SparseVector{Int64,Int64}) + @test isa(vcat(spv6464, SparseVector(0, Int32[], Int32[])), SparseVector{Int64,Int64}) +end ## sparsemat: combinations with sparse matrix From 453ddf005396aacb3c4b1c387fd9e9eb4b657a19 Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Sat, 10 Jun 2017 16:00:39 -0700 Subject: [PATCH 1053/1534] Add jl_has_so_reuseport to check whether SO_REUSEPORT is defined (#22303) Without this, the best proxy is to condition on the OS, which is less reliable and may not properly cover all cases. --- base/distributed/managers.jl | 14 +++++++------- src/jl_uv.c | 11 ++++++++++- test/distributed_exec.jl | 13 ++++--------- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/base/distributed/managers.jl b/base/distributed/managers.jl index c5e4fd24515c8..d32da4d90c765 100644 --- a/base/distributed/managers.jl +++ b/base/distributed/managers.jl @@ -455,22 +455,22 @@ end const client_port = Ref{Cushort}(0) function socket_reuse_port() - @static if is_linux() || is_apple() + if ccall(:jl_has_so_reuseport, Int32, ()) == 1 s = TCPSocket(delay = false) - # Linux requires the port to be bound before setting REUSEPORT, OSX after. - is_linux() && bind_client_port(s) + # Some systems (e.g. Linux) require the port to be bound before setting REUSEPORT + bind_early = is_linux() + + bind_early && bind_client_port(s) rc = ccall(:jl_tcp_reuseport, Int32, (Ptr{Void},), s.handle) - if rc > 0 # SO_REUSEPORT is unsupported, just return the ephemerally bound socket - return s - elseif rc < 0 + if rc < 0 # This is an issue only on systems with lots of client connections, hence delay the warning nworkers() > 128 && warn_once("Error trying to reuse client port number, falling back to regular socket.") # provide a clean new socket return TCPSocket() end - is_apple() && bind_client_port(s) + bind_early || bind_client_port(s) return s else return TCPSocket() diff --git a/src/jl_uv.c b/src/jl_uv.c index 8b246d658af38..2aaea64c5987b 100644 --- a/src/jl_uv.c +++ b/src/jl_uv.c @@ -823,6 +823,15 @@ JL_DLLEXPORT int jl_tcp_quickack(uv_tcp_t *handle, int on) #endif +JL_DLLEXPORT int jl_has_so_reuseport(void) +{ +#if defined(SO_REUSEPORT) + return 1; +#else + return 0; +#endif +} + JL_DLLEXPORT int jl_tcp_reuseport(uv_tcp_t *handle) { #if defined(SO_REUSEPORT) @@ -833,7 +842,7 @@ JL_DLLEXPORT int jl_tcp_reuseport(uv_tcp_t *handle) } return 0; #else - return 1; + return -1; #endif } diff --git a/test/distributed_exec.jl b/test/distributed_exec.jl index d54763101d6dd..402948cf96ec4 100644 --- a/test/distributed_exec.jl +++ b/test/distributed_exec.jl @@ -48,15 +48,10 @@ end # Test that the client port is reused. SO_REUSEPORT may not be supported on # all UNIX platforms, Linux kernels prior to 3.9 and older versions of OSX -if is_unix() - # Run reuse client port tests only if SO_REUSEPORT is supported. - s = TCPSocket(delay = false) - is_linux() && Base.Distributed.bind_client_port(s) - if ccall(:jl_tcp_reuseport, Int32, (Ptr{Void},), s.handle) == 0 - reuseport_tests() - else - info("SO_REUSEPORT is unsupported, skipping reuseport tests.") - end +if ccall(:jl_has_so_reuseport, Int32, ()) == 1 + reuseport_tests() +else + info("SO_REUSEPORT is unsupported, skipping reuseport tests.") end id_me = myid() From 2b03ba8cd21d192b80527454502d09fe827234ec Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Fri, 9 Jun 2017 16:59:52 +0200 Subject: [PATCH 1054/1534] random.jl: allow Integer instead of Int in few signatures --- base/random.jl | 18 +++++++++--------- test/random.jl | 8 +++++--- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/base/random.jl b/base/random.jl index 74f91f7c4d76b..e6f795b75378d 100644 --- a/base/random.jl +++ b/base/random.jl @@ -277,9 +277,9 @@ julia> rand(MersenneTwister(0), Dict(1=>2, 3=>4)) @inline rand() = rand(GLOBAL_RNG, CloseOpen) @inline rand(T::Type) = rand(GLOBAL_RNG, T) rand(dims::Dims) = rand(GLOBAL_RNG, dims) -rand(dims::Integer...) = rand(convert(Tuple{Vararg{Int}}, dims)) +rand(dims::Integer...) = rand(convert(Dims, dims)) rand(T::Type, dims::Dims) = rand(GLOBAL_RNG, T, dims) -rand(T::Type, d1::Integer, dims::Integer...) = rand(T, tuple(Int(d1), convert(Tuple{Vararg{Int}}, dims)...)) +rand(T::Type, d1::Integer, dims::Integer...) = rand(T, tuple(Int(d1), convert(Dims, dims)...)) rand!(A::AbstractArray) = rand!(GLOBAL_RNG, A) rand(r::AbstractArray) = rand(GLOBAL_RNG, r) @@ -296,7 +296,7 @@ but without allocating a new array. rand!(A::AbstractArray, r::AbstractArray) = rand!(GLOBAL_RNG, A, r) rand(r::AbstractArray, dims::Dims) = rand(GLOBAL_RNG, r, dims) -rand(r::AbstractArray, dims::Integer...) = rand(GLOBAL_RNG, r, convert(Tuple{Vararg{Int}}, dims)) +rand(r::AbstractArray, dims::Integer...) = rand(GLOBAL_RNG, r, convert(Dims, dims)) ## random floating point values @@ -383,10 +383,10 @@ rand(s::IntSet) = rand(GLOBAL_RNG, s) ## Arrays of random numbers rand(r::AbstractRNG, dims::Dims) = rand(r, Float64, dims) -rand(r::AbstractRNG, dims::Integer...) = rand(r, convert(Tuple{Vararg{Int}}, dims)) +rand(r::AbstractRNG, dims::Integer...) = rand(r, convert(Dims, dims)) rand(r::AbstractRNG, T::Type, dims::Dims) = rand!(r, Array{T}(dims)) -rand(r::AbstractRNG, T::Type, d1::Integer, dims::Integer...) = rand(r, T, tuple(Int(d1), convert(Tuple{Vararg{Int}}, dims)...)) +rand(r::AbstractRNG, T::Type, d1::Integer, dims::Integer...) = rand(r, T, tuple(Int(d1), convert(Dims, dims)...)) # note: the above method would trigger an ambiguity warning if d1 was not separated out: # rand(r, ()) would match both this method and rand(r, dims::Dims) # moreover, a call like rand(r, NotImplementedType()) would be an infinite loop @@ -413,7 +413,7 @@ rand(r::AbstractRNG, s::Dict{K,V}, dims::Dims) where {K,V} = rand!(r, Array{Pair rand(r::AbstractRNG, s::Set{T}, dims::Dims) where {T} = rand!(r, Array{T}(dims), s) rand(r::AbstractRNG, s::IntSet, dims::Dims) = rand!(r, Array{Int}(dims), s) rand(r::AbstractRNG, s::Union{Dict,Set,IntSet}, dims::Integer...) = rand(r, s, convert(Dims, dims)) -rand(s::Union{Dict,Set,IntSet}, dims::Integer...) = rand(GLOBAL_RNG, s, dims) +rand(s::Union{Dict,Set,IntSet}, dims::Integer...) = rand(GLOBAL_RNG, s, convert(Dims, dims)) rand(s::Union{Dict,Set,IntSet}, dims::Dims) = rand(GLOBAL_RNG, s, dims) # MersenneTwister @@ -687,7 +687,7 @@ function rand!(rng::AbstractRNG, A::AbstractArray, r::AbstractArray) end rand(rng::AbstractRNG, r::AbstractArray{T}, dims::Dims) where {T} = rand!(rng, Array{T}(dims), r) -rand(rng::AbstractRNG, r::AbstractArray, dims::Int...) = rand(rng, r, dims) +rand(rng::AbstractRNG, r::AbstractArray, dims::Integer...) = rand(rng, r, convert(Dims, dims)) ## random BitArrays (AbstractRNG) @@ -705,10 +705,10 @@ end Generate a `BitArray` of random boolean values. """ bitrand(r::AbstractRNG, dims::Dims) = rand!(r, BitArray(dims)) -bitrand(r::AbstractRNG, dims::Int...) = rand!(r, BitArray(dims)) +bitrand(r::AbstractRNG, dims::Integer...) = rand!(r, BitArray(convert(Dims, dims))) bitrand(dims::Dims) = rand!(BitArray(dims)) -bitrand(dims::Int...) = rand!(BitArray(dims)) +bitrand(dims::Integer...) = rand!(BitArray(convert(Dims, dims))) ## randn() - Normally distributed random numbers using Ziggurat algorithm diff --git a/test/random.jl b/test/random.jl index 4c21e355bc45a..6752a68e65c15 100644 --- a/test/random.jl +++ b/test/random.jl @@ -341,9 +341,10 @@ for rng in ([], [MersenneTwister(0)], [RandomDevice()]) a0 = rand(rng..., C) ::T a1 = rand(rng..., C, 5) ::Vector{T} a2 = rand(rng..., C, 2, 3) ::Array{T, 2} - a3 = rand!(rng..., Array{T}(5), C) ::Vector{T} - a4 = rand!(rng..., Array{T}(2, 3), C) ::Array{T, 2} - for a in [a0, a1..., a2..., a3..., a4...] + a3 = rand(rng..., C, b2, u3) ::Array{T, 2} + a4 = rand!(rng..., Array{T}(5), C) ::Vector{T} + a5 = rand!(rng..., Array{T}(2, 3), C) ::Array{T, 2} + for a in [a0, a1..., a2..., a3..., a4..., a5...] if C isa Type @test a isa C else @@ -373,6 +374,7 @@ for rng in ([], [MersenneTwister(0)], [RandomDevice()]) bitrand(rng..., 5) ::BitArray{1} bitrand(rng..., 2, 3) ::BitArray{2} + bitrand(rng..., b2, u3) ::BitArray{2} rand!(rng..., BitArray(5)) ::BitArray{1} rand!(rng..., BitArray(2, 3)) ::BitArray{2} From 6caaad80f6c81932a3e3bd872b16a2d969b2f2e9 Mon Sep 17 00:00:00 2001 From: Josh Bode Date: Mon, 12 Jun 2017 02:29:32 +1000 Subject: [PATCH 1055/1534] Time string parsing for Time type (#22163) Adds: - `parse(::Type{Time}, ...)` methods - constructors for creating `Time` from a string - default ISO time format (`HH:MM:SS.s`) - conversion defaults for `Microsecond` and `Nanosecond` (`0`) --- base/dates/Dates.jl | 2 +- base/dates/io.jl | 66 ++++++++++++++++++++++++++++++++------------- test/dates/io.jl | 39 +++++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 19 deletions(-) diff --git a/base/dates/Dates.jl b/base/dates/Dates.jl index cf5631a9f7244..b2551e94784d1 100644 --- a/base/dates/Dates.jl +++ b/base/dates/Dates.jl @@ -78,6 +78,6 @@ export Period, DatePeriod, TimePeriod, firstdayofquarter, lastdayofquarter, adjust, tonext, toprev, tofirst, tolast, # io.jl - ISODateTimeFormat, ISODateFormat, DateFormat, RFC1123Format, @dateformat_str + ISODateTimeFormat, ISODateFormat, ISOTimeFormat, DateFormat, RFC1123Format, @dateformat_str end # module diff --git a/base/dates/io.jl b/base/dates/io.jl index b31e28c35fd33..f7ce2480feffc 100644 --- a/base/dates/io.jl +++ b/base/dates/io.jl @@ -273,6 +273,8 @@ const CONVERSION_DEFAULTS = Dict{Type, Any}( Minute => Int64(0), Second => Int64(0), Millisecond => Int64(0), + Microsecond => Int64(0), + Nanosecond => Int64(0), ) # Specifies the required fields in order to parse a TimeType @@ -280,6 +282,7 @@ const CONVERSION_DEFAULTS = Dict{Type, Any}( const CONVERSION_TRANSLATIONS = Dict{Type{<:TimeType}, Tuple}( Date => (Year, Month, Day), DateTime => (Year, Month, Day, Hour, Minute, Second, Millisecond), + Time => (Hour, Minute, Second, Millisecond, Microsecond, Nanosecond), ) """ @@ -388,10 +391,12 @@ end # Standard formats const ISODateTimeFormat = DateFormat("yyyy-mm-dd\\THH:MM:SS.s") const ISODateFormat = DateFormat("yyyy-mm-dd") +const ISOTimeFormat = DateFormat("HH:MM:SS.s") const RFC1123Format = DateFormat("e, dd u yyyy HH:MM:SS") default_format(::Type{DateTime}) = ISODateTimeFormat default_format(::Type{Date}) = ISODateFormat +default_format(::Type{Time}) = ISOTimeFormat ### API @@ -400,12 +405,12 @@ const Locale = Union{DateLocale, String} """ DateTime(dt::AbstractString, format::AbstractString; locale="english") -> DateTime -Construct a `DateTime` by parsing the `dt` date string following the pattern given in -the `format` string. +Construct a `DateTime` by parsing the `dt` date time string following the +pattern given in the `format` string. -This method creates a `DateFormat` object each time it is called. If you are parsing many -date strings of the same format, consider creating a [`DateFormat`](@ref) object once and using -that as the second argument instead. +This method creates a `DateFormat` object each time it is called. If you are +parsing many date time strings of the same format, consider creating a +[`DateFormat`](@ref) object once and using that as the second argument instead. """ function DateTime(dt::AbstractString, format::AbstractString; locale::Locale=ENGLISH) parse(DateTime, dt, DateFormat(format, locale)) @@ -414,30 +419,55 @@ end """ DateTime(dt::AbstractString, df::DateFormat) -> DateTime -Construct a `DateTime` by parsing the `dt` date string following the pattern given in -the [`DateFormat`](@ref) object. Similar to -`DateTime(::AbstractString, ::AbstractString)` but more efficient when repeatedly parsing -similarly formatted date strings with a pre-created `DateFormat` object. +Construct a `DateTime` by parsing the `dt` date time string following the +pattern given in the [`DateFormat`](@ref) object. Similar to +`DateTime(::AbstractString, ::AbstractString)` but more efficient when +repeatedly parsing similarly formatted date time strings with a pre-created +`DateFormat` object. """ DateTime(dt::AbstractString, df::DateFormat=ISODateTimeFormat) = parse(DateTime, dt, df) """ - Date(dt::AbstractString, format::AbstractString; locale="english") -> Date + Date(d::AbstractString, format::AbstractString; locale="english") -> Date -Construct a `Date` object by parsing a `dt` date string following the pattern given in the -`format` string. Follows the same conventions as -`DateTime(::AbstractString, ::AbstractString)`. +Construct a `Date` by parsing the `d` date string following the pattern given +in the `format` string. + +This method creates a `DateFormat` object each time it is called. If you are +parsing many date strings of the same format, consider creating a +[`DateFormat`](@ref) object once and using that as the second argument instead. +""" +function Date(d::AbstractString, format::AbstractString; locale::Locale=ENGLISH) + parse(Date, d, DateFormat(format, locale)) +end + +""" + Date(d::AbstractString, df::DateFormat) -> Date + +Parse a date from a date string `d` using a `DateFormat` object `df`. +""" +Date(d::AbstractString, df::DateFormat=ISODateFormat) = parse(Date, d, df) + +""" + Time(t::AbstractString, format::AbstractString; locale="english") -> Time + +Construct a `Time` by parsing the `t` time string following the pattern given +in the `format` string. + +This method creates a `DateFormat` object each time it is called. If you are +parsing many time strings of the same format, consider creating a +[`DateFormat`](@ref) object once and using that as the second argument instead. """ -function Date(dt::AbstractString, format::AbstractString; locale::Locale=ENGLISH) - parse(Date, dt, DateFormat(format, locale)) +function Time(t::AbstractString, format::AbstractString; locale::Locale=ENGLISH) + parse(Time, t, DateFormat(format, locale)) end """ - Date(dt::AbstractString, df::DateFormat) -> Date + Time(t::AbstractString, df::DateFormat) -> Time -Parse a date from a date string `dt` using a `DateFormat` object `df`. +Parse a time from a time string `t` using a `DateFormat` object `df`. """ -Date(dt::AbstractString,df::DateFormat=ISODateFormat) = parse(Date, dt, df) +Time(t::AbstractString, df::DateFormat=ISOTimeFormat) = parse(Time, t, df) @generated function format(io::IO, dt::TimeType, fmt::DateFormat{<:Any,T}) where T N = nfields(T) diff --git a/test/dates/io.jl b/test/dates/io.jl index b5090eef1086a..4a34d87859637 100644 --- a/test/dates/io.jl +++ b/test/dates/io.jl @@ -445,3 +445,42 @@ end # Ensure that no overflow occurs when using Int32 literals: Int32(10)^10 @test Dates.parse_components("." * rpad(999, 10, '0'), Dates.DateFormat(".s")) == [Dates.Millisecond(999)] end + +# Time Parsing +let + time_tuple(t::Dates.Time) = ( + Dates.hour(t), Dates.minute(t), Dates.second(t), + Dates.millisecond(t), Dates.microsecond(t), Dates.nanosecond(t) + ) + + ## default ISOTimeFormat + t = Dates.Time("01") + @test time_tuple(t) == (1, 0, 0, 0, 0, 0) + t = Dates.Time("01:23") + @test time_tuple(t) == (1, 23, 0, 0, 0, 0) + t = Dates.Time("01:23:45") + @test time_tuple(t) == (1, 23, 45, 0, 0, 0) + t = Dates.Time("01:23:45.678") + @test time_tuple(t) == (1, 23, 45, 678, 0, 0) + + ## string format + t = Dates.Time("23:56:12.1", "HH:MM:SS.s") + @test time_tuple(t) == (23, 56, 12, 100, 0, 0) + + ## precomputed DateFormat + t = Dates.Time("04:09:45.012", DateFormat("HH:MM:SS.s")) + @test time_tuple(t) == (4, 9, 45, 12, 0, 0) + t = Dates.Time("21 07", DateFormat("HH MM")) + @test time_tuple(t) == (21, 7, 0, 0, 0, 0) + t = Dates.Time("4.02", DateFormat("H.MM")) + @test time_tuple(t) == (4, 2, 0, 0, 0, 0) + t = Dates.Time("1725", DateFormat("HHMM")) + @test time_tuple(t) == (17, 25, 0, 0, 0, 0) + + ## exceptions + @test_throws ArgumentError Dates.Time("24:00") # invalid hours + @test_throws ArgumentError Dates.Time("00:60") # invalid minutes + @test_throws ArgumentError Dates.Time("00:00:60") # invalid seconds + @test_throws ArgumentError Dates.Time("20:03:20", DateFormat("HH:MM")) # too much precision + @test_throws ArgumentError Dates.Time("10:33:51", DateFormat("YYYY-MM-DD HH:MM:SS")) # Time can't hold year/month/day +end From 71de18f3c1aa8aee80d5372a477b5d9558372e07 Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Sat, 10 Jun 2017 14:52:47 -0700 Subject: [PATCH 1056/1534] Add remaining 0.6 news items --- NEWS.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/NEWS.md b/NEWS.md index 08dc34e3e8d72..9c1cf6429f779 100644 --- a/NEWS.md +++ b/NEWS.md @@ -679,6 +679,23 @@ Deprecated or removed [StatsBase.jl package](https://github.com/JuliaStats/StatsBase.jl)'s `midpoints` function ([#20058]). + * Passing a type argument to `LibGit2.cat` has been deprecated in favor of a simpler, + two-argument method for `LibGit2.cat` ([#20435]). + + * The `LibGit2.owner` function for finding the repository which owns a given Git object + has been deprecated in favor of `LibGit2.repository` ([#20135]). + + * The `LibGit2.GitAnyObject` type has been renamed to `LibGit2.GitUnknownObject` to + clarify its intent ([#19935]). + + * The `LibGit2.GitOid` type has been renamed to `LibGit2.GitHash` for clarity ([#19878]). + + * Finalizing `LibGit2` objects with `finalize` has been deprecated in favor of using `close` + ([#19660]). + + * Parsing string dates from a `Dates.DateFormat` object has been deprecated as part of a + larger effort toward faster, more extensible date parsing ([#20952]). + Command-line option changes --------------------------- @@ -768,6 +785,7 @@ Command-line option changes [#19598]: https://github.com/JuliaLang/julia/issues/19598 [#19635]: https://github.com/JuliaLang/julia/issues/19635 [#19636]: https://github.com/JuliaLang/julia/issues/19636 +[#19660]: https://github.com/JuliaLang/julia/issues/19660 [#19669]: https://github.com/JuliaLang/julia/issues/19669 [#19670]: https://github.com/JuliaLang/julia/issues/19670 [#19677]: https://github.com/JuliaLang/julia/issues/19677 @@ -794,6 +812,7 @@ Command-line option changes [#19811]: https://github.com/JuliaLang/julia/issues/19811 [#19814]: https://github.com/JuliaLang/julia/issues/19814 [#19841]: https://github.com/JuliaLang/julia/issues/19841 +[#19878]: https://github.com/JuliaLang/julia/issues/19878 [#19900]: https://github.com/JuliaLang/julia/issues/19900 [#19901]: https://github.com/JuliaLang/julia/issues/19901 [#19903]: https://github.com/JuliaLang/julia/issues/19903 @@ -803,6 +822,7 @@ Command-line option changes [#19926]: https://github.com/JuliaLang/julia/issues/19926 [#19931]: https://github.com/JuliaLang/julia/issues/19931 [#19934]: https://github.com/JuliaLang/julia/issues/19934 +[#19935]: https://github.com/JuliaLang/julia/issues/19935 [#19937]: https://github.com/JuliaLang/julia/issues/19937 [#19944]: https://github.com/JuliaLang/julia/issues/19944 [#19949]: https://github.com/JuliaLang/julia/issues/19949 @@ -812,6 +832,7 @@ Command-line option changes [#20047]: https://github.com/JuliaLang/julia/issues/20047 [#20058]: https://github.com/JuliaLang/julia/issues/20058 [#20079]: https://github.com/JuliaLang/julia/issues/20079 +[#20135]: https://github.com/JuliaLang/julia/issues/20135 [#20164]: https://github.com/JuliaLang/julia/issues/20164 [#20213]: https://github.com/JuliaLang/julia/issues/20213 [#20228]: https://github.com/JuliaLang/julia/issues/20228 @@ -831,12 +852,14 @@ Command-line option changes [#20414]: https://github.com/JuliaLang/julia/issues/20414 [#20418]: https://github.com/JuliaLang/julia/issues/20418 [#20427]: https://github.com/JuliaLang/julia/issues/20427 +[#20435]: https://github.com/JuliaLang/julia/issues/20435 [#20500]: https://github.com/JuliaLang/julia/issues/20500 [#20530]: https://github.com/JuliaLang/julia/issues/20530 [#20543]: https://github.com/JuliaLang/julia/issues/20543 [#20575]: https://github.com/JuliaLang/julia/issues/20575 [#20609]: https://github.com/JuliaLang/julia/issues/20609 [#20889]: https://github.com/JuliaLang/julia/issues/20889 +[#20952]: https://github.com/JuliaLang/julia/issues/20952 [#21183]: https://github.com/JuliaLang/julia/issues/21183 [#21359]: https://github.com/JuliaLang/julia/issues/21359 [#21692]: https://github.com/JuliaLang/julia/issues/21692 From 4935abc498676ae820b5dd23f941d392c4601eed Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Sun, 11 Jun 2017 14:12:52 -0700 Subject: [PATCH 1057/1534] Add more 0.7 news references [ci skip] --- NEWS.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/NEWS.md b/NEWS.md index 9c1cf6429f779..0a09739658788 100644 --- a/NEWS.md +++ b/NEWS.md @@ -798,6 +798,7 @@ Command-line option changes [#19721]: https://github.com/JuliaLang/julia/issues/19721 [#19722]: https://github.com/JuliaLang/julia/issues/19722 [#19724]: https://github.com/JuliaLang/julia/issues/19724 +[#19730]: https://github.com/JuliaLang/julia/issues/19730 [#19737]: https://github.com/JuliaLang/julia/issues/19737 [#19741]: https://github.com/JuliaLang/julia/issues/19741 [#19766]: https://github.com/JuliaLang/julia/issues/19766 @@ -864,4 +865,15 @@ Command-line option changes [#21359]: https://github.com/JuliaLang/julia/issues/21359 [#21692]: https://github.com/JuliaLang/julia/issues/21692 [#21697]: https://github.com/JuliaLang/julia/issues/21697 +[#21746]: https://github.com/JuliaLang/julia/issues/21746 [#21759]: https://github.com/JuliaLang/julia/issues/21759 +[#21818]: https://github.com/JuliaLang/julia/issues/21818 +[#21825]: https://github.com/JuliaLang/julia/issues/21825 +[#21973]: https://github.com/JuliaLang/julia/issues/21973 +[#21974]: https://github.com/JuliaLang/julia/issues/21974 +[#22007]: https://github.com/JuliaLang/julia/issues/22007 +[#22038]: https://github.com/JuliaLang/julia/issues/22038 +[#22062]: https://github.com/JuliaLang/julia/issues/22062 +[#22064]: https://github.com/JuliaLang/julia/issues/22064 +[#22187]: https://github.com/JuliaLang/julia/issues/22187 +[#22188]: https://github.com/JuliaLang/julia/issues/22188 From 85ef52c1e2cdb49dd74b834b39b4abc39fd6aad4 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Mon, 12 Jun 2017 00:13:46 +0200 Subject: [PATCH 1058/1534] add a base keyword to logspace (#22310) to specify the base (which otherwise defaults to 10) --- NEWS.md | 3 +++ base/range.jl | 14 +++++++++++--- test/ranges.jl | 11 +++++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/NEWS.md b/NEWS.md index 0a09739658788..056f62e2d8549 100644 --- a/NEWS.md +++ b/NEWS.md @@ -65,6 +65,9 @@ Library improvements git repo. Additionally, the argument order was changed to be consistent with the git command line tool ([#22062]). + * `logspace` now accepts a `base` keyword argument to specify the base of the logarithmic + range. The base defaults to 10 ([#22310]). + Compiler/Runtime improvements ----------------------------- diff --git a/base/range.jl b/base/range.jl index dafa655c2054e..4d5bb7f342ae8 100644 --- a/base/range.jl +++ b/base/range.jl @@ -316,9 +316,9 @@ function print_range(io::IO, r::Range, end """ - logspace(start::Real, stop::Real, n::Integer=50) + logspace(start::Real, stop::Real, n::Integer=50; base=10) -Construct a vector of `n` logarithmically spaced numbers from `10^start` to `10^stop`. +Construct a vector of `n` logarithmically spaced numbers from `base^start` to `base^stop`. ```jldoctest julia> logspace(1.,10.,5) @@ -328,9 +328,17 @@ julia> logspace(1.,10.,5) 3.16228e5 5.62341e7 1.0e10 + +julia> logspace(1.,10.,5,base=2) +5-element Array{Float64,1}: + 2.0 + 9.51366 + 45.2548 + 215.269 + 1024.0 ``` """ -logspace(start::Real, stop::Real, n::Integer=50) = 10.^linspace(start, stop, n) +logspace(start::Real, stop::Real, n::Integer=50; base=10) = base.^linspace(start, stop, n) ## interface implementations diff --git a/test/ranges.jl b/test/ranges.jl index 506c030db9a33..30b87be782b72 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -918,3 +918,14 @@ let linsp = linspace(1.0, 2.0, 10) @test Float32(linsp.ref) === convert(Float32, linsp.ref) @test Float32(linsp.ref) ≈ linsp.ref.hi + linsp.ref.lo end + +@testset "logspace" begin + n = 10; a = 2; b = 4 + # test default values; n = 50, base = 10 + @test logspace(a, b) == logspace(a, b, 50) == 10.^linspace(a, b, 50) + @test logspace(a, b, n) == 10.^linspace(a, b, n) + for base in (10, 2, e) + @test logspace(a, b, base=base) == logspace(a, b, 50, base=base) == base.^linspace(a, b, 50) + @test logspace(a, b, n, base=base) == base.^linspace(a, b, n) + end +end From ef0c35fe6f128313aabd45403a06e291152d60e1 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 5 Jun 2017 20:24:09 -0400 Subject: [PATCH 1059/1534] eliminate another turing machines from subarray (find_extended_dims) --- base/subarray.jl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/base/subarray.jl b/base/subarray.jl index 9c2e31aae95e9..3a1b3ddf4d256 100644 --- a/base/subarray.jl +++ b/base/subarray.jl @@ -264,7 +264,7 @@ end # indexing uses the indices along the given dimension. Otherwise # linear indexing always starts with 1. compute_offset1(parent, stride1::Integer, I::Tuple) = - (@_inline_meta; compute_offset1(parent, stride1, find_extended_dims(I)..., I)) + (@_inline_meta; compute_offset1(parent, stride1, find_extended_dims(1, I...), find_extended_inds(I...), I)) compute_offset1(parent, stride1::Integer, dims::Tuple{Int}, inds::Tuple{Slice}, I::Tuple) = (@_inline_meta; compute_linindex(parent, I) - stride1*first(indices(parent, dims[1]))) # index-preserving case compute_offset1(parent, stride1::Integer, dims, inds, I::Tuple) = @@ -287,12 +287,12 @@ function compute_linindex(f, s, IP::Tuple, I::Tuple{Any, Vararg{Any}}) end compute_linindex(f, s, IP::Tuple, I::Tuple{}) = f -find_extended_dims(I) = (@_inline_meta; _find_extended_dims((), (), 1, I...)) -_find_extended_dims(dims, inds, dim) = dims, inds -_find_extended_dims(dims, inds, dim, ::ScalarIndex, I...) = - (@_inline_meta; _find_extended_dims(dims, inds, dim+1, I...)) -_find_extended_dims(dims, inds, dim, i1, I...) = - (@_inline_meta; _find_extended_dims((dims..., dim), (inds..., i1), dim+1, I...)) +find_extended_dims(dim, ::ScalarIndex, I...) = (@_inline_meta; find_extended_dims(dim + 1, I...)) +find_extended_dims(dim, i1, I...) = (@_inline_meta; (dim, find_extended_dims(dim + 1, I...)...)) +find_extended_dims(dim) = () +find_extended_inds(::ScalarIndex, I...) = (@_inline_meta; find_extended_inds(I...)) +find_extended_inds(i1, I...) = (@_inline_meta; (i1, find_extended_inds(I...)...)) +find_extended_inds() = () unsafe_convert(::Type{Ptr{T}}, V::SubArray{T,N,P,<:Tuple{Vararg{RangeIndex}}}) where {T,N,P} = unsafe_convert(Ptr{T}, V.parent) + (first_index(V)-1)*sizeof(T) From 545fb0b4d5223db4fabbae0bef9ba0d033c732fb Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 17 May 2017 16:13:20 -0400 Subject: [PATCH 1060/1534] duplicate some type-dissimilar code in the `inv` function detecting this code optimization (jump-threading) in the compiler is desirable, but generally very difficult --- base/linalg/dense.jl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/base/linalg/dense.jl b/base/linalg/dense.jl index c1dc43965e13b..590156356c06a 100644 --- a/base/linalg/dense.jl +++ b/base/linalg/dense.jl @@ -653,12 +653,15 @@ function inv(A::StridedMatrix{T}) where T AA = convert(AbstractArray{S}, A) if istriu(AA) Ai = inv(UpperTriangular(AA)) + Ai = convert(typeof(parent(Ai)), Ai) elseif istril(AA) Ai = inv(LowerTriangular(AA)) + Ai = convert(typeof(parent(Ai)), Ai) else Ai = inv(lufact(AA)) + Ai = convert(typeof(parent(Ai)), Ai) end - return convert(typeof(parent(Ai)), Ai) + return Ai end """ From 825c408a915de5161dcc7efe07b8b8a07bd5c1ec Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 18 May 2017 23:54:43 -0400 Subject: [PATCH 1061/1534] reduce the impact of generated functions on getindex inference --- base/multidimensional.jl | 37 ++++++++++++++----------------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 0f125757aca10..a5dfd377fbad6 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -435,13 +435,9 @@ getindex(t::Tuple, i::CartesianIndex{1}) = getindex(t, i.I[1]) # These are not defined on directly on getindex to avoid # ambiguities for AbstractArray subtypes. See the note in abstractarray.jl -@generated function _getindex(l::IndexStyle, A::AbstractArray, I::Union{Real, AbstractArray}...) - N = length(I) - quote - @_inline_meta - @boundscheck checkbounds(A, I...) - _unsafe_getindex(l, _maybe_reshape(l, A, I...), I...) - end +@inline function _getindex(l::IndexStyle, A::AbstractArray, I::Union{Real, AbstractArray}...) + @boundscheck checkbounds(A, I...) + return _unsafe_getindex(l, _maybe_reshape(l, A, I...), I...) end # But we can speed up IndexCartesian arrays by reshaping them to the appropriate dimensionality: _maybe_reshape(::IndexLinear, A::AbstractArray, I...) = A @@ -450,31 +446,26 @@ _maybe_reshape(::IndexCartesian, A::AbstractVector, I...) = A @inline __maybe_reshape(A::AbstractArray{T,N}, ::NTuple{N,Any}) where {T,N} = A @inline __maybe_reshape(A::AbstractArray, ::NTuple{N,Any}) where {N} = reshape(A, Val{N}) -@generated function _unsafe_getindex(::IndexStyle, A::AbstractArray, I::Union{Real, AbstractArray}...) - N = length(I) - quote - # This is specifically not inlined to prevent exessive allocations in type unstable code - @nexprs $N d->(I_d = I[d]) - shape = @ncall $N index_shape I - dest = similar(A, shape) - map(unsafe_length, indices(dest)) == map(unsafe_length, shape) || throw_checksize_error(dest, shape) - @ncall $N _unsafe_getindex! dest A I - end +function _unsafe_getindex(::IndexStyle, A::AbstractArray, I::Vararg{Union{Real, AbstractArray}, N}) where N + # This is specifically not inlined to prevent excessive allocations in type unstable code + shape = index_shape(I...) + dest = similar(A, shape) + map(unsafe_length, indices(dest)) == map(unsafe_length, shape) || throw_checksize_error(dest, shape) + _unsafe_getindex!(dest, A, I...) # usually a generated function, don't allow it to impact inference result + return dest end # Always index with the exactly indices provided. -@generated function _unsafe_getindex!(dest::AbstractArray, src::AbstractArray, I::Union{Real, AbstractArray}...) - N = length(I) +@generated function _unsafe_getindex!(dest::AbstractArray, src::AbstractArray, I::Vararg{Union{Real, AbstractArray}, N}) where N quote - $(Expr(:meta, :inline)) - @nexprs $N d->(J_d = I[d]) + @_inline_meta D = eachindex(dest) Ds = start(D) - @inbounds @nloops $N j d->J_d begin + @inbounds @nloops $N j d->I[d] begin d, Ds = next(D, Ds) dest[d] = @ncall $N getindex src j end - dest + return dest end end From fcfe875b1ca65aec316f43397c1ee5ed5e7c0326 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 16 May 2017 00:17:32 -0400 Subject: [PATCH 1062/1534] inference: work on making the termination heuristics work correctly now that our inference convergence algorithm is reasonably reliable, this is a starting point for making the inference capabilities even better --- base/inference.jl | 446 +++++++++++++++++++++++++++-------- doc/src/devdocs/functions.md | 51 ---- test/inference.jl | 30 ++- 3 files changed, 383 insertions(+), 144 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index a9829626bed31..ecb08f74ab081 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -5,6 +5,7 @@ import Core: _apply, svec, apply_type, Builtin, IntrinsicFunction, MethodInstanc #### parameters limiting potentially-infinite types #### const MAX_TYPEUNION_LEN = 3 const MAX_TYPE_DEPTH = 8 +const TUPLE_COMPLEXITY_LIMIT_DEPTH = 3 const MAX_INLINE_CONST_SIZE = 256 @@ -306,6 +307,20 @@ function get_staged(li::MethodInstance) return ccall(:jl_code_for_staged, Any, (Any,), li)::CodeInfo end + +#### debugging utilities #### + +function print_callstack(sv::InferenceState) + while sv !== nothing + println(sv.linfo) + for cycle in sv.callers_in_cycle + println(' ', cycle.linfo) + end + sv = sv.parent + end +end + + #### helper functions #### @inline slot_id(s) = isa(s, SlotNumber) ? (s::SlotNumber).id : (s::TypedSlot).id # using a function to ensure we can infer this @@ -703,7 +718,7 @@ function type_depth(t::ANY) if t.var.ub === Any && t.var.lb === Bottom return type_depth(t.body) end - return max(type_depth(t.var.ub)+1, type_depth(t.var.lb)+1, type_depth(t.body)) + return max(type_depth(t.var.ub) + 1, type_depth(t.var.lb) + 1, type_depth(t.body)) end return 0 end @@ -715,8 +730,8 @@ function limit_type_depth(t::ANY, d::Int) end function limit_type_depth(t::ANY, d::Int, cov::Bool, vars::Vector{TypeVar}=TypeVar[]) - if isa(t,Union) - if d > MAX_TYPE_DEPTH + if isa(t, Union) + if d < 0 if cov return Any else @@ -725,9 +740,9 @@ function limit_type_depth(t::ANY, d::Int, cov::Bool, vars::Vector{TypeVar}=TypeV return var end end - return Union{limit_type_depth(t.a, d+1, cov, vars), - limit_type_depth(t.b, d+1, cov, vars)} - elseif isa(t,UnionAll) + return Union{limit_type_depth(t.a, d - 1, cov, vars), + limit_type_depth(t.b, d - 1, cov, vars)} + elseif isa(t, UnionAll) v = t.var if v.ub === Any if v.lb === Bottom @@ -735,9 +750,9 @@ function limit_type_depth(t::ANY, d::Int, cov::Bool, vars::Vector{TypeVar}=TypeV end ub = Any else - ub = limit_type_depth(v.ub, d+1, true) + ub = limit_type_depth(v.ub, d - 1, true) end - if v.lb === Bottom || type_depth(v.lb) > MAX_TYPE_DEPTH + if v.lb === Bottom || type_depth(v.lb) > d # note: lower bounds need to be widened by making them lower lb = Bottom else @@ -750,7 +765,7 @@ function limit_type_depth(t::ANY, d::Int, cov::Bool, vars::Vector{TypeVar}=TypeV end P = t.parameters isempty(P) && return t - if d > MAX_TYPE_DEPTH + if d < 0 if isvarargtype(t) # never replace Vararg with non-Vararg return Vararg{limit_type_depth(P[1], d, cov, vars), P[2]} @@ -768,7 +783,7 @@ function limit_type_depth(t::ANY, d::Int, cov::Bool, vars::Vector{TypeVar}=TypeV return var end stillcov = cov && (t.name === Tuple.name) - Q = map(x->limit_type_depth(x, d+1, stillcov, vars), P) + Q = map(x -> limit_type_depth(x, d - 1, stillcov, vars), P) R = t.name.wrapper{Q...} if cov && !stillcov for var in vars @@ -778,6 +793,253 @@ function limit_type_depth(t::ANY, d::Int, cov::Bool, vars::Vector{TypeVar}=TypeV return R end +# limit the complexity of type `t` to be simpler than the comparison type `compare` +# no new values may be introduced, so the parameter `source` encodes the set of all values already present +function limit_type_size(t::ANY, compare::ANY, source::ANY) + source = svec(unwrap_unionall(compare), unwrap_unionall(source)) + source[1] === source[2] && (source = svec(source[1])) + type_more_complex(t, compare, source, TUPLE_COMPLEXITY_LIMIT_DEPTH) || return t + r = _limit_type_size(t, compare, source) + @assert t <: r + #@assert r === _limit_type_size(r, t, source) # this monotonicity constraint is slightly stronger than actually required, + # since we only actually need to demonstrate that repeated application would reaches a fixed point, + #not that it is already at the fixed point + return r +end + +sym_isless(a::Symbol, b::Symbol) = ccall(:strcmp, Int32, (Ptr{UInt8}, Ptr{UInt8}), a, b) < 0 + +function type_more_complex(t::ANY, c::ANY, sources::SimpleVector, tupledepth::Int) + # detect cases where the comparison is trivial + if t === c + return false + elseif t === Union{} + return false # Bottom is as simple as they come + elseif isa(t, DataType) && isempty(t.parameters) + return false # fastpath: unparameterized types are always finite + elseif tupledepth > 0 && isa(unwrap_unionall(t), DataType) && isa(c, Type) && c !== Union{} && c <: t + return false # t is already wider than the comparison in the type lattice + elseif tupledepth > 0 && is_derived_type_from_any(unwrap_unionall(t), sources) + return false # t isn't something new + end + # peel off wrappers + if isa(c, UnionAll) + # allow wrapping type with fewer UnionAlls than comparison if in a covariant context + if !isa(t, UnionAll) && tupledepth == 0 + return true + end + t = unwrap_unionall(t) + c = unwrap_unionall(c) + end + # rules for various comparison types + if isa(c, TypeVar) + if isa(t, TypeVar) + return !(t.lb === Union{} || t.lb === c.lb) || # simplify lb towards Union{} + type_more_complex(t.ub, c.ub, sources, tupledepth) + end + c.lb === Union{} || return true + return type_more_complex(t, c.ub, sources, max(tupledepth, 1)) # allow replacing a TypeVar with a concrete value + elseif isa(c, Union) + if isa(t, Union) + return type_more_complex(t.a, c.a, sources, tupledepth) || + type_more_complex(t.b, c.b, sources, tupledepth) + end + return type_more_complex(t, c.a, sources, tupledepth) && + type_more_complex(t, c.b, sources, tupledepth) + elseif isa(t, Int) && isa(c, Int) + return t !== 1 # alternatively, could use !(0 <= t < c) + end + # base case for data types + if isa(t, DataType) + tP = t.parameters + if isa(c, DataType) && t.name === c.name + cP = c.parameters + length(cP) < length(tP) && return true + ntail = length(cP) - length(tP) # assume parameters were dropped from the tuple head + # allow creating variation within a nested tuple, but only so deep + if t.name === Tuple.name && tupledepth > 0 + tupledepth -= 1 + elseif !isvarargtype(t) + tupledepth = 0 + end + isgenerator = (t.name.name === :Generator && t.name.module === _topmod(t.name.module)) + for i = 1:length(tP) + tPi = tP[i] + cPi = cP[i + ntail] + if isgenerator + let tPi = unwrap_unionall(tPi), + cPi = unwrap_unionall(cPi) + if isa(tPi, DataType) && isa(cPi, DataType) && + !tPi.abstract && !cPi.abstract && + sym_isless(cPi.name.name, tPi.name.name) + # allow collect on (anonymous) Generators to nest, provided that their functions are appropriately ordered + # TODO: is there a better way? + continue + end + end + end + type_more_complex(tPi, cPi, sources, tupledepth) && return true + end + return false + end + if isType(t) # allow taking typeof any source type anywhere as Type{...}, as long as it isn't nesting Type{Type{...}} + tt = unwrap_unionall(t.parameters[1]) + if isa(tt, DataType) && !isType(tt) + is_derived_type_from_any(tt, sources) || return true + return false + end + end + end + return true +end + +function is_derived_type(t::ANY, c::ANY) # try to find `type` somewhere in `comparison` type + t === c && return true + if isa(c, TypeVar) + # see if it is replacing a TypeVar upper bound with something simpler + return is_derived_type(t, c.ub) + elseif isa(c, Union) + # see if it is one of the elements of the union + return is_derived_type(t, c.a) || is_derived_type(t, c.b) + elseif isa(c, UnionAll) + # see if it is derived from the body + return is_derived_type(t, c.body) + elseif isa(c, DataType) + if isa(t, DataType) + # see if it is one of the supertypes of a parameter + super = supertype(c) + while super !== Any + t === super && return true + super = supertype(super) + end + end + # see if it was extracted from a type parameter + cP = c.parameters + for p in cP + is_derived_type(t, p) && return true + end + if isleaftype(c) && isbits(c) + # see if it was extracted from a fieldtype + # however, only look through types that can be inlined + # to ensure monotonicity of derivation + # since we know that for immutable types, + # the field types must have been constructed prior to the type, + # it cannot have a reference cycle in the type graph + cF = c.types + for f in cF + is_derived_type(t, f) && return true + end + end + end + return false +end + +function is_derived_type_from_any(t::ANY, sources::SimpleVector) + for s in sources + is_derived_type(t, s) && return true + end + return false +end + +function _limit_type_size(t::ANY, c::ANY, sources::SimpleVector) # type vs. comparison which was derived from source + if t === c + return t # quick egal test + elseif t === Union{} + return t # easy case + elseif isa(t, DataType) && isempty(t.parameters) + return t # fast path: unparameterized are always simple + elseif isa(unwrap_unionall(t), DataType) && isa(c, Type) && c !== Union{} && c <: t + return t # t is already wider than the comparison in the type lattice + elseif is_derived_type_from_any(unwrap_unionall(t), sources) + return t # t isn't something new + end + if isa(t, TypeVar) + if isa(c, TypeVar) + if t.ub === c.ub && t.lb === c.lb + return t + end + end + elseif isa(t, Union) + if isa(c, Union) + a = _limit_type_size(t.a, c.a, sources) + b = _limit_type_size(t.b, c.b, sources) + return Union{a, b} + end + elseif isa(t, UnionAll) + if isa(c, UnionAll) + tv = t.var + cv = c.var + if tv.ub === cv.ub + if tv.lb === cv.lb + return UnionAll(tv, _limit_type_size(t.body, c.body, sources)) + end + ub = tv.ub + else + ub = _limit_type_size(tv.ub, cv.ub, sources) + end + if tv.lb === cv.lb + lb = tv.lb + else + # note: lower bounds need to be widened by making them lower + lb = Bottom + end + v2 = TypeVar(tv.name, lb, ub) + return UnionAll(v2, _limit_type_size(t{v2}, c{v2}, sources)) + end + tbody = _limit_type_size(t.body, c, sources) + tbody === t.body && return t + return UnionAll(t.var, tbody) + elseif isa(t, DataType) + if isa(c, DataType) + tP = t.parameters + cP = c.parameters + if t.name === c.name && !isempty(cP) + if isvarargtype(t) + VaT = _limit_type_size(tP[1], cP[1], sources) + N = tP[2] + if isa(N, TypeVar) || N === cP[2] + return Vararg{VaT, N} + end + return Vararg{VaT} + elseif t.name === Tuple.name + # for covariant datatypes (aka Tuple), + # apply type-size limit elementwise + np = min(length(tP), length(cP)) + Q = Any[ tP[i] for i in 1:np ] + if length(tP) > np # implies Tuple + # combine tp[np:end] into tP[np] using Vararg + Q[np] = tuple_tail_elem(Bottom, Any[ tP[i] for i in np:length(tP) ]) + end + for i = 1:np + Q[i] = _limit_type_size(Q[i], cP[i], sources) + end + return Tuple{Q...} + end + end + end + if isType(t) # allow taking typeof as Type{...}, but ensure it doesn't start nesting + tt = unwrap_unionall(t.parameters[1]) + if isa(tt, DataType) && !isType(tt) + is_derived_type_from_any(tt, sources) && return t + end + end + if isvarargtype(t) + # never replace Vararg with non-Vararg + return Vararg + end + widert = t.name.wrapper + if !(t <: widert) + # This can happen when a typevar has bounds too wide for its context, e.g. + # `Complex{T} where T` is not a subtype of `Complex`. In that case widen even + # faster to something safe to ensure the result is a supertype of the input. + return Any + end + return widert + end + return Any +end + + const DataType_name_fieldindex = fieldindex(DataType, :name) const DataType_parameters_fieldindex = fieldindex(DataType, :parameters) const DataType_types_fieldindex = fieldindex(DataType, :types) @@ -881,7 +1143,7 @@ function getfield_tfunc(s00::ANY, name) if isempty(s.parameters) return R end - return limit_type_depth(R, 0) + return limit_type_depth(R, MAX_TYPE_DEPTH) end fld = name.val if isa(fld,Symbol) @@ -916,7 +1178,7 @@ function getfield_tfunc(s00::ANY, name) # conservatively limit the type depth here, # since the UnionAll type bound is otherwise incorrect # in the current type system - return rewrap_unionall(limit_type_depth(R, 0), s00) + return rewrap_unionall(limit_type_depth(R, MAX_TYPE_DEPTH), s00) end add_tfunc(getfield, 2, 2, (s::ANY, name::ANY) -> getfield_tfunc(s, name)) add_tfunc(setfield!, 3, 3, (o::ANY, f::ANY, v::ANY) -> v) @@ -1094,7 +1356,7 @@ function apply_type_tfunc(headtypetype::ANY, args::ANY...) if isvarargtype(headtype) return Type end - if uncertain && type_too_complex(appl,0) + if uncertain && type_too_complex(appl, MAX_TYPE_DEPTH) return Type{<:headtype} end if istuple @@ -1407,59 +1669,36 @@ end function abstract_call_method(method::Method, f::ANY, sig::ANY, sparams::SimpleVector, sv::InferenceState) sigtuple = unwrap_unionall(sig)::DataType - recomputesvec = false - - # limit argument type tuple growth - msig = unwrap_unionall(method.sig) - lsig = length(msig.parameters) - ls = length(sigtuple.parameters) - td = type_depth(sig) - mightlimitlength = ls > lsig + 1 - mightlimitdepth = td > 2 - limitlength = false - if mightlimitlength || mightlimitdepth - # TODO: FIXME: this heuristic depends on non-local state making type-inference unpredictable + + tm = _topmod(sv) + if (# promote_typeof signature may be used with many arguments + !istopfunction(tm, f, :promote_typeof) + # assume getindex methods aren't directly recursive, since wrappers like ReshapedArrays won't look like it here + # should still manage to detect recursive growth either via other intermediate methods or actual type-equal signature recursion + && !istopfunction(tm, f, :getindex) + && !istopfunction(tm, f, :setindex!) + # the construct-to-convert method is a bottleneck in inference, + # so just assume that recursion will get prevented at some other point + && !(method.sig == Tuple{Type, Any})) + # otherwise: limit argument type tuple growth of all other functions + msig = unwrap_unionall(method.sig) + lsig = length(msig.parameters) + ls = length(sigtuple.parameters) + # look through the parents list to find the topmost + # function call to the same method cyclei = 0 infstate = sv + topmost = nothing while infstate !== nothing infstate = infstate::InferenceState if method === infstate.linfo.def - if mightlimitlength && ls > length(unwrap_unionall(infstate.linfo.specTypes).parameters) - limitlength = true - end - if mightlimitdepth && td > type_depth(infstate.linfo.specTypes) - # impose limit if we recur and the argument types grow beyond MAX_TYPE_DEPTH - if td > MAX_TYPE_DEPTH - sig = limit_type_depth(sig, 0) - sigtuple = unwrap_unionall(sig) - recomputesvec = true - break - else - p1, p2 = sigtuple.parameters, unwrap_unionall(infstate.linfo.specTypes).parameters - if length(p2) == ls - limitdepth = false - newsig = Vector{Any}(ls) - for i = 1:ls - if p1[i] <: Function && type_depth(p1[i]) > type_depth(p2[i]) && - isa(p1[i],DataType) - # if a Function argument is growing (e.g. nested closures) - # then widen to the outermost function type. without this - # inference fails to terminate on do_quadgk. - newsig[i] = p1[i].name.wrapper - limitdepth = true - else - newsig[i] = limit_type_depth(p1[i], 1) - end - end - if limitdepth - sigtuple = Tuple{newsig...} - sig = rewrap_unionall(sigtuple, sig) - recomputesvec = true - break - end - end - end + if infstate.linfo.specTypes == sig + # avoid widening when detecting self-recursion + # TODO: merge call cycle and return right away + topmost = nothing + break end + topmost === nothing && (topmost = infstate) end # iterate through the cycle before walking to the parent if cyclei < length(infstate.callers_in_cycle) @@ -1470,35 +1709,57 @@ function abstract_call_method(method::Method, f::ANY, sig::ANY, sparams::SimpleV infstate = infstate.parent end end - end - # limit length based on size of definition signature. - # for example, given function f(T, Any...), limit to 3 arguments - # instead of the default (MAX_TUPLETYPE_LEN) - if limitlength - tm = _topmod(sv) - if !istopfunction(tm, f, :promote_typeof) - fst = sigtuple.parameters[lsig + 1] - allsame = true - # allow specializing on longer arglists if all the trailing - # arguments are the same, since there is no exponential - # blowup in this case. - for i = (lsig + 2):ls - if sigtuple.parameters[i] != fst - allsame = false - break + # TODO: FIXME: this heuristic depends on non-local state making type-inference unpredictable + # it also should be integrated into the cycle resolution and iterated to convergence + if topmost !== nothing + # impose limit if we recur on the same method and the argument type complexity is growing or is beyond MAX_TYPE_DEPTH + newsig = sig + if !isempty(topmost.callers_in_cycle) + # already discovered this method causes dependent self-recursion + # widen fully to avoid making the cycle any larger + newsig = method.sig + else + comparison = topmost.linfo.specTypes + if ls > lsig + 1 && ls > length(unwrap_unionall(comparison).parameters) + # limit length based on size of definition signature. + # for example, given function f(T, Any...), limit to 3 arguments + # instead of the default (MAX_TUPLETYPE_LEN) + fst = sigtuple.parameters[lsig + 1] + allsame = true + # allow specializing on longer arglists if all the trailing + # arguments are the same, since there is no exponential + # blowup in this case. + for i = (lsig + 2):ls + if sigtuple.parameters[i] != fst + allsame = false + break + end + end + if !allsame + sigtuple = limit_tuple_type_n(sigtuple, lsig + 1) + newsig = rewrap_unionall(sigtuple, newsig) + end + end + td = type_depth(newsig) + max_type_depth = min(MAX_TYPE_DEPTH, type_depth(comparison)) + if td > max_type_depth + # limit growth in type depth + newsig = limit_type_depth(newsig, max_type_depth) end + # see if the type is still too big, and limit it further if required + newsig = limit_type_size(newsig, comparison, sv.linfo.specTypes) end - if !allsame - sigtuple = limit_tuple_type_n(sigtuple, lsig + 1) - sig = rewrap_unionall(sigtuple, sig) - recomputesvec = true + if newsig !== sig + sig = newsig + sigtuple = unwrap_unionall(sig) + sparams = svec() end end end # if sig changed, may need to recompute the sparams environment - if isa(method.sig, UnionAll) && (recomputesvec || isempty(sparams)) + if isa(method.sig, UnionAll) && isempty(sparams) recomputed = ccall(:jl_env_from_type_intersection, Ref{SimpleVector}, (Any, Any), sig, method.sig) sig = recomputed[1] if !isa(unwrap_unionall(sig), DataType) # probably Union{} @@ -1565,7 +1826,7 @@ function precise_container_type(arg::ANY, typ::ANY, vtypes::VarTable, sv::Infere if isvatuple(tti0) && length(tti0.parameters) == 1 return Any[Vararg{unwrapva(tti0.parameters[1])}] else - return tti0.parameters + return Any[ p for p in tti0.parameters ] end elseif tti0 <: Array return Any[Vararg{eltype(tti0)}] @@ -2201,18 +2462,18 @@ function abstract_interpret(e::ANY, vtypes::VarTable, sv::InferenceState) return vtypes end -function type_too_complex(t::ANY, d) - if d > MAX_TYPE_DEPTH +function type_too_complex(t::ANY, d::Int) + if d < 0 return true - elseif isa(t,Union) - return type_too_complex(t.a, d+1) || type_too_complex(t.b, d+1) - elseif isa(t,TypeVar) - return type_too_complex(t.lb,d+1) || type_too_complex(t.ub,d+1) - elseif isa(t,UnionAll) + elseif isa(t, Union) + return type_too_complex(t.a, d - 1) || type_too_complex(t.b, d - 1) + elseif isa(t, TypeVar) + return type_too_complex(t.lb, d - 1) || type_too_complex(t.ub, d - 1) + elseif isa(t, UnionAll) return type_too_complex(t.var, d) || type_too_complex(t.body, d) - elseif isa(t,DataType) + elseif isa(t, DataType) for x in (t.parameters)::SimpleVector - if type_too_complex(x, d+1) + if type_too_complex(x, d - 1) return true end end @@ -2317,7 +2578,7 @@ function tmerge(typea::ANY, typeb::ANY) end end u = Union{typea, typeb} - if unionlen(u) > MAX_TYPEUNION_LEN || type_too_complex(u, 0) + if unionlen(u) > MAX_TYPEUNION_LEN || type_too_complex(u, MAX_TYPE_DEPTH) # don't let type unions get too big # TODO: something smarter, like a common supertype return Any @@ -2653,6 +2914,7 @@ function typeinf_edge(method::Method, atypes::ANY, sparams::SimpleVector, caller return frame.bestguess, nothing end + #### entry points for inferring a MethodInstance given a type signature #### # compute an inferred AST and return type diff --git a/doc/src/devdocs/functions.md b/doc/src/devdocs/functions.md index f693d692f9499..70c509ec341d2 100644 --- a/doc/src/devdocs/functions.md +++ b/doc/src/devdocs/functions.md @@ -251,54 +251,3 @@ The next problem was the `@test` macro, which generated a 0-argument closure for This is not really necessary, since each test case is simply run once in place. Therefore I modified `@test` to expand to a try-catch block that records the test result (true, false, or exception raised) and calls the test suite handler on it. - -However this caused a new problem. When many tests are grouped together in a single function, -e.g. a single top level expression, or some other test grouping function, that function could -have a very large number of exception handlers. This triggered a kind of dataflow analysis worst -case, where type inference spun around for minutes enumerating possible paths through the forest -of handlers. This was fixed by simply bailing out of type inference when it encounters more than -some number of handlers (currently 25). Presumably no performance-critical function will have -more than 25 exception handlers. If one ever does, I'm willing to raise the limit to 26. - -A minor issue occurs during the bootstrap process due to storing all constructors in a single -method table. In the second bootstrap step, where `inference.ji` is compiled using `inference0.ji`, -constructors for `inference0`'s types remain in the table, so there are still references to the -old inference module and `inference.ji` is 2x the size it should be. This was fixed in `dump.c` by -filtering definitions from "replaced modules" out of method tables and caches before saving a -system image. A "replaced module" is one that satisfies the condition `m != jl_get_global(m->parent, m->name)` --- in other words, some newer module has taken its name and place. - -Another type inference worst case was triggered by the following code from the [QuadGK.jl package](https://github.com/JuliaMath/QuadGK.jl), -formerly part of Base: - -```julia -function do_quadgk(f, s, n, ::Type{Tw}, abstol, reltol, maxevals, nrm) where Tw - if eltype(s) <: Real # check for infinite or semi-infinite intervals - s1 = s[1]; s2 = s[end]; inf1 = isinf(s1); inf2 = isinf(s2) - if inf1 || inf2 - if inf1 && inf2 # x = t/(1-t^2) coordinate transformation - return do_quadgk(t -> begin t2 = t*t; den = 1 / (1 - t2); - f(t*den) * (1+t2)*den*den; end, - map(x -> isinf(x) ? copysign(one(x), x) : 2x / (1+hypot(1,2x)), s), - n, Tw, abstol, reltol, maxevals, nrm) - end - s0,si = inf1 ? (s2,s1) : (s1,s2) - if si < 0 # x = s0 - t/(1-t) - return do_quadgk(t -> begin den = 1 / (1 - t); - f(s0 - t*den) * den*den; end, - reverse!(map(x -> 1 / (1 + 1 / (s0 - x)), s)), - n, Tw, abstol, reltol, maxevals, nrm) - else # x = s0 + t/(1-t) - return do_quadgk(t -> begin den = 1 / (1 - t); - f(s0 + t*den) * den*den; end, - map(x -> 1 / (1 + 1 / (x - s0)), s), - n, Tw, abstol, reltol, maxevals, nrm) - end - end - end -``` - -This code has a 3-way tail recursion, where each call wraps the current function argument `f` -in a different new closure. Inference must consider 3^n (where n is the call depth) possible signatures. -This blows up way too quickly, so logic was added to `typeinf_uncached` to immediately widen any -argument that is a subtype of `Function` and that grows in depth down the stack. diff --git a/test/inference.jl b/test/inference.jl index 542f5fb032e3e..e4b8d33cd8b3f 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -810,7 +810,7 @@ for A in (1,) end # issue #21848 -@test Core.Inference.limit_type_depth(Ref{Complex{T} where T}, Core.Inference.MAX_TYPE_DEPTH) == Ref +@test Core.Inference.limit_type_depth(Ref{Complex{T} where T}, 0) == Ref let T = Tuple{Tuple{Int64, Void}, Tuple{Tuple{Int64, Void}, Tuple{Int64, Tuple{Tuple{Int64, Void}, @@ -910,3 +910,31 @@ end @test isdefined_tfunc(Tuple{Any,Vararg{Any}}, Const(1)) === Const(true) @test isdefined_tfunc(Tuple{Any,Vararg{Any}}, Const(2)) === Bool @test isdefined_tfunc(Tuple{Any,Vararg{Any}}, Const(3)) === Bool + +# demonstrate that inference must converge +# while doing constant propagation +Base.@pure plus1(x) = x + 1 +f21933(x::Val{T}) where {T} = f(Val{plus1(T)}()) +@code_typed f21933(Val{1}()) +Base.return_types(f21933, (Val{1},)) + +function count_specializations(method::Method) + n = 0 + Base.visit(method.specializations) do m + n += 1 + end + return n::Int +end + +# demonstrate that inference can complete without waiting for MAX_TUPLETYPE_LEN or MAX_TYPE_DEPTH +copy_dims_out(out) = () +copy_dims_out(out, dim::Int, tail...) = copy_dims_out((out..., dim), tail...) +copy_dims_out(out, dim::Colon, tail...) = copy_dims_out((out..., dim), tail...) +@test Base.return_types(copy_dims_out, (Tuple{}, Vararg{Union{Int,Colon}})) == Any[Tuple{}, Tuple{}, Tuple{}] +@test all(m -> 2 < count_specializations(m) < 15, methods(copy_dims_out)) + +copy_dims_pair(out) = () +copy_dims_pair(out, dim::Int, tail...) = copy_dims_out(out => dim, tail...) +copy_dims_pair(out, dim::Colon, tail...) = copy_dims_out(out => dim, tail...) +@test Base.return_types(copy_dims_pair, (Tuple{}, Vararg{Union{Int,Colon}})) == Any[Tuple{}, Tuple{}, Tuple{}] +@test all(m -> 5 < count_specializations(m) < 25, methods(copy_dims_out)) From 53761ddc6f50406c848dad05d7c38cce120ae9a4 Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Mon, 12 Jun 2017 15:04:12 -0400 Subject: [PATCH 1063/1534] Use testsets in symmetric.jl (#21996) --- test/linalg/symmetric.jl | 63 +++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 33 deletions(-) diff --git a/test/linalg/symmetric.jl b/test/linalg/symmetric.jl index 3d686a037d09f..65464000410b7 100644 --- a/test/linalg/symmetric.jl +++ b/test/linalg/symmetric.jl @@ -3,24 +3,22 @@ using Base.Test srand(101) -debug = false #Turn on for more debugging info -#Pauli σ-matrices -for σ in map(Hermitian, Any[ eye(2), [0 1; 1 0], [0 -im; im 0], [1 0; 0 -1] ]) +@testset "Pauli σ-matrices: $σ" for σ in map(Hermitian, + Any[ eye(2), [0 1; 1 0], [0 -im; im 0], [1 0; 0 -1] ]) @test ishermitian(σ) end -# Hermitian matrix exponential/log -let A1 = randn(4,4) + im*randn(4,4) +@testset "Hermitian matrix exponential/log" begin + A1 = randn(4,4) + im*randn(4,4) A2 = A1 + A1' @test expm(A2) ≈ expm(Hermitian(A2)) @test logm(A2) ≈ logm(Hermitian(A2)) A3 = A1 * A1' # posdef @test expm(A3) ≈ expm(Hermitian(A3)) @test logm(A3) ≈ logm(Hermitian(A3)) -end -let A1 = randn(4,4) + A1 = randn(4,4) A3 = A1 * A1' A4 = A1 + A1.' @test expm(A4) ≈ expm(Symmetric(A4)) @@ -28,11 +26,12 @@ let A1 = randn(4,4) @test logm(A3) ≈ logm(Hermitian(A3)) end -let n=10 +@testset "Core functionality" begin + n = 10 areal = randn(n,n)/2 aimg = randn(n,n)/2 - debug && println("symmetric eigendecomposition") - for eltya in (Float32, Float64, Complex64, Complex128, BigFloat, Int) + @testset "symmetric eigendecomposition with element type $(eltya)" for eltya in + (Float32, Float64, Complex64, Complex128, BigFloat, Int) a = eltya == Int ? rand(1:7, n, n) : convert(Matrix{eltya}, eltya <: Complex ? complex.(areal, aimg) : areal) asym = a'+a # symmetric indefinite ε = εa = eps(abs(float(one(eltya)))) @@ -44,8 +43,6 @@ let n=10 y = eltya == Int ? rand(1:7, n) : convert(Vector{eltya}, eltya <: Complex ? complex.(y, zeros(n)) : y) b = eltya == Int ? rand(1:7, n, n) : convert(Matrix{eltya}, eltya <: Complex ? complex.(b, zeros(n,n)) : b) - debug && println("\ntype of a: ", eltya, "\n") - # constructor @test Symmetric(Symmetric(asym, :U)) === Symmetric(asym, :U) @test Hermitian(Hermitian(asym, :U)) === Hermitian(asym, :U) @@ -229,48 +226,48 @@ let n=10 end end -#Issue #7647: test xsyevr, xheevr, xstevr drivers -for Mi7647 in (Symmetric(diagm(1.0:3.0)), - Hermitian(diagm(1.0:3.0)), - Hermitian(diagm(complex(1.0:3.0))), - SymTridiagonal([1.0:3.0;], zeros(2))) - debug && println("Eigenvalues in interval for $(typeof(Mi7647))") +#Issue #7647: test xsyevr, xheevr, xstevr drivers. +@testset "Eigenvalues in interval for $(typeof(Mi7647))" for Mi7647 in + (Symmetric(diagm(1.0:3.0)), + Hermitian(diagm(1.0:3.0)), + Hermitian(diagm(complex(1.0:3.0))), + SymTridiagonal([1.0:3.0;], zeros(2))) @test eigmin(Mi7647) == eigvals(Mi7647, 0.5, 1.5)[1] == 1.0 @test eigmax(Mi7647) == eigvals(Mi7647, 2.5, 3.5)[1] == 3.0 @test eigvals(Mi7647) == eigvals(Mi7647, 0.5, 3.5) == [1.0:3.0;] end -#Issue #7933 -let A7933 = [1 2; 3 4] +@testset "Issue #7933" begin + A7933 = [1 2; 3 4] B7933 = copy(A7933) C7933 = full(Symmetric(A7933)) @test A7933 == B7933 end -# Issues #8057 and #8058 -for f in (eigfact, eigvals, eig) - for A in (Symmetric([0 1; 1 0]), Hermitian([0 im; -im 0])) - @test_throws ArgumentError f(A, 3, 2) - @test_throws ArgumentError f(A, 1:4) - end +@testset "Issues #8057 and #8058. f=$f, A=$A" for f in + (eigfact, eigvals, eig), + A in (Symmetric([0 1; 1 0]), Hermitian([0 im; -im 0])) + @test_throws ArgumentError f(A, 3, 2) + @test_throws ArgumentError f(A, 1:4) end -#Issue 10671 -let A = [1.0+im 2.0; 2.0 0.0] +@testset "Issue #10671" begin + A = [1.0+im 2.0; 2.0 0.0] @test !ishermitian(A) @test_throws ArgumentError Hermitian(A) end # Unary minus for Symmetric/Hermitian matrices -let A = randn(5, 5) +@testset "Unary minus for Symmetric/Hermitian matrices" begin + A = randn(5, 5) for SH in (Symmetric(A), Hermitian(A)) F = Matrix(SH) @test (-SH)::typeof(SH) == -F end end -# 17780 -let a = randn(2,2) +@testset "Issue #17780" begin + a = randn(2,2) a = a'a b = complex.(a,a) c = Symmetric(b) @@ -283,8 +280,8 @@ let a = randn(2,2) @test conj!(c) == conj(Array(c)) end -# 19225 -let X = [1 -1; -1 1] +@testset "Issue # 19225" begin + X = [1 -1; -1 1] for T in (Symmetric, Hermitian) Y = T(copy(X)) _Y = similar(Y) From bd2dcf197ba61696965cf84fd8d256bd688bfe6c Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 12 Jun 2017 16:21:00 -0400 Subject: [PATCH 1064/1534] fix #22338 and #22339, specificity problems --- src/subtype.c | 9 +++++++-- test/specificity.jl | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/subtype.c b/src/subtype.c index 7ad25a92be3ab..b0a4a81e1705b 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -2322,11 +2322,17 @@ static int tuple_morespecific(jl_datatype_t *cdt, jl_datatype_t *pdt, int invari if (!cms && !eqv) return 0; + // Tuple{..., T} not more specific than Tuple{..., Vararg{S}} if S is diagonal + if (eqv && i == clen-1 && clen == plen && !cva && pva && jl_is_typevar(ce) && jl_is_typevar(pe) && !cdiag && pdiag) + return 0; + if (cms) some_morespecific = 1; i++; } if (cva && pva && clen > plen && (!pdiag || cdiag)) return 1; + if (cva && !pva && !some_morespecific) + return 0; return some_morespecific || (cdiag && !pdiag); } @@ -2570,8 +2576,7 @@ static int type_morespecific_(jl_value_t *a, jl_value_t *b, int invariant, jl_ty ( type_morespecific_((jl_value_t*)((jl_tvar_t*)b)->lb, (jl_value_t*)((jl_tvar_t*)a)->lb, 0, env) && !type_morespecific_((jl_value_t*)((jl_tvar_t*)b)->ub, - (jl_value_t*)((jl_tvar_t*)a)->ub, 0, env))) && - num_occurs((jl_tvar_t*)a, env) >= num_occurs((jl_tvar_t*)b, env); + (jl_value_t*)((jl_tvar_t*)a)->ub, 0, env))); } if (!jl_is_type(b)) return 0; diff --git a/test/specificity.jl b/test/specificity.jl index 501b4a759ff0f..65ac3c4fbdc91 100644 --- a/test/specificity.jl +++ b/test/specificity.jl @@ -151,3 +151,22 @@ let A = Tuple{Type{D},D} where D<:Pair, @test !args_morespecific(A, B) @test !args_morespecific(C, B) end + +# issue #22338 +let A = Tuple{Ref, Tuple{T}} where T, + B = Tuple{Ref{T}, Tuple{Vararg{T}}} where T, + C = Tuple{Ref{T}, Tuple{T}} where T + @test args_morespecific(C, A) + @test args_morespecific(C, B) + @test !args_morespecific(A, B) + @test !args_morespecific(B, A) +end + +# issue #22339 +let A = Tuple{T, Array{T, 1}} where T, + B = Tuple{T} where T, + C = Tuple{T} where T<:AbstractFloat + @test args_morespecific(B, A) + @test args_morespecific(C, B) + @test args_morespecific(C, A) +end From d19b1be5e94e7c5d161f6c628ce91a67a8ddd982 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 12 Jun 2017 16:28:41 -0400 Subject: [PATCH 1065/1534] test_throws: update to allow passing an instance for comparison this allows concisely writing reliable test_throws tests --- base/test.jl | 31 ++++++++++++++++++++++++------- test/ccall.jl | 26 ++++++++++---------------- test/test.jl | 6 ++++-- 3 files changed, 38 insertions(+), 25 deletions(-) diff --git a/base/test.jl b/base/test.jl index 9180f27061f01..9d9e8c8591876 100644 --- a/base/test.jl +++ b/base/test.jl @@ -99,7 +99,7 @@ function Base.show(io::IO, t::Fail) if t.test_type == :test_throws_wrong # An exception was thrown, but it was of the wrong type print(io, "\n Expected: ", t.data) - print(io, "\n Thrown: ", typeof(t.value)) + print(io, "\n Thrown: ", isa(t.data, Type) ? typeof(t.value) : t.value) elseif t.test_type == :test_throws_nothing # An exception was expected, but no exception was thrown print(io, "\n Expected: ", t.data) @@ -363,9 +363,11 @@ end #----------------------------------------------------------------------- """ - @test_throws extype ex + @test_throws exception expr -Tests that the expression `ex` throws an exception of type `extype`. +Tests that the expression `expr` throws `exception`. +The exception may specify either a type, +or a value (which will be tested for equality by comparing fields). Note that `@test_throws` does not support a trailing keyword form. """ macro test_throws(extype, ex) @@ -383,13 +385,28 @@ end # An internal function, called by the code generated by @test_throws # to evaluate and catch the thrown exception - if it exists -function do_test_throws(result::ExecutionResult, orig_expr, extype) +function do_test_throws(result::ExecutionResult, orig_expr::ANY, extype::ANY) if isa(result, Threw) # Check that the right type of exception was thrown - if isa(result.exception, extype) - testres = Pass(:test_throws, nothing, nothing, result.exception) + success = false + exc = result.exception + if isa(extype, Type) + success = isa(exc, extype) + else + if isa(exc, typeof(extype)) + success = true + for fld in 1:nfields(extype) + if !(getfield(extype, fld) == getfield(exc, fld)) + success = false + break + end + end + end + end + if success + testres = Pass(:test_throws, nothing, nothing, exc) else - testres = Fail(:test_throws_wrong, orig_expr, extype, result.exception) + testres = Fail(:test_throws_wrong, orig_expr, extype, exc) end else testres = Fail(:test_throws_nothing, orig_expr, extype, nothing) diff --git a/test/ccall.jl b/test/ccall.jl index 204a40c6080f3..44cf4e55e5fdd 100644 --- a/test/ccall.jl +++ b/test/ccall.jl @@ -1238,26 +1238,19 @@ for i in 1:100 end # issue #20835 -@test_throws ErrorException eval(:(f20835(x) = ccall(:fn, Void, (Ptr{typeof(x)},), x))) -@test_throws UndefVarError eval(:(f20835(x) = ccall(:fn, Something_not_defined_20835, (Ptr{typeof(x)},), x))) +@test_throws(ErrorException("could not evaluate ccall argument type (it might depend on a local variable)"), + eval(:(f20835(x) = ccall(:fn, Void, (Ptr{typeof(x)},), x)))) +@test_throws(UndefVarError(:Something_not_defined_20835), + eval(:(f20835(x) = ccall(:fn, Something_not_defined_20835, (Ptr{typeof(x)},), x)))) @noinline f21104at(::Type{T}) where {T} = ccall(:fn, Void, (Nullable{T},), 0) @noinline f21104rt(::Type{T}) where {T} = ccall(:fn, Nullable{T}, ()) @test code_llvm(DevNull, f21104at, (Type{Float64},)) === nothing @test code_llvm(DevNull, f21104rt, (Type{Float64},)) === nothing -@test try - f21104at(Float64) - "unreachable" - catch ex - (ex::ErrorException).msg - end == "ccall: the type of argument 1 doesn't correspond to a C type" -@test try - f21104rt(Float64) - "unreachable" - catch ex - (ex::ErrorException).msg - end == "ccall: return type doesn't correspond to a C type" - +@test_throws(ErrorException("ccall: the type of argument 1 doesn't correspond to a C type"), + f21104at(Float64)) +@test_throws(ErrorException("ccall: return type doesn't correspond to a C type"), + f21104rt(Float64)) # cfunction on non-function singleton struct CallableSingleton @@ -1276,4 +1269,5 @@ evalf_callback_19805{FUNC_FT}(ci::callinfos_19805{FUNC_FT}) = ci.f(0.5)::Float64 evalf_callback_c_19805{FUNC_FT}(ci::callinfos_19805{FUNC_FT}) = cfunction( evalf_callback_19805, Float64, (callinfos_19805{FUNC_FT},)) -@test_throws ErrorException evalf_callback_c_19805( callinfos_19805(sin) ) +@test_throws(ErrorException("ccall: the type of argument 1 doesn't correspond to a C type"), + evalf_callback_c_19805( callinfos_19805(sin) )) diff --git a/test/test.jl b/test/test.jl index 01898c234e93c..138758e435a4e 100644 --- a/test/test.jl +++ b/test/test.jl @@ -43,8 +43,10 @@ a[1,1,1,1,1] = 10 @test rand() != rand() # Pass - exception -@test contains(sprint(show, @test_throws ErrorException error()), - "Thrown: ErrorException") +@test endswith(sprint(show, @test_throws ErrorException error()), + "Thrown: ErrorException") +@test endswith(sprint(show, @test_throws ErrorException("test") error("test")), + "Thrown: ErrorException") # Test printing of Fail results mutable struct NoThrowTestSet <: Base.Test.AbstractTestSet From a7e04ad1c4da761f03ab642702856d77d50749b9 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 12 Jun 2017 16:28:41 -0400 Subject: [PATCH 1066/1534] ccall: add syntax validation --- base/event.jl | 2 +- src/julia-syntax.scm | 38 ++++++++++++-------------------------- src/method.c | 9 --------- test/ccall.jl | 14 ++++++++++++++ 4 files changed, 27 insertions(+), 36 deletions(-) diff --git a/base/event.jl b/base/event.jl index d6aaf36263fcd..ed701f3148516 100644 --- a/base/event.jl +++ b/base/event.jl @@ -226,7 +226,7 @@ function wait() # probably broken now, but try discarding this switch and keep going # can't throw here, because it's probably not the fault of the caller to wait # and don't want to use print() here, because that may try to incur a task switch - ccall(:jl_safe_printf, Void, (Ptr{UInt8}, Vararg{Int32}), + ccall(:jl_safe_printf, Void, (Ptr{UInt8}, Int32...), "\nWARNING: Workqueue inconsistency detected: shift!(Workqueue).state != :queued\n") continue end diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index bb4226f56b4c4..03821caa2abba 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -951,20 +951,24 @@ ;; insert calls to convert() in ccall, and pull out expressions that might ;; need to be rooted before conversion. -(define (lower-ccall name RT atypes args) +(define (lower-ccall name RT atypes args cconv) (let loop ((F atypes) ;; formals (A args) ;; actuals (stmts '()) ;; initializers (C '())) ;; converted - (if (or (null? F) (null? A)) + (if (and (null? F) (not (null? A))) (error "more arguments than types for ccall")) + (if (and (null? A) (not (or (null? F) (and (pair? F) (vararg? (car F)) (null? (cdr F)))))) (error "more types than arguments for ccall")) + (if (null? A) `(block ,.(reverse! stmts) (foreigncall ,name ,RT (call (core svec) ,@(dots->vararg atypes)) ,.(reverse! C) - ,@A)) + ,@A + ,@cconv)) (let* ((a (car A)) - (isseq (and (pair? (car F)) (eq? (caar F) '...))) + (isseq (and (vararg? (car F)))) (ty (if isseq (cadar F) (car F)))) + (if (and isseq (not (null? (cdr F)))) (error "only the trailing ccall argument type should have '...'")) (if (eq? ty 'Any) (loop (if isseq F (cdr F)) (cdr A) stmts (list* 0 a C)) (let* ((g (make-ssavalue)) @@ -2080,7 +2084,8 @@ (let ((f (cadr e))) (cond ((dotop? f) (expand-fuse-broadcast '() `(|.| ,(undotop f) (tuple ,@(cddr e))))) - ((and (eq? f 'ccall) (length> e 4)) + ((eq? f 'ccall) + (if (not (length> e 4)) (error "too few arguments to ccall")) (let* ((cconv (cadddr e)) (have-cconv (memq cconv '(cdecl stdcall fastcall thiscall llvmcall))) (after-cconv (if have-cconv (cddddr e) (cdddr e))) @@ -2096,8 +2101,8 @@ (error "ccall argument types must be a tuple; try \"(T,)\" and check if you specified a correct return type") (error "ccall argument types must be a tuple; try \"(T,)\""))) (expand-forms - (lower-ccall name RT (cdr argtypes) - (if have-cconv (append args (list (list cconv))) args)))))) ;; place (callingconv) at end of arglist + (lower-ccall name RT (cdr argtypes) args + (if have-cconv (list (list cconv)) '())))))) ((and (pair? (caddr e)) (eq? (car (caddr e)) 'parameters)) ;; (call f (parameters . kwargs) ...) @@ -2316,25 +2321,6 @@ '|'| (lambda (e) `(call ctranspose ,(expand-forms (cadr e)))) '|.'| (lambda (e) `(call transpose ,(expand-forms (cadr e)))) - 'ccall - (lambda (e) - (syntax-deprecation #f "Expr(:ccall)" "Expr(:call, :ccall)") - (if (length> e 3) - (let ((name (cadr e)) - (RT (caddr e)) - (argtypes (cadddr e)) - (args (cddddr e))) - (begin - (if (not (and (pair? argtypes) - (eq? (car argtypes) 'tuple))) - (if (and (pair? RT) - (eq? (car RT) 'tuple)) - (error "ccall argument types must be a tuple; try \"(T,)\" and check if you specified a correct return type") - (error "ccall argument types must be a tuple; try \"(T,)\""))) - (expand-forms - (lower-ccall name RT (cdr argtypes) args)))) - e)) - 'generator (lambda (e) (let* ((expr (cadr e)) diff --git a/src/method.c b/src/method.c index 123ccd0007b14..630d3d60d2072 100644 --- a/src/method.c +++ b/src/method.c @@ -100,15 +100,6 @@ jl_value_t *jl_resolve_globals(jl_value_t *expr, jl_module_t *module, jl_svec_t jl_error("ccall: missing return type"); JL_TYPECHK(ccall method definition, type, rt); JL_TYPECHK(ccall method definition, simplevector, at); - size_t nargt = jl_svec_len(at); - int isVa = (nargt > 0 && jl_is_vararg_type(jl_svecref(at, nargt - 1))); - if (nargs % 2 == 0) // ignore calling-convention arg, if present - nargs -= 1; - if ((!isVa && nargt != (nargs - 2) / 2) || - ( isVa && nargt - 1 > (nargs - 2) / 2)) { - jl_printf(JL_STDERR, "WARNING: ccall: wrong number of arguments to C function in %s\n", - jl_symbol_name(module->name)); // TODO: make this an error - } } if (e->head == method_sym || e->head == abstracttype_sym || e->head == compositetype_sym || e->head == bitstype_sym || e->head == module_sym) { diff --git a/test/ccall.jl b/test/ccall.jl index 44cf4e55e5fdd..3b2b265652dd1 100644 --- a/test/ccall.jl +++ b/test/ccall.jl @@ -1252,6 +1252,20 @@ end @test_throws(ErrorException("ccall: return type doesn't correspond to a C type"), f21104rt(Float64)) +# test for malformed syntax errors +@test Expr(:error, "more arguments than types for ccall") == expand(@__MODULE__, :(ccall(:fn, A, (), x))) +@test Expr(:error, "more arguments than types for ccall") == expand(@__MODULE__, :(ccall(:fn, A, (B,), x, y))) +@test Expr(:error, "more arguments than types for ccall") == expand(@__MODULE__, :(ccall(:fn, A, (B,), x, y, z))) +@test Expr(:error, "more arguments than types for ccall") == expand(@__MODULE__, :(ccall(:fn, A, (B,), x, y))) +@test Expr(:error, "more arguments than types for ccall") == expand(@__MODULE__, :(ccall(:fn, A, (B,), x, y, z))) +@test Expr(:error, "more arguments than types for ccall") == expand(@__MODULE__, :(ccall(:fn, A, (B, C), x, y, z))) +@test Expr(:error, "more types than arguments for ccall") == expand(@__MODULE__, :(ccall(:fn, A, (B,),))) +@test Expr(:error, "more types than arguments for ccall") == expand(@__MODULE__, :(ccall(:fn, A, (B, C), ))) +@test Expr(:error, "more types than arguments for ccall") == expand(@__MODULE__, :(ccall(:fn, A, (B..., C...), ))) +@test Expr(:error, "only the trailing ccall argument type should have '...'") == expand(@__MODULE__, :(ccall(:fn, A, (B..., C...), x))) +@test Expr(:error, "only the trailing ccall argument type should have '...'") == expand(@__MODULE__, :(ccall(:fn, A, (B..., C...), x, y, z))) +@test Expr(:error, "more types than arguments for ccall") == expand(@__MODULE__, :(ccall(:fn, A, (B, C...), ))) + # cfunction on non-function singleton struct CallableSingleton end From 39e5b0c634969383a886ac10a9fd6547dffa1fe4 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Tue, 13 Jun 2017 02:18:36 +0200 Subject: [PATCH 1067/1534] isposdef rewrite with help of cholfact (#22245) --- NEWS.md | 4 ++++ base/deprecated.jl | 4 ++++ base/linalg/cholesky.jl | 10 ++++++---- base/linalg/dense.jl | 22 ++++++++-------------- base/linalg/symmetric.jl | 2 -- test/linalg/cholesky.jl | 11 +++++++++++ test/linalg/dense.jl | 7 ++++++- test/linalg/diagonal.jl | 1 + test/linalg/eigen.jl | 3 ++- 9 files changed, 42 insertions(+), 22 deletions(-) diff --git a/NEWS.md b/NEWS.md index 056f62e2d8549..cff38eca2c720 100644 --- a/NEWS.md +++ b/NEWS.md @@ -83,6 +83,10 @@ Deprecated or removed * The `cholfact`/`cholfact!` methods that accepted an `uplo` symbol have been deprecated in favor of using `Hermitian` (or `Symmetric`) views ([#22187], [#22188]). + * `isposdef(A::AbstractMatrix, UL::Symbol)` and `isposdef!(A::AbstractMatrix, UL::Symbol)` + have been deprecated in favor of `isposdef(Hermitian(A, UL))` and `isposdef!(Hermitian(A, UL))` + respectively ([#22245]). + * The function `current_module` is deprecated and replaced with `@__MODULE__` ([#22064]). This caused the deprecation of some reflection methods (such as `macroexpand` and `isconst`), which now require a module argument. diff --git a/base/deprecated.jl b/base/deprecated.jl index 555998ca6f546..4defa517f7c34 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1361,6 +1361,10 @@ end @deprecate cholfact!(A::StridedMatrix, uplo::Symbol, ::Type{Val{true}}; tol = 0.0) cholfact!(Hermitian(A, uplo), Val{true}, tol = tol) @deprecate cholfact(A::StridedMatrix, uplo::Symbol, ::Type{Val{true}}; tol = 0.0) cholfact(Hermitian(A, uplo), Val{true}, tol = tol) +# PR #22245 +@deprecate isposdef(A::AbstractMatrix, UL::Symbol) isposdef(Hermitian(A, UL)) +@deprecate isposdef!(A::StridedMatrix, UL::Symbol) isposdef!(Hermitian(A, UL)) + # also remove all support machinery in src for current_module when removing this deprecation # and make Base.include an error _current_module() = ccall(:jl_get_current_module, Ref{Module}, ()) diff --git a/base/linalg/cholesky.jl b/base/linalg/cholesky.jl index ca9f7c2be51c3..434a7fdbe5a5c 100644 --- a/base/linalg/cholesky.jl +++ b/base/linalg/cholesky.jl @@ -288,7 +288,7 @@ and return a `Cholesky` factorization. The matrix `A` can either be a [`Symmetri `StridedMatrix` or a *perfectly* symmetric or Hermitian `StridedMatrix`. The triangular Cholesky factor can be obtained from the factorization `F` with: `F[:L]` and `F[:U]`. The following functions are available for `Cholesky` objects: [`size`](@ref), [`\\`](@ref), -[`inv`](@ref), and [`det`](@ref). +[`inv`](@ref), [`det`](@ref), [`logdet`](@ref) and [`isposdef`](@ref). # Example @@ -461,17 +461,19 @@ function A_ldiv_B!(C::CholeskyPivoted, B::StridedMatrix) end end +isposdef(C::Cholesky) = C.info == 0 + function det(C::Cholesky) - C.info == 0 || throw(PosDefException(C.info)) dd = one(real(eltype(C))) @inbounds for i in 1:size(C.factors,1) dd *= real(C.factors[i,i])^2 end - dd + @assertposdef dd C.info end function logdet(C::Cholesky) - C.info == 0 || throw(PosDefException(C.info)) + # need to check first, or log will throw DomainError + isposdef(C) || throw(PosDefException(C.info)) dd = zero(real(eltype(C))) @inbounds for i in 1:size(C.factors,1) dd += log(real(C.factors[i,i])) diff --git a/base/linalg/dense.jl b/base/linalg/dense.jl index c1dc43965e13b..c58d9afe6fe10 100644 --- a/base/linalg/dense.jl +++ b/base/linalg/dense.jl @@ -29,13 +29,12 @@ function scale!(X::Array{T}, s::Real) where T<:BlasComplex X end -# Test whether a matrix is positive-definite -isposdef!(A::StridedMatrix{<:BlasFloat}, UL::Symbol) = LAPACK.potrf!(char_uplo(UL), A)[2] == 0 - """ isposdef!(A) -> Bool -Test whether a matrix is positive definite, overwriting `A` in the process. +Test whether a matrix is positive definite by trying to perform a +Cholesky factorization of `A`, overwriting `A` in the process. +See also [`isposdef`](@ref). # Example @@ -51,16 +50,14 @@ julia> A 2.0 6.78233 ``` """ -isposdef!(A::StridedMatrix) = ishermitian(A) && isposdef!(A, :U) +isposdef!(A::AbstractMatrix) = ishermitian(A) && isposdef(cholfact!(Hermitian(A))) -function isposdef(A::AbstractMatrix{T}, UL::Symbol) where T - S = typeof(sqrt(one(T))) - isposdef!(S == T ? copy(A) : convert(AbstractMatrix{S}, A), UL) -end """ isposdef(A) -> Bool -Test whether a matrix is positive definite. +Test whether a matrix is positive definite by trying to perform a +Cholesky factorization of `A`. +See also [`isposdef!`](@ref) # Example @@ -74,10 +71,7 @@ julia> isposdef(A) true ``` """ -function isposdef(A::AbstractMatrix{T}) where T - S = typeof(sqrt(one(T))) - isposdef!(S == T ? copy(A) : convert(AbstractMatrix{S}, A)) -end +isposdef(A::AbstractMatrix) = ishermitian(A) && isposdef(cholfact(Hermitian(A))) isposdef(x::Number) = imag(x)==0 && real(x) > 0 stride1(x::Array) = 1 diff --git a/base/linalg/symmetric.jl b/base/linalg/symmetric.jl index 9dc5bc9a083a0..7645908ddf25d 100644 --- a/base/linalg/symmetric.jl +++ b/base/linalg/symmetric.jl @@ -315,8 +315,6 @@ det(A::Symmetric) = det(bkfact(A)) inv(A::Hermitian{T,S}) where {T<:BlasFloat,S<:StridedMatrix} = Hermitian{T,S}(inv(bkfact(A)), A.uplo) inv(A::Symmetric{T,S}) where {T<:BlasFloat,S<:StridedMatrix} = Symmetric{T,S}(inv(bkfact(A)), A.uplo) -isposdef!(A::HermOrSym{<:BlasFloat,<:StridedMatrix}) = ishermitian(A) && LAPACK.potrf!(A.uplo, A.data)[2] == 0 - eigfact!(A::RealHermSymComplexHerm{<:BlasReal,<:StridedMatrix}) = Eigen(LAPACK.syevr!('V', 'A', A.uplo, A.data, 0.0, 0.0, 0, 0, -1.0)...) function eigfact(A::RealHermSymComplexHerm) diff --git a/test/linalg/cholesky.jl b/test/linalg/cholesky.jl index 531f19ee15230..3152ca219475d 100644 --- a/test/linalg/cholesky.jl +++ b/test/linalg/cholesky.jl @@ -67,10 +67,14 @@ using Base.LinAlg: BlasComplex, BlasFloat, BlasReal, QRPivoted, PosDefException capds = cholfact(apds) @test inv(capds)*apds ≈ eye(n) @test abs((det(capds) - det(apd))/det(capds)) <= ε*κ*n + @test logdet(capds) ≈ log(det(capds)) + @test isposdef(capds) if eltya <: BlasReal capds = cholfact!(copy(apds)) @test inv(capds)*apds ≈ eye(n) @test abs((det(capds) - det(apd))/det(capds)) <= ε*κ*n + @test logdet(capds) ≈ log(det(capds)) + @test isposdef(capds) end ulstring = sprint(show,capds[:UL]) @test sprint(show,capds) == "$(typeof(capds)) with factor:\n$ulstring" @@ -78,12 +82,18 @@ using Base.LinAlg: BlasComplex, BlasFloat, BlasReal, QRPivoted, PosDefException capdh = cholfact(apdh) @test inv(capdh)*apdh ≈ eye(n) @test abs((det(capdh) - det(apd))/det(capdh)) <= ε*κ*n + @test logdet(capdh) ≈ log(det(capdh)) + @test isposdef(capdh) capdh = cholfact!(copy(apdh)) @test inv(capdh)*apdh ≈ eye(n) @test abs((det(capdh) - det(apd))/det(capdh)) <= ε*κ*n + @test logdet(capdh) ≈ log(det(capdh)) + @test isposdef(capdh) capdh = cholfact!(copy(apd)) @test inv(capdh)*apdh ≈ eye(n) @test abs((det(capdh) - det(apd))/det(capdh)) <= ε*κ*n + @test logdet(capdh) ≈ log(det(capdh)) + @test isposdef(capdh) ulstring = sprint(show,capdh[:UL]) @test sprint(show,capdh) == "$(typeof(capdh)) with factor:\n$ulstring" end @@ -270,6 +280,7 @@ end for T in (Float32, Float64, Complex64, Complex128) A = T[1 2; 2 1]; B = T[1, 1] C = cholfact(A) + @test !isposdef(C) @test_throws PosDefException C\B @test_throws PosDefException det(C) @test_throws PosDefException logdet(C) diff --git a/test/linalg/dense.jl b/test/linalg/dense.jl index 3f1b316ba3905..74d26f0601c93 100644 --- a/test/linalg/dense.jl +++ b/test/linalg/dense.jl @@ -49,7 +49,12 @@ bimg = randn(n,2)/2 apd = ainit'*ainit # symmetric positive-definite @testset "Positive definiteness" begin - @test isposdef(apd,:U) + @test !isposdef(ainit) + @test isposdef(apd) + if eltya != Int # cannot perform cholfact! for Matrix{Int} + @test !isposdef!(copy(ainit)) + @test isposdef!(copy(apd)) + end end @testset "For b containing $eltyb" for eltyb in (Float32, Float64, Complex64, Complex128, Int) binit = eltyb == Int ? rand(1:5, n, 2) : convert(Matrix{eltyb}, eltyb <: Complex ? complex.(breal, bimg) : breal) diff --git a/test/linalg/diagonal.jl b/test/linalg/diagonal.jl index 6c2f8b2977bcb..d551b24548db0 100644 --- a/test/linalg/diagonal.jl +++ b/test/linalg/diagonal.jl @@ -235,6 +235,7 @@ end end @testset "isposdef" begin + @test isposdef(Diagonal(1.0 + rand(n))) @test !isposdef(Diagonal(-1.0 * rand(n))) end diff --git a/test/linalg/eigen.jl b/test/linalg/eigen.jl index c44563e5676f2..5e6ec48db16f2 100644 --- a/test/linalg/eigen.jl +++ b/test/linalg/eigen.jl @@ -35,14 +35,15 @@ aimg = randn(n,n)/2 @test eab[1] == eigvals(fill(α,1,1),fill(β,1,1)) @test eab[2] == eigvecs(fill(α,1,1),fill(β,1,1)) - d,v = eig(a) @testset "non-symmetric eigen decomposition" begin + d, v = eig(a) for i in 1:size(a,2) @test a*v[:,i] ≈ d[i]*v[:,i] end f = eigfact(a) @test det(a) ≈ det(f) @test inv(a) ≈ inv(f) + @test isposdef(a) == isposdef(f) @test eigvals(f) === f[:values] @test eigvecs(f) === f[:vectors] From 85b42fa2e97b4e76c2f2ed28d159767220a3f82e Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Mon, 12 Jun 2017 23:18:41 -0400 Subject: [PATCH 1068/1534] fix #22347, `_apply` optimization dropping argument expressions --- base/inference.jl | 3 ++- test/inference.jl | 11 +++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/base/inference.jl b/base/inference.jl index a9829626bed31..e65885b4a0be2 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -4595,7 +4595,8 @@ function inlining_pass(e::Expr, sv::InferenceState, stmts, ins) if isa(aarg,Expr) && (is_known_call(aarg, tuple, sv.src, sv.mod) || is_known_call(aarg, svec, sv.src, sv.mod)) # apply(f,tuple(x,y,...)) => f(x,y,...) newargs[i-2] = aarg.args[2:end] - elseif isa(argt,Const) && (isa(argt.val, Tuple) || isa(argt.val, SimpleVector)) + elseif isa(argt,Const) && (isa(argt.val, Tuple) || isa(argt.val, SimpleVector)) && + effect_free(aarg, sv.src, sv.mod, true) newargs[i-2] = Any[ QuoteNode(x) for x in argt.val ] elseif isa(aarg, Tuple) || (isa(aarg, QuoteNode) && (isa(aarg.value, Tuple) || isa(aarg.value, SimpleVector))) if isa(aarg, QuoteNode) diff --git a/test/inference.jl b/test/inference.jl index 542f5fb032e3e..a4004c0ad30ee 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -910,3 +910,14 @@ end @test isdefined_tfunc(Tuple{Any,Vararg{Any}}, Const(1)) === Const(true) @test isdefined_tfunc(Tuple{Any,Vararg{Any}}, Const(2)) === Bool @test isdefined_tfunc(Tuple{Any,Vararg{Any}}, Const(3)) === Bool + +@noinline map3_22347(f, t::Tuple{}) = () +@noinline map3_22347(f, t::Tuple) = (f(t[1]), map3_22347(f, Base.tail(t))...) +# issue #22347 +let niter = 0 + map3_22347((1, 2, 3, 4)) do y + niter += 1 + nothing + end + @test niter == 4 +end From 51ad96f956eec56af8b6dbb62cd16a228553947f Mon Sep 17 00:00:00 2001 From: Amit Murthy Date: Tue, 13 Jun 2017 10:05:33 +0530 Subject: [PATCH 1069/1534] fix leak in WorkerPool. (#22185) --- base/distributed/workerpool.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/base/distributed/workerpool.jl b/base/distributed/workerpool.jl index 2abee54e57ac8..4c0c24dc82449 100644 --- a/base/distributed/workerpool.jl +++ b/base/distributed/workerpool.jl @@ -25,7 +25,7 @@ end function WorkerPool() wp = WorkerPool(Channel{Int}(typemax(Int)), RemoteChannel()) - put!(wp.ref, wp) + put!(wp.ref, WeakRef(wp)) wp end @@ -124,7 +124,7 @@ for func = (:length, :isready, :workers, :nworkers, :take!) @eval begin function ($func)(pool::WorkerPool) if pool.ref.where != myid() - return remotecall_fetch(ref->($func_local)(fetch(ref)), pool.ref.where, pool.ref) + return remotecall_fetch(ref->($func_local)(fetch(ref).value), pool.ref.where, pool.ref) else return ($func_local)(pool) end @@ -140,7 +140,7 @@ for func = (:push!, :put!) @eval begin function ($func)(pool::WorkerPool, w::Int) if pool.ref.where != myid() - return remotecall_fetch((ref, w)->($func_local)(fetch(ref), w), pool.ref.where, pool.ref, w) + return remotecall_fetch((ref, w)->($func_local)(fetch(ref).value, w), pool.ref.where, pool.ref, w) else return ($func_local)(pool, w) end From 8b8fa11c26f29a451537ff65e2ac18dbad85eacc Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Mon, 12 Jun 2017 21:44:00 -0700 Subject: [PATCH 1070/1534] Avoid setting the RPATH for LLVM --- deps/libgit2.mk | 5 ++++- deps/libssh2.mk | 4 ++++ deps/mbedtls.mk | 4 ++++ deps/tools/common.mk | 10 ++++------ 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/deps/libgit2.mk b/deps/libgit2.mk index 11d5bcbee196b..2d518cf2ac9c0 100644 --- a/deps/libgit2.mk +++ b/deps/libgit2.mk @@ -37,7 +37,10 @@ LIBGIT2_OPTS += -DCURL_INCLUDE_DIRS=$(build_includedir) -DCURL_LIBRARIES="-L$(bu endif ifeq ($(OS),Linux) -LIBGIT2_OPTS += -DUSE_OPENSSL=OFF -DUSE_MBEDTLS=ON +LIBGIT2_OPTS += -DUSE_OPENSSL=OFF -DUSE_MBEDTLS=ON -DCMAKE_INSTALL_RPATH="\$$ORIGIN" +endif +ifeq ($(OS),FreeBSD) +LIBGIT2_OPTS += -DCMAKE_INSTALL_RPATH="\$$ORIGIN" endif # We need to bundle ca certs on linux now that we're using libgit2 with ssl diff --git a/deps/libssh2.mk b/deps/libssh2.mk index ea77379988ac0..e0f91a1b6f21f 100644 --- a/deps/libssh2.mk +++ b/deps/libssh2.mk @@ -20,6 +20,10 @@ else LIBSSH2_OPTS += -DCRYPTO_BACKEND=mbedTLS -DENABLE_ZLIB_COMPRESSION=OFF endif +ifneq (,$(findstring $(OS),Linux FreeBSD)) +LIBSSH2_OPTS += -DCMAKE_INSTALL_RPATH="\$$ORIGIN" +endif + $(SRCDIR)/srccache/$(LIBSSH2_SRC_DIR)/libssh2-encryptedpem.patch-applied: $(SRCDIR)/srccache/$(LIBSSH2_SRC_DIR)/source-extracted cd $(SRCDIR)/srccache/$(LIBSSH2_SRC_DIR) && patch -p1 -f < $(SRCDIR)/patches/libssh2-encryptedpem.patch echo 1 > $@ diff --git a/deps/mbedtls.mk b/deps/mbedtls.mk index 9ebc0c071dbdd..894551a790927 100644 --- a/deps/mbedtls.mk +++ b/deps/mbedtls.mk @@ -15,6 +15,10 @@ ifeq ($(BUILD_OS),WINNT) MBEDTLS_OPTS += -G"MSYS Makefiles" endif +ifneq (,$(findstring $(OS),Linux FreeBSD)) +MBEDTLS_OPTS += -DCMAKE_INSTALL_RPATH="\$$ORIGIN" +endif + $(SRCDIR)/srccache/$(MBEDTLS_SRC).tgz: | $(SRCDIR)/srccache $(JLDOWNLOAD) $@ $(MBEDTLS_URL) diff --git a/deps/tools/common.mk b/deps/tools/common.mk index edab53c5f7682..2a3b735beeac5 100644 --- a/deps/tools/common.mk +++ b/deps/tools/common.mk @@ -40,16 +40,14 @@ CMAKE_COMMON += -DCMAKE_RC_COMPILER="$$(which $(CROSS_COMPILE)windres)" endif endif -ifneq (,$(findstring $(OS),Linux FreeBSD)) -INSTALL_RPATH := "\$$ORIGIN" -# Part of the FreeBSD libgcc_s kludge +# NOTE: Do not make RPATH changes in CMAKE_COMMON on platforms other than FreeBSD, since +# it will make its way into the LLVM build flags, and LLVM is picky about RPATH (though +# apparently not on FreeBSD). Ref PR #22352 ifeq ($(OS),FreeBSD) ifneq ($(GCCPATH),) -INSTALL_RPATH := "\$$ORIGIN:$(GCCPATH)" +CMAKE_COMMON += -DCMAKE_INSTALL_RPATH="\$$ORIGIN:$(GCCPATH)" endif endif -CMAKE_COMMON += -DCMAKE_INSTALL_RPATH=$(INSTALL_RPATH) -endif # Linux or FreeBSD # For now this is LLVM specific, but I expect it won't be in the future ifeq ($(LLVM_USE_CMAKE),1) From 9e37db0d7ddde2ae8ae81b8142771a3694a0dc91 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Tue, 13 Jun 2017 01:01:01 -0400 Subject: [PATCH 1071/1534] Declare LLVM Make variables as simply-expanded, not recursively expanded --- deps/llvm.mk | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/deps/llvm.mk b/deps/llvm.mk index 79b5d6f8d4969..351bb38908348 100644 --- a/deps/llvm.mk +++ b/deps/llvm.mk @@ -60,6 +60,12 @@ else LLVM_TARGETS := host;NVPTX endif +LLVM_CFLAGS := +LLVM_CXXFLAGS := +LLVM_CPPFLAGS := +LLVM_LDFLAGS := +LLVM_CMAKE := + # Allow adding LLVM specific flags LLVM_CFLAGS += $(CFLAGS) LLVM_CXXFLAGS += $(CXXFLAGS) From c6799e64372209cad36b14b95cd05b5d53d001d5 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Tue, 13 Jun 2017 08:58:30 +0200 Subject: [PATCH 1072/1534] enable rand(::Union{AbstractSet,Associative}) (#22228) --- base/random.jl | 42 +++++++++++++++++++++++++++++++----------- base/test.jl | 38 +++++++++++++++++++++++++++++++++++++- test/random.jl | 22 ++++++++++++++-------- 3 files changed, 82 insertions(+), 20 deletions(-) diff --git a/base/random.jl b/base/random.jl index e6f795b75378d..f95e0ed7354a4 100644 --- a/base/random.jl +++ b/base/random.jl @@ -257,13 +257,15 @@ globalRNG() = GLOBAL_RNG Pick a random element or array of random elements from the set of values specified by `S`; `S` can be * an indexable collection (for example `1:n` or `['x','y','z']`), or -* a `Dict`, a `Set` or an `IntSet`, or +* an `Associative` or `AbstractSet` object, or * a type: the set of values to pick from is then equivalent to `typemin(S):typemax(S)` for integers (this is not applicable to [`BigInt`](@ref)), and to ``[0, 1)`` for floating point numbers; `S` defaults to [`Float64`](@ref). +# Examples + ```julia-repl julia> rand(Int, 2) 2-element Array{Int64,1}: @@ -273,6 +275,14 @@ julia> rand(Int, 2) julia> rand(MersenneTwister(0), Dict(1=>2, 3=>4)) 1=>2 ``` + +!!! note + The complexity of `rand(rng, s::Union{Associative,AbstractSet})` + is linear in the length of `s`, unless an optimized method with + constant complexity is available, which is the case for `Dict`, + `Set` and `IntSet`. For more than a few calls, use `rand(rng, + collect(s))` instead, or either `rand(rng, Dict(s))` or `rand(rng, + Set(s))` as appropriate. """ @inline rand() = rand(GLOBAL_RNG, CloseOpen) @inline rand(T::Type) = rand(GLOBAL_RNG, T) @@ -362,9 +372,8 @@ function rand(r::AbstractRNG, t::Dict) Base.isslotfilled(t, i) && @inbounds return (t.keys[i] => t.vals[i]) end end -rand(t::Dict) = rand(GLOBAL_RNG, t) + rand(r::AbstractRNG, s::Set) = rand(r, s.dict).first -rand(s::Set) = rand(GLOBAL_RNG, s) function rand(r::AbstractRNG, s::IntSet) isempty(s) && throw(ArgumentError("collection must be non-empty")) @@ -378,7 +387,16 @@ function rand(r::AbstractRNG, s::IntSet) end end -rand(s::IntSet) = rand(GLOBAL_RNG, s) +function nth(iter, n::Integer)::eltype(iter) + for (i, x) in enumerate(iter) + i == n && return x + end +end +nth(iter::AbstractArray, n::Integer) = iter[n] + +rand(r::AbstractRNG, s::Union{Associative,AbstractSet}) = nth(s, rand(r, 1:length(s))) + +rand(s::Union{Associative,AbstractSet}) = rand(GLOBAL_RNG, s) ## Arrays of random numbers @@ -407,14 +425,16 @@ function rand!(r::AbstractRNG, A::AbstractArray, s::Union{Dict,Set,IntSet}) A end -rand!(A::AbstractArray, s::Union{Dict,Set,IntSet}) = rand!(GLOBAL_RNG, A, s) +# avoid linear complexity for repeated calls with generic containers +rand!(r::AbstractRNG, A::AbstractArray, s::Union{Associative,AbstractSet}) = rand!(r, A, collect(s)) + +rand!(A::AbstractArray, s::Union{Associative,AbstractSet}) = rand!(GLOBAL_RNG, A, s) -rand(r::AbstractRNG, s::Dict{K,V}, dims::Dims) where {K,V} = rand!(r, Array{Pair{K,V}}(dims), s) -rand(r::AbstractRNG, s::Set{T}, dims::Dims) where {T} = rand!(r, Array{T}(dims), s) -rand(r::AbstractRNG, s::IntSet, dims::Dims) = rand!(r, Array{Int}(dims), s) -rand(r::AbstractRNG, s::Union{Dict,Set,IntSet}, dims::Integer...) = rand(r, s, convert(Dims, dims)) -rand(s::Union{Dict,Set,IntSet}, dims::Integer...) = rand(GLOBAL_RNG, s, convert(Dims, dims)) -rand(s::Union{Dict,Set,IntSet}, dims::Dims) = rand(GLOBAL_RNG, s, dims) +rand(r::AbstractRNG, s::Associative{K,V}, dims::Dims) where {K,V} = rand!(r, Array{Pair{K,V}}(dims), s) +rand(r::AbstractRNG, s::AbstractSet{T}, dims::Dims) where {T} = rand!(r, Array{T}(dims), s) +rand(r::AbstractRNG, s::Union{Associative,AbstractSet}, dims::Integer...) = rand(r, s, convert(Dims, dims)) +rand(s::Union{Associative,AbstractSet}, dims::Integer...) = rand(GLOBAL_RNG, s, convert(Dims, dims)) +rand(s::Union{Associative,AbstractSet}, dims::Dims) = rand(GLOBAL_RNG, s, dims) # MersenneTwister diff --git a/base/test.jl b/base/test.jl index 9180f27061f01..80eacffa61642 100644 --- a/base/test.jl +++ b/base/test.jl @@ -11,6 +11,8 @@ test set that throws on the first failure. Users can choose to wrap their tests in (possibly nested) test sets that will store results and summarize them at the end of the test set with `@testset`. """ +:Test # cf. #22288 + module Test export @test, @test_throws, @test_broken, @test_skip, @test_warn, @test_nowarn @@ -18,7 +20,7 @@ export @testset # Legacy approximate testing functions, yet to be included export @inferred export detect_ambiguities -export GenericString +export GenericString, GenericSet, GenericDict #----------------------------------------------------------------------- @@ -1182,4 +1184,38 @@ Base.convert(::Type{GenericString}, s::AbstractString) = GenericString(s) Base.endof(s::GenericString) = endof(s.string) Base.next(s::GenericString, i::Int) = next(s.string, i) +""" +The `GenericSet` can be used to test generic set APIs that program to +the `AbstractSet` interface, in order to ensure that functions can work +with set types besides the standard `Set` and `IntSet` types. +""" +struct GenericSet{T} <: AbstractSet{T} + s::AbstractSet{T} +end + +""" +The `GenericDict` can be used to test generic dict APIs that program to +the `Associative` interface, in order to ensure that functions can work +with associative types besides the standard `Dict` type. +""" +struct GenericDict{K,V} <: Associative{K,V} + s::Associative{K,V} +end + +for (G, A) in ((GenericSet, AbstractSet), + (GenericDict, Associative)) + @eval begin + Base.convert(::Type{$G}, s::$A) = $G(s) + Base.done(s::$G, state) = done(s.s, state) + Base.next(s::$G, state) = next(s.s, state) + end + for f in (:eltype, :isempty, :length, :start) + @eval begin + Base.$f(s::$G) = $f(s.s) + end + end +end + +Base.get(s::GenericDict, x, y) = get(s.s, x, y) + end # module diff --git a/test/random.jl b/test/random.jl index 6752a68e65c15..5672ff3066e6d 100644 --- a/test/random.jl +++ b/test/random.jl @@ -309,13 +309,18 @@ for rng in ([], [MersenneTwister(0)], [RandomDevice()]) ftypes = [Float16, Float32, Float64] cftypes = [Complex32, Complex64, Complex128, ftypes...] types = [Bool, Char, Base.BitInteger_types..., ftypes...] - collections = [IntSet(rand(1:100, 20)) => Int, - Set(rand(Int, 20)) => Int, - Dict(zip(rand(Int,10), rand(Int, 10))) => Pair{Int,Int}, - 1:100 => Int, - rand(Int, 100) => Int, - Int => Int, - Float64 => Float64] + randset = Set(rand(Int, 20)) + randdict = Dict(zip(rand(Int,10), rand(Int, 10))) + collections = [IntSet(rand(1:100, 20)) => Int, + randset => Int, + GenericSet(randset) => Int, + randdict => Pair{Int,Int}, + GenericDict(randdict) => Pair{Int,Int}, + 1:100 => Int, + rand(Int, 100) => Int, + Int => Int, + Float64 => Float64] + b2 = big(2) u3 = UInt(3) for f in [rand, randn, randexp] @@ -352,7 +357,8 @@ for rng in ([], [MersenneTwister(0)], [RandomDevice()]) end end end - for C in [1:0, Dict(), Set(), IntSet(), Int[]] + for C in [1:0, Dict(), Set(), IntSet(), Int[], + GenericDict(Dict()), GenericSet(Set())] @test_throws ArgumentError rand(rng..., C) @test_throws ArgumentError rand(rng..., C, 5) end From 49ea8df142b8df7c7ce7a4df5221c4edcd3f7581 Mon Sep 17 00:00:00 2001 From: Mus M Date: Tue, 13 Jun 2017 03:08:37 -0400 Subject: [PATCH 1073/1534] Update ast.md to where syntax (#22109) --- doc/src/devdocs/ast.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/doc/src/devdocs/ast.md b/doc/src/devdocs/ast.md index bcde2617b7b1d..16724c3154954 100644 --- a/doc/src/devdocs/ast.md +++ b/doc/src/devdocs/ast.md @@ -476,7 +476,8 @@ parses as: ``` (if a (block (line 2) b) (block (line 3) (if c (block (line 4) d) - (block (line 5) e (line 6) f)))) + (block (line 5) e + (line 6) f)))) ``` A `while` loop parses as `(while condition body)`. @@ -491,7 +492,7 @@ they are parsed as a block: `(for (block (= v1 iter1) (= v2 iter2)) body)`. A basic function definition is parsed as `(function (call f x) body)`. A more complex example: ```julia -function f{T}(x::T; k = 1) +function f(x::T; k = 1) where T return x+1 end ``` @@ -499,9 +500,10 @@ end parses as: ``` -(function (call (curly f T) (parameters (kw k 1)) - (:: x T)) - (block (line 2 file.jl) (return (call + x 1)))) +(function (where (call f (parameters (kw k 1)) + (:: x T)) + T) + (block (line 2) (return (call + x 1)))) ``` Type definition: @@ -515,8 +517,8 @@ end parses as: ``` -(type #t (curly Foo (<: T S)) - (block (line 2 none) (:: x T))) +(type true (curly Foo (<: T S)) + (block (line 2) (:: x T))) ``` The first argument is a boolean telling whether the type is mutable. From 5c89a9db5eb2ae91b4cdc5f944bb294308a01020 Mon Sep 17 00:00:00 2001 From: Tony Kelman Date: Tue, 13 Jun 2017 06:09:59 -0700 Subject: [PATCH 1074/1534] Update appveyor llvm binaries to include latest patches --- appveyor.yml | 4 ++-- contrib/windows/msys_build.sh | 2 +- .../llvm-3.9.1-i686-w64-mingw32-juliadeps-r04.7z/md5 | 1 - .../llvm-3.9.1-i686-w64-mingw32-juliadeps-r04.7z/sha512 | 1 - .../llvm-3.9.1-i686-w64-mingw32-juliadeps-r06.7z/md5 | 1 + .../llvm-3.9.1-i686-w64-mingw32-juliadeps-r06.7z/sha512 | 1 + .../llvm-3.9.1-x86_64-w64-mingw32-juliadeps-r04.7z/md5 | 1 - .../llvm-3.9.1-x86_64-w64-mingw32-juliadeps-r04.7z/sha512 | 1 - .../llvm-3.9.1-x86_64-w64-mingw32-juliadeps-r06.7z/md5 | 1 + .../llvm-3.9.1-x86_64-w64-mingw32-juliadeps-r06.7z/sha512 | 1 + 10 files changed, 7 insertions(+), 7 deletions(-) delete mode 100644 deps/checksums/llvm-3.9.1-i686-w64-mingw32-juliadeps-r04.7z/md5 delete mode 100644 deps/checksums/llvm-3.9.1-i686-w64-mingw32-juliadeps-r04.7z/sha512 create mode 100644 deps/checksums/llvm-3.9.1-i686-w64-mingw32-juliadeps-r06.7z/md5 create mode 100644 deps/checksums/llvm-3.9.1-i686-w64-mingw32-juliadeps-r06.7z/sha512 delete mode 100644 deps/checksums/llvm-3.9.1-x86_64-w64-mingw32-juliadeps-r04.7z/md5 delete mode 100644 deps/checksums/llvm-3.9.1-x86_64-w64-mingw32-juliadeps-r04.7z/sha512 create mode 100644 deps/checksums/llvm-3.9.1-x86_64-w64-mingw32-juliadeps-r06.7z/md5 create mode 100644 deps/checksums/llvm-3.9.1-x86_64-w64-mingw32-juliadeps-r06.7z/sha512 diff --git a/appveyor.yml b/appveyor.yml index 44027c9244827..6028d4dc4af1e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -33,8 +33,8 @@ cache: # Cache large downloads to avoid network unreliability - i686-4.9.2-release-win32-sjlj-rt_v4-rev3.7z - x86_64-4.9.2-release-win32-seh-rt_v4-rev3.7z - - llvm-3.9.1-i686-w64-mingw32-juliadeps-r04.7z - - llvm-3.9.1-x86_64-w64-mingw32-juliadeps-r04.7z + - llvm-3.9.1-i686-w64-mingw32-juliadeps-r06.7z + - llvm-3.9.1-x86_64-w64-mingw32-juliadeps-r06.7z - usr/bin/busybox.exe build_script: diff --git a/contrib/windows/msys_build.sh b/contrib/windows/msys_build.sh index f33930c02d035..bda423a761910 100755 --- a/contrib/windows/msys_build.sh +++ b/contrib/windows/msys_build.sh @@ -123,7 +123,7 @@ if [ -z "$USEMSVC" ]; then fi export AR=${CROSS_COMPILE}ar - f=llvm-3.9.1-$ARCH-w64-mingw32-juliadeps-r04.7z + f=llvm-3.9.1-$ARCH-w64-mingw32-juliadeps-r06.7z else echo "override USEMSVC = 1" >> Make.user echo "override ARCH = $ARCH" >> Make.user diff --git a/deps/checksums/llvm-3.9.1-i686-w64-mingw32-juliadeps-r04.7z/md5 b/deps/checksums/llvm-3.9.1-i686-w64-mingw32-juliadeps-r04.7z/md5 deleted file mode 100644 index cb690525311e1..0000000000000 --- a/deps/checksums/llvm-3.9.1-i686-w64-mingw32-juliadeps-r04.7z/md5 +++ /dev/null @@ -1 +0,0 @@ -912e986977539e14fccaac70229852cc diff --git a/deps/checksums/llvm-3.9.1-i686-w64-mingw32-juliadeps-r04.7z/sha512 b/deps/checksums/llvm-3.9.1-i686-w64-mingw32-juliadeps-r04.7z/sha512 deleted file mode 100644 index c376e13589815..0000000000000 --- a/deps/checksums/llvm-3.9.1-i686-w64-mingw32-juliadeps-r04.7z/sha512 +++ /dev/null @@ -1 +0,0 @@ -c2632222dc2662c0fe65372d74dbf65e9dcad638a9b668952b12ab270fc633c83b1a3a48342e488757a5ded1e0b633f04fb545fd0f5867c329524ca6b2881143 diff --git a/deps/checksums/llvm-3.9.1-i686-w64-mingw32-juliadeps-r06.7z/md5 b/deps/checksums/llvm-3.9.1-i686-w64-mingw32-juliadeps-r06.7z/md5 new file mode 100644 index 0000000000000..6bf3fdba8b1c0 --- /dev/null +++ b/deps/checksums/llvm-3.9.1-i686-w64-mingw32-juliadeps-r06.7z/md5 @@ -0,0 +1 @@ +1f70cf1067b4bbb7b583ceb772a73f98 diff --git a/deps/checksums/llvm-3.9.1-i686-w64-mingw32-juliadeps-r06.7z/sha512 b/deps/checksums/llvm-3.9.1-i686-w64-mingw32-juliadeps-r06.7z/sha512 new file mode 100644 index 0000000000000..7c3f9a3bd6fcd --- /dev/null +++ b/deps/checksums/llvm-3.9.1-i686-w64-mingw32-juliadeps-r06.7z/sha512 @@ -0,0 +1 @@ +7327de3b52de100f2091ee6f7e456f5882723d0c835ead63a3485dd16770cb26927b4ff8bf2f6885ae09f07047434f2f1acd88c15b9e54c08ddca961b6e660bd diff --git a/deps/checksums/llvm-3.9.1-x86_64-w64-mingw32-juliadeps-r04.7z/md5 b/deps/checksums/llvm-3.9.1-x86_64-w64-mingw32-juliadeps-r04.7z/md5 deleted file mode 100644 index 04b2fc7b4a267..0000000000000 --- a/deps/checksums/llvm-3.9.1-x86_64-w64-mingw32-juliadeps-r04.7z/md5 +++ /dev/null @@ -1 +0,0 @@ -a32011de56ca5146a601e9866d3b4619 diff --git a/deps/checksums/llvm-3.9.1-x86_64-w64-mingw32-juliadeps-r04.7z/sha512 b/deps/checksums/llvm-3.9.1-x86_64-w64-mingw32-juliadeps-r04.7z/sha512 deleted file mode 100644 index aef55552d5567..0000000000000 --- a/deps/checksums/llvm-3.9.1-x86_64-w64-mingw32-juliadeps-r04.7z/sha512 +++ /dev/null @@ -1 +0,0 @@ -3c6010b1b59979d56b611201e824405fde14a11a56c45b6fb5007c6c38c2db41c2b2590b0ca81ad0d9dbaaad9d83fd7342653a2937806f04d9693fd9611f5be3 diff --git a/deps/checksums/llvm-3.9.1-x86_64-w64-mingw32-juliadeps-r06.7z/md5 b/deps/checksums/llvm-3.9.1-x86_64-w64-mingw32-juliadeps-r06.7z/md5 new file mode 100644 index 0000000000000..c78ceb43ecffc --- /dev/null +++ b/deps/checksums/llvm-3.9.1-x86_64-w64-mingw32-juliadeps-r06.7z/md5 @@ -0,0 +1 @@ +32fe1b8f31f2ee0dae492ffaff7feaa7 diff --git a/deps/checksums/llvm-3.9.1-x86_64-w64-mingw32-juliadeps-r06.7z/sha512 b/deps/checksums/llvm-3.9.1-x86_64-w64-mingw32-juliadeps-r06.7z/sha512 new file mode 100644 index 0000000000000..f4fad1b78a41b --- /dev/null +++ b/deps/checksums/llvm-3.9.1-x86_64-w64-mingw32-juliadeps-r06.7z/sha512 @@ -0,0 +1 @@ +9e06261f5d8c5e2905dc35dc283fd179535381d3f951160f43d565b48a4fc59e924666c6f8e308405a365ab43120f8c97ecc8e93cf3ffbd34e015f326635e207 From a32071dd23f4803467dd79e0f4c9da36a177dc4d Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Tue, 13 Jun 2017 06:52:30 -0700 Subject: [PATCH 1075/1534] Simplify some grammar (#22348) --- doc/src/manual/functions.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/src/manual/functions.md b/doc/src/manual/functions.md index 1793befa0beed..1b7c86760fb29 100644 --- a/doc/src/manual/functions.md +++ b/doc/src/manual/functions.md @@ -206,10 +206,10 @@ julia> map(round, [1.2,3.5,1.7]) 2.0 ``` -This is fine if a named function effecting the transform one wants already exists to pass as the -first argument to [`map()`](@ref). Often, however, a ready-to-use, named function does not exist. -In these situations, the anonymous function construct allows easy creation of a single-use function -object without needing a name: +This is fine if a named function effecting the transform already exists to pass as the first argument +to [`map()`](@ref). Often, however, a ready-to-use, named function does not exist. In these +situations, the anonymous function construct allows easy creation of a single-use function object +without needing a name: ```jldoctest julia> map(x -> x^2 + 2x - 1, [1,3,-1]) From 70be8ab80ec84e69384615a3134d4570866b7b4f Mon Sep 17 00:00:00 2001 From: Singapuram Sanjay Srivallabh Date: Tue, 13 Jun 2017 19:42:53 +0530 Subject: [PATCH 1076/1534] USE_POLLY_ACC : Remove dependency on CUDA headerfiles and link libjulia to libGPURuntime (#22036) * USE_POLLY_ACC : Remove dependency on CUDA headerfiles and link libjulia to libGPURuntime * Removed comments and CUDALIB_INCLUDE_DIR variable. --- Make.inc | 1 - src/Makefile | 8 ++------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Make.inc b/Make.inc index d23d614e9b983..2b9a9df45950f 100644 --- a/Make.inc +++ b/Make.inc @@ -243,7 +243,6 @@ BUILD_LLDB := 0 USE_POLLY := 0 USE_POLLY_OPENMP := 0 # Enable OpenMP code-generation USE_POLLY_ACC := 0 # Enable GPU code-generation -CUDALIB_INCLUDE_DIR := # Path to CUDA header files # Cross-compile #XC_HOST := i686-w64-mingw32 diff --git a/src/Makefile b/src/Makefile index 494720aa772c4..ce5e8b63a5679 100644 --- a/src/Makefile +++ b/src/Makefile @@ -65,13 +65,9 @@ ifeq ($(USE_POLLY_OPENMP),1) FLAGS += -fopenmp endif ifeq ($(USE_POLLY_ACC),1) -LLVMLINK += -lPollyPPCG +LLVMLINK += -lPollyPPCG -lGPURuntime FLAGS += -DUSE_POLLY_ACC -ifeq ($(CUDALIB_INCLUDE_DIR),) -$(error CUDALIB_INCLUDE_DIR not set: If compiling with USE_POLLY_ACC, user must provide the path to CUDA header files) -endif -FLAGS += -I$(CUDALIB_INCLUDE_DIR) -FLAGS += -I$(shell $(LLVM_CONFIG_HOST) --src-root)/tools/polly/tools +FLAGS += -I$(shell $(LLVM_CONFIG_HOST) --src-root)/tools/polly/tools # Required to find GPURuntime/GPUJIT.h endif endif else From 84300a6ac29d414775644a97d52f15fb645adc91 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Tue, 13 Jun 2017 10:50:53 -0400 Subject: [PATCH 1077/1534] clean up and export crc32c function (#22274) * clean up and export crc32c function * added PR to NEWS * restore crc32 of String, add crc32c(io) to read all of a stream, add optimized open(crc32c, filename), make IOBuffer checksums consistent with other streams * use crc32c block size of 8192*3, matching the underling C library * optimized IOBuffer crc32c --- NEWS.md | 2 ++ base/exports.jl | 1 + base/iobuffer.jl | 12 +++++++++ base/loading.jl | 13 +++------- base/util.jl | 48 +++++++++++++++++++++++++++++++----- doc/src/stdlib/arrays.md | 1 + doc/src/stdlib/io-network.md | 1 + test/misc.jl | 34 ++++++++++++++++++++++--- 8 files changed, 93 insertions(+), 19 deletions(-) diff --git a/NEWS.md b/NEWS.md index cff38eca2c720..24aaa02f22dcf 100644 --- a/NEWS.md +++ b/NEWS.md @@ -59,6 +59,8 @@ Library improvements * `resize!` and `sizehint!` methods no longer over-reserve memory when the requested array size is more than double of its current size ([#22038]). + * The `crc32c` function for CRC-32c checksums is now exported ([#22274]). + * The output of `versioninfo()` is now controlled with keyword arguments ([#21974]). * The function `LibGit2.set_remote_url` now always sets both the fetch and push URLs for a diff --git a/base/exports.jl b/base/exports.jl index d88133ca324d7..0aeba4d7b2eb0 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -1047,6 +1047,7 @@ export atexit, atreplinit, clipboard, + crc32c, exit, ntuple, quit, diff --git a/base/iobuffer.jl b/base/iobuffer.jl index c9d4226462dac..854e39cbc4f17 100644 --- a/base/iobuffer.jl +++ b/base/iobuffer.jl @@ -412,3 +412,15 @@ function readuntil(io::AbstractIOBuffer, delim::UInt8) end A end + +# copy-free crc32c of IOBuffer: +function crc32c(io::IOBuffer, nb::Integer, crc::UInt32=0x00000000) + nb < 0 && throw(ArgumentError("number of bytes to checksum must be ≥ 0")) + io.readable || throw(ArgumentError("read failed, IOBuffer is not readable")) + n = min(nb, nb_available(io)) + n == 0 && return crc + crc = unsafe_crc32c(pointer(io.data, io.ptr), n, crc) + io.ptr += n + return crc +end +crc32c(io::IOBuffer, crc::UInt32=0x00000000) = crc32c(io, nb_available(io), crc) diff --git a/base/loading.jl b/base/loading.jl index 1a6b5671342d0..1382f4f2a00ed 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -683,10 +683,7 @@ function compilecache(name::String) if success(create_expr_cache(path, cachefile, concrete_deps)) # append checksum to the end of the .ji file: open(cachefile, "a+") do f - data = Mmap.mmap(f, Vector{UInt8}, filesize(f), 0) - checksum = crc32c(data) - finalize(data) - write(f, hton(checksum)) + write(f, hton(crc32c(seekstart(f)))) end else error("Failed to precompile $name to $cachefile.") @@ -809,12 +806,8 @@ function stale_cachefile(modpath::String, cachefile::String) end # finally, verify that the cache file has a valid checksum - data = Mmap.mmap(io, Vector{UInt8}, filesize(io), 0) - # checksum = UInt32 read in bigendian format from the last 4 bytes: - checksum = UInt32(data[end]) + UInt32(data[end-1])<<8 + UInt32(data[end-2])<<16 + UInt32(data[end-3])<<24 - crc = crc32c(@view(data[1:end-4])) - finalize(data) - if checksum != crc + crc = crc32c(seekstart(io), filesize(io)-4) + if crc != ntoh(read(io, UInt32)) DEBUG_LOADING[] && info("JL_DEBUG_LOADING: Rejecting cache file $cachefile because it has an invalid checksum.") return true end diff --git a/base/util.jl b/base/util.jl index a909b8355cf7a..1617b3d6c5df1 100644 --- a/base/util.jl +++ b/base/util.jl @@ -765,10 +765,6 @@ if is_windows() end -# compute sizeof correctly for strings, arrays, and subarrays of bytes -_sizeof(a) = sizeof(a) -_sizeof(a::FastContiguousSubArray{UInt8,N,<:Array{UInt8}} where N) = length(a) - """ crc32c(data, crc::UInt32=0x00000000) @@ -778,9 +774,49 @@ a starting `crc` integer to be mixed in with the checksum. The `crc` parameter can be used to compute a checksum on data divided into chunks: performing `crc32c(data2, crc32c(data1))` is equivalent to the checksum of `[data1; data2]`. (Technically, a little-endian checksum is computed.) + +There is also a method `crc32c(io, nb, crc)` to checksum `nb` bytes from +a stream `io`, or `crc32c(io, crc)` to checksum all the remaining bytes. +Hence you can do [`open(crc32c, filename)`](@ref) to checksum an entire file, +or `crc32c(seekstart(buf))` to checksum an [`IOBuffer`](@ref) without +calling [`take!`](@ref). + +For a `String`, note that the result is specific to the UTF-8 encoding +(a different checksum would be obtained from a different Unicode encoding). +To checksum an `a::Array` of some other bitstype, you can do `crc32c(reinterpret(UInt8,a))`, +but note that the result may be endian-dependent. """ -crc32c(a::Union{Array{UInt8},FastContiguousSubArray{UInt8,N,<:Array{UInt8}} where N,String}, crc::UInt32=0x00000000) = - ccall(:jl_crc32c, UInt32, (UInt32, Ptr{UInt8}, Csize_t), crc, a, _sizeof(a)) +function crc32c end + +unsafe_crc32c(a, n, crc) = ccall(:jl_crc32c, UInt32, (UInt32, Ptr{UInt8}, Csize_t), crc, a, n) + +crc32c(a::Union{Array{UInt8},FastContiguousSubArray{UInt8,N,<:Array{UInt8}} where N}, crc::UInt32=0x00000000) = + unsafe_crc32c(a, length(a), crc) + +crc32c(s::String, crc::UInt32=0x00000000) = unsafe_crc32c(s, sizeof(s), crc) + +""" + crc32c(io::IO, [nb::Integer,] crc::UInt32=0x00000000) + +Read up to `nb` bytes from `io` and return the CRC-32c checksum, optionally +mixed with a starting `crc` integer. If `nb` is not supplied, then +`io` will be read until the end of the stream. +""" +function crc32c(io::IO, nb::Integer, crc::UInt32=0x00000000) + nb < 0 && throw(ArgumentError("number of bytes to checksum must be ≥ 0")) + # use block size 24576=8192*3, since that is the threshold for + # 3-way parallel SIMD code in the underlying jl_crc32c C function. + buf = Array{UInt8}(min(nb, 24576)) + while !eof(io) && nb > 24576 + n = readbytes!(io, buf) + crc = unsafe_crc32c(buf, n, crc) + nb -= n + end + return unsafe_crc32c(buf, readbytes!(io, buf, min(nb, length(buf))), crc) +end +crc32c(io::IO, crc::UInt32=0x00000000) = crc32c(io, typemax(Int64), crc) +crc32c(io::IOStream, crc::UInt32=0x00000000) = crc32c(io, filesize(io)-position(io), crc) + """ @kwdef typedef diff --git a/doc/src/stdlib/arrays.md b/doc/src/stdlib/arrays.md index 2fc43f52bee53..9221735386c58 100644 --- a/doc/src/stdlib/arrays.md +++ b/doc/src/stdlib/arrays.md @@ -131,6 +131,7 @@ Base.cumprod! Base.cumsum Base.cumsum! Base.cumsum_kbn +Base.crc32c Base.LinAlg.diff Base.LinAlg.gradient Base.rot180 diff --git a/doc/src/stdlib/io-network.md b/doc/src/stdlib/io-network.md index 88fd2b2cf3bb0..173261912b02e 100644 --- a/doc/src/stdlib/io-network.md +++ b/doc/src/stdlib/io-network.md @@ -12,6 +12,7 @@ Base.take!(::Base.AbstractIOBuffer) Base.fdio Base.flush Base.close +Base.crc32c(::IO, ::Integer, ::UInt32) Base.write Base.read Base.read! diff --git a/test/misc.jl b/test/misc.jl index f6cc13c538f78..4a0b481d56acd 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -566,14 +566,42 @@ end for force_software_crc in (1,0) ccall(:jl_crc32c_init, Void, (Cint,), force_software_crc) for (n,crc) in [(0,0x00000000),(1,0xa016d052),(2,0x03f89f52),(3,0xf130f21e),(4,0x29308cf4),(5,0x53518fab),(6,0x4f4dfbab),(7,0xbd3a64dc),(8,0x46891f81),(9,0x5a14b9f9),(10,0xb219db69),(11,0xd232a91f),(12,0x51a15563),(13,0x9f92de41),(14,0x4d8ae017),(15,0xc8b74611),(16,0xa0de6714),(17,0x672c992a),(18,0xe8206eb6),(19,0xc52fd285),(20,0x327b0397),(21,0x318263dd),(22,0x08485ccd),(23,0xea44d29e),(24,0xf6c0cb13),(25,0x3969bba2),(26,0x6a8810ec),(27,0x75b3d0df),(28,0x82d535b1),(29,0xbdf7fc12),(30,0x1f836b7d),(31,0xd29f33af),(32,0x8e4acb3e),(33,0x1cbee2d1),(34,0xb25f7132),(35,0xb0fa484c),(36,0xb9d262b4),(37,0x3207fe27),(38,0xa024d7ac),(39,0x49a2e7c5),(40,0x0e2c157f),(41,0x25f7427f),(42,0x368c6adc),(43,0x75efd4a5),(44,0xa84c5c31),(45,0x0fc817b2),(46,0x8d99a881),(47,0x5cc3c078),(48,0x9983d5e2),(49,0x9267c2db),(50,0xc96d4745),(51,0x058d8df3),(52,0x453f9cf3),(53,0xb714ade1),(54,0x55d3c2bc),(55,0x495710d0),(56,0x3bddf494),(57,0x4f2577d0),(58,0xdae0f604),(59,0x3c57c632),(60,0xfe39bbb0),(61,0x6f5d1d41),(62,0x7d996665),(63,0x68c738dc),(64,0x8dfea7ae)] - @test Base.crc32c(UInt8[1:n;]) == crc + @test crc32c(UInt8[1:n;]) == crc == crc32c(String(UInt8[1:n;])) end # test that crc parameter is equivalent to checksum of concatenated data, # and test crc of subarrays: a = UInt8[1:255;] - crc_256 = Base.crc32c(UInt8[1:255;]) + crc_256 = crc32c(a) @views for n = 1:255 - @test Base.crc32c(a[n+1:end], Base.crc32c(a[1:n])) == crc_256 + @test crc32c(a[n+1:end], crc32c(a[1:n])) == crc_256 + end + + @test crc32c(IOBuffer(a)) == crc_256 + let buf = IOBuffer() + write(buf, a[1:3]) + @test crc32c(seekstart(buf)) == crc32c(a[1:3]) + @test crc32c(buf) == 0x00000000 + @test crc32c(seek(buf, 1)) == crc32c(a[2:3]) + @test crc32c(seek(buf, 0), 2) == crc32c(a[1:2]) + @test crc32c(buf) == crc32c(a[3:3]) + end + + let f = tempname() + try + write(f, a) + @test open(crc32c, f) == crc_256 + open(f, "r") do io + @test crc32c(io, 16) == crc32c(a[1:16]) + @test crc32c(io, 16) == crc32c(a[17:32]) + @test crc32c(io) == crc32c(a[33:end]) + @test crc32c(io, 1000) == 0x00000000 + end + a = rand(UInt8, 30000) + write(f, a) + @test open(crc32c, f) == crc32c(a) == open(io -> crc32c(io, 10^6), f) + finally + rm(f, force=true) + end end end From 8079ee3fa12cec0a8864b3104f533a2f588f39e1 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Mon, 12 Jun 2017 14:39:54 -0400 Subject: [PATCH 1078/1534] Add utilities for debugging LLVM during sysimg build This adds an extra command line option to dump the unoptimized rather than the optimized representation of the LLVM IR. This is very useful when debugging new LLVM passes (which we're now increasingly making use of) or when profiling LLVM, to split out JIT and sysimg optimization. --- base/options.jl | 1 + src/codegen.cpp | 19 +++++++++------ src/jitlayers.cpp | 58 +++++++++++++++++++++++++++++++++++++++++--- src/jloptions.c | 8 ++++++ src/julia.h | 1 + src/julia_internal.h | 3 ++- src/precompile.c | 9 ++++--- 7 files changed, 83 insertions(+), 16 deletions(-) diff --git a/base/options.jl b/base/options.jl index ef3c88bc96110..660db20b928c3 100644 --- a/base/options.jl +++ b/base/options.jl @@ -32,6 +32,7 @@ struct JLOptions use_compilecache::Int8 bindto::Ptr{UInt8} outputbc::Ptr{UInt8} + outputunoptbc::Ptr{UInt8} outputo::Ptr{UInt8} outputji::Ptr{UInt8} incremental::Int8 diff --git a/src/codegen.cpp b/src/codegen.cpp index a2e99c6bd4001..7277da7a078f3 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -7260,7 +7260,7 @@ static inline void checkARMArchFeature(std::string &cpu, static inline SmallVector getTargetFeatures(std::string &cpu) { StringMap HostFeatures; - if (!strcmp(jl_options.cpu_target,"native")) { + if (jl_options.cpu_target && !strcmp(jl_options.cpu_target,"native")) { // On earlier versions of LLVM this is empty llvm::sys::getHostCPUFeatures(HostFeatures); } @@ -7286,8 +7286,8 @@ static inline SmallVector getTargetFeatures(std::string &cpu) #endif // Figure out if we know the cpu_target - cpu = (strcmp(jl_options.cpu_target,"native") ? jl_options.cpu_target : - getNativeTarget()); + cpu = ((jl_options.cpu_target && strcmp(jl_options.cpu_target,"native")) ? + jl_options.cpu_target : getNativeTarget()); #if defined(_CPU_ARM_) // Figure out what we are compiling against from the C defines. // This might affect ABI but is fine since @@ -7372,7 +7372,7 @@ static inline SmallVector getTargetFeatures(std::string &cpu) return attr; } -extern "C" void jl_init_codegen(void) +extern "C" void *jl_init_llvm(void) { const char *const argv_tailmerge[] = {"", "-enable-tail-merge=0"}; // NOO TOUCHIE; NO TOUCH! See #922 cl::ParseCommandLineOptions(sizeof(argv_tailmerge)/sizeof(argv_tailmerge[0]), argv_tailmerge, "disable-tail-merge\n"); @@ -7487,14 +7487,13 @@ extern "C" void jl_init_codegen(void) targetFeatures); assert(jl_TargetMachine && "Failed to select target machine -" " Is the LLVM backend for this CPU enabled?"); -#if defined(USE_MCJIT) && (!defined(_CPU_ARM_) && !defined(_CPU_PPC64_)) + #if defined(USE_MCJIT) && (!defined(_CPU_ARM_) && !defined(_CPU_PPC64_)) // FastISel seems to be buggy for ARM. Ref #13321 if (jl_options.opt_level < 2) jl_TargetMachine->setFastISel(true); -#endif + #endif init_julia_llvm_meta(); - #ifdef USE_ORCJIT jl_ExecutionEngine = new JuliaOJIT(*jl_TargetMachine); #else @@ -7514,6 +7513,12 @@ extern "C" void jl_init_codegen(void) // Now that the execution engine exists, initialize all modules jl_setup_module(engine_module); jl_setup_module(m); + return (void*)m; +} + +extern "C" void jl_init_codegen(void) +{ + Module *m = (Module *)jl_init_llvm(); init_julia_llvm_env(m); #ifndef USE_ORCJIT diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index e6ae9474d9c9c..08d47d66a4156 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -1174,7 +1174,7 @@ static void jl_gen_llvm_globaldata(llvm::Module *mod, ValueToValueMapTy &VMap, // takes the running content that has collected in the shadow module and dump it to disk // this builds the object file portion of the sysimage files for fast startup extern "C" -void jl_dump_native(const char *bc_fname, const char *obj_fname, const char *sysimg_data, size_t sysimg_len) +void jl_dump_native(const char *bc_fname, const char *unopt_bc_fname, const char *obj_fname, const char *sysimg_data, size_t sysimg_len) { JL_TIMING(NATIVE_DUMP); assert(imaging_mode); @@ -1240,18 +1240,46 @@ void jl_dump_native(const char *bc_fname, const char *obj_fname, const char *sys PM.add(new DataLayout(*jl_ExecutionEngine->getDataLayout())); #endif - addOptimizationPasses(&PM); - + std::unique_ptr unopt_bc_OS; std::unique_ptr bc_OS; std::unique_ptr obj_OS; #if JL_LLVM_VERSION >= 30700 // 3.7 simplified formatted output; just use the raw stream alone + std::unique_ptr &unopt_bc_FOS = unopt_bc_OS; std::unique_ptr &bc_FOS = bc_OS; std::unique_ptr &obj_FOS = obj_OS; #else + std::unique_ptr unopt_bc_FOS; std::unique_ptr bc_FOS; std::unique_ptr obj_FOS; #endif + + if (unopt_bc_fname) { +#if JL_LLVM_VERSION >= 30500 + // call output handler directly to avoid special case handling of `-` filename + int FD; + std::error_code EC = sys::fs::openFileForWrite(unopt_bc_fname, FD, sys::fs::F_None); + unopt_bc_FOS.reset(new raw_fd_ostream(FD, true)); + std::string err; + if (EC) + err = "ERROR: failed to open --output-unopt-bc file '" + std::string(unopt_bc_fname) + "': " + EC.message(); +#else + std::string err; + unopt_bc_OS.reset(new raw_fd_ostream(unopt_bc_fname, err, raw_fd_ostream::F_Binary)); +#endif + if (!err.empty()) + jl_safe_printf("%s\n", err.c_str()); + else { +#if JL_LLVM_VERSION < 30700 + unopt_bc_FOS.reset(new formatted_raw_ostream(*unopt_bc_OS.get())); +#endif + PM.add(createBitcodeWriterPass(*unopt_bc_FOS.get())); + } + } + + if (bc_fname || obj_fname) + addOptimizationPasses(&PM); + if (bc_fname) { #if JL_LLVM_VERSION >= 30500 // call output handler directly to avoid special case handling of `-` filename @@ -1271,7 +1299,7 @@ void jl_dump_native(const char *bc_fname, const char *obj_fname, const char *sys #if JL_LLVM_VERSION < 30700 bc_FOS.reset(new formatted_raw_ostream(*bc_OS.get())); #endif - PM.add(createBitcodeWriterPass(*bc_FOS.get())); // Unroll small loops + PM.add(createBitcodeWriterPass(*bc_FOS.get())); } } @@ -1369,3 +1397,25 @@ GlobalVariable *jl_get_global_for(const char *cname, void *addr, Module *M) *(void**)jl_emit_and_add_to_shadow(gv, addr) = addr; return gv; } + +// An LLVM module pass that just runs all julia passes in order. Useful for +// debugging +extern "C" void jl_init_codegen(void); +class JuliaPipeline : public ModulePass { +public: + static char ID; + JuliaPipeline() : ModulePass(ID) {} + virtual bool runOnModule(Module &M) { + (void)jl_init_llvm(); +#if JL_LLVM_VERSION >= 30700 + legacy::PassManager PM; +#else + PassManager PM; +#endif + addOptimizationPasses(&PM); + PM.run(M); + return true; + } +}; +char JuliaPipeline::ID = 0; +static RegisterPass X("julia", "Runs the entire julia pipeline", false, false); diff --git a/src/jloptions.c b/src/jloptions.c index 38333570e52c9..ffdfc259ce1e8 100644 --- a/src/jloptions.c +++ b/src/jloptions.c @@ -67,6 +67,7 @@ jl_options_t jl_options = { 0, // quiet JL_OPTIONS_USE_COMPILECACHE_YES, NULL, // bind-to NULL, // output-bc + NULL, // output-unopt-bc NULL, // output-o NULL, // output-ji 0, // incremental @@ -125,6 +126,7 @@ static const char opts[] = // compiler output options " --output-o name Generate an object file (including system image data)\n" " --output-ji name Generate a system image data file (.ji)\n" + " --output-unopt-bc name Generate unoptimized LLVM bitcode (.bc)\n" " --output-bc name Generate LLVM bitcode (.bc)\n" " --output-incremental=no Generate an incremental output file (rather than complete)\n\n" @@ -145,6 +147,7 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp) opt_code_coverage, opt_track_allocation, opt_check_bounds, + opt_output_unopt_bc, opt_output_bc, opt_depwarn, opt_inline, @@ -186,6 +189,7 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp) { "optimize", optional_argument, 0, 'O' }, { "check-bounds", required_argument, 0, opt_check_bounds }, { "output-bc", required_argument, 0, opt_output_bc }, + { "output-unopt-bc", required_argument, 0, opt_output_unopt_bc }, { "output-o", required_argument, 0, opt_output_o }, { "output-ji", required_argument, 0, opt_output_ji }, { "output-incremental",required_argument, 0, opt_incremental }, @@ -434,6 +438,10 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp) jl_options.outputbc = optarg; if (!jl_options.image_file_specified) jl_options.image_file = NULL; break; + case opt_output_unopt_bc: + jl_options.outputunoptbc = optarg; + if (!jl_options.image_file_specified) jl_options.image_file = NULL; + break; case opt_output_o: jl_options.outputo = optarg; if (!jl_options.image_file_specified) jl_options.image_file = NULL; diff --git a/src/julia.h b/src/julia.h index c6d63d1f3517c..183cfef8ab532 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1726,6 +1726,7 @@ typedef struct { int8_t use_compilecache; const char *bindto; const char *outputbc; + const char *outputunoptbc; const char *outputo; const char *outputji; int8_t incremental; diff --git a/src/julia_internal.h b/src/julia_internal.h index 81ca3bedfa957..4689211efd850 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -511,6 +511,7 @@ void jl_init_types(void); void jl_init_box_caches(void); void jl_init_frontend(void); void jl_init_primitives(void); +void *jl_init_llvm(void); void jl_init_codegen(void); void jl_init_intrinsic_functions(void); void jl_init_intrinsic_properties(void); @@ -592,7 +593,7 @@ static inline void jl_set_gc_and_wait(void) } #endif -void jl_dump_native(const char *bc_fname, const char *obj_fname, const char *sysimg_data, size_t sysimg_len); +void jl_dump_native(const char *bc_fname, const char *unopt_bc_fname, const char *obj_fname, const char *sysimg_data, size_t sysimg_len); int32_t jl_get_llvm_gv(jl_value_t *p); int32_t jl_assign_functionID(/*llvm::Function*/void *function); int32_t jl_jlcall_api(/*llvm::Function*/const void *function); diff --git a/src/precompile.c b/src/precompile.c index 747f2dfb4c970..6022d57d2852b 100644 --- a/src/precompile.c +++ b/src/precompile.c @@ -17,7 +17,7 @@ extern "C" { JL_DLLEXPORT int jl_generating_output(void) { - return jl_options.outputo || jl_options.outputbc || jl_options.outputji; + return jl_options.outputo || jl_options.outputbc || jl_options.outputunoptbc || jl_options.outputji; } void jl_precompile(int all); @@ -50,14 +50,14 @@ void jl_write_compiler_output(void) if (jl_options.outputji) if (jl_save_incremental(jl_options.outputji, worklist)) jl_exit(1); - if (jl_options.outputbc) + if (jl_options.outputbc || jl_options.outputunoptbc) jl_printf(JL_STDERR, "WARNING: incremental output to a .bc file is not implemented\n"); if (jl_options.outputo) jl_printf(JL_STDERR, "WARNING: incremental output to a .o file is not implemented\n"); } else { ios_t *s = NULL; - if (jl_options.outputo || jl_options.outputbc) + if (jl_options.outputo || jl_options.outputbc || jl_options.outputunoptbc) s = jl_create_system_image(); if (jl_options.outputji) { @@ -73,8 +73,9 @@ void jl_write_compiler_output(void) } } - if (jl_options.outputo || jl_options.outputbc) + if (jl_options.outputo || jl_options.outputbc || jl_options.outputunoptbc) jl_dump_native(jl_options.outputbc, + jl_options.outputunoptbc, jl_options.outputo, (const char*)s->buf, (size_t)s->size); } From 37da3243cafeacc2961540384506c051bb51e6fd Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Tue, 13 Jun 2017 13:57:04 -0400 Subject: [PATCH 1079/1534] Add some documentation --- doc/src/devdocs/llvm.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/doc/src/devdocs/llvm.md b/doc/src/devdocs/llvm.md index 0d88cc8cf17ea..35266648de520 100644 --- a/doc/src/devdocs/llvm.md +++ b/doc/src/devdocs/llvm.md @@ -60,6 +60,38 @@ via the environment variable `JULIA_LLVM_ARGS`. Here are example settings using about "Unknown command line argument". Counter-intuitively, building Julia with `LLVM_DEBUG=1` is *not* enough to dump `DEBUG` diagnostics from a pass. +## Debugging LLVM transformations in isolation + +On occasion, it can be useful to debug LLVM's transformations in isolation from +the rest of the julia system, e.g. because reproducing the issue inside julia +would take too long, or because one wants to take advantage of LLVM's tooling +(e.g. bugpoint). To get unoptimized IR for the entire system iamge, pass the +`--output-unopt-bc unopt.bc` option to the system image build process, which will +output the unoptimized IR to an `unopt.bc` file. This file can then be passed to +LLVM tools as usual. `libjulia` can function as an LLVM pass plugin and can be +loaded into LLVM tools, to make julia-specific passes available in this +environment. In addition, it exposes the `-julia` meta-pass, which runs the +entire julia pass-pipeline over the IR. As an example, to generate a system +image, one could do: +``` +opt -load libjulia.so -julia -o opt.bc unopt.bc +llc -o sys.o opt.bc +cc -shared -o sys.so sys.o +``` +This system image can then be loaded by julia as usual. + +It is also possible to dump an LLVM IR module for just one julia function, +using: +``` +f, T = +, Tuple{Int,Int} # Substitute your function of interest here +optimize = false +open("plus.ll","w") do f + println(f, Base._dump_function(f, T, false, false, false, true, :att, optimize)) +end +``` +These files can be processed the same way as the unoptimized sysimg IR shown +above. + ## Improving LLVM optimizations for Julia Improving LLVM code generation usually involves either changing Julia lowering to be more friendly From 702256f532cbceb8d1bf041563ae12e78a33b8d4 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Tue, 13 Jun 2017 13:39:56 -0500 Subject: [PATCH 1080/1534] Assign PROGRAM_FILE earlier (#22092) * Assign PROGRAM_FILE earlier I discovered a use case where it would be nice to be able to access `PROGRAM_FILE` while within the .juliarc.jl. The global variable is now assigned and available within `--load` file or the .juliarc.jl. Additionally, PROGRAM_FILE is now a constant. * Add to NEWS [ci skip] * Test startup-file and PROGRAM_FILE * Modify user home properly on Windows * Style correction and remove escape function * Expand arguments tests to include the startup-file * Refactor PROGRAM_FILE tests --- NEWS.md | 4 ++ base/client.jl | 9 +++-- base/initdefs.jl | 2 +- test/cmdlineargs.jl | 96 +++++++++++++++++++++++++++------------------ 4 files changed, 69 insertions(+), 42 deletions(-) diff --git a/NEWS.md b/NEWS.md index 24aaa02f22dcf..8253b47908af3 100644 --- a/NEWS.md +++ b/NEWS.md @@ -40,6 +40,10 @@ This section lists changes that do not have deprecation warnings. of the socket. Previously the address of the remote endpoint was being returned ([#21825]). + * Using `ARGS` within the ~/.juliarc.jl or within a .jl file loaded with `--load` will no + longer contain the script name as the first argument. Instead the script name will be + assigned to `PROGRAM_FILE`. ([#22092]) + Library improvements -------------------- diff --git a/base/client.jl b/base/client.jl index 1b2f6506911a8..4013fcd42ceb1 100644 --- a/base/client.jl +++ b/base/client.jl @@ -257,6 +257,11 @@ function process_options(opts::JLOptions) color_set = (opts.color != 0) global have_color = (opts.color == 1) global is_interactive = (opts.isinteractive != 0) + + # remove filename from ARGS + arg_is_program = opts.eval == C_NULL && opts.print == C_NULL && !isempty(ARGS) + global const PROGRAM_FILE = arg_is_program ? shift!(ARGS) : "" + while true # startup worker. # opts.startupfile, opts.load, etc should should not be processed for workers. @@ -296,11 +301,9 @@ function process_options(opts::JLOptions) break end # load file - if !isempty(ARGS) && !isempty(ARGS[1]) + if !isempty(PROGRAM_FILE) # program repl = false - # remove filename from ARGS - global PROGRAM_FILE = shift!(ARGS) if !is_interactive ccall(:jl_exit_on_sigint, Void, (Cint,), 1) end diff --git a/base/initdefs.jl b/base/initdefs.jl index 20437a4e57cba..4535a718a5fd7 100644 --- a/base/initdefs.jl +++ b/base/initdefs.jl @@ -9,7 +9,7 @@ A string containing the script name passed to Julia from the command line. Note script name remains unchanged from within included files. Alternatively see [`@__FILE__`](@ref). """ -PROGRAM_FILE = "" +:PROGRAM_FILE """ ARGS diff --git a/test/cmdlineargs.jl b/test/cmdlineargs.jl index 7af3336c3fd98..41544f87f5df9 100644 --- a/test/cmdlineargs.jl +++ b/test/cmdlineargs.jl @@ -248,53 +248,73 @@ let exename = `$(Base.julia_cmd()) --precompiled=yes --startup-file=no` # tested in test/parallel.jl, test/examples.jl) @test !success(`$exename --worker=true`) - escape(str) = replace(str, "\\", "\\\\") - # test passing arguments - let testfile = tempname() - try - # write a julia source file that just prints ARGS to STDOUT - write(testfile, """ - println(ARGS) + mktempdir() do dir + testfile = joinpath(dir, tempname()) + # write a julia source file that just prints ARGS to STDOUT + write(testfile, """ + println(ARGS) """) - @test readchomp(`$exename $testfile foo -bar --baz`) == - "String[\"foo\", \"-bar\", \"--baz\"]" - @test readchomp(`$exename $testfile -- foo -bar --baz`) == - "String[\"foo\", \"-bar\", \"--baz\"]" + cp(testfile, joinpath(dir, ".juliarc.jl")) + + withenv((is_windows() ? "USERPROFILE" : "HOME") => dir) do + output = "String[\"foo\", \"-bar\", \"--baz\"]" + @test readchomp(`$exename $testfile foo -bar --baz`) == output + @test readchomp(`$exename $testfile -- foo -bar --baz`) == output @test readchomp(`$exename -L $testfile -e 'exit(0)' -- foo -bar --baz`) == - "String[\"foo\", \"-bar\", \"--baz\"]" - @test split(readchomp(`$exename -L $testfile $testfile`), '\n') == - ["String[\"$(escape(testfile))\"]", "String[]"] + output + @test readchomp(`$exename --startup-file=yes -e 'exit(0)' -- foo -bar --baz`) == + output + + output = "String[]\nString[]" + @test readchomp(`$exename -L $testfile $testfile`) == output + @test readchomp(`$exename --startup-file=yes $testfile`) == output + @test !success(`$exename --foo $testfile`) - @test readchomp(`$exename -L $testfile -e 'exit(0)' -- foo -bar -- baz`) == "String[\"foo\", \"-bar\", \"--\", \"baz\"]" - finally - rm(testfile) + @test readchomp(`$exename -L $testfile -e 'exit(0)' -- foo -bar -- baz`) == + "String[\"foo\", \"-bar\", \"--\", \"baz\"]" end end - # test the script name - let a = tempname(), b = tempname() - try - write(a, """ - println(@__FILE__) - println(PROGRAM_FILE) - println(length(ARGS)) - include(\"$(escape(b))\") + # test the program name remains constant + mktempdir() do dir + a = joinpath(dir, "a.jl") + b = joinpath(dir, "b.jl") + c = joinpath(dir, ".juliarc.jl") + + write(a, """ + println(@__FILE__) + println(PROGRAM_FILE) + include(\"$(escape_string(b))\") """) - write(b, """ - println(@__FILE__) - println(PROGRAM_FILE) - println(length(ARGS)) + write(b, """ + println(@__FILE__) + println(PROGRAM_FILE) """) - @test split(readchomp(`$exename $a`), '\n') == - ["$a", "$a", "0", "$b", "$a", "0"] - @test split(readchomp(`$exename -L $b -e 'exit(0)'`), '\n') == - ["$(realpath(b))", "", "0"] - @test split(readchomp(`$exename -L $b $a`), '\n') == - ["$(realpath(b))", "", "1", "$a", "$a", "0", "$b", "$a", "0"] - finally - rm(a) - rm(b) + cp(b, c) + + readsplit(cmd) = split(readchomp(cmd), '\n') + + withenv((is_windows() ? "USERPROFILE" : "HOME") => dir) do + @test readsplit(`$exename $a`) == + [a, a, + b, a] + @test readsplit(`$exename -L $b -e 'exit(0)'`) == + [realpath(b), ""] + @test readsplit(`$exename -L $b $a`) == + [realpath(b), a, + a, a, + b, a] + @test readsplit(`$exename --startup-file=yes -e 'exit(0)'`) == + [c, ""] + @test readsplit(`$exename --startup-file=yes -L $b -e 'exit(0)'`) == + [c, "", + realpath(b), ""] + @test readsplit(`$exename --startup-file=yes -L $b $a`) == + [c, a, + realpath(b), a, + a, a, + b, a] end end From 1fe65f6757ca3fc9c176750fe8f87991a55753dd Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Tue, 13 Jun 2017 21:36:47 +0200 Subject: [PATCH 1081/1534] dispatch matvec/matmat with Hermitian{<:Real} to BLAS (#22309) instead of ending up in generic_matvec/generic_matmat --- base/linalg/symmetric.jl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/base/linalg/symmetric.jl b/base/linalg/symmetric.jl index 7645908ddf25d..5d32d821c51b0 100644 --- a/base/linalg/symmetric.jl +++ b/base/linalg/symmetric.jl @@ -281,6 +281,8 @@ end ## Matvec A_mul_B!(y::StridedVector{T}, A::Symmetric{T,<:StridedMatrix}, x::StridedVector{T}) where {T<:BlasFloat} = BLAS.symv!(A.uplo, one(T), A.data, x, zero(T), y) +A_mul_B!(y::StridedVector{T}, A::Hermitian{T,<:StridedMatrix}, x::StridedVector{T}) where {T<:BlasReal} = + BLAS.symv!(A.uplo, one(T), A.data, x, zero(T), y) A_mul_B!(y::StridedVector{T}, A::Hermitian{T,<:StridedMatrix}, x::StridedVector{T}) where {T<:BlasComplex} = BLAS.hemv!(A.uplo, one(T), A.data, x, zero(T), y) ## Matmat @@ -288,6 +290,10 @@ A_mul_B!(C::StridedMatrix{T}, A::Symmetric{T,<:StridedMatrix}, B::StridedMatrix{ BLAS.symm!('L', A.uplo, one(T), A.data, B, zero(T), C) A_mul_B!(C::StridedMatrix{T}, A::StridedMatrix{T}, B::Symmetric{T,<:StridedMatrix}) where {T<:BlasFloat} = BLAS.symm!('R', B.uplo, one(T), B.data, A, zero(T), C) +A_mul_B!(C::StridedMatrix{T}, A::Hermitian{T,<:StridedMatrix}, B::StridedMatrix{T}) where {T<:BlasReal} = + BLAS.symm!('L', A.uplo, one(T), A.data, B, zero(T), C) +A_mul_B!(C::StridedMatrix{T}, A::StridedMatrix{T}, B::Hermitian{T,<:StridedMatrix}) where {T<:BlasReal} = + BLAS.symm!('R', B.uplo, one(T), B.data, A, zero(T), C) A_mul_B!(C::StridedMatrix{T}, A::Hermitian{T,<:StridedMatrix}, B::StridedMatrix{T}) where {T<:BlasComplex} = BLAS.hemm!('L', A.uplo, one(T), A.data, B, zero(T), C) A_mul_B!(C::StridedMatrix{T}, A::StridedMatrix{T}, B::Hermitian{T,<:StridedMatrix}) where {T<:BlasComplex} = From 2c3d9471f9b3fd29eef6605288fefd20369585ec Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 6 Jun 2017 13:30:30 -0400 Subject: [PATCH 1082/1534] remove Operators module --- NEWS.md | 3 ++ base/dates/Dates.jl | 2 +- base/dates/periods.jl | 1 - base/deprecated.jl | 13 ++++++ base/exports.jl | 1 - base/grisu/float.jl | 2 + base/grisu/grisu.jl | 2 - base/multidimensional.jl | 2 +- base/operators.jl | 71 ------------------------------- base/pkg/resolve/fieldvalue.jl | 1 - base/pkg/resolve/versionweight.jl | 2 - base/sysimg.jl | 1 - doc/src/manual/functions.md | 3 -- 13 files changed, 20 insertions(+), 84 deletions(-) diff --git a/NEWS.md b/NEWS.md index cff38eca2c720..015fdf1457670 100644 --- a/NEWS.md +++ b/NEWS.md @@ -92,6 +92,9 @@ Deprecated or removed which now require a module argument. And it caused the bugfix of other default arguments to use the Main module (including `whos`, `which`). + * The `Operators` module is deprecated. Instead, import required operators explicitly + from `Base`, e.g. `import Base: +, -, *, /` ([#22251]). + Julia v0.6.0 Release Notes ========================== diff --git a/base/dates/Dates.jl b/base/dates/Dates.jl index b2551e94784d1..44ed2aefa7972 100644 --- a/base/dates/Dates.jl +++ b/base/dates/Dates.jl @@ -32,7 +32,7 @@ for more information. """ module Dates -importall ..Base.Operators +import ..Base: ==, div, fld, mod, rem, gcd, lcm, +, -, *, /, % import ..Base.broadcast using Base.Iterators diff --git a/base/dates/periods.jl b/base/dates/periods.jl index 76754a4e67d10..628e077b1aec8 100644 --- a/base/dates/periods.jl +++ b/base/dates/periods.jl @@ -65,7 +65,6 @@ Base.isless(x::P, y::P) where {P<:Period} = isless(value(x), value(y)) Base.isless(x::Period, y::Period) = isless(promote(x, y)...) # Period Arithmetic, grouped by dimensionality: -import Base: div, fld, mod, rem, gcd, lcm, +, -, *, /, % for op in (:+, :-, :lcm, :gcd) @eval ($op)(x::P, y::P) where {P<:Period} = P(($op)(value(x), value(y))) end diff --git a/base/deprecated.jl b/base/deprecated.jl index 4defa517f7c34..f600006bddc47 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1421,6 +1421,19 @@ function LibGit2.set_remote_url(path::AbstractString, url::AbstractString; remot LibGit2.set_remote_url(path, remote, url) end +module Operators + for op in [:!, :(!=), :(!==), :%, :&, :*, :+, :-, :/, ://, :<, :<:, :<<, :(<=), + :<|, :(==), :(===), :>, :>:, :(>=), :>>, :>>>, :\, :^, :colon, + :ctranspose, :getindex, :hcat, :hvcat, :setindex!, :transpose, :vcat, + :xor, :|, :|>, :~, :×, :÷, :∈, :∉, :∋, :∌, :∘, :√, :∛, :∩, :∪, :≠, :≤, + :≥, :⊆, :⊈, :⊊, :⊻, :⋅] + if isdefined(Base, op) + @eval Base.@deprecate_binding $op Base.$op + end + end +end +export Operators + # END 0.7 deprecations # BEGIN 1.0 deprecations diff --git a/base/exports.jl b/base/exports.jl index d88133ca324d7..52866a9014705 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -4,7 +4,6 @@ export # Modules FFTW, Meta, - Operators, Pkg, LibGit2, StackTraces, diff --git a/base/grisu/float.jl b/base/grisu/float.jl index af95f941dd10f..a92b94ccd4b51 100644 --- a/base/grisu/float.jl +++ b/base/grisu/float.jl @@ -28,6 +28,8 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import Base: -, * + struct Float s::UInt64 e::Int32 diff --git a/base/grisu/grisu.jl b/base/grisu/grisu.jl index 40ddf401ce865..83f1f89365bf9 100644 --- a/base/grisu/grisu.jl +++ b/base/grisu/grisu.jl @@ -2,8 +2,6 @@ module Grisu -importall ..Base.Operators - export print_shortest export DIGITS, grisu diff --git a/base/multidimensional.jl b/base/multidimensional.jl index a5dfd377fbad6..ebe78615ac392 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -6,7 +6,7 @@ module IteratorsMD setindex!, IndexStyle, min, max, zero, one, isless, eachindex, ndims, iteratorsize, convert - importall ..Base.Operators + import Base: +, -, * import Base: simd_outer_range, simd_inner_length, simd_index using Base: IndexLinear, IndexCartesian, AbstractCartesianIndex, fill_to_length, tail diff --git a/base/operators.jl b/base/operators.jl index fbb99958f67e9..bb347e3e41207 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -902,74 +902,3 @@ julia> filter(!isalpha, str) ``` """ !(f::Function) = (x...)->!f(x...) - -# some operators not defined yet -global //, >:, <|, hcat, hvcat, ⋅, ×, ∈, ∉, ∋, ∌, ⊆, ⊈, ⊊, ∩, ∪, √, ∛ - -this_module = @__MODULE__ -baremodule Operators - -export - !, - !=, - !==, - ===, - xor, - %, - ÷, - &, - *, - +, - -, - /, - //, - <, - <:, - >:, - <<, - <=, - ==, - >, - >=, - ≥, - ≤, - ≠, - >>, - >>>, - \, - ^, - |, - |>, - <|, - ~, - ⋅, - ×, - ∈, - ∉, - ∋, - ∌, - ⊆, - ⊈, - ⊊, - ∩, - ∪, - √, - ∛, - ⊻, - ∘, - colon, - hcat, - vcat, - hvcat, - getindex, - setindex!, - transpose, - ctranspose - -import ..this_module: !, !=, xor, %, ÷, &, *, +, -, - /, //, <, <:, <<, <=, ==, >, >=, >>, >>>, - <|, |>, \, ^, |, ~, !==, ===, >:, colon, hcat, vcat, hvcat, getindex, setindex!, - transpose, ctranspose, - ≥, ≤, ≠, ⋅, ×, ∈, ∉, ∋, ∌, ⊆, ⊈, ⊊, ∩, ∪, √, ∛, ⊻, ∘ - -end diff --git a/base/pkg/resolve/fieldvalue.jl b/base/pkg/resolve/fieldvalue.jl index 7831dce0ec56e..01549cd8ca4b9 100644 --- a/base/pkg/resolve/fieldvalue.jl +++ b/base/pkg/resolve/fieldvalue.jl @@ -3,7 +3,6 @@ module FieldValues using ...VersionWeights -importall .....Base.Operators export FieldValue, Field, validmax, secondmax diff --git a/base/pkg/resolve/versionweight.jl b/base/pkg/resolve/versionweight.jl index 596377c55bf9a..440483181c4c9 100644 --- a/base/pkg/resolve/versionweight.jl +++ b/base/pkg/resolve/versionweight.jl @@ -2,8 +2,6 @@ module VersionWeights -importall ....Base.Operators - export VersionWeight struct HierarchicalValue{T} diff --git a/base/sysimg.jl b/base/sysimg.jl index 5431dd9706392..280d26e4c16b3 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -447,6 +447,5 @@ include(Base, "precompile.jl") end # baremodule Base using Base -importall Base.Operators Base.isfile("userimg.jl") && Base.include(Main, "userimg.jl") diff --git a/doc/src/manual/functions.md b/doc/src/manual/functions.md index 1b7c86760fb29..c1832848f2061 100644 --- a/doc/src/manual/functions.md +++ b/doc/src/manual/functions.md @@ -169,9 +169,6 @@ A few special expressions correspond to calls to functions with non-obvious name | `A[i]` | [`getindex()`](@ref) | | `A[i]=x` | [`setindex!()`](@ref) | -These functions are included in the `Base.Operators` module even though they do not have operator-like -names. - ## [Anonymous Functions](@id man-anonymous-functions) Functions in Julia are [first-class objects](https://en.wikipedia.org/wiki/First-class_citizen): From 1574aa0fc009b33eb73559c3e102a3f1fadaf5e2 Mon Sep 17 00:00:00 2001 From: Philip Tellis Date: Tue, 13 Jun 2017 17:29:34 -0400 Subject: [PATCH 1083/1534] Make usage of `foo` clearer (#22317) Replaces the placeholder `foo` with the built-in `norm` to make sure the example works when typed into a julia program. Thanks to Avik Sengupta for the text and for all the commenters on https://discourse.julialang.org/t/what-does-foo-in-the-parallel-computing-docs-refer-to/4182 for making this happen. --- doc/src/manual/parallel-computing.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/doc/src/manual/parallel-computing.md b/doc/src/manual/parallel-computing.md index b29445132d2b7..5079dc9c9c11d 100644 --- a/doc/src/manual/parallel-computing.md +++ b/doc/src/manual/parallel-computing.md @@ -258,11 +258,15 @@ snippet: ```julia-repl A = rand(10,10) -remotecall_fetch(()->foo(A), 2) +remotecall_fetch(()->norm(A), 2) ``` +In this case [`norm`](@ref) is a function that takes 2D array as a parameter, and MUST be defined in +the remote process. You could use any function other than `norm` as long as it is defined in the remote +process and accepts the appropriate parameter. + Note that `A` is a global variable defined in the local workspace. Worker 2 does not have a variable called -`A` under `Main`. The act of shipping the closure `()->foo(A)` to worker 2 results in `Main.A` being defined +`A` under `Main`. The act of shipping the closure `()->norm(A)` to worker 2 results in `Main.A` being defined on 2. `Main.A` continues to exist on worker 2 even after the call `remotecall_fetch` returns. Remote calls with embedded global references (under `Main` module only) manage globals as follows: @@ -276,9 +280,9 @@ with embedded global references (under `Main` module only) manage globals as fol ```julia A = rand(10,10) - remotecall_fetch(()->foo(A), 2) # worker 2 + remotecall_fetch(()->norm(A), 2) # worker 2 A = rand(10,10) - remotecall_fetch(()->foo(A), 3) # worker 3 + remotecall_fetch(()->norm(A), 3) # worker 3 A = nothing ``` From 17d5c550e159446d5f278156b5c963bdb69cd6cd Mon Sep 17 00:00:00 2001 From: Amit Murthy Date: Wed, 14 Jun 2017 10:44:30 +0530 Subject: [PATCH 1084/1534] topology test to listen only on localhost (#22353) --- test/topology.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/topology.jl b/test/topology.jl index 8e5cbcaf93459..9afb668b85fa4 100644 --- a/test/topology.jl +++ b/test/topology.jl @@ -41,7 +41,7 @@ function Base.launch(manager::TopoTestManager, params::Dict, launched::Array, c: exename = params[:exename] exeflags = params[:exeflags] - cmd = `$exename $exeflags --bind-to $(Base.Distributed.LPROC.bind_addr) --worker $(Base.cluster_cookie())` + cmd = `$exename $exeflags --bind-to 127.0.0.1 --worker $(Base.cluster_cookie())` cmd = pipeline(detach(setenv(cmd, dir=dir))) for i in 1:manager.np io = open(cmd) From 516617d0d12b019ab1f3d525c56eca40c1352caa Mon Sep 17 00:00:00 2001 From: Douglas Bates Date: Wed, 14 Jun 2017 10:55:38 -0500 Subject: [PATCH 1085/1534] Diagonal inverse scaling (#22230) * Diagonal inverse scaling As described in https://github.com/dmbates/MixedModels.jl/issues/85, I use in-place `_rdiv_` and `_ldiv_` methods. This would move the methods for Base types into Base. * Don't use commutativity Use division instead multipliciation with the reciprocal --- base/linalg/diagonal.jl | 43 +++++++++++++++++++++++++++++++---------- base/sparse/linalg.jl | 21 ++++++++++++++++++++ base/sparse/sparse.jl | 2 +- test/linalg/diagonal.jl | 12 +++++++++++- test/sparse/sparse.jl | 9 +++++++++ 5 files changed, 75 insertions(+), 12 deletions(-) diff --git a/base/linalg/diagonal.jl b/base/linalg/diagonal.jl index a94414d2c3ddb..954848191bd58 100644 --- a/base/linalg/diagonal.jl +++ b/base/linalg/diagonal.jl @@ -236,36 +236,59 @@ At_mul_B!(out::AbstractMatrix, A::Diagonal, in::AbstractMatrix) = out .= transpo (/)(Da::Diagonal, Db::Diagonal) = Diagonal(Da.diag ./ Db.diag) -function A_ldiv_B!(D::Diagonal{T}, v::AbstractVector{T}) where T +function A_ldiv_B!(D::Diagonal{T}, v::AbstractVector{T}) where {T} if length(v) != length(D.diag) throw(DimensionMismatch("diagonal matrix is $(length(D.diag)) by $(length(D.diag)) but right hand side has $(length(v)) rows")) end - for i=1:length(D.diag) + for i = 1:length(D.diag) d = D.diag[i] - if d == zero(T) + if iszero(d) throw(SingularException(i)) end - v[i] *= inv(d) + v[i] = d\v[i] end v end -function A_ldiv_B!(D::Diagonal{T}, V::AbstractMatrix{T}) where T +function A_ldiv_B!(D::Diagonal{T}, V::AbstractMatrix{T}) where {T} if size(V,1) != length(D.diag) throw(DimensionMismatch("diagonal matrix is $(length(D.diag)) by $(length(D.diag)) but right hand side has $(size(V,1)) rows")) end - for i=1:length(D.diag) + for i = 1:length(D.diag) d = D.diag[i] - if d == zero(T) + if iszero(d) throw(SingularException(i)) end - d⁻¹ = inv(d) - for j=1:size(V,2) - @inbounds V[i,j] *= d⁻¹ + for j = 1:size(V,2) + @inbounds V[i,j] = d\V[i,j] end end V end +Ac_ldiv_B!(D::Diagonal{T}, B::AbstractVecOrMat{T}) where {T} = A_ldiv_B!(conj(D), B) +At_ldiv_B!(D::Diagonal{T}, B::AbstractVecOrMat{T}) where {T} = A_ldiv_B!(D, B) + +function A_rdiv_B!(A::AbstractMatrix{T}, D::Diagonal{T}) where {T} + dd = D.diag + m, n = size(A) + if (k = length(dd)) ≠ n + throw(DimensionMismatch("left hand side has $n columns but D is $k by $k")) + end + @inbounds for j in 1:n + ddj = dd[j] + if iszero(ddj) + throw(SingularException(j)) + end + for i in 1:m + A[i, j] /= ddj + end + end + A +end + +A_rdiv_Bc!(A::AbstractMatrix{T}, D::Diagonal{T}) where {T} = A_rdiv_B!(A, conj(D)) +A_rdiv_Bt!(A::AbstractMatrix{T}, D::Diagonal{T}) where {T} = A_rdiv_B!(A, D) + # Methods to resolve ambiguities with `Diagonal` @inline *(rowvec::RowVector, D::Diagonal) = transpose(D * transpose(rowvec)) @inline A_mul_Bt(D::Diagonal, rowvec::RowVector) = D*transpose(rowvec) diff --git a/base/sparse/linalg.jl b/base/sparse/linalg.jl index 23590f216bf60..8f0463449fef2 100644 --- a/base/sparse/linalg.jl +++ b/base/sparse/linalg.jl @@ -290,6 +290,27 @@ A_ldiv_B!(U::UpperTriangular{T,<:SparseMatrixCSC{T}}, B::StridedVecOrMat) where (\)(L::LowerTriangular{T,<:SparseMatrixCSC{T}}, B::SparseMatrixCSC) where {T} = A_ldiv_B!(L, Array(B)) (\)(U::UpperTriangular{T,<:SparseMatrixCSC{T}}, B::SparseMatrixCSC) where {T} = A_ldiv_B!(U, Array(B)) +function A_rdiv_B!(A::SparseMatrixCSC{T}, D::Diagonal{T}) where T + dd = D.diag + if (k = length(dd)) ≠ A.n + throw(DimensionMismatch("size(A, 2)=$(A.n) should be size(D, 1)=$k")) + end + nonz = nonzeros(A) + @inbounds for j in 1:k + ddj = dd[j] + if iszero(ddj) + throw(SingularException(j)) + end + for k in nzrange(A, j) + nonz[k] /= ddj + end + end + A +end + +A_rdiv_Bc!(A::SparseMatrixCSC{T}, D::Diagonal{T}) where T = A_rdiv_B!(A, conj(D)) +A_rdiv_Bt!(A::SparseMatrixCSC{T}, D::Diagonal{T}) where T = A_rdiv_B!(A, D) + ## triu, tril function triu(S::SparseMatrixCSC{Tv,Ti}, k::Integer=0) where {Tv,Ti} diff --git a/base/sparse/sparse.jl b/base/sparse/sparse.jl index 23e7c8c54ec6f..28126d551c10b 100644 --- a/base/sparse/sparse.jl +++ b/base/sparse/sparse.jl @@ -10,7 +10,7 @@ import Base: +, -, *, \, /, &, |, xor, == import Base: A_mul_B!, Ac_mul_B, Ac_mul_B!, At_mul_B, At_mul_B! import Base: A_mul_Bc, A_mul_Bt, Ac_mul_Bc, At_mul_Bt import Base: At_ldiv_B, Ac_ldiv_B, A_ldiv_B! -import Base.LinAlg: At_ldiv_B!, Ac_ldiv_B! +import Base.LinAlg: At_ldiv_B!, Ac_ldiv_B!, A_rdiv_B!, A_rdiv_Bc! import Base: @get!, acos, acosd, acot, acotd, acsch, asech, asin, asind, asinh, atan, atand, atanh, broadcast!, chol, conj!, cos, cosc, cosd, cosh, cospi, cot, diff --git a/test/linalg/diagonal.jl b/test/linalg/diagonal.jl index d551b24548db0..01ea996517e32 100644 --- a/test/linalg/diagonal.jl +++ b/test/linalg/diagonal.jl @@ -1,7 +1,8 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license using Base.Test -import Base.LinAlg: BlasFloat, BlasComplex, SingularException +import Base.LinAlg: BlasFloat, BlasComplex, SingularException, A_rdiv_B!, A_rdiv_Bt!, + A_rdiv_Bc! n=12 #Size of matrix problem to test srand(1) @@ -82,7 +83,16 @@ srand(1) @test D\v ≈ DM\v atol=2n^2*eps(relty)*(1+(elty<:Complex)) @test D\U ≈ DM\U atol=2n^3*eps(relty)*(1+(elty<:Complex)) @test A_ldiv_B!(D,copy(v)) ≈ DM\v atol=2n^2*eps(relty)*(1+(elty<:Complex)) + @test At_ldiv_B!(D,copy(v)) ≈ DM\v atol=2n^2*eps(relty)*(1+(elty<:Complex)) + @test Ac_ldiv_B!(conj(D),copy(v)) ≈ DM\v atol=2n^2*eps(relty)*(1+(elty<:Complex)) @test A_ldiv_B!(D,copy(U)) ≈ DM\U atol=2n^3*eps(relty)*(1+(elty<:Complex)) + @test At_ldiv_B!(D,copy(U)) ≈ DM\U atol=2n^3*eps(relty)*(1+(elty<:Complex)) + @test Ac_ldiv_B!(conj(D),copy(U)) ≈ DM\U atol=2n^3*eps(relty)*(1+(elty<:Complex)) + Uc = ctranspose(U) + target = scale!(Uc,inv.(D.diag)) + @test A_rdiv_B!(Uc,D) ≈ target atol=2n^3*eps(relty)*(1+(elty<:Complex)) + @test A_rdiv_Bt!(Uc,D) ≈ target atol=2n^3*eps(relty)*(1+(elty<:Complex)) + @test A_rdiv_Bc!(Uc,conj(D)) ≈ target atol=2n^3*eps(relty)*(1+(elty<:Complex)) @test A_ldiv_B!(D,eye(D)) ≈ D\eye(D) atol=2n^3*eps(relty)*(1+(elty<:Complex)) @test_throws DimensionMismatch A_ldiv_B!(D, ones(elty, n + 1)) @test_throws SingularException A_ldiv_B!(Diagonal(zeros(relty,n)),copy(v)) diff --git a/test/sparse/sparse.jl b/test/sparse/sparse.jl index e22c0b7fe1d0d..f55041f2b87a5 100644 --- a/test/sparse/sparse.jl +++ b/test/sparse/sparse.jl @@ -288,6 +288,15 @@ b = randn(7) @test scale!(sC, 0.5, sA) == scale!(sC, sA, 0.5) end +@testset "inverse scale!" begin + bi = inv.(b) + dAt = transpose(dA) + sAt = transpose(sA) + @test scale!(copy(dAt), bi) ≈ Base.LinAlg.A_rdiv_B!(copy(sAt), Diagonal(b)) + @test scale!(copy(dAt), bi) ≈ Base.LinAlg.A_rdiv_Bt!(copy(sAt), Diagonal(b)) + @test scale!(copy(dAt), conj(bi)) ≈ Base.LinAlg.A_rdiv_Bc!(copy(sAt), Diagonal(b)) +end + @testset "copy!" begin A = sprand(5, 5, 0.2) B = sprand(5, 5, 0.2) From 65d38be4674b307add974b3dd944fdb7c29fff56 Mon Sep 17 00:00:00 2001 From: Singapuram Sanjay SV Date: Wed, 14 Jun 2017 23:49:46 +0530 Subject: [PATCH 1086/1534] Fix compilation on LLVM svn. --- src/debuginfo.cpp | 3 +++ src/disasm.cpp | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/src/debuginfo.cpp b/src/debuginfo.cpp index 56ea92040ec45..558bb83fcff71 100644 --- a/src/debuginfo.cpp +++ b/src/debuginfo.cpp @@ -29,6 +29,9 @@ #else #include #endif +#if JL_LLVM_VERSION >= 50000 +#include +#endif #include #include #if JL_LLVM_VERSION >= 30700 diff --git a/src/disasm.cpp b/src/disasm.cpp index 2e30877a5315d..766f726303fce 100644 --- a/src/disasm.cpp +++ b/src/disasm.cpp @@ -28,8 +28,13 @@ #include "llvm-version.h" #include +#if JL_LLVM_VERSION >= 50000 +#include +#include +#else #include #include +#endif #include #include #include From d1ed663592da0d1d17d3ec22433820025f841b65 Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Wed, 14 Jun 2017 12:09:24 -0700 Subject: [PATCH 1087/1534] Expand FreeBSD build section of the README (#22321) * Expand FreeBSD build section of the README [ci skip] * Add a note about the FreeBSD port in the README [ci skip] --- README.md | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index b0805eb8dfb0e..aef25f96b9cde 100644 --- a/README.md +++ b/README.md @@ -225,20 +225,25 @@ When building Julia, or its dependencies, libraries installed by third party pac ### FreeBSD -On *FreeBSD Release 11.0*, install the gfortran, git, cmake, and gmake packages/ports (`pkg install gcc6 gmake git cmake`), and compile Julia with the command: - - $ echo 'FC=gfortran6' >> Make.user - $ gmake - -You must use the `gmake` command on FreeBSD instead of `make`. - -Note that Julia is community-supported and we have little control over our upstream dependencies, you may still run into issues with dependencies and YMMV. Current known issues include: - - - The x86 arch doesn't support threading due to lack of compiler runtime library support (set `JULIA_THREADS=0`). - - OpenBLAS patches in pkg haven't been upstreamed. - - gfortran can't link binaries. Set `FFLAGS=-Wl,-rpath,/usr/local/lib/gcc6` to work around this (upstream bug submitted to FreeBSD pkg maintainers). - - System libraries installed by pkg are not on the compiler path by default. You may need to add `LDFLAGS=-L/usr/local/lib` and `CPPFLAGS=-I/usr/local/include` to your environment or `Make.user` file to build successfully. - +Clang is the default compiler on FreeBSD 11.0-RELEASE and above. +The remaining build tools are available from the Ports Collection, and can be installed using `pkg install git gcc gmake cmake`. +To build Julia, simply run `gmake`. +(Note that `gmake` must be used rather than `make`, since `make` on FreeBSD corresponds to the incompatible BSD Make rather than GNU Make.) + +It's important to note that the `USE_SYSTEM_*` flags should be used with caution on FreeBSD. +This is because many system libraries, and even libraries from the Ports Collection, link to the system's `libgcc_s.so.1`, +or to another library which links to the system `libgcc_s`. +This library declares its GCC version to be 4.6, which is too old to build Julia, and conflicts with other libraries when linking. +Thus it is highly recommended to simply allow Julia to build all of its dependencies. +If you do choose to use the `USE_SYSTEM_*` flags, note that `/usr/local` is not on the compiler path by default, so you may need +to add `LDFLAGS=-L/usr/local/lib` and `CPPFLAGS=-I/usr/local/include` to your `Make.user`, though doing so may interfere with +other dependencies. + +Some known issues on FreeBSD are: + +* The x86 architecture does not support threading due to lack of compiler runtime library support, so you may need to + set `JULIA_THREADS=0` in your `Make.user` if you're on a 32-bit system. +* Some stack trace information is not available due to differences with libunwind. ### Windows @@ -407,6 +412,7 @@ The following distributions include julia, but the versions may be out of date d * [Nightly builds PPA](https://launchpad.net/~staticfloat/+archive/julianightlies) (depends on the [julia-deps PPA](https://launchpad.net/~staticfloat/+archive/julia-deps/)) * [MacPorts](https://trac.macports.org/browser/trunk/dports/lang/julia/Portfile) * [OS X Homebrew Tap](https://github.com/staticfloat/homebrew-julia/) +* [FreeBSD Ports](https://www.freshports.org/lang/julia/) ## Editor and Terminal Setup From 6facbe3bf50236c25a42b45eba0336593a32f5b4 Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Wed, 14 Jun 2017 12:19:38 -0700 Subject: [PATCH 1088/1534] Improve the platform support section of the README (#22319) --- README.md | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index aef25f96b9cde..6f11425865ca7 100644 --- a/README.md +++ b/README.md @@ -42,12 +42,25 @@ New developers may find the notes in [CONTRIBUTING](https://github.com/JuliaLang ## Currently Supported Platforms -- **Linux** -- **MacOS** -- **FreeBSD** -- **Windows** - -All systems are supported with both x86/64 (64-bit) and x86 (32-bit, except MacOS) architectures. Support for [ARM](https://github.com/JuliaLang/julia/blob/master/README.arm.md), AARCH64, and POWER8 (little-endian) has been added recently. +Julia is built and tested regularly on the following platforms: + +| Operating System | Architecture | CI | Binaries | Support Level | +|:----------------:|:----------------:|:--:|:--------:|:-------------:| +| Linux 2.6.18+ | x86-64 (64-bit) | ✓ | ✓ | Official | +| | i686 (32-bit) | ✓ | ✓ | Official | +| | PowerPC (64-bit) | | ✓ | Official | +| | ARM v7 (32-bit) | | ✓ | Official | +| | ARM v8 (64-bit) | | ✓ | Official | +| macOS 10.8+ | x86-64 (64-bit) | ✓ | ✓ | Official | +| Windows 7+ | x86-64 (64-bit) | ✓ | ✓ | Official | +| | i686 (32-bit) | ✓ | ✓ | Official | +| FreeBSD 11.0+ | x86-64 (64-bit) | | | Community | + +All systems marked with ✓ for CI are tested using continuous integration for every commit. +Systems with ✓ for binaries have official binaries available on the [downloads](https://julialang.org/downloads) page and are tested regularly. +The systems listed here with neither CI nor official binaries are known to build and work, but ongoing support for those platforms is dependent on community efforts. +It's possible that Julia will build and work on other platforms too, and we're always looking to better our platform coverage. +If you're using Julia on a platform not listed here, let us know! ## Source Download and Compilation From 1c40bab035025e7ab996b54d588f3c7512c9991f Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Thu, 15 Jun 2017 11:07:34 +0200 Subject: [PATCH 1089/1534] add rand(::String) (#22224) --- NEWS.md | 9 +++++++++ base/random.jl | 32 ++++++++++++++++++++++++++++++-- test/random.jl | 19 ++++++++++++------- 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/NEWS.md b/NEWS.md index 8253b47908af3..8599a7cb34050 100644 --- a/NEWS.md +++ b/NEWS.md @@ -53,6 +53,9 @@ Library improvements * The function `randn` now accepts complex arguments (`Complex{T <: AbstractFloat}`) ([#21973]). + * The function `rand` can now pick up random elements from strings, associatives + and sets ([#22228], [#21960], [#18155], [#22224]). + * Method lists are now printed as a numbered list. In addition, the source code of a method can be opened in an editor by entering the corresponding number in the REPL and pressing `^Q` ([#22007]). @@ -749,6 +752,7 @@ Command-line option changes [#17785]: https://github.com/JuliaLang/julia/issues/17785 [#18012]: https://github.com/JuliaLang/julia/issues/18012 [#18050]: https://github.com/JuliaLang/julia/issues/18050 +[#18155]: https://github.com/JuliaLang/julia/issues/18155 [#18159]: https://github.com/JuliaLang/julia/issues/18159 [#18218]: https://github.com/JuliaLang/julia/issues/18218 [#18251]: https://github.com/JuliaLang/julia/issues/18251 @@ -882,6 +886,7 @@ Command-line option changes [#21759]: https://github.com/JuliaLang/julia/issues/21759 [#21818]: https://github.com/JuliaLang/julia/issues/21818 [#21825]: https://github.com/JuliaLang/julia/issues/21825 +[#21960]: https://github.com/JuliaLang/julia/issues/21960 [#21973]: https://github.com/JuliaLang/julia/issues/21973 [#21974]: https://github.com/JuliaLang/julia/issues/21974 [#22007]: https://github.com/JuliaLang/julia/issues/22007 @@ -890,3 +895,7 @@ Command-line option changes [#22064]: https://github.com/JuliaLang/julia/issues/22064 [#22187]: https://github.com/JuliaLang/julia/issues/22187 [#22188]: https://github.com/JuliaLang/julia/issues/22188 +[#22224]: https://github.com/JuliaLang/julia/issues/22224 +[#22228]: https://github.com/JuliaLang/julia/issues/22228 +[#22245]: https://github.com/JuliaLang/julia/issues/22245 +[#22310]: https://github.com/JuliaLang/julia/issues/22310 diff --git a/base/random.jl b/base/random.jl index f95e0ed7354a4..2e0c0b49ffdfc 100644 --- a/base/random.jl +++ b/base/random.jl @@ -256,8 +256,9 @@ globalRNG() = GLOBAL_RNG Pick a random element or array of random elements from the set of values specified by `S`; `S` can be -* an indexable collection (for example `1:n` or `['x','y','z']`), or -* an `Associative` or `AbstractSet` object, or +* an indexable collection (for example `1:n` or `['x','y','z']`), +* an `Associative` or `AbstractSet` object, +* a string (considered as a collection of characters), or * a type: the set of values to pick from is then equivalent to `typemin(S):typemax(S)` for integers (this is not applicable to [`BigInt`](@ref)), and to ``[0, 1)`` for floating point numbers; @@ -709,6 +710,33 @@ end rand(rng::AbstractRNG, r::AbstractArray{T}, dims::Dims) where {T} = rand!(rng, Array{T}(dims), r) rand(rng::AbstractRNG, r::AbstractArray, dims::Integer...) = rand(rng, r, convert(Dims, dims)) +# rand from a string + +isvalid_unsafe(s::String, i) = !Base.is_valid_continuation(unsafe_load(pointer(s), i)) +isvalid_unsafe(s::AbstractString, i) = isvalid(s, i) +_endof(s::String) = s.len +_endof(s::AbstractString) = endof(s) + +function rand(rng::AbstractRNG, s::AbstractString)::Char + g = RangeGenerator(1:_endof(s)) + while true + pos = rand(rng, g) + isvalid_unsafe(s, pos) && return s[pos] + end +end + +rand(s::AbstractString) = rand(GLOBAL_RNG, s) + +## rand from a string for arrays +# we use collect(str), which is most of the time more efficient than specialized methods +# (except maybe for very small arrays) +rand!(rng::AbstractRNG, A::AbstractArray, str::AbstractString) = rand!(rng, A, collect(str)) +rand!(A::AbstractArray, str::AbstractString) = rand!(GLOBAL_RNG, A, str) +rand(rng::AbstractRNG, str::AbstractString, dims::Dims) = rand!(rng, Array{eltype(str)}(dims), str) +rand(rng::AbstractRNG, str::AbstractString, d1::Integer, dims::Integer...) = rand(rng, str, convert(Dims, tuple(d1, dims...))) +rand(str::AbstractString, dims::Dims) = rand(GLOBAL_RNG, str, dims) +rand(str::AbstractString, d1::Integer, dims::Integer...) = rand(GLOBAL_RNG, str, d1, dims...) + ## random BitArrays (AbstractRNG) function rand!(rng::AbstractRNG, B::BitArray) diff --git a/test/random.jl b/test/random.jl index 5672ff3066e6d..e08da68baea7c 100644 --- a/test/random.jl +++ b/test/random.jl @@ -319,8 +319,9 @@ for rng in ([], [MersenneTwister(0)], [RandomDevice()]) 1:100 => Int, rand(Int, 100) => Int, Int => Int, - Float64 => Float64] - + Float64 => Float64, + "qwèrtï" => Char, + GenericString("qwèrtï") => Char] b2 = big(2) u3 = UInt(3) for f in [rand, randn, randexp] @@ -346,10 +347,13 @@ for rng in ([], [MersenneTwister(0)], [RandomDevice()]) a0 = rand(rng..., C) ::T a1 = rand(rng..., C, 5) ::Vector{T} a2 = rand(rng..., C, 2, 3) ::Array{T, 2} - a3 = rand(rng..., C, b2, u3) ::Array{T, 2} - a4 = rand!(rng..., Array{T}(5), C) ::Vector{T} - a5 = rand!(rng..., Array{T}(2, 3), C) ::Array{T, 2} - for a in [a0, a1..., a2..., a3..., a4..., a5...] + a3 = rand(rng..., C, (2, 3)) ::Array{T, 2} + a4 = rand(rng..., C, b2, u3) ::Array{T, 2} + a5 = rand!(rng..., Array{T}(5), C) ::Vector{T} + a6 = rand!(rng..., Array{T}(2, 3), C) ::Array{T, 2} + @test size(a1) == (5,) + @test size(a2) == size(a3) == (2, 3) + for a in [a0, a1..., a2..., a3..., a4..., a5..., a6...] if C isa Type @test a isa C else @@ -358,7 +362,8 @@ for rng in ([], [MersenneTwister(0)], [RandomDevice()]) end end for C in [1:0, Dict(), Set(), IntSet(), Int[], - GenericDict(Dict()), GenericSet(Set())] + GenericDict(Dict()), GenericSet(Set()), + "", Base.Test.GenericString("")] @test_throws ArgumentError rand(rng..., C) @test_throws ArgumentError rand(rng..., C, 5) end From 3b5213fad1b98e332e1706a2f35dedea63c3cd3f Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Thu, 15 Jun 2017 11:54:02 +0200 Subject: [PATCH 1090/1534] Require the runtime language feature for such foreigncalls. --- src/ccall.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ccall.cpp b/src/ccall.cpp index c50f0bb20e8e8..29ace38f3e65a 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -1565,6 +1565,12 @@ static jl_cgval_t emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) rt = (jl_value_t*)jl_any_type; // convert return type to jl_value_t* } + // check if we require the runtime + // TODO: could be more fine-grained, + // respecting special functions below that don't require the runtime + if (!llvmcall && (!f_lib || f_lib == JL_DL_LIBNAME)) + JL_FEAT_REQUIRE(ctx, runtime); + // some sanity checking and check whether there's a vararg bool isVa; size_t nargt; From 6fdf36e60028e88a2dd56ef2e50ca974288aaf09 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 14 Jun 2017 00:14:54 -0400 Subject: [PATCH 1091/1534] add missing wb for module->using --- src/module.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/module.c b/src/module.c index 9b518fb2637a8..57378a7b65b85 100644 --- a/src/module.c +++ b/src/module.c @@ -387,6 +387,7 @@ JL_DLLEXPORT void jl_module_using(jl_module_t *to, jl_module_t *from) } arraylist_push(&to->usings, from); + jl_gc_wb(to, from); } JL_DLLEXPORT void jl_module_export(jl_module_t *from, jl_sym_t *s) From 0e19311fe51524efaba570b37abf964bd2a8b295 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 12 Jun 2017 13:30:19 -0400 Subject: [PATCH 1092/1534] incremental deserialize: fix backedge insertion the previous attempt to preserve the backedge map was being too cute it is more reliable to simply flatten the whole map into the new caller also corrects the validation that the backedge is not already invalid make sure internal backedges are only internal: this preserves the expected invariant for jl_insert_backedges/jl_method_instance_delete that any backedges encountered there are purely internal / new enable GC slightly sooner when loading precompiled modules (part of #20671) reverts 11a984bb301e14d6fbd572cb63eea494cf6ab733 - but who needed that anyways --- src/array.c | 13 ++ src/dump.c | 377 ++++++++++++++++++++----------------------- src/gf.c | 5 +- src/julia.h | 1 + src/julia_internal.h | 2 + test/compile.jl | 18 ++- 6 files changed, 210 insertions(+), 206 deletions(-) diff --git a/src/array.c b/src/array.c index c1050609a7cd8..3e77a0e9cbc30 100644 --- a/src/array.c +++ b/src/array.c @@ -1016,6 +1016,19 @@ JL_DLLEXPORT void jl_array_ptr_1d_push(jl_array_t *a, jl_value_t *item) jl_array_ptr_set(a, n - 1, item); } +JL_DLLEXPORT void jl_array_ptr_1d_append(jl_array_t *a, jl_array_t *a2) +{ + assert(jl_typeis(a, jl_array_any_type)); + assert(jl_typeis(a2, jl_array_any_type)); + size_t i; + size_t n = jl_array_nrows(a); + size_t n2 = jl_array_nrows(a2); + jl_array_grow_end(a, n2); + for (i = 0; i < n2; i++) { + jl_array_ptr_set(a, n + i, jl_array_ptr_ref(a2, i)); + } +} + JL_DLLEXPORT void jl_array_ptr_1d_push2(jl_array_t *a, jl_value_t *b, jl_value_t *c) { assert(jl_typeis(a, jl_array_any_type)); diff --git a/src/dump.c b/src/dump.c index 73e7a2c60a42a..555935d1cdd26 100644 --- a/src/dump.c +++ b/src/dump.c @@ -990,7 +990,24 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li jl_serialize_value(s, li->inferred_const); jl_serialize_value(s, li->rettype); jl_serialize_value(s, (jl_value_t*)li->sparam_vals); - jl_serialize_value(s, (jl_value_t*)li->backedges); + jl_array_t *backedges = li->backedges; + if (s->mode == MODE_MODULE && backedges) { + // filter backedges to only contain pointers + // to items that we will actually store (internal == 2) + size_t ins, i, l = jl_array_len(backedges); + jl_method_instance_t **b_edges = (jl_method_instance_t**)jl_array_data(backedges); + for (ins = i = 0; i < l; i++) { + jl_method_instance_t *backedge = b_edges[i]; + if (module_in_worklist(backedge->def.method->module)) { + b_edges[ins++] = backedge; + } + } + if (ins != l) + jl_array_del_end(backedges, l - ins); + if (ins == 0) + backedges = NULL; + } + jl_serialize_value(s, (jl_value_t*)backedges); if (s->mode != MODE_MODULE) { write_int32(s->s, li->min_world); write_int32(s->s, li->max_world); @@ -1157,7 +1174,7 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li } } -static void jl_serialize_missing_backedges_to_mod(jl_serializer_state *s, jl_methtable_t *mt) +static void jl_collect_missing_backedges_to_mod(jl_methtable_t *mt) { jl_array_t *backedges = mt->backedges; if (backedges) { @@ -1176,7 +1193,8 @@ static void jl_serialize_missing_backedges_to_mod(jl_serializer_state *s, jl_met } // the intent of this function is to invert the backedges tree -static void serialize_backedges(jl_method_instance_t *callee) +// for anything that points to a method not part of the worklist +static void collect_backedges(jl_method_instance_t *callee) { jl_array_t *backedges = callee->backedges; if (backedges) { @@ -1195,34 +1213,34 @@ static void serialize_backedges(jl_method_instance_t *callee) } -static int jl_serialize_backedges_to_mod(jl_typemap_entry_t *ml, void *closure) +static int jl_collect_backedges_to_mod(jl_typemap_entry_t *ml, void *closure) { - (void)(jl_serializer_state*)closure; + (void)(jl_array_t*)closure; jl_method_instance_t *callee = ml->func.linfo; - serialize_backedges(callee); + collect_backedges(callee); return 1; } -static int jl_serialize_methcache_from_mod(jl_typemap_entry_t *ml, void *closure) +static int jl_collect_methcache_from_mod(jl_typemap_entry_t *ml, void *closure) { - jl_serializer_state *s = (jl_serializer_state*)closure; + jl_array_t *s = (jl_array_t*)closure; jl_method_t *m = ml->func.method; if (module_in_worklist(m->module)) { - jl_serialize_value(s, m); - jl_serialize_value(s, ml->simplesig); + jl_array_ptr_1d_push(s, (jl_value_t*)m); + jl_array_ptr_1d_push(s, (jl_value_t*)ml->simplesig); } else { - jl_typemap_visitor(m->specializations, jl_serialize_backedges_to_mod, closure); + jl_typemap_visitor(m->specializations, jl_collect_backedges_to_mod, closure); } return 1; } -static void jl_serialize_methtable_from_mod(jl_serializer_state *s, jl_typename_t *tn) +static void jl_collect_methtable_from_mod(jl_array_t *s, jl_typename_t *tn) { - jl_typemap_visitor(tn->mt->defs, jl_serialize_methcache_from_mod, (void*)s); + jl_typemap_visitor(tn->mt->defs, jl_collect_methcache_from_mod, (void*)s); } -static void jl_serialize_lambdas_from_mod(jl_serializer_state *s, jl_module_t *m) +static void jl_collect_lambdas_from_mod(jl_array_t *s, jl_module_t *m) { if (module_in_worklist(m)) return; @@ -1240,8 +1258,8 @@ static void jl_serialize_lambdas_from_mod(jl_serializer_state *s, jl_module_t *m if (mt != NULL && (jl_value_t*)mt != jl_nothing && (mt != jl_type_type_mt || tn == jl_type_typename)) { - jl_serialize_methtable_from_mod(s, tn); - jl_serialize_missing_backedges_to_mod(s, mt); + jl_collect_methtable_from_mod(s, tn); + jl_collect_missing_backedges_to_mod(mt); } } } @@ -1249,7 +1267,7 @@ static void jl_serialize_lambdas_from_mod(jl_serializer_state *s, jl_module_t *m jl_module_t *child = (jl_module_t*)b->value; if (child != m && child->parent == m && child->name == b->name) { // this is the original/primary binding for the submodule - jl_serialize_lambdas_from_mod(s, (jl_module_t*)b->value); + jl_collect_lambdas_from_mod(s, (jl_module_t*)b->value); } } } @@ -1257,31 +1275,48 @@ static void jl_serialize_lambdas_from_mod(jl_serializer_state *s, jl_module_t *m } } -static void jl_serialize_backedges(jl_serializer_state *s) +// flatten the backedge map reachable from caller into callees +static void jl_collect_backedges_to(jl_method_instance_t *caller, jl_array_t *direct_callees, arraylist_t *to_restore) { - arraylist_t worklist; - arraylist_new(&worklist, 0); + jl_array_t **pcallees = (jl_array_t**)ptrhash_bp(&edges_map, (void*)caller), + *callees = *pcallees; + if (callees != HT_NOTFOUND) { + arraylist_push(to_restore, (void*)pcallees); + arraylist_push(to_restore, (void*)callees); + *pcallees = (jl_array_t*) HT_NOTFOUND; + jl_array_ptr_1d_append(direct_callees, callees); + size_t i, l = jl_array_len(callees); + for (i = 0; i < l; i++) { + jl_value_t *c = jl_array_ptr_ref(callees, i); + if (jl_is_method_instance(c)) { + jl_collect_backedges_to((jl_method_instance_t*)c, direct_callees, to_restore); + } + } + } +} + +static void jl_collect_backedges(jl_array_t *s) +{ + arraylist_t to_restore; + arraylist_new(&to_restore, 0); size_t i; void **table = edges_map.table; for (i = 0; i < edges_map.size; i += 2) { jl_method_instance_t *caller = (jl_method_instance_t*)table[i]; - jl_array_t *callee = (jl_array_t*)table[i + 1]; - if (callee != HT_NOTFOUND && module_in_worklist(caller->def.method->module)) { - arraylist_push(&worklist, (void*)caller); - } - } - while (worklist.len) { - jl_method_instance_t *caller = (jl_method_instance_t*)arraylist_pop(&worklist); - jl_array_t **pcallee = (jl_array_t**)ptrhash_bp(&edges_map, (void*)caller), - *callee = *pcallee; - if (callee != HT_NOTFOUND) { - jl_serialize_value(s, caller); - jl_serialize_value(s, callee); - *pcallee = (jl_array_t*) HT_NOTFOUND; - for (i = 0; i < jl_array_len(callee); i++) { - jl_value_t *c = jl_array_ptr_ref(callee, i); - if (jl_is_method_instance(c)) - arraylist_push(&worklist, (void*)c); + jl_array_t *callees = (jl_array_t*)table[i + 1]; + if (callees != HT_NOTFOUND && module_in_worklist(caller->def.method->module)) { + size_t i, l = jl_array_len(callees); // length may change during iteration + for (i = 0; i < l; i++) { // only consider the initial list + jl_value_t *c = jl_array_ptr_ref(callees, i); + if (jl_is_method_instance(c)) { + jl_collect_backedges_to((jl_method_instance_t*)c, callees, &to_restore); + } + } + jl_array_ptr_1d_push(s, (jl_value_t*)caller); + jl_array_ptr_1d_push(s, (jl_value_t*)callees); + while (to_restore.len) { + void **pp = (void**)arraylist_pop(&to_restore); + *pp = arraylist_pop(&to_restore); } } } @@ -2141,130 +2176,94 @@ static jl_value_t *jl_deserialize_value_(jl_serializer_state *s, jl_value_t *vta } } -JL_EXTENSION typedef struct _linkedlist_t { - struct _linkedlist_t *next; - union { - struct { - jl_method_t *meth; - jl_tupletype_t *simpletype; - }; - struct { - jl_method_instance_t *caller; - jl_array_t *callee; - }; - } def[100]; - size_t count; -} linkedlist_t; - -static void jl_deserialize_methods_from_mod(jl_serializer_state *s, linkedlist_t *list) +static void jl_insert_methods(jl_array_t *list) { - list->count = 0; - list->next = NULL; - while (1) { - if (list->count == sizeof(list->def) / sizeof(list->def[0])) { - list->next = (linkedlist_t*)malloc(sizeof(linkedlist_t)); - list = list->next; - list->count = 0; - list->next = NULL; - } - // using a linked list so that we can take these addresses - // and have them remain constant (arraylist reallocates) - jl_value_t **loc_meth = (jl_value_t**)&list->def[list->count].meth; - jl_value_t **loc_styp = (jl_value_t**)&list->def[list->count].simpletype; - *loc_meth = jl_deserialize_value(s, loc_meth); - if (*loc_meth == NULL) - return; - *loc_styp = jl_deserialize_value(s, loc_styp); - list->count++; + size_t i, l = jl_array_len(list); + for (i = 0; i < l; i += 2) { + jl_method_t *meth = (jl_method_t*)jl_array_ptr_ref(list, i); + jl_tupletype_t *simpletype = (jl_tupletype_t*)jl_array_ptr_ref(list, i + 1); + assert(jl_is_method(meth)); + jl_datatype_t *gf = jl_first_argument_datatype((jl_value_t*)meth->sig); + assert(jl_is_datatype(gf) && gf->name->mt); + jl_method_table_insert(gf->name->mt, meth, simpletype); } } -static void jl_insert_methods(linkedlist_t *list) +static size_t lowerbound_dependent_world_set(size_t world, arraylist_t *dependent_worlds) { - while (list) { - size_t i; - for (i = 0; i < list->count; i++) { - assert(jl_is_method(list->def[i].meth)); - jl_method_t *meth = list->def[i].meth; - jl_datatype_t *gf = jl_first_argument_datatype((jl_value_t*)meth->sig); - assert(jl_is_datatype(gf) && gf->name->mt); - jl_method_table_insert(gf->name->mt, meth, list->def[i].simpletype); - } - list = list->next; + size_t i, l = dependent_worlds->len; + if (world <= (size_t)dependent_worlds->items[l - 1]) + return world; + for (i = 0; i < l; i++) { + size_t depworld = (size_t)dependent_worlds->items[i]; + if (depworld <= world) + return depworld; } + abort(); // unreachable } void jl_method_instance_delete(jl_method_instance_t *mi); -static void jl_insert_backedges(linkedlist_t *list) -{ - while (list) { - size_t i, j; - for (i = 0; i < list->count; i++) { - jl_method_instance_t *caller = list->def[i].caller; - assert(jl_is_method_instance(caller)); - jl_array_t *callees = list->def[i].callee; - assert(jl_is_array(callees)); - if (!caller->inferred || module_in_worklist(caller->def.method->module)) { - for (j = 0; j < jl_array_len(callees); j++) { - jl_value_t *callee = jl_array_ptr_ref(callees, j); - if (jl_is_method_instance(callee)) { - jl_method_instance_t *callee_mi = (jl_method_instance_t*)callee; - if (!module_in_worklist(callee_mi->def.method->module)) { - // verify that this MethodInstance is still the correct lookup for this callee sig - jl_value_t *sig = callee_mi->specTypes; - jl_method_t *m = NULL; - if (jl_is_datatype(sig)) { - jl_datatype_t *ftype = jl_first_argument_datatype(sig); - jl_methtable_t *mt = ftype->name->mt; - jl_typemap_entry_t *entry = jl_typemap_assoc_by_type( - mt->defs, (jl_datatype_t*)sig, - NULL, /*inexact*/0, /*subtype*/1, 0, jl_world_counter); - if (entry != NULL) - m = entry->func.method; - } - if (m != callee_mi->def.method) { - // probably no good, just invalidate everything now - jl_method_instance_delete(caller); - break; - } - } - if (callee_mi->max_world == ~(size_t)0) { - // if this callee is still valid, just add a backedge - jl_method_instance_add_backedge(callee_mi, caller); - } - else if (caller->min_world == jl_world_counter) { - // if this caller was just added, delete everything associated with it - jl_method_instance_delete(caller); - break; - } - else { - // the caller must have been something pre-existing - // assume that it'll take care of deleting the deserialized code - // whenever we process it here - } - } - else { - jl_datatype_t *gf = jl_first_argument_datatype(callee); - assert(jl_is_datatype(gf) && gf->name->mt); - jl_method_table_add_backedge(gf->name->mt, callee, (jl_value_t*)caller); - } +static void jl_insert_backedges(jl_array_t *list, arraylist_t *dependent_worlds) +{ + size_t i, l = jl_array_len(list); + for (i = 0; i < l; i += 2) { + jl_method_instance_t *caller = (jl_method_instance_t*)jl_array_ptr_ref(list, i); + assert(jl_is_method_instance(caller)); + assert(caller->min_world == jl_world_counter); // caller should be new + jl_array_t *callees = (jl_array_t*)jl_array_ptr_ref(list, i + 1); + assert(jl_is_array(callees)); + int valid = 1; + size_t j; + for (j = 0; valid && j < jl_array_len(callees); j++) { + jl_value_t *callee = jl_array_ptr_ref(callees, j); + jl_method_instance_t *callee_mi = (jl_method_instance_t*)callee; + jl_value_t *sig; + if (jl_is_method_instance(callee)) { + sig = callee_mi->specTypes; + assert(!module_in_worklist(callee_mi->def.method->module)); + assert(callee_mi->max_world == ~(size_t)0); + } + else { + sig = callee; + } + // verify that this backedge doesn't intersect with any new methods + size_t min_valid = 0; + size_t max_valid = ~(size_t)0; + jl_value_t *matches = jl_matching_methods((jl_tupletype_t*)sig, 50, 1, jl_world_counter, &min_valid, &max_valid); + if (matches == jl_false) + valid = 0; + size_t k; + for (k = 0; valid && k < jl_array_len(matches); k++) { + jl_method_t *m = (jl_method_t*)jl_svecref(jl_array_ptr_ref(matches, k), 2); + if (lowerbound_dependent_world_set(m->min_world, dependent_worlds) != m->min_world) { + // intersection has a new method and is now probably no good, just invalidate everything now + valid = 0; + } + } + } + if (valid) { + // if this callee is still valid, add all the backedges + for (j = 0; j < jl_array_len(callees); j++) { + jl_value_t *callee = jl_array_ptr_ref(callees, j); + if (jl_is_method_instance(callee)) { + jl_method_instance_add_backedge((jl_method_instance_t*)callee, caller); + } + else { + jl_datatype_t *ftype = jl_first_argument_datatype(callee); + jl_methtable_t *mt = ftype->name->mt; + assert(jl_is_datatype(ftype) && mt); + jl_method_table_add_backedge(mt, callee, (jl_value_t*)caller); } } } - list = list->next; + else { + // otherwise delete it + jl_method_instance_delete(caller); + } } } -static void free_linkedlist(linkedlist_t *list) -{ - while (list) { - linkedlist_t *prev = list; - list = list->next; - free(prev); - } -} - static int size_isgreater(const void *a, const void *b) { return *(size_t*)b - *(size_t*)a; @@ -2905,17 +2904,20 @@ JL_DLLEXPORT int jl_save_incremental(const char *fname, jl_array_t *worklist) backref_table_numel = 1; jl_idtable_type = jl_base_module ? jl_get_global(jl_base_module, jl_symbol("ObjectIdDict")) : NULL; - int en = jl_gc_enable(0); + int en = jl_gc_enable(0); // edges map is not gc-safe + jl_array_t *lambdas = jl_alloc_vec_any(0); + jl_array_t *edges = jl_alloc_vec_any(0); + jl_collect_lambdas_from_mod(lambdas, jl_main_module); + jl_collect_backedges(edges); + jl_serializer_state s = { &f, MODE_MODULE, NULL, NULL, jl_get_ptls_states() }; jl_serialize_value(&s, worklist); - jl_serialize_lambdas_from_mod(&s, jl_main_module); - jl_serialize_value(&s, NULL); // signal end of lambdas - jl_serialize_backedges(&s); - jl_serialize_value(&s, NULL); // signal end of backedges + jl_serialize_value(&s, lambdas); + jl_serialize_value(&s, edges); jl_finalize_serializer(&s); // done with f serializer_worklist = NULL; @@ -3108,17 +3110,6 @@ static void jl_update_backref_list(jl_value_t *old, jl_value_t *_new, size_t sta } } -static size_t lowerbound_dependent_world_set(size_t world, arraylist_t *dependent_worlds) -{ - size_t i, l = dependent_worlds->len; - for (i = 0; i < l; i++) { - size_t depworld = (size_t)dependent_worlds->items[i]; - if (depworld <= world) - return depworld; - } - return jl_main_module->primary_world; -} - // repeatedly look up older methods until we come to one that existed // at the time this module was serialized static jl_method_t *jl_lookup_method_worldset(jl_methtable_t *mt, jl_datatype_t *sig, arraylist_t *dependent_worlds) @@ -3128,28 +3119,6 @@ static jl_method_t *jl_lookup_method_worldset(jl_methtable_t *mt, jl_datatype_t while (1) { _new = (jl_method_t*)jl_methtable_lookup(mt, sig, world); assert(_new && jl_is_method(_new)); - if (_new->min_world == jl_world_counter) - return _new; - if (_new->min_world <= jl_main_module->primary_world) - return _new; - world = lowerbound_dependent_world_set(_new->min_world, dependent_worlds); - if (world == _new->min_world) - return _new; - } -} - -// repeated look up older methods until we come to one that was valid -// at the time this module was serialized -static jl_method_instance_t *jl_lookup_methodinstance_worldset(jl_method_t *m, jl_datatype_t *argtypes, jl_svec_t *env, arraylist_t *dependent_worlds) -{ - size_t world = jl_world_counter; - jl_method_instance_t *_new; - while (1) { - _new = jl_specializations_get_linfo(m, (jl_value_t*)argtypes, env, world); - if (_new->min_world == jl_world_counter) - return _new; - if (_new->min_world <= jl_main_module->primary_world) - return _new; world = lowerbound_dependent_world_set(_new->min_world, dependent_worlds); if (world == _new->min_world) return _new; @@ -3182,7 +3151,7 @@ static jl_method_instance_t *jl_recache_method_instance(jl_method_instance_t *li //assert(ti != jl_bottom_type); (void)ti; if (ti == jl_bottom_type) env = jl_emptysvec; // the intersection may fail now if the type system had made an incorrect subtype env in the past - jl_method_instance_t *_new = jl_lookup_methodinstance_worldset(m, argtypes, env, dependent_worlds); + jl_method_instance_t *_new = jl_specializations_get_linfo(m, (jl_value_t*)argtypes, env, jl_world_counter); jl_update_backref_list((jl_value_t*)li, (jl_value_t*)_new, start); return _new; } @@ -3222,6 +3191,7 @@ static int trace_method(jl_typemap_entry_t *entry, void *closure) static jl_value_t *_jl_restore_incremental(ios_t *f) { + jl_ptls_t ptls = jl_get_ptls_states(); if (ios_eof(f) || !jl_read_verify_header(f)) { ios_close(f); return jl_get_exceptionf(jl_errorexception_type, @@ -3250,28 +3220,28 @@ static jl_value_t *_jl_restore_incremental(ios_t *f) } // prepare to deserialize + int en = jl_gc_enable(0); + jl_gc_enable_finalizers(ptls, 0); + ++jl_world_counter; // reserve a world age for the deserialization + arraylist_new(&backref_list, 4000); arraylist_push(&backref_list, jl_main_module); arraylist_new(&flagref_list, 0); + arraylist_push(&dependent_worlds, (void*)jl_world_counter); + arraylist_push(&dependent_worlds, (void*)jl_main_module->primary_world); qsort(dependent_worlds.items, dependent_worlds.len, sizeof(size_t), size_isgreater); - int en = jl_gc_enable(0); - ++jl_world_counter; // reserve a world age for the deserialization jl_serializer_state s = { f, MODE_MODULE, NULL, NULL, - jl_get_ptls_states() + ptls }; - jl_array_t *restored = NULL; - jl_array_t *init_order = NULL; - restored = (jl_array_t*)jl_deserialize_value(&s, (jl_value_t**)&restored); + jl_array_t *restored = (jl_array_t*)jl_deserialize_value(&s, (jl_value_t**)&restored); serializer_worklist = restored; // get list of external generic functions - linkedlist_t external_methods; - jl_deserialize_methods_from_mod(&s, &external_methods); - linkedlist_t external_backedges; - jl_deserialize_methods_from_mod(&s, &external_backedges); + jl_value_t *external_methods = jl_deserialize_value(&s, &external_methods); + jl_value_t *external_backedges = jl_deserialize_value(&s, &external_backedges); arraylist_t *tracee_list = NULL; if (jl_newmeth_tracer) @@ -3280,21 +3250,22 @@ static jl_value_t *_jl_restore_incremental(ios_t *f) // at this point, the AST is fully reconstructed, but still completely disconnected // now all of the interconnects will be created jl_recache_types(); // make all of the types identities correct - jl_recache_other(&dependent_worlds); // make all of the other objects identities correct (needs to be after recache types) - init_order = jl_finalize_deserializer(&s, tracee_list); // done with f and s (needs to be after recache types) - jl_insert_methods(&external_methods); // hook up methods of external generic functions (needs to be after recache other) - jl_insert_backedges(&external_backedges); // restore external backedges (needs to be after insert methods) - free_linkedlist(external_methods.next); - free_linkedlist(external_backedges.next); - serializer_worklist = NULL; + jl_insert_methods((jl_array_t*)external_methods); // hook up methods of external generic functions (needs to be after recache types) + jl_recache_other(&dependent_worlds); // make all of the other objects identities correct (needs to be after insert methods) + jl_array_t *init_order = jl_finalize_deserializer(&s, tracee_list); // done with f and s (needs to be after recache) + + JL_GC_PUSH3(&init_order, &restored, &external_backedges); + jl_gc_enable(en); // subtyping can allocate a lot, not valid before recache-other + + jl_insert_backedges((jl_array_t*)external_backedges, &dependent_worlds); // restore external backedges (needs to be last) + serializer_worklist = NULL; arraylist_free(&flagref_list); arraylist_free(&backref_list); arraylist_free(&dependent_worlds); ios_close(f); - JL_GC_PUSH2(&init_order, &restored); - jl_gc_enable(en); + jl_gc_enable_finalizers(ptls, 1); // make sure we don't run any Julia code concurrently before this point if (tracee_list) { jl_methtable_t *mt; while ((mt = (jl_methtable_t*)arraylist_pop(tracee_list)) != NULL) diff --git a/src/gf.c b/src/gf.c index 800901649870b..1247383b24c47 100644 --- a/src/gf.c +++ b/src/gf.c @@ -1249,6 +1249,8 @@ static int JL_DEBUG_METHOD_INVALIDATION = 0; // invalidate cached methods that had an edge to a replaced method static void invalidate_method_instance(jl_method_instance_t *replaced, size_t max_world, int depth) { + if (!jl_is_method(replaced->def.method)) + return; JL_LOCK_NOGC(&replaced->def.method->writelock); jl_array_t *backedges = replaced->backedges; if (replaced->max_world > max_world) { @@ -1599,7 +1601,8 @@ jl_method_instance_t *jl_method_lookup(jl_methtable_t *mt, jl_value_t **args, si // // lim is the max # of methods to return. if there are more, returns jl_false. // -1 for no limit. -JL_DLLEXPORT jl_value_t *jl_matching_methods(jl_tupletype_t *types, int lim, int include_ambiguous, size_t world, size_t *min_valid, size_t *max_valid) +JL_DLLEXPORT jl_value_t *jl_matching_methods(jl_tupletype_t *types, int lim, int include_ambiguous, + size_t world, size_t *min_valid, size_t *max_valid) { jl_value_t *unw = jl_unwrap_unionall((jl_value_t*)types); if (jl_is_tuple_type(unw) && jl_tparam0(unw) == jl_bottom_type) diff --git a/src/julia.h b/src/julia.h index 183cfef8ab532..65e27a02db8df 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1206,6 +1206,7 @@ JL_DLLEXPORT void jl_array_del_beg(jl_array_t *a, size_t dec); JL_DLLEXPORT void jl_array_sizehint(jl_array_t *a, size_t sz); JL_DLLEXPORT void jl_array_ptr_1d_push(jl_array_t *a, jl_value_t *item); JL_DLLEXPORT void jl_array_ptr_1d_push2(jl_array_t *a, jl_value_t *b, jl_value_t *c); +JL_DLLEXPORT void jl_array_ptr_1d_append(jl_array_t *a, jl_array_t *a2); JL_DLLEXPORT jl_value_t *jl_apply_array_type(jl_value_t *type, size_t dim); // property access JL_DLLEXPORT void *jl_array_ptr(jl_array_t *a); diff --git a/src/julia_internal.h b/src/julia_internal.h index 4689211efd850..eb9f91420dc64 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -487,6 +487,8 @@ jl_method_instance_t *jl_method_lookup_by_type(jl_methtable_t *mt, jl_tupletype_ jl_method_instance_t *jl_method_lookup(jl_methtable_t *mt, jl_value_t **args, size_t nargs, int cache, size_t world); jl_value_t *jl_gf_invoke(jl_tupletype_t *types, jl_value_t **args, size_t nargs); jl_method_instance_t *jl_lookup_generic(jl_value_t **args, uint32_t nargs, uint32_t callsite, size_t world); +JL_DLLEXPORT jl_value_t *jl_matching_methods(jl_tupletype_t *types, int lim, int include_ambiguous, + size_t world, size_t *min_valid, size_t *max_valid); JL_DLLEXPORT jl_datatype_t *jl_first_argument_datatype(jl_value_t *argtypes); jl_datatype_t *jl_argument_datatype(jl_value_t *argt); diff --git a/test/compile.jl b/test/compile.jl index acbf869a5b52c..c4d2f5353cafe 100644 --- a/test/compile.jl +++ b/test/compile.jl @@ -30,6 +30,14 @@ try __precompile__(true) module $FooBase_module + import Base: hash, > + struct fmpz end + struct typeA end + >(x::fmpz, y::Int) = Base.cmp(x, y) > 0 + function hash(a::typeA, h::UInt) + d = den(a) + return h + end end """) write(Foo2_file, @@ -47,8 +55,14 @@ try __precompile__(true) module $Foo_module - using $FooBase_module + using $FooBase_module, $FooBase_module.typeA import $Foo2_module: $Foo2_module, override + import $FooBase_module.hash + + struct typeB + y::typeA + end + hash(x::typeB) = hash(x.y) # test that docs get reconnected @doc "foo function" foo(x) = x + 1 @@ -157,7 +171,7 @@ try cachefile = joinpath(dir, "$Foo_module.ji") # use _require_from_serialized to ensure that the test fails if # the module doesn't reload from the image: - @test_warn "WARNING: replacing module Foo4b3a94a1a081a8cb.\nWARNING: Method definition " begin + @test_warn "WARNING: replacing module $Foo_module." begin @test isa(Base._require_from_serialized(myid(), Foo_module, cachefile, #=broadcast-load=#false), Array{Any,1}) end From 52069d71c7db2d5ba4d0a569f1254ee76593a6c6 Mon Sep 17 00:00:00 2001 From: Andreas Noack Date: Thu, 15 Jun 2017 12:57:55 -0400 Subject: [PATCH 1093/1534] Move the BLAS test to the linalg subdirectory (#22375) --- test/choosetests.jl | 5 +++-- test/{ => linalg}/blas.jl | 0 2 files changed, 3 insertions(+), 2 deletions(-) rename test/{ => linalg}/blas.jl (100%) diff --git a/test/choosetests.jl b/test/choosetests.jl index b8a88c16f2ee5..778385e3c5693 100644 --- a/test/choosetests.jl +++ b/test/choosetests.jl @@ -20,7 +20,7 @@ function choosetests(choices = []) "printf", "char", "strings", "triplequote", "unicode", "intrinsics", "dates", "dict", "hashing", "iobuffer", "staged", "offsetarray", "arrayops", "tuple", "reduce", "reducedim", "random", "abstractarray", - "intfuncs", "simdloop", "vecelement", "blas", "sparse", + "intfuncs", "simdloop", "vecelement", "sparse", "bitarray", "copy", "math", "fastmath", "functional", "iterators", "operators", "path", "ccall", "parse", "loading", "bigint", "bigfloat", "sorting", "statistics", "spawn", "backtrace", @@ -130,7 +130,8 @@ function choosetests(choices = []) "linalg/diagonal", "linalg/pinv", "linalg/givens", "linalg/cholesky", "linalg/lu", "linalg/symmetric", "linalg/generic", "linalg/uniformscaling", "linalg/lq", - "linalg/hessenberg", "linalg/rowvector", "linalg/conjarray"] + "linalg/hessenberg", "linalg/rowvector", "linalg/conjarray", + "linalg/blas"] if Base.USE_GPL_LIBS push!(linalgtests, "linalg/arnoldi") end diff --git a/test/blas.jl b/test/linalg/blas.jl similarity index 100% rename from test/blas.jl rename to test/linalg/blas.jl From 1a3391f9c849ea812990f63f1619f1a244963c44 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Thu, 15 Jun 2017 13:10:59 -0500 Subject: [PATCH 1094/1534] Correct rendering of unicode on unicode-input.md (#22369) Surrounds the unicode category characters Mn and Me with no-break spaces when rendering the unicode character. This follows how the unicode.org webpage displays unicode characters. Note some characters will not be rendered including: '\u2095':'\u2096' '\u20D0':'\u20DC' '\u20DE':'\u20F0' This behavior matches the unicode.org behavior. --- doc/src/manual/unicode-input.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/src/manual/unicode-input.md b/doc/src/manual/unicode-input.md index 69c7d3eb5452c..bb0ab649e70b7 100644 --- a/doc/src/manual/unicode-input.md +++ b/doc/src/manual/unicode-input.md @@ -20,6 +20,8 @@ the symbol). # Generate a table containing all LaTeX and Emoji tab completions available in the REPL. # +const NBSP = '\u00A0' + function tab_completions(symbols...) completions = Dict{String, Vector{String}}() for each in symbols, (k, v) in each @@ -41,10 +43,12 @@ function unicode_data() return names end -# Prepend a dotted circle ('◌' i.e. '\u25CC') to combining characters +# Surround combining characters with no-break spaces (i.e '\u00A0'). Follows the same format +# for how unicode is displayed on the unicode.org website: +# http://unicode.org/cldr/utility/character.jsp?a=0300 function fix_combining_chars(char) cat = Base.UTF8proc.category_code(char) - return string(cat == 6 || cat == 8 ? "◌" : "", char) + return cat == 6 || cat == 8 ? "$NBSP$char$NBSP" : "$char" end From 7227007ce277b7418a836177a50c4ffba96d5fd0 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Thu, 27 Apr 2017 13:44:34 -0400 Subject: [PATCH 1095/1534] Introduce new GC root placement pass Design notes are in the devdocs. Algorithmic documentation in code comments. --- doc/src/devdocs/llvm.md | 157 ++++ src/Makefile | 2 +- src/ccall.cpp | 55 +- src/cgutils.cpp | 271 ++++-- src/codegen.cpp | 477 ++++++---- src/codegen_internal.h | 2 + src/codegen_shared.h | 6 + src/intrinsics.cpp | 38 +- src/jitlayers.cpp | 63 +- src/jitlayers.h | 6 +- src/julia.h | 4 + src/llvm-gc-invariant-verifier.cpp | 171 ++++ src/llvm-gcroot.cpp | 8 +- src/llvm-late-gc-lowering.cpp | 1347 ++++++++++++++++++++++++++++ test/llvmpasses/gcroots-391.ll | 67 ++ test/llvmpasses/gcroots-50.ll | 64 ++ test/llvmpasses/gcroots.ll | 296 ++++++ 17 files changed, 2715 insertions(+), 319 deletions(-) create mode 100644 src/codegen_shared.h create mode 100644 src/llvm-gc-invariant-verifier.cpp create mode 100644 src/llvm-late-gc-lowering.cpp create mode 100644 test/llvmpasses/gcroots-391.ll create mode 100644 test/llvmpasses/gcroots-50.ll create mode 100644 test/llvmpasses/gcroots.ll diff --git a/doc/src/devdocs/llvm.md b/doc/src/devdocs/llvm.md index 35266648de520..ecfe7a0eb3dd0 100644 --- a/doc/src/devdocs/llvm.md +++ b/doc/src/devdocs/llvm.md @@ -107,3 +107,160 @@ study it and the pass of interest in isolation. 4. Strip the debug metadata and fix up the TBAA metadata by hand. The last step is labor intensive. Suggestions on a better way would be appreciated. + +## GC root placement + +GC root placement is done by an LLVM late in the pass pipeline. Doing GC root +placement this late enables LLVM to make more aggressive optimizations around +code that requires GC roots, as well as allowing us to reduce the number of +required GC roots and GC root store operations (since LLVM doesn't understand +our GC, it wouldn't otherwise know what it is and is not allowed to do with +values stored to the GC frame, so it'll conservatively do very little). As an +example, consider an error path +``` + if some_condition() + #= Use some variables maybe =# + error("An error occurred") + end +``` +During constant folding, LLVM may discover that the condition is always false, +and can remove the basic block. However, if GC root lowering is done early, +the GC root slots used in the deleted block, as well as any values kept alive +in those slots only because they were used in the error path, would be kept +alive by LLVM. By doing GC root lowering late, we give LLVM the license to do +any of its usual optimizations (constant folding, dead code elimination, etc.), +without having to worry (too much) about which values may or may not be gc +tracked. + +However, in order to be able to do late GC root placement, we need to be able to +identify a) which pointers are gc tracked and b) all uses of such pointers. The +goal of the GC placement pass is thus simple: + +Minimize the number of needed gc roots/stores to them subject to the constraint +that at every safepoint, any live gc-tracked pointer (i.e. for which there is +a path after this point that contains a use of this pointer) is in some gc slot. + +### Representation + +The primary difficulty is thus choosing an IR representation that allows us to +identify gc-tracked pointers and their uses, even after the program has been +run through the optimizer. Our design makes use of three LLVM features to achieve +this: +- Custom address spaces +- Operand Bundles +- non-integral pointers + +Custom address spaces allow us to tag every point with an integer that needs +to be preserved through optimizations. The compiler may not insert casts between +address spaces that did not exist in the original program and it must never +change the address space of a pointer on a load/store/etc operation. This allows +us to annotate which pointers are gc-tracked in an optimizer-resistant way. Note +that metadata would not be able to achieve the same purpose. Metadata is supposed +to always be discardable without altering the semantics of the program. However, +failing to identify a gc-tracked pointer alters the resulting program behavior +dramatically - it'll probably crash or return wrong results. We currently use +three different addressspaces (their numbers are defined in src/codegen_shared.cpp): + +- GC Tracked Pointers (currently 10): These are pointers to boxed values that may be put + into a GC frame. It is loosely equivalent to a `jl_value_t*` pointer on the C + side. N.B. It is illegal to ever have a pointer in this address space that may + not be stored to a GC slot. +- Derived Pointers (currently 11): These are pointers that are derived from some GC + tracked pointer. Uses of these pointers generate uses of the original pointer. + However, they need not themselves be known to the GC. The GC root placement + pass MUST always find the GC tracked pointer from which this pointer is + derived and use that as the pointer to root. +- Callee Rooted Pointers (currently 12): This is a utility address space to express the + notion of a callee rooted value. All values of this address space MUST be + storable to a GC root (though it is possible to relax this condition in the + future), but unlike the other pointers need not be rooted if passed to a + call (they do still need to be rooted if they are live across another safepoint + between the definition and the call). + +### Invariants. +The GC root placement pass makes use of several invariants, which need +to be observed by the frontend and are preserved by the optimizer. + +First, only the following addressspace casts are allowed +- 0->{Tracked,Derived,CalleeRooted}: It is allowable to decay an untracked pointer to any of the + other. However, do note that the optimizer has broad license to not root + such a value. It is never safe to have a value in addressspace 0 in any part + of the program if it is (or is derived from) a value that requires a GC root. +- Tracked->Derived: This is the standard decay route for interior values. The placement + pass will look for these to identify the base pointer for any use. +- Tracked->CalleeRooted: Addrspace CalleeRooted serves merely as a hint that a GC root is not + required. However, do note that the Derived->CalleeRooted decay is prohibited, since + pointers should generally be storable to a GC slot, even in this address space. + +Now let us consider what constitutes a use: +- Loads whose loaded values is in one of the address spaces +- Stores of a value in one of the address spaces to a location +- Stores to a pointer in one of the address spaces +- Calls for which a value in one of the address spaces is an operand +- Calls in jlcall ABI, for which the argument array contains a value +- Return instructions. + +We explicitly allow load/stores and simple calls in address spaces Tracked/Derived. Elements of jlcall +argument arrays must always be in address space Tracked (it is required by the ABI that +they are valid `jl_value_t*` pointers). The same is true for return instructions +(though note that struct return arguments are allowed to have any of the address +spaces). The only allowable use of an address space CalleRooted pointer is to pass it to +a call (which must have an appropriately typed operand). + +Further, we disallow getelementptr in addrspace Tracked. This is because unless +the operation is a noop, the resulting pointer will not be validly storable +to a GC slot and may thus not be in this address space. If such a pointer +is required, it should be decayed to addrspace Derived first. + +Lastly, we disallow inttoptr/ptrtoint instructions in these address spaces. +Having these instructions would mean that some i64 values are really gc tracked. +This is problematic, because it breaks that stated requirement that we're able +to identify gc-relevant pointers. This invariant is accomplished using the LLVM +"non-integral pointers" feature, which is new in LLVM 5.0. It prohibits the +optimizer from making optimizations that would introduce these operations. Note +we can still insert static constants at JIT time by using inttoptr in address +space 0 and then decaying to the appropriate address space afterwards. + +### Supporting ccall +One important aspect missing from the discussion so far is the handling of +`ccall`. `ccall` has the peculiar feature that the location and scope of a use +do not coincide. As an example consider: +``` +A = randn(1024) +ccall(:foo, Void, (Ptr{Float64},), A) +``` +In lowering, the compiler will insert a conversion from the array to the +pointer which drops the reference to the array value. However, we of course +need to make sure that the array does stay alive while we're doing the ccall. +To understand how this is done, first recall the lowering of the above code: +``` + return $(Expr(:foreigncall, :(:foo), Void, svec(Ptr{Float64}), :($(Expr(:foreigncall, :(:jl_array_ptr), Ptr{Float64}, svec(Any), :(A), 0))), :(A))) +``` +The last `:(A)`, is an extra argument list inserted during lowering that informs +the code generator which julia level values need to be kept alive for the +duration of this ccall. We then take this information and represent it in an +"operand bundle" at the IR level. An operand bundle is essentially a fake use +that is attached to the call site. At the IR level, this looks like so: +``` + call void inttoptr (i64 ... to void (double*)*)(double* %5) [ "jl_roots"(%jl_value_t addrspace(10)* %A) ] +``` +The GC root placement pass will treat the jl_roots operand bundle as if it were +a regular operand. However, as a final step, after the gc roots are inserted, +it will drop the operand bundle to avoid confusing instruction selection. + +### Supporting pointer_from_objref +`pointer_from_objref` is special because it requires the user to take explicit +control of GC rooting. By our above invariants, this function is illegal, +because it performs an addressspace cast from 10 to 0. However, it can be useful, +in certain situations, so we provide a special intrinsic: +``` +declared %jl_value_t *julia.pointer_from_objref(%jl_value_t addrspace(10)*) +``` +which is lowered to the corresponding address space cast after gc root lowering. +Do note however that by using this intrinsic, the caller assumes all responsibility +for making sure that the value in question is rooted. Further this intrinsic is +not considered a use, so the GC root placement pass will not provide a GC root +for the function. As a result, the external rooting must be arranged while the +value is still tracked by the system. I.e. it is not valid to attempt use the +result of this operation to establish a global root - the optimizer may have +already dropped the value. diff --git a/src/Makefile b/src/Makefile index ce5e8b63a5679..c91d797778967 100644 --- a/src/Makefile +++ b/src/Makefile @@ -53,7 +53,7 @@ endif LLVMLINK := ifeq ($(JULIACODEGEN),LLVM) -SRCS += codegen jitlayers disasm debuginfo llvm-simdloop llvm-ptls llvm-gcroot llvm-lower-handlers cgmemmgr +SRCS += codegen jitlayers disasm debuginfo llvm-simdloop llvm-ptls llvm-late-gc-lowering llvm-lower-handlers llvm-gc-invariant-verifier cgmemmgr FLAGS += -I$(shell $(LLVM_CONFIG_HOST) --includedir) LLVM_LIBS := all ifeq ($(USE_POLLY),1) diff --git a/src/ccall.cpp b/src/ccall.cpp index c50f0bb20e8e8..1fb38faf1dadc 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -459,7 +459,9 @@ static Value *llvm_type_rewrite( // sizes. Value *from; Value *to; -#if JL_LLVM_VERSION >= 30600 +#if JL_LLVM_VERSION >= 40000 + const DataLayout &DL = jl_data_layout; +#elif JL_LLVM_VERSION >= 30600 const DataLayout &DL = jl_ExecutionEngine->getDataLayout(); #else const DataLayout &DL = *jl_ExecutionEngine->getDataLayout(); @@ -485,8 +487,8 @@ static Value *runtime_apply_type(jl_value_t *ty, jl_unionall_t *unionall, jl_cod args[0] = literal_pointer_val(ty); args[1] = literal_pointer_val((jl_value_t*)ctx->linfo->def.method->sig); args[2] = builder.CreateInBoundsGEP( - LLVM37_param(T_pjlvalue) - emit_bitcast(ctx->spvals_ptr, T_ppjlvalue), + LLVM37_param(T_prjlvalue) + emit_bitcast(decay_derived(ctx->spvals_ptr), T_pprjlvalue), ConstantInt::get(T_size, sizeof(jl_svec_t) / sizeof(jl_value_t*))); return builder.CreateCall(prepare_call(jlapplytype_func), makeArrayRef(args)); } @@ -639,7 +641,7 @@ static Value *julia_to_native(Type *to, bool toboxed, jl_value_t *jlto, jl_union // We're passing Any if (toboxed) { assert(!byRef); // don't expect any ABI to pass pointers by pointer - return boxed(jvinfo, ctx); + return maybe_decay_untracked(boxed(jvinfo, ctx)); } assert(jl_is_datatype(jlto) && julia_struct_has_layout((jl_datatype_t*)jlto, jlto_env)); @@ -1208,7 +1210,9 @@ static jl_cgval_t mark_or_box_ccall_result(Value *result, bool isboxed, jl_value Value *runtime_dt = runtime_apply_type(rt, unionall, ctx); // TODO: is this leaf check actually necessary, or is it structurally guaranteed? emit_leafcheck(runtime_dt, "ccall: return type must be a leaf DataType", ctx); -#if JL_LLVM_VERSION >= 30600 +#if JL_LLVM_VERSION >= 40000 + const DataLayout &DL = jl_data_layout; +#elif JL_LLVM_VERSION >= 30600 const DataLayout &DL = jl_ExecutionEngine->getDataLayout(); #else const DataLayout &DL = *jl_ExecutionEngine->getDataLayout(); @@ -1306,7 +1310,7 @@ std::string generate_func_sig() #else paramattrs.push_back(AttributeSet::get(jl_LLVMContext, 1, retattrs)); #endif - fargt_sig.push_back(PointerType::get(lrt, 0)); + fargt_sig.push_back(PointerType::get(lrt, AddressSpace::Derived)); sret = 1; prt = lrt; } @@ -1349,6 +1353,8 @@ std::string generate_func_sig() } t = julia_struct_to_llvm(tti, unionall_env, &isboxed); + if (isboxed) + t = T_prjlvalue; if (t == NULL || t == T_void) { std::stringstream msg; msg << "ccall: the type of argument "; @@ -1369,7 +1375,7 @@ std::string generate_func_sig() pat = t; } else if (byRef) { - pat = PointerType::get(t, 0); + pat = PointerType::get(t, AddressSpace::Derived); } else { pat = abi->preferred_llvm_type((jl_datatype_t*)tti, false); @@ -1459,6 +1465,8 @@ static const std::string verify_ccall_sig(size_t nargs, jl_value_t *&rt, jl_valu lrt = julia_struct_to_llvm(rt, unionall_env, &retboxed); if (lrt == NULL) return "ccall: return type doesn't correspond to a C type"; + else if (retboxed) + lrt = T_prjlvalue; // is return type fully statically known? if (unionall_env == NULL) { @@ -1646,8 +1654,16 @@ static jl_cgval_t emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) ary = emit_unbox(largty, emit_expr(argi, ctx), tti); } JL_GC_POP(); - return mark_or_box_ccall_result(emit_bitcast(ary, lrt), - retboxed, rt, unionall, static_rt, ctx); + if (!retboxed) { + return mark_or_box_ccall_result( + emit_bitcast(emit_pointer_from_objref( + emit_bitcast(ary, T_prjlvalue)), lrt), + retboxed, rt, unionall, static_rt, ctx); + } else { + return mark_or_box_ccall_result(maybe_decay_untracked( + emit_bitcast(ary, lrt)), + retboxed, rt, unionall, static_rt, ctx); + } } else if (is_libjulia_func(jl_cpu_pause)) { // Keep in sync with the julia_threads.h version @@ -1971,6 +1987,7 @@ jl_cgval_t function_sig_t::emit_a_ccall( ai + 1, ctx, &needStackRestore); bool issigned = jl_signed_type && jl_subtype(jargty, (jl_value_t*)jl_signed_type); if (byRef) { + v = decay_derived(v); // julia_to_native should already have done the alloca and store assert(v->getType() == pargty); } @@ -1986,6 +2003,13 @@ jl_cgval_t function_sig_t::emit_a_ccall( } v = julia_to_address(largty, jargty_in_env, unionall_env, arg, ai + 1, ctx, &needStackRestore); + if (isa(v)) { + JL_GC_POP(); + return jl_cgval_t(); + } + // A bit of a hack, but we're trying to get rid of this feature + // anyway. + v = emit_bitcast(emit_pointer_from_objref(v), pargty); assert((!toboxed && !byRef) || isa(v)); } @@ -2013,7 +2037,7 @@ jl_cgval_t function_sig_t::emit_a_ccall( literal_pointer_val((jl_value_t*)rt)); sretboxed = true; } - argvals[0] = emit_bitcast(result, fargt_sig.at(0)); + argvals[0] = emit_bitcast(decay_derived(result), fargt_sig.at(0)); } Instruction *stacksave = NULL; @@ -2101,9 +2125,11 @@ jl_cgval_t function_sig_t::emit_a_ccall( // Mark GC use before **and** after the ccall to make sure the arguments // are alive during the ccall even if the function called is `noreturn`. mark_gc_uses(gc_uses); + OperandBundleDef OpBundle("jl_roots", gc_uses); // the actual call Value *ret = builder.CreateCall(prepare_call(llvmf), - ArrayRef(&argvals[0], nargs + sret)); + ArrayRef(&argvals[0], nargs + sret), + ArrayRef(&OpBundle, gc_uses.empty() ? 0 : 1)); ((CallInst*)ret)->setAttributes(attributes); if (cc != CallingConv::C) @@ -2145,6 +2171,9 @@ jl_cgval_t function_sig_t::emit_a_ccall( } else { Type *jlrt = julia_type_to_llvm(rt, &jlretboxed); // compute the real "julian" return type and compute whether it is boxed + if (jlretboxed) { + jlrt = T_prjlvalue; + } if (type_is_ghost(jlrt)) { return ghostValue(rt); } @@ -2160,7 +2189,9 @@ jl_cgval_t function_sig_t::emit_a_ccall( Value *strct = emit_allocobj(ctx, rtsz, runtime_bt); int boxalign = jl_gc_alignment(rtsz); #ifndef JL_NDEBUG -#if JL_LLVM_VERSION >= 30600 +#if JL_LLVM_VERSION >= 40000 + const DataLayout &DL = jl_data_layout; +#elif JL_LLVM_VERSION >= 30600 const DataLayout &DL = jl_ExecutionEngine->getDataLayout(); #else const DataLayout &DL = *jl_ExecutionEngine->getDataLayout(); diff --git a/src/cgutils.cpp b/src/cgutils.cpp index a14dff0ecfe91..a317c76bea4c8 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -25,6 +25,40 @@ static Value *prepare_call(Value *Callee) return prepare_call(builder, Callee); } +static Value *maybe_decay_untracked(Value *V) +{ + if (V->getType() == T_pjlvalue) + return builder.CreateAddrSpaceCast(V, T_prjlvalue); + else if (V->getType() == T_ppjlvalue) + return builder.CreateBitCast(V, T_pprjlvalue); + return V; +} + +static Constant *maybe_decay_untracked(Constant *C) +{ + if (C->getType() == T_pjlvalue) + return ConstantExpr::getAddrSpaceCast(C, T_prjlvalue); + else if (C->getType() == T_ppjlvalue) + return ConstantExpr::getBitCast(C, T_pprjlvalue); + return C; +} + +static Value *decay_derived(Value *V) +{ + Type *T = V->getType(); + if (cast(T)->getAddressSpace() == AddressSpace::Derived) + return V; + // Once llvm deletes pointer element types, we won't need it here any more either. + Type *NewT = PointerType::get(cast(T)->getElementType(), AddressSpace::Derived); + return builder.CreateAddrSpaceCast(V, NewT); +} + +static Value *mark_callee_rooted(Value *V) +{ + assert(V->getType() == T_pjlvalue || V->getType() == T_prjlvalue); + return builder.CreateAddrSpaceCast(V, + PointerType::get(T_jlvalue, AddressSpace::CalleeRooted)); +} // --- language feature checks --- @@ -215,6 +249,22 @@ static DIType julia_type_to_di(jl_value_t *jt, DIBuilder *dbuilder, bool isboxed return jl_pvalue_dillvmt; } +static Value *emit_pointer_from_objref(Value *V) +{ + unsigned AS = cast(V->getType())->getAddressSpace(); + if (AS != AddressSpace::Tracked && AS != AddressSpace::Derived) + return builder.CreateBitCast(V, T_pjlvalue); + V = builder.CreateBitCast(decay_derived(V), + PointerType::get(T_jlvalue, AddressSpace::Derived)); + CallInst *Call = builder.CreateCall(prepare_call(pointer_from_objref_func), V); +#if JL_LLVM_VERSION >= 50000 + Call->addAttribute(AttributeList::FunctionIndex, Attribute::ReadNone); +#else + Call->addAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone); +#endif + return Call; +} + // --- emitting pointers directly into code --- static Constant *literal_static_pointer_val(const void *p, Type *t) @@ -223,9 +273,9 @@ static Constant *literal_static_pointer_val(const void *p, Type *t) // the generated code will only be valid during the current session, // and thus, this should typically be avoided in new API's #if defined(_P64) - return ConstantExpr::getIntToPtr(ConstantInt::get(T_int64, (uint64_t)p), t); + return ConstantExpr::getPointerBitCastOrAddrSpaceCast(ConstantExpr::getIntToPtr(ConstantInt::get(T_int64, (uint64_t)p), T_pjlvalue), t); #else - return ConstantExpr::getIntToPtr(ConstantInt::get(T_int32, (uint32_t)p), t); + return ConstantExpr::getPointerBitCastOrAddrSpaceCast(ConstantExpr::getIntToPtr(ConstantInt::get(T_int32, (uint32_t)p), T_pjlvalue), t); #endif } @@ -284,31 +334,31 @@ static Value *literal_pointer_val_slot(jl_value_t *p) } if (GlobalVariable *gv = julia_const_gv(p)) { // if this is a known object, use the existing GlobalValue - return prepare_global(gv, jl_builderModule); + return maybe_decay_untracked(prepare_global(gv, jl_builderModule)); } if (jl_is_datatype(p)) { jl_datatype_t *addr = (jl_datatype_t*)p; // DataTypes are prefixed with a + - return julia_pgv("+", addr->name->name, addr->name->module, p); + return maybe_decay_untracked(julia_pgv("+", addr->name->name, addr->name->module, p)); } if (jl_is_method(p)) { jl_method_t *m = (jl_method_t*)p; // functions are prefixed with a - - return julia_pgv("-", m->name, m->module, p); + return maybe_decay_untracked(julia_pgv("-", m->name, m->module, p)); } if (jl_is_method_instance(p)) { jl_method_instance_t *linfo = (jl_method_instance_t*)p; // Type-inferred functions are also prefixed with a - if (jl_is_method(linfo->def.method)) - return julia_pgv("-", linfo->def.method->name, linfo->def.method->module, p); + return maybe_decay_untracked(julia_pgv("-", linfo->def.method->name, linfo->def.method->module, p)); } if (jl_is_symbol(p)) { jl_sym_t *addr = (jl_sym_t*)p; // Symbols are prefixed with jl_sym# - return julia_pgv("jl_sym#", addr, NULL, p); + return maybe_decay_untracked(julia_pgv("jl_sym#", addr, NULL, p)); } // something else gets just a generic name - return julia_pgv("jl_global#", p); + return maybe_decay_untracked(julia_pgv("jl_global#", p)); } static Value *literal_pointer_val(jl_value_t *p) @@ -316,7 +366,7 @@ static Value *literal_pointer_val(jl_value_t *p) if (p == NULL) return V_null; if (!imaging_mode) - return literal_static_pointer_val(p, T_pjlvalue); + return literal_static_pointer_val(p, T_prjlvalue); Value *pgv = literal_pointer_val_slot(p); return tbaa_decorate(tbaa_const, builder.CreateLoad(pgv)); } @@ -364,9 +414,9 @@ static Value *julia_binding_gv(jl_binding_t *b) bv = emit_bitcast( tbaa_decorate(tbaa_const, builder.CreateLoad(julia_pgv("*", b->name, b->owner, b))), - T_ppjlvalue); + T_pprjlvalue); else - bv = literal_static_pointer_val(b, T_ppjlvalue); + bv = literal_static_pointer_val(b, T_pprjlvalue); return julia_binding_gv(bv); } @@ -517,7 +567,9 @@ static Type *julia_struct_to_llvm(jl_value_t *jt, jl_unionall_t *ua, bool *isbox // If LLVM and Julia disagree about alignment, much trouble ensues, so check it! if (jst->layout) { const DataLayout &DL = -#if JL_LLVM_VERSION >= 30600 +#if JL_LLVM_VERSION >= 40000 + jl_data_layout; +#elif JL_LLVM_VERSION >= 30600 jl_ExecutionEngine->getDataLayout(); #else *jl_ExecutionEngine->getDataLayout(); @@ -618,15 +670,15 @@ static unsigned get_box_tindex(jl_datatype_t *jt, jl_value_t *ut) // --- generating various field accessors --- -static Value *emit_nthptr_addr(Value *v, ssize_t n) +static Value *emit_nthptr_addr(Value *v, ssize_t n, bool gctracked = true) { - return builder.CreateGEP(emit_bitcast(v, T_ppjlvalue), + return builder.CreateGEP(emit_bitcast(gctracked ? decay_derived(v) : v, T_pprjlvalue), ConstantInt::get(T_size, n)); } -static Value *emit_nthptr_addr(Value *v, Value *idx) +static Value *emit_nthptr_addr(Value *v, Value *idx, bool gctracked = true) { - return builder.CreateGEP(emit_bitcast(v, T_ppjlvalue), idx); + return builder.CreateGEP(emit_bitcast(gctracked ? decay_derived(v) : v, T_pprjlvalue), idx); } static Value *emit_nthptr(Value *v, ssize_t n, MDNode *tbaa) @@ -636,17 +688,17 @@ static Value *emit_nthptr(Value *v, ssize_t n, MDNode *tbaa) return tbaa_decorate(tbaa,builder.CreateLoad(vptr, false)); } -static Value *emit_nthptr_recast(Value *v, Value *idx, MDNode *tbaa, Type *ptype) +static Value *emit_nthptr_recast(Value *v, Value *idx, MDNode *tbaa, Type *ptype, bool gctracked = true) { // p = (jl_value_t**)v; *(ptype)&p[n] - Value *vptr = emit_nthptr_addr(v, idx); + Value *vptr = emit_nthptr_addr(v, idx, gctracked); return tbaa_decorate(tbaa,builder.CreateLoad(emit_bitcast(vptr,ptype), false)); } -static Value *emit_nthptr_recast(Value *v, ssize_t n, MDNode *tbaa, Type *ptype) +static Value *emit_nthptr_recast(Value *v, ssize_t n, MDNode *tbaa, Type *ptype, bool gctracked = true) { // p = (jl_value_t**)v; *(ptype)&p[n] - Value *vptr = emit_nthptr_addr(v, n); + Value *vptr = emit_nthptr_addr(v, n, gctracked); return tbaa_decorate(tbaa,builder.CreateLoad(emit_bitcast(vptr,ptype), false)); } @@ -672,8 +724,13 @@ static Value *emit_typeof(Value *tt) { assert(tt != NULL && !isa(tt) && "expected a conditionally boxed value"); // given p, a jl_value_t*, compute its type tag - tt = tbaa_decorate(tbaa_tag, builder.CreateLoad(emit_typeptr_addr(tt))); - return mask_gc_bits(tt); + // The raw address is not GC-safe to load from as it may have mask bits set. + // Note that this gives the optimizer license to not root this value. That + // is fine however, since leaf types are not GCed at the moment. Should + // that ever change, this may have to go through a special intrinsic. + Value *addr = emit_bitcast(emit_typeptr_addr(tt), T_ppjlvalue); + tt = tbaa_decorate(tbaa_tag, builder.CreateLoad(addr)); + return maybe_decay_untracked(mask_gc_bits(tt)); } static jl_cgval_t emit_typeof(const jl_cgval_t &p, jl_codectx_t *ctx) @@ -695,22 +752,27 @@ static jl_cgval_t emit_typeof(const jl_cgval_t &p, jl_codectx_t *ctx) counter); if (allunboxed) pdatatype = Constant::getNullValue(T_ppjlvalue); - else - pdatatype = emit_typeptr_addr(p.V); + else { + // See note above in emit_typeof(Value*), we can't tell the system + // about this until we've cleared the GC bits. + pdatatype = emit_bitcast(emit_typeptr_addr(builder.CreateLoad(p.gcroot)), T_ppjlvalue); + } counter = 0; for_each_uniontype_small( [&](unsigned idx, jl_datatype_t *jt) { Value *cmp = builder.CreateICmpEQ(tindex, ConstantInt::get(T_int8, idx)); - pdatatype = builder.CreateSelect(cmp, literal_pointer_val_slot((jl_value_t*)jt), pdatatype); + pdatatype = builder.CreateSelect(cmp, + decay_derived(emit_bitcast(literal_pointer_val_slot((jl_value_t*)jt), T_ppjlvalue)), + decay_derived(pdatatype)); }, p.typ, counter); Value *datatype; if (allunboxed) { - datatype = tbaa_decorate(tbaa_const, builder.CreateLoad(pdatatype)); + datatype = tbaa_decorate(tbaa_const, builder.CreateLoad(maybe_decay_untracked(pdatatype))); } else { - datatype = mask_gc_bits(tbaa_decorate(tbaa_tag, builder.CreateLoad(pdatatype))); + datatype = maybe_decay_untracked(mask_gc_bits(tbaa_decorate(tbaa_tag, builder.CreateLoad(pdatatype)))); } return mark_julia_type(datatype, true, jl_datatype_type, ctx, /*needsroot*/false); } @@ -732,7 +794,7 @@ static Value *emit_datatype_types(Value *dt) { return tbaa_decorate(tbaa_const, builder. CreateLoad(emit_bitcast(builder. - CreateGEP(emit_bitcast(dt, T_pint8), + CreateGEP(emit_bitcast(decay_derived(dt), T_pint8), ConstantInt::get(T_size, offsetof(jl_datatype_t, types))), T_ppjlvalue))); } @@ -743,7 +805,7 @@ static Value *emit_datatype_nfields(Value *dt) tbaa_decorate(tbaa_const, builder.CreateLoad( emit_bitcast( builder.CreateGEP( - emit_bitcast(dt, T_pint8), + emit_bitcast(decay_derived(dt), T_pint8), ConstantInt::get(T_size, offsetof(jl_datatype_t, types))), T_pint32->getPointerTo()))))); #ifdef _P64 @@ -756,7 +818,7 @@ static Value *emit_datatype_size(Value *dt) { Value *size = tbaa_decorate(tbaa_const, builder. CreateLoad(emit_bitcast(builder. - CreateGEP(emit_bitcast(dt, T_pint8), + CreateGEP(emit_bitcast(decay_derived(dt), T_pint8), ConstantInt::get(T_size, offsetof(jl_datatype_t, size))), T_pint32))); return size; @@ -814,7 +876,7 @@ static Value *emit_sizeof(const jl_cgval_t &p, jl_codectx_t *ctx) static Value *emit_datatype_mutabl(Value *dt) { Value *mutabl = tbaa_decorate(tbaa_const, builder. - CreateLoad(builder.CreateGEP(emit_bitcast(dt, T_pint8), + CreateLoad(builder.CreateGEP(emit_bitcast(decay_derived(dt), T_pint8), ConstantInt::get(T_size, offsetof(jl_datatype_t, mutabl))))); return builder.CreateTrunc(mutabl, T_int1); } @@ -822,7 +884,7 @@ static Value *emit_datatype_mutabl(Value *dt) static Value *emit_datatype_abstract(Value *dt) { Value *abstract = tbaa_decorate(tbaa_const, builder. - CreateLoad(builder.CreateGEP(emit_bitcast(dt, T_pint8), + CreateLoad(builder.CreateGEP(emit_bitcast(decay_derived(dt), T_pint8), ConstantInt::get(T_size, offsetof(jl_datatype_t, abstract))))); return builder.CreateTrunc(abstract, T_int1); } @@ -885,9 +947,9 @@ static void raise_exception(Value *exc, jl_codectx_t *ctx, } else { JL_FEAT_REQUIRE(ctx, runtime); #if JL_LLVM_VERSION >= 30700 - builder.CreateCall(prepare_call(jlthrow_func), { exc }); + builder.CreateCall(prepare_call(jlthrow_func), { mark_callee_rooted(exc) }); #else - builder.CreateCall(prepare_call(jlthrow_func), exc); + builder.CreateCall(prepare_call(jlthrow_func), mark_callee_rooted(exc)); #endif } builder.CreateUnreachable(); @@ -977,11 +1039,11 @@ static void emit_type_error(const jl_cgval_t &x, Value *type, const std::string #if JL_LLVM_VERSION >= 30700 builder.CreateCall(prepare_call(jltypeerror_func), { fname_val, msg_val, - type, boxed(x, ctx, false)}); // x is rooted by jl_type_error_rt + type, mark_callee_rooted(boxed(x, ctx, false))}); #else builder.CreateCall4(prepare_call(jltypeerror_func), fname_val, msg_val, - type, boxed(x, ctx, false)); // x is rooted by jl_type_error_rt + type, mark_callee_rooted(boxed(x, ctx, false))); #endif } @@ -1006,20 +1068,21 @@ static std::pair emit_isa(const jl_cgval_t &x, jl_value_t *type, c // intersection with Type needs to be handled specially if (jl_has_intersect_type_not_kind(type)) { - Value *vx = boxed(x, ctx); + Value *vx = maybe_decay_untracked(boxed(x, ctx)); + Value *vtyp = literal_pointer_val(type); if (msg && *msg == "typeassert") { #if JL_LLVM_VERSION >= 30700 - builder.CreateCall(prepare_call(jltypeassert_func), { vx, literal_pointer_val(type) }); + builder.CreateCall(prepare_call(jltypeassert_func), { vx, vtyp }); #else - builder.CreateCall2(prepare_call(jltypeassert_func), vx, literal_pointer_val(type)); + builder.CreateCall2(prepare_call(jltypeassert_func), vx, vtyp); #endif return std::make_pair(ConstantInt::get(T_int1, 1), true); } return std::make_pair(builder.CreateICmpNE( #if JL_LLVM_VERSION >= 30700 - builder.CreateCall(prepare_call(jlisa_func), { vx, literal_pointer_val(type) }), + builder.CreateCall(prepare_call(jlisa_func), { vx, vtyp }), #else - builder.CreateCall2(prepare_call(jlisa_func), vx, literal_pointer_val(type)), + builder.CreateCall2(prepare_call(jlisa_func), vx, vtyp), #endif ConstantInt::get(T_int32, 0)), false); } @@ -1040,7 +1103,8 @@ static std::pair emit_isa(const jl_cgval_t &x, jl_value_t *type, c BasicBlock *postBB = BasicBlock::Create(jl_LLVMContext, "post_isa", ctx->f); builder.CreateCondBr(isboxed, isaBB, postBB); builder.SetInsertPoint(isaBB); - Value *istype_boxed = builder.CreateICmpEQ(emit_typeof(x.V), literal_pointer_val(type)); + Value *istype_boxed = builder.CreateICmpEQ(emit_typeof(x.V), + maybe_decay_untracked(literal_pointer_val(type))); builder.CreateBr(postBB); builder.SetInsertPoint(postBB); PHINode *istype = builder.CreatePHI(T_int1, 2); @@ -1049,15 +1113,20 @@ static std::pair emit_isa(const jl_cgval_t &x, jl_value_t *type, c return std::make_pair(istype, false); } } - return std::make_pair(builder.CreateICmpEQ(emit_typeof_boxed(x, ctx), literal_pointer_val(type)), false); + return std::make_pair(builder.CreateICmpEQ(emit_typeof_boxed(x, ctx), + maybe_decay_untracked(literal_pointer_val(type))), false); } // everything else can be handled via subtype tests Value *vxt = emit_typeof_boxed(x, ctx); return std::make_pair(builder.CreateICmpNE( #if JL_LLVM_VERSION >= 30700 - builder.CreateCall(prepare_call(jlsubtype_func), { vxt, literal_pointer_val(type) }), + builder.CreateCall(prepare_call(jlsubtype_func), + { vxt, + literal_pointer_val(type) }), #else - builder.CreateCall2(prepare_call(jlsubtype_func), vxt, literal_pointer_val(type)), + builder.CreateCall2(prepare_call(jlsubtype_func), + vxt, + literal_pointer_val(type)), #endif ConstantInt::get(T_int32, 0)), false); } @@ -1087,7 +1156,7 @@ static void emit_leafcheck(Value *typ, const std::string &msg, jl_codectx_t *ctx assert(typ->getType() == T_pjlvalue); emit_typecheck(mark_julia_type(typ, true, jl_any_type, ctx, false), (jl_value_t*)jl_datatype_type, msg, ctx); Value *isleaf; - isleaf = builder.CreateConstInBoundsGEP1_32(LLVM37_param(T_int8) emit_bitcast(typ, T_pint8), offsetof(jl_datatype_t, isleaftype)); + isleaf = builder.CreateConstInBoundsGEP1_32(LLVM37_param(T_int8) emit_bitcast(decay_derived(typ), T_pint8), offsetof(jl_datatype_t, isleaftype)); isleaf = builder.CreateLoad(isleaf, tbaa_const); isleaf = builder.CreateTrunc(isleaf, T_int1); error_unless(isleaf, msg, ctx); @@ -1123,9 +1192,9 @@ static Value *emit_bounds_check(const jl_cgval_t &ainfo, jl_value_t *ty, Value * } else if (ainfo.isboxed) { // jl_datatype_t or boxed jl_value_t #if JL_LLVM_VERSION >= 30700 - builder.CreateCall(prepare_call(jlboundserror_func), { boxed(ainfo, ctx), i }); + builder.CreateCall(prepare_call(jlboundserror_func), { mark_callee_rooted(boxed(ainfo, ctx)), i }); #else - builder.CreateCall2(prepare_call(jlboundserror_func), boxed(ainfo, ctx), i); + builder.CreateCall2(prepare_call(jlboundserror_func), mark_callee_rooted(boxed(ainfo, ctx)), i); #endif } else { // unboxed jl_value_t* @@ -1141,12 +1210,12 @@ static Value *emit_bounds_check(const jl_cgval_t &ainfo, jl_value_t *ty, Value * } #if JL_LLVM_VERSION >= 30700 builder.CreateCall(prepare_call(jluboundserror_func), { - builder.CreatePointerCast(a, T_pint8), + emit_bitcast(decay_derived(a), T_pint8), literal_pointer_val(ty), i }); #else builder.CreateCall3(prepare_call(jluboundserror_func), - builder.CreatePointerCast(a, T_pint8), + emit_bitcast(decay_derived(a), T_pint8), literal_pointer_val(ty), i); #endif @@ -1187,9 +1256,11 @@ static jl_cgval_t typed_load(Value *ptr, Value *idx_0based, jl_value_t *jltype, if (type_is_ghost(elty)) return ghostValue(jltype); Value *data; + if (isboxed) + elty = T_prjlvalue; // TODO: preserving_pointercast? if (ptr->getType()->getContainedType(0) != elty) - data = builder.CreatePointerCast(ptr, PointerType::get(elty, 0)); + data = emit_bitcast(ptr, PointerType::get(elty, 0)); else data = ptr; if (idx_0based) @@ -1231,13 +1302,17 @@ static void typed_store(Value *ptr, Value *idx_0based, const jl_cgval_t &rhs, r = emit_unbox(elty, rhs, jltype); } else { - r = boxed(rhs, ctx, root_box); + r = maybe_decay_untracked(boxed(rhs, ctx, root_box)); if (parent != NULL) emit_write_barrier(ctx, parent, r); } Value *data; - if (ptr->getType()->getContainedType(0) != elty) - data = emit_bitcast(ptr, PointerType::get(elty, 0)); - else + if (ptr->getType()->getContainedType(0) != elty) { + if (isboxed) { + data = emit_bitcast(ptr, T_pprjlvalue); + } else { + data = emit_bitcast(ptr, PointerType::get(elty, cast(ptr->getType())->getAddressSpace())); + } + } else data = ptr; Instruction *store = builder.CreateAlignedStore(r, builder.CreateGEP(data, idx_0based), isboxed ? alignment : julia_alignment(r, jltype, alignment)); @@ -1342,7 +1417,7 @@ static Value *data_pointer(const jl_cgval_t &x, jl_codectx_t *ctx, Type *astype } if (data->getType() != astype) data = emit_bitcast(data, astype); - return data; + return decay_derived(data); } static bool emit_getfield_unknownidx(jl_cgval_t *ret, const jl_cgval_t &strct, @@ -1363,7 +1438,8 @@ static bool emit_getfield_unknownidx(jl_cgval_t *ret, const jl_cgval_t &strct, Value *fld = tbaa_decorate(strct.tbaa, maybe_mark_load_dereferenceable( builder.CreateLoad( - builder.CreateGEP(data_pointer(strct, ctx), idx)), + builder.CreateBitCast(builder.CreateGEP(decay_derived(data_pointer(strct, ctx)), idx), + PointerType::get(T_prjlvalue, AddressSpace::Derived))), maybe_null, minimum_field_size)); if (maybe_null) null_pointer_check(fld, ctx); @@ -1378,7 +1454,7 @@ static bool emit_getfield_unknownidx(jl_cgval_t *ret, const jl_cgval_t &strct, if (!stt->mutabl) { // just compute the pointer and let user load it when necessary Type *fty = julia_type_to_llvm(jt); - Value *addr = builder.CreateGEP(builder.CreatePointerCast(ptr, PointerType::get(fty,0)), idx); + Value *addr = builder.CreateGEP(emit_bitcast(decay_derived(ptr), PointerType::get(fty,0)), idx); *ret = mark_julia_slot(addr, jt, NULL, strct.tbaa); ret->gcroot = strct.gcroot; ret->isimmutable = strct.isimmutable; @@ -1439,7 +1515,7 @@ static jl_cgval_t emit_getfield_knownidx(const jl_cgval_t &strct, unsigned idx, bool isboxed; Type *lt = julia_type_to_llvm((jl_value_t*)jt, &isboxed); if (isboxed) { - Value *ptr = data_pointer(strct, ctx, T_pint8); + Value *ptr = decay_derived(data_pointer(strct, ctx, T_pint8)); Value *llvm_idx = ConstantInt::get(T_size, jl_field_offset(jt, idx)); addr = builder.CreateGEP(ptr, llvm_idx); } @@ -1463,7 +1539,7 @@ static jl_cgval_t emit_getfield_knownidx(const jl_cgval_t &strct, unsigned idx, if (jl_field_isptr(jt, idx)) { bool maybe_null = idx >= (unsigned)jt->ninitialized; Instruction *Load = maybe_mark_load_dereferenceable( - builder.CreateLoad(emit_bitcast(addr, T_ppjlvalue)), + builder.CreateLoad(emit_bitcast(addr, T_pprjlvalue)), maybe_null, jl_field_type(jt, idx) ); Value *fldv = tbaa_decorate(strct.tbaa, Load); @@ -1529,11 +1605,15 @@ static void maybe_alloc_arrayvar(int s, jl_codectx_t *ctx) // passed to an external function (ideally only impure functions) jl_arrayvar_t av; int ndims = jl_unbox_long(jl_tparam1(jt)); - Type *elt = julia_type_to_llvm(jl_tparam0(jt)); + jl_value_t *jelt = jl_tparam0(jt); + bool isboxed = !jl_array_store_unboxed(jelt); + Type *elt = julia_type_to_llvm(jelt); if (type_is_ghost(elt)) return; + if (isboxed) + elt = T_prjlvalue; // CreateAlloca is OK here because maybe_alloc_arrayvar is only called in the prologue setup - av.dataptr = builder.CreateAlloca(PointerType::get(elt,0)); + av.dataptr = builder.CreateAlloca(PointerType::get(elt, 0)); av.len = builder.CreateAlloca(T_size); for (int i = 0; i < ndims - 1; i++) av.sizes.push_back(builder.CreateAlloca(T_size)); @@ -1578,7 +1658,7 @@ static Value *emit_arraylen_prim(const jl_cgval_t &tinfo, jl_codectx_t *ctx) #if JL_LLVM_VERSION >= 30700 nullptr, #endif - emit_bitcast(t,jl_parray_llvmt), + emit_bitcast(decay_derived(t), jl_parray_llvmt), 1); //index (not offset) of length field in jl_parray_llvmt MDNode *tbaa = arraytype_constshape(ty) ? tbaa_const : tbaa_arraylen; @@ -1611,26 +1691,30 @@ static Value *emit_arraylen(const jl_cgval_t &tinfo, jl_value_t *ex, jl_codectx_ return emit_arraylen_prim(tinfo, ctx); } -static Value *emit_arrayptr(const jl_cgval_t &tinfo, jl_codectx_t *ctx) +static Value *emit_arrayptr(const jl_cgval_t &tinfo, jl_codectx_t *ctx, bool isboxed = false) { Value *t = boxed(tinfo, ctx); Value *addr = builder.CreateStructGEP( #if JL_LLVM_VERSION >= 30700 nullptr, #endif - emit_bitcast(t,jl_parray_llvmt), + emit_bitcast(decay_derived(t), jl_parray_llvmt), 0); //index (not offset) of data field in jl_parray_llvmt MDNode *tbaa = arraytype_constshape(tinfo.typ) ? tbaa_const : tbaa_arrayptr; + if (isboxed) { + addr = builder.CreateBitCast(addr, + PointerType::get(T_pprjlvalue, cast(addr->getType())->getAddressSpace())); + } return tbaa_decorate(tbaa, builder.CreateLoad(addr, false)); } -static Value *emit_arrayptr(const jl_cgval_t &tinfo, jl_value_t *ex, jl_codectx_t *ctx) +static Value *emit_arrayptr(const jl_cgval_t &tinfo, jl_value_t *ex, jl_codectx_t *ctx, bool isboxed = false) { jl_arrayvar_t *av = arrayvar_for(ex, ctx); if (av!=NULL) return builder.CreateLoad(av->dataptr); - return emit_arrayptr(tinfo, ctx); + return emit_arrayptr(tinfo, ctx, isboxed); } static Value *emit_arraysize(const jl_cgval_t &tinfo, jl_value_t *ex, int dim, jl_codectx_t *ctx) @@ -1653,7 +1737,7 @@ static Value *emit_arrayflags(const jl_cgval_t &tinfo, jl_codectx_t *ctx) #if JL_LLVM_VERSION >= 30700 nullptr, #endif - emit_bitcast(t, jl_parray_llvmt), + emit_bitcast(decay_derived(t), jl_parray_llvmt), arrayflag_field); return tbaa_decorate(tbaa_arrayflags, builder.CreateLoad(addr)); } @@ -1765,9 +1849,11 @@ static Value *emit_array_nd_index(const jl_cgval_t &ainfo, jl_value_t *ex, ssize builder.CreateStore(idxs[k], builder.CreateGEP(tmp, ConstantInt::get(T_size, k))); } #if JL_LLVM_VERSION >= 30700 - builder.CreateCall(prepare_call(jlboundserrorv_func), { a, tmp, ConstantInt::get(T_size, nidxs) }); + builder.CreateCall(prepare_call(jlboundserrorv_func), + { mark_callee_rooted(a), tmp, ConstantInt::get(T_size, nidxs) }); #else - builder.CreateCall3(prepare_call(jlboundserrorv_func), a, tmp, ConstantInt::get(T_size, nidxs)); + builder.CreateCall3(prepare_call(jlboundserrorv_func), + mark_callee_rooted(a), tmp, ConstantInt::get(T_size, nidxs)); #endif builder.CreateUnreachable(); @@ -1964,14 +2050,14 @@ static Value *box_union(const jl_cgval_t &vinfo, jl_codectx_t *ctx, const SmallB // box_union_isboxed: // br post_box_union // post_box_union: - // box = phi [ box1, box_union_1 ], [ box2, box_union_2 ], [ vinfo, post_box_union ] + // box = phi [ box1, box_union_1 ], [ box2, box_union_2 ], [ vinfo, box_union_isboxed ] // ... Value *tindex = vinfo.TIndex; BasicBlock *defaultBB = BasicBlock::Create(jl_LLVMContext, "box_union_isboxed", ctx->f); SwitchInst *switchInst = builder.CreateSwitch(tindex, defaultBB); BasicBlock *postBB = BasicBlock::Create(jl_LLVMContext, "post_box_union", ctx->f); builder.SetInsertPoint(postBB); - PHINode *box_merge = builder.CreatePHI(T_pjlvalue, 2); + PHINode *box_merge = builder.CreatePHI(T_prjlvalue, 2); unsigned counter = 0; for_each_uniontype_small( [&](unsigned idx, jl_datatype_t *jt) { @@ -1993,7 +2079,7 @@ static Value *box_union(const jl_cgval_t &vinfo, jl_codectx_t *ctx, const SmallB init_bits_cgval(box, vinfo_r, jl_is_mutable(jt) ? tbaa_mutab : tbaa_immut, ctx); } } - box_merge->addIncoming(box, tempBB); + box_merge->addIncoming(maybe_decay_untracked(box), tempBB); builder.CreateBr(postBB); }, vinfo.typ, @@ -2002,10 +2088,10 @@ static Value *box_union(const jl_cgval_t &vinfo, jl_codectx_t *ctx, const SmallB if (skip.size() > 0 && skip[0]) { // skip[0] specifies where to return NULL or the original pointer // if the value was not handled above - box_merge->addIncoming(V_null, defaultBB); + box_merge->addIncoming(maybe_decay_untracked(V_null), defaultBB); builder.CreateBr(postBB); } - else if (vinfo.V == NULL || isa(vinfo.V)) { + else if ((vinfo.V == NULL || isa(vinfo.V)) && !vinfo.gcroot) { Function *trap_func = Intrinsic::getDeclaration( ctx->f->getParent(), Intrinsic::trap); @@ -2017,7 +2103,9 @@ static Value *box_union(const jl_cgval_t &vinfo, jl_codectx_t *ctx, const SmallB // if this is a derived pointer, make sure the root usage itself is also visible to the delete-root pass mark_gc_use(vinfo); } - box_merge->addIncoming(emit_bitcast(vinfo.V, T_pjlvalue), defaultBB); + // We're guaranteed here that Load(.gcroot) == .V, because we have determined + // that this union is a boxed value, rather than an interior pointer of some sort + box_merge->addIncoming(builder.CreateLoad(vinfo.gcroot), defaultBB); builder.CreateBr(postBB); } builder.SetInsertPoint(postBB); @@ -2032,12 +2120,14 @@ static Value *boxed(const jl_cgval_t &vinfo, jl_codectx_t *ctx, bool gcrooted) jl_value_t *jt = vinfo.typ; if (jt == jl_bottom_type || jt == NULL) // We have an undef value on a (hopefully) dead branch - return UndefValue::get(T_pjlvalue); + return UndefValue::get(T_prjlvalue); if (vinfo.constant) return literal_pointer_val(vinfo.constant); if (vinfo.isboxed) { assert(vinfo.V && "Missing value for box."); - return vinfo.V; + // We're guaranteed here that Load(.gcroot) == .V, because we have determined + // that this value is a box, so if it has a gcroot, that's where the value is. + return vinfo.gcroot ? builder.CreateLoad(vinfo.gcroot) : vinfo.V; } Value *box; @@ -2150,8 +2240,8 @@ static void emit_cpointercheck(const jl_cgval_t &x, const std::string &msg, jl_c emit_typecheck(mark_julia_type(t, true, jl_any_type, ctx, false), (jl_value_t*)jl_datatype_type, msg, ctx); Value *istype = - builder.CreateICmpEQ(emit_datatype_name(t), - literal_pointer_val((jl_value_t*)jl_pointer_typename)); + builder.CreateICmpEQ(mark_callee_rooted(emit_datatype_name(t)), + mark_callee_rooted(literal_pointer_val((jl_value_t*)jl_pointer_typename))); BasicBlock *failBB = BasicBlock::Create(jl_LLVMContext,"fail",ctx->f); BasicBlock *passBB = BasicBlock::Create(jl_LLVMContext,"pass"); builder.CreateCondBr(istype, passBB, failBB); @@ -2186,7 +2276,7 @@ static Value *emit_allocobj(jl_codectx_t *ctx, size_t static_size, Value *jt) v = builder.CreateCall(prepare_call(jlalloc_pool_func), ArrayRef(args, 3)); } - tbaa_decorate(tbaa_tag, builder.CreateStore(jt, emit_typeptr_addr(v))); + tbaa_decorate(tbaa_tag, builder.CreateStore(maybe_decay_untracked(jt), emit_typeptr_addr(v))); return v; } @@ -2212,7 +2302,7 @@ static void emit_write_barrier(jl_codectx_t *ctx, Value *parent, Value *ptr) Value *ptr_not_marked = builder.CreateICmpEQ(ptr_mark_bit, ConstantInt::get(T_size, 0)); builder.CreateCondBr(ptr_not_marked, barrier_trigger, cont); builder.SetInsertPoint(barrier_trigger); - builder.CreateCall(prepare_call(queuerootfun), emit_bitcast(parent, T_pjlvalue)); + builder.CreateCall(prepare_call(queuerootfun), maybe_decay_untracked(emit_bitcast(parent, T_prjlvalue))); builder.CreateBr(cont); ctx->f->getBasicBlockList().push_back(cont); builder.SetInsertPoint(cont); @@ -2221,7 +2311,7 @@ static void emit_write_barrier(jl_codectx_t *ctx, Value *parent, Value *ptr) static void emit_checked_write_barrier(jl_codectx_t *ctx, Value *parent, Value *ptr) { BasicBlock *cont; - Value *not_null = builder.CreateICmpNE(ptr, V_null); + Value *not_null = builder.CreateICmpNE(mark_callee_rooted(ptr), mark_callee_rooted(V_null)); BasicBlock *if_not_null = BasicBlock::Create(jl_LLVMContext, "wb_not_null", ctx->f); cont = BasicBlock::Create(jl_LLVMContext, "cont"); builder.CreateCondBr(not_null, if_not_null, cont); @@ -2241,8 +2331,9 @@ static void emit_setfield(jl_datatype_t *sty, const jl_cgval_t &strct, size_t id ConstantInt::get(T_size, jl_field_offset(sty, idx0))); jl_value_t *jfty = jl_svecref(sty->types, idx0); if (jl_field_isptr(sty, idx0)) { - Value *r = boxed(rhs, ctx, false); // don't need a temporary gcroot since it'll be rooted by strct (but should ensure strct is rooted via mark_gc_use) - tbaa_decorate(strct.tbaa, builder.CreateStore(r, emit_bitcast(addr, T_ppjlvalue))); + Value *r = maybe_decay_untracked(boxed(rhs, ctx, false)); // don't need a temporary gcroot since it'll be rooted by strct (but should ensure strct is rooted via mark_gc_use) + tbaa_decorate(strct.tbaa, builder.CreateStore(r, + emit_bitcast(addr, T_pprjlvalue))); if (wb && strct.isboxed) emit_checked_write_barrier(ctx, boxed(strct, ctx), r); mark_gc_use(strct); } @@ -2331,11 +2422,11 @@ static jl_cgval_t emit_new_struct(jl_value_t *ty, size_t nargs, jl_value_t **arg for (size_t i = 0; i < nf; i++) { if (jl_field_isptr(sty, i)) { tbaa_decorate(strctinfo.tbaa, builder.CreateStore( - V_null, - builder.CreatePointerCast( - builder.CreateGEP(emit_bitcast(strct, T_pint8), + ConstantPointerNull::get(cast(T_prjlvalue)), + emit_bitcast( + builder.CreateGEP(emit_bitcast(decay_derived(strct), T_pint8), ConstantInt::get(T_size, jl_field_offset(sty, i))), - T_ppjlvalue))); + T_pprjlvalue))); } } bool need_wb = false; @@ -2374,7 +2465,7 @@ static jl_cgval_t emit_new_struct(jl_value_t *ty, size_t nargs, jl_value_t **arg static Value *emit_exc_in_transit(jl_codectx_t *ctx) { - Value *pexc_in_transit = emit_bitcast(ctx->ptlsStates, T_ppjlvalue); + Value *pexc_in_transit = emit_bitcast(ctx->ptlsStates, T_pprjlvalue); Constant *offset = ConstantInt::getSigned(T_int32, offsetof(jl_tls_states_t, exception_in_transit) / sizeof(void*)); return builder.CreateGEP(pexc_in_transit, ArrayRef(offset), "jl_exception_in_transit"); diff --git a/src/codegen.cpp b/src/codegen.cpp index 7277da7a078f3..083774bfef9fe 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -206,6 +206,7 @@ Module *shadow_output; #define jl_builderModule builder.GetInsertBlock()->getParent()->getParent() #if JL_LLVM_VERSION >= 30700 +static DataLayout jl_data_layout(""); // No DataLayout pass needed anymore. #elif JL_LLVM_VERSION >= 30500 static DataLayoutPass *jl_data_layout; @@ -214,8 +215,11 @@ static DataLayout *jl_data_layout; #endif // types +static Type *T_jlvalue; static Type *T_pjlvalue; +static Type *T_prjlvalue; static Type *T_ppjlvalue; +static Type *T_pprjlvalue; static Type *jl_parray_llvmt; static FunctionType *jl_func_sig; static FunctionType *jl_func_sig_sparams; @@ -419,6 +423,7 @@ static Function *gckill_func; static Function *jlcall_frame_func; static Function *gcroot_flush_func; static Function *except_enter_func; +static Function *pointer_from_objref_func; static std::vector two_pvalue_llvmt; static std::vector three_pvalue_llvmt; @@ -1011,7 +1016,7 @@ static jl_cgval_t convert_julia_type(const jl_cgval_t &v, jl_value_t *typ, jl_co union_box_dt = emit_typeof(v.V); } // didn't handle this item before, select its new union index - Value *cmp = builder.CreateICmpEQ(literal_pointer_val((jl_value_t*)jt), union_box_dt); + Value *cmp = builder.CreateICmpEQ(maybe_decay_untracked(literal_pointer_val((jl_value_t*)jt)), union_box_dt); union_box_tindex = builder.CreateSelect(cmp, ConstantInt::get(T_int8, 0x80 | idx), union_box_tindex); } }, @@ -1078,7 +1083,8 @@ static jl_cgval_t convert_julia_type(const jl_cgval_t &v, jl_value_t *typ, jl_co tbaa = tbaa_stack; isimmutable = true; } - slotv = builder.CreateSelect(isboxv, boxv, emit_bitcast(slotv, boxv->getType())); + slotv = builder.CreateSelect(isboxv, + decay_derived(boxv), emit_bitcast(slotv, boxv->getType())); jl_cgval_t newv = jl_cgval_t(slotv, froot, false, typ, new_tindex); newv.tbaa = tbaa; newv.isimmutable = isimmutable; @@ -1121,11 +1127,11 @@ static jl_cgval_t convert_julia_type(const jl_cgval_t &v, jl_value_t *typ, jl_co } if (makeboxed) { // convert to a simple isboxed value - Value *boxv = boxed(v, ctx); + Value *boxv = boxed(v, ctx, false); Value *froot = NULL; if (needsroot) { froot = emit_local_root(ctx); - builder.CreateStore(boxv, froot); + builder.CreateStore(maybe_decay_untracked(boxv), froot); } return jl_cgval_t(boxv, froot, true, typ, NULL); } @@ -1380,7 +1386,9 @@ static void jl_setup_module(Module *m, const jl_cgparams_t *params = &jl_default m->addModuleFlag(llvm::Module::Error, "Debug Info Version", llvm::DEBUG_METADATA_VERSION); #endif -#if JL_LLVM_VERSION >= 30700 +#if JL_LLVM_VERSION >= 40000 + m->setDataLayout(jl_data_layout); +#elif JL_LLVM_VERSION >= 30700 #ifdef USE_ORCJIT m->setDataLayout(jl_ExecutionEngine->getDataLayout()); #elif JL_LLVM_VERSION >= 30800 @@ -2369,13 +2377,14 @@ static void simple_escape_analysis(jl_value_t *expr, bool esc, jl_codectx_t *ctx // Emit a gc-root slot indicator static Value *emit_local_root(jl_codectx_t *ctx, jl_varinfo_t *vi) { - CallInst *newroot = CallInst::Create(prepare_call(gcroot_func), "", /*InsertBefore*/ctx->ptlsStates); + Instruction *newroot = new AllocaInst(T_prjlvalue, 0, "gcroot", /*InsertBefore*/ctx->ptlsStates); if (vi) { vi->boxroot->replaceAllUsesWith(newroot); newroot->takeName(vi->boxroot); vi->boxroot->eraseFromParent(); vi->boxroot = newroot; } + return newroot; } @@ -2393,23 +2402,47 @@ static void mark_gc_use(const jl_cgval_t &v) // turn an array of arguments into a single object suitable for passing to a jlcall static Value *make_jlcall(ArrayRef args, jl_codectx_t *ctx) { - // the temporary variables are after all local variables in the GC frame. - CallInst *largs = CallInst::Create(prepare_call(jlcall_frame_func), - ConstantInt::get(T_int32, args.size()), - "", - /*InsertBefore*/ctx->ptlsStates); + Value *largs = new AllocaInst(T_prjlvalue, +#if JL_LLVM_VERSION >= 50000 + 0, +#endif + ConstantInt::get(T_int32, args.size()), "jlcall", ctx->ptlsStates); int slot = 0; assert(args.size() > 0); + Value *lifetime_largs = largs; +#if JL_LLVM_VERSION < 50000 + lifetime_largs = builder.CreateBitCast(largs, T_pint8); + auto lifetime_start = Intrinsic::getDeclaration(jl_Module, Intrinsic::lifetime_start); +#else + auto lifetime_start = Intrinsic::getDeclaration(jl_Module, Intrinsic::lifetime_start, {T_pprjlvalue}); +#endif + builder.CreateCall(lifetime_start, { + ConstantInt::get(T_int64, args.size()*sizeof(jl_value_t*)), + lifetime_largs}); for (ArrayRef::iterator I = args.begin(), E = args.end(); I < E; ++I, ++slot) { Value *arg = boxed(**I, ctx, false); // mark_gc_use isn't needed since jlcall_frame_func can take ownership of this root GetElementPtrInst *newroot = GetElementPtrInst::Create(LLVM37_param(NULL) largs, ArrayRef(ConstantInt::get(T_int32, slot))); - newroot->insertAfter(ctx->ptlsStates); + builder.Insert(newroot); + arg = maybe_decay_untracked(arg); builder.CreateStore(arg, newroot); } return largs; } +static void end_lifetime(Value *args, size_t size, jl_codectx_t *ctx) { + Value *lifetime_args = args; +#if JL_LLVM_VERSION < 50000 + lifetime_args = builder.CreateBitCast(args, T_pint8); + auto lifetime_end = Intrinsic::getDeclaration(jl_Module, Intrinsic::lifetime_end); +#else + auto lifetime_end = Intrinsic::getDeclaration(jl_Module, Intrinsic::lifetime_end, {T_pprjlvalue}); +#endif + builder.CreateCall(lifetime_end, { + ConstantInt::get(T_int64, size*sizeof(jl_value_t*)), + lifetime_args}); +} + static void jl_add_method_root(jl_codectx_t *ctx, jl_value_t *val) { if (jl_is_leaf_type(val) || jl_is_bool(val) || jl_is_symbol(val) || @@ -2482,12 +2515,13 @@ static jl_cgval_t emit_getfield(jl_value_t *expr, jl_sym_t *name, jl_codectx_t * const jl_cgval_t* myargs_array[2] = {&arg1, &arg2}; Value *myargs = make_jlcall(makeArrayRef(myargs_array), ctx); #if JL_LLVM_VERSION >= 30700 - Value *result = builder.CreateCall(prepare_call(jlgetfield_func), {V_null, myargs, - ConstantInt::get(T_int32,2)}); + Value *result = builder.CreateCall(prepare_call(jlgetfield_func), + {maybe_decay_untracked(V_null), myargs, ConstantInt::get(T_int32,2)}); #else - Value *result = builder.CreateCall3(prepare_call(jlgetfield_func), V_null, myargs, - ConstantInt::get(T_int32,2)); + Value *result = builder.CreateCall3(prepare_call(jlgetfield_func), + maybe_decay_untracked(V_null), myargs, ConstantInt::get(T_int32,2)); #endif + end_lifetime(myargs, 2, ctx); bool needsgcroot = true; // !arg1.isimmutable || !jl_is_leaf_type(arg1.typ) || !is_datatype_all_pointers((jl_datatype_t*)arg1.typ); // TODO: probably want this as a llvm pass jl_cgval_t ret = mark_julia_type(result, true, jl_any_type, ctx, needsgcroot); // (typ will be patched up by caller) return ret; @@ -2583,11 +2617,13 @@ static Value *emit_f_is(const jl_cgval_t &arg1, const jl_cgval_t &arg2, jl_codec return emit_isa(arg1, rt2, NULL, ctx).first; // rt2 is a singleton type if (arg2.TIndex) return emit_isa(arg2, rt1, NULL, ctx).first; // rt1 is a singleton type - // mark_gc_use isn't needed since we won't load this pointer + // rooting these values isn't needed since we won't load this pointer // and we know at least one of them is a unique Singleton // which is already enough to ensure pointer uniqueness for this test // even if the other pointer managed to get garbage collected - return builder.CreateICmpEQ(boxed(arg1, ctx, false), boxed(arg2, ctx, false)); + return builder.CreateICmpEQ( + mark_callee_rooted(boxed(arg1, ctx, false)), + mark_callee_rooted(boxed(arg2, ctx, false))); } if (jl_type_intersection(rt1, rt2) == (jl_value_t*)jl_bottom_type) // types are disjoint (exhaustive test) @@ -2632,12 +2668,13 @@ static Value *emit_f_is(const jl_cgval_t &arg1, const jl_cgval_t &arg2, jl_codec Value *varg2 = arg2.constant ? literal_pointer_val(arg2.constant) : arg2.V; assert(varg1 && varg2 && (arg1.isboxed || arg1.TIndex) && (arg2.isboxed || arg2.TIndex) && "Only boxed types are valid for pointer comparison."); - return builder.CreateICmpEQ(varg1, varg2); + return builder.CreateICmpEQ(decay_derived(varg1), + decay_derived(varg2)); } JL_FEAT_REQUIRE(ctx, runtime); - Value *varg1 = boxed(arg1, ctx); - Value *varg2 = boxed(arg2, ctx, false); // potentially unrooted! + Value *varg1 = mark_callee_rooted(boxed(arg1, ctx)); + Value *varg2 = mark_callee_rooted(boxed(arg2, ctx, false)); // potentially unrooted! #if JL_LLVM_VERSION >= 30700 return builder.CreateTrunc(builder.CreateCall(prepare_call(jlegal_func), {varg1, varg2}), T_int1); #else @@ -2701,11 +2738,12 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, if (jl_subtype(ty, (jl_value_t*)jl_type_type)) { *ret = emit_expr(args[1], ctx); Value *rt_ty = boxed(emit_expr(args[2], ctx), ctx); + Value *rt_val = boxed(*ret, ctx); JL_FEAT_REQUIRE(ctx, runtime); #if JL_LLVM_VERSION >= 30700 - builder.CreateCall(prepare_call(jltypeassert_func), {boxed(*ret, ctx), rt_ty}); + builder.CreateCall(prepare_call(jltypeassert_func), {rt_val, rt_ty}); #else - builder.CreateCall2(prepare_call(jltypeassert_func), boxed(*ret, ctx), rt_ty); + builder.CreateCall2(prepare_call(jltypeassert_func), rt_val, rt_ty); #endif JL_GC_POP(); return true; @@ -2751,7 +2789,7 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, else if (f==jl_builtin__apply && nargs==2 && ctx->vaStack && slot_eq(args[2], ctx->vaSlot)) { // turn Core._apply(f, Tuple) ==> f(Tuple...) using the jlcall calling convention if Tuple is the vaStack allocation - Value *theF = boxed(emit_expr(args[1], ctx), ctx); + Value *theF = maybe_decay_untracked(boxed(emit_expr(args[1], ctx), ctx)); Value *nva = emit_n_varargs(ctx); #ifdef _P64 nva = builder.CreateTrunc(nva, T_int32); @@ -2920,7 +2958,7 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, PHINode *data_owner = NULL; // owner object against which the write barrier must check if (isboxed) { // if not boxed we don't need a write barrier assert(ary.isboxed); - Value *aryv = boxed(ary, ctx); + Value *aryv = maybe_decay_untracked(boxed(ary, ctx)); Value *flags = emit_arrayflags(ary, ctx); // the owner of the data is ary itself except if ary->how == 3 flags = builder.CreateAnd(flags, 3); @@ -2936,9 +2974,9 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, own_ptr = tbaa_decorate(tbaa_const, builder.CreateLoad( emit_bitcast( builder.CreateConstGEP1_32( - emit_bitcast(aryv, T_pint8), + emit_bitcast(decay_derived(aryv), T_pint8), jl_array_data_owner_offset(nd)), - T_ppjlvalue))); + T_pprjlvalue))); } else { #if JL_LLVM_VERSION >= 30700 @@ -2953,11 +2991,11 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, } builder.CreateBr(mergeBB); builder.SetInsertPoint(mergeBB); - data_owner = builder.CreatePHI(T_pjlvalue, 2); + data_owner = builder.CreatePHI(T_prjlvalue, 2); data_owner->addIncoming(aryv, curBB); data_owner->addIncoming(own_ptr, ownedBB); } - typed_store(emit_arrayptr(ary,args[1],ctx), idx, v, + typed_store(emit_arrayptr(ary,args[1],ctx,isboxed), idx, v, ety, ctx, !isboxed ? tbaa_arraybuf : tbaa_ptrarraybuf, data_owner, 0, false); // don't need to root the box if we had to make one since it's being stored in the array immediatly } @@ -3135,7 +3173,7 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, Value *types_len = emit_datatype_nfields(tyv); Value *idx = emit_unbox(T_size, emit_expr(args[2], ctx), (jl_value_t*)jl_long_type); emit_bounds_check(ty, (jl_value_t*)jl_datatype_type, idx, types_len, ctx); - Value *fieldtyp = tbaa_decorate(tbaa_const, builder.CreateLoad(builder.CreateGEP(emit_bitcast(types_svec, T_ppjlvalue), idx))); + Value *fieldtyp = tbaa_decorate(tbaa_const, builder.CreateLoad(builder.CreateGEP(decay_derived(emit_bitcast(types_svec, T_pprjlvalue)), idx))); *ret = mark_julia_type(fieldtyp, true, expr_type(expr, ctx), ctx); JL_GC_POP(); return true; @@ -3250,15 +3288,18 @@ static Value *emit_jlcall(Value *theFptr, Value *theF, jl_value_t **args, myargs = make_jlcall(makeArrayRef(largs, nargs), ctx); } else { - myargs = Constant::getNullValue(T_ppjlvalue); + myargs = Constant::getNullValue(T_pprjlvalue); } #if JL_LLVM_VERSION >= 30700 - Value *result = builder.CreateCall(prepare_call(theFptr), {theF, myargs, + Value *result = builder.CreateCall(prepare_call(theFptr), {maybe_decay_untracked(theF), myargs, ConstantInt::get(T_int32,nargs)}); #else - Value *result = builder.CreateCall3(prepare_call(theFptr), theF, myargs, + Value *result = builder.CreateCall3(prepare_call(theFptr), maybe_decay_untracked(theF), myargs, ConstantInt::get(T_int32,nargs)); #endif + if (nargs > 0) { + end_lifetime(myargs, nargs, ctx); + } return result; } @@ -3294,7 +3335,7 @@ static jl_cgval_t emit_call_function_object(jl_method_instance_t *li, const jl_c break; case jl_returninfo_t::SRet: result = emit_static_alloca(cft->getParamType(0)->getContainedType(0), ctx); - argvals[idx] = result; + argvals[idx] = decay_derived(result); idx++; break; case jl_returninfo_t::Union: @@ -3320,16 +3361,16 @@ static jl_cgval_t emit_call_function_object(jl_method_instance_t *li, const jl_c assert(idx < nfargs); Type *at = cft->getParamType(idx); if (isboxed) { - assert(at == T_pjlvalue && et == T_pjlvalue); + assert(at == T_prjlvalue && (et == T_pjlvalue || et == T_prjlvalue)); jl_cgval_t origval = i == 0 ? theF : emit_expr(args[i], ctx); - argvals[idx] = boxed(origval, ctx); + argvals[idx] = maybe_decay_untracked(boxed(origval, ctx)); } else if (et->isAggregateType()) { // can lazy load on demand, no copy needed - assert(at == PointerType::get(et, 0)); + assert(at == PointerType::get(et, AddressSpace::Derived)); jl_cgval_t arg = i == 0 ? theF : emit_expr(args[i], ctx); assert(arg.ispointer()); - argvals[idx] = data_pointer(arg, ctx, at); + argvals[idx] = decay_derived(data_pointer(arg, ctx, at)); push_gc_use(gc_uses, arg); } else { @@ -3358,22 +3399,25 @@ static jl_cgval_t emit_call_function_object(jl_method_instance_t *li, const jl_c case jl_returninfo_t::SRet: retval = mark_julia_slot(result, jlretty, NULL, tbaa_stack); break; - case jl_returninfo_t::Union: - retval = mark_julia_slot(builder.CreateExtractValue(call, 0), + case jl_returninfo_t::Union: { + Value *box = builder.CreateExtractValue(call, 0); + Value *tindex = builder.CreateExtractValue(call, 1); + Value *derived = builder.CreateSelect( + builder.CreateICmpEQ( + builder.CreateAnd(tindex, ConstantInt::get(T_int8, 0x80)), + ConstantInt::get(T_int8, 0)), + decay_derived(builder.CreateBitCast(argvals[0], T_pjlvalue)), + decay_derived(box) + ); + retval = mark_julia_slot(derived, jlretty, - builder.CreateExtractValue(call, 1), + tindex, tbaa_stack); // root this, if the return value was a box (tindex & 0x80) != 0 retval.gcroot = emit_local_root(ctx); - builder.CreateStore( - builder.CreateSelect( - builder.CreateICmpEQ( - builder.CreateAnd(retval.TIndex, ConstantInt::get(T_int8, 0x80)), - ConstantInt::get(T_int8, 0)), - V_null, - retval.V), - retval.gcroot); + builder.CreateStore(box, retval.gcroot); break; + } case jl_returninfo_t::Ghosts: retval = mark_julia_slot(NULL, jlretty, call, tbaa_stack); break; @@ -3458,7 +3502,8 @@ static jl_cgval_t emit_call(jl_expr_t *ex, jl_codectx_t *ctx) std::map::iterator it = builtin_func_map.find(jl_get_builtin_fptr(f)); if (it != builtin_func_map.end()) { theFptr = (*it).second; - result = mark_julia_type(emit_jlcall(theFptr, V_null, &args[1], nargs, ctx), true, expr_type(expr,ctx), ctx); + result = mark_julia_type(emit_jlcall(theFptr, + maybe_decay_untracked(V_null), &args[1], nargs, ctx), true, expr_type(expr,ctx), ctx); JL_GC_POP(); return result; } @@ -3491,6 +3536,7 @@ static jl_cgval_t emit_call(jl_expr_t *ex, jl_codectx_t *ctx) Value *callval = builder.CreateCall2(prepare_call(jlapplygeneric_func), myargs, ConstantInt::get(T_int32, nargs)); #endif + end_lifetime(myargs, nargs, ctx); result = mark_julia_type(callval, true, expr_type(expr, ctx), ctx); JL_GC_POP(); @@ -3505,7 +3551,8 @@ static void undef_var_error_ifnot(Value *ok, jl_sym_t *name, jl_codectx_t *ctx) BasicBlock *ifok = BasicBlock::Create(jl_LLVMContext, "ok"); builder.CreateCondBr(ok, ifok, err); builder.SetInsertPoint(err); - builder.CreateCall(prepare_call(jlundefvarerror_func), literal_pointer_val((jl_value_t*)name)); + builder.CreateCall(prepare_call(jlundefvarerror_func), + mark_callee_rooted(literal_pointer_val((jl_value_t*)name))); builder.CreateUnreachable(); ctx->f->getBasicBlockList().push_back(ifok); builder.SetInsertPoint(ifok); @@ -3542,11 +3589,11 @@ static Value *global_binding_pointer(jl_module_t *m, jl_sym_t *s, builder.SetInsertPoint(not_found); #if JL_LLVM_VERSION >= 30700 Value *bval = builder.CreateCall(prepare_call(jlgetbindingorerror_func), - {literal_pointer_val((jl_value_t*)m), + {maybe_decay_untracked(literal_pointer_val((jl_value_t*)m)), literal_pointer_val((jl_value_t*)s)}); #else Value *bval = builder.CreateCall2(prepare_call(jlgetbindingorerror_func), - literal_pointer_val((jl_value_t*)m), + maybe_decay_untracked(literal_pointer_val((jl_value_t*)m)), literal_pointer_val((jl_value_t*)s)); #endif builder.CreateStore(bval, bindinggv); @@ -3556,7 +3603,7 @@ static Value *global_binding_pointer(jl_module_t *m, jl_sym_t *s, PHINode *p = builder.CreatePHI(T_pjlvalue, 2); p->addIncoming(cachedval, currentbb); p->addIncoming(bval, not_found); - return julia_binding_gv(emit_bitcast(p, T_ppjlvalue)); + return julia_binding_gv(emit_bitcast(p, T_pprjlvalue)); } if (b->deprecated) cg_bdw(b, ctx); } @@ -3566,11 +3613,11 @@ static Value *global_binding_pointer(jl_module_t *m, jl_sym_t *s, static jl_cgval_t emit_checked_var(Value *bp, jl_sym_t *name, jl_codectx_t *ctx, bool isvol, MDNode *tbaa) { - assert(bp->getType() == T_ppjlvalue); + assert(bp->getType() == T_pprjlvalue); Instruction *v = builder.CreateLoad(bp, isvol); if (tbaa) tbaa_decorate(tbaa, v); - undef_var_error_ifnot(builder.CreateICmpNE(v, V_null), name, ctx); + undef_var_error_ifnot(builder.CreateICmpNE(v, maybe_decay_untracked(V_null)), name, ctx); return mark_julia_type(v, true, jl_any_type, ctx); } @@ -3583,8 +3630,8 @@ static jl_cgval_t emit_sparam(size_t i, jl_codectx_t *ctx) } } assert(ctx->spvals_ptr != NULL); - Value *bp = builder.CreateConstInBoundsGEP1_32(LLVM37_param(T_pjlvalue) - emit_bitcast(ctx->spvals_ptr, T_ppjlvalue), + Value *bp = builder.CreateConstInBoundsGEP1_32(LLVM37_param(T_prjlvalue) + emit_bitcast(decay_derived(ctx->spvals_ptr), T_pprjlvalue), i + sizeof(jl_svec_t) / sizeof(jl_value_t*)); return mark_julia_type(tbaa_decorate(tbaa_const, builder.CreateLoad(bp)), true, jl_any_type, ctx, false); } @@ -3619,7 +3666,7 @@ static jl_cgval_t emit_isdefined(jl_value_t *sym, jl_codectx_t *ctx) } if (vi.boxroot != NULL) { Value *boxed = builder.CreateLoad(vi.boxroot, vi.isVolatile); - Value *box_isnull = builder.CreateICmpNE(boxed, V_null); + Value *box_isnull = builder.CreateICmpNE(boxed, maybe_decay_untracked(V_null)); if (vi.pTIndex) { // value is either boxed in the stack slot, or unboxed in value // as indicated by testing (pTIndex & 0x80) @@ -3660,7 +3707,7 @@ static jl_cgval_t emit_isdefined(jl_value_t *sym, jl_codectx_t *ctx) literal_pointer_val((jl_value_t*)modu), literal_pointer_val((jl_value_t*)name) }); - isnull = builder.CreateICmpNE(v, V_null); + isnull = builder.CreateICmpNE(v, ConstantInt::get(T_int32, 0)); } } return mark_julia_type(isnull, false, jl_bool_type, ctx); @@ -3715,8 +3762,9 @@ static jl_cgval_t emit_local(jl_value_t *slotload, jl_codectx_t *ctx) if (vi.boxroot != NULL) { Value *boxed = builder.CreateLoad(vi.boxroot, vi.isVolatile); Value *box_isnull; + v.gcroot = vi.boxroot; if (vi.usedUndef) - box_isnull = builder.CreateICmpNE(boxed, V_null); + box_isnull = builder.CreateICmpNE(boxed, maybe_decay_untracked(V_null)); if (vi.pTIndex) { // value is either boxed in the stack slot, or unboxed in value // as indicated by testing (pTIndex & 0x80) @@ -3725,9 +3773,11 @@ static jl_cgval_t emit_local(jl_value_t *slotload, jl_codectx_t *ctx) ConstantInt::get(T_int8, 0)); if (vi.usedUndef) isnull = builder.CreateSelect(load_unbox, isnull, box_isnull); - if (v.V) // v.V will be null if it is a union of all ghost values - v.V = builder.CreateSelect(load_unbox, emit_bitcast(v.V, boxed->getType()), boxed); - else + if (v.V) { // v.V will be null if it is a union of all ghost values + boxed = decay_derived(boxed); + v.V = builder.CreateSelect(load_unbox, emit_bitcast( + decay_derived(v.V), boxed->getType()), boxed); + } else v.V = boxed; v = update_julia_type(v, typ, ctx); } @@ -3792,7 +3842,7 @@ static Value *compute_box_tindex(Value *datatype, jl_value_t *supertype, jl_valu for_each_uniontype_small( [&](unsigned idx, jl_datatype_t *jt) { if (jl_subtype((jl_value_t*)jt, supertype)) { - Value *cmp = builder.CreateICmpEQ(literal_pointer_val((jl_value_t*)jt), datatype); + Value *cmp = builder.CreateICmpEQ(maybe_decay_untracked(literal_pointer_val((jl_value_t*)jt)), datatype); tindex = builder.CreateSelect(cmp, ConstantInt::get(T_int8, idx), tindex); } }, @@ -3849,14 +3899,21 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) emit_unionmove(dest, slot, isboxed, false, NULL, ctx); Value *gcroot = NULL; if (isboxed) { - if (slot.gcroot) + Value *box; + if (slot.gcroot) { gcroot = emit_local_root(ctx); - else + // This might load the wrong object in general, but if it gets selected, below, + // we know that it was in fact the one we wanted. + box = builder.CreateLoad(slot.gcroot); + } else { gcroot = emit_static_alloca(T_pjlvalue); - Value *box = builder.CreateSelect(isboxed, emit_bitcast(slot.V, T_pjlvalue), V_null); + box = V_null; + } builder.CreateStore(box, gcroot); if (dest) // might be all ghost values - dest = builder.CreateSelect(isboxed, box, emit_bitcast(dest, box->getType())); + dest = builder.CreateSelect(isboxed, + decay_derived(box), + emit_bitcast(decay_derived(dest), box->getType())); else dest = box; } @@ -3894,7 +3951,7 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) if (bp != NULL) { // it's a global JL_FEAT_REQUIRE(ctx, runtime); assert(bnd); - Value *rval = boxed(emit_expr(r, ctx), ctx, false); // no root needed since this is about to be assigned to a global + Value *rval = mark_callee_rooted(boxed(emit_expr(r, ctx), ctx, false)); // no root needed since this is about to be assigned to a global #if JL_LLVM_VERSION >= 30700 builder.CreateCall(prepare_call(jlcheckassign_func), {literal_pointer_val(bnd), @@ -3923,7 +3980,7 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) // convert rval-type to lval-type jl_value_t *slot_type = vi.value.typ; - rval_info = convert_julia_type(rval_info, slot_type, ctx, /*needs-root*/false); + rval_info = convert_julia_type(rval_info, slot_type, ctx, /*needs-root*/true); if (rval_info.typ == jl_bottom_type) return; @@ -3966,16 +4023,17 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) isboxed = builder.CreateICmpNE( builder.CreateAnd(rval_info.TIndex, ConstantInt::get(T_int8, 0x80)), ConstantInt::get(T_int8, 0)); - rval = V_null; - if (rval_info.ispointer() && rval_info.V != NULL && !isa(rval_info.V)) // might be all ghost values or otherwise definitely not boxed - rval = builder.CreateSelect(isboxed, emit_bitcast(rval_info.V, rval->getType()), rval); + rval = maybe_decay_untracked(V_null); + if (rval_info.ispointer() && rval_info.V != NULL && !isa(rval_info.V) && + !(isa(isboxed) && cast(isboxed)->isZero())) // might be all ghost values or otherwise definitely not boxed + rval = builder.CreateLoad(rval_info.gcroot); assert(!vi.value.constant); } else { assert(!vi.pTIndex || rval_info.isboxed || rval_info.constant); - rval = boxed(rval_info, ctx, false); + rval = maybe_decay_untracked(boxed(rval_info, ctx, false)); } - builder.CreateStore(rval, vi.boxroot, vi.isVolatile); + builder.CreateStore(maybe_decay_untracked(rval), vi.boxroot, vi.isVolatile); } // store unboxed variables @@ -4061,7 +4119,8 @@ static Value *emit_condition(const jl_cgval_t &condV, const std::string &msg, return builder.CreateXor(builder.CreateTrunc(cond, T_int1), ConstantInt::get(T_int1, 1)); } if (condV.isboxed) { - return builder.CreateICmpEQ(boxed(condV, ctx), literal_pointer_val(jl_false)); + return builder.CreateICmpEQ(boxed(condV, ctx), + maybe_decay_untracked(literal_pointer_val(jl_false))); } // not a boolean return ConstantInt::get(T_int1, 0); // TODO: replace with Undef @@ -4093,7 +4152,7 @@ static void emit_stmtpos(jl_value_t *expr, jl_codectx_t *ctx) // create a new uninitialized variable Value *lv = vi.boxroot; if (lv != NULL) - builder.CreateStore(V_null, lv); + builder.CreateStore(maybe_decay_untracked(V_null), lv); if (lv == NULL || vi.pTIndex != NULL) store_def_flag(vi, false); } @@ -4257,15 +4316,16 @@ static jl_cgval_t emit_expr(jl_value_t *expr, jl_codectx_t *ctx) name = literal_pointer_val((jl_value_t*)slot_symbol(sl, ctx)); } if (bp) { - Value *mdargs[5] = { name, literal_pointer_val((jl_value_t*)mod), bp, bp_owner, literal_pointer_val(bnd) }; + Value *mdargs[5] = { name, literal_pointer_val((jl_value_t*)mod), bp, + maybe_decay_untracked(bp_owner), literal_pointer_val(bnd) }; jl_cgval_t gf = mark_julia_type( builder.CreateCall(prepare_call(jlgenericfunction_func), makeArrayRef(mdargs)), true, jl_function_type, ctx); if (jl_expr_nargs(ex) == 1) return gf; } - Value *a1 = boxed(emit_expr(args[1], ctx), ctx); - Value *a2 = boxed(emit_expr(args[2], ctx), ctx); + Value *a1 = maybe_decay_untracked(boxed(emit_expr(args[1], ctx), ctx)); + Value *a2 = maybe_decay_untracked(boxed(emit_expr(args[2], ctx), ctx)); Value *mdargs[4] = { /*argdata*/a1, /*code*/a2, @@ -4319,7 +4379,8 @@ static jl_cgval_t emit_expr(jl_value_t *expr, jl_codectx_t *ctx) } } jl_cgval_t ast = emit_expr(arg, ctx); - return mark_julia_type(builder.CreateCall(prepare_call(jlcopyast_func), boxed(ast, ctx)), true, ast.typ, ctx); + return mark_julia_type(builder.CreateCall(prepare_call(jlcopyast_func), + maybe_decay_untracked(boxed(ast, ctx))), true, ast.typ, ctx); } else if (head == simdloop_sym) { llvm::annotateSimdLoop(builder.GetInsertBlock()); @@ -4378,7 +4439,7 @@ static void allocate_gc_frame(BasicBlock *b0, jl_codectx_t *ctx) ctx->ptlsStates = builder.CreateCall(prepare_call(jltls_states_func)); int nthfield = offsetof(jl_tls_states_t, safepoint) / sizeof(void*); ctx->signalPage = emit_nthptr_recast(ctx->ptlsStates, nthfield, tbaa_const, - PointerType::get(T_psize, 0)); + PointerType::get(T_psize, 0), false); } static void emit_last_age_field(jl_codectx_t *ctx) @@ -4396,6 +4457,8 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t Type *crt = julia_struct_to_llvm(jlrettype, NULL, &toboxed); if (crt == NULL) jl_error("cfunction: return type doesn't correspond to a C type"); + else if (toboxed) + crt = T_prjlvalue; size_t nargs = jl_nparams(argt); function_sig_t sig(crt, jlrettype, toboxed, argt->parameters, NULL, nargs, false, CallingConv::C, false); @@ -4480,7 +4543,7 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t Value *lam_max = builder.CreateLoad( builder.CreateConstInBoundsGEP1_32( LLVM37_param(T_size) - emit_bitcast(literal_pointer_val((jl_value_t*)lam), T_psize), + emit_bitcast(decay_derived(literal_pointer_val((jl_value_t*)lam)), T_psize), offsetof(jl_method_instance_t, max_world) / sizeof(size_t))); // XXX: age is always OK if we don't have a TLS. This is a hack required due to `@threadcall` abuse. // and adds quite a bit of complexity here, even though it's still wrong @@ -4532,7 +4595,7 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t if (sig.sret && jlfunc_sret) result = emit_bitcast(sretPtr, cft->getParamType(0)); else - result = builder.CreateAlloca(cft->getParamType(0)->getContainedType(0)); + result = decay_derived(builder.CreateAlloca(cft->getParamType(0)->getContainedType(0))); args.push_back(result); FParamIndex++; } @@ -4542,10 +4605,11 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t theFptr = lam ? (Function*)lam->functionObjectsDecls.functionObject : NULL; specsig = false; jlfunc_sret = false; - myargs = CallInst::Create(prepare_call(jlcall_frame_func), - ConstantInt::get(T_int32, nargs + 1), - "", - /*InsertBefore*/ctx.ptlsStates); + myargs = new AllocaInst(T_prjlvalue, +#if JL_LLVM_VERSION >= 50000 + 0, +#endif + ConstantInt::get(T_int32, nargs + 1), "jlcall", /*InsertBefore*/ctx.ptlsStates); FParamIndex++; // leave room for writing the ff object at the beginning } @@ -4560,12 +4624,12 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t jargty = jl_tparam0(jargty); if (jargty == (jl_value_t*)jl_any_type) { inputarg = mark_julia_type( - builder.CreateLoad(builder.CreatePointerCast(val, T_ppjlvalue)), + builder.CreateLoad(emit_bitcast(val, T_pprjlvalue)), true, jargty, &ctx); } else if (!jl_isbits(jargty)) { // must be a jl_value_t* (because it's mutable or contains gc roots) - inputarg = mark_julia_type(builder.CreatePointerCast(val, T_pjlvalue), true, jargty, &ctx); + inputarg = mark_julia_type(maybe_decay_untracked(emit_bitcast(val, T_prjlvalue)), true, jargty, &ctx); } else { bool isboxed; @@ -4576,7 +4640,7 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t inputarg = ghostValue(jargty); } else { - val = builder.CreatePointerCast(val, T->getPointerTo()); + val = emit_bitcast(val, T->getPointerTo()); val = builder.CreateAlignedLoad(val, 1); // make no alignment assumption about pointer from C inputarg = mark_julia_type(val, false, jargty, &ctx); } @@ -4593,7 +4657,7 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t // something of type T // undo whatever we might have done to this poor argument if (sig.byRefList.at(i)) { - assert(val->getType() == sig.fargt[i]->getPointerTo()); + assert(cast(val->getType())->getElementType() == sig.fargt[i]); val = builder.CreateAlignedLoad(val, 1); // unknown alignment from C } else { @@ -4802,10 +4866,12 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t allocate_gc_frame(b0, &ctx2); Function::arg_iterator AI = gf_thunk->arg_begin(); - Value *myargs = CallInst::Create(prepare_call(jlcall_frame_func), - ConstantInt::get(T_int32, nargs + 1), - "", - /*InsertBefore*/ctx2.ptlsStates); + + Value *myargs = new AllocaInst(T_prjlvalue, +#if JL_LLVM_VERSION >= 50000 + 0, +#endif + ConstantInt::get(T_int32, nargs + 1), "jlcall", ctx2.ptlsStates); if (cc == jl_returninfo_t::SRet || cc == jl_returninfo_t::Union) ++AI; for (size_t i = 0; i < nargs + 1; i++) { @@ -4822,7 +4888,7 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t ++AI; Type *at = arg_v->getType(); if (isboxed) { - assert(at == T_pjlvalue && et == T_pjlvalue); + assert(at == T_prjlvalue && et == T_pjlvalue); arg_box = arg_v; } else if (et->isAggregateType()) { @@ -4835,7 +4901,7 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t (void)at; } Value *argn = builder.CreateConstInBoundsGEP1_32(LLVM37_param(NULL) myargs, i); - builder.CreateStore(arg_box, argn); + builder.CreateStore(maybe_decay_untracked(arg_box), argn); } assert(AI == gf_thunk->arg_end()); Value *nargs_v = ConstantInt::get(T_int32, nargs + 1); @@ -5039,7 +5105,7 @@ static Function *gen_jlcall_wrapper(jl_method_instance_t *lam, const jl_returnin break; case jl_returninfo_t::SRet: result = builder.CreateAlloca(ftype->getParamType(0)->getContainedType(0)); - args[idx] = result; + args[idx] = decay_derived(result); idx++; break; case jl_returninfo_t::Union: @@ -5065,7 +5131,7 @@ static Function *gen_jlcall_wrapper(jl_method_instance_t *lam, const jl_returnin theArg = builder.CreateLoad(argPtr); } if (lty != NULL && !isboxed) { - theArg = builder.CreatePointerCast(theArg, PointerType::get(lty, 0)); + theArg = decay_derived(emit_bitcast(theArg, PointerType::get(lty, 0))); if (!lty->isAggregateType()) // keep "aggregate" type values in place as pointers theArg = builder.CreateAlignedLoad(theArg, julia_alignment(theArg, ty, 0)); } @@ -5089,10 +5155,14 @@ static Function *gen_jlcall_wrapper(jl_method_instance_t *lam, const jl_returnin retval = mark_julia_slot(result, jlretty, NULL, tbaa_stack); break; case jl_returninfo_t::Union: - retval = mark_julia_slot(builder.CreateExtractValue(call, 0), + // result is technically not right here, but we only need to look at it + // for the unboxed values, so it's ok. + retval = mark_julia_slot(result, jlretty, builder.CreateExtractValue(call, 1), tbaa_stack); + retval.gcroot = emit_local_root(&ctx); + builder.CreateStore(builder.CreateExtractValue(call, 0), retval.gcroot); break; case jl_returninfo_t::Ghosts: retval = mark_julia_slot(NULL, jlretty, call, tbaa_stack); @@ -5119,7 +5189,7 @@ static jl_returninfo_t get_specsig_function(Module *M, const std::string &name, props.cc = jl_returninfo_t::Union; Type *AT = ArrayType::get(T_int8, props.union_bytes); fsig.push_back(AT->getPointerTo()); - Type *pair[] = { T_pjlvalue, T_int8 }; + Type *pair[] = { T_prjlvalue, T_int8 }; rt = StructType::get(jl_LLVMContext, makeArrayRef(pair)); } else if (allunbox) { @@ -5127,7 +5197,7 @@ static jl_returninfo_t get_specsig_function(Module *M, const std::string &name, rt = T_int8; } else { - rt = T_pjlvalue; + rt = T_prjlvalue; } } else { @@ -5136,12 +5206,14 @@ static jl_returninfo_t get_specsig_function(Module *M, const std::string &name, if (!retboxed) { if (rt != T_void && deserves_sret(jlrettype, rt)) { props.cc = jl_returninfo_t::SRet; - fsig.push_back(rt->getPointerTo()); + fsig.push_back(rt->getPointerTo(AddressSpace::Derived)); rt = T_void; } else { props.cc = jl_returninfo_t::Register; } + } else { + rt = T_prjlvalue; } } #if JL_LLVM_VERSION >= 50000 @@ -5160,7 +5232,8 @@ static jl_returninfo_t get_specsig_function(Module *M, const std::string &name, } for (size_t i = 0; i < jl_nparams(sig); i++) { jl_value_t *jt = jl_tparam(sig, i); - Type *ty = julia_type_to_llvm(jt); + bool isboxed; + Type *ty = julia_type_to_llvm(jt, &isboxed); if (type_is_ghost(ty)) continue; if (ty->isAggregateType()) { // aggregate types are passed by pointer @@ -5168,8 +5241,10 @@ static jl_returninfo_t get_specsig_function(Module *M, const std::string &name, #if JL_LLVM_VERSION >= 30500 attributes = attributes.addAttribute(jl_LLVMContext, fsig.size() + 1, Attribute::ReadOnly); #endif - ty = PointerType::get(ty, 0); + ty = PointerType::get(ty, AddressSpace::Derived); } + if (isboxed) + ty = PointerType::get(cast(ty)->getElementType(), AddressSpace::Tracked); fsig.push_back(ty); } FunctionType *ftype = FunctionType::get(rt, fsig, false); @@ -5712,11 +5787,15 @@ static std::unique_ptr emit_function( (va && (int)i == ctx.vaSlot && varinfo.escapes) || // or it's the va arg tuple (s != unused_sym && i == 0)) { // or it is the first argument (which isn't in `argArray`) #if JL_LLVM_VERSION >= 50000 - AllocaInst *av = new AllocaInst(T_pjlvalue, 0, + AllocaInst *av = new AllocaInst(T_prjlvalue, 0, #else - AllocaInst *av = new AllocaInst(T_pjlvalue, + AllocaInst *av = new AllocaInst(T_prjlvalue, #endif jl_symbol_name(s), /*InsertBefore*/ctx.ptlsStates); + StoreInst *SI = new StoreInst( + ConstantPointerNull::get(cast(T_prjlvalue)), av, + false); + SI->insertAfter(ctx.ptlsStates); varinfo.boxroot = av; #if JL_LLVM_VERSION >= 30600 if (ctx.debug_enabled && varinfo.dinfo) { @@ -5852,14 +5931,14 @@ static std::unique_ptr emit_function( if (vi.boxroot != NULL) { #if JL_LLVM_VERSION >= 30700 Value *restTuple = - builder.CreateCall(prepare_call(jltuple_func), {V_null, + builder.CreateCall(prepare_call(jltuple_func), {maybe_decay_untracked(V_null), builder.CreateGEP(argArray, ConstantInt::get(T_size,nreq-1)), builder.CreateSub(argCount, ConstantInt::get(T_int32,nreq-1))}); #else Value *restTuple = - builder.CreateCall3(prepare_call(jltuple_func), V_null, + builder.CreateCall3(prepare_call(jltuple_func), maybe_decay_untracked(V_null), builder.CreateGEP(argArray, ConstantInt::get(T_size,nreq-1)), builder.CreateSub(argCount, @@ -6205,18 +6284,25 @@ static std::unique_ptr emit_function( tindex = retvalinfo.TIndex; if (retvalinfo.V == NULL) { // treat this as a simple Ghosts - data = V_null; + data = maybe_decay_untracked(V_null); sret = NULL; } else { - data = emit_bitcast(sret, T_pjlvalue); + data = maybe_decay_untracked(V_null); if (retvalinfo.ispointer() && !isa(retvalinfo.V)) { // also need to account for the possibility the return object is boxed // and avoid / skip copying it to the stack isboxed_union = builder.CreateICmpNE( builder.CreateAnd(tindex, ConstantInt::get(T_int8, 0x80)), ConstantInt::get(T_int8, 0)); - data = builder.CreateSelect(isboxed_union, emit_bitcast(retvalinfo.V, T_pjlvalue), data); + // Lift the select, because gcroot may be NULL if + // there's no boxed value. + if (isa(isboxed_union)) + data = cast(isboxed_union)->isZero() ? data : builder.CreateLoad(retvalinfo.gcroot); + else + data = builder.CreateSelect(isboxed_union, + builder.CreateLoad(retvalinfo.gcroot), + data); } } } @@ -6225,7 +6311,7 @@ static std::unique_ptr emit_function( //assert(retvalinfo.isboxed); tindex = compute_tindex_unboxed(retvalinfo, jlrettype, &ctx); tindex = builder.CreateOr(tindex, ConstantInt::get(T_int8, 0x80)); - data = boxed(retvalinfo, &ctx, false); // skip the gcroot on the return path + data = maybe_decay_untracked(boxed(retvalinfo, &ctx, false)); // skip the gcroot on the return path sret = NULL; } retval = UndefValue::get(retty); @@ -6599,8 +6685,11 @@ static void init_julia_llvm_env(Module *m) dbuilder.getOrCreateArray(ArrayRef())); #endif - T_pjlvalue = T_ppint8; + T_jlvalue = StructType::create(jl_LLVMContext, "jl_value_t"); + T_pjlvalue = PointerType::get(T_jlvalue, 0); + T_prjlvalue = PointerType::get(T_jlvalue, AddressSpace::Tracked); T_ppjlvalue = PointerType::get(T_pjlvalue, 0); + T_pprjlvalue = PointerType::get(T_prjlvalue, 0); two_pvalue_llvmt.push_back(T_pjlvalue); two_pvalue_llvmt.push_back(T_pjlvalue); three_pvalue_llvmt.push_back(T_pjlvalue); @@ -6614,14 +6703,14 @@ static void init_julia_llvm_env(Module *m) jl_init_jit(T_pjlvalue); std::vector ftargs(0); - ftargs.push_back(T_pjlvalue); // linfo->sparam_vals - ftargs.push_back(T_pjlvalue); // function - ftargs.push_back(T_ppjlvalue); // args[] - ftargs.push_back(T_int32); // nargs - jl_func_sig_sparams = FunctionType::get(T_pjlvalue, ftargs, false); + ftargs.push_back(T_prjlvalue); // linfo->sparam_vals + ftargs.push_back(T_prjlvalue); // function + ftargs.push_back(T_pprjlvalue); // args[] + ftargs.push_back(T_int32); // nargs + jl_func_sig_sparams = FunctionType::get(T_prjlvalue, ftargs, false); assert(jl_func_sig_sparams != NULL); ftargs.erase(ftargs.begin()); // drop linfo->sparams_vals argument - jl_func_sig = FunctionType::get(T_pjlvalue, ftargs, false); + jl_func_sig = FunctionType::get(T_prjlvalue, ftargs, false); assert(jl_func_sig != NULL); Type *vaelts[] = {T_pint8 @@ -6722,7 +6811,7 @@ static void init_julia_llvm_env(Module *m) add_named_global(jlerror_func, &jl_error); std::vector args1_(0); - args1_.push_back(T_pjlvalue); + args1_.push_back(PointerType::get(T_jlvalue, AddressSpace::CalleeRooted)); jlthrow_func = Function::Create(FunctionType::get(T_void, args1_, false), Function::ExternalLinkage, @@ -6730,6 +6819,8 @@ static void init_julia_llvm_env(Module *m) jlthrow_func->setDoesNotReturn(); add_named_global(jlthrow_func, &jl_throw); + // Symbols are not gc-tracked, but we'll treat them as callee rooted anyway, + // because they may come from a gc-rooted location jlundefvarerror_func = Function::Create(FunctionType::get(T_void, args1_, false), Function::ExternalLinkage, @@ -6738,7 +6829,7 @@ static void init_julia_llvm_env(Module *m) add_named_global(jlundefvarerror_func, &jl_undefined_var_error); std::vector args2_boundserrorv(0); - args2_boundserrorv.push_back(T_pjlvalue); + args2_boundserrorv.push_back(PointerType::get(T_jlvalue, AddressSpace::CalleeRooted)); args2_boundserrorv.push_back(T_psize); args2_boundserrorv.push_back(T_size); jlboundserrorv_func = @@ -6749,7 +6840,7 @@ static void init_julia_llvm_env(Module *m) add_named_global(jlboundserrorv_func, &jl_bounds_error_ints); std::vector args2_boundserror(0); - args2_boundserror.push_back(T_pjlvalue); + args2_boundserror.push_back(PointerType::get(T_jlvalue, AddressSpace::CalleeRooted)); args2_boundserror.push_back(T_size); jlboundserror_func = Function::Create(FunctionType::get(T_void, args2_boundserror, false), @@ -6759,7 +6850,7 @@ static void init_julia_llvm_env(Module *m) add_named_global(jlboundserror_func, &jl_bounds_error_int); std::vector args3_vboundserror(0); - args3_vboundserror.push_back(T_ppjlvalue); + args3_vboundserror.push_back(T_pprjlvalue); args3_vboundserror.push_back(T_size); args3_vboundserror.push_back(T_size); jlvboundserror_func = @@ -6770,8 +6861,8 @@ static void init_julia_llvm_env(Module *m) add_named_global(jlvboundserror_func, &jl_bounds_error_tuple_int); std::vector args3_uboundserror(0); - args3_uboundserror.push_back(T_pint8); - args3_uboundserror.push_back(T_pjlvalue); + args3_uboundserror.push_back(PointerType::get(T_int8, AddressSpace::Derived)); + args3_uboundserror.push_back(T_prjlvalue); args3_uboundserror.push_back(T_size); jluboundserror_func = Function::Create(FunctionType::get(T_void, args3_uboundserror, false), @@ -6808,8 +6899,8 @@ static void init_julia_llvm_env(Module *m) std::vector te_args(0); te_args.push_back(T_pint8); te_args.push_back(T_pint8); - te_args.push_back(T_pjlvalue); - te_args.push_back(T_pjlvalue); + te_args.push_back(T_prjlvalue); + te_args.push_back(PointerType::get(T_jlvalue, AddressSpace::CalleeRooted)); jltypeerror_func = Function::Create(FunctionType::get(T_void, te_args, false), Function::ExternalLinkage, @@ -6819,29 +6910,32 @@ static void init_julia_llvm_env(Module *m) std::vector args_2ptrs(0); args_2ptrs.push_back(T_pjlvalue); - args_2ptrs.push_back(T_pjlvalue); + args_2ptrs.push_back(PointerType::get(T_jlvalue, AddressSpace::CalleeRooted)); jlcheckassign_func = Function::Create(FunctionType::get(T_void, args_2ptrs, false), Function::ExternalLinkage, "jl_checked_assignment", m); add_named_global(jlcheckassign_func, &jl_checked_assignment); - std::vector args_1ptr(0); - args_1ptr.push_back(T_pjlvalue); + std::vector args_1binding(0); + args_1binding.push_back(T_pjlvalue); jldeclareconst_func = - Function::Create(FunctionType::get(T_void, args_1ptr, false), + Function::Create(FunctionType::get(T_void, args_1binding, false), Function::ExternalLinkage, "jl_declare_constant", m); add_named_global(jldeclareconst_func, &jl_declare_constant); + std::vector args_2ptrs_(0); + args_2ptrs_.push_back(T_prjlvalue); + args_2ptrs_.push_back(T_prjlvalue); jlgetbindingorerror_func = - Function::Create(FunctionType::get(T_pjlvalue, args_2ptrs, false), + Function::Create(FunctionType::get(T_pjlvalue, args_2ptrs_, false), Function::ExternalLinkage, "jl_get_binding_or_error", m); add_named_global(jlgetbindingorerror_func, &jl_get_binding_or_error); jlboundp_func = - Function::Create(FunctionType::get(T_pjlvalue, args_2ptrs, false), + Function::Create(FunctionType::get(T_int32, args_2ptrs_, false), Function::ExternalLinkage, "jl_boundp", m); add_named_global(jlboundp_func, &jl_boundp); @@ -6876,11 +6970,6 @@ static void init_julia_llvm_env(Module *m) jlapply2va_func = jlcall_func_to_llvm("jl_apply_2va", &jl_apply_2va, m); - jltypeassert_func = Function::Create(FunctionType::get(T_void, two_pvalue_llvmt, false), - Function::ExternalLinkage, - "jl_typeassert", m); - add_named_global(jltypeassert_func, &jl_typeassert); - std::vector argsdepwarnpi(0); argsdepwarnpi.push_back(T_size); jldepwarnpi_func = Function::Create(FunctionType::get(T_void, argsdepwarnpi, false), @@ -6888,24 +6977,26 @@ static void init_julia_llvm_env(Module *m) "jl_depwarn_partial_indexing", m); add_named_global(jldepwarnpi_func, &jl_depwarn_partial_indexing); + std::vector args_1ptr(0); + args_1ptr.push_back(T_prjlvalue); queuerootfun = Function::Create(FunctionType::get(T_void, args_1ptr, false), Function::ExternalLinkage, "jl_gc_queue_root", m); add_named_global(queuerootfun, &jl_gc_queue_root); std::vector agargs(0); - agargs.push_back(T_ppjlvalue); + agargs.push_back(T_pprjlvalue); agargs.push_back(T_uint32); - jlapplygeneric_func = Function::Create(FunctionType::get(T_pjlvalue, agargs, false), + jlapplygeneric_func = Function::Create(FunctionType::get(T_prjlvalue, agargs, false), Function::ExternalLinkage, "jl_apply_generic", m); add_named_global(jlapplygeneric_func, &jl_apply_generic); std::vector invokeargs(0); - invokeargs.push_back(T_pjlvalue); - invokeargs.push_back(T_ppjlvalue); + invokeargs.push_back(T_prjlvalue); + invokeargs.push_back(T_pprjlvalue); invokeargs.push_back(T_uint32); - jlinvoke_func = Function::Create(FunctionType::get(T_pjlvalue, invokeargs, false), + jlinvoke_func = Function::Create(FunctionType::get(T_prjlvalue, invokeargs, false), Function::ExternalLinkage, "jl_invoke", m); add_named_global(jlinvoke_func, &jl_invoke); @@ -6915,8 +7006,8 @@ static void init_julia_llvm_env(Module *m) expect_func = Intrinsic::getDeclaration(m, Intrinsic::expect, exp_args); std::vector args_topeval(0); - args_topeval.push_back(T_pjlvalue); - args_topeval.push_back(T_pjlvalue); + args_topeval.push_back(T_prjlvalue); + args_topeval.push_back(T_prjlvalue); jltopeval_func = Function::Create(FunctionType::get(T_pjlvalue, args_topeval, false), Function::ExternalLinkage, @@ -6924,9 +7015,9 @@ static void init_julia_llvm_env(Module *m) add_named_global(jltopeval_func, &jl_toplevel_eval); std::vector args_copyast(0); - args_copyast.push_back(T_pjlvalue); + args_copyast.push_back(T_prjlvalue); jlcopyast_func = - Function::Create(FunctionType::get(T_pjlvalue, args_copyast, false), + Function::Create(FunctionType::get(T_prjlvalue, args_copyast, false), Function::ExternalLinkage, "jl_copy_ast", m); add_named_global(jlcopyast_func, &jl_copy_ast); @@ -6940,10 +7031,10 @@ static void init_julia_llvm_env(Module *m) add_named_global(jlnsvec_func, &jl_svec); std::vector mdargs(0); - mdargs.push_back(T_pjlvalue); - mdargs.push_back(T_pjlvalue); - mdargs.push_back(T_pjlvalue); - mdargs.push_back(T_pjlvalue); + mdargs.push_back(T_prjlvalue); + mdargs.push_back(T_prjlvalue); + mdargs.push_back(T_prjlvalue); + mdargs.push_back(T_prjlvalue); jlmethod_func = Function::Create(FunctionType::get(T_void, mdargs, false), Function::ExternalLinkage, @@ -6951,13 +7042,13 @@ static void init_julia_llvm_env(Module *m) add_named_global(jlmethod_func, &jl_method_def); std::vector funcdefargs(0); - funcdefargs.push_back(T_pjlvalue); - funcdefargs.push_back(T_pjlvalue); - funcdefargs.push_back(T_ppjlvalue); - funcdefargs.push_back(T_pjlvalue); + funcdefargs.push_back(T_prjlvalue); + funcdefargs.push_back(T_prjlvalue); + funcdefargs.push_back(T_pprjlvalue); + funcdefargs.push_back(T_prjlvalue); funcdefargs.push_back(T_pjlvalue); jlgenericfunction_func = - Function::Create(FunctionType::get(T_pjlvalue, funcdefargs, false), + Function::Create(FunctionType::get(T_prjlvalue, funcdefargs, false), Function::ExternalLinkage, "jl_generic_function_def", m); add_named_global(jlgenericfunction_func, &jl_generic_function_def); @@ -7012,31 +7103,39 @@ static void init_julia_llvm_env(Module *m) "jl_pop_handler", m); add_named_global(jlleave_func, &jl_pop_handler); - std::vector args_2vals(0); - args_2vals.push_back(T_pjlvalue); - args_2vals.push_back(T_pjlvalue); + std::vector args_2vals_callee_rooted(0); + args_2vals_callee_rooted.push_back(PointerType::get(T_jlvalue, AddressSpace::CalleeRooted)); + args_2vals_callee_rooted.push_back(PointerType::get(T_jlvalue, AddressSpace::CalleeRooted)); jlegal_func = - Function::Create(FunctionType::get(T_int32, args_2vals, false), + Function::Create(FunctionType::get(T_int32, args_2vals_callee_rooted, false), Function::ExternalLinkage, "jl_egal", m); add_named_global(jlegal_func, &jl_egal); + std::vector args_2vals_tracked(0); + args_2vals_tracked.push_back(T_prjlvalue); + args_2vals_tracked.push_back(T_prjlvalue); jlisa_func = - Function::Create(FunctionType::get(T_int32, args_2vals, false), + Function::Create(FunctionType::get(T_int32, args_2vals_tracked, false), Function::ExternalLinkage, "jl_isa", m); add_named_global(jlisa_func, &jl_isa); jlsubtype_func = - Function::Create(FunctionType::get(T_int32, args_2vals, false), + Function::Create(FunctionType::get(T_int32, args_2vals_tracked, false), Function::ExternalLinkage, "jl_subtype", m); add_named_global(jlsubtype_func, &jl_subtype); + jltypeassert_func = Function::Create(FunctionType::get(T_void, args_2vals_tracked, false), + Function::ExternalLinkage, + "jl_typeassert", m); + add_named_global(jltypeassert_func, &jl_typeassert); + std::vector applytype_args(0); - applytype_args.push_back(T_pjlvalue); - applytype_args.push_back(T_pjlvalue); - applytype_args.push_back(T_ppjlvalue); + applytype_args.push_back(T_prjlvalue); + applytype_args.push_back(T_prjlvalue); + applytype_args.push_back(PointerType::get(T_prjlvalue, AddressSpace::Derived)); jlapplytype_func = Function::Create(FunctionType::get(T_pjlvalue, applytype_args, false), Function::ExternalLinkage, @@ -7048,7 +7147,7 @@ static void init_julia_llvm_env(Module *m) alloc_pool_args.push_back(T_int32); alloc_pool_args.push_back(T_int32); jlalloc_pool_func = - Function::Create(FunctionType::get(T_pjlvalue, alloc_pool_args, false), + Function::Create(FunctionType::get(T_prjlvalue, alloc_pool_args, false), Function::ExternalLinkage, "jl_gc_pool_alloc", m); add_named_global(jlalloc_pool_func, &jl_gc_pool_alloc); @@ -7057,7 +7156,7 @@ static void init_julia_llvm_env(Module *m) alloc_big_args.push_back(T_pint8); alloc_big_args.push_back(T_size); jlalloc_big_func = - Function::Create(FunctionType::get(T_pjlvalue, alloc_big_args, false), + Function::Create(FunctionType::get(T_prjlvalue, alloc_big_args, false), Function::ExternalLinkage, "jl_gc_big_alloc", m); add_named_global(jlalloc_big_func, &jl_gc_big_alloc); @@ -7082,10 +7181,10 @@ static void init_julia_llvm_env(Module *m) add_named_global(jlnewbits_func, &jl_new_bits); std::vector getnthfld_args(0); - getnthfld_args.push_back(T_pjlvalue); + getnthfld_args.push_back(T_prjlvalue); getnthfld_args.push_back(T_size); jlgetnthfieldchecked_func = - Function::Create(FunctionType::get(T_pjlvalue, getnthfld_args, false), + Function::Create(FunctionType::get(T_prjlvalue, getnthfld_args, false), Function::ExternalLinkage, "jl_get_nth_field_checked", m); add_named_global(jlgetnthfieldchecked_func, *jl_get_nth_field_checked); @@ -7097,9 +7196,9 @@ static void init_julia_llvm_env(Module *m) add_named_global(diff_gc_total_bytes_func, *jl_gc_diff_total_bytes); std::vector array_owner_args(0); - array_owner_args.push_back(T_pjlvalue); + array_owner_args.push_back(T_prjlvalue); jlarray_data_owner_func = - Function::Create(FunctionType::get(T_pjlvalue, array_owner_args, false), + Function::Create(FunctionType::get(T_prjlvalue, array_owner_args, false), Function::ExternalLinkage, "jl_array_data_owner", m); jlarray_data_owner_func->setAttributes( @@ -7118,19 +7217,19 @@ static void init_julia_llvm_env(Module *m) add_named_global(jlarray_data_owner_func, jl_array_data_owner); gcroot_func = - Function::Create(FunctionType::get(T_ppjlvalue, false), + Function::Create(FunctionType::get(T_pprjlvalue, false), Function::ExternalLinkage, "julia.gc_root_decl"); add_named_global(gcroot_func, (void*)NULL, /*dllimport*/false); gckill_func = - Function::Create(FunctionType::get(T_void, ArrayRef(T_ppjlvalue), false), + Function::Create(FunctionType::get(T_void, ArrayRef(T_pprjlvalue), false), Function::ExternalLinkage, "julia.gc_root_kill"); add_named_global(gckill_func, (void*)NULL, /*dllimport*/false); jlcall_frame_func = - Function::Create(FunctionType::get(T_ppjlvalue, ArrayRef(T_int32), false), + Function::Create(FunctionType::get(T_pprjlvalue, ArrayRef(T_int32), false), Function::ExternalLinkage, "julia.jlcall_frame_decl"); add_named_global(jlcall_frame_func, (void*)NULL, /*dllimport*/false); @@ -7140,6 +7239,13 @@ static void init_julia_llvm_env(Module *m) "julia.gcroot_flush"); add_named_global(gcroot_flush_func, (void*)NULL, /*dllimport*/false); + pointer_from_objref_func = Function::Create(FunctionType::get(T_pjlvalue, + ArrayRef(PointerType::get(T_jlvalue, AddressSpace::Derived)), false), + Function::ExternalLinkage, + "julia.pointer_from_objref"); + pointer_from_objref_func->addFnAttr(Attribute::ReadNone); + add_named_global(pointer_from_objref_func, (void*)NULL, /*dllimport*/false); + except_enter_func = Function::Create(FunctionType::get(T_int32, false), Function::ExternalLinkage, "julia.except_enter"); @@ -7176,7 +7282,7 @@ static void init_julia_llvm_env(Module *m) #if JL_LLVM_VERSION < 30700 jl_globalPM->add(jl_data_layout); #endif - addOptimizationPasses(jl_globalPM); + addOptimizationPasses(jl_globalPM, jl_options.opt_level); } static inline std::string getNativeTarget() @@ -7510,6 +7616,13 @@ extern "C" void *jl_init_llvm(void) jl_ExecutionEngine->DisableLazyCompilation(); #endif +// Mark our address spaces as non-integral +#if JL_LLVM_VERSION >= 40000 + jl_data_layout = jl_ExecutionEngine->getDataLayout(); + std::string DL = jl_data_layout.getStringRepresentation() + "-ni:10:11:12"; + jl_data_layout.reset(DL); +#endif + // Now that the execution engine exists, initialize all modules jl_setup_module(engine_module); jl_setup_module(m); @@ -7564,6 +7677,14 @@ extern "C" void jl_dump_llvm_value(void *v) ((Value*)v)->dump(); #endif } +extern "C" void jl_dump_llvm_inst_function(void *v) +{ +#if JL_LLVM_VERSION >= 50000 + cast(((Value*)v))->getParent()->getParent()->print(llvm::dbgs(), nullptr, true); +#else + cast(((Value*)v))->getParent()->getParent()->dump(); +#endif +} extern "C" void jl_dump_llvm_type(void *v) { #if JL_LLVM_VERSION >= 50000 diff --git a/src/codegen_internal.h b/src/codegen_internal.h index f2175991f4138..1ee60e0611af4 100644 --- a/src/codegen_internal.h +++ b/src/codegen_internal.h @@ -1,5 +1,7 @@ // This file is a part of Julia. License is MIT: https://julialang.org/license +#include "codegen_shared.h" + #if defined(USE_ORCJIT) && JL_LLVM_VERSION <= 30800 # include void notifyObjectLoaded(RTDyldMemoryManager *memmgr, diff --git a/src/codegen_shared.h b/src/codegen_shared.h new file mode 100644 index 0000000000000..81c3a1f9c906b --- /dev/null +++ b/src/codegen_shared.h @@ -0,0 +1,6 @@ +enum AddressSpace { + Generic = 0, + Tracked = 10, Derived = 11, CalleeRooted = 12, + FirstSpecial = Tracked, + LastSpecial = CalleeRooted, +}; diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index dc1f8ed89f0c0..7211038633620 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -12,22 +12,22 @@ static bool float_func[num_intrinsics]; static void jl_init_intrinsic_functions_codegen(Module *m) { std::vector args1(0); \ - args1.push_back(T_pjlvalue); \ + args1.push_back(T_prjlvalue); \ std::vector args2(0); \ - args2.push_back(T_pjlvalue); \ - args2.push_back(T_pjlvalue); \ + args2.push_back(T_prjlvalue); \ + args2.push_back(T_prjlvalue); \ std::vector args3(0); \ - args3.push_back(T_pjlvalue); \ - args3.push_back(T_pjlvalue); \ - args3.push_back(T_pjlvalue); \ + args3.push_back(T_prjlvalue); \ + args3.push_back(T_prjlvalue); \ + args3.push_back(T_prjlvalue); \ std::vector args4(0); \ - args4.push_back(T_pjlvalue); \ - args4.push_back(T_pjlvalue); \ - args4.push_back(T_pjlvalue); \ - args4.push_back(T_pjlvalue); + args4.push_back(T_prjlvalue); \ + args4.push_back(T_prjlvalue); \ + args4.push_back(T_prjlvalue); \ + args4.push_back(T_prjlvalue); #define ADD_I(name, nargs) do { \ - Function *func = Function::Create(FunctionType::get(T_pjlvalue, args##nargs, false), \ + Function *func = Function::Create(FunctionType::get(T_prjlvalue, args##nargs, false), \ Function::ExternalLinkage, "jl_"#name, m); \ runtime_func[name] = func; \ add_named_global(func, &jl_##name); \ @@ -601,7 +601,7 @@ static jl_cgval_t emit_pointerref(jl_cgval_t *argv, jl_codectx_t *ctx) if (!jl_isbits(ety)) { if (ety == (jl_value_t*)jl_any_type) { - Value *thePtr = emit_unbox(T_ppjlvalue, e, e.typ); + Value *thePtr = emit_unbox(T_pprjlvalue, e, e.typ); return mark_julia_type( builder.CreateAlignedLoad(builder.CreateGEP(thePtr, im1), align_nb), true, @@ -682,7 +682,15 @@ static jl_cgval_t emit_pointerset(jl_cgval_t *argv, jl_codectx_t *ctx) Type *ptrty = julia_type_to_llvm(e.typ, &isboxed); assert(!isboxed); thePtr = emit_unbox(ptrty, e, e.typ); - typed_store(thePtr, im1, x, ety, ctx, tbaa_data, NULL, align_nb); + if (ety == (jl_value_t*)jl_any_type) { + // unsafe_store to Ptr{Any} is allowed to implicitly drop GC roots. + Instruction *store = builder.CreateAlignedStore( + emit_pointer_from_objref(boxed(x, ctx, false)), + builder.CreateGEP(thePtr, im1), align_nb); + tbaa_decorate(tbaa_data, store); + } else { + typed_store(thePtr, im1, x, ety, ctx, tbaa_data, NULL, align_nb); + } } return mark_julia_type(thePtr, false, aty, ctx); } @@ -1212,8 +1220,8 @@ static Value *emit_untyped_intrinsic(intrinsic f, Value **argvalues, size_t narg assert(0 && "unreachable"); } -#define BOX_F(ct,jl_ct) \ - box_##ct##_func = boxfunc_llvm(ft1arg(T_pjlvalue, T_##jl_ct), \ +#define BOX_F(ct,jl_ct) \ + box_##ct##_func = boxfunc_llvm(ft1arg(T_prjlvalue, T_##jl_ct), \ "jl_box_"#ct, &jl_box_##ct, m); #define SBOX_F(ct,jl_ct) BOX_F(ct,jl_ct); box_##ct##_func->addAttribute(1, Attribute::SExt); diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index 08d47d66a4156..2a200ba7215cf 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -109,14 +109,13 @@ void jl_init_jit(Type *T_pjlvalue_) // this defines the set of optimization passes defined for Julia at various optimization levels #if JL_LLVM_VERSION >= 30700 -void addOptimizationPasses(legacy::PassManager *PM) +void addOptimizationPasses(legacy::PassManager *PM, int opt_level) #else -void addOptimizationPasses(PassManager *PM) +void addOptimizationPasses(PassManager *PM, int opt_level) #endif { - PM->add(createLowerExcHandlersPass()); - PM->add(createLowerGCFramePass()); #ifdef JL_DEBUG_BUILD + PM->add(createGCInvariantVerifierPass(true)); PM->add(createVerifierPass()); #endif @@ -130,14 +129,28 @@ void addOptimizationPasses(PassManager *PM) #if defined(JL_MSAN_ENABLED) PM->add(llvm::createMemorySanitizerPass(true)); #endif - if (jl_options.opt_level == 0) { + if (opt_level == 0) { PM->add(createCFGSimplificationPass()); // Clean up disgusting code - PM->add(createMemCpyOptPass()); // Remove memcpy / form memset +#if JL_LLVM_VERSION < 50000 + PM->add(createBarrierNoopPass()); + PM->add(createLowerExcHandlersPass()); + PM->add(createGCInvariantVerifierPass(false)); + PM->add(createLateLowerGCFramePass()); PM->add(createLowerPTLSPass(imaging_mode)); + PM->add(createBarrierNoopPass()); +#endif + PM->add(createMemCpyOptPass()); // Remove memcpy / form memset #if JL_LLVM_VERSION >= 40000 PM->add(createAlwaysInlinerLegacyPass()); // Respect always_inline #else PM->add(createAlwaysInlinerPass()); // Respect always_inline +#endif +#if JL_LLVM_VERSION >= 50000 + PM->add(createBarrierNoopPass()); + PM->add(createLowerExcHandlersPass()); + PM->add(createGCInvariantVerifierPass(false)); + PM->add(createLateLowerGCFramePass()); + PM->add(createLowerPTLSPass(imaging_mode)); #endif return; } @@ -161,6 +174,16 @@ void addOptimizationPasses(PassManager *PM) // list of passes from vmkit PM->add(createCFGSimplificationPass()); // Clean up disgusting code PM->add(createPromoteMemoryToRegisterPass()); // Kill useless allocas + + // Due to bugs and missing features LLVM < 5.0, does not properly propagate + // our invariants. We need to do GC rooting here. This reduces the + // effectiveness of the optimization, but should retain correctness. +#if JL_LLVM_VERSION < 50000 + PM->add(createLowerExcHandlersPass()); + PM->add(createLateLowerGCFramePass()); + PM->add(createLowerPTLSPass(imaging_mode)); +#endif + PM->add(createMemCpyOptPass()); // hopefully these functions (from llvmcall) don't try to interact with the Julia runtime @@ -176,7 +199,6 @@ void addOptimizationPasses(PassManager *PM) #endif // Let the InstCombine pass remove the unnecessary load of // safepoint address first - PM->add(createLowerPTLSPass(imaging_mode)); PM->add(createSROAPass()); // Break up aggregate allocas #ifndef INSTCOMBINE_BUG PM->add(createInstructionCombiningPass()); // Cleanup for scalarrepl. @@ -265,6 +287,16 @@ void addOptimizationPasses(PassManager *PM) PM->add(createInstructionCombiningPass()); // Clean up after SLP loop vectorizer PM->add(createLoopVectorizePass()); // Vectorize loops PM->add(createInstructionCombiningPass()); // Clean up after loop vectorizer +#endif + // LowerPTLS removes an indirect call. As a result, it is likely to trigger + // LLVM's devirtualization heuristics, which would result in the entire + // pass pipeline being re-exectuted. Prevent this by inserting a barrier. +#if JL_LLVM_VERSION >= 50000 + PM->add(createBarrierNoopPass()); + PM->add(createLowerExcHandlersPass()); + PM->add(createGCInvariantVerifierPass(false)); + PM->add(createLateLowerGCFramePass()); + PM->add(createLowerPTLSPass(imaging_mode)); #endif } @@ -490,14 +522,7 @@ JuliaOJIT::JuliaOJIT(TargetMachine &TM) } ) { - if (!jl_generating_output()) { - addOptimizationPasses(&PM); - } - else { - PM.add(createLowerExcHandlersPass()); - PM.add(createLowerGCFramePass()); - PM.add(createLowerPTLSPass(imaging_mode)); - } + addOptimizationPasses(&PM, jl_generating_output() ? 0 : jl_options.opt_level); if (TM.addPassesToEmitMC(PM, Ctx, ObjStream)) llvm_unreachable("Target does not support MC emission."); @@ -1278,7 +1303,7 @@ void jl_dump_native(const char *bc_fname, const char *unopt_bc_fname, const char } if (bc_fname || obj_fname) - addOptimizationPasses(&PM); + addOptimizationPasses(&PM, jl_options.opt_level); if (bc_fname) { #if JL_LLVM_VERSION >= 30500 @@ -1339,7 +1364,11 @@ void jl_dump_native(const char *bc_fname, const char *unopt_bc_fname, const char #if JL_LLVM_VERSION >= 30700 // Reset the target triple to make sure it matches the new target machine clone->setTargetTriple(TM->getTargetTriple().str()); -#if JL_LLVM_VERSION >= 30800 +#if JL_LLVM_VERSION >= 40000 + DataLayout DL = TM->createDataLayout(); + DL.reset(DL.getStringRepresentation() + "-ni:10:11:12"); + clone->setDataLayout(DL); +#elif JL_LLVM_VERSION >= 30800 clone->setDataLayout(TM->createDataLayout()); #else clone->setDataLayout(TM->getDataLayout()->getStringRepresentation()); diff --git a/src/jitlayers.h b/src/jitlayers.h index 972867f0ebda6..42244ddbff4b7 100644 --- a/src/jitlayers.h +++ b/src/jitlayers.h @@ -61,9 +61,9 @@ extern size_t jltls_offset_idx; typedef struct {Value *gv; int32_t index;} jl_value_llvm; // uses 1-based indexing #if JL_LLVM_VERSION >= 30700 -void addOptimizationPasses(legacy::PassManager *PM); +void addOptimizationPasses(legacy::PassManager *PM, int opt_level); #else -void addOptimizationPasses(PassManager *PM); +void addOptimizationPasses(PassManager *PM, int opt_level); #endif void* jl_emit_and_add_to_shadow(GlobalVariable *gv, void *gvarinit = NULL); GlobalVariable *jl_emit_sysimg_slot(Module *m, Type *typ, const char *name, @@ -248,7 +248,9 @@ JL_DLLEXPORT extern LLVMContext &jl_LLVMContext; Pass *createLowerPTLSPass(bool imaging_mode); Pass *createLowerGCFramePass(); +Pass *createLateLowerGCFramePass(); Pass *createLowerExcHandlersPass(); +Pass *createGCInvariantVerifierPass(bool Strong); // Whether the Function is an llvm or julia intrinsic. static inline bool isIntrinsicFunction(Function *F) { diff --git a/src/julia.h b/src/julia.h index 183cfef8ab532..dca92fca16061 100644 --- a/src/julia.h +++ b/src/julia.h @@ -42,13 +42,17 @@ #if defined(__GNUC__) # define JL_NORETURN __attribute__ ((noreturn)) # define JL_CONST_FUNC __attribute__((const)) +# define JL_USED_FUNC __attribute__((used)) #elif defined(_COMPILER_MICROSOFT_) # define JL_NORETURN __declspec(noreturn) // This is the closest I can find for __attribute__((const)) # define JL_CONST_FUNC __declspec(noalias) +// Does MSVC have this? +# define JL_USED_FUNC #else # define JL_NORETURN # define JL_CONST_FUNC +# define JL_USED_FUNC #endif #define container_of(ptr, type, member) \ diff --git a/src/llvm-gc-invariant-verifier.cpp b/src/llvm-gc-invariant-verifier.cpp new file mode 100644 index 0000000000000..c8964440111fc --- /dev/null +++ b/src/llvm-gc-invariant-verifier.cpp @@ -0,0 +1,171 @@ +// This file is a part of Julia. License is MIT: https://julialang.org/license +// This LLVM pass verifier invariants required for correct GC root placement. +// See the devdocs for a description of these invariants. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "llvm-version.h" +#include "codegen_shared.h" +#include "julia.h" + +#define DEBUG_TYPE "verify_gc_invariants" +#undef DEBUG + +using namespace llvm; + +struct GCInvariantVerifier : public FunctionPass, public InstVisitor { + static char ID; + bool Broken = false; + bool Strong; + GCInvariantVerifier(bool Strong = false) : FunctionPass(ID), Strong(Strong) {} + +private: + void Check(bool Cond, const char *message, Value *Val) { + if (!Cond) { + dbgs() << message << "\n\t" << *Val << "\n"; + Broken = true; + } + } + +public: + void getAnalysisUsage(AnalysisUsage &AU) const override { + FunctionPass::getAnalysisUsage(AU); + AU.setPreservesAll(); + } + + bool runOnFunction(Function &F) override; + void visitAddrSpaceCastInst(AddrSpaceCastInst &I); + void visitStoreInst(StoreInst &SI); + void visitLoadInst(LoadInst &LI); + void visitReturnInst(ReturnInst &RI); + void visitGetElementPtrInst(GetElementPtrInst &GEP); + void visitIntToPtrInst(IntToPtrInst &IPI); + void visitPtrToIntInst(PtrToIntInst &PII); +}; + +void GCInvariantVerifier::visitAddrSpaceCastInst(AddrSpaceCastInst &I) { + unsigned FromAS = cast(I.getSrcTy())->getAddressSpace(); + unsigned ToAS = cast(I.getDestTy())->getAddressSpace(); + if (FromAS == 0) + return; + Check(FromAS != AddressSpace::Tracked || + ToAS == AddressSpace::CalleeRooted || + ToAS == AddressSpace::Derived, + "Illegal address space cast from tracked ptr", &I); + Check(FromAS != AddressSpace::CalleeRooted && + FromAS != AddressSpace::Derived, + "Illegal address space cast from decayed ptr", &I); +} + +void GCInvariantVerifier::visitStoreInst(StoreInst &SI) { + Type *VTy = SI.getValueOperand()->getType(); + if (VTy->isPointerTy()) { + /* We currently don't obey this for arguments. That's ok - they're + externally rooted. */ + if (!isa(SI.getValueOperand())) { + unsigned AS = cast(VTy)->getAddressSpace(); + Check(AS != AddressSpace::CalleeRooted && + AS != AddressSpace::Derived, + "Illegal store of decayed value", &SI); + } + } + VTy = SI.getPointerOperand()->getType(); + if (VTy->isPointerTy()) { + unsigned AS = cast(VTy)->getAddressSpace(); + Check(AS != AddressSpace::CalleeRooted, + "Illegal store to callee rooted value", &SI); + } +} + +void GCInvariantVerifier::visitLoadInst(LoadInst &LI) { + Type *Ty = LI.getType(); + if (Ty->isPointerTy()) { + unsigned AS = cast(Ty)->getAddressSpace(); + Check(AS != AddressSpace::CalleeRooted && + AS != AddressSpace::Derived, + "Illegal load of gc relevant value", &LI); + } + Ty = LI.getPointerOperand()->getType(); + if (Ty->isPointerTy()) { + unsigned AS = cast(Ty)->getAddressSpace(); + Check(AS != AddressSpace::CalleeRooted, + "Illegal store of callee rooted value", &LI); + } +} + +static bool isSpecialAS(unsigned AS) { + return AddressSpace::FirstSpecial <= AS && AS <= AddressSpace::LastSpecial; +} + +void GCInvariantVerifier::visitReturnInst(ReturnInst &RI) { + if (!RI.getReturnValue()) + return; + Type *RTy = RI.getReturnValue()->getType(); + if (!RTy->isPointerTy()) + return; + unsigned AS = cast(RTy)->getAddressSpace(); + Check(!isSpecialAS(AS) || AS == AddressSpace::Tracked, + "Only gc tracked values may be directly returned", &RI); +} + +void GCInvariantVerifier::visitGetElementPtrInst(GetElementPtrInst &GEP) { + Type *Ty = GEP.getType(); + if (!Ty->isPointerTy()) + return; + unsigned AS = cast(Ty)->getAddressSpace(); + if (!isSpecialAS(AS)) + return; + /* We're actually ok with GEPs here, as long as they don't feed into any + uses. Upstream is currently still debating whether CAST(GEP) == GEP(CAST), + so though we enforce casting to they decayed as first in the frontend, + the optimizer will introduce the other form. While upstream is debating + what the semantics here are, just check this for things coming from + the frontend */ + if (Strong) { + Check(AS != AddressSpace::Tracked, + "GC tracked values may not appear in GEP expressions." + " You may have to decay the value first", &GEP); + } +} + +/* These next two are caught by the regular verifier on LLVM 5.0+, but we + may want to run this on earlier LLVM versions. */ +void GCInvariantVerifier::visitIntToPtrInst(IntToPtrInst &IPI) { + Check(!isSpecialAS(IPI.getAddressSpace()), + "Illegal inttoptr", &IPI); +} + +void GCInvariantVerifier::visitPtrToIntInst(PtrToIntInst &PII) { + Check(!isSpecialAS(PII.getPointerAddressSpace()), + "Illegal inttoptr", &PII); +} + +bool GCInvariantVerifier::runOnFunction(Function &F) { + visit(F); + if (Broken) { + abort(); + } + return false; +} + +char GCInvariantVerifier::ID = 0; +static RegisterPass X("GCInvariantVerifier", "GC Invariant Verification Pass", false, false); + +Pass *createGCInvariantVerifierPass(bool Strong) { + return new GCInvariantVerifier(Strong); +} diff --git a/src/llvm-gcroot.cpp b/src/llvm-gcroot.cpp index 5f0af51c20f1a..e1e7dfa46823b 100644 --- a/src/llvm-gcroot.cpp +++ b/src/llvm-gcroot.cpp @@ -128,19 +128,19 @@ static void tbaa_decorate_gcframe(Instruction *inst, MDNode *tbaa_gcframe) class JuliaGCAllocator { public: JuliaGCAllocator(Function &F, CallInst *ptlsStates, - Type *T_pjlvalue, MDNode *tbaa) : + Type *T_prjlvalue, MDNode *tbaa) : F(F), M(*F.getParent()), T_int1(Type::getInt1Ty(F.getContext())), T_int8(Type::getInt8Ty(F.getContext())), T_int32(Type::getInt32Ty(F.getContext())), T_int64(Type::getInt64Ty(F.getContext())), - V_null(T_pjlvalue ? Constant::getNullValue(T_pjlvalue) : nullptr), + V_null(T_prjlvalue ? Constant::getNullValue(T_prjlvalue) : nullptr), ptlsStates(ptlsStates), #if JL_LLVM_VERSION >= 50000 - gcframe(ptlsStates ? new AllocaInst(T_pjlvalue, 0, ConstantInt::get(T_int32, 0)) : nullptr), + gcframe(ptlsStates ? new AllocaInst(T_prjlvalue, 0, ConstantInt::get(T_int32, 0)) : nullptr), #else - gcframe(ptlsStates ? new AllocaInst(T_pjlvalue, ConstantInt::get(T_int32, 0)) : nullptr), + gcframe(ptlsStates ? new AllocaInst(T_prjlvalue, ConstantInt::get(T_int32, 0)) : nullptr), #endif gcroot_func(M.getFunction("julia.gc_root_decl")), gckill_func(M.getFunction("julia.gc_root_kill")), diff --git a/src/llvm-late-gc-lowering.cpp b/src/llvm-late-gc-lowering.cpp new file mode 100644 index 0000000000000..ec02ec536f4ac --- /dev/null +++ b/src/llvm-late-gc-lowering.cpp @@ -0,0 +1,1347 @@ +// This file is a part of Julia. License is MIT: https://julialang.org/license + +#include +#include +#include "llvm/Analysis/CFG.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "llvm-version.h" +#include "codegen_shared.h" +#include "julia.h" + +#define DEBUG_TYPE "late_lower_gcroot" + +using namespace llvm; + +/* Julia GC Root Placement pass. For a general overview of the design of GC + root lowering, see the devdocs. This file is the actual implementation. + + The actual algorithm is fairly straightforward. First recall the goal of this + pass: + + Minimize the number of needed gc roots/stores to them subject to the constraint + that at every safepoint, any live gc-tracked pointer (i.e. for which there is + a path after this point that contains a use of this pointer) is in some gc slot. + + In particular, in order to understand this algorithm, it is important to + realize that the only places where rootedness matters is at a safepoint. + + Now, the primary phases of the algorithm are: + + 1. Local Scan + + During this step, each Basic Block is inspected and analyzed for local + properties. In particular, we want to determine the ordering of any of + the following activities: + + - Any Def of a gc-tracked pointer. In general Defs are the results of + calls or loads from appropriate memory locations. Phi nodes and + selects do complicate this story slightly as described below. + - Any use of a gc-tracked or derived pointer. As described in the + devdocs, a use is in general one of + a) a load from a tracked/derived value + b) a store to a tracked/derived value + c) a store OF a tracked/derived value + d) a use of a value as a call operand (including operand bundles) + e) an indirect use through a jlcall array + - Any safepoint + + Crucially, we also perform pointer numbering during the local scan, + assigning every Def a unique integer and caching the integer for each + derived pointer. This allows us to operate only on the set of Defs ( + represented by these integers) for the rest of the algorithm. We also + maintain some local utility information that is needed by later passes + (see the BBState struct for details). + + 2. Dataflow Computation + + This computation operates entirely over the function's control flow graph + and does not look into a basic block. The algorithm is essentially + textbook iterative data flow for liveness computation. However, the + data flow equations are slightly more complicated because we also + forward propagate rootedness information in addition to backproagating + liveness. + + 3. Live Set Computation + + With the liveness information from the previous step, we can now compute, + for every safepoint, the set of values live at that particular safepoint. + There are three pieces of information being combined here: + i. Values that needed to be live due to local analysis (e.g. there + was a def, then a safepoint, then a use). This was computed during + local analysis. + ii. Values that are live across the basic block (i.e. they are live + at every safepoint within the basic block). This relies entirely + on the liveness information. + iii. Values that are now live-out from the basic block (i.e. they are + live at every safepoint following their def). During local + analysis, we keep, for every safepoint, those values that would + be live if they were live out. Here we can check if they are + actually live-out and make the appropriate additions to the live + set. + + Lastly, we also explicitly compute, for each value, the list of values + that are simulataneously live at some safepoint. This is known as an + "interference graph" and is the input to the next step. + + 4. GC Root coloring + + Two values which are not simulataneously live at a safepoint can share the + same slot. This is an important optimization, because otherwise long + functions would have exceptionally large GC slots, reducing performance + and bloating the size of the stack. Assigning values to these slots is, + equivalent to doing graph coloring on the interference graph - the graph + where nodes are values and two values have an edge if they are + simulataneously live at a safepoint - which we computed in the previous + step. Now graph coloring in general is a hard problem. However, for SSA + form programs, (and most programs in general, by virtue of their + structure), the resulting interference graphs are chordal and can be + colored optimally in linear time by performing greedy coloring in a + perfect elimination order. Now, our interference graphs are likely not + entirely chordal due to some non-SSA corner cases. However, using the same + algorithm should still give a very good coloring while having sufficiently + low runtime. + + 5. JLCall frame optimizations + + Unlike earlier iterations of the gc root placement logic, jlcall frames + are no longer treated as a special case and need not necessarily be sunk + into the gc frame. Additionally, the frontend now emits lifetime + intrinsics, so regular stack slot coloring will merge any jlcall frames + not sunk into the gc frame. Nevertheless performing such sinking can still + be profitable. Since all arguments to a jlcall are guaranteed to be live + at that call in some gc slot, we can attempt to rearrange the slots within + the gc-frame, or re-use slots not assigned at that particular location + for the gcframe. However, even without this optimization, stack frames + are at most two times larger than optimal (because regular stack coloring + can merge the jlcall allocas). + + N.B.: This step is not yet implemented. + + 6. Root placement + + This performs the actual insertion of the GCFrame pushes/pops, zeros out + the gc frame and creates the stores to the gc frame according to the + stack slot assignment computed in the previous step. GC frames stores + are generally sunk right before the first safe point that use them + (this is beneficial for code where the primary path does not have + safepoints, but some other path - e.g. the error path does). However, + if the first safepoint is not dominated by the definition (this can + happen due to the non-ssa corner cases), the store is insert right after + the definition. + + 7. Cleanup + + This step performs necessary cleanup before passing the IR to codegen. In + particular, it removes any calls to julia_from_objref intrinsics and + removes the extra operand bundles from ccalls. In the future it could + also strip the addrspace information from all values as this + information is no longer needed. + + + There are a couple important special cases that deserve special attention: + + A. PHIs and Selects + + In general PHIs and selects are treated as separate defs for the purposes + of the algorithm and their operands as uses of those values. It is + important to consider however WHERE the uses of PHI's operands are + located. It is neither at the start of the basic block, because the values + do not dominated the block (so can't really consider them live-in), nor + at the end of the predecessor (because they are actually live out). + Instead it is best to think of those uses as living on the edge between + the appropriate predecessor and the block containing the PHI. + + Another concern is PHIs of derived values. Since we cannot simply root + these values by storing them to a GC slot, we need to insert a new, + artificial PHI that tracks the base pointers for the derived values. E.g. + in: + + A: + %Abase = load addrspace(10) *... + %Aderived = addrspacecast %Abase to addrspace(11) + B: + %Bbase = load addrspace(10) *... + %Bderived = addrspacecast %Bbase to addrspace(11) + C: + %phi = phi [%Aderived, %A + %Bderived, %B] + + we will insert another phi in C to track the relevant base pointers: + + %philift = phi [%Abase, %A + %Bbase, %B] + + We then pretend, for the purposes of numbering that %phi was derived from + %philift. Note that in order to be able to this, we need to be able to + perform this lifting either during numbering or instruction scanning. + + B. Vectors of pointers/Union representations + + Since this pass runs very late in the pass pipeline, it runs after the + various vectorization passes. As a result, we have to potentially deal + with vectors of gc-tracked pointers. For the purposes of most of the + algorithm, we simply assign every element of the vector a separate number + and no changes are needed. However, those parts of the algorithm that + look at IR need to be aware of the possibility of encountering vectors of + pointers. + + Similarly, unions (e.g. in call returns) are represented as a struct of + a gc-tracked value and an argument selector. We simply assign a single + number to this struct and proceed as if it was a single pointer. However, + this again requires care at the IR level. + + C. Non mem2reg'd allocas + + Under some circumstances, allocas will still be present in the IR when + we get to this pass. We don't try very hard to handle this case, and + simply sink the alloca into the GCFrame. +*/ + +struct BBState { + // These do not get updated after local analysis + BitVector Defs; + BitVector PhiOuts; + //// Upward exposed uses that do not have a preceeding safepoint + BitVector UpExposedUsesUnrooted; + //// All other uses + BitVector UpExposedUses; + //// Downward exposed uses that were not followed by a safepoint + BitVector DownExposedUnrooted; + // These get updated during dataflow + BitVector LiveIn; + BitVector LiveOut; + //// Incoming values that are unrooted - these are propagated forward. I.e. + //// they need not necessarily be LiveIn if there are no following uses, + //// but if they are they haven't been rooted yet. + BitVector UnrootedIn; + BitVector UnrootedOut; + std::vector Safepoints; + int TopmostSafepoint = -1; + bool HasSafepoint = false; + // Have we gone through this basic block in our local scan yet? + bool Done = false; +}; + +struct State { + // The maximum assigned value number + int MaxPtrNumber; + // The maximum assigned safepoint number + int MaxSafepointNumber; + // Cache of numbers assigned to IR values. This includes caching of numbers + // for derived values + std::map AllPtrNumbering; + std::map> AllVectorNumbering; + // Numbering of pointers. This only includes Defs + std::map PtrNumbering; + // The reverse of the previous maps + std::map ReversePtrNumbering; + // Neighbors in the coloring interferece graph. I.e. for each value, the + // indicies of other values that are used simulataneously at some safe point. + std::vector> Neighbors; + // The result of the local analysis + std::map BBStates; + + // The assignment of numbers to safepoints. The indicies in the map + // are indices into the next three maps which store safepoint properties + std::map SafepointNumbering; + + // The set of values live at a particular safepoint + std::vector LiveSets; + // The set of values for which this is the first safepoint along some + // relevant path - i.e. the value needs to be rooted at this safepoint + std::vector> Rootings; + // Those values that - if live out from our parent basic block - are live + // at this safepoint. + std::vector> LiveIfLiveOut; + // We don't bother doing liveness on Allocas that were not mem2reg'ed. + // they just get directly sunk into the root array. + std::vector Allocas; + State() : MaxPtrNumber(-1), MaxSafepointNumber(-1) {} +}; + +namespace llvm { + void initializeLateLowerGCFramePass(PassRegistry &Registry); +} + +extern std::pair tbaa_make_child(const char *name, MDNode *parent=nullptr, bool isConstant=false); +struct LateLowerGCFrame: public FunctionPass { + static char ID; + LateLowerGCFrame() : FunctionPass(ID) + { + llvm::initializeDominatorTreeWrapperPassPass(*PassRegistry::getPassRegistry()); + tbaa_gcframe = tbaa_make_child("jtbaa_gcframe").first; + } + +protected: + void getAnalysisUsage(AnalysisUsage &AU) const override { + FunctionPass::getAnalysisUsage(AU); + AU.addRequired(); + AU.addPreserved(); + AU.setPreservesCFG(); + } + +private: + Type *T_prjlvalue; + Type *T_ppjlvalue; + Type *T_size; + Type *T_int32; + MDNode *tbaa_gcframe; + Function *gc_kill_func; + Function *ptls_getter; + Function *gc_flush_func; + Function *pointer_from_objref_func; + CallInst *ptlsStates; + + void MaybeNoteDef(State &S, BBState &BBS, Value *Def, const std::vector &SafepointsSoFar); + void NoteUse(State &S, BBState &BBS, Value *V, BitVector &Uses); + void NoteUse(State &S, BBState &BBS, Value *V) { + NoteUse(S, BBS, V, BBS.UpExposedUses); + } + int LiftPhi(State &S, PHINode *Phi); + int Number(State &S, Value *V); + std::vector NumberVector(State &S, Value *Vec); + void NoteOperandUses(State &S, BBState &BBS, User &UI, BitVector &Uses); + void NoteOperandUses(State &S, BBState &BBS, User &UI){ + NoteOperandUses(S, BBS, UI, BBS.UpExposedUses); + } + State LocalScan(Function &F); + void ComputeLiveness(Function &F, State &S); + void ComputeLiveSets(Function &F, State &S); + void PushGCFrame(AllocaInst *gcframe, unsigned NRoots, Instruction *InsertAfter); + void PopGCFrame(AllocaInst *gcframe, Instruction *InsertBefore); + std::vector ColorRoots(const State &S); + void PlaceRootsAndUpdateCalls(Function &F, std::vector &Colors, State &S, std::map>); + bool doInitialization(Module &M) override; + bool runOnFunction(Function &F) override; + Instruction *get_pgcstack(Instruction *ptlsStates); + bool CleanupIR(Function &F); + void NoteUseChain(State &S, BBState &BBS, User *TheUser); + void MaybeNotePhiJLCallFrameUses(State &S, BBState &BBS, PHINode *Phi); +}; + +static unsigned getValueAddrSpace(Value *V) { + return cast(V->getType())->getAddressSpace(); +} + +static bool isSpecialPtr(Type *Ty) { + PointerType *PTy = dyn_cast(Ty); + if (!PTy) + return false; + unsigned AS = PTy->getAddressSpace(); + return AddressSpace::FirstSpecial <= AS && AS <= AddressSpace::LastSpecial; +} + +static bool isSpecialPtrVec(Type *Ty) { + auto *VTy = dyn_cast(Ty); + if (!VTy) + return false; + return isSpecialPtr(VTy->getElementType()); +} + +static bool isUnionRep(Type *Ty) { + return Ty->isStructTy() && cast(Ty)->getNumElements() == 2 && + isSpecialPtr(cast(Ty)->getTypeAtIndex((unsigned)0)); +} + +static Value *FindBaseValue(const State &S, Value *V, bool UseCache = true) { + Value *CurrentV = V; + while (true) { + if (UseCache) { + if (CurrentV->getType()->isPointerTy()) { + auto it = S.AllPtrNumbering.find(CurrentV); + if (it != S.AllPtrNumbering.end()) + return CurrentV; + } else { + auto it = S.AllVectorNumbering.find(CurrentV); + if (it != S.AllVectorNumbering.end()) + return CurrentV; + } + } + if (isa(CurrentV)) + CurrentV = cast(CurrentV)->getOperand(0); + else if (isa(CurrentV)) { + Value *NewV = cast(CurrentV)->getOperand(0); + if (getValueAddrSpace(NewV) == 0) + break; + CurrentV = NewV; + } + else if (isa(CurrentV)) + CurrentV = cast(CurrentV)->getOperand(0); + else if (isa(CurrentV)) { + Value *Operand = cast(CurrentV)->getOperand(0); + if (!isUnionRep(Operand->getType())) + break; + CurrentV = Operand; + continue; + } else + break; + } + assert(isa(CurrentV) || isa(CurrentV) || + isa(CurrentV) || isa(CurrentV) || + isa(CurrentV) || isa(CurrentV) || + isa(CurrentV) || isa(CurrentV) || + isa(CurrentV)); + return CurrentV; +} + +static Value *MaybeExtractUnion(Value *Val, Instruction *InsertBefore) { + if (isUnionRep(Val->getType())) { + Val = ExtractValueInst::Create(Val, {(unsigned)0}, "", InsertBefore); + } + return Val; +} + +static int LiftSelect(State &S, SelectInst *SI) { + Value *TrueBase = FindBaseValue(S, SI->getTrueValue(), false); + Value *FalseBase = FindBaseValue(S, SI->getFalseValue(), false); + TrueBase = MaybeExtractUnion(TrueBase, SI); + FalseBase = MaybeExtractUnion(FalseBase, SI); + if (getValueAddrSpace(TrueBase) != AddressSpace::Tracked) + TrueBase = ConstantPointerNull::get(cast(FalseBase->getType())); + else if (getValueAddrSpace(FalseBase) != AddressSpace::Tracked) + FalseBase = ConstantPointerNull::get(cast(TrueBase->getType())); + Value *SelectBase = SelectInst::Create(SI->getCondition(), + TrueBase, FalseBase, "gclift", SI); + int Number = ++S.MaxPtrNumber; + S.PtrNumbering[SelectBase] = S.AllPtrNumbering[SelectBase] = + S.AllPtrNumbering[SI] = Number; + S.ReversePtrNumbering[Number] = SelectBase; + return Number; +} + +int LateLowerGCFrame::LiftPhi(State &S, PHINode *Phi) +{ + PHINode *lift = PHINode::Create(T_prjlvalue, Phi->getNumIncomingValues(), "gclift", Phi); + for (unsigned i = 0; i < Phi->getNumIncomingValues(); ++i) { + Value *Incoming = Phi->getIncomingValue(i); + Value *Base = FindBaseValue(S, Incoming, false); + if (getValueAddrSpace(Base) != AddressSpace::Tracked) + Base = ConstantPointerNull::get(cast(T_prjlvalue)); + if (Base->getType() != T_prjlvalue) + Base = new BitCastInst(Base, T_prjlvalue, "", Phi->getIncomingBlock(i)->getTerminator()); + lift->addIncoming(Base, Phi->getIncomingBlock(i)); + } + int Number = ++S.MaxPtrNumber; + S.PtrNumbering[lift] = S.AllPtrNumbering[lift] = + S.AllPtrNumbering[Phi] = Number; + S.ReversePtrNumbering[Number] = lift; + return Number; +} + +int LateLowerGCFrame::Number(State &S, Value *V) { + assert(isSpecialPtr(V->getType()) || isUnionRep(V->getType())); + Value *CurrentV = FindBaseValue(S, V); + auto it = S.AllPtrNumbering.find(CurrentV); + if (it != S.AllPtrNumbering.end()) + return it->second; + int Number; + if (isa(CurrentV) || + ((isa(CurrentV) || isa(CurrentV) || + isa(CurrentV)) && + getValueAddrSpace(CurrentV) != AddressSpace::Tracked)) { + // We know this is rooted in the parent + Number = -1; + } else if (isa(CurrentV) && getValueAddrSpace(CurrentV) != AddressSpace::Tracked) { + int Number = LiftSelect(S, cast(CurrentV)); + S.AllPtrNumbering[V] = Number; + return Number; + } else if (isa(CurrentV) && getValueAddrSpace(CurrentV) != AddressSpace::Tracked) { + int Number = LiftPhi(S, cast(CurrentV)); + S.AllPtrNumbering[V] = Number; + return Number; + } else if (isa(CurrentV) && !isUnionRep(CurrentV->getType())) { + assert(false && "TODO: Extract"); + abort(); + } else { + assert( + (CurrentV->getType()->isPointerTy() && + getValueAddrSpace(CurrentV) == AddressSpace::Tracked) || + isUnionRep(CurrentV->getType())); + Number = ++S.MaxPtrNumber; + S.ReversePtrNumbering[Number] = CurrentV; + } + S.PtrNumbering[CurrentV] = S.AllPtrNumbering[CurrentV] = S.AllPtrNumbering[V] = Number; + return Number; +} + +std::vector LateLowerGCFrame::NumberVector(State &S, Value *V) { + auto it = S.AllVectorNumbering.find(V); + if (it != S.AllVectorNumbering.end()) + return it->second; + Value *CurrentV = FindBaseValue(S, V); + it = S.AllVectorNumbering.find(CurrentV); + if (it != S.AllVectorNumbering.end()) + return it->second; + if (isa(CurrentV) || + ((isa(CurrentV) || isa(CurrentV) || + isa(CurrentV)) && + getValueAddrSpace(CurrentV) != AddressSpace::Tracked)) { + S.AllVectorNumbering[V] = std::vector{}; + } + /* We (the frontend) don't insert either of these, but it would be legal - + though a bit strange, considering they're pointers) for the optimizer to + do so. All that's needed here is to NumberVector the previous vector/value + and lift the operation */ + else if (isa(CurrentV)) { + assert(false && "TODO Shuffle"); + } else if (isa(CurrentV)) { + assert(false && "TODO Insert"); + } else if (isa(CurrentV)) { + // This is simple, we can just number them sequentially + std::vector Numbers; + for (unsigned i = 0; i < cast(CurrentV->getType())->getNumElements(); ++i) { + int Num = ++S.MaxPtrNumber; + Numbers.push_back(Num); + S.ReversePtrNumbering[Num] = V; + } + S.AllVectorNumbering[V] = Numbers; + } + return S.AllVectorNumbering[CurrentV]; +} + +static void MaybeResize(BBState &BBS, unsigned Idx) { + if (BBS.Defs.size() <= Idx) { + BBS.Defs.resize(Idx + 1); + BBS.UpExposedUses.resize(Idx + 1); + BBS.UpExposedUsesUnrooted.resize(Idx + 1); + BBS.DownExposedUnrooted.resize(Idx + 1); + BBS.PhiOuts.resize(Idx + 1); + } +} + +static bool HasBitSet(const BitVector &BV, unsigned Bit) { + return Bit < BV.size() && BV[Bit]; +} + +static void NoteDef(State &S, BBState &BBS, int Num, const std::vector &SafepointsSoFar) { + assert(Num != -1); + MaybeResize(BBS, Num); + assert(BBS.Defs[Num] == 0 && "SSA Violation or misnumbering?"); + BBS.Defs[Num] = 1; + BBS.UpExposedUses[Num] = 0; + BBS.UpExposedUsesUnrooted[Num] = 0; + if (!BBS.HasSafepoint) + BBS.DownExposedUnrooted[Num] = 1; + else if (HasBitSet(S.LiveSets[BBS.TopmostSafepoint], Num)) { + S.Rootings[BBS.TopmostSafepoint].insert(Num); + } + // This value could potentially be live at any following safe point + // if it ends up live out, so add it to the LiveIfLiveOut lists for all + // following safepoints. + for (int Safepoint : SafepointsSoFar) { + S.LiveIfLiveOut[Safepoint].push_back(Num); + } +} + +void LateLowerGCFrame::MaybeNoteDef(State &S, BBState &BBS, Value *Def, const std::vector &SafepointsSoFar) { + int Num = -1; + Type *RT = Def->getType(); + if (isSpecialPtr(RT)) { + assert(getValueAddrSpace(Def) == AddressSpace::Tracked && + "Returned value of GC interest, but not tracked?"); + Num = Number(S, Def); + } + else if (isUnionRep(RT)) { + // Probably a union return. Find the extractvalue + Num = Number(S, Def); + } + else if (isSpecialPtrVec(RT)) { + std::vector Nums = NumberVector(S, Def); + for (int Num : Nums) { + NoteDef(S, BBS, Num, SafepointsSoFar); + } + return; + } + else { + return; + } + NoteDef(S, BBS, Num, SafepointsSoFar); +} + +static int NoteSafepoint(State &S, BBState &BBS, CallInst *CI) { + int Number = ++S.MaxSafepointNumber; + S.SafepointNumbering[CI] = Number; + // Note which pointers are upward exposed live here. They need to be + // considered live at this safepoint even when they have a def earlier + // in this BB (i.e. even when they don't participate in the dataflow + // computation) + BBS.UpExposedUses |= BBS.UpExposedUsesUnrooted; + BBS.UpExposedUsesUnrooted.reset(); + S.LiveSets.push_back(BBS.UpExposedUses); + S.Rootings.push_back(std::set{}); + S.LiveIfLiveOut.push_back(std::vector{}); + return Number; +} + +void LateLowerGCFrame::NoteUse(State &S, BBState &BBS, Value *V, BitVector &Uses) { + // Short circuit to have to avoid dealing specially with vectors of + // constants, etc. + if (isa(V)) + return; + else if (isSpecialPtrVec(V->getType())) { + std::vector Nums = NumberVector(S, V); + for (int Num : Nums) { + MaybeResize(BBS, Num); + Uses[Num] = 1; + } + } + else { + int Num = Number(S, V); + if (Num == -1) + return; + MaybeResize(BBS, Num); + Uses[Num] = 1; + } +} + +void LateLowerGCFrame::NoteOperandUses(State &S, BBState &BBS, User &UI, BitVector &Uses) { + for (Use &U : UI.operands()) { + Value *V = U; + if (!isSpecialPtr(V->getType())) + continue; + NoteUse(S, BBS, V, Uses); + } +} + +template +void RecursivelyVisit(callback f, Value *V) { + for (Use &VU : V->uses()) { + User *TheUser = VU.getUser(); + if (isa(TheUser)) + f(VU); + if (isa(TheUser) || isa(TheUser) || + isa(TheUser) || isa(TheUser) || + isa(TheUser)) + continue; + if (isa(TheUser) || isa(TheUser) || isa(TheUser)) { + RecursivelyVisit(f, TheUser); + continue; + } + V->dump(); + TheUser->dump(); + assert(false && "Unexpected instruction"); + } +} + +template +void RecursivelyVisitStoresTo(callback f, Value *V) { + RecursivelyVisit( + [&](Use &VU) { + assert(isa(VU.getUser())); + if (VU.getOperandNo() != 1) { + // We spill jlcall arg arrays to the stack for + // better debugging. These have no uses, so we're + // ok. Allow that as a special case. + assert(cast(VU.getUser())->getPointerOperand()->getNumUses() == 1); + return; + } + f(cast(VU.getUser())); + }, V); +} + +/* + * Mark phi uses in jlcall frames. Note this does not do any sort of phi lifting + * which is done only if a phi actually ends up getting used somewhere. + */ +void LateLowerGCFrame::MaybeNotePhiJLCallFrameUses(State &S, BBState &BBS, PHINode *Phi) +{ + if (!Phi->getType()->isPointerTy()) + return; + Type *ElType = cast(Phi->getType())->getElementType(); + if (isSpecialPtr(ElType) && cast(ElType)->getAddressSpace() == AddressSpace::Tracked) { + for (unsigned i = 0; i < Phi->getNumIncomingValues(); ++i) { + RecursivelyVisitStoresTo([&](StoreInst *SI){ + BBState &IncombingBBS = S.BBStates[Phi->getIncomingBlock(i)]; + NoteUse(S, IncombingBBS, SI->getValueOperand(), IncombingBBS.PhiOuts); + }, Phi->getIncomingValue(i)); + } + } +} + +static void dumpBitVectorValues(State &S, BitVector &BV) { + bool first = true; + for (int Idx = BV.find_first(); Idx >= 0; Idx = BV.find_next(Idx)) { + if (!first) + dbgs() << ", "; + first = false; + S.ReversePtrNumbering[Idx]->printAsOperand(dbgs()); + } +} + +/* Debugging utility to dump liveness information */ +JL_USED_FUNC static void dumpLivenessState(Function &F, State &S) { + for (auto &BB : F) { + dbgs() << "Liveness analysis for BB " << BB.getName(); + dbgs() << "\n\tDefs: "; + dumpBitVectorValues(S, S.BBStates[&BB].Defs); + dbgs() << "\n\tPhiOuts: "; + dumpBitVectorValues(S, S.BBStates[&BB].PhiOuts); + dbgs() << "\n\tUpExposedUsesUnrooted: "; + dumpBitVectorValues(S, S.BBStates[&BB].UpExposedUsesUnrooted); + dbgs() << "\n\tUpExposedUses: "; + dumpBitVectorValues(S, S.BBStates[&BB].UpExposedUses); + dbgs() << "\n\tDownExposedUnrooted: "; + dumpBitVectorValues(S, S.BBStates[&BB].DownExposedUnrooted); + dbgs() << "\n\tLiveIn: "; + dumpBitVectorValues(S, S.BBStates[&BB].LiveIn); + dbgs() << "\n\tLiveOut: "; + dumpBitVectorValues(S, S.BBStates[&BB].LiveOut); + dbgs() << "\n\tUnrootedIn: "; + dumpBitVectorValues(S, S.BBStates[&BB].UnrootedIn); + dbgs() << "\n\tUnrootedOut: "; + dumpBitVectorValues(S, S.BBStates[&BB].UnrootedOut); + dbgs() << "\n"; + } +} + +static std::set DominatingLifetimes(DominatorTree &DT, Instruction *I, Value *V) { + // Find all lifetime starts that dominate this call + // instruction. + std::set Dead; + std::set LifeTimeStarts; + // This could be combined with the visit in the caller or even cached + // Don't bother with the additional complexity for now. + RecursivelyVisit([&](Use &VU) { + IntrinsicInst *II = cast(VU.getUser()); + if (II->getIntrinsicID() == Intrinsic::lifetime_start && + DT.dominates(II, I)) { + LifeTimeStarts.insert(II); + } + }, V); + // If one lifetime start dominates another, we can + // remove the earlier one. + for (auto *LifetimeStart : LifeTimeStarts) { + for (auto *LifetimeStart2 : LifeTimeStarts) { + if (LifetimeStart == LifetimeStart2 || + Dead.find(LifetimeStart2) != Dead.end()) + continue; + if (DT.dominates(LifetimeStart, LifetimeStart2)) { + Dead.insert(LifetimeStart); + } + } + } + for (auto *ToDelete : Dead) + LifeTimeStarts.erase(ToDelete); + return LifeTimeStarts; +} + +State LateLowerGCFrame::LocalScan(Function &F) { + State S; + auto &DT = getAnalysis().getDomTree(); + for (BasicBlock &BB : F) { + BBState &BBS = S.BBStates[&BB]; + for (auto it = BB.rbegin(); it != BB.rend(); ++it) { + Instruction &I = *it; + if (CallInst *CI = dyn_cast(&I)) { + if (isa(CI)) { + // Intrinsics are never GC uses/defs + continue; + } + MaybeNoteDef(S, BBS, CI, BBS.Safepoints); + NoteOperandUses(S, BBS, I); + // Note uses via jlcall frames + for (Use &U : CI->operands()) { + Value *V = U; + if (isUnionRep(V->getType())) { + NoteUse(S, BBS, V); + continue; + } + if (!V->getType()->isPointerTy()) + continue; + if (isSpecialPtr(cast(V->getType())->getElementType())) { + V = FindBaseValue(S, V, false); + if (AllocaInst *AI = dyn_cast(V)) { + // This was sunk into the gc frame anyway - nothing + // to do. + if (isSpecialPtr(AI->getAllocatedType()) && !AI->isArrayAllocation()) + continue; + } + if (isa(V) || isa(V)) + continue; + if (PHINode *Phi = dyn_cast(V)) { + // Find the set of values that could potentially be + // referenced here. We marks uses for all of them + // that are fully available and create a splitting + // phi for those that are not. Note we may be + // keeping more values alive than we need to, but + // this situation is a bit of a marginal case. + std::set PotentialUses; + for (unsigned i = 0; i < cast(V)->getNumIncomingValues(); ++i) { + RecursivelyVisitStoresTo([&](StoreInst *SI){ + PotentialUses.insert(SI->getValueOperand()); + }, Phi->getIncomingValue(i)); + } + for (Value *Val : PotentialUses) { + if (isa(Val) || isa(Val) || + DT.dominates(cast(Val), Phi)) + NoteUse(S, BBS, Val); + else { + PHINode *Lift = PHINode::Create(T_prjlvalue, 0, "partiallift", Phi); + for (unsigned i = 0; i < Phi->getNumIncomingValues(); ++i) { + BasicBlock *IncomingBB = Phi->getIncomingBlock(i); + if (DT.dominates(cast(Val), IncomingBB->getTerminator())) { + Lift->addIncoming(Val, IncomingBB); + NoteUse(S, S.BBStates[IncomingBB], Val, S.BBStates[IncomingBB].PhiOuts); + } else { + Lift->addIncoming(ConstantPointerNull::get(cast(T_prjlvalue)), IncomingBB); + } + } + NoteUse(S, BBS, Lift); + BBState &LiftBBS = S.BBStates[Phi->getParent()]; + if (LiftBBS.Done) { + // This is ok to do if we already processed that + // basic block (up to phis), because we inserted it at the start + // of the basic block, so we're not violating any + // ordering constraints. + MaybeNoteDef(S, LiftBBS, Lift, LiftBBS.Safepoints); + } + } + } + continue; + } + // Sometimes we load an arg array from a global. That's + // fine as long as we don't store to it. + if (isa(V)) { + RecursivelyVisitStoresTo([&](StoreInst *SI){ + assert(false && "Shouldn't try to store to a global arg array"); + }, V); + continue; + } + std::set LifeTimeStarts = DominatingLifetimes(DT, CI, V); + + assert(isa(V) || isa(V) || isa(V)); + RecursivelyVisitStoresTo([&](StoreInst *SI){ + bool AnyDominates = LifeTimeStarts.empty(); + for (auto *Lifetime : LifeTimeStarts) { + if (DT.dominates(Lifetime, SI)) + AnyDominates = true; + } + if (AnyDominates) + NoteUse(S, BBS, SI->getValueOperand()); + }, V); + + continue; + } + } + int SafepointNumber = NoteSafepoint(S, BBS, CI); + BBS.HasSafepoint = true; + BBS.TopmostSafepoint = SafepointNumber; + BBS.Safepoints.push_back(SafepointNumber); + } else if (LoadInst *LI = dyn_cast(&I)) { + // Allocas get sunk into the gc frame, so don't generate defs + MaybeNoteDef(S, BBS, LI, BBS.Safepoints); + NoteOperandUses(S, BBS, I, BBS.UpExposedUsesUnrooted); + } else if (SelectInst *SI = dyn_cast(&I)) { + // We need to insert an extra select for the GC root + if (!isSpecialPtr(SI->getType())) + continue; + if (getValueAddrSpace(SI) != AddressSpace::Tracked) { + if (S.AllPtrNumbering.find(SI) != S.AllPtrNumbering.end()) + continue; + LiftSelect(S, SI); + } else { + MaybeNoteDef(S, BBS, SI, BBS.Safepoints); + NoteOperandUses(S, BBS, I, BBS.UpExposedUsesUnrooted); + } + } else if (PHINode *Phi = dyn_cast(&I)) { + // We can have phis of jlcall frames. We consider each of the + // values stored to that jlcall frame a phi use + if (!isSpecialPtr(Phi->getType())) { + MaybeNotePhiJLCallFrameUses(S, BBS, Phi); + continue; + } + // We need to insert an extra phi for the GC root + if (getValueAddrSpace(Phi) != AddressSpace::Tracked) { + if (S.AllPtrNumbering.find(Phi) != S.AllPtrNumbering.end()) + continue; + LiftPhi(S, Phi); + } else { + MaybeNoteDef(S, BBS, Phi, BBS.Safepoints); + for (unsigned i = 0; i < Phi->getNumIncomingValues(); ++i) { + BBState &IncombingBBS = S.BBStates[Phi->getIncomingBlock(i)]; + NoteUse(S, IncombingBBS, Phi->getIncomingValue(i), IncombingBBS.PhiOuts); + } + } + } else if (isa(&I) || isa(&I)) { + NoteOperandUses(S, BBS, I, BBS.UpExposedUsesUnrooted); + } else if (auto *ASCI = dyn_cast(&I)) { + if (getValueAddrSpace(ASCI) == AddressSpace::Tracked) + MaybeNoteDef(S, BBS, ASCI, BBS.Safepoints); + } else if (auto *AI = dyn_cast(&I)) { + if (isSpecialPtr(AI->getAllocatedType()) && !AI->isArrayAllocation() && + cast(AI->getAllocatedType())->getAddressSpace() == AddressSpace::Tracked) + { + S.Allocas.push_back(AI); + } + } + } + // Pre-seed the dataflow variables; + BBS.LiveIn = BBS.UpExposedUses; + BBS.LiveIn |= BBS.UpExposedUsesUnrooted; + BBS.UnrootedOut = BBS.DownExposedUnrooted; + BBS.Done = true; + } + return S; +} + +/* + * DataFlow equations: + * LiveIn[BB] = UpExposedUses[BB] ∪ (LiveOut[BB] - Defs[BB]) + * LiveOut[BB] = PhiUses[BB] ∪ ∪_{Succ} LiveIn[Succ] + * UnrootedOut[BB] = DownExposedUnrooted[BB] ∪ (HasSafepoint ? {} : UnrootedIn[BB]) + * UnrootedIn[BB] = ∪_{Pred} UnrootedOut[Pred] + * + * We'll perform textbook iterative dataflow to compute this. There are better + * algorithms. If this starts becoming a problem, we should use one of them. + */ +void LateLowerGCFrame::ComputeLiveness(Function &F, State &S) { + bool Converged = false; + /* Liveness is a reverse problem. Our problem is slightly more general, + * because the Unrooted* variables are forward problems. Nevertheless, + * we use reverse postorder in an attempt to speed convergence of the Live* + * variables, in anticipation of the live ranges being larger than the + * unrooted ranges (since those terminate at any safe point). + */ + ReversePostOrderTraversal RPOT(&F); + while (!Converged) { + bool AnyChanged = false; + for (BasicBlock *BB : RPOT) { + // This could all be done more efficiently, by only updating what + // changed - Let's get it working first though. + BBState &BBS = S.BBStates[BB]; + BitVector NewLiveOut = BBS.PhiOuts; + for (BasicBlock *Succ : successors(BB)) { + NewLiveOut |= S.BBStates[Succ].LiveIn; + } + if (NewLiveOut != BBS.LiveOut) { + AnyChanged = true; + BBS.LiveOut = NewLiveOut; + MaybeResize(BBS, BBS.LiveOut.size() - 1); + } + BitVector NewLiveIn = BBS.LiveOut; + BitVector FlippedDefs = BBS.Defs; + FlippedDefs.flip(); + NewLiveIn &= FlippedDefs; + NewLiveIn |= BBS.UpExposedUses; + NewLiveIn |= BBS.UpExposedUsesUnrooted; + if (NewLiveIn != BBS.LiveIn) { + AnyChanged = true; + BBS.LiveIn = NewLiveIn; + } + BitVector NewUnrootedIn; + for (BasicBlock *Pred : predecessors(BB)) + NewUnrootedIn |= S.BBStates[Pred].UnrootedOut; + if (NewUnrootedIn != BBS.UnrootedIn) { + AnyChanged = true; + BBS.UnrootedIn = NewUnrootedIn; + if (!BBS.HasSafepoint) { + BBS.UnrootedOut |= BBS.UnrootedIn; + } + } + } + Converged = !AnyChanged; + } + ComputeLiveSets(F, S); +} + +void LateLowerGCFrame::ComputeLiveSets(Function &F, State &S) { + // Iterate over all safe points. Add to live sets all those variables that + // are now live across their parent block. + for (auto it : S.SafepointNumbering) { + int idx = it.second; + Instruction *Safepoint = it.first; + BasicBlock *BB = Safepoint->getParent(); + BBState &BBS = S.BBStates[BB]; + BitVector LiveAcross = BBS.LiveIn; + LiveAcross &= BBS.LiveOut; + S.LiveSets[idx] |= LiveAcross; + for (int Live : S.LiveIfLiveOut[idx]) { + if (HasBitSet(BBS.LiveOut, Live)) + S.LiveSets[idx][Live] = 1; + } + } + // Compute the inference graph + for (int i = 0; i <= S.MaxPtrNumber; ++i) { + std::vector Neighbors; + for (auto it : S.SafepointNumbering) { + const BitVector &LS = S.LiveSets[it.second]; + if ((unsigned)i >= LS.size() || !LS[i]) + continue; + for (int Idx = LS.find_first(); Idx >= 0; Idx = LS.find_next(Idx)) { + if (Idx == i) + continue; + Neighbors.push_back(Idx); + } + } + S.Neighbors.push_back(Neighbors); + } + // Compute Rooting Locations + for (auto &BB : F) { + BBState &BBS = S.BBStates[&BB]; + if (BBS.HasSafepoint) { + BitVector UnrootedIn = BBS.UnrootedIn; + // Only those values that have uses after a safepoint or are live + // across need to be rooted. N.B. We're explicitly not or-ing in + // UpExposedUsesUnrooted + BitVector Mask = BBS.UpExposedUses; + Mask |= BBS.LiveOut; + Mask &= BBS.LiveIn; + UnrootedIn &= Mask; + for (int Idx = UnrootedIn.find_first(); Idx >= 0; Idx = UnrootedIn.find_next(Idx)) { + S.Rootings[BBS.TopmostSafepoint].insert(Idx); + } + // Backfill any interior rootings + BitVector Interior = BBS.UnrootedOut; + Interior.flip(); + Interior &= BBS.LiveOut; + Interior &= BBS.Defs; + for (int Idx = Interior.find_first(); Idx >= 0; Idx = Interior.find_next(Idx)) { + // Needs to be rooted at the first safepoint after the def + Instruction *Def = cast(S.ReversePtrNumbering[Idx]); + auto it = ++BasicBlock::iterator(Def); + while (true) { + auto sit = S.SafepointNumbering.find(&*it++); + if (sit != S.SafepointNumbering.end()) { + S.Rootings[sit->second].insert(Idx); + break; + } + assert(it != Def->getParent()->end()); + } + } + } + } +} + +/* For chordal interference graphs, this class gives the verticies in a (reverse + * - depending on definition) perfect elimination ordering, in such a way that + * greedy coloring gives an optimal coloring. Since our roots are in SSA form, + * the interference should be chordal. + */ +struct PEOIterator { + struct Element { + unsigned weight; + unsigned pos; + }; + std::vector Elements; + std::vector> Levels; + const std::vector> &Neighbors; + PEOIterator(const std::vector> &Neighbors) : Neighbors(Neighbors) { + // Initialize State + std::vector FirstLevel; + for (unsigned i = 0; i < Neighbors.size(); ++i) { + FirstLevel.push_back(i); + Element E{0, i}; + Elements.push_back(E); + } + Levels.push_back(FirstLevel); + } + int next() { + // Find the element in the highest bucket + int NextElement = -1; + while (NextElement == -1 && !Levels.empty()) { + std::vector &LastLevel = Levels.back(); + while (NextElement == -1 && !LastLevel.empty()) { + NextElement = LastLevel.back(); + LastLevel.pop_back(); + } + if (LastLevel.empty()) + Levels.pop_back(); + } + if (NextElement == -1) + return NextElement; + // Make sure not to try to re-use this later. + Elements[NextElement].weight = (unsigned)-1; + // Raise neighbors + for (int Neighbor : Neighbors[NextElement]) { + Element &NElement = Elements[Neighbor]; + // Already processed. Don't re-enqueue + if (NElement.weight == (unsigned)-1) + continue; + // Kill old queue position + Levels[NElement.weight][NElement.pos] = -1; + // Raise the neighbor to the next level. + NElement.weight += 1; + if (NElement.weight >= Levels.size()) + Levels.push_back(std::vector{}); + Levels[NElement.weight].push_back(Neighbor); + NElement.pos = Levels[NElement.weight].size()-1; + } + // As an enhancement, we might want to periodically compactify the whole + // data structure. This could be done here. + return NextElement; + } +}; + +std::vector LateLowerGCFrame::ColorRoots(const State &S) { + std::vector Colors; + Colors.resize(S.MaxPtrNumber + 1, -1); + PEOIterator Ordering(S.Neighbors); + /* Greedy coloring */ + int ActiveElement = 1; + int MaxAssignedColor = -1; + BitVector UsedColors; + while ((ActiveElement = Ordering.next()) != -1) { + assert(Colors[ActiveElement] == -1); + UsedColors.resize(MaxAssignedColor + 2, false); + UsedColors.reset(); + for (int Neighbor : S.Neighbors[ActiveElement]) { + if (Colors[Neighbor] == -1) + continue; + UsedColors[Colors[Neighbor]] = 1; + } + Colors[ActiveElement] = UsedColors.flip().find_first(); + if (Colors[ActiveElement] > MaxAssignedColor) + MaxAssignedColor = Colors[ActiveElement]; + } + return Colors; +} + +Instruction *LateLowerGCFrame::get_pgcstack(Instruction *ptlsStates) +{ + Constant *offset = ConstantInt::getSigned(T_int32, offsetof(jl_tls_states_t, pgcstack) / sizeof(void*)); + return GetElementPtrInst::Create(nullptr, + ptlsStates, + ArrayRef(offset), + "jl_pgcstack"); +} + +void LateLowerGCFrame::PushGCFrame(AllocaInst *gcframe, unsigned NRoots, Instruction *InsertAfter) { + IRBuilder<> builder(gcframe->getContext()); + builder.SetInsertPoint(&*(++BasicBlock::iterator(InsertAfter))); + Instruction *inst = + builder.CreateStore(ConstantInt::get(T_size, NRoots << 1), + builder.CreateBitCast(builder.CreateConstGEP1_32(gcframe, 0), T_size->getPointerTo())); + inst->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_gcframe); + Value *pgcstack = builder.Insert(get_pgcstack(ptlsStates)); + inst = builder.CreateStore(builder.CreateLoad(pgcstack), + builder.CreatePointerCast(builder.CreateConstGEP1_32(gcframe, 1), PointerType::get(T_ppjlvalue,0))); + inst->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_gcframe); + builder.CreateStore(gcframe, builder.CreateBitCast(pgcstack, + PointerType::get(PointerType::get(T_prjlvalue, 0), 0))); +} + +void LateLowerGCFrame::PopGCFrame(AllocaInst *gcframe, Instruction *InsertBefore) { + IRBuilder<> builder(InsertBefore->getContext()); + builder.SetInsertPoint(InsertBefore); // set insert *before* Ret + Instruction *gcpop = + (Instruction*)builder.CreateConstGEP1_32(gcframe, 1); + Instruction *inst = builder.CreateLoad(gcpop); + inst->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_gcframe); + inst = builder.CreateStore(inst, + builder.CreateBitCast( + builder.Insert(get_pgcstack(ptlsStates)), + PointerType::get(T_prjlvalue, 0))); + inst->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_gcframe); +} + +bool LateLowerGCFrame::CleanupIR(Function &F) { + bool ChangesMade = false; + for (BasicBlock &BB : F) { + for (auto it = BB.begin(); it != BB.end();) { + auto *CI = dyn_cast(&*it); + if (!CI) { + ++it; + continue; + } + if ((gc_kill_func != nullptr && CI->getCalledFunction() == gc_kill_func) || + (gc_flush_func != nullptr && CI->getCalledFunction() == gc_flush_func)) { + /* No replacement */ + } else if (pointer_from_objref_func != nullptr && + CI->getCalledFunction() == pointer_from_objref_func) { + auto *ASCI = new AddrSpaceCastInst(CI->getOperand(0), + CI->getType(), "", CI); + ASCI->takeName(CI); + CI->replaceAllUsesWith(ASCI); + } else if (CI->getNumArgOperands() == CI->getNumOperands()) { + /* No operand bundle to lower */ + ++it; + continue; + } else { + CallInst *NewCall = CallInst::Create(CI, None, CI); + NewCall->takeName(CI); + CI->replaceAllUsesWith(NewCall); + } + it = CI->eraseFromParent(); + ChangesMade = true; + } + } + return ChangesMade; +} + +static Value *GetPtrForNumber(State &S, unsigned Num, Instruction *InsertionPoint) +{ + Value *Val = S.ReversePtrNumbering[Num]; + if (isSpecialPtrVec(Val->getType())) { + const std::vector &AllNums = S.AllVectorNumbering[Val]; + unsigned Idx = 0; + for (; Idx < AllNums.size(); ++Idx) { + if ((unsigned)AllNums[Idx] == Num) + break; + } + Val = ExtractElementInst::Create(Val, ConstantInt::get( + Type::getInt32Ty(Val->getContext()), Idx), "", InsertionPoint); + } + return Val; +} + +void LateLowerGCFrame::PlaceRootsAndUpdateCalls(Function &F, std::vector &Colors, State &S, std::map>) { + auto &DT = getAnalysis().getDomTree(); + int MaxColor = -1; + for (auto C : Colors) + if (C > MaxColor) + MaxColor = C; + // Insert instructions for the actual gc frame + if (MaxColor != -1 || S.Allocas.size() != 0) { + unsigned NRoots = MaxColor + 1 + S.Allocas.size(); + // Create GC Frame + AllocaInst *gcframe = new AllocaInst(T_prjlvalue, +#if JL_LLVM_VERSION >= 50000 + 0, +#endif + ConstantInt::get(T_int32, NRoots+2), "gcframe"); + gcframe->insertBefore(&*F.getEntryBlock().begin()); + // Zero out gcframe + BitCastInst *tempSlot_i8 = new BitCastInst(gcframe, Type::getInt8PtrTy(F.getContext()), ""); + tempSlot_i8->insertAfter(gcframe); + Type *argsT[2] = {tempSlot_i8->getType(), T_int32}; + Function *memset = Intrinsic::getDeclaration(F.getParent(), Intrinsic::memset, makeArrayRef(argsT)); + Value *args[5] = { + tempSlot_i8, // dest + ConstantInt::get(Type::getInt8Ty(F.getContext()), 0), // val + ConstantInt::get(T_int32, sizeof(jl_value_t*)*(NRoots+2)), // len + ConstantInt::get(T_int32, 0), // align + ConstantInt::get(Type::getInt1Ty(F.getContext()), 0)}; // volatile + CallInst *zeroing = CallInst::Create(memset, makeArrayRef(args)); + zeroing->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_gcframe); + zeroing->insertAfter(tempSlot_i8); + // Push GC Frame + PushGCFrame(gcframe, NRoots, ptlsStates); + // Replace Allocas + unsigned AllocaSlot = 2; + for (AllocaInst *AI : S.Allocas) { + Value *args[1] = { + ConstantInt::get(T_int32, AllocaSlot++) + }; + GetElementPtrInst *gep = GetElementPtrInst::Create(T_prjlvalue, gcframe, makeArrayRef(args)); + gep->insertAfter(gcframe); + gep->takeName(AI); + // Check for lifetime intrinsics on this alloca, we can't keep them + // because we're changing the semantics + std::vector ToDelete; + RecursivelyVisit([&](Use &VU) { + IntrinsicInst *II = cast(VU.getUser()); + if ((II->getIntrinsicID() != Intrinsic::lifetime_start && + II->getIntrinsicID() != Intrinsic::lifetime_end)) + return; + ToDelete.push_back(II); + }, AI); + for (CallInst *II : ToDelete) + II->eraseFromParent(); + AI->replaceAllUsesWith(gep); + AI->eraseFromParent(); + } + unsigned MinColorRoot = AllocaSlot; + // Insert GC frame stores + for (auto it : S.SafepointNumbering) { + const std::set &Rooting = S.Rootings[it.second]; + for (int R : Rooting) { + if (Colors[R] != -1) { + Instruction *InsertionPoint = it.first; + Value *Val = S.ReversePtrNumbering[R]; + /* + * Generally we like doing the rooting late, because it lets + * us avoid doing so on paths that have no safe points. + * However, it is possible for the first safepoint to not + * be dominated by the definition. In that case, just start + * rooting it right after the definition. + */ + if (isa(Val) && !DT.dominates(cast(Val), InsertionPoint)) { + InsertionPoint = &*(++(cast(Val)->getIterator())); + // No need to root this anywhere else any more + Colors[R] = -1; + } + Val = GetPtrForNumber(S, R, InsertionPoint); + Value *args[1] = { + ConstantInt::get(T_int32, Colors[R]+MinColorRoot) + }; + GetElementPtrInst *gep = GetElementPtrInst::Create(T_prjlvalue, gcframe, makeArrayRef(args)); + gep->insertBefore(InsertionPoint); + Val = MaybeExtractUnion(Val, InsertionPoint); + // Pointee types don't have semantics, so the optimizer is + // free to rewrite them if convenient. We need to change + // it back here for the store. + if (Val->getType() != T_prjlvalue) + Val = new BitCastInst(Val, T_prjlvalue, "", InsertionPoint); + new StoreInst(Val, gep, InsertionPoint); + } + } + } + // Insert GCFrame pops + for(Function::iterator I = F.begin(), E = F.end(); I != E; ++I) { + if (isa(I->getTerminator())) { + PopGCFrame(gcframe, I->getTerminator()); + } + } + } +} + +bool LateLowerGCFrame::doInitialization(Module &M) { + ptls_getter = M.getFunction("jl_get_ptls_states"); + gc_kill_func = M.getFunction("julia.gc_root_kill"); + gc_flush_func = M.getFunction("julia.gcroot_flush"); + pointer_from_objref_func = M.getFunction("julia.pointer_from_objref"); + return false; +} + +bool LateLowerGCFrame::runOnFunction(Function &F) { + DEBUG(dbgs() << "GC ROOT PLACEMENT: Processing function " << F.getName() << "\n"); + if (ptls_getter) { + auto functype = ptls_getter->getFunctionType(); + T_ppjlvalue = + cast(functype->getReturnType())->getElementType(); + auto T_pjlvalue = cast(T_ppjlvalue)->getElementType(); + T_prjlvalue = PointerType::get(cast(T_pjlvalue)->getElementType(), AddressSpace::Tracked); + } else { + return CleanupIR(F); + } + T_size = F.getParent()->getDataLayout().getIntPtrType(F.getContext()); + T_int32 = Type::getInt32Ty(F.getContext()); + ptlsStates = nullptr; + for (auto I = F.getEntryBlock().begin(), E = F.getEntryBlock().end(); + ptls_getter && I != E; ++I) { + if (CallInst *callInst = dyn_cast(&*I)) { + if (callInst->getCalledValue() == ptls_getter) { + ptlsStates = callInst; + break; + } + } + } + if (!ptlsStates) + return CleanupIR(F); + State S = LocalScan(F); + ComputeLiveness(F, S); + std::vector Colors = ColorRoots(S); + std::map> CallFrames; // = OptimizeCallFrames(S, Ordering); + PlaceRootsAndUpdateCalls(F, Colors, S, CallFrames); + CleanupIR(F); + return true; +} + +char LateLowerGCFrame::ID = 0; +static RegisterPass X("LateLowerGCFrame", "Late Lower GCFrame Pass", false, false); + +Pass *createLateLowerGCFramePass() { + return new LateLowerGCFrame(); +} diff --git a/test/llvmpasses/gcroots-391.ll b/test/llvmpasses/gcroots-391.ll new file mode 100644 index 0000000000000..b162a1ac6a6d9 --- /dev/null +++ b/test/llvmpasses/gcroots-391.ll @@ -0,0 +1,67 @@ +; RUN: opt -load libjulia.so -LateLowerGCFrame -S %s | FileCheck %s + +; This file has test cases for IR only valid on LLVM 3.9.1/4.0 + +%jl_value_t = type opaque + +declare void @llvm.lifetime.start(i64, i8*) +declare void @llvm.lifetime.end(i64, i8*) + +declare %jl_value_t*** @jl_get_ptls_states() +declare %jl_value_t addrspace(10)* @jl_apply_generic(%jl_value_t addrspace(10)*, %jl_value_t addrspace(10)**, i32) +declare %jl_value_t addrspace(10)* @jl_box_int64(i64) + +; Check that LLVM duplicating some blocks doesn't confuse the GC placement pass +define void @bb_duplication(i1 %cnd, i64 %a, i64 %b) { +; CHECK-LABEL: @bb_duplication +; CHECK: %gcframe = alloca %jl_value_t addrspace(10)*, i32 4 +top: + %jlcall = alloca [2 x %jl_value_t addrspace(10)*], align 8 + %ptls = call %jl_value_t*** @jl_get_ptls_states() + %jlcall.sub = getelementptr inbounds [2 x %jl_value_t addrspace(10)*], [2 x %jl_value_t addrspace(10)*]* %jlcall, i64 0, i64 0 + %jlcall1 = getelementptr inbounds [2 x %jl_value_t addrspace(10)*], [2 x %jl_value_t addrspace(10)*]* %jlcall, i64 0, i64 1 + br label %loop +loop: + br i1 %cnd, label %A, label %B +A: + %Aaboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %a) + %Abboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %b) + br i1 undef, label %loop, label %Abody + +Abody: + %aarg = bitcast %jl_value_t addrspace(10)** %jlcall.sub to i8* + call void @llvm.lifetime.start(i64 16, i8* %aarg) + store %jl_value_t addrspace(10)* %Aaboxed, %jl_value_t addrspace(10)** %jlcall.sub + store %jl_value_t addrspace(10)* %Abboxed, %jl_value_t addrspace(10)** %jlcall1 + call %jl_value_t addrspace(10)* @jl_apply_generic(%jl_value_t addrspace(10)* null, %jl_value_t addrspace(10)** %jlcall.sub, i32 2) + call void @llvm.lifetime.end(i64 16, i8* %aarg) + br i1 undef, label %loop, label %out +B: + %Baboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %a) + %Bbboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %b) + %aarg2 = bitcast %jl_value_t addrspace(10)** %jlcall.sub to i8* + call void @llvm.lifetime.start(i64 16, i8* %aarg2) + store %jl_value_t addrspace(10)* %Baboxed, %jl_value_t addrspace(10)** %jlcall.sub + store %jl_value_t addrspace(10)* %Bbboxed, %jl_value_t addrspace(10)** %jlcall1 + call %jl_value_t addrspace(10)* @jl_apply_generic(%jl_value_t addrspace(10)* null, %jl_value_t addrspace(10)** %jlcall.sub, i32 2) + call void @llvm.lifetime.end(i64 16, i8* %aarg2) + br i1 undef, label %loop, label %out +out: + ret void +} + +; We can trivially sink single allocas into the gc frame, but we need to delete +; any lifetime markers +define void @single_alloca_lifetime(i64 %a) { +; CHECK-LABEL: @single_alloca_lifetime +; CHECK-NOT: call void @llvm.lifetime.start + %ptls = call %jl_value_t*** @jl_get_ptls_states() + %jlcall = alloca %jl_value_t addrspace(10)* + %aboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %a) + %aarg = bitcast %jl_value_t addrspace(10)** %jlcall to i8* + call void @llvm.lifetime.start(i64 16, i8* %aarg) + store %jl_value_t addrspace(10)* %aboxed, %jl_value_t addrspace(10)** %jlcall + call %jl_value_t addrspace(10)* @jl_apply_generic(%jl_value_t addrspace(10)* null, %jl_value_t addrspace(10)** %jlcall, i32 1) + call void @llvm.lifetime.start(i64 16, i8* %aarg) + ret void +} diff --git a/test/llvmpasses/gcroots-50.ll b/test/llvmpasses/gcroots-50.ll new file mode 100644 index 0000000000000..d8366b3a72ddf --- /dev/null +++ b/test/llvmpasses/gcroots-50.ll @@ -0,0 +1,64 @@ +; RUN: opt -load libjulia.so -LateLowerGCFrame -S %s | FileCheck %s + +; This file has test cases for IR only valid on LLVM 5.0 + +%jl_value_t = type opaque + +declare void @llvm.lifetime.start.p0p10s_jl_value_ts(i64, %jl_value_t addrspace(10)**) +declare void @llvm.lifetime.end.p0p10s_jl_value_ts(i64, %jl_value_t addrspace(10)**) + +declare %jl_value_t*** @jl_get_ptls_states() +declare %jl_value_t addrspace(10)* @jl_apply_generic(%jl_value_t addrspace(10)*, %jl_value_t addrspace(10)**, i32) +declare %jl_value_t addrspace(10)* @jl_box_int64(i64) + +; Check that LLVM duplicating some blocks doesn't confuse the GC placement pass +define void @bb_duplication(i1 %cnd, i64 %a, i64 %b) { +; CHECK-LABEL: @bb_duplication +; CHECK: %gcframe = alloca %jl_value_t addrspace(10)*, i32 4 +top: + %jlcall = alloca [2 x %jl_value_t addrspace(10)*], align 8 + %ptls = call %jl_value_t*** @jl_get_ptls_states() + %jlcall.sub = getelementptr inbounds [2 x %jl_value_t addrspace(10)*], [2 x %jl_value_t addrspace(10)*]* %jlcall, i64 0, i64 0 + %jlcall1 = getelementptr inbounds [2 x %jl_value_t addrspace(10)*], [2 x %jl_value_t addrspace(10)*]* %jlcall, i64 0, i64 1 + br label %loop +loop: + br i1 %cnd, label %A, label %B +A: + %Aaboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %a) + %Abboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %b) + br i1 undef, label %loop, label %Abody + +Abody: + call void @llvm.lifetime.start.p0p10s_jl_value_ts(i64 16, %jl_value_t addrspace(10)** %jlcall.sub) + store %jl_value_t addrspace(10)* %Aaboxed, %jl_value_t addrspace(10)** %jlcall.sub + store %jl_value_t addrspace(10)* %Abboxed, %jl_value_t addrspace(10)** %jlcall1 + call %jl_value_t addrspace(10)* @jl_apply_generic(%jl_value_t addrspace(10)* null, %jl_value_t addrspace(10)** %jlcall.sub, i32 2) + call void @llvm.lifetime.end.p0p10s_jl_value_ts(i64 16, %jl_value_t addrspace(10)** %jlcall.sub) + br i1 undef, label %loop, label %out +B: + %Baboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %a) + %Bbboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %b) + call void @llvm.lifetime.start.p0p10s_jl_value_ts(i64 16, %jl_value_t addrspace(10)** %jlcall.sub) + store %jl_value_t addrspace(10)* %Baboxed, %jl_value_t addrspace(10)** %jlcall.sub + store %jl_value_t addrspace(10)* %Bbboxed, %jl_value_t addrspace(10)** %jlcall1 + call %jl_value_t addrspace(10)* @jl_apply_generic(%jl_value_t addrspace(10)* null, %jl_value_t addrspace(10)** %jlcall.sub, i32 2) + call void @llvm.lifetime.end.p0p10s_jl_value_ts(i64 16, %jl_value_t addrspace(10)** %jlcall.sub) + br i1 undef, label %loop, label %out +out: + ret void +} + +; We can trivially sink single allocas into the gc frame, but we need to delete +; any lifetime markers +define void @single_alloca_lifetime(i64 %a) { +; CHECK-LABEL: @single_alloca_lifetime +; CHECK-NOT: call void @llvm.lifetime.start + %ptls = call %jl_value_t*** @jl_get_ptls_states() + %jlcall = alloca %jl_value_t addrspace(10)* + %aboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %a) + call void @llvm.lifetime.start.p0p10s_jl_value_ts(i64 16, %jl_value_t addrspace(10)** %jlcall) + store %jl_value_t addrspace(10)* %aboxed, %jl_value_t addrspace(10)** %jlcall + call %jl_value_t addrspace(10)* @jl_apply_generic(%jl_value_t addrspace(10)* null, %jl_value_t addrspace(10)** %jlcall, i32 1) + call void @llvm.lifetime.end.p0p10s_jl_value_ts(i64 16, %jl_value_t addrspace(10)** %jlcall) + ret void +} diff --git a/test/llvmpasses/gcroots.ll b/test/llvmpasses/gcroots.ll new file mode 100644 index 0000000000000..f77a7a5bf5aa9 --- /dev/null +++ b/test/llvmpasses/gcroots.ll @@ -0,0 +1,296 @@ +; RUN: opt -load libjulia.so -LateLowerGCFrame -S %s | FileCheck %s + +%jl_value_t = type opaque + +declare void @boxed_simple(%jl_value_t addrspace(10)*, %jl_value_t addrspace(10)*) +declare %jl_value_t addrspace(10)* @jl_box_int64(i64) +declare %jl_value_t*** @jl_get_ptls_states() +declare %jl_value_t addrspace(10)* @jl_apply_generic(%jl_value_t addrspace(10)*, %jl_value_t addrspace(10)**, i32) + +define void @simple(i64 %a, i64 %b) { +top: +; CHECK-LABEL: @simple + %ptls = call %jl_value_t*** @jl_get_ptls_states() +; CHECK: %gcframe = alloca %jl_value_t addrspace(10)*, i32 4 +; CHECK: call %jl_value_t addrspace(10)* @jl_box_int64 + %aboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %a) +; CHECK: [[GEP0:%.*]] = getelementptr %jl_value_t addrspace(10)*, %jl_value_t addrspace(10)** %gcframe, i32 [[GEPSLOT0:[0-9]+]] +; CHECK-NEXT: store %jl_value_t addrspace(10)* %aboxed, %jl_value_t addrspace(10)** [[GEP0]] + %bboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %b) +; CHECK-NEXT: %bboxed = +; Make sure the same gc slot isn't re-used +; CHECK-NOT: getelementptr %jl_value_t addrspace(10)*, %jl_value_t addrspace(10)** %gcframe, i32 [[GEPSLOT0]] +; CHECK: [[GEP1:%.*]] = getelementptr %jl_value_t addrspace(10)*, %jl_value_t addrspace(10)** %gcframe, i32 [[GEPSLOT1:[0-9]+]] +; CHECK-NEXT: store %jl_value_t addrspace(10)* %bboxed, %jl_value_t addrspace(10)** [[GEP1]] +; CHECK-NEXT: call void @boxed_simple + call void @boxed_simple(%jl_value_t addrspace(10)* %aboxed, + %jl_value_t addrspace(10)* %bboxed) + ret void +} + +define void @leftover_alloca(%jl_value_t addrspace(10)*%a) { +; If this pass encounters an alloca, it'll just sink it into the gcframe, +; relying on mem2reg to catch simple cases such as this earlier +; CHECK-LABEL: @leftover_alloca +; CHECK: %var = getelementptr %jl_value_t addrspace(10)*, %jl_value_t addrspace(10)** %gcframe + %ptls = call %jl_value_t*** @jl_get_ptls_states() + %var = alloca %jl_value_t addrspace(10)* + store %jl_value_t addrspace(10)* %a, %jl_value_t addrspace(10)** %var + %b = load %jl_value_t addrspace(10)*, %jl_value_t addrspace(10)** %var + call void @boxed_simple(%jl_value_t addrspace(10)* %a, + %jl_value_t addrspace(10)* %b) + ret void +} + +declare {%jl_value_t addrspace(10)*, i8} @union_ret() +declare void @union_arg({%jl_value_t addrspace(10)*, i8}) + +define void @simple_union() { +; CHECK-LABEL: @simple_union + %ptls = call %jl_value_t*** @jl_get_ptls_states() +; CHECK: %a = call { %jl_value_t addrspace(10)*, i8 } @union_ret() + %a = call { %jl_value_t addrspace(10)*, i8 } @union_ret() +; CHECK: [[GEP0:%.*]] = getelementptr %jl_value_t addrspace(10)*, %jl_value_t addrspace(10)** %gcframe, i32 [[GEPSLOT0:[0-9]+]] +; CHECK-NEXT: [[EXTRACT:%.*]] = extractvalue { %jl_value_t addrspace(10)*, i8 } %a, 0 +; CHECK-NEXT: store %jl_value_t addrspace(10)* [[EXTRACT]], %jl_value_t addrspace(10)** [[GEP0]] + call void @union_arg({%jl_value_t addrspace(10)*, i8} %a) + ret void +} + +declare void @one_arg_boxed(%jl_value_t addrspace(10)*) + +define void @select_simple(i64 %a, i64 %b) { +; CHECK-LABEL: @select_simple + %ptls = call %jl_value_t*** @jl_get_ptls_states() + %aboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %a) + %bboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %b) + %cmp = icmp eq i64 %a, %b + %selectb = select i1 %cmp, %jl_value_t addrspace(10)* %aboxed, %jl_value_t addrspace(10)* %bboxed + call void @one_arg_boxed(%jl_value_t addrspace(10)* %selectb) + ret void +} + +define void @phi_simple(i64 %a, i64 %b) { +top: +; CHECK-LABEL: @phi_simple +; CHECK: %gcframe = alloca %jl_value_t addrspace(10)*, i32 3 + %ptls = call %jl_value_t*** @jl_get_ptls_states() + %cmp = icmp eq i64 %a, %b + br i1 %cmp, label %alabel, label %blabel +alabel: + %aboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %a) + br label %common +blabel: + %bboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %b) + br label %common +common: + %phi = phi %jl_value_t addrspace(10)* [ %aboxed, %alabel ], [ %bboxed, %blabel ] +; CHECK: [[GEP:%.*]] = getelementptr %jl_value_t addrspace(10)*, %jl_value_t addrspace(10)** %gcframe, i32 2 +; CHECK: store %jl_value_t addrspace(10)* %phi, %jl_value_t addrspace(10)** [[GEP]] + call void @one_arg_boxed(%jl_value_t addrspace(10)* %phi) + ret void +} + +declare void @one_arg_decayed(i64 addrspace(12)*) + +define void @select_lift(i64 %a, i64 %b) { +; CHECK-LABEL: @select_lift +; CHECK: %gcframe = alloca %jl_value_t addrspace(10)*, i32 3 + %ptls = call %jl_value_t*** @jl_get_ptls_states() + %aboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %a) + %adecayed = addrspacecast %jl_value_t addrspace(10)* %aboxed to i64 addrspace(12)* + %bboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %b) + %bdecayed = addrspacecast %jl_value_t addrspace(10)* %bboxed to i64 addrspace(12)* + %cmp = icmp eq i64 %a, %b +; CHECK: %gclift = select i1 %cmp, %jl_value_t addrspace(10)* %aboxed, %jl_value_t addrspace(10)* %bboxed + %selectb = select i1 %cmp, i64 addrspace(12)* %adecayed, i64 addrspace(12)* %bdecayed + call void @one_arg_decayed(i64 addrspace(12)* %selectb) + ret void +} + +define void @phi_lift(i64 %a, i64 %b) { +top: +; CHECK-LABEL: @phi_lift + %ptls = call %jl_value_t*** @jl_get_ptls_states() + %cmp = icmp eq i64 %a, %b + br i1 %cmp, label %alabel, label %blabel +alabel: + %aboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %a) + %adecayed = addrspacecast %jl_value_t addrspace(10)* %aboxed to i64 addrspace(12)* + br label %common +blabel: + %bboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %b) + %bdecayed = addrspacecast %jl_value_t addrspace(10)* %bboxed to i64 addrspace(12)* + br label %common +common: + %phi = phi i64 addrspace(12)* [ %adecayed, %alabel ], [ %bdecayed, %blabel ] + call void @one_arg_decayed(i64 addrspace(12)* %phi) + ret void +} + +; Checks for ugly phi corner case +define void @phi_corner_case(i64 %a, i64 %b, i64 %c, i64 %d) { +top: +; CHECK-LABEL: @phi_corner_case +; CHECK: %gcframe = alloca %jl_value_t addrspace(10)*, i32 6 +; Currently each value gets stored twice, once to the gc frame, once to the +; jlcall frame. Future optimizations may change that, which would require appropriate +; adjustments to this test. +; CHECK: store %jl_value_t addrspace(10)* %aboxed +; CHECK: store %jl_value_t addrspace(10)* %aboxed +; CHECK: store %jl_value_t addrspace(10)* %bboxed +; CHECK: store %jl_value_t addrspace(10)* %bboxed +; CHECK: store %jl_value_t addrspace(10)* %cboxed +; CHECK: store %jl_value_t addrspace(10)* %cboxed +; CHECK: store %jl_value_t addrspace(10)* %dboxed +; CHECK: store %jl_value_t addrspace(10)* %dboxed + %ptls = call %jl_value_t*** @jl_get_ptls_states() + %frame1 = alloca %jl_value_t addrspace(10)*, i32 2 + %frame11 = getelementptr %jl_value_t addrspace(10)*, %jl_value_t addrspace(10)** %frame1, i32 1 + %frame2 = alloca %jl_value_t addrspace(10)*, i32 2 + %frame21 = getelementptr %jl_value_t addrspace(10)*, %jl_value_t addrspace(10)** %frame2, i32 1 + %aboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %a) + %bboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %b) + store %jl_value_t addrspace(10)* %aboxed, %jl_value_t addrspace(10)** %frame1 + store %jl_value_t addrspace(10)* %bboxed, %jl_value_t addrspace(10)** %frame11 + %cboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %c) + %dboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %d) + store %jl_value_t addrspace(10)* %cboxed, %jl_value_t addrspace(10)** %frame2 + store %jl_value_t addrspace(10)* %dboxed, %jl_value_t addrspace(10)** %frame21 + %cmp = icmp eq i64 %a, %b + br i1 %cmp, label %alabel, label %blabel +alabel: + br label %common +blabel: + br label %common +common: + %callframe = phi %jl_value_t addrspace(10)** [ %frame1, %alabel], [ %frame2, %blabel ] + call %jl_value_t addrspace(10)* @jl_apply_generic(%jl_value_t addrspace(10)* null, %jl_value_t addrspace(10)** %callframe, i32 2) + ret void +} + +define void @phi_corner_case2(i64 %a, i64 %b, i64 %c, i64 %d) { +; CHECK-LABEL: @phi_corner_case2 +; CHECK: %gcframe = alloca %jl_value_t addrspace(10)*, i32 6 + %ptls = call %jl_value_t*** @jl_get_ptls_states() + %frame1 = alloca %jl_value_t addrspace(10)*, i32 2 + %frame11 = getelementptr %jl_value_t addrspace(10)*, %jl_value_t addrspace(10)** %frame1, i32 1 + %frame2 = alloca %jl_value_t addrspace(10)*, i32 2 + %frame21 = getelementptr %jl_value_t addrspace(10)*, %jl_value_t addrspace(10)** %frame2, i32 1 + %aboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %a) + %bboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %b) + store %jl_value_t addrspace(10)* %aboxed, %jl_value_t addrspace(10)** %frame1 + store %jl_value_t addrspace(10)* %bboxed, %jl_value_t addrspace(10)** %frame11 + %cmp = icmp eq i64 %a, %b + br i1 %cmp, label %alabel, label %blabel +alabel: + br label %common +blabel: + %cboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %c) +; cboxed gets two stores (one to gcroot it for the boxing of d) +; CHECK: store %jl_value_t addrspace(10)* %cboxed +; CHECK: store %jl_value_t addrspace(10)* %cboxed +; CHECK: store %jl_value_t addrspace(10)* %dboxed + %dboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %d) + store %jl_value_t addrspace(10)* %cboxed, %jl_value_t addrspace(10)** %frame2 + store %jl_value_t addrspace(10)* %dboxed, %jl_value_t addrspace(10)** %frame21 + br label %common +common: +; CHECK-DAG: [[LIFT1:%.*]] = phi %jl_value_t addrspace(10)* [ null, %alabel ], [ %cboxed, %blabel ] +; CHECK-DAG: [[LIFT2:%.*]] = phi %jl_value_t addrspace(10)* [ null, %alabel ], [ %dboxed, %blabel ] +; CHECK-DAG: store %jl_value_t addrspace(10)* [[LIFT2]] +; CHECK-DAG: store %jl_value_t addrspace(10)* [[LIFT1]] + %callframe = phi %jl_value_t addrspace(10)** [ %frame1, %alabel], [ %frame2, %blabel ] + call %jl_value_t addrspace(10)* @jl_apply_generic(%jl_value_t addrspace(10)* null, %jl_value_t addrspace(10)** %callframe, i32 2) + ret void +} + +define void @underlying_object(i64 %a, i64 %b) { +; CHECK-LABEL: @underlying_object +; We need to root both values here. The observed failure case was that we'd +; only consider stores to the gep passed to the call rather than all stores +; to the alloca. +; CHECK: %gcframe = alloca %jl_value_t addrspace(10)*, i32 4 + %jlcall = alloca [2 x %jl_value_t addrspace(10)*], align 8 + %jlcall.sub = getelementptr inbounds [2 x %jl_value_t addrspace(10)*], [2 x %jl_value_t addrspace(10)*]* %jlcall, i64 0, i64 0 + %ptls = call %jl_value_t*** @jl_get_ptls_states() + %aboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %a) + %bboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %b) + store %jl_value_t addrspace(10)* %aboxed, %jl_value_t addrspace(10)** %jlcall.sub + %bslot = getelementptr inbounds [2 x %jl_value_t addrspace(10)*], [2 x %jl_value_t addrspace(10)*]* %jlcall, i64 0, i64 1 + store %jl_value_t addrspace(10)* %bboxed, %jl_value_t addrspace(10)** %bslot + call %jl_value_t addrspace(10)* @jl_apply_generic(%jl_value_t addrspace(10)* null, %jl_value_t addrspace(10)** %jlcall.sub, i32 2) + ret void +} + +define void @live_if_live_out(i64 %a, i64 %b) { +; CHECK-LABEL: @live_if_live_out +top: +; CHECK: %gcframe = alloca %jl_value_t addrspace(10)*, i32 4 + %ptls = call %jl_value_t*** @jl_get_ptls_states() +; The failure case is failing to realize that `aboxed` is live across the first +; one_arg_boxed safepoint and putting bboxed in the same root slot + %aboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %a) + %bboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %b) + call void @one_arg_boxed(%jl_value_t addrspace(10)* %bboxed) + br label %succ +succ: + call void @one_arg_boxed(%jl_value_t addrspace(10)* %aboxed) + ret void +} + +declare void @llvm.lifetime.start.p0p10s_jl_value_ts(i64, %jl_value_t addrspace(10)**) +declare void @llvm.lifetime.end.p0p10s_jl_value_ts(i64, %jl_value_t addrspace(10)**) + +; The system shouldn't really be generating things like this, but we can get unlucky +define void @weird_alloca(i1 %cnd, i64 %a, i64 %b) { +; CHECK-LABEL: weird_alloca +; CHECK: %gcframe = alloca %jl_value_t addrspace(10)*, i32 4 + %jlcall = alloca [2 x %jl_value_t addrspace(10)*], align 8 + %ptls = call %jl_value_t*** @jl_get_ptls_states() + %jlcall.sub = getelementptr inbounds [2 x %jl_value_t addrspace(10)*], [2 x %jl_value_t addrspace(10)*]* %jlcall, i64 0, i64 0 + %jlcall1 = getelementptr inbounds [2 x %jl_value_t addrspace(10)*], [2 x %jl_value_t addrspace(10)*]* %jlcall, i64 0, i64 1 + store %jl_value_t addrspace(10)* null, %jl_value_t addrspace(10)** %jlcall.sub + store %jl_value_t addrspace(10)* null, %jl_value_t addrspace(10)** %jlcall1 + br i1 %cnd, label %if, label %done + +if: + %aboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %a) + %bboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %b) + store %jl_value_t addrspace(10)* %aboxed, %jl_value_t addrspace(10)** %jlcall.sub + store %jl_value_t addrspace(10)* %bboxed, %jl_value_t addrspace(10)** %jlcall1 + br label %done + +done: + call %jl_value_t addrspace(10)* @jl_apply_generic(%jl_value_t addrspace(10)* null, %jl_value_t addrspace(10)** %jlcall.sub, i32 2) + ret void +} + +; A ret is a use - make sure the value is kept alive for any intervening +; safepoint +define %jl_value_t addrspace(10)* @ret_use(i64 %a, i64 %b) { +; CHECK-LABEL: @ret_use +; CHECK: %gcframe = alloca %jl_value_t addrspace(10)*, i32 3 + %ptls = call %jl_value_t*** @jl_get_ptls_states() + %aboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %a) +; CHECK: store %jl_value_t addrspace(10)* %aboxed + %bboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %b) + ret %jl_value_t addrspace(10)* %aboxed +} + +define void @vector_ops(%jl_value_t addrspace(10)* %a, %jl_value_t addrspace(10)** %b, i32 %c) { +; CHECK-LABEL: @vector_ops +; N.B.: This should be 4, but it's currently not realizing that %a doesn't need a root +; CHECK: %gcframe = alloca %jl_value_t addrspace(10)*, i32 5 + %ptls = call %jl_value_t*** @jl_get_ptls_states() + %jlcall = alloca [3 x %jl_value_t addrspace(10)*], align 8 + %jlcall.sub = getelementptr inbounds [3 x %jl_value_t addrspace(10)*], [3 x %jl_value_t addrspace(10)*]* %jlcall, i64 0, i64 0 + %casted = bitcast %jl_value_t addrspace(10)** %b to <2 x %jl_value_t addrspace(10)*>* + %loaded = load <2 x %jl_value_t addrspace(10)*>, <2 x %jl_value_t addrspace(10)*>* %casted + %jlcall.casted = bitcast [3 x %jl_value_t addrspace(10)*]* %jlcall to <2 x %jl_value_t addrspace(10)*>* + store <2 x %jl_value_t addrspace(10)*> %loaded, <2 x %jl_value_t addrspace(10)*>* %jlcall.casted + %third = getelementptr inbounds [3 x %jl_value_t addrspace(10)*], [3 x %jl_value_t addrspace(10)*]* %jlcall, i64 0, i64 2 + store %jl_value_t addrspace(10)* %a, %jl_value_t addrspace(10)** %third + call %jl_value_t addrspace(10)* @jl_apply_generic(%jl_value_t addrspace(10)* %a, %jl_value_t addrspace(10)** %jlcall.sub, i32 3) + ret void +} From 3a9fa438ecf205c4669579f6817a2b1201506a3d Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Mon, 15 May 2017 10:38:24 -0400 Subject: [PATCH 1096/1534] Remove old GC placement pass --- src/jitlayers.h | 1 - src/llvm-gcroot.cpp | 1071 ------------------------------------------- 2 files changed, 1072 deletions(-) delete mode 100644 src/llvm-gcroot.cpp diff --git a/src/jitlayers.h b/src/jitlayers.h index 42244ddbff4b7..780c489f3e750 100644 --- a/src/jitlayers.h +++ b/src/jitlayers.h @@ -247,7 +247,6 @@ JL_DLLEXPORT extern LLVMContext &jl_LLVMContext; #endif Pass *createLowerPTLSPass(bool imaging_mode); -Pass *createLowerGCFramePass(); Pass *createLateLowerGCFramePass(); Pass *createLowerExcHandlersPass(); Pass *createGCInvariantVerifierPass(bool Strong); diff --git a/src/llvm-gcroot.cpp b/src/llvm-gcroot.cpp deleted file mode 100644 index e1e7dfa46823b..0000000000000 --- a/src/llvm-gcroot.cpp +++ /dev/null @@ -1,1071 +0,0 @@ -// This file is a part of Julia. License is MIT: https://julialang.org/license - -#define DEBUG_TYPE "lower_gcroot" -#undef DEBUG - -#include "llvm-version.h" -#include -#include -#include -#include -#include -#include -#include -#if JL_LLVM_VERSION >= 30700 -#include -#else -#include -#endif -#include -#include -#if JL_LLVM_VERSION >= 30600 -#include -#include -#endif -#include - -#include "fix_llvm_assert.h" - -#include -#include -#include -#include -#include - -#include "julia.h" - -#if JL_LLVM_VERSION >= 30700 -#define LLVM37_param(x) (x), -#else -#define LLVM37_param(x) -#endif - -using namespace llvm; - -extern std::pair tbaa_make_child(const char *name, MDNode *parent=nullptr, bool isConstant=false); - -namespace { - -#ifndef JL_NDEBUG -static struct { - unsigned count; - unsigned locals; - unsigned temp; -} jl_gc_frame_stats = {0}; -#endif - -typedef std::pair frame_register; -struct liveness { - typedef unsigned id; - enum { - // an assignment to a gcroot exists in the basic-block - // (potentially no live-in from the predecessor basic-blocks) - assign = 1<<0, - // a use of a gcroot exists in the basic-block - // (potentially a "kill" and no live-out to the successor basic-blocks) - kill = 1<<1, - // the gcroot is live over the entire basic-block - // (the assign/kill are not dominating of entry/exit) - live = 1<<2 - - // live | kill | assign: - // a usage and assignment exist, but it is also live on exit, - // the entry liveness depends on whether a store or use is - // encountered first - // live | kill: - // a usage exists, - // but the value must be live for the entire basic-block - // since it is not the terminal usage in the domination tree - // kill | assign: - // a usage and definition exist in domination order, - // so the actual lifetime is only a subset of the basic-block - // live | assign: - // impossible (this would be strange) - }; -}; - -static void tbaa_decorate_gcframe(Instruction *inst, - std::set &visited, - MDNode *tbaa_gcframe) -{ - if (!visited.insert(inst).second) - return; -#if JL_LLVM_VERSION >= 30500 - Value::user_iterator I = inst->user_begin(), E = inst->user_end(); -#else - Value::use_iterator I = inst->use_begin(), E = inst->use_end(); -#endif - for (;I != E;++I) { - Instruction *user = dyn_cast(*I); - if (!user) { - continue; - } - else if (isa(user)) { - if (__likely(user->getOperand(0) == inst)) { - tbaa_decorate_gcframe(user, visited, tbaa_gcframe); - } - } - else if (isa(user)) { - if (user->getOperand(1) == inst) { - user->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_gcframe); - } - } - else if (isa(user)) { - user->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_gcframe); - } - else if (isa(user)) { - tbaa_decorate_gcframe(user, visited, tbaa_gcframe); - } - } -} - -static void tbaa_decorate_gcframe(Instruction *inst, MDNode *tbaa_gcframe) -{ - std::set visited; - tbaa_decorate_gcframe(inst, visited, tbaa_gcframe); -} - -class JuliaGCAllocator { -public: - JuliaGCAllocator(Function &F, CallInst *ptlsStates, - Type *T_prjlvalue, MDNode *tbaa) : - F(F), - M(*F.getParent()), - T_int1(Type::getInt1Ty(F.getContext())), - T_int8(Type::getInt8Ty(F.getContext())), - T_int32(Type::getInt32Ty(F.getContext())), - T_int64(Type::getInt64Ty(F.getContext())), - V_null(T_prjlvalue ? Constant::getNullValue(T_prjlvalue) : nullptr), - ptlsStates(ptlsStates), -#if JL_LLVM_VERSION >= 50000 - gcframe(ptlsStates ? new AllocaInst(T_prjlvalue, 0, ConstantInt::get(T_int32, 0)) : nullptr), -#else - gcframe(ptlsStates ? new AllocaInst(T_prjlvalue, ConstantInt::get(T_int32, 0)) : nullptr), -#endif - gcroot_func(M.getFunction("julia.gc_root_decl")), - gckill_func(M.getFunction("julia.gc_root_kill")), - jlcall_frame_func(M.getFunction("julia.jlcall_frame_decl")), - gcroot_flush_func(M.getFunction("julia.gcroot_flush")), - except_enter_func(M.getFunction("julia.except_enter")), - jlleave_func(M.getFunction("jl_pop_handler")), - tbaa_gcframe(tbaa) - { -/* Algorithm sketch: - * Compute liveness for each basic block - * liveness computed at the basic-block level for pairs - * Propagate liveness from each basic block to its predecessors - * Allocate argument slot for each jlcall frame - */ - if (gcframe) { -#ifdef JL_DEBUG_BUILD - gcframe->setName("gcrootframe"); -#endif - gcframe->insertAfter(ptlsStates); - } - } - -private: - Function &F; - Module &M; - Type *const T_int1; - Type *const T_int8; - Type *const T_int32; - Type *const T_int64; - Value *const V_null; - CallInst *const ptlsStates; - AllocaInst *const gcframe; - Function *const gcroot_func; - Function *const gckill_func; - Function *const jlcall_frame_func; - Function *const gcroot_flush_func; - Function *const except_enter_func; - Function *const jlleave_func; - MDNode *const tbaa_gcframe; - - Instruction *get_pgcstack(Instruction *ptlsStates); - frame_register get_gcroot(Value *ptr); - void collapseRedundantRoots(); - bool record_usage(CallInst *callInst, - std::map > &bb_uses, - std::map ®s_used, - unsigned &offset, bool commit=true); - unsigned find_space_for(CallInst *callInst, - std::map > &bb_uses, - std::map ®s_used); - void rearrangeRoots(); -public: - void allocate_frame(); -}; - -struct HandlerData { - // Pairs of , number of pops left after popping - // this frame. - std::vector> leaves; - // enters that are directly nested in this frame - std::set nested; - std::unique_ptr> parent_vec; - CallInst *parent{nullptr}; - bool processed{false}; -#ifdef _COMPILER_MICROSOFT_ - // MSVC 2013 seems to call the copy version instead of the move verion - // without this, which triggers compilation error since `std::unique_ptr` - // is not copyable. - HandlerData() = default; - HandlerData(HandlerData &&other) - : HandlerData() - { - operator=(std::move(other)); - } - HandlerData(const HandlerData&) = delete; - HandlerData &operator=(HandlerData &&other) - { - std::swap(leaves, other.leaves); - std::swap(nested, other.nested); - std::swap(parent_vec, other.parent_vec); - std::swap(parent, other.parent); - std::swap(processed, other.processed); - return *this; - } - HandlerData &operator=(const HandlerData&) = delete; -#endif -}; - - -Instruction *JuliaGCAllocator::get_pgcstack(Instruction *ptlsStates) -{ - Constant *offset = ConstantInt::getSigned(T_int32, offsetof(jl_tls_states_t, pgcstack) / sizeof(void*)); - return GetElementPtrInst::Create(LLVM37_param(NULL) - ptlsStates, - ArrayRef(offset), - "jl_pgcstack"); -} - -frame_register JuliaGCAllocator::get_gcroot(Value *ptr) -{ - frame_register frame; - frame.first = dyn_cast(ptr); - frame.second = 0; - if (frame.first == NULL) { - // also try to look through GEP for jlcall_frame_func - if (GetElementPtrInst *gepInst = dyn_cast(ptr)) { - if (gepInst->getNumIndices() == 1) { - frame.first = dyn_cast(gepInst->getPointerOperand()); - if (frame.first && frame.first->getCalledValue() == jlcall_frame_func) - frame.second = cast(gepInst->idx_begin()->get())->getZExtValue(); - else - frame.first = NULL; - } - } - } - return frame; -} - -void JuliaGCAllocator::collapseRedundantRoots() -{ - for (BasicBlock::iterator I = gcframe->getParent()->begin(), E(gcframe); I != E; ) { - CallInst* callInst = dyn_cast(&*I); - ++I; - if (callInst && callInst->getCalledValue() == gcroot_func) { - // see if a root is only used briefly for `store -> load -> store other` pattern or `store, store other` - // such that the first store can be trivially replaced with just "other" and delete the chain - // or if is used for store, but the value is never needed - StoreInst *theStore = NULL; - unsigned n_stores = 0; - bool variable_slot = true; // whether this gc-root is only used as a variable-slot; e.g. whether theLoad is theValue - LoadInst *theLoad = NULL; - for (User::use_iterator use = callInst->use_begin(), usee = callInst->use_end(); use != usee; ) { -#if JL_LLVM_VERSION >= 30500 - User *user = use->getUser(); -#else - User *user = use.getUse().getUser(); -#endif - ++use; - if (StoreInst *storeInst = dyn_cast(user)) { - if (n_stores == 0) - theStore = storeInst; - else - theStore = NULL; - Value *theValue = storeInst->getValueOperand(); - if (!theValue->hasOneUse()) { // not just the store - variable_slot = false; // this gc-root is used as more than just a variable-slot (aka phi node) - } - n_stores++; - } - else if (LoadInst *loadInst = dyn_cast(user)) { - if (loadInst->use_empty()) { - // dead load? - loadInst->eraseFromParent(); - } - else { - if (theLoad) { - // multiple live loads, this is hard to optimize, so skip it - n_stores = 0; - break; - } - theLoad = loadInst; - } - } - else { - // what is this? oh, well. skip trying to optimize this gc-root - n_stores = 0; - break; - } - } - - if (n_stores == 0) - continue; - - if (theLoad == NULL) { - // this gc-root is never loaded from, so we don't need it as a variable location - // delete any stores to this gc-root that would be keeping an otherwise-unused value alive - for (User::use_iterator use = callInst->use_begin(), usee = callInst->use_end(); use != usee; ) { -#if JL_LLVM_VERSION >= 30500 - User *user = use->getUser(); -#else - User *user = use.getUse().getUser(); -#endif - StoreInst *theStore = cast(user); - ++use; - Value *theValue = theStore->getValueOperand(); - if (theValue->hasOneUse()) { // just the store - if (&*I == theStore) ++I; - theStore->eraseFromParent(); - } - } - if (callInst->use_empty()) { - callInst->eraseFromParent(); - continue; - } - else if (callInst->hasOneUse()) { - User::use_iterator use = callInst->use_begin(); -#if JL_LLVM_VERSION >= 30500 - theStore = cast(use->getUser()); -#else - theStore = cast(use.getUse().getUser()); -#endif - } - } - - if ((theLoad != NULL && variable_slot) || - (theLoad == NULL && theStore != NULL)) { - Value *theValue = theLoad ? theLoad : theStore->getValueOperand(); - if (theValue->hasNUses(theLoad ? 1 : 2)) { // only uses are theStore and theLoad and theOther - // check if this value is only used for a store to another gcroot - User::use_iterator value_use = theValue->use_begin(); - if (theLoad && *value_use == theStore) - ++value_use; -#if JL_LLVM_VERSION >= 30500 - StoreInst *theOther = dyn_cast(value_use->getUser()); - unsigned OperandNo = value_use->getOperandNo(); -#else - StoreInst *theOther = dyn_cast(value_use.getUse().getUser()); - unsigned OperandNo = value_use.getOperandNo(); -#endif - if (theOther && OperandNo != StoreInst::getPointerOperandIndex()) { - // test whether this store is valid as a gc-root - bool patternMatchSuccess = false; - frame_register gcroot_other_gep = get_gcroot(theOther->getPointerOperand()); - CallInst *gcroot_other = gcroot_other_gep.first; - // it could be a gcroot... - if (gcroot_other && gcroot_other->getCalledValue() == gcroot_func && theStore != NULL) { - // need to make sure there aren't any other uses of gcroot_other (including gckill) - // between the initial store and the replacement store - // TODO: do this better once we have liveness information for locals? - BasicBlock *current = theStore->getParent(); - BasicBlock::iterator bbi(theStore); - BasicBlock::iterator bbi_end = current->end(); - patternMatchSuccess = true; - ++bbi; - while (patternMatchSuccess) { - Instruction *inst = &*bbi; - if (inst == theOther) { - break; // success - } - for (Instruction::op_iterator op = inst->op_begin(), op_e = inst->op_end(); op != op_e; ++op) { - if (op->get() == gcroot_other) { - patternMatchSuccess = false; - break; // fail: gcroot_other had another reference, can't make this replacement - } - } - if (++bbi == bbi_end) { - // iterate the basicblock forward, if it's a simple branch -#if JL_LLVM_VERSION >= 30500 - BasicBlock *next = current->getUniqueSuccessor(); -#else - succ_iterator SI = succ_begin(current), E = succ_end(current); - BasicBlock *next = NULL; - if (SI != E) { - next = *SI; - for (++SI; SI != E; ++SI) { - if (*SI != next) { - next = NULL; - break; - } - } - } -#endif - if (next) { - bbi = next->begin(); - bbi_end = next->end(); - current = next; - } - else { - patternMatchSuccess = false; - } - } - } - } - // ...or it could be a jlcall frame - else if (gcroot_other && gcroot_other->getCalledValue() == jlcall_frame_func) { - // jlcall_frame_func slots are effectively SSA, - // so it's always safe to merge an earlier store into it - // but do need to update liveness information for this slot - // TODO: do this better once we have liveness information for locals? - if (theStore != NULL && theOther->getParent() == theStore->getParent()) { - //unsigned arg_offset = gcroot_other_gep->second; - //frame_register def(gcroot_other, arg_offset); - //std::map &inuse_list = bb_uses[theOther->getParent()]; - //std::map::iterator inuse_reg = inuse_list.find(def); - patternMatchSuccess = true; - } - } - if (patternMatchSuccess) { - // do the gcroot merge -- replace gcroot with gcroot_other in all the store operations for this gcroot - // so that theOther, theLoad, and this gcroot are no longer needed - Value *gcroot_other = theOther->getPointerOperand(); - if (&*I == theOther) ++I; - theOther->eraseFromParent(); - if (theLoad) { - if (&*I == theLoad) ++I; - theLoad->eraseFromParent(); - } - if (theStore) { - theStore->setOperand(StoreInst::getPointerOperandIndex(), gcroot_other); - } - else { - for (User::use_iterator use = callInst->use_begin(), usee = callInst->use_end(); use != usee; ) { -#if JL_LLVM_VERSION >= 30500 - User *user = use->getUser(); -#else - User *user = use.getUse().getUser(); -#endif - ++use; - StoreInst *theStore = cast(user); - theStore->setOperand(StoreInst::getPointerOperandIndex(), gcroot_other); - } - } - callInst->eraseFromParent(); - } - } - } - } - } - } -} - -bool JuliaGCAllocator::record_usage(CallInst *callInst, - std::map > &bb_uses, - std::map ®s_used, - unsigned &offset, bool commit) -{ -/* record-usage(inst, bb-uses, regs-used, offset, commit=true) - * for (arg-offset, operand) in enumerate(arguments(inst)) - * reg = - * for (bb, liveness) in bb-uses - * if not reg in liveness - * continue - * # TODO: optimize better if liveness[reg] doesn't contain live - * conflict = regs-used[bb][offset + arg-offset] - * if commit - * assert !conflict - * regs-used[bb][offset + arg-offset] = true - * else if conflict - * return false - * return true - */ - unsigned arg_n = cast(callInst->getArgOperand(0))->getZExtValue(); -#if 0 // suboptimal allocator that ignores computed liveness data - { - SmallBitVector ®s = regs_used[&callInst->getParent()->getParent()->getEntryBlock()]; - if (offset + arg_n > regs.size()) - regs.resize(offset + arg_n); - for (unsigned arg_offset = 0; arg_offset < arg_n; ++arg_offset) { - frame_register def(callInst, arg_offset); -#else // }} better allocator that uses per-basicblock liveness - for (std::map >::iterator - live_reg = bb_uses.begin(), e = bb_uses.end(); live_reg != e; ++live_reg) { - BasicBlock *bb = live_reg->first; - SmallBitVector ®s = regs_used[bb]; - if (offset + arg_n > regs.size()) - regs.resize(offset + arg_n); - for (unsigned arg_offset = 0; arg_offset < arg_n; ++arg_offset) { - frame_register def(callInst, arg_offset); - std::map::iterator inuse_reg = live_reg->second.find(def); - if (inuse_reg == live_reg->second.end()) - continue; - // TODO: optimize here better when not live in inuse_reg->second, by ascertaining liveness at the instruction level for this bb -#endif - unsigned index = offset + arg_offset; - bool conflict = regs.test(index); - if (commit) { - assert(!conflict); - regs.set(index); - } - else if (conflict) { - // update the offset argument to point to the next open register beyond index - // to help avoid unnecessary work and accelerate the search - ++offset; - while (offset + arg_offset < regs.size() && regs.test(offset + arg_offset)) - ++offset; - return false; - } - } - } - return true; -} - -unsigned JuliaGCAllocator::find_space_for(CallInst *callInst, - std::map > &bb_uses, - std::map ®s_used) -{ -/* find-space-for(inst, bb-uses, regs-used) - * n = 0 - * while !record-usage(inst, bb-uses, regs-used, n, false) - * n++ - * return n - * - */ - unsigned n = 0; - while (!record_usage(callInst, bb_uses, regs_used, n, false)) { } - return n; -} - -void JuliaGCAllocator::rearrangeRoots() -{ - for (auto BB = F.begin(), E(F.end()); BB != E; BB++) { - auto terminst = BB->getTerminator(); - if (!isa(terminst) && !isa(terminst)) - continue; - SmallVector toRemove; - for (auto I = BB->rbegin(), E(BB->rend()); I != E; ++I) { - // Only handle the simplest case for now, give up if there's a call - // or load from the GC frame. - // (Assume we don't have loads that can alias GC frame - // unless the source address is a `julia.gc_root_decl`) - Instruction *inst = &*I; - if (isa(inst)) - break; - if (LoadInst *loadInst = dyn_cast(inst)) { - CallInst *loadAddr = - dyn_cast(loadInst->getPointerOperand()); - if (loadAddr && loadAddr->getCalledValue() == gcroot_func) - break; - continue; - } - if (StoreInst *storeInst = dyn_cast(inst)) { - CallInst *storeAddr = - dyn_cast(storeInst->getPointerOperand()); - if (storeAddr && storeAddr->getCalledValue() == gcroot_func) - toRemove.push_back(storeInst); - continue; - } - } - for (auto inst: toRemove) { - CallInst *decl = cast(inst->getPointerOperand()); - inst->eraseFromParent(); - // TODO removing unused slot should probably be handled later - // when we allocate the frame - if (decl->use_empty()) { - decl->eraseFromParent(); - } - } - } -} - -void JuliaGCAllocator::allocate_frame() -{ - if (!ptlsStates) - return; - Instruction *last_gcframe_inst = gcframe; - collapseRedundantRoots(); - rearrangeRoots(); - -/* # initialize the kill BasicBlock of all jlcall-frames - * bb-uses : map, assign|live|kill > > - * for inst in gc-frame(f) - * if inst match "a call to make-jlcall-frame" - * kill-use = get-unique-use(inst) - * bb-uses[bb][] = kill - */ - std::map > bb_uses; - std::priority_queue< std::pair > frames; - for (BasicBlock::iterator I = gcframe->getParent()->begin(), E(gcframe); I != E; ) { - CallInst* callInst = dyn_cast(&*I); - ++I; - if (callInst && callInst->getCalledValue() == jlcall_frame_func) { - BasicBlock *bb = NULL; - unsigned arg_n = cast(callInst->getArgOperand(0))->getZExtValue(); - frames.push(std::make_pair(arg_n, callInst)); - // the jlcall frame should have been passed to exactly one call (the jlcall) -- find its basic-block - for (User::use_iterator use = callInst->use_begin(), usee = callInst->use_end(); use != usee; ++use) { -#if JL_LLVM_VERSION >= 30500 - User *user = use->getUser(); -#else - User *user = use.getUse().getUser(); -#endif - if (CallInst *callInst = dyn_cast(user)) { - assert(bb == NULL); - bb = callInst->getParent(); -#ifdef JL_NDEBUG - break; -#endif - } - } - assert(bb != NULL); - std::map &inuse_list = bb_uses[bb]; - for (unsigned arg_offset = 0; arg_offset < arg_n; ++arg_offset) { - inuse_list[frame_register(callInst, arg_offset)] = liveness::kill; - } - } - } - -/* # initialize the dataflow queue for tracking liveness - * bb-queue : queue - * for bb in iterator(f) - * inuse-list = &bb-uses[bb] - * for inst in reverse-iterator(f) - * if inst matches store-inst # todo: or inst matches "gc-store-inst" (for stores to non-stack-slots) - * if inst->operand(0) matches "a call to make-jlcall-frame" (or gep thereof) - * def = - * if inuse-list[def] is kill - * inuse-list[def] = assign|kill - * if not has-live-out(bb) - * continue - * for pred in predecessors(bb) - * if not pred in bb-queue - * push-back(bb-queue, pred) - */ - std::vector bb_queue; - for (std::map >::iterator - live_reg = bb_uses.begin(), e = bb_uses.end(); live_reg != e; ++live_reg) { - BasicBlock *bb = live_reg->first; - std::map &inuse_list = live_reg->second; - unsigned live_out = inuse_list.size(); - - for (BasicBlock::iterator ri = bb->end(); ri != bb->begin(); ) { - Instruction *i = &*--ri; - if (StoreInst *storeInst = dyn_cast(i)) { - frame_register def = get_gcroot(storeInst->getPointerOperand()); - if (CallInst *callInst = def.first) { - if (callInst->getCalledValue() == jlcall_frame_func) { - std::map::iterator inuse_reg = inuse_list.find(def); - if (inuse_reg != inuse_list.end() && inuse_reg->second == liveness::kill) { - inuse_reg->second |= liveness::assign; - --live_out; - } - } - } - } - } - if (live_out == 0) - continue; - assert(&*bb != &F.getEntryBlock()); // only undef variables should live-out from the entry bb - for (pred_iterator PI = pred_begin(bb), PE = pred_end(bb); PI != PE; ++PI) { - if (std::find(bb_queue.begin(), bb_queue.end(), *PI) == bb_queue.end()) - bb_queue.push_back(*PI); - } - } - - -/* # follow liveness information flow until termination - * while not empty(bb-queue) - * bb = pop(bb-queue) - * inuse-list = &bb-uses[bb] - * changes = 0 - * for succ in successors(bb) - * for in bb-uses[succ] - * if (not assign in op) and not (inuse-list[def] contains live or assign) - * # need to add live value from successor to current block, unless it was already marked - * inuse-list[def] |= live - * changes += 1 - * for inst in iterator(bb) - * if inst matches store-inst # todo: or inst matches "gc-store-inst" (for stores to non-stack-slots) - * if inst->operand(0) matches "a call to make-jlcall-frame" (or gep thereof) - * def = - * if live in inuse-list[def] - * inuse-list[def] |= assign - * if not kill in inuse-list[def] - * # found the assignment, def is no longer live - * inuse-list[def] &= ~live - * else - * # not a true kill due to recursion -- the kill happened before this assign in this BB, so it is still live - * changes -= 1 - * # if the live list changed, make sure all predecessors are in the queue to be reanalyzed - * if changes == 0 - * continue - * for pred in predecessors(bb) - * if not pred in bb-queue - * push-back(bb-queue, pred) - */ - - while (!bb_queue.empty()) { - BasicBlock *bb = bb_queue.back(); - bb_queue.pop_back(); - std::map &inuse_list = bb_uses[bb]; - unsigned changes = 0; - for (succ_iterator SI = succ_begin(bb), SE = succ_end(bb); SI != SE; ++SI) { - std::map &succ_uses = bb_uses[*SI]; - for (std::map::iterator reg = succ_uses.begin(), rege = succ_uses.end(); reg != rege; ++reg) { - if (!(reg->second & liveness::assign)) { - liveness::id &live = inuse_list[reg->first]; - if (!(live & (liveness::live | liveness::assign))) { - live |= liveness::live; - ++changes; - } - } - } - } - if (!changes) // short-circuit - continue; - for (BasicBlock::iterator i = bb->begin(), ie = bb->end(); i != ie; ++i) { - if (StoreInst *storeInst = dyn_cast(&*i)) { - frame_register def = get_gcroot(storeInst->getPointerOperand()); - if (CallInst *callInst = def.first) { - if (callInst->getCalledValue() == jlcall_frame_func) { - std::map::iterator inuse_reg = inuse_list.find(def); - if (inuse_reg != inuse_list.end() && (inuse_reg->second & liveness::live)) { - inuse_reg->second |= liveness::assign; - if (!(inuse_reg->second & liveness::kill)) - inuse_reg->second &= ~liveness::live; - --changes; - } - } - } - } - } - if (!changes) - continue; - assert(bb != &F.getEntryBlock()); // only undef variables should live-out from the entry bb - for (pred_iterator PI = pred_begin(bb), PE = pred_end(bb); PI != PE; ++PI) { - if (std::find(bb_queue.begin(), bb_queue.end(), *PI) == bb_queue.end()) - bb_queue.push_back(*PI); - } - } - -/* # allocate space in locals for the variables - * TBD - */ - -/* # allocate space in temp-args for each jlcall frame - * regs-used = zip(get-basic-blocks(), falses) - * for in frames - * frame-offset = find-space-for(inst, bb-uses, regs-used) - * record-usage(inst, bb-uses, regs-used, frame-offset) - * # frame iterator allocates space in reverse size order - * # so that the large frames get allocated first - * # and the smaller frames just fill in the gaps - * # I believe this is likely to give good results (compact gc-frames) - */ - std::map regs_used; - std::map frame_offsets; - unsigned maxDepth = 0; - for (; !frames.empty(); frames.pop()) { - std::pair frame = frames.top(); - unsigned arg_n = frame.first; - if (arg_n == 0) continue; - CallInst *callInst = frame.second; - unsigned frame_offset = find_space_for(callInst, bb_uses, regs_used); - record_usage(callInst, bb_uses, regs_used, frame_offset); - frame_offsets[callInst] = frame_offset; - if (frame_offset + arg_n > maxDepth) - maxDepth = frame_offset + arg_n; - } - -/* # cleanup and finalize the IR */ - for (Function::iterator bb = F.begin(), be = F.end(); bb != be; ++bb) { - for (BasicBlock::iterator i = bb->begin(), ie = bb->end(); i != ie; ) { - Instruction *inst = &*i; - ++i; - // delete the now unused gckill information - if (CallInst* callInst = dyn_cast(inst)) { - Value *callee = callInst->getCalledValue(); - if (callee == gckill_func || callee == gcroot_flush_func) { - callInst->eraseFromParent(); - } - } - // delete any StoreInst to a gcframe slot that isn't live - else if (StoreInst *storeInst = dyn_cast(inst)) { - frame_register def = get_gcroot(storeInst->getPointerOperand()); - if (CallInst *gcroot = def.first) { - if (gcroot->getCalledValue() == jlcall_frame_func) { - std::map &inuse_list = bb_uses[storeInst->getParent()]; - std::map::iterator inuse_reg = inuse_list.find(def); - if (inuse_reg == inuse_list.end()) - storeInst->eraseFromParent(); - } - } - } - } - } - - Instruction *tempSlot; - if (frame_offsets.empty()) { - tempSlot = NULL; - } - else { - tempSlot = GetElementPtrInst::Create(LLVM37_param(NULL) gcframe, ArrayRef(ConstantInt::get(T_int32, 2))); -#ifdef JL_DEBUG_BUILD - tempSlot->setName("temproots"); -#endif - tempSlot->insertAfter(gcframe); - if (last_gcframe_inst == gcframe) - last_gcframe_inst = tempSlot; - - // finalize all of the jlcall frames by replacing all of the frames with the appropriate gep(tempslot) - for (std::map::iterator frame = frame_offsets.begin(), framee = frame_offsets.end(); frame != framee; ++frame) { - CallInst *gcroot = frame->first; - tbaa_decorate_gcframe(gcroot, tbaa_gcframe); - Value* offset[1] = {ConstantInt::get(T_int32, frame->second)}; - GetElementPtrInst *gep = GetElementPtrInst::Create(LLVM37_param(NULL) tempSlot, makeArrayRef(offset)); - gep->insertAfter(last_gcframe_inst); - gcroot->replaceAllUsesWith(gep); - gep->takeName(gcroot); - gcroot->eraseFromParent(); - last_gcframe_inst = gep; - } - } - -/* # replace all intermediate roots defs with the appropriate gep(gcroot) - * for inst in entry-basic-block(function) - * if inst matches "gc-root" - * slot = get-argument(inst) - * newslot = CreateGEP(gc-frame) -> at InsertPoint(gc-frame) - * Replace(slot, newslot) -> at InsertPoint(gc-frame) - * CreateStore(NULL, newslot) -> at InsertPoint(gc-frame) - */ -#if JL_LLVM_VERSION >= 30600 - DIBuilder dbuilder(M, false); -#endif - unsigned argSpaceSize = 0; - for (BasicBlock::iterator I = gcframe->getParent()->begin(), E(gcframe); I != E; ) { - Instruction* inst = &*I; - ++I; - if (CallInst* callInst = dyn_cast(inst)) { - if (callInst->getCalledValue() == gcroot_func) { - unsigned offset = 2 + argSpaceSize++; - Instruction *argTempi = GetElementPtrInst::Create(LLVM37_param(NULL) gcframe, ArrayRef(ConstantInt::get(T_int32, offset))); - argTempi->insertAfter(last_gcframe_inst); -#if JL_LLVM_VERSION >= 30600 - Metadata *md = ValueAsMetadata::getIfExists(callInst); - if (md) { - Value *mdValue = MetadataAsValue::get(M.getContext(), md); - for (User::use_iterator use = mdValue->use_begin(), usee = mdValue->use_end(); use != usee; ) { - // need to recreate the dbg_declare accordingly -- sadly llvm can't handle this in RAUW - User *user = use->getUser(); - ++use; - if (CallInst* dbg = dyn_cast(user)) { - Function *called = dbg->getCalledFunction(); - if (called && called->getIntrinsicID() == Intrinsic::dbg_declare) { - DILocalVariable *dinfo = cast(cast(dbg->getOperand(1))->getMetadata()); - DIExpression *expr = cast(cast(dbg->getOperand(2))->getMetadata()); - SmallVector addr; - addr.push_back(llvm::dwarf::DW_OP_plus); - addr.push_back(offset * sizeof(void*)); - addr.append(expr->elements_begin(), expr->elements_end()); - expr = dbuilder.createExpression(addr); - dbuilder.insertDeclare(gcframe, dinfo, expr, -#if JL_LLVM_VERSION >= 30700 - dbg->getDebugLoc(), -#endif - dbg->getParent()); - dbg->eraseFromParent(); - } - } - } - } -#endif - tbaa_decorate_gcframe(callInst, tbaa_gcframe); - callInst->replaceAllUsesWith(argTempi); - argTempi->takeName(callInst); - callInst->eraseFromParent(); - // Initialize the slots for function variables to NULL - StoreInst *store = new StoreInst(V_null, argTempi); - store->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_gcframe); - store->insertAfter(argTempi); - last_gcframe_inst = store; - } - } - else if (AllocaInst *allocaInst = dyn_cast(inst)) { - if (allocaInst->getAllocatedType() == V_null->getType()) { - // TODO: this is overly aggressive at zeroing allocas that may not actually need to be zeroed - StoreInst *store = new StoreInst(V_null, allocaInst); - store->insertAfter(allocaInst); - } - } - } -#if JL_LLVM_VERSION >= 30600 - dbuilder.finalize(); -#endif - - if (argSpaceSize + maxDepth == 0) { - // 0 roots; remove gc frame entirely - gcframe->eraseFromParent(); - } - else { - // Initialize the slots for temporary variables to NULL - if (maxDepth > 0) { - BitCastInst *tempSlot_i8 = new BitCastInst(tempSlot, PointerType::get(T_int8, 0), "", last_gcframe_inst); - Type *argsT[2] = {tempSlot_i8->getType(), T_int32}; - Function *memset = Intrinsic::getDeclaration(&M, Intrinsic::memset, makeArrayRef(argsT)); - Value *args[5] = { - tempSlot_i8, // dest - ConstantInt::get(T_int8, 0), // val - ConstantInt::get(T_int32, sizeof(jl_value_t*)*maxDepth), // len - ConstantInt::get(T_int32, 0), // align - ConstantInt::get(T_int1, 0)}; // volatile - CallInst *zeroing = CallInst::Create(memset, makeArrayRef(args)); - zeroing->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_gcframe); - zeroing->insertAfter(tempSlot_i8); - last_gcframe_inst = zeroing; - } - - gcframe->setOperand(0, ConstantInt::get(T_int32, 2 + argSpaceSize + maxDepth)); // fix up the size of the gc frame - if (tempSlot) - tempSlot->setOperand(1, ConstantInt::get(T_int32, 2 + argSpaceSize)); // fix up the offset to the temp slot space - - IRBuilder<> builder(F.getContext()); - Type *T_ppjlvalue = V_null->getType()->getPointerTo(); -#ifdef _P64 - Type *T_size = T_int64; -#else - Type *T_size = T_int32; -#endif - builder.SetInsertPoint(&*(++BasicBlock::iterator(last_gcframe_inst))); // set insert *before* point, e.g. after the gcframe - DebugLoc noDbg; - builder.SetCurrentDebugLocation(noDbg); - - Instruction *inst = - builder.CreateStore(ConstantInt::get(T_size, (argSpaceSize + maxDepth) << 1), - builder.CreateBitCast(builder.CreateConstGEP1_32(gcframe, 0), T_size->getPointerTo())); - inst->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_gcframe); - inst = builder.CreateStore(builder.CreateLoad(builder.Insert(get_pgcstack(ptlsStates))), - builder.CreatePointerCast(builder.CreateConstGEP1_32(gcframe, 1), PointerType::get(T_ppjlvalue,0))); - inst->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_gcframe); - builder.CreateStore(gcframe, builder.Insert(get_pgcstack(ptlsStates))); - - // Finish by emitting the gc pops before any return - for(Function::iterator I = F.begin(), E = F.end(); I != E; ++I) { - if (isa(I->getTerminator())) { - builder.SetInsertPoint(I->getTerminator()); // set insert *before* Ret - Instruction *gcpop = - (Instruction*)builder.CreateConstGEP1_32(gcframe, 1); - inst = builder.CreateLoad(gcpop); - inst->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_gcframe); - inst = builder.CreateStore(builder.CreatePointerCast(inst, T_ppjlvalue), - builder.Insert(get_pgcstack(ptlsStates))); - inst->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_gcframe); - } - } - } - -#ifndef JL_NDEBUG - jl_gc_frame_stats.count++; - jl_gc_frame_stats.locals += argSpaceSize; - jl_gc_frame_stats.temp += maxDepth; -#endif -} - -struct LowerGCFrame: public ModulePass { - static char ID; - LowerGCFrame() : ModulePass(ID) - {} - -private: - void runOnFunction(Module *M, Function &F, Function *ptls_getter, - Type *T_pjlvalue, MDNode *tbaa_gcframe); - bool runOnModule(Module &M) override; -}; - -static void eraseFunction(Module &M, const char *name) -{ - if (Function *f = M.getFunction(name)) { - f->eraseFromParent(); - } -} - -bool LowerGCFrame::runOnModule(Module &M) -{ - MDNode *tbaa_gcframe = tbaa_make_child("jtbaa_gcframe").first; - - Function *ptls_getter = M.getFunction("jl_get_ptls_states"); - FunctionType *functype = nullptr; - Type *T_pjlvalue = nullptr; - if (ptls_getter) { - functype = ptls_getter->getFunctionType(); - auto T_ppjlvalue = - cast(functype->getReturnType())->getElementType(); - T_pjlvalue = cast(T_ppjlvalue)->getElementType(); - } - for (auto F = M.begin(), E = M.end(); F != E; ++F) { - if (F->isDeclaration()) - continue; - runOnFunction(&M, *F, ptls_getter, T_pjlvalue, tbaa_gcframe); - } - - // Cleanup for GC frame lowering. - eraseFunction(M, "julia.gc_root_decl"); - eraseFunction(M, "julia.gc_root_kill"); - eraseFunction(M, "julia.jlcall_frame_decl"); - eraseFunction(M, "julia.gcroot_flush"); - return true; -} - -void LowerGCFrame::runOnFunction(Module *M, Function &F, Function *ptls_getter, - Type *T_pjlvalue, MDNode *tbaa_gcframe) -{ - CallInst *ptlsStates = nullptr; - for (auto I = F.getEntryBlock().begin(), E = F.getEntryBlock().end(); - ptls_getter && I != E; ++I) { - if (CallInst *callInst = dyn_cast(&*I)) { - if (callInst->getCalledValue() == ptls_getter) { - ptlsStates = callInst; - break; - } - } - } - JuliaGCAllocator allocator(F, ptlsStates, T_pjlvalue, tbaa_gcframe); - allocator.allocate_frame(); -} - -char LowerGCFrame::ID = 0; - -static RegisterPass X("LowerGCFrame", "Lower GCFrame Pass", - false /* Only looks at CFG */, - false /* Analysis Pass */); -} - -#ifndef JL_NDEBUG // llvm assertions build -// gdb debugging code for inspecting the bb_uses map -void jl_dump_bb_uses(std::map > &bb_uses) -{ - for (std::map >::iterator - live_reg = bb_uses.begin(), e = bb_uses.end(); live_reg != e; ++live_reg) { - BasicBlock *bb = live_reg->first; - errs() << '\n' << bb << '\n'; - for (std::map::iterator - regs = live_reg->second.begin(), regse = live_reg->second.end(); regs != regse; ++regs) { - errs() << regs->second << " #" << regs->first.second << ' ' << regs->first.first << '\n'; - } - } -} -#endif - -Pass *createLowerGCFramePass() -{ - return new LowerGCFrame(); -} - -extern "C" JL_DLLEXPORT -void LLVMAddLowerGCFramePass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createLowerGCFramePass()); -} From cff6a5c398a1a21f5d244b4b9b57754bc64805d8 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Thu, 1 Jun 2017 14:41:52 -0400 Subject: [PATCH 1097/1534] Remove unnecessary MaybeNotePhiJLCallFrameUses --- src/llvm-late-gc-lowering.cpp | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/src/llvm-late-gc-lowering.cpp b/src/llvm-late-gc-lowering.cpp index ec02ec536f4ac..3971dfcf158aa 100644 --- a/src/llvm-late-gc-lowering.cpp +++ b/src/llvm-late-gc-lowering.cpp @@ -328,7 +328,6 @@ struct LateLowerGCFrame: public FunctionPass { Instruction *get_pgcstack(Instruction *ptlsStates); bool CleanupIR(Function &F); void NoteUseChain(State &S, BBState &BBS, User *TheUser); - void MaybeNotePhiJLCallFrameUses(State &S, BBState &BBS, PHINode *Phi); }; static unsigned getValueAddrSpace(Value *V) { @@ -651,25 +650,6 @@ void RecursivelyVisitStoresTo(callback f, Value *V) { }, V); } -/* - * Mark phi uses in jlcall frames. Note this does not do any sort of phi lifting - * which is done only if a phi actually ends up getting used somewhere. - */ -void LateLowerGCFrame::MaybeNotePhiJLCallFrameUses(State &S, BBState &BBS, PHINode *Phi) -{ - if (!Phi->getType()->isPointerTy()) - return; - Type *ElType = cast(Phi->getType())->getElementType(); - if (isSpecialPtr(ElType) && cast(ElType)->getAddressSpace() == AddressSpace::Tracked) { - for (unsigned i = 0; i < Phi->getNumIncomingValues(); ++i) { - RecursivelyVisitStoresTo([&](StoreInst *SI){ - BBState &IncombingBBS = S.BBStates[Phi->getIncomingBlock(i)]; - NoteUse(S, IncombingBBS, SI->getValueOperand(), IncombingBBS.PhiOuts); - }, Phi->getIncomingValue(i)); - } - } -} - static void dumpBitVectorValues(State &S, BitVector &BV) { bool first = true; for (int Idx = BV.find_first(); Idx >= 0; Idx = BV.find_next(Idx)) { @@ -856,10 +836,7 @@ State LateLowerGCFrame::LocalScan(Function &F) { NoteOperandUses(S, BBS, I, BBS.UpExposedUsesUnrooted); } } else if (PHINode *Phi = dyn_cast(&I)) { - // We can have phis of jlcall frames. We consider each of the - // values stored to that jlcall frame a phi use if (!isSpecialPtr(Phi->getType())) { - MaybeNotePhiJLCallFrameUses(S, BBS, Phi); continue; } // We need to insert an extra phi for the GC root From eefbde75326d88b5c19e05310bc2d091f93f72c6 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Fri, 2 Jun 2017 18:22:08 -0400 Subject: [PATCH 1098/1534] Change IR representation of jlcall frames Details are in the devdocs. This scheme is signfificantly simpler. --- doc/src/devdocs/llvm.md | 24 ++++ src/cgutils.cpp | 2 +- src/codegen.cpp | 138 +++++++---------------- src/codegen_shared.h | 3 + src/llvm-gc-invariant-verifier.cpp | 12 ++ src/llvm-late-gc-lowering.cpp | 174 ++++++++--------------------- test/llvmpasses/gcroots-391.ll | 67 ----------- test/llvmpasses/gcroots-50.ll | 64 ----------- test/llvmpasses/gcroots.ll | 139 ----------------------- 9 files changed, 127 insertions(+), 496 deletions(-) delete mode 100644 test/llvmpasses/gcroots-391.ll delete mode 100644 test/llvmpasses/gcroots-50.ll diff --git a/doc/src/devdocs/llvm.md b/doc/src/devdocs/llvm.md index ecfe7a0eb3dd0..65aa8b7ef2c88 100644 --- a/doc/src/devdocs/llvm.md +++ b/doc/src/devdocs/llvm.md @@ -108,6 +108,30 @@ study it and the pass of interest in isolation. The last step is labor intensive. Suggestions on a better way would be appreciated. +## The jlcall calling convention + +Julia has a generic calling convention for unoptimized code, which looks somewhat +as follows: +``` + jl_value_t *any_unoptimized_call(jl_value_t *, jl_value_t **, int); +``` +where the first argument is the boxed function object, the second argument is +an on-stack array of arguments and the third is the number of arguments. Now, +we could perform a straightforward lowering and emit an alloca for the argument +array. However, this would betray the SSA nature of the uses at the callsite, +making optimizations (including GC root placement), significantly harder. +Instead, we emit it as follows: +``` + %bitcast = bitcast @any_unoptimized_call to %jl_value_t *(*)(%jl_value_t *, %jl_value_t *) + call cc 37 %jl_value_t *%bitcast(%jl_value_t *%arg1, %jl_value_t *%arg2) +``` +The special `cc 37` annotation marks the fact that this call site is really using +jlcall calling convention. This allows us to retain the SSA-ness of the +uses throughout the optimizer. GC root placement will later lower this call to +the original C ABI. In the code the calling convention number is represented by +the `JLCALL_F_CC` constant. In addition, there ist the `JLCALL_CC` calling +convention which functions similarly, but omits the first argument. + ## GC root placement GC root placement is done by an LLVM late in the pass pipeline. Doing GC root diff --git a/src/cgutils.cpp b/src/cgutils.cpp index a317c76bea4c8..41ebed0981fd2 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -1117,7 +1117,7 @@ static std::pair emit_isa(const jl_cgval_t &x, jl_value_t *type, c maybe_decay_untracked(literal_pointer_val(type))), false); } // everything else can be handled via subtype tests - Value *vxt = emit_typeof_boxed(x, ctx); + Value *vxt = maybe_decay_untracked(emit_typeof_boxed(x, ctx)); return std::make_pair(builder.CreateICmpNE( #if JL_LLVM_VERSION >= 30700 builder.CreateCall(prepare_call(jlsubtype_func), diff --git a/src/codegen.cpp b/src/codegen.cpp index 083774bfef9fe..0aefa9fe40d93 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -646,7 +646,6 @@ static jl_cgval_t emit_expr(jl_value_t *expr, jl_codectx_t *ctx); static Value *emit_local_root(jl_codectx_t *ctx, jl_varinfo_t *vi = NULL); static void mark_gc_use(const jl_cgval_t &v); -static Value *make_jlcall(ArrayRef args, jl_codectx_t *ctx); static Value *global_binding_pointer(jl_module_t *m, jl_sym_t *s, jl_binding_t **pbnd, bool assign, jl_codectx_t *ctx); static jl_cgval_t emit_checked_var(Value *bp, jl_sym_t *name, jl_codectx_t *ctx, bool isvol, MDNode *tbaa); @@ -657,6 +656,10 @@ static GlobalVariable *prepare_global(GlobalVariable *G, Module *M = jl_builderM static Value *prepare_call(Value *Callee); static Value *prepare_call(IRBuilder<> &builder, Value *Callee); static void CreateTrap(IRBuilder<> &builder); +static Value *emit_jlcall(Value *theFptr, Value *theF, jl_cgval_t *args, + size_t nargs, jl_codectx_t *ctx); +static Value *emit_jlcall(Value *theFptr, Value *theF, jl_value_t **args, + size_t nargs, jl_codectx_t *ctx); template static void push_gc_use(T &&vec, const jl_cgval_t &v) { @@ -2399,50 +2402,6 @@ static void mark_gc_use(const jl_cgval_t &v) builder.CreateCall(prepare_call(gckill_func), v.gcroot); } -// turn an array of arguments into a single object suitable for passing to a jlcall -static Value *make_jlcall(ArrayRef args, jl_codectx_t *ctx) -{ - Value *largs = new AllocaInst(T_prjlvalue, -#if JL_LLVM_VERSION >= 50000 - 0, -#endif - ConstantInt::get(T_int32, args.size()), "jlcall", ctx->ptlsStates); - int slot = 0; - assert(args.size() > 0); - Value *lifetime_largs = largs; -#if JL_LLVM_VERSION < 50000 - lifetime_largs = builder.CreateBitCast(largs, T_pint8); - auto lifetime_start = Intrinsic::getDeclaration(jl_Module, Intrinsic::lifetime_start); -#else - auto lifetime_start = Intrinsic::getDeclaration(jl_Module, Intrinsic::lifetime_start, {T_pprjlvalue}); -#endif - builder.CreateCall(lifetime_start, { - ConstantInt::get(T_int64, args.size()*sizeof(jl_value_t*)), - lifetime_largs}); - for (ArrayRef::iterator I = args.begin(), E = args.end(); I < E; ++I, ++slot) { - Value *arg = boxed(**I, ctx, false); // mark_gc_use isn't needed since jlcall_frame_func can take ownership of this root - GetElementPtrInst *newroot = GetElementPtrInst::Create(LLVM37_param(NULL) largs, - ArrayRef(ConstantInt::get(T_int32, slot))); - builder.Insert(newroot); - arg = maybe_decay_untracked(arg); - builder.CreateStore(arg, newroot); - } - return largs; -} - -static void end_lifetime(Value *args, size_t size, jl_codectx_t *ctx) { - Value *lifetime_args = args; -#if JL_LLVM_VERSION < 50000 - lifetime_args = builder.CreateBitCast(args, T_pint8); - auto lifetime_end = Intrinsic::getDeclaration(jl_Module, Intrinsic::lifetime_end); -#else - auto lifetime_end = Intrinsic::getDeclaration(jl_Module, Intrinsic::lifetime_end, {T_pprjlvalue}); -#endif - builder.CreateCall(lifetime_end, { - ConstantInt::get(T_int64, size*sizeof(jl_value_t*)), - lifetime_args}); -} - static void jl_add_method_root(jl_codectx_t *ctx, jl_value_t *val) { if (jl_is_leaf_type(val) || jl_is_bool(val) || jl_is_symbol(val) || @@ -2510,18 +2469,11 @@ static jl_cgval_t emit_getfield(jl_value_t *expr, jl_sym_t *name, jl_codectx_t * // and offsets of some fields are independent of parameters. // TODO: generic getfield func with more efficient calling convention - jl_cgval_t arg1 = emit_expr(expr, ctx); - jl_cgval_t arg2 = mark_julia_const((jl_value_t*)name); - const jl_cgval_t* myargs_array[2] = {&arg1, &arg2}; - Value *myargs = make_jlcall(makeArrayRef(myargs_array), ctx); -#if JL_LLVM_VERSION >= 30700 - Value *result = builder.CreateCall(prepare_call(jlgetfield_func), - {maybe_decay_untracked(V_null), myargs, ConstantInt::get(T_int32,2)}); -#else - Value *result = builder.CreateCall3(prepare_call(jlgetfield_func), - maybe_decay_untracked(V_null), myargs, ConstantInt::get(T_int32,2)); -#endif - end_lifetime(myargs, 2, ctx); + jl_cgval_t myargs_array[2] = { + emit_expr(expr, ctx), + mark_julia_const((jl_value_t*)name) + }; + Value *result = emit_jlcall(jlgetfield_func, maybe_decay_untracked(V_null), myargs_array, 2, ctx); bool needsgcroot = true; // !arg1.isimmutable || !jl_is_leaf_type(arg1.typ) || !is_datatype_all_pointers((jl_datatype_t*)arg1.typ); // TODO: probably want this as a llvm pass jl_cgval_t ret = mark_julia_type(result, true, jl_any_type, ctx, needsgcroot); // (typ will be patched up by caller) return ret; @@ -3272,37 +3224,42 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args, return false; } -static Value *emit_jlcall(Value *theFptr, Value *theF, jl_value_t **args, +static Value *emit_jlcall(Value *theFptr, Value *theF, jl_cgval_t *args, size_t nargs, jl_codectx_t *ctx) { // emit arguments - Value *myargs; - if (nargs > 0) { - jl_cgval_t *anArg = (jl_cgval_t*)alloca(sizeof(jl_cgval_t) * nargs); - const jl_cgval_t **largs = (const jl_cgval_t**)alloca(sizeof(jl_cgval_t*) * nargs); - for(size_t i=0; i < nargs; i++) { - anArg[i] = emit_expr(args[i], ctx); - largs[i] = &anArg[i]; - } - // put into argument space - myargs = make_jlcall(makeArrayRef(largs, nargs), ctx); - } - else { - myargs = Constant::getNullValue(T_pprjlvalue); - } -#if JL_LLVM_VERSION >= 30700 - Value *result = builder.CreateCall(prepare_call(theFptr), {maybe_decay_untracked(theF), myargs, - ConstantInt::get(T_int32,nargs)}); -#else - Value *result = builder.CreateCall3(prepare_call(theFptr), maybe_decay_untracked(theF), myargs, - ConstantInt::get(T_int32,nargs)); -#endif - if (nargs > 0) { - end_lifetime(myargs, nargs, ctx); - } + SmallVector theArgs; + if (theF) + theArgs.push_back(theF); + for(size_t i=0; i < nargs; i++) { + Value *arg = maybe_decay_untracked(boxed(args[i], ctx, false)); + theArgs.push_back(arg); + } + SmallVector argsT; + for(size_t i=0; i < nargs + (theF != nullptr); i++) { + argsT.push_back(T_prjlvalue); + } + FunctionType *FTy = FunctionType::get(T_prjlvalue, argsT, false); + CallInst *result = builder.CreateCall(FTy, + builder.CreateBitCast(prepare_call(theFptr), FTy->getPointerTo()), + theArgs); + if (theF) + result->setCallingConv(JLCALL_F_CC); + else + result->setCallingConv(JLCALL_CC); return result; } + +static Value *emit_jlcall(Value *theFptr, Value *theF, jl_value_t **args, + size_t nargs, jl_codectx_t *ctx) +{ + jl_cgval_t *cgargs = (jl_cgval_t*)alloca(sizeof(jl_cgval_t) * nargs); + for (size_t i = 0; i < nargs; ++i) + cgargs[i] = emit_expr(args[i], ctx); + return emit_jlcall(theFptr, theF, cgargs, nargs, ctx); +} + static jl_cgval_t emit_call_function_object(jl_method_instance_t *li, const jl_cgval_t &theF, jl_llvm_functions_t decls, jl_value_t **args, size_t nargs, jl_value_t *callexpr, jl_codectx_t *ctx) { @@ -3521,22 +3478,7 @@ static jl_cgval_t emit_call(jl_expr_t *ex, jl_codectx_t *ctx) // emit function and arguments nargs++; // add function to nargs count - jl_cgval_t *anArg = (jl_cgval_t*)alloca(sizeof(jl_cgval_t) * nargs); - const jl_cgval_t **largs = (const jl_cgval_t**)alloca(sizeof(jl_cgval_t*) * nargs); - for(size_t i=0; i < nargs; i++) { - anArg[i] = emit_expr(args[i], ctx); - largs[i] = &anArg[i]; - } - // put into argument space - Value *myargs = make_jlcall(makeArrayRef(largs, nargs), ctx); -#if JL_LLVM_VERSION >= 30700 - Value *callval = builder.CreateCall(prepare_call(jlapplygeneric_func), - {myargs, ConstantInt::get(T_int32, nargs)}); -#else - Value *callval = builder.CreateCall2(prepare_call(jlapplygeneric_func), - myargs, ConstantInt::get(T_int32, nargs)); -#endif - end_lifetime(myargs, nargs, ctx); + Value *callval = emit_jlcall(jlapplygeneric_func, nullptr, args, nargs, ctx); result = mark_julia_type(callval, true, expr_type(expr, ctx), ctx); JL_GC_POP(); diff --git a/src/codegen_shared.h b/src/codegen_shared.h index 81c3a1f9c906b..6930d007e8315 100644 --- a/src/codegen_shared.h +++ b/src/codegen_shared.h @@ -4,3 +4,6 @@ enum AddressSpace { FirstSpecial = Tracked, LastSpecial = CalleeRooted, }; + +#define JLCALL_CC (CallingConv::ID)36 +#define JLCALL_F_CC (CallingConv::ID)37 diff --git a/src/llvm-gc-invariant-verifier.cpp b/src/llvm-gc-invariant-verifier.cpp index c8964440111fc..629152ee62ef3 100644 --- a/src/llvm-gc-invariant-verifier.cpp +++ b/src/llvm-gc-invariant-verifier.cpp @@ -56,6 +56,7 @@ struct GCInvariantVerifier : public FunctionPass, public InstVisitorgetType(); + Check(Ty->isPointerTy() && cast(Ty)->getAddressSpace() == AddressSpace::Tracked, + "Invalid derived pointer in jlcall", &CI); + } + } +} + /* These next two are caught by the regular verifier on LLVM 5.0+, but we may want to run this on earlier LLVM versions. */ void GCInvariantVerifier::visitIntToPtrInst(IntToPtrInst &IPI) { diff --git a/src/llvm-late-gc-lowering.cpp b/src/llvm-late-gc-lowering.cpp index 3971dfcf158aa..5a4beca3ef1a7 100644 --- a/src/llvm-late-gc-lowering.cpp +++ b/src/llvm-late-gc-lowering.cpp @@ -54,7 +54,6 @@ using namespace llvm; b) a store to a tracked/derived value c) a store OF a tracked/derived value d) a use of a value as a call operand (including operand bundles) - e) an indirect use through a jlcall array - Any safepoint Crucially, we also perform pointer numbering during the local scan, @@ -117,7 +116,7 @@ using namespace llvm; Unlike earlier iterations of the gc root placement logic, jlcall frames are no longer treated as a special case and need not necessarily be sunk - into the gc frame. Additionally, the frontend now emits lifetime + into the gc frame. Additionally, we now emit lifetime intrinsics, so regular stack slot coloring will merge any jlcall frames not sunk into the gc frame. Nevertheless performing such sinking can still be profitable. Since all arguments to a jlcall are guaranteed to be live @@ -634,22 +633,6 @@ void RecursivelyVisit(callback f, Value *V) { } } -template -void RecursivelyVisitStoresTo(callback f, Value *V) { - RecursivelyVisit( - [&](Use &VU) { - assert(isa(VU.getUser())); - if (VU.getOperandNo() != 1) { - // We spill jlcall arg arrays to the stack for - // better debugging. These have no uses, so we're - // ok. Allow that as a special case. - assert(cast(VU.getUser())->getPointerOperand()->getNumUses() == 1); - return; - } - f(cast(VU.getUser())); - }, V); -} - static void dumpBitVectorValues(State &S, BitVector &BV) { bool first = true; for (int Idx = BV.find_first(); Idx >= 0; Idx = BV.find_next(Idx)) { @@ -686,40 +669,8 @@ JL_USED_FUNC static void dumpLivenessState(Function &F, State &S) { } } -static std::set DominatingLifetimes(DominatorTree &DT, Instruction *I, Value *V) { - // Find all lifetime starts that dominate this call - // instruction. - std::set Dead; - std::set LifeTimeStarts; - // This could be combined with the visit in the caller or even cached - // Don't bother with the additional complexity for now. - RecursivelyVisit([&](Use &VU) { - IntrinsicInst *II = cast(VU.getUser()); - if (II->getIntrinsicID() == Intrinsic::lifetime_start && - DT.dominates(II, I)) { - LifeTimeStarts.insert(II); - } - }, V); - // If one lifetime start dominates another, we can - // remove the earlier one. - for (auto *LifetimeStart : LifeTimeStarts) { - for (auto *LifetimeStart2 : LifeTimeStarts) { - if (LifetimeStart == LifetimeStart2 || - Dead.find(LifetimeStart2) != Dead.end()) - continue; - if (DT.dominates(LifetimeStart, LifetimeStart2)) { - Dead.insert(LifetimeStart); - } - } - } - for (auto *ToDelete : Dead) - LifeTimeStarts.erase(ToDelete); - return LifeTimeStarts; -} - State LateLowerGCFrame::LocalScan(Function &F) { State S; - auto &DT = getAnalysis().getDomTree(); for (BasicBlock &BB : F) { BBState &BBS = S.BBStates[&BB]; for (auto it = BB.rbegin(); it != BB.rend(); ++it) { @@ -731,89 +682,12 @@ State LateLowerGCFrame::LocalScan(Function &F) { } MaybeNoteDef(S, BBS, CI, BBS.Safepoints); NoteOperandUses(S, BBS, I); - // Note uses via jlcall frames for (Use &U : CI->operands()) { Value *V = U; if (isUnionRep(V->getType())) { NoteUse(S, BBS, V); continue; } - if (!V->getType()->isPointerTy()) - continue; - if (isSpecialPtr(cast(V->getType())->getElementType())) { - V = FindBaseValue(S, V, false); - if (AllocaInst *AI = dyn_cast(V)) { - // This was sunk into the gc frame anyway - nothing - // to do. - if (isSpecialPtr(AI->getAllocatedType()) && !AI->isArrayAllocation()) - continue; - } - if (isa(V) || isa(V)) - continue; - if (PHINode *Phi = dyn_cast(V)) { - // Find the set of values that could potentially be - // referenced here. We marks uses for all of them - // that are fully available and create a splitting - // phi for those that are not. Note we may be - // keeping more values alive than we need to, but - // this situation is a bit of a marginal case. - std::set PotentialUses; - for (unsigned i = 0; i < cast(V)->getNumIncomingValues(); ++i) { - RecursivelyVisitStoresTo([&](StoreInst *SI){ - PotentialUses.insert(SI->getValueOperand()); - }, Phi->getIncomingValue(i)); - } - for (Value *Val : PotentialUses) { - if (isa(Val) || isa(Val) || - DT.dominates(cast(Val), Phi)) - NoteUse(S, BBS, Val); - else { - PHINode *Lift = PHINode::Create(T_prjlvalue, 0, "partiallift", Phi); - for (unsigned i = 0; i < Phi->getNumIncomingValues(); ++i) { - BasicBlock *IncomingBB = Phi->getIncomingBlock(i); - if (DT.dominates(cast(Val), IncomingBB->getTerminator())) { - Lift->addIncoming(Val, IncomingBB); - NoteUse(S, S.BBStates[IncomingBB], Val, S.BBStates[IncomingBB].PhiOuts); - } else { - Lift->addIncoming(ConstantPointerNull::get(cast(T_prjlvalue)), IncomingBB); - } - } - NoteUse(S, BBS, Lift); - BBState &LiftBBS = S.BBStates[Phi->getParent()]; - if (LiftBBS.Done) { - // This is ok to do if we already processed that - // basic block (up to phis), because we inserted it at the start - // of the basic block, so we're not violating any - // ordering constraints. - MaybeNoteDef(S, LiftBBS, Lift, LiftBBS.Safepoints); - } - } - } - continue; - } - // Sometimes we load an arg array from a global. That's - // fine as long as we don't store to it. - if (isa(V)) { - RecursivelyVisitStoresTo([&](StoreInst *SI){ - assert(false && "Shouldn't try to store to a global arg array"); - }, V); - continue; - } - std::set LifeTimeStarts = DominatingLifetimes(DT, CI, V); - - assert(isa(V) || isa(V) || isa(V)); - RecursivelyVisitStoresTo([&](StoreInst *SI){ - bool AnyDominates = LifeTimeStarts.empty(); - for (auto *Lifetime : LifeTimeStarts) { - if (DT.dominates(Lifetime, SI)) - AnyDominates = true; - } - if (AnyDominates) - NoteUse(S, BBS, SI->getValueOperand()); - }, V); - - continue; - } } int SafepointNumber = NoteSafepoint(S, BBS, CI); BBS.HasSafepoint = true; @@ -1125,6 +999,17 @@ void LateLowerGCFrame::PopGCFrame(AllocaInst *gcframe, Instruction *InsertBefore bool LateLowerGCFrame::CleanupIR(Function &F) { bool ChangesMade = false; + // We create one alloca for all the jlcall frames that haven't been processed + // yet. LLVM would merge them anyway later, so might as well save it a bit + // of work + size_t maxframeargs = 0; + PointerType *T_pprjlvalue = T_prjlvalue->getPointerTo(); + Instruction *StartOff = &*(F.getEntryBlock().begin()); + AllocaInst *Frame = new AllocaInst(T_prjlvalue, ConstantInt::get(T_int32, maxframeargs), +#if JL_LLVM_VERSION >= 50000 + 0, +#endif + "", StartOff); for (BasicBlock &BB : F) { for (auto it = BB.begin(); it != BB.end();) { auto *CI = dyn_cast(&*it); @@ -1132,6 +1017,7 @@ bool LateLowerGCFrame::CleanupIR(Function &F) { ++it; continue; } + CallingConv::ID CC = CI->getCallingConv(); if ((gc_kill_func != nullptr && CI->getCalledFunction() == gc_kill_func) || (gc_flush_func != nullptr && CI->getCalledFunction() == gc_flush_func)) { /* No replacement */ @@ -1141,6 +1027,36 @@ bool LateLowerGCFrame::CleanupIR(Function &F) { CI->getType(), "", CI); ASCI->takeName(CI); CI->replaceAllUsesWith(ASCI); + } else if (CC == JLCALL_CC || + CC == JLCALL_F_CC) { + size_t nframeargs = CI->getNumArgOperands() - (CC == JLCALL_F_CC); + SmallVector ReplacementArgs; + auto it = CI->arg_begin(); + if (CC == JLCALL_F_CC) + ReplacementArgs.push_back(*(it++)); + maxframeargs = std::max(maxframeargs, nframeargs); + int slot = 0; + IRBuilder<> Builder (CI); + for (; it != CI->arg_end(); ++it) { + Builder.CreateStore(*it, Builder.CreateGEP(T_prjlvalue, Frame, + {ConstantInt::get(T_int32, slot++)})); + } + ReplacementArgs.push_back(nframeargs == 0 ? + (llvm::Value*)ConstantPointerNull::get(T_pprjlvalue) : + (llvm::Value*)Frame); + ReplacementArgs.push_back(ConstantInt::get(T_int32, nframeargs)); + FunctionType *FTy = CC == JLCALL_F_CC ? + FunctionType::get(T_prjlvalue, {T_prjlvalue, + T_pprjlvalue, T_int32}, false) : + FunctionType::get(T_prjlvalue, + {T_pprjlvalue, T_int32}, false); + Value *newFptr = Builder.CreateBitCast(CI->getCalledValue(), + FTy->getPointerTo()); + CallInst *NewCall = CallInst::Create(newFptr, ReplacementArgs, "", CI); + NewCall->setTailCallKind(CI->getTailCallKind()); + NewCall->setAttributes(CI->getAttributes()); + NewCall->setDebugLoc(CI->getDebugLoc()); + CI->replaceAllUsesWith(NewCall); } else if (CI->getNumArgOperands() == CI->getNumOperands()) { /* No operand bundle to lower */ ++it; @@ -1154,6 +1070,10 @@ bool LateLowerGCFrame::CleanupIR(Function &F) { ChangesMade = true; } } + if (maxframeargs == 0) + Frame->eraseFromParent(); + else + Frame->setOperand(0, ConstantInt::get(T_int32, maxframeargs)); return ChangesMade; } diff --git a/test/llvmpasses/gcroots-391.ll b/test/llvmpasses/gcroots-391.ll deleted file mode 100644 index b162a1ac6a6d9..0000000000000 --- a/test/llvmpasses/gcroots-391.ll +++ /dev/null @@ -1,67 +0,0 @@ -; RUN: opt -load libjulia.so -LateLowerGCFrame -S %s | FileCheck %s - -; This file has test cases for IR only valid on LLVM 3.9.1/4.0 - -%jl_value_t = type opaque - -declare void @llvm.lifetime.start(i64, i8*) -declare void @llvm.lifetime.end(i64, i8*) - -declare %jl_value_t*** @jl_get_ptls_states() -declare %jl_value_t addrspace(10)* @jl_apply_generic(%jl_value_t addrspace(10)*, %jl_value_t addrspace(10)**, i32) -declare %jl_value_t addrspace(10)* @jl_box_int64(i64) - -; Check that LLVM duplicating some blocks doesn't confuse the GC placement pass -define void @bb_duplication(i1 %cnd, i64 %a, i64 %b) { -; CHECK-LABEL: @bb_duplication -; CHECK: %gcframe = alloca %jl_value_t addrspace(10)*, i32 4 -top: - %jlcall = alloca [2 x %jl_value_t addrspace(10)*], align 8 - %ptls = call %jl_value_t*** @jl_get_ptls_states() - %jlcall.sub = getelementptr inbounds [2 x %jl_value_t addrspace(10)*], [2 x %jl_value_t addrspace(10)*]* %jlcall, i64 0, i64 0 - %jlcall1 = getelementptr inbounds [2 x %jl_value_t addrspace(10)*], [2 x %jl_value_t addrspace(10)*]* %jlcall, i64 0, i64 1 - br label %loop -loop: - br i1 %cnd, label %A, label %B -A: - %Aaboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %a) - %Abboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %b) - br i1 undef, label %loop, label %Abody - -Abody: - %aarg = bitcast %jl_value_t addrspace(10)** %jlcall.sub to i8* - call void @llvm.lifetime.start(i64 16, i8* %aarg) - store %jl_value_t addrspace(10)* %Aaboxed, %jl_value_t addrspace(10)** %jlcall.sub - store %jl_value_t addrspace(10)* %Abboxed, %jl_value_t addrspace(10)** %jlcall1 - call %jl_value_t addrspace(10)* @jl_apply_generic(%jl_value_t addrspace(10)* null, %jl_value_t addrspace(10)** %jlcall.sub, i32 2) - call void @llvm.lifetime.end(i64 16, i8* %aarg) - br i1 undef, label %loop, label %out -B: - %Baboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %a) - %Bbboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %b) - %aarg2 = bitcast %jl_value_t addrspace(10)** %jlcall.sub to i8* - call void @llvm.lifetime.start(i64 16, i8* %aarg2) - store %jl_value_t addrspace(10)* %Baboxed, %jl_value_t addrspace(10)** %jlcall.sub - store %jl_value_t addrspace(10)* %Bbboxed, %jl_value_t addrspace(10)** %jlcall1 - call %jl_value_t addrspace(10)* @jl_apply_generic(%jl_value_t addrspace(10)* null, %jl_value_t addrspace(10)** %jlcall.sub, i32 2) - call void @llvm.lifetime.end(i64 16, i8* %aarg2) - br i1 undef, label %loop, label %out -out: - ret void -} - -; We can trivially sink single allocas into the gc frame, but we need to delete -; any lifetime markers -define void @single_alloca_lifetime(i64 %a) { -; CHECK-LABEL: @single_alloca_lifetime -; CHECK-NOT: call void @llvm.lifetime.start - %ptls = call %jl_value_t*** @jl_get_ptls_states() - %jlcall = alloca %jl_value_t addrspace(10)* - %aboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %a) - %aarg = bitcast %jl_value_t addrspace(10)** %jlcall to i8* - call void @llvm.lifetime.start(i64 16, i8* %aarg) - store %jl_value_t addrspace(10)* %aboxed, %jl_value_t addrspace(10)** %jlcall - call %jl_value_t addrspace(10)* @jl_apply_generic(%jl_value_t addrspace(10)* null, %jl_value_t addrspace(10)** %jlcall, i32 1) - call void @llvm.lifetime.start(i64 16, i8* %aarg) - ret void -} diff --git a/test/llvmpasses/gcroots-50.ll b/test/llvmpasses/gcroots-50.ll deleted file mode 100644 index d8366b3a72ddf..0000000000000 --- a/test/llvmpasses/gcroots-50.ll +++ /dev/null @@ -1,64 +0,0 @@ -; RUN: opt -load libjulia.so -LateLowerGCFrame -S %s | FileCheck %s - -; This file has test cases for IR only valid on LLVM 5.0 - -%jl_value_t = type opaque - -declare void @llvm.lifetime.start.p0p10s_jl_value_ts(i64, %jl_value_t addrspace(10)**) -declare void @llvm.lifetime.end.p0p10s_jl_value_ts(i64, %jl_value_t addrspace(10)**) - -declare %jl_value_t*** @jl_get_ptls_states() -declare %jl_value_t addrspace(10)* @jl_apply_generic(%jl_value_t addrspace(10)*, %jl_value_t addrspace(10)**, i32) -declare %jl_value_t addrspace(10)* @jl_box_int64(i64) - -; Check that LLVM duplicating some blocks doesn't confuse the GC placement pass -define void @bb_duplication(i1 %cnd, i64 %a, i64 %b) { -; CHECK-LABEL: @bb_duplication -; CHECK: %gcframe = alloca %jl_value_t addrspace(10)*, i32 4 -top: - %jlcall = alloca [2 x %jl_value_t addrspace(10)*], align 8 - %ptls = call %jl_value_t*** @jl_get_ptls_states() - %jlcall.sub = getelementptr inbounds [2 x %jl_value_t addrspace(10)*], [2 x %jl_value_t addrspace(10)*]* %jlcall, i64 0, i64 0 - %jlcall1 = getelementptr inbounds [2 x %jl_value_t addrspace(10)*], [2 x %jl_value_t addrspace(10)*]* %jlcall, i64 0, i64 1 - br label %loop -loop: - br i1 %cnd, label %A, label %B -A: - %Aaboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %a) - %Abboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %b) - br i1 undef, label %loop, label %Abody - -Abody: - call void @llvm.lifetime.start.p0p10s_jl_value_ts(i64 16, %jl_value_t addrspace(10)** %jlcall.sub) - store %jl_value_t addrspace(10)* %Aaboxed, %jl_value_t addrspace(10)** %jlcall.sub - store %jl_value_t addrspace(10)* %Abboxed, %jl_value_t addrspace(10)** %jlcall1 - call %jl_value_t addrspace(10)* @jl_apply_generic(%jl_value_t addrspace(10)* null, %jl_value_t addrspace(10)** %jlcall.sub, i32 2) - call void @llvm.lifetime.end.p0p10s_jl_value_ts(i64 16, %jl_value_t addrspace(10)** %jlcall.sub) - br i1 undef, label %loop, label %out -B: - %Baboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %a) - %Bbboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %b) - call void @llvm.lifetime.start.p0p10s_jl_value_ts(i64 16, %jl_value_t addrspace(10)** %jlcall.sub) - store %jl_value_t addrspace(10)* %Baboxed, %jl_value_t addrspace(10)** %jlcall.sub - store %jl_value_t addrspace(10)* %Bbboxed, %jl_value_t addrspace(10)** %jlcall1 - call %jl_value_t addrspace(10)* @jl_apply_generic(%jl_value_t addrspace(10)* null, %jl_value_t addrspace(10)** %jlcall.sub, i32 2) - call void @llvm.lifetime.end.p0p10s_jl_value_ts(i64 16, %jl_value_t addrspace(10)** %jlcall.sub) - br i1 undef, label %loop, label %out -out: - ret void -} - -; We can trivially sink single allocas into the gc frame, but we need to delete -; any lifetime markers -define void @single_alloca_lifetime(i64 %a) { -; CHECK-LABEL: @single_alloca_lifetime -; CHECK-NOT: call void @llvm.lifetime.start - %ptls = call %jl_value_t*** @jl_get_ptls_states() - %jlcall = alloca %jl_value_t addrspace(10)* - %aboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %a) - call void @llvm.lifetime.start.p0p10s_jl_value_ts(i64 16, %jl_value_t addrspace(10)** %jlcall) - store %jl_value_t addrspace(10)* %aboxed, %jl_value_t addrspace(10)** %jlcall - call %jl_value_t addrspace(10)* @jl_apply_generic(%jl_value_t addrspace(10)* null, %jl_value_t addrspace(10)** %jlcall, i32 1) - call void @llvm.lifetime.end.p0p10s_jl_value_ts(i64 16, %jl_value_t addrspace(10)** %jlcall) - ret void -} diff --git a/test/llvmpasses/gcroots.ll b/test/llvmpasses/gcroots.ll index f77a7a5bf5aa9..7fdb392ea403f 100644 --- a/test/llvmpasses/gcroots.ll +++ b/test/llvmpasses/gcroots.ll @@ -128,101 +128,6 @@ common: ret void } -; Checks for ugly phi corner case -define void @phi_corner_case(i64 %a, i64 %b, i64 %c, i64 %d) { -top: -; CHECK-LABEL: @phi_corner_case -; CHECK: %gcframe = alloca %jl_value_t addrspace(10)*, i32 6 -; Currently each value gets stored twice, once to the gc frame, once to the -; jlcall frame. Future optimizations may change that, which would require appropriate -; adjustments to this test. -; CHECK: store %jl_value_t addrspace(10)* %aboxed -; CHECK: store %jl_value_t addrspace(10)* %aboxed -; CHECK: store %jl_value_t addrspace(10)* %bboxed -; CHECK: store %jl_value_t addrspace(10)* %bboxed -; CHECK: store %jl_value_t addrspace(10)* %cboxed -; CHECK: store %jl_value_t addrspace(10)* %cboxed -; CHECK: store %jl_value_t addrspace(10)* %dboxed -; CHECK: store %jl_value_t addrspace(10)* %dboxed - %ptls = call %jl_value_t*** @jl_get_ptls_states() - %frame1 = alloca %jl_value_t addrspace(10)*, i32 2 - %frame11 = getelementptr %jl_value_t addrspace(10)*, %jl_value_t addrspace(10)** %frame1, i32 1 - %frame2 = alloca %jl_value_t addrspace(10)*, i32 2 - %frame21 = getelementptr %jl_value_t addrspace(10)*, %jl_value_t addrspace(10)** %frame2, i32 1 - %aboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %a) - %bboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %b) - store %jl_value_t addrspace(10)* %aboxed, %jl_value_t addrspace(10)** %frame1 - store %jl_value_t addrspace(10)* %bboxed, %jl_value_t addrspace(10)** %frame11 - %cboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %c) - %dboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %d) - store %jl_value_t addrspace(10)* %cboxed, %jl_value_t addrspace(10)** %frame2 - store %jl_value_t addrspace(10)* %dboxed, %jl_value_t addrspace(10)** %frame21 - %cmp = icmp eq i64 %a, %b - br i1 %cmp, label %alabel, label %blabel -alabel: - br label %common -blabel: - br label %common -common: - %callframe = phi %jl_value_t addrspace(10)** [ %frame1, %alabel], [ %frame2, %blabel ] - call %jl_value_t addrspace(10)* @jl_apply_generic(%jl_value_t addrspace(10)* null, %jl_value_t addrspace(10)** %callframe, i32 2) - ret void -} - -define void @phi_corner_case2(i64 %a, i64 %b, i64 %c, i64 %d) { -; CHECK-LABEL: @phi_corner_case2 -; CHECK: %gcframe = alloca %jl_value_t addrspace(10)*, i32 6 - %ptls = call %jl_value_t*** @jl_get_ptls_states() - %frame1 = alloca %jl_value_t addrspace(10)*, i32 2 - %frame11 = getelementptr %jl_value_t addrspace(10)*, %jl_value_t addrspace(10)** %frame1, i32 1 - %frame2 = alloca %jl_value_t addrspace(10)*, i32 2 - %frame21 = getelementptr %jl_value_t addrspace(10)*, %jl_value_t addrspace(10)** %frame2, i32 1 - %aboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %a) - %bboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %b) - store %jl_value_t addrspace(10)* %aboxed, %jl_value_t addrspace(10)** %frame1 - store %jl_value_t addrspace(10)* %bboxed, %jl_value_t addrspace(10)** %frame11 - %cmp = icmp eq i64 %a, %b - br i1 %cmp, label %alabel, label %blabel -alabel: - br label %common -blabel: - %cboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %c) -; cboxed gets two stores (one to gcroot it for the boxing of d) -; CHECK: store %jl_value_t addrspace(10)* %cboxed -; CHECK: store %jl_value_t addrspace(10)* %cboxed -; CHECK: store %jl_value_t addrspace(10)* %dboxed - %dboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %d) - store %jl_value_t addrspace(10)* %cboxed, %jl_value_t addrspace(10)** %frame2 - store %jl_value_t addrspace(10)* %dboxed, %jl_value_t addrspace(10)** %frame21 - br label %common -common: -; CHECK-DAG: [[LIFT1:%.*]] = phi %jl_value_t addrspace(10)* [ null, %alabel ], [ %cboxed, %blabel ] -; CHECK-DAG: [[LIFT2:%.*]] = phi %jl_value_t addrspace(10)* [ null, %alabel ], [ %dboxed, %blabel ] -; CHECK-DAG: store %jl_value_t addrspace(10)* [[LIFT2]] -; CHECK-DAG: store %jl_value_t addrspace(10)* [[LIFT1]] - %callframe = phi %jl_value_t addrspace(10)** [ %frame1, %alabel], [ %frame2, %blabel ] - call %jl_value_t addrspace(10)* @jl_apply_generic(%jl_value_t addrspace(10)* null, %jl_value_t addrspace(10)** %callframe, i32 2) - ret void -} - -define void @underlying_object(i64 %a, i64 %b) { -; CHECK-LABEL: @underlying_object -; We need to root both values here. The observed failure case was that we'd -; only consider stores to the gep passed to the call rather than all stores -; to the alloca. -; CHECK: %gcframe = alloca %jl_value_t addrspace(10)*, i32 4 - %jlcall = alloca [2 x %jl_value_t addrspace(10)*], align 8 - %jlcall.sub = getelementptr inbounds [2 x %jl_value_t addrspace(10)*], [2 x %jl_value_t addrspace(10)*]* %jlcall, i64 0, i64 0 - %ptls = call %jl_value_t*** @jl_get_ptls_states() - %aboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %a) - %bboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %b) - store %jl_value_t addrspace(10)* %aboxed, %jl_value_t addrspace(10)** %jlcall.sub - %bslot = getelementptr inbounds [2 x %jl_value_t addrspace(10)*], [2 x %jl_value_t addrspace(10)*]* %jlcall, i64 0, i64 1 - store %jl_value_t addrspace(10)* %bboxed, %jl_value_t addrspace(10)** %bslot - call %jl_value_t addrspace(10)* @jl_apply_generic(%jl_value_t addrspace(10)* null, %jl_value_t addrspace(10)** %jlcall.sub, i32 2) - ret void -} - define void @live_if_live_out(i64 %a, i64 %b) { ; CHECK-LABEL: @live_if_live_out top: @@ -239,33 +144,6 @@ succ: ret void } -declare void @llvm.lifetime.start.p0p10s_jl_value_ts(i64, %jl_value_t addrspace(10)**) -declare void @llvm.lifetime.end.p0p10s_jl_value_ts(i64, %jl_value_t addrspace(10)**) - -; The system shouldn't really be generating things like this, but we can get unlucky -define void @weird_alloca(i1 %cnd, i64 %a, i64 %b) { -; CHECK-LABEL: weird_alloca -; CHECK: %gcframe = alloca %jl_value_t addrspace(10)*, i32 4 - %jlcall = alloca [2 x %jl_value_t addrspace(10)*], align 8 - %ptls = call %jl_value_t*** @jl_get_ptls_states() - %jlcall.sub = getelementptr inbounds [2 x %jl_value_t addrspace(10)*], [2 x %jl_value_t addrspace(10)*]* %jlcall, i64 0, i64 0 - %jlcall1 = getelementptr inbounds [2 x %jl_value_t addrspace(10)*], [2 x %jl_value_t addrspace(10)*]* %jlcall, i64 0, i64 1 - store %jl_value_t addrspace(10)* null, %jl_value_t addrspace(10)** %jlcall.sub - store %jl_value_t addrspace(10)* null, %jl_value_t addrspace(10)** %jlcall1 - br i1 %cnd, label %if, label %done - -if: - %aboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %a) - %bboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %b) - store %jl_value_t addrspace(10)* %aboxed, %jl_value_t addrspace(10)** %jlcall.sub - store %jl_value_t addrspace(10)* %bboxed, %jl_value_t addrspace(10)** %jlcall1 - br label %done - -done: - call %jl_value_t addrspace(10)* @jl_apply_generic(%jl_value_t addrspace(10)* null, %jl_value_t addrspace(10)** %jlcall.sub, i32 2) - ret void -} - ; A ret is a use - make sure the value is kept alive for any intervening ; safepoint define %jl_value_t addrspace(10)* @ret_use(i64 %a, i64 %b) { @@ -277,20 +155,3 @@ define %jl_value_t addrspace(10)* @ret_use(i64 %a, i64 %b) { %bboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %b) ret %jl_value_t addrspace(10)* %aboxed } - -define void @vector_ops(%jl_value_t addrspace(10)* %a, %jl_value_t addrspace(10)** %b, i32 %c) { -; CHECK-LABEL: @vector_ops -; N.B.: This should be 4, but it's currently not realizing that %a doesn't need a root -; CHECK: %gcframe = alloca %jl_value_t addrspace(10)*, i32 5 - %ptls = call %jl_value_t*** @jl_get_ptls_states() - %jlcall = alloca [3 x %jl_value_t addrspace(10)*], align 8 - %jlcall.sub = getelementptr inbounds [3 x %jl_value_t addrspace(10)*], [3 x %jl_value_t addrspace(10)*]* %jlcall, i64 0, i64 0 - %casted = bitcast %jl_value_t addrspace(10)** %b to <2 x %jl_value_t addrspace(10)*>* - %loaded = load <2 x %jl_value_t addrspace(10)*>, <2 x %jl_value_t addrspace(10)*>* %casted - %jlcall.casted = bitcast [3 x %jl_value_t addrspace(10)*]* %jlcall to <2 x %jl_value_t addrspace(10)*>* - store <2 x %jl_value_t addrspace(10)*> %loaded, <2 x %jl_value_t addrspace(10)*>* %jlcall.casted - %third = getelementptr inbounds [3 x %jl_value_t addrspace(10)*], [3 x %jl_value_t addrspace(10)*]* %jlcall, i64 0, i64 2 - store %jl_value_t addrspace(10)* %a, %jl_value_t addrspace(10)** %third - call %jl_value_t addrspace(10)* @jl_apply_generic(%jl_value_t addrspace(10)* %a, %jl_value_t addrspace(10)** %jlcall.sub, i32 3) - ret void -} From 226bca3409e5b2d9400dbfba69a263a3907d9806 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Mon, 12 Jun 2017 12:22:19 -0400 Subject: [PATCH 1099/1534] Add a pass to propagate addrspace information Some LLVM passes don't handle addrspacecast too well, so try to minimize addrspace cast transitions where legal according to our invariants. --- src/Makefile | 2 +- src/jitlayers.cpp | 4 +- src/jitlayers.h | 1 + src/llvm-propagate-addrspaces.cpp | 205 +++++++++++++++++++++++++ test/llvmpasses/propagate-addrspace.ll | 21 +++ 5 files changed, 231 insertions(+), 2 deletions(-) create mode 100644 src/llvm-propagate-addrspaces.cpp create mode 100644 test/llvmpasses/propagate-addrspace.ll diff --git a/src/Makefile b/src/Makefile index c91d797778967..0140eb90f50e9 100644 --- a/src/Makefile +++ b/src/Makefile @@ -53,7 +53,7 @@ endif LLVMLINK := ifeq ($(JULIACODEGEN),LLVM) -SRCS += codegen jitlayers disasm debuginfo llvm-simdloop llvm-ptls llvm-late-gc-lowering llvm-lower-handlers llvm-gc-invariant-verifier cgmemmgr +SRCS += codegen jitlayers disasm debuginfo llvm-simdloop llvm-ptls llvm-late-gc-lowering llvm-lower-handlers llvm-gc-invariant-verifier llvm-propagate-addrspaces cgmemmgr FLAGS += -I$(shell $(LLVM_CONFIG_HOST) --includedir) LLVM_LIBS := all ifeq ($(USE_POLLY),1) diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index 2a200ba7215cf..f3af6b4f9275b 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -154,6 +154,7 @@ void addOptimizationPasses(PassManager *PM, int opt_level) #endif return; } + PM->add(createPropagateJuliaAddrspaces()); #if JL_LLVM_VERSION >= 30700 PM->add(createTargetTransformInfoWrapperPass(jl_TargetMachine->getTargetIRAnalysis())); #else @@ -173,6 +174,7 @@ void addOptimizationPasses(PassManager *PM, int opt_level) } // list of passes from vmkit PM->add(createCFGSimplificationPass()); // Clean up disgusting code + PM->add(createDeadInstEliminationPass()); PM->add(createPromoteMemoryToRegisterPass()); // Kill useless allocas // Due to bugs and missing features LLVM < 5.0, does not properly propagate @@ -1441,7 +1443,7 @@ class JuliaPipeline : public ModulePass { #else PassManager PM; #endif - addOptimizationPasses(&PM); + addOptimizationPasses(&PM, 3); PM.run(M); return true; } diff --git a/src/jitlayers.h b/src/jitlayers.h index 780c489f3e750..bb29534ba234b 100644 --- a/src/jitlayers.h +++ b/src/jitlayers.h @@ -250,6 +250,7 @@ Pass *createLowerPTLSPass(bool imaging_mode); Pass *createLateLowerGCFramePass(); Pass *createLowerExcHandlersPass(); Pass *createGCInvariantVerifierPass(bool Strong); +Pass *createPropagateJuliaAddrspaces(); // Whether the Function is an llvm or julia intrinsic. static inline bool isIntrinsicFunction(Function *F) { diff --git a/src/llvm-propagate-addrspaces.cpp b/src/llvm-propagate-addrspaces.cpp new file mode 100644 index 0000000000000..6e6d4a5f3032d --- /dev/null +++ b/src/llvm-propagate-addrspaces.cpp @@ -0,0 +1,205 @@ +// This file is a part of Julia. License is MIT: https://julialang.org/license + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "llvm-version.h" +#include "codegen_shared.h" +#include "julia.h" + +#define DEBUG_TYPE "propagate_julia_addrspaces" + +using namespace llvm; + +/* This pass performs propagation of addrspace information that is legal from + the frontend definition, but illegal by general IR semantics. In particular, + this includes: + - Changing the address space of a load/store if the base pointer is + in an untracked address space + - Commuting GEPs and addrspace casts + + This is most useful for removing superflous casts that can inhibit LLVM + optimizations. +*/ + +struct PropagateJuliaAddrspaces : public FunctionPass, public InstVisitor { + static char ID; + DenseMap LiftingMap; + SmallPtrSet Visited; + std::vector ToDelete; + std::vector> ToInsert; + PropagateJuliaAddrspaces() : FunctionPass(ID) {}; + +public: + bool runOnFunction(Function &F) override; + Value *LiftPointer(Value *V, Type *LocTy = nullptr, Instruction *InsertPt=nullptr); + void visitStoreInst(StoreInst &SI); + void visitLoadInst(LoadInst &LI); + void visitMemSetInst(MemSetInst &MI); + void visitMemTransferInst(MemTransferInst &MTI); +}; + +bool PropagateJuliaAddrspaces::runOnFunction(Function &F) { + visit(F); + for (auto it : ToInsert) + it.first->insertBefore(it.second); + for (Instruction *I : ToDelete) + I->eraseFromParent(); + ToInsert.clear(); + ToDelete.clear(); + LiftingMap.clear(); + Visited.clear(); + return true; +} + +static unsigned getValueAddrSpace(Value *V) { + return cast(V->getType())->getAddressSpace(); +} + +static bool isSpecialAS(unsigned AS) { + return AddressSpace::FirstSpecial <= AS && AS <= AddressSpace::LastSpecial; +} + +Value *PropagateJuliaAddrspaces::LiftPointer(Value *V, Type *LocTy, Instruction *InsertPt) { + SmallVector Stack; + Value *CurrentV = V; + // Follow pointer casts back, see if we're based on a pointer in + // an untracked address space, in which case we're allowed to drop + // intermediate addrspace casts. + while (true) { + Stack.push_back(CurrentV); + if (isa(CurrentV)) + CurrentV = cast(CurrentV)->getOperand(0); + else if (isa(CurrentV)) { + CurrentV = cast(CurrentV)->getOperand(0); + if (!isSpecialAS(getValueAddrSpace(CurrentV))) + break; + } + else if (isa(CurrentV)) { + if (LiftingMap.count(CurrentV)) { + CurrentV = LiftingMap[CurrentV]; + break; + } else if (Visited.count(CurrentV)) { + return nullptr; + } + Visited.insert(CurrentV); + CurrentV = cast(CurrentV)->getOperand(0); + } else + break; + } + if (!CurrentV->getType()->isPointerTy()) + return nullptr; + if (isSpecialAS(getValueAddrSpace(CurrentV))) + return nullptr; + // Ok, we're allowed to change the address space of this load, go back and + // reconstitute any GEPs in the new address space. + for (Value *V : llvm::reverse(Stack)) { + GetElementPtrInst *GEP = dyn_cast(V); + if (!GEP) + continue; + if (LiftingMap.count(GEP)) { + CurrentV = LiftingMap[GEP]; + continue; + } + GetElementPtrInst *NewGEP = cast(GEP->clone()); + ToInsert.push_back(std::make_pair(NewGEP, GEP)); + Type *GEPTy = GEP->getSourceElementType(); + Type *NewRetTy = cast(GEP->getType())->getElementType()->getPointerTo(getValueAddrSpace(CurrentV)); + NewGEP->mutateType(NewRetTy); + if (cast(CurrentV->getType())->getElementType() != GEPTy) { + auto *BCI = new BitCastInst(CurrentV, GEPTy->getPointerTo()); + ToInsert.push_back(std::make_pair(BCI, NewGEP)); + CurrentV = BCI; + } + NewGEP->setOperand(GetElementPtrInst::getPointerOperandIndex(), CurrentV); + LiftingMap[GEP] = NewGEP; + CurrentV = NewGEP; + } + if (LocTy && cast(CurrentV->getType())->getElementType() != LocTy) { + auto *BCI = new BitCastInst(CurrentV, LocTy->getPointerTo()); + ToInsert.push_back(std::make_pair(BCI, InsertPt)); + CurrentV = BCI; + } + return CurrentV; +} + +void PropagateJuliaAddrspaces::visitLoadInst(LoadInst &LI) { + unsigned AS = LI.getPointerAddressSpace(); + if (!isSpecialAS(AS)) + return; + Value *Replacement = LiftPointer(LI.getPointerOperand(), LI.getType(), &LI); + if (!Replacement) + return; + LI.setOperand(LoadInst::getPointerOperandIndex(), Replacement); +} + +void PropagateJuliaAddrspaces::visitStoreInst(StoreInst &SI) { + unsigned AS = SI.getPointerAddressSpace(); + if (!isSpecialAS(AS)) + return; + Value *Replacement = LiftPointer(SI.getPointerOperand(), SI.getValueOperand()->getType(), &SI); + if (!Replacement) + return; + SI.setOperand(StoreInst::getPointerOperandIndex(), Replacement); +} + +void PropagateJuliaAddrspaces::visitMemSetInst(MemSetInst &MI) { + unsigned AS = MI.getDestAddressSpace(); + if (!isSpecialAS(AS)) + return; + Value *Replacement = LiftPointer(MI.getRawDest()); + if (!Replacement) + return; + Value *TheFn = Intrinsic::getDeclaration(MI.getModule(), Intrinsic::memset, + {Replacement->getType(), MI.getOperand(1)->getType()}); + MI.setCalledFunction(TheFn); + MI.setArgOperand(0, Replacement); +} + +void PropagateJuliaAddrspaces::visitMemTransferInst(MemTransferInst &MTI) { + unsigned DestAS = MTI.getDestAddressSpace(); + unsigned SrcAS = MTI.getSourceAddressSpace(); + if (!isSpecialAS(DestAS) && !isSpecialAS(SrcAS)) + return; + Value *Dest = MTI.getRawDest(); + if (isSpecialAS(DestAS)) { + Value *Replacement = LiftPointer(Dest, cast(Dest->getType())->getElementType(), &MTI); + if (Replacement) + Dest = Replacement; + } + Value *Src = MTI.getRawSource(); + if (isSpecialAS(SrcAS)) { + Value *Replacement = LiftPointer(Src, cast(Src->getType())->getElementType(), &MTI); + if (Replacement) + Src = Replacement; + } + if (Dest == MTI.getRawDest() && Src == MTI.getRawSource()) + return; + Value *TheFn = Intrinsic::getDeclaration(MTI.getModule(), MTI.getIntrinsicID(), + {Dest->getType(), Src->getType(), + MTI.getOperand(2)->getType()}); + MTI.setCalledFunction(TheFn); + MTI.setArgOperand(0, Dest); + MTI.setArgOperand(1, Src); +} + +char PropagateJuliaAddrspaces::ID = 0; +static RegisterPass X("PropagateJuliaAddrspaces", "Propagate (non-)rootedness information", false, false); + +Pass *createPropagateJuliaAddrspaces() { + return new PropagateJuliaAddrspaces(); +} diff --git a/test/llvmpasses/propagate-addrspace.ll b/test/llvmpasses/propagate-addrspace.ll new file mode 100644 index 0000000000000..80ee269616d8c --- /dev/null +++ b/test/llvmpasses/propagate-addrspace.ll @@ -0,0 +1,21 @@ +; RUN: opt -load libjulia.so -PropagateJuliaAddrspaces -dce -S %s | FileCheck %s + +define i64 @simple() { +; CHECK-LABEL: @simple +; CHECK-NOT: addrspace(11) + %stack = alloca i64 + %casted = addrspacecast i64 *%stack to i64 addrspace(11)* + %loaded = load i64, i64 addrspace(11)* %casted + ret i64 %loaded +} + +define i64 @twogeps() { +; CHECK-LABEL: @twogeps +; CHECK-NOT: addrspace(11) + %stack = alloca i64 + %casted = addrspacecast i64 *%stack to i64 addrspace(11)* + %gep1 = getelementptr i64, i64 addrspace(11)* %casted, i64 1 + %gep2 = getelementptr i64, i64 addrspace(11)* %gep1, i64 1 + %loaded = load i64, i64 addrspace(11)* %gep2 + ret i64 %loaded +} From b2d0caf09c0be32d2cf2467d603827e80701a96a Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Tue, 13 Jun 2017 19:49:21 -0400 Subject: [PATCH 1100/1534] Better way to expose julia meta-pass In the previous iteration of this code, timing would be double counted. This way, the individual passes are correctly registered with the top level manager, so timing works properly. It's a bit hacky but with the legacy pass manager, there's not much else to be done. --- src/jitlayers.cpp | 30 ++++++++++++++++++------------ src/jitlayers.h | 2 +- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index f3af6b4f9275b..68d29c5f75dc2 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -55,6 +55,8 @@ namespace llvm { #include #endif +#include +#include #include #include @@ -109,7 +111,7 @@ void jl_init_jit(Type *T_pjlvalue_) // this defines the set of optimization passes defined for Julia at various optimization levels #if JL_LLVM_VERSION >= 30700 -void addOptimizationPasses(legacy::PassManager *PM, int opt_level) +void addOptimizationPasses(legacy::PassManagerBase *PM, int opt_level) #else void addOptimizationPasses(PassManager *PM, int opt_level) #endif @@ -1432,20 +1434,24 @@ GlobalVariable *jl_get_global_for(const char *cname, void *addr, Module *M) // An LLVM module pass that just runs all julia passes in order. Useful for // debugging extern "C" void jl_init_codegen(void); -class JuliaPipeline : public ModulePass { +class JuliaPipeline : public Pass { public: static char ID; - JuliaPipeline() : ModulePass(ID) {} - virtual bool runOnModule(Module &M) { + // A bit of a hack, but works + struct TPMAdapter : public PassManagerBase { + PMTopLevelManager *TPM; + TPMAdapter(PMTopLevelManager *TPM) : TPM(TPM) {} + void add(Pass *P) { TPM->schedulePass(P); } + }; + void preparePassManager(PMStack &Stack) override { (void)jl_init_llvm(); -#if JL_LLVM_VERSION >= 30700 - legacy::PassManager PM; -#else - PassManager PM; -#endif - addOptimizationPasses(&PM, 3); - PM.run(M); - return true; + PMTopLevelManager *TPM = Stack.top()->getTopLevelManager(); + TPMAdapter Adapter(TPM); + addOptimizationPasses(&Adapter, 3); + } + JuliaPipeline() : Pass(PT_PassManager, ID) {} + Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const { + return createPrintModulePass(O, Banner); } }; char JuliaPipeline::ID = 0; diff --git a/src/jitlayers.h b/src/jitlayers.h index bb29534ba234b..78f4147aff6a4 100644 --- a/src/jitlayers.h +++ b/src/jitlayers.h @@ -61,7 +61,7 @@ extern size_t jltls_offset_idx; typedef struct {Value *gv; int32_t index;} jl_value_llvm; // uses 1-based indexing #if JL_LLVM_VERSION >= 30700 -void addOptimizationPasses(legacy::PassManager *PM, int opt_level); +void addOptimizationPasses(legacy::PassManagerBase *PM, int opt_level); #else void addOptimizationPasses(PassManager *PM, int opt_level); #endif From b0a162c5f94580a654d01190affd770582e11170 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Wed, 14 Jun 2017 11:57:17 -0400 Subject: [PATCH 1101/1534] Don't color roots that don't need it Also avoid numbering arguments early in the pipeline. Improves performance on small test cases without safepoints. --- src/llvm-late-gc-lowering.cpp | 16 +++++++++++----- test/llvmpasses/gcroots.ll | 19 +++++++++++++++++++ 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/llvm-late-gc-lowering.cpp b/src/llvm-late-gc-lowering.cpp index 5a4beca3ef1a7..f40d9215dec95 100644 --- a/src/llvm-late-gc-lowering.cpp +++ b/src/llvm-late-gc-lowering.cpp @@ -445,9 +445,8 @@ int LateLowerGCFrame::Number(State &S, Value *V) { if (it != S.AllPtrNumbering.end()) return it->second; int Number; - if (isa(CurrentV) || - ((isa(CurrentV) || isa(CurrentV) || - isa(CurrentV)) && + if (isa(CurrentV) || isa(CurrentV) || + ((isa(CurrentV) || isa(CurrentV)) && getValueAddrSpace(CurrentV) != AddressSpace::Tracked)) { // We know this is rooted in the parent Number = -1; @@ -831,8 +830,9 @@ void LateLowerGCFrame::ComputeLiveSets(Function &F, State &S) { if ((unsigned)i >= LS.size() || !LS[i]) continue; for (int Idx = LS.find_first(); Idx >= 0; Idx = LS.find_next(Idx)) { - if (Idx == i) - continue; + // We explicitly let i be a neighbor of itself, to distinguish + // between being the only value live at a safepoint, vs not + // being live at any safepoint. Neighbors.push_back(Idx); } } @@ -916,6 +916,8 @@ struct PEOIterator { Elements[NextElement].weight = (unsigned)-1; // Raise neighbors for (int Neighbor : Neighbors[NextElement]) { + if (Neighbor == NextElement) + continue; Element &NElement = Elements[Neighbor]; // Already processed. Don't re-enqueue if (NElement.weight == (unsigned)-1) @@ -947,6 +949,10 @@ std::vector LateLowerGCFrame::ColorRoots(const State &S) { assert(Colors[ActiveElement] == -1); UsedColors.resize(MaxAssignedColor + 2, false); UsedColors.reset(); + if (S.Neighbors[ActiveElement].empty()) { + // No need to color a value not live at any safe point + continue; + } for (int Neighbor : S.Neighbors[ActiveElement]) { if (Colors[Neighbor] == -1) continue; diff --git a/test/llvmpasses/gcroots.ll b/test/llvmpasses/gcroots.ll index 7fdb392ea403f..db2c22543936b 100644 --- a/test/llvmpasses/gcroots.ll +++ b/test/llvmpasses/gcroots.ll @@ -155,3 +155,22 @@ define %jl_value_t addrspace(10)* @ret_use(i64 %a, i64 %b) { %bboxed = call %jl_value_t addrspace(10)* @jl_box_int64(i64 signext %b) ret %jl_value_t addrspace(10)* %aboxed } + +define i8 @nosafepoint(%jl_value_t addrspace(10)* dereferenceable(16)) { +; CHECK-LABEL: @nosafepoint +; CHECK-NOT: %gcframe +top: + %1 = call %jl_value_t*** @jl_get_ptls_states() + %2 = bitcast %jl_value_t*** %1 to %jl_value_t addrspace(10)** + %3 = getelementptr %jl_value_t addrspace(10)*, %jl_value_t addrspace(10)** %2, i64 3 + %4 = bitcast %jl_value_t addrspace(10)** %3 to i64** + %5 = load i64*, i64** %4 + %6 = bitcast %jl_value_t addrspace(10)* %0 to i8 addrspace(10)* + %7 = addrspacecast i8 addrspace(10)* %6 to i8 addrspace(11)* + %8 = getelementptr i8, i8 addrspace(11)* %7, i64 0 + %9 = load i8, i8 addrspace(11)* %8 + %10 = trunc i8 %9 to i1 + %11 = zext i1 %10 to i8 + %12 = xor i8 %11, 1 + ret i8 %12 +} From ce3f853348e23eb6adae211891738058d80b50e7 Mon Sep 17 00:00:00 2001 From: Jack Devine Date: Fri, 16 Jun 2017 14:04:22 +1200 Subject: [PATCH 1102/1534] Add `unique!` (#20619) --- NEWS.md | 2 + base/exports.jl | 1 + base/set.jl | 88 +++++++++++++++++++++++++++++++++++ doc/src/stdlib/collections.md | 1 + test/TestHelpers.jl | 2 + test/sets.jl | 38 +++++++++++++++ 6 files changed, 132 insertions(+) diff --git a/NEWS.md b/NEWS.md index e24ea3d8117af..3904ed072a5c0 100644 --- a/NEWS.md +++ b/NEWS.md @@ -77,6 +77,8 @@ Library improvements * `logspace` now accepts a `base` keyword argument to specify the base of the logarithmic range. The base defaults to 10 ([#22310]). + * Added `unique!` which is an inplace version of `unique` ([#20549]). + Compiler/Runtime improvements ----------------------------- diff --git a/base/exports.jl b/base/exports.jl index e139a7d9b3705..a5e127871f2bf 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -719,6 +719,7 @@ export symdiff, union!, union, + unique!, unique, values, valtype, diff --git a/base/set.jl b/base/set.jl index 1eb269adca42a..f2fb82e781054 100644 --- a/base/set.jl +++ b/base/set.jl @@ -202,6 +202,94 @@ function unique(f::Callable, C) out end +# If A is not grouped, then we will need to keep track of all of the elements that we have +# seen so far. +function _unique!(A::AbstractVector) + seen = Set{eltype(A)}() + idxs = eachindex(A) + i = state = start(idxs) + for x in A + if x ∉ seen + push!(seen, x) + i, state = next(idxs, state) + A[i] = x + end + end + resize!(A, i - first(idxs) + 1) +end + +# If A is grouped, so that each unique element is in a contiguous group, then we only +# need to keep track of one element at a time. We replace the elements of A with the +# unique elements that we see in the order that we see them. Once we have iterated +# through A, we resize A based on the number of unique elements that we see. +function _groupedunique!(A::AbstractVector) + isempty(A) && return A + idxs = eachindex(A) + y = first(A) + state = start(idxs) + i, state = next(idxs, state) + for x in A + if !isequal(x, y) + i, state = next(idxs, state) + y = A[i] = x + end + end + resize!(A, i - first(idxs) + 1) +end + +""" + unique!(A::AbstractVector) + +Remove duplicate items as determined by [`isequal`](@ref), then return the modified `A`. +`unique!` will return the elements of `A` in the order that they occur. If you do not care +about the order of the returned data, then calling `(sort!(A); unique!(A))` will be much +more efficient as long as the elements of `A` can be sorted. + +```jldoctest +julia> unique!([1, 1, 1]) +1-element Array{Int64,1}: + 1 + +julia> A = [7, 3, 2, 3, 7, 5]; + +julia> unique!(A) +4-element Array{Int64,1}: + 7 + 3 + 2 + 5 + +julia> B = [7, 6, 42, 6, 7, 42]; + +julia> sort!(B); # unique! is able to process sorted data much more efficiently. + +julia> unique!(B) +3-element Array{Int64,1}: + 6 + 7 + 42 +``` +""" +function unique!(A::Union{AbstractVector{<:Real}, AbstractVector{<:AbstractString}, + AbstractVector{<:Symbol}}) + if isempty(A) + return A + elseif issorted(A) || issorted(A, rev=true) + return _groupedunique!(A) + else + return _unique!(A) + end +end +# issorted fails for some element types, so the method above has to be restricted to +# elements with isless/< defined. +function unique!(A) + if isempty(A) + return A + else + return _unique!(A) + end +end + """ allunique(itr) -> Bool diff --git a/doc/src/stdlib/collections.md b/doc/src/stdlib/collections.md index 1ab225a854208..89d7ddd2ceea5 100644 --- a/doc/src/stdlib/collections.md +++ b/doc/src/stdlib/collections.md @@ -79,6 +79,7 @@ Base.eltype Base.indexin Base.findin Base.unique +Base.unique! Base.allunique Base.reduce(::Any, ::Any, ::Any) Base.reduce(::Any, ::Any) diff --git a/test/TestHelpers.jl b/test/TestHelpers.jl index 42ed574835063..8debcba768ed8 100644 --- a/test/TestHelpers.jl +++ b/test/TestHelpers.jl @@ -224,6 +224,8 @@ _offset(out, ::Tuple{}, ::Tuple{}) = out indsoffset(r::Range) = first(r) - 1 indsoffset(i::Integer) = 0 +Base.resize!(A::OffsetVector, nl::Integer) = (resize!(A.parent, nl); A) + end end diff --git a/test/sets.jl b/test/sets.jl index f8cc3fc28edd7..8808036301acb 100644 --- a/test/sets.jl +++ b/test/sets.jl @@ -1,6 +1,8 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license # Set tests +isdefined(Main, :TestHelpers) || @eval Main include("TestHelpers.jl") +using TestHelpers.OAs # Construction, collect @test ===(typeof(Set([1,2,3])), Set{Int}) @@ -221,6 +223,42 @@ u = unique([1,1,2]) @test @inferred(unique(x for x in 1:1)) == [1] @test unique(x for x in Any[1,1.0])::Vector{Real} == [1] +# unique! +@testset "unique!" begin + u = [1,1,3,2,1] + unique!(u) + @test u == [1,3,2] + @test unique!([]) == [] + @test unique!(Float64[]) == Float64[] + u = [1,2,2,3,5,5] + @test unique!(u) === u + @test u == [1,2,3,5] + u = [6,5,5,3,3,2,1] + @test unique!(u) === u + @test u == [6,5,3,2,1] + u = OffsetArray([1,2,2,3,5,5], -1) + @test unique!(u) === u + @test u == OffsetArray([1,2,3,5], -1) + u = OffsetArray([5,5,4,4,2,2,0,-1,-1], -1) + @test unique!(u) === u + @test u == OffsetArray([5,4,2,0,-1], -1) + u = OffsetArray(["w","we","w",5,"r",5,5], -1) + @test unique!(u) === u + @test u == OffsetArray(["w","we",5,"r"], -1) + u = [0.0,-0.0,1.0,2] + @test unique!(u) === u + @test u == [0.0,-0.0,1.0,2.0] + u = [1,NaN,NaN,3] + @test unique!(u) === u + @test u[1] == 1 + @test isnan(u[2]) + @test u[3] == 3 + u = [5,"w","we","w","r",5,"w"] + unique!(u) + @test u == [5,"w","we","r"] + u = [1,2,5,1,3,2] +end + # allunique @test allunique([]) @test allunique(Set()) From 00b9ea250ec824106aa82933b6f787b290e5e736 Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Thu, 15 Jun 2017 19:11:44 -0700 Subject: [PATCH 1103/1534] Remove the FFTW bindings from Base (#21956) --- .travis.yml | 2 +- DISTRIBUTING.md | 5 +- LICENSE.md | 1 - Make.inc | 17 - Makefile | 5 - README.arm.md | 3 +- README.md | 3 - base/Makefile | 2 - base/deprecated.jl | 51 ++ base/dft.jl | 591 ----------------- base/docs/basedocs.jl | 2 +- base/dsp.jl | 207 ------ base/exports.jl | 37 -- base/fft/FFTW.jl | 802 ----------------------- base/fft/dct.jl | 103 --- base/sysimg.jl | 6 - base/util.jl | 8 - contrib/julia.lang | 1 - contrib/julia.xml | 1 - contrib/mac/macports.make | 1 - contrib/vagrant/Vagrantfile | 4 +- contrib/windows/msys_build.sh | 2 +- deps/Makefile | 11 +- deps/Versions.make | 1 - deps/fftw.mk | 116 ---- doc/src/manual/documentation.md | 2 +- doc/src/manual/noteworthy-differences.md | 2 - doc/src/stdlib/math.md | 51 -- test/choosetests.jl | 4 - test/dsp.jl | 139 ---- test/fft.jl | 352 ---------- test/offsetarray.jl | 25 - test/subarray.jl | 8 - 33 files changed, 62 insertions(+), 2503 deletions(-) delete mode 100644 base/dft.jl delete mode 100644 base/dsp.jl delete mode 100644 base/fft/FFTW.jl delete mode 100644 base/fft/dct.jl delete mode 100644 deps/fftw.mk delete mode 100644 test/dsp.jl delete mode 100644 test/fft.jl diff --git a/.travis.yml b/.travis.yml index 66afbebdd48c8..4d7ac5e3d254c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -86,7 +86,7 @@ before_install: BUILDOPTS="-j3 USECLANG=1 LLVM_CONFIG=$(brew --prefix llvm39-julia)/bin/llvm-config LLVM_SIZE=$(brew --prefix llvm39-julia)/bin/llvm-size"; BUILDOPTS="$BUILDOPTS VERBOSE=1 USE_BLAS64=0 SUITESPARSE_INC=-I$(brew --prefix suite-sparse-julia)/include FORCE_ASSERTIONS=1"; BUILDOPTS="$BUILDOPTS LIBBLAS=-lopenblas LIBBLASNAME=libopenblas LIBLAPACK=-lopenblas LIBLAPACKNAME=libopenblas"; - for lib in LLVM SUITESPARSE ARPACK BLAS FFTW LAPACK GMP MPFR PCRE LIBUNWIND; do + for lib in LLVM SUITESPARSE ARPACK BLAS LAPACK GMP MPFR PCRE LIBUNWIND; do BUILDOPTS="$BUILDOPTS USE_SYSTEM_$lib=1"; done; export LDFLAGS="-L$(brew --prefix openblas-julia)/lib -L$(brew --prefix suite-sparse-julia)/lib"; diff --git a/DISTRIBUTING.md b/DISTRIBUTING.md index cdceecb728e30..2d0e6916e2037 100644 --- a/DISTRIBUTING.md +++ b/DISTRIBUTING.md @@ -12,9 +12,8 @@ separated most of the notes by OS. Note that while the code for Julia is [MIT-licensed, with a few exceptions](https://github.com/JuliaLang/julia/blob/master/LICENSE.md), the distribution created by the techniques described herein will be -GPL licensed, as various dependent libraries such as `FFTW` and -`SuiteSparse` are GPL licensed. We do hope to have a -non-GPL distribution of Julia in the future. +GPL licensed, as various dependent libraries such as `SuiteSparse` are +GPL licensed. We do hope to have a non-GPL distribution of Julia in the future. Versioning and Git ------------------ diff --git a/LICENSE.md b/LICENSE.md index 1d812d2a7c300..8904e41b74eb0 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -56,7 +56,6 @@ their own licenses: - [OPENLIBM](https://github.com/JuliaLang/openlibm/blob/master/LICENSE.md) [MIT, BSD-2, ISC] - [OPENSPECFUN](https://github.com/JuliaLang/openspecfun) [MIT, public domain] - [FADDEEVA](http://ab-initio.mit.edu/Faddeeva) [MIT] -- [FFTW](http://fftw.org/doc/License-and-Copyright.html) [GPL2+] - [GMP](http://gmplib.org/manual/Copying.html#Copying) [LGPL3+ or GPL2+] - [LIBGIT2](https://github.com/libgit2/libgit2/blob/development/COPYING) [GPL2+ with unlimited linking exception] - [CURL](https://curl.haxx.se/docs/copyright.html) [MIT/X derivative] diff --git a/Make.inc b/Make.inc index 2b9a9df45950f..4b2524a8ca7c1 100644 --- a/Make.inc +++ b/Make.inc @@ -35,7 +35,6 @@ USE_SYSTEM_OPENSPECFUN:=0 USE_SYSTEM_DSFMT:=0 USE_SYSTEM_BLAS:=0 USE_SYSTEM_LAPACK:=0 -USE_SYSTEM_FFTW:=0 USE_SYSTEM_GMP:=0 USE_SYSTEM_MPFR:=0 USE_SYSTEM_ARPACK:=0 @@ -54,8 +53,6 @@ USE_LLVM_SHLIB := 1 ## Settings for various Intel tools # Set to 1 to use MKL USE_INTEL_MKL ?= 0 -# Set to 1 to use MKL FFT -USE_INTEL_MKL_FFT ?= 0 # Set to 1 to use Intel LIBM USE_INTEL_LIBM ?= 0 # Set to 1 to enable profiling with Intel VTune Amplifier @@ -864,14 +861,6 @@ LIBLAPACKNAME := liblapack endif endif -ifeq ($(OS), WINNT) -LIBFFTWNAME := libfftw3 -LIBFFTWFNAME := libfftw3f -else -LIBFFTWNAME := libfftw3_threads -LIBFFTWFNAME := libfftw3f_threads -endif - ifeq ($(USE_SYSTEM_LIBM), 1) LIBM := -lm LIBMNAME := libm @@ -1059,12 +1048,6 @@ LIBBLAS := $(MKL_LDFLAGS) LIBLAPACK := $(MKL_LDFLAGS) endif -ifeq ($(USE_INTEL_MKL_FFT), 1) -USE_SYSTEM_FFTW := 1 -LIBFFTWNAME := libmkl_rt -LIBFFTWFNAME := libmkl_rt -endif - ifeq ($(HAVE_SSP),1) JCPPFLAGS += -DHAVE_SSP=1 ifeq ($(USEGCC),1) diff --git a/Makefile b/Makefile index e30685efe3f9b..fbfa04579240f 100644 --- a/Makefile +++ b/Makefile @@ -246,11 +246,6 @@ JL_PRIVATE_LIBS := ccalltest ifeq ($(USE_GPL_LIBS), 1) JL_PRIVATE_LIBS += suitesparse_wrapper endif -ifeq ($(USE_SYSTEM_FFTW),0) -ifeq ($(USE_GPL_LIBS), 1) -JL_PRIVATE_LIBS += fftw3 fftw3f fftw3_threads fftw3f_threads -endif -endif ifeq ($(USE_SYSTEM_PCRE),0) JL_PRIVATE_LIBS += pcre endif diff --git a/README.arm.md b/README.arm.md index b4320738be8c8..9de38fdeee94e 100644 --- a/README.arm.md +++ b/README.arm.md @@ -27,7 +27,6 @@ adding the following lines in `Make.user`: override USE_SYSTEM_BLAS=1 override USE_SYSTEM_LAPACK=1 override USE_SYSTEM_LIBM=1 -override USE_SYSTEM_FFTW=1 override USE_SYSTEM_GMP=1 override USE_SYSTEM_MPFR=1 override USE_SYSTEM_ARPACK=1 @@ -36,7 +35,7 @@ override USE_SYSTEM_ARPACK=1 The following command will install all the necessary libraries on Ubuntu: ```` -sudo apt-get install libblas3gf liblapack3gf libarpack2 libfftw3-dev libgmp3-dev \ +sudo apt-get install libblas3gf liblapack3gf libarpack2 libgmp3-dev \ libmpfr-dev libblas-dev liblapack-dev cmake gcc-4.8 \ g++-4.8 gfortran libgfortran3 m4 libedit-dev ```` diff --git a/README.md b/README.md index 6f11425865ca7..80a08906046de 100644 --- a/README.md +++ b/README.md @@ -295,7 +295,6 @@ Julia uses the following external libraries, which are automatically downloaded - **[AMOS]** — subroutines for computing Bessel and Airy functions. - **[SuiteSparse]** (>= 4.1) — library of linear algebra routines for sparse matrices. - **[ARPACK]** — collection of subroutines designed to solve large, sparse eigenvalue problems. -- **[FFTW]** (>= 3.3) — library for computing fast Fourier transforms very quickly and efficiently. - **[PCRE]** (>= 10.00) — Perl-compatible regular expressions library. - **[GMP]** (>= 5.0) — GNU multiple precision arithmetic library, needed for `BigInt` support. - **[MPFR]** (>= 3.0) — GNU multiple precision floating point library, needed for arbitrary precision floating point (`BigFloat`) support. @@ -327,7 +326,6 @@ Julia uses the following external libraries, which are automatically downloaded [SuiteSparse]: http://faculty.cse.tamu.edu/davis/suitesparse.html [AMOS]: http://netlib.org/amos [ARPACK]: http://forge.scilab.org/index.php/p/arpack-ng -[FFTW]: http://www.fftw.org [PCRE]: http://www.pcre.org [LLVM]: http://www.llvm.org [FemtoLisp]: https://github.com/JeffBezanson/femtolisp @@ -368,7 +366,6 @@ Add the following to the `Make.user` file: USEICC = 1 USEIFC = 1 USE_INTEL_MKL = 1 - USE_INTEL_MKL_FFT = 1 USE_INTEL_LIBM = 1 It is highly recommended to start with a fresh clone of the Julia repository. diff --git a/base/Makefile b/base/Makefile index 02d68c08ea3cd..cc07a57aa8f57 100644 --- a/base/Makefile +++ b/base/Makefile @@ -53,8 +53,6 @@ ifeq ($(USE_GPL_LIBS), 1) else @echo "const USE_GPL_LIBS = false" >> $@ endif - @echo "const libfftw_name = \"$(LIBFFTWNAME)\"" >> $@ - @echo "const libfftwf_name = \"$(LIBFFTWFNAME)\"" >> $@ @echo "const libllvm_version_string = \"$$($(LLVM_CONFIG_HOST) --version)\"" >> $@ @echo "const VERSION_STRING = \"$(JULIA_VERSION)\"" >> $@ @echo "const TAGGED_RELEASE_BANNER = \"$(TAGGED_RELEASE_BANNER)\"" >> $@ diff --git a/base/deprecated.jl b/base/deprecated.jl index f600006bddc47..0293f8c24f51a 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1434,6 +1434,57 @@ module Operators end export Operators +# PR #21956 +# This mimics the structure as it was defined in Base to avoid directly breaking code +# that assumes this structure +module DFT + for f in [:bfft, :bfft!, :brfft, :dct, :dct!, :fft, :fft!, :fftshift, :idct, :idct!, + :ifft, :ifft!, :ifftshift, :irfft, :plan_bfft, :plan_bfft!, :plan_brfft, + :plan_dct, :plan_dct!, :plan_fft, :plan_fft!, :plan_idct, :plan_idct!, + :plan_ifft, :plan_ifft!, :plan_irfft, :plan_rfft, :rfft] + pkg = endswith(String(f), "shift") ? "AbstractFFTs" : "FFTW" + @eval begin + function $f(args...; kwargs...) + error($f, " has been moved to the package $pkg.jl.\n", + "Run `Pkg.add(\"$pkg\")` to install $pkg then run `using $pkg` ", + "to load it.") + end + export $f + end + end + module FFTW + for f in [:r2r, :r2r!, :plan_r2r, :plan_r2r!] + @eval begin + function $f(args...; kwargs...) + error($f, " has been moved to the package FFTW.jl.\n", + "Run `Pkg.add(\"FFTW\")` to install FFTW then run `using FFTW` ", + "to load it.") + end + export $f + end + end + end + export FFTW +end +using .DFT +for f in names(DFT) + @eval export $f +end +module DSP + for f in [:conv, :conv2, :deconv, :filt, :filt!, :xcorr] + @eval begin + function $f(args...; kwargs...) + error($f, " has been moved to the package DSP.jl.\n", + "Run `Pkg.add(\"DSP\")` to install DSP then run `using DSP` ", + "to load it.") + end + export $f + end + end +end +using .DSP +export conv, conv2, deconv, filt, filt!, xcorr + # END 0.7 deprecations # BEGIN 1.0 deprecations diff --git a/base/dft.jl b/base/dft.jl deleted file mode 100644 index ab4e7e0269409..0000000000000 --- a/base/dft.jl +++ /dev/null @@ -1,591 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -module DFT - -# DFT plan where the inputs are an array of eltype T -abstract type Plan{T} end - -import Base: show, summary, size, ndims, length, eltype, - *, A_mul_B!, inv, \, A_ldiv_B! - -eltype(::Type{Plan{T}}) where {T} = T - -# size(p) should return the size of the input array for p -size(p::Plan, d) = size(p)[d] -ndims(p::Plan) = length(size(p)) -length(p::Plan) = prod(size(p))::Int - -############################################################################## -export fft, ifft, bfft, fft!, ifft!, bfft!, - plan_fft, plan_ifft, plan_bfft, plan_fft!, plan_ifft!, plan_bfft!, - rfft, irfft, brfft, plan_rfft, plan_irfft, plan_brfft - -const FFTWFloat = Union{Float32,Float64} -fftwfloat(x) = _fftwfloat(float(x)) -_fftwfloat(::Type{T}) where {T<:FFTWFloat} = T -_fftwfloat(::Type{Float16}) = Float32 -_fftwfloat(::Type{Complex{T}}) where {T} = Complex{_fftwfloat(T)} -_fftwfloat(::Type{T}) where {T} = error("type $T not supported") -_fftwfloat(x::T) where {T} = _fftwfloat(T)(x) - -complexfloat(x::StridedArray{Complex{<:FFTWFloat}}) = x -realfloat(x::StridedArray{<:FFTWFloat}) = x - -# return an Array, rather than similar(x), to avoid an extra copy for FFTW -# (which only works on StridedArray types). -complexfloat(x::AbstractArray{T}) where {T<:Complex} = copy1(typeof(fftwfloat(zero(T))), x) -complexfloat(x::AbstractArray{T}) where {T<:Real} = copy1(typeof(complex(fftwfloat(zero(T)))), x) - -realfloat(x::AbstractArray{T}) where {T<:Real} = copy1(typeof(fftwfloat(zero(T))), x) - -# copy to a 1-based array, using circular permutation -function copy1(::Type{T}, x) where T - y = Array{T}(map(length, indices(x))) - Base.circcopy!(y, x) -end - -to1(x::AbstractArray) = _to1(indices(x), x) -_to1(::Tuple{Base.OneTo,Vararg{Base.OneTo}}, x) = x -_to1(::Tuple, x) = copy1(eltype(x), x) - -# implementations only need to provide plan_X(x, region) -# for X in (:fft, :bfft, ...): -for f in (:fft, :bfft, :ifft, :fft!, :bfft!, :ifft!, :rfft) - pf = Symbol("plan_", f) - @eval begin - $f(x::AbstractArray) = (y = to1(x); $pf(y) * y) - $f(x::AbstractArray, region) = (y = to1(x); $pf(y, region) * y) - $pf(x::AbstractArray; kws...) = (y = to1(x); $pf(y, 1:ndims(y); kws...)) - end -end - -""" - plan_ifft(A [, dims]; flags=FFTW.ESTIMATE; timelimit=Inf) - -Same as [`plan_fft`](@ref), but produces a plan that performs inverse transforms -[`ifft`](@ref). -""" -plan_ifft - -""" - plan_ifft!(A [, dims]; flags=FFTW.ESTIMATE; timelimit=Inf) - -Same as [`plan_ifft`](@ref), but operates in-place on `A`. -""" -plan_ifft! - -""" - plan_bfft!(A [, dims]; flags=FFTW.ESTIMATE; timelimit=Inf) - -Same as [`plan_bfft`](@ref), but operates in-place on `A`. -""" -plan_bfft! - -""" - plan_bfft(A [, dims]; flags=FFTW.ESTIMATE; timelimit=Inf) - -Same as [`plan_fft`](@ref), but produces a plan that performs an unnormalized -backwards transform [`bfft`](@ref). -""" -plan_bfft - -""" - plan_fft(A [, dims]; flags=FFTW.ESTIMATE; timelimit=Inf) - -Pre-plan an optimized FFT along given dimensions (`dims`) of arrays matching the shape and -type of `A`. (The first two arguments have the same meaning as for [`fft`](@ref).) -Returns an object `P` which represents the linear operator computed by the FFT, and which -contains all of the information needed to compute `fft(A, dims)` quickly. - -To apply `P` to an array `A`, use `P * A`; in general, the syntax for applying plans is much -like that of matrices. (A plan can only be applied to arrays of the same size as the `A` -for which the plan was created.) You can also apply a plan with a preallocated output array `Â` -by calling `A_mul_B!(Â, plan, A)`. (For `A_mul_B!`, however, the input array `A` must -be a complex floating-point array like the output `Â`.) You can compute the inverse-transform plan by `inv(P)` -and apply the inverse plan with `P \\ Â` (the inverse plan is cached and reused for -subsequent calls to `inv` or `\\`), and apply the inverse plan to a pre-allocated output -array `A` with `A_ldiv_B!(A, P, Â)`. - -The `flags` argument is a bitwise-or of FFTW planner flags, defaulting to `FFTW.ESTIMATE`. -e.g. passing `FFTW.MEASURE` or `FFTW.PATIENT` will instead spend several seconds (or more) -benchmarking different possible FFT algorithms and picking the fastest one; see the FFTW -manual for more information on planner flags. The optional `timelimit` argument specifies a -rough upper bound on the allowed planning time, in seconds. Passing `FFTW.MEASURE` or -`FFTW.PATIENT` may cause the input array `A` to be overwritten with zeros during plan -creation. - -[`plan_fft!`](@ref) is the same as [`plan_fft`](@ref) but creates a -plan that operates in-place on its argument (which must be an array of complex -floating-point numbers). [`plan_ifft`](@ref) and so on are similar but produce -plans that perform the equivalent of the inverse transforms [`ifft`](@ref) and so on. -""" -plan_fft - -""" - plan_fft!(A [, dims]; flags=FFTW.ESTIMATE; timelimit=Inf) - -Same as [`plan_fft`](@ref), but operates in-place on `A`. -""" -plan_fft! - -""" - rfft(A [, dims]) - -Multidimensional FFT of a real array `A`, exploiting the fact that the transform has -conjugate symmetry in order to save roughly half the computational time and storage costs -compared with [`fft`](@ref). If `A` has size `(n_1, ..., n_d)`, the result has size -`(div(n_1,2)+1, ..., n_d)`. - -The optional `dims` argument specifies an iterable subset of one or more dimensions of `A` -to transform, similar to [`fft`](@ref). Instead of (roughly) halving the first -dimension of `A` in the result, the `dims[1]` dimension is (roughly) halved in the same way. -""" -rfft - -""" - ifft!(A [, dims]) - -Same as [`ifft`](@ref), but operates in-place on `A`. -""" -ifft! - -""" - ifft(A [, dims]) - -Multidimensional inverse FFT. - -A one-dimensional inverse FFT computes - -```math -\\operatorname{IDFT}(A)[k] = \\frac{1}{\\operatorname{length}(A)} -\\sum_{n=1}^{\\operatorname{length}(A)} \\exp\\left(+i\\frac{2\\pi (n-1)(k-1)} -{\\operatorname{length}(A)} \\right) A[n]. -``` - -A multidimensional inverse FFT simply performs this operation along each transformed dimension of `A`. -""" -ifft - -""" - fft!(A [, dims]) - -Same as [`fft`](@ref), but operates in-place on `A`, which must be an array of -complex floating-point numbers. -""" -fft! - -""" - bfft(A [, dims]) - -Similar to [`ifft`](@ref), but computes an unnormalized inverse (backward) -transform, which must be divided by the product of the sizes of the transformed dimensions -in order to obtain the inverse. (This is slightly more efficient than [`ifft`](@ref) -because it omits a scaling step, which in some applications can be combined with other -computational steps elsewhere.) - -```math -\\operatorname{BDFT}(A)[k] = \\operatorname{length}(A) \\operatorname{IDFT}(A)[k] -``` -""" -bfft - -""" - bfft!(A [, dims]) - -Same as [`bfft`](@ref), but operates in-place on `A`. -""" -bfft! - -# promote to a complex floating-point type (out-of-place only), -# so implementations only need Complex{Float} methods -for f in (:fft, :bfft, :ifft) - pf = Symbol("plan_", f) - @eval begin - $f(x::AbstractArray{<:Real}, region=1:ndims(x)) = $f(complexfloat(x), region) - $pf(x::AbstractArray{<:Real}, region; kws...) = $pf(complexfloat(x), region; kws...) - $f(x::AbstractArray{<:Complex{<:Union{Integer,Rational}}}, region=1:ndims(x)) = $f(complexfloat(x), region) - $pf(x::AbstractArray{<:Complex{<:Union{Integer,Rational}}}, region; kws...) = $pf(complexfloat(x), region; kws...) - end -end -rfft(x::AbstractArray{<:Union{Integer,Rational}}, region=1:ndims(x)) = rfft(realfloat(x), region) -plan_rfft(x::AbstractArray, region; kws...) = plan_rfft(realfloat(x), region; kws...) - -# only require implementation to provide *(::Plan{T}, ::Array{T}) -*(p::Plan{T}, x::AbstractArray) where {T} = p * copy1(T, x) - -# Implementations should also implement A_mul_B!(Y, plan, X) so as to support -# pre-allocated output arrays. We don't define * in terms of A_mul_B! -# generically here, however, because of subtleties for in-place and rfft plans. - -############################################################################## -# To support inv, \, and A_ldiv_B!(y, p, x), we require Plan subtypes -# to have a pinv::Plan field, which caches the inverse plan, and which -# should be initially undefined. They should also implement -# plan_inv(p) to construct the inverse of a plan p. - -# hack from @simonster (in #6193) to compute the return type of plan_inv -# without actually calling it or even constructing the empty arrays. -_pinv_type(p::Plan) = typeof([plan_inv(x) for x in typeof(p)[]]) -pinv_type(p::Plan) = eltype(_pinv_type(p)) - -inv(p::Plan) = - isdefined(p, :pinv) ? p.pinv::pinv_type(p) : (p.pinv = plan_inv(p)) -\(p::Plan, x::AbstractArray) = inv(p) * x -A_ldiv_B!(y::AbstractArray, p::Plan, x::AbstractArray) = A_mul_B!(y, inv(p), x) - -############################################################################## -# implementations only need to provide the unnormalized backwards FFT, -# similar to FFTW, and we do the scaling generically to get the ifft: - -mutable struct ScaledPlan{T,P,N} <: Plan{T} - p::P - scale::N # not T, to avoid unnecessary promotion to Complex - pinv::Plan - ScaledPlan{T,P,N}(p, scale) where {T,P,N} = new(p, scale) -end -ScaledPlan{T}(p::P, scale::N) where {T,P,N} = ScaledPlan{T,P,N}(p, scale) -ScaledPlan(p::Plan{T}, scale::Number) where {T} = ScaledPlan{T}(p, scale) -ScaledPlan(p::ScaledPlan, α::Number) = ScaledPlan(p.p, p.scale * α) - -size(p::ScaledPlan) = size(p.p) - -show(io::IO, p::ScaledPlan) = print(io, p.scale, " * ", p.p) -summary(p::ScaledPlan) = string(p.scale, " * ", summary(p.p)) - -*(p::ScaledPlan, x::AbstractArray) = scale!(p.p * x, p.scale) - -*(α::Number, p::Plan) = ScaledPlan(p, α) -*(p::Plan, α::Number) = ScaledPlan(p, α) -*(I::UniformScaling, p::ScaledPlan) = ScaledPlan(p, I.λ) -*(p::ScaledPlan, I::UniformScaling) = ScaledPlan(p, I.λ) -*(I::UniformScaling, p::Plan) = ScaledPlan(p, I.λ) -*(p::Plan, I::UniformScaling) = ScaledPlan(p, I.λ) - -# Normalization for ifft, given unscaled bfft, is 1/prod(dimensions) -normalization(T, sz, region) = one(T) / Int(prod([sz...][[region...]])) -normalization(X, region) = normalization(real(eltype(X)), size(X), region) - -plan_ifft(x::AbstractArray, region; kws...) = - ScaledPlan(plan_bfft(x, region; kws...), normalization(x, region)) -plan_ifft!(x::AbstractArray, region; kws...) = - ScaledPlan(plan_bfft!(x, region; kws...), normalization(x, region)) - -plan_inv(p::ScaledPlan) = ScaledPlan(plan_inv(p.p), inv(p.scale)) - -A_mul_B!(y::AbstractArray, p::ScaledPlan, x::AbstractArray) = - scale!(p.scale, A_mul_B!(y, p.p, x)) - -############################################################################## -# Real-input DFTs are annoying because the output has a different size -# than the input if we want to gain the full factor-of-two(ish) savings -# For backward real-data transforms, we must specify the original length -# of the first dimension, since there is no reliable way to detect this -# from the data (we can't detect whether the dimension was originally even -# or odd). - -for f in (:brfft, :irfft) - pf = Symbol("plan_", f) - @eval begin - $f(x::AbstractArray, d::Integer) = $pf(x, d) * x - $f(x::AbstractArray, d::Integer, region) = $pf(x, d, region) * x - $pf(x::AbstractArray, d::Integer;kws...) = $pf(x, d, 1:ndims(x);kws...) - end -end - -for f in (:brfft, :irfft) - @eval begin - $f(x::AbstractArray{<:Real}, d::Integer, region=1:ndims(x)) = $f(complexfloat(x), d, region) - $f(x::AbstractArray{<:Complex{<:Union{Integer,Rational}}}, d::Integer, region=1:ndims(x)) = $f(complexfloat(x), d, region) - end -end - -""" - irfft(A, d [, dims]) - -Inverse of [`rfft`](@ref): for a complex array `A`, gives the corresponding real -array whose FFT yields `A` in the first half. As for [`rfft`](@ref), `dims` is an -optional subset of dimensions to transform, defaulting to `1:ndims(A)`. - -`d` is the length of the transformed real array along the `dims[1]` dimension, which must -satisfy `div(d,2)+1 == size(A,dims[1])`. (This parameter cannot be inferred from `size(A)` -since both `2*size(A,dims[1])-2` as well as `2*size(A,dims[1])-1` are valid sizes for the -transformed real array.) -""" -irfft - -""" - brfft(A, d [, dims]) - -Similar to [`irfft`](@ref) but computes an unnormalized inverse transform (similar -to [`bfft`](@ref)), which must be divided by the product of the sizes of the -transformed dimensions (of the real output array) in order to obtain the inverse transform. -""" -brfft - -function rfft_output_size(x::AbstractArray, region) - d1 = first(region) - osize = [size(x)...] - osize[d1] = osize[d1]>>1 + 1 - return osize -end - -function brfft_output_size(x::AbstractArray, d::Integer, region) - d1 = first(region) - osize = [size(x)...] - @assert osize[d1] == d>>1 + 1 - osize[d1] = d - return osize -end - -plan_irfft(x::AbstractArray{Complex{T}}, d::Integer, region; kws...) where {T} = - ScaledPlan(plan_brfft(x, d, region; kws...), - normalization(T, brfft_output_size(x, d, region), region)) - -""" - plan_irfft(A, d [, dims]; flags=FFTW.ESTIMATE; timelimit=Inf) - -Pre-plan an optimized inverse real-input FFT, similar to [`plan_rfft`](@ref) -except for [`irfft`](@ref) and [`brfft`](@ref), respectively. The first -three arguments have the same meaning as for [`irfft`](@ref). -""" -plan_irfft - -############################################################################## - -export fftshift, ifftshift - -fftshift(x) = circshift(x, div.([size(x)...],2)) - -""" - fftshift(x) - -Swap the first and second halves of each dimension of `x`. -""" -fftshift(x) - -function fftshift(x,dim) - s = zeros(Int,ndims(x)) - for i in dim - s[i] = div(size(x,i),2) - end - circshift(x, s) -end - -""" - fftshift(x,dim) - -Swap the first and second halves of the given dimension or iterable of dimensions of array `x`. -""" -fftshift(x,dim) - -ifftshift(x) = circshift(x, div.([size(x)...],-2)) - -""" - ifftshift(x, [dim]) - -Undoes the effect of `fftshift`. -""" -ifftshift - -function ifftshift(x,dim) - s = zeros(Int,ndims(x)) - for i in dim - s[i] = -div(size(x,i),2) - end - circshift(x, s) -end - -############################################################################## - -# FFTW module (may move to an external package at some point): -""" - fft(A [, dims]) - -Performs a multidimensional FFT of the array `A`. The optional `dims` argument specifies an -iterable subset of dimensions (e.g. an integer, range, tuple, or array) to transform along. -Most efficient if the size of `A` along the transformed dimensions is a product of small -primes; see `nextprod()`. See also `plan_fft()` for even greater efficiency. - -A one-dimensional FFT computes the one-dimensional discrete Fourier transform (DFT) as -defined by - -```math -\\operatorname{DFT}(A)[k] = - \\sum_{n=1}^{\\operatorname{length}(A)} - \\exp\\left(-i\\frac{2\\pi - (n-1)(k-1)}{\\operatorname{length}(A)} \\right) A[n]. -``` - -A multidimensional FFT simply performs this operation along each transformed dimension of `A`. - -!!! note - * Julia starts FFTW up with 1 thread by default. Higher performance is usually possible by - increasing number of threads. Use `FFTW.set_num_threads(Sys.CPU_CORES)` to use as many - threads as cores on your system. - - * This performs a multidimensional FFT by default. FFT libraries in other languages such as - Python and Octave perform a one-dimensional FFT along the first non-singleton dimension - of the array. This is worth noting while performing comparisons. For more details, - refer to the [Noteworthy Differences from other Languages](@ref) - section of the manual. -""" -fft - -""" - plan_rfft(A [, dims]; flags=FFTW.ESTIMATE; timelimit=Inf) - -Pre-plan an optimized real-input FFT, similar to [`plan_fft`](@ref) except for -[`rfft`](@ref) instead of [`fft`](@ref). The first two arguments, and the -size of the transformed result, are the same as for [`rfft`](@ref). -""" -plan_rfft - -""" - plan_brfft(A, d [, dims]; flags=FFTW.ESTIMATE; timelimit=Inf) - -Pre-plan an optimized real-input unnormalized transform, similar to -[`plan_rfft`](@ref) except for [`brfft`](@ref) instead of -[`rfft`](@ref). The first two arguments and the size of the transformed result, are -the same as for [`brfft`](@ref). -""" -plan_brfft - -module FFTW - import ..DFT: fft, bfft, ifft, rfft, brfft, irfft, plan_fft, plan_bfft, plan_ifft, - plan_rfft, plan_brfft, plan_irfft, fft!, bfft!, ifft!, plan_fft!, plan_bfft!, plan_ifft!, - Plan, rfft_output_size, brfft_output_size, plan_inv, normalization, ScaledPlan - - export r2r, r2r!, plan_r2r, plan_r2r! - - """ - plan_dct!(A [, dims [, flags [, timelimit]]]) - - Same as [`plan_dct`](@ref), but operates in-place on `A`. - """ - function plan_dct! end - - """ - plan_idct(A [, dims [, flags [, timelimit]]]) - - Pre-plan an optimized inverse discrete cosine transform (DCT), similar to - [`plan_fft`](@ref) except producing a function that computes - [`idct`](@ref). The first two arguments have the same meaning as for - [`idct`](@ref). - """ - function plan_idct end - - """ - plan_dct(A [, dims [, flags [, timelimit]]]) - - Pre-plan an optimized discrete cosine transform (DCT), similar to - [`plan_fft`](@ref) except producing a function that computes - [`dct`](@ref). The first two arguments have the same meaning as for - [`dct`](@ref). - """ - function plan_dct end - - """ - plan_idct!(A [, dims [, flags [, timelimit]]]) - - Same as [`plan_idct`](@ref), but operates in-place on `A`. - """ - function plan_idct! end - - """ - dct(A [, dims]) - - Performs a multidimensional type-II discrete cosine transform (DCT) of the array `A`, using - the unitary normalization of the DCT. The optional `dims` argument specifies an iterable - subset of dimensions (e.g. an integer, range, tuple, or array) to transform along. Most - efficient if the size of `A` along the transformed dimensions is a product of small primes; - see [`nextprod`](@ref). See also [`plan_dct`](@ref) for even greater - efficiency. - """ - function dct end - - """ - idct(A [, dims]) - - Computes the multidimensional inverse discrete cosine transform (DCT) of the array `A` - (technically, a type-III DCT with the unitary normalization). The optional `dims` argument - specifies an iterable subset of dimensions (e.g. an integer, range, tuple, or array) to - transform along. Most efficient if the size of `A` along the transformed dimensions is a - product of small primes; see [`nextprod`](@ref). See also - [`plan_idct`](@ref) for even greater efficiency. - """ - function idct end - - """ - dct!(A [, dims]) - - Same as [`dct!`](@ref), except that it operates in-place on `A`, which must be an - array of real or complex floating-point values. - """ - function dct! end - - """ - idct!(A [, dims]) - - Same as [`idct!`](@ref), but operates in-place on `A`. - """ - function idct! end - - """ - r2r(A, kind [, dims]) - - Performs a multidimensional real-input/real-output (r2r) transform - of type `kind` of the array `A`, as defined in the FFTW manual. - `kind` specifies either a discrete cosine transform of various types - (`FFTW.REDFT00`, `FFTW.REDFT01`, `FFTW.REDFT10`, or - `FFTW.REDFT11`), a discrete sine transform of various types - (`FFTW.RODFT00`, `FFTW.RODFT01`, `FFTW.RODFT10`, or - `FFTW.RODFT11`), a real-input DFT with halfcomplex-format output - (`FFTW.R2HC` and its inverse `FFTW.HC2R`), or a discrete - Hartley transform (`FFTW.DHT`). The `kind` argument may be - an array or tuple in order to specify different transform types - along the different dimensions of `A`; `kind[end]` is used - for any unspecified dimensions. See the FFTW manual for precise - definitions of these transform types, at http://www.fftw.org/doc. - - The optional `dims` argument specifies an iterable subset of - dimensions (e.g. an integer, range, tuple, or array) to transform - along. `kind[i]` is then the transform type for `dims[i]`, - with `kind[end]` being used for `i > length(kind)`. - - See also [`plan_r2r`](@ref) to pre-plan optimized r2r transforms. - """ - function r2r end - - """ - r2r!(A, kind [, dims]) - - Same as [`r2r`](@ref), but operates in-place on `A`, which must be - an array of real or complex floating-point numbers. - """ - function r2r! end - - """ - plan_r2r!(A, kind [, dims [, flags [, timelimit]]]) - - Similar to [`plan_fft`](@ref), but corresponds to [`r2r!`](@ref). - """ - function plan_r2r! end - - """ - plan_r2r(A, kind [, dims [, flags [, timelimit]]]) - - Pre-plan an optimized r2r transform, similar to [`plan_fft`](@ref) - except that the transforms (and the first three arguments) - correspond to [`r2r`](@ref) and [`r2r!`](@ref), respectively. - """ - function plan_r2r end - - (Base.USE_GPL_LIBS || Base.fftw_vendor() == :mkl) && include(joinpath("fft", "FFTW.jl")) -end - -importall .FFTW -export FFTW, dct, idct, dct!, idct!, plan_dct, plan_idct, plan_dct!, plan_idct! - -############################################################################## - -end diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index 8cadb4d1d0b72..c99b9f747cb40 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -17,7 +17,7 @@ as well many great tutorials and learning resources: https://julialang.org/learning/ For help on a specific function or macro, type `?` followed -by its name, e.g. `?fft`, or `?@time`, and press enter. +by its name, e.g. `?cos`, or `?@time`, and press enter. """ kw"help", kw"?", kw"julia" diff --git a/base/dsp.jl b/base/dsp.jl deleted file mode 100644 index 470852e84b561..0000000000000 --- a/base/dsp.jl +++ /dev/null @@ -1,207 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -module DSP - -import Base.trailingsize - -export filt, filt!, deconv, conv, conv2, xcorr - -_zerosi(b,a,T) = zeros(promote_type(eltype(b), eltype(a), T), max(length(a), length(b))-1) - -""" - filt(b, a, x, [si]) - -Apply filter described by vectors `a` and `b` to vector `x`, with an optional initial filter -state vector `si` (defaults to zeros). -""" -function filt(b::Union{AbstractVector, Number}, a::Union{AbstractVector, Number}, - x::AbstractArray{T}, si::AbstractArray{S} = _zerosi(b,a,T)) where {T,S} - filt!(Array{promote_type(eltype(b), eltype(a), T, S)}(size(x)), b, a, x, si) -end - -# in-place filtering: returns results in the out argument, which may shadow x -# (and does so by default) - -""" - filt!(out, b, a, x, [si]) - -Same as [`filt`](@ref) but writes the result into the `out` argument, which may -alias the input `x` to modify it in-place. -""" -function filt!(out::AbstractArray, b::Union{AbstractVector, Number}, a::Union{AbstractVector, Number}, - x::AbstractArray{T}, si::AbstractArray{S,N} = _zerosi(b,a,T)) where {T,S,N} - isempty(b) && throw(ArgumentError("filter vector b must be non-empty")) - isempty(a) && throw(ArgumentError("filter vector a must be non-empty")) - a[1] == 0 && throw(ArgumentError("filter vector a[1] must be nonzero")) - if size(x) != size(out) - throw(ArgumentError("output size $(size(out)) must match input size $(size(x))")) - end - - as = length(a) - bs = length(b) - sz = max(as, bs) - silen = sz - 1 - ncols = trailingsize(x,2) - - if size(si, 1) != silen - throw(ArgumentError("initial state vector si must have max(length(a),length(b))-1 rows")) - end - if N > 1 && trailingsize(si,2) != ncols - throw(ArgumentError("initial state vector si must be a vector or have the same number of columns as x")) - end - - size(x,1) == 0 && return out - sz == 1 && return scale!(out, x, b[1]/a[1]) # Simple scaling without memory - - # Filter coefficient normalization - if a[1] != 1 - norml = a[1] - a ./= norml - b ./= norml - end - # Pad the coefficients with zeros if needed - bs 1 ? col : 1] - if as > 1 - _filt_iir!(out, b, a, x, si, col) - else - _filt_fir!(out, b, x, si, col) - end - end - return out -end - -function _filt_iir!(out, b, a, x, si, col) - silen = length(si) - @inbounds for i=1:size(x, 1) - xi = x[i,col] - val = si[1] + b[1]*xi - for j=1:(silen-1) - si[j] = si[j+1] + b[j+1]*xi - a[j+1]*val - end - si[silen] = b[silen+1]*xi - a[silen+1]*val - out[i,col] = val - end -end - -function _filt_fir!(out, b, x, si, col) - silen = length(si) - @inbounds for i=1:size(x, 1) - xi = x[i,col] - val = si[1] + b[1]*xi - for j=1:(silen-1) - si[j] = si[j+1] + b[j+1]*xi - end - si[silen] = b[silen+1]*xi - out[i,col] = val - end -end - -""" - deconv(b,a) -> c - -Construct vector `c` such that `b = conv(a,c) + r`. -Equivalent to polynomial division. -""" -function deconv(b::StridedVector{T}, a::StridedVector{T}) where T - lb = size(b,1) - la = size(a,1) - if lb < la - return [zero(T)] - end - lx = lb-la+1 - x = zeros(T, lx) - x[1] = 1 - filt(b, a, x) -end - -""" - conv(u,v) - -Convolution of two vectors. Uses FFT algorithm. -""" -function conv(u::StridedVector{T}, v::StridedVector{T}) where T<:Base.LinAlg.BlasFloat - nu = length(u) - nv = length(v) - n = nu + nv - 1 - np2 = n > 1024 ? nextprod([2,3,5], n) : nextpow2(n) - upad = [u; zeros(T, np2 - nu)] - vpad = [v; zeros(T, np2 - nv)] - if T <: Real - p = plan_rfft(upad) - y = irfft((p*upad).*(p*vpad), np2) - else - p = plan_fft!(upad) - y = ifft!((p*upad).*(p*vpad)) - end - return y[1:n] -end -conv(u::StridedVector{T}, v::StridedVector{T}) where {T<:Integer} = round.(Int, conv(float(u), float(v))) -conv(u::StridedVector{<:Integer}, v::StridedVector{<:Base.LinAlg.BlasFloat}) = conv(float(u), v) -conv(u::StridedVector{<:Base.LinAlg.BlasFloat}, v::StridedVector{<:Integer}) = conv(u, float(v)) - -""" - conv2(u,v,A) - -2-D convolution of the matrix `A` with the 2-D separable kernel generated by -the vectors `u` and `v`. -Uses 2-D FFT algorithm. -""" -function conv2(u::StridedVector{T}, v::StridedVector{T}, A::StridedMatrix{T}) where T - m = length(u)+size(A,1)-1 - n = length(v)+size(A,2)-1 - B = zeros(T, m, n) - B[1:size(A,1),1:size(A,2)] = A - u = fft([u;zeros(T,m-length(u))]) - v = fft([v;zeros(T,n-length(v))]) - C = ifft(fft(B) .* (u * v.')) - if T <: Real - return real(C) - end - return C -end - -""" - conv2(B,A) - -2-D convolution of the matrix `B` with the matrix `A`. Uses 2-D FFT algorithm. -""" -function conv2(A::StridedMatrix{T}, B::StridedMatrix{T}) where T - sa, sb = size(A), size(B) - At = zeros(T, sa[1]+sb[1]-1, sa[2]+sb[2]-1) - Bt = zeros(T, sa[1]+sb[1]-1, sa[2]+sb[2]-1) - At[1:sa[1], 1:sa[2]] = A - Bt[1:sb[1], 1:sb[2]] = B - p = plan_fft(At) - C = ifft((p*At).*(p*Bt)) - if T <: Real - return real(C) - end - return C -end -conv2(A::StridedMatrix{T}, B::StridedMatrix{T}) where {T<:Integer} = - round.(Int, conv2(float(A), float(B))) -conv2(u::StridedVector{T}, v::StridedVector{T}, A::StridedMatrix{T}) where {T<:Integer} = - round.(Int, conv2(float(u), float(v), float(A))) - -""" - xcorr(u,v) - -Compute the cross-correlation of two vectors. -""" -function xcorr(u, v) - su = size(u,1); sv = size(v,1) - if su < sv - u = [u;zeros(eltype(u),sv-su)] - elseif sv < su - v = [v;zeros(eltype(v),su-sv)] - end - flipdim(conv(flipdim(u, 1), v), 1) -end - -end # module diff --git a/base/exports.jl b/base/exports.jl index a5e127871f2bf..34e266a0ee002 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -2,7 +2,6 @@ export # Modules - FFTW, Meta, Pkg, LibGit2, @@ -863,42 +862,6 @@ export var, varm, -# signal processing - bfft!, - bfft, - brfft, - conv, - conv2, - dct!, - dct, - deconv, - fft!, - fft, - fftshift, - filt, - filt!, - idct!, - idct, - ifft!, - ifft, - ifftshift, - irfft, - plan_bfft!, - plan_bfft, - plan_brfft, - plan_dct!, - plan_dct, - plan_fft!, - plan_fft, - plan_idct!, - plan_idct, - plan_ifft!, - plan_ifft, - plan_irfft, - plan_rfft, - rfft, - xcorr, - # iteration done, next, diff --git a/base/fft/FFTW.jl b/base/fft/FFTW.jl deleted file mode 100644 index 50cf8556b708d..0000000000000 --- a/base/fft/FFTW.jl +++ /dev/null @@ -1,802 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -import Base: show, *, convert, unsafe_convert, size, strides, ndims, pointer, A_mul_B! - -export export_wisdom, import_wisdom, import_system_wisdom, forget_wisdom, - MEASURE, DESTROY_INPUT, UNALIGNED, CONSERVE_MEMORY, EXHAUSTIVE, - PRESERVE_INPUT, PATIENT, ESTIMATE, WISDOM_ONLY, NO_TIMELIMIT, - R2HC, HC2R, DHT, REDFT00, REDFT01, REDFT10, REDFT11, - RODFT00, RODFT01, RODFT10, RODFT11, - fftwNumber, fftwReal, fftwComplex, flops - -## FFT: Implement fft by calling fftw. - -const libfftw = Base.libfftw_name -const libfftwf = Base.libfftwf_name - -const version = convert(VersionNumber, split(unsafe_string(cglobal( - (:fftw_version,Base.DFT.FFTW.libfftw), UInt8)), ['-', ' '])[2]) - -## Direction of FFT - -const FORWARD = -1 -const BACKWARD = 1 - -## FFTW Flags from fftw3.h - -const MEASURE = UInt32(0) -const DESTROY_INPUT = UInt32(1 << 0) -const UNALIGNED = UInt32(1 << 1) -const CONSERVE_MEMORY = UInt32(1 << 2) -const EXHAUSTIVE = UInt32(1 << 3) # NO_EXHAUSTIVE is default -const PRESERVE_INPUT = UInt32(1 << 4) # cancels DESTROY_INPUT -const PATIENT = UInt32(1 << 5) # IMPATIENT is default -const ESTIMATE = UInt32(1 << 6) -const WISDOM_ONLY = UInt32(1 << 21) -const NO_SIMD = UInt32(1 << 17) # disable SIMD, useful for benchmarking - -## R2R transform kinds - -const R2HC = 0 -const HC2R = 1 -const DHT = 2 -const REDFT00 = 3 -const REDFT01 = 4 -const REDFT10 = 5 -const REDFT11 = 6 -const RODFT00 = 7 -const RODFT01 = 8 -const RODFT10 = 9 -const RODFT11 = 10 - -let k2s = Dict(R2HC => "R2HC", HC2R => "HC2R", DHT => "DHT", REDFT00 => "REDFT00", REDFT01 => "REDFT01", REDFT10 => "REDFT10", REDFT11 => "REDFT11", RODFT00 => "RODFT00", RODFT01 => "RODFT01", RODFT10 => "RODFT10", RODFT11 => "RODFT11") - global kind2string - kind2string(k::Integer) = k2s[Int(k)] -end - -# FFTW floating-point types: - -const fftwNumber = Union{Float64,Float32,Complex128,Complex64} -const fftwReal = Union{Float64,Float32} -const fftwComplex = Union{Complex128,Complex64} -const fftwDouble = Union{Float64,Complex128} -const fftwSingle = Union{Float32,Complex64} -const fftwTypeDouble = Union{Type{Float64},Type{Complex128}} -const fftwTypeSingle = Union{Type{Float32},Type{Complex64}} - -# For ESTIMATE plans, FFTW allows one to pass NULL for the array pointer, -# since it is not written to. Hence, it is convenient to create an -# array-like type that carries a size and a stride like a "real" array -# but which is converted to C_NULL as a pointer. -struct FakeArray{T,N} <: DenseArray{T,N} - sz::NTuple{N,Int} - st::NTuple{N,Int} -end -size(a::FakeArray) = a.sz -strides(a::FakeArray) = a.st -unsafe_convert(::Type{Ptr{T}}, a::FakeArray{T}) where {T} = convert(Ptr{T}, C_NULL) -pointer(a::FakeArray{T}) where {T} = convert(Ptr{T}, C_NULL) -FakeArray(::Type{T}, sz::NTuple{N,Int}) where {T,N} = FakeArray{T,N}(sz, colmajorstrides(sz)) -FakeArray(::Type{T}, sz::Int...) where {T} = FakeArray(T, sz) -fakesimilar(flags, X, T) = flags & ESTIMATE != 0 ? FakeArray(T, size(X)) : Array{T}(size(X)) -alignment_of(A::FakeArray) = Int32(0) - -## Julia wrappers around FFTW functions - -# _init_() must be called before any FFTW planning routine. -# -- Once FFTW is split into its own module, this can be called -# in the module __init__(), but for now we must call it lazily -# in every routine that might initialize the FFTW planner. -# -- This initializes FFTW's threads support (defaulting to 1 thread). -# If this isn't called before the FFTW planner is created, then -# FFTW's threads algorithms won't be registered or used at all. -# (Previously, we called fftw_cleanup, but this invalidated existing -# plans, causing issue #19892.) -const threads_initialized = Ref(false) -function _init_() - if !threads_initialized[] - stat = ccall((:fftw_init_threads,libfftw), Int32, ()) - statf = ccall((:fftwf_init_threads,libfftwf), Int32, ()) - if stat == 0 || statf == 0 - error("could not initialize FFTW threads") - end - threads_initialized[] = true - end -end - -# Wisdom - -# Import and export wisdom to/from a single file for all precisions, -# which is more user-friendly than requiring the user to call a -# separate routine depending on the fp precision of the plans. This -# requires a bit of trickness since we have to (a) use the libc file -# I/O routines with fftw_export_wisdom_to_file/import_wisdom_from_file -# (b) we need 256 bytes of space padding between the wisdoms to work -# around FFTW's internal file i/o buffering [see the BUFSZ constant in -# FFTW's api/import-wisdom-from-file.c file]. - -function export_wisdom(fname::AbstractString) - _init_() - f = ccall(:fopen, Ptr{Void}, (Cstring,Cstring), fname, :w) - systemerror("could not open wisdom file $fname for writing", f == C_NULL) - ccall((:fftw_export_wisdom_to_file,libfftw), Void, (Ptr{Void},), f) - ccall(:fputs, Int32, (Ptr{UInt8},Ptr{Void}), " "^256, f) # no NUL, hence no Cstring - ccall((:fftwf_export_wisdom_to_file,libfftwf), Void, (Ptr{Void},), f) - ccall(:fclose, Void, (Ptr{Void},), f) -end - -function import_wisdom(fname::AbstractString) - _init_() - f = ccall(:fopen, Ptr{Void}, (Cstring,Cstring), fname, :r) - systemerror("could not open wisdom file $fname for reading", f == C_NULL) - if ccall((:fftw_import_wisdom_from_file,libfftw),Int32,(Ptr{Void},),f)==0|| - ccall((:fftwf_import_wisdom_from_file,libfftwf),Int32,(Ptr{Void},),f)==0 - error("failed to import wisdom from $fname") - end - ccall(:fclose, Void, (Ptr{Void},), f) -end - -function import_system_wisdom() - _init_() - if ccall((:fftw_import_system_wisdom,libfftw), Int32, ()) == 0 || - ccall((:fftwf_import_system_wisdom,libfftwf), Int32, ()) == 0 - error("failed to import system wisdom") - end -end - -function forget_wisdom() - _init_() - ccall((:fftw_forget_wisdom,libfftw), Void, ()) - ccall((:fftwf_forget_wisdom,libfftwf), Void, ()) -end - -# Threads - -function set_num_threads(nthreads::Integer) - _init_() - ccall((:fftw_plan_with_nthreads,libfftw), Void, (Int32,), nthreads) - ccall((:fftwf_plan_with_nthreads,libfftwf), Void, (Int32,), nthreads) -end - -# pointer type for fftw_plan (opaque pointer) - -struct fftw_plan_struct end -const PlanPtr = Ptr{fftw_plan_struct} - -# Planner timelimits - -const NO_TIMELIMIT = -1.0 # from fftw3.h - -function set_timelimit(precision::fftwTypeDouble,seconds) - _init_() - ccall((:fftw_set_timelimit,libfftw), Void, (Float64,), seconds) -end - -function set_timelimit(precision::fftwTypeSingle,seconds) - _init_() - ccall((:fftwf_set_timelimit,libfftwf), Void, (Float64,), seconds) -end - -# Array alignment mod 16: -# FFTW plans may depend on the alignment of the array mod 16 bytes, -# i.e. the address mod 16 of the first element of the array, in order -# to exploit SIMD operations. Julia arrays are, by default, aligned -# to 16-byte boundaries (address mod 16 == 0), but this may not be -# true for data imported from external C code, or for SubArrays. -# Use the undocumented routine fftw_alignment_of to determine the -# alignment of a given pointer modulo whatever FFTW needs; this -# function will be documented in FFTW 3.3.4. - - -if Base.libfftw_name == "libmkl_rt" - alignment_of(A::StridedArray{<:fftwDouble}) = - convert(Int32, convert(Int64, pointer(A)) % 16) - alignment_of(A::StridedArray{<:fftwSingle}) = - convert(Int32, convert(Int64, pointer(A)) % 16) -else - alignment_of(A::StridedArray{T}) where {T<:fftwDouble} = - ccall((:fftw_alignment_of, libfftw), Int32, (Ptr{T},), A) - alignment_of(A::StridedArray{T}) where {T<:fftwSingle} = - ccall((:fftwf_alignment_of, libfftwf), Int32, (Ptr{T},), A) -end - -# FFTWPlan (low-level) - -# low-level storage of the FFTW plan, along with the information -# needed to determine whether it is applicable. We need to put -# this into a type to support a finalizer on the fftw_plan. -# K is FORWARD/BACKWARD for forward/backward or r2c/c2r plans, respectively. -# For r2r plans, K is a tuple of the transform kinds along each dimension. -abstract type FFTWPlan{T<:fftwNumber,K,inplace} <: Plan{T} end -for P in (:cFFTWPlan, :rFFTWPlan, :r2rFFTWPlan) # complex, r2c/c2r, and r2r - @eval begin - mutable struct $P{T<:fftwNumber,K,inplace,N} <: FFTWPlan{T,K,inplace} - plan::PlanPtr - sz::NTuple{N,Int} # size of array on which plan operates (Int tuple) - osz::NTuple{N,Int} # size of output array (Int tuple) - istride::NTuple{N,Int} # strides of input - ostride::NTuple{N,Int} # strides of output - ialign::Int32 # alignment mod 16 of input - oalign::Int32 # alignment mod 16 of input - flags::UInt32 # planner flags - region::Any # region (iterable) of dims that are transormed - pinv::ScaledPlan - function $P{T,K,inplace,N}(plan::PlanPtr, flags::Integer, R::Any, - X::StridedArray{T,N}, Y::StridedArray) where {T<:fftwNumber,K,inplace,N} - p = new(plan, size(X), size(Y), strides(X), strides(Y), - alignment_of(X), alignment_of(Y), flags, R) - finalizer(p, destroy_plan) - p - end - end - end -end - -size(p::FFTWPlan) = p.sz - -unsafe_convert(::Type{PlanPtr}, p::FFTWPlan) = p.plan - -destroy_plan(plan::FFTWPlan{<:fftwDouble}) = - ccall((:fftw_destroy_plan,libfftw), Void, (PlanPtr,), plan) - -destroy_plan(plan::FFTWPlan{<:fftwSingle}) = - ccall((:fftwf_destroy_plan,libfftwf), Void, (PlanPtr,), plan) - -cost(plan::FFTWPlan{<:fftwDouble}) = - ccall((:fftw_cost,libfftw), Float64, (PlanPtr,), plan) -cost(plan::FFTWPlan{<:fftwSingle}) = - ccall((:fftwf_cost,libfftwf), Float64, (PlanPtr,), plan) - -function arithmetic_ops(plan::FFTWPlan{<:fftwDouble}) - # Change to individual Ref after we can allocate them on stack - ref = Ref{NTuple{3,Float64}}() - ptr = Ptr{Float64}(Base.unsafe_convert(Ptr{NTuple{3,Float64}}, ref)) - ccall((:fftw_flops,libfftw), Void, - (PlanPtr,Ptr{Float64},Ptr{Float64},Ptr{Float64}), - plan, ptr, ptr + 8, ptr + 16) - (round(Int64, ref[][1]), round(Int64, ref[][2]), round(Int64, ref[][3])) -end -function arithmetic_ops(plan::FFTWPlan{<:fftwSingle}) - # Change to individual Ref after we can allocate them on stack - ref = Ref{NTuple{3,Float64}}() - ptr = Ptr{Float64}(Base.unsafe_convert(Ptr{NTuple{3,Float64}}, ref)) - ccall((:fftwf_flops,libfftwf), Void, - (PlanPtr,Ptr{Float64},Ptr{Float64},Ptr{Float64}), - plan, ptr, ptr + 8, ptr + 16) - (round(Int64, ref[][1]), round(Int64, ref[][2]), round(Int64, ref[][3])) -end -flops(plan::FFTWPlan) = let ops = arithmetic_ops(plan) - ops[1] + ops[2] + 2 * ops[3] # add + mul + 2*fma -end - -# Pretty-printing plans - -function showfftdims(io, sz::Dims, istride::Dims, T) - if isempty(sz) - print(io, "0-dimensional") - elseif length(sz) == 1 - print(io, sz[1], "-element") - else - print(io, join(sz, "×")) - end - if istride == colmajorstrides(sz) - print(io, " array of ", T) - else - print(io, " $istride-strided array of ", T) - end -end - -# The sprint_plan function was released in FFTW 3.3.4 -sprint_plan_(plan::FFTWPlan{<:fftwDouble}) = - ccall((:fftw_sprint_plan,libfftw), Ptr{UInt8}, (PlanPtr,), plan) -sprint_plan_(plan::FFTWPlan{<:fftwSingle}) = - ccall((:fftwf_sprint_plan,libfftwf), Ptr{UInt8}, (PlanPtr,), plan) -function sprint_plan(plan::FFTWPlan) - p = sprint_plan_(plan) - str = unsafe_string(p) - Libc.free(p) - return str -end - -function show(io::IO, p::cFFTWPlan{T,K,inplace}) where {T,K,inplace} - print(io, inplace ? "FFTW in-place " : "FFTW ", - K < 0 ? "forward" : "backward", " plan for ") - showfftdims(io, p.sz, p.istride, T) - version >= v"3.3.4" && print(io, "\n", sprint_plan(p)) -end - -function show(io::IO, p::rFFTWPlan{T,K,inplace}) where {T,K,inplace} - print(io, inplace ? "FFTW in-place " : "FFTW ", - K < 0 ? "real-to-complex" : "complex-to-real", - " plan for ") - showfftdims(io, p.sz, p.istride, T) - version >= v"3.3.4" && print(io, "\n", sprint_plan(p)) -end - -function show(io::IO, p::r2rFFTWPlan{T,K,inplace}) where {T,K,inplace} - print(io, inplace ? "FFTW in-place r2r " : "FFTW r2r ") - if isempty(K) - print(io, "0-dimensional") - elseif K == ntuple(i -> K[1], length(K)) - print(io, kind2string(K[1])) - if length(K) > 1 - print(io, "^", length(K)) - end - else - print(io, join(map(kind2string, K), "×")) - end - print(io, " plan for ") - showfftdims(io, p.sz, p.istride, T) - version >= v"3.3.4" && print(io, "\n", sprint_plan(p)) -end - -# Check whether a FFTWPlan is applicable to a given input array, and -# throw an informative error if not: -function assert_applicable(p::FFTWPlan{T}, X::StridedArray{T}) where T - if size(X) != p.sz - throw(ArgumentError("FFTW plan applied to wrong-size array")) - elseif strides(X) != p.istride - throw(ArgumentError("FFTW plan applied to wrong-strides array")) - elseif alignment_of(X) != p.ialign || p.flags & UNALIGNED != 0 - throw(ArgumentError("FFTW plan applied to array with wrong memory alignment")) - end -end - -function assert_applicable(p::FFTWPlan{T,K,inplace}, X::StridedArray{T}, Y::StridedArray) where {T,K,inplace} - assert_applicable(p, X) - if size(Y) != p.osz - throw(ArgumentError("FFTW plan applied to wrong-size output")) - elseif strides(Y) != p.ostride - throw(ArgumentError("FFTW plan applied to wrong-strides output")) - elseif alignment_of(Y) != p.oalign || p.flags & UNALIGNED != 0 - throw(ArgumentError("FFTW plan applied to output with wrong memory alignment")) - elseif inplace != (pointer(X) == pointer(Y)) - throw(ArgumentError(string("FFTW ", - inplace ? "in-place" : "out-of-place", - " plan applied to ", - inplace ? "out-of-place" : "in-place", - " data"))) - end -end - -# strides for a column-major (Julia-style) array of size == sz -colmajorstrides(sz) = isempty(sz) ? () : (1,cumprod(Int[sz[1:end-1]...])...) - -# Execute - -unsafe_execute!(plan::FFTWPlan{<:fftwDouble}) = - ccall((:fftw_execute,libfftw), Void, (PlanPtr,), plan) - -unsafe_execute!(plan::FFTWPlan{<:fftwSingle}) = - ccall((:fftwf_execute,libfftwf), Void, (PlanPtr,), plan) - -unsafe_execute!(plan::cFFTWPlan{T}, - X::StridedArray{T}, Y::StridedArray{T}) where {T<:fftwDouble} = - ccall((:fftw_execute_dft,libfftw), Void, - (PlanPtr,Ptr{T},Ptr{T}), plan, X, Y) - -unsafe_execute!(plan::cFFTWPlan{T}, - X::StridedArray{T}, Y::StridedArray{T}) where {T<:fftwSingle} = - ccall((:fftwf_execute_dft,libfftwf), Void, - (PlanPtr,Ptr{T},Ptr{T}), plan, X, Y) - -unsafe_execute!(plan::rFFTWPlan{Float64,FORWARD}, - X::StridedArray{Float64}, Y::StridedArray{Complex128}) = - ccall((:fftw_execute_dft_r2c,libfftw), Void, - (PlanPtr,Ptr{Float64},Ptr{Complex128}), plan, X, Y) - -unsafe_execute!(plan::rFFTWPlan{Float32,FORWARD}, - X::StridedArray{Float32}, Y::StridedArray{Complex64}) = - ccall((:fftwf_execute_dft_r2c,libfftwf), Void, - (PlanPtr,Ptr{Float32},Ptr{Complex64}), plan, X, Y) - -unsafe_execute!(plan::rFFTWPlan{Complex128,BACKWARD}, - X::StridedArray{Complex128}, Y::StridedArray{Float64}) = - ccall((:fftw_execute_dft_c2r,libfftw), Void, - (PlanPtr,Ptr{Complex128},Ptr{Float64}), plan, X, Y) - -unsafe_execute!(plan::rFFTWPlan{Complex64,BACKWARD}, - X::StridedArray{Complex64}, Y::StridedArray{Float32}) = - ccall((:fftwf_execute_dft_c2r,libfftwf), Void, - (PlanPtr,Ptr{Complex64},Ptr{Float32}), plan, X, Y) - -unsafe_execute!(plan::r2rFFTWPlan{T}, - X::StridedArray{T}, Y::StridedArray{T}) where {T<:fftwDouble} = - ccall((:fftw_execute_r2r,libfftw), Void, - (PlanPtr,Ptr{T},Ptr{T}), plan, X, Y) - -unsafe_execute!(plan::r2rFFTWPlan{T}, - X::StridedArray{T}, Y::StridedArray{T}) where {T<:fftwSingle} = - ccall((:fftwf_execute_r2r,libfftwf), Void, - (PlanPtr,Ptr{T},Ptr{T}), plan, X, Y) - -# NOTE ON GC (garbage collection): -# The FFTWPlan has a finalizer so that gc will destroy the plan, -# which is necessary for gc to work with plan_fft. However, -# even when we are creating a single-use FFTWPlan [e.g. for fftn(x)], -# we intentionally do NOT call destroy_plan explicitly, and instead -# wait for garbage collection. The reason is that, in the common -# case where the user calls fft(x) a second time soon afterwards, -# if destroy_plan has not yet been called then FFTW will internally -# re-use the table of trigonometric constants from the first plan. - -# Compute dims and howmany for FFTW guru planner -function dims_howmany(X::StridedArray, Y::StridedArray, - sz::Array{Int,1}, region) - reg = [region...] - if length(unique(reg)) < length(reg) - throw(ArgumentError("each dimension can be transformed at most once")) - end - ist = [strides(X)...] - ost = [strides(Y)...] - dims = [sz[reg] ist[reg] ost[reg]]' - oreg = [1:ndims(X);] - oreg[reg] = 0 - oreg = filter(d -> d > 0, oreg) - howmany = [sz[oreg] ist[oreg] ost[oreg]]' - return (dims, howmany) -end - -# check & convert kinds into int32 array with same length as region -function fix_kinds(region, kinds) - if length(kinds) != length(region) - if length(kinds) > length(region) - throw(ArgumentError("too many transform kinds")) - else - if isempty(kinds) - throw(ArgumentError("must supply a transform kind")) - end - k = Vector{Int32}(length(region)) - k[1:length(kinds)] = [kinds...] - k[length(kinds)+1:end] = kinds[end] - kinds = k - end - else - kinds = Int32[kinds...] - end - for i = 1:length(kinds) - if kinds[i] < 0 || kinds[i] > 10 - throw(ArgumentError("invalid transform kind")) - end - end - return kinds -end - -# low-level FFTWPlan creation (for internal use in FFTW module) - -for (Tr,Tc,fftw,lib) in ((:Float64,:Complex128,"fftw",libfftw), - (:Float32,:Complex64,"fftwf",libfftwf)) - @eval function (::Type{cFFTWPlan{$Tc,K,inplace,N}})(X::StridedArray{$Tc,N}, - Y::StridedArray{$Tc,N}, - region, flags::Integer, timelimit::Real) where {K,inplace,N} - direction = K - set_timelimit($Tr, timelimit) - R = isa(region, Tuple) ? region : copy(region) - dims, howmany = dims_howmany(X, Y, [size(X)...], R) - plan = ccall(($(string(fftw,"_plan_guru64_dft")),$lib), - PlanPtr, - (Int32, Ptr{Int}, Int32, Ptr{Int}, - Ptr{$Tc}, Ptr{$Tc}, Int32, UInt32), - size(dims,2), dims, size(howmany,2), howmany, - X, Y, direction, flags) - set_timelimit($Tr, NO_TIMELIMIT) - if plan == C_NULL - error("FFTW could not create plan") # shouldn't normally happen - end - return cFFTWPlan{$Tc,K,inplace,N}(plan, flags, R, X, Y) - end - - @eval function (::Type{rFFTWPlan{$Tr,$FORWARD,inplace,N}})(X::StridedArray{$Tr,N}, - Y::StridedArray{$Tc,N}, - region, flags::Integer, timelimit::Real) where {inplace,N} - R = isa(region, Tuple) ? region : copy(region) - region = circshift([region...],-1) # FFTW halves last dim - set_timelimit($Tr, timelimit) - dims, howmany = dims_howmany(X, Y, [size(X)...], region) - plan = ccall(($(string(fftw,"_plan_guru64_dft_r2c")),$lib), - PlanPtr, - (Int32, Ptr{Int}, Int32, Ptr{Int}, - Ptr{$Tr}, Ptr{$Tc}, UInt32), - size(dims,2), dims, size(howmany,2), howmany, - X, Y, flags) - set_timelimit($Tr, NO_TIMELIMIT) - if plan == C_NULL - error("FFTW could not create plan") # shouldn't normally happen - end - return rFFTWPlan{$Tr,$FORWARD,inplace,N}(plan, flags, R, X, Y) - end - - @eval function (::Type{rFFTWPlan{$Tc,$BACKWARD,inplace,N}})(X::StridedArray{$Tc,N}, - Y::StridedArray{$Tr,N}, - region, flags::Integer, timelimit::Real) where {inplace,N} - R = isa(region, Tuple) ? region : copy(region) - region = circshift([region...],-1) # FFTW halves last dim - set_timelimit($Tr, timelimit) - dims, howmany = dims_howmany(X, Y, [size(Y)...], region) - plan = ccall(($(string(fftw,"_plan_guru64_dft_c2r")),$lib), - PlanPtr, - (Int32, Ptr{Int}, Int32, Ptr{Int}, - Ptr{$Tc}, Ptr{$Tr}, UInt32), - size(dims,2), dims, size(howmany,2), howmany, - X, Y, flags) - set_timelimit($Tr, NO_TIMELIMIT) - if plan == C_NULL - error("FFTW could not create plan") # shouldn't normally happen - end - return rFFTWPlan{$Tc,$BACKWARD,inplace,N}(plan, flags, R, X, Y) - end - - @eval function (::Type{r2rFFTWPlan{$Tr,ANY,inplace,N}})(X::StridedArray{$Tr,N}, - Y::StridedArray{$Tr,N}, - region, kinds, flags::Integer, - timelimit::Real) where {inplace,N} - R = isa(region, Tuple) ? region : copy(region) - knd = fix_kinds(region, kinds) - set_timelimit($Tr, timelimit) - dims, howmany = dims_howmany(X, Y, [size(X)...], region) - plan = ccall(($(string(fftw,"_plan_guru64_r2r")),$lib), - PlanPtr, - (Int32, Ptr{Int}, Int32, Ptr{Int}, - Ptr{$Tr}, Ptr{$Tr}, Ptr{Int32}, UInt32), - size(dims,2), dims, size(howmany,2), howmany, - X, Y, knd, flags) - set_timelimit($Tr, NO_TIMELIMIT) - if plan == C_NULL - error("FFTW could not create plan") # shouldn't normally happen - end - r2rFFTWPlan{$Tr,(map(Int,knd)...),inplace,N}(plan, flags, R, X, Y) - end - - # support r2r transforms of complex = transforms of real & imag parts - @eval function (::Type{r2rFFTWPlan{$Tc,ANY,inplace,N}})(X::StridedArray{$Tc,N}, - Y::StridedArray{$Tc,N}, - region, kinds, flags::Integer, - timelimit::Real) where {inplace,N} - R = isa(region, Tuple) ? region : copy(region) - knd = fix_kinds(region, kinds) - set_timelimit($Tr, timelimit) - dims, howmany = dims_howmany(X, Y, [size(X)...], region) - dims[2:3, 1:size(dims,2)] *= 2 - howmany[2:3, 1:size(howmany,2)] *= 2 - howmany = [howmany [2,1,1]] # append loop over real/imag parts - plan = ccall(($(string(fftw,"_plan_guru64_r2r")),$lib), - PlanPtr, - (Int32, Ptr{Int}, Int32, Ptr{Int}, - Ptr{$Tc}, Ptr{$Tc}, Ptr{Int32}, UInt32), - size(dims,2), dims, size(howmany,2), howmany, - X, Y, knd, flags) - set_timelimit($Tr, NO_TIMELIMIT) - if plan == C_NULL - error("FFTW could not create plan") # shouldn't normally happen - end - r2rFFTWPlan{$Tc,(map(Int,knd)...),inplace,N}(plan, flags, R, X, Y) - end - -end - -# Convert arrays of numeric types to FFTW-supported packed complex-float types -# (FIXME: is there a way to use the Julia promotion rules more cleverly here?) -fftwcomplex(X::StridedArray{<:fftwComplex}) = X -fftwcomplex(X::AbstractArray{T}) where {T<:fftwReal} = - copy!(Array{typeof(complex(zero(T)))}(size(X)), X) -fftwcomplex(X::AbstractArray{<:Real}) = copy!(Array{Complex128}(size(X)),X) -fftwcomplex(X::AbstractArray{<:Complex}) = copy!(Array{Complex128}(size(X)), X) -fftwfloat(X::StridedArray{<:fftwReal}) = X -fftwfloat(X::AbstractArray{<:Real}) = copy!(Array{Float64}(size(X)), X) -fftwfloat(X::AbstractArray{<:Complex}) = fftwcomplex(X) - -for (f,direction) in ((:fft,FORWARD), (:bfft,BACKWARD)) - plan_f = Symbol("plan_",f) - plan_f! = Symbol("plan_",f,"!") - idirection = -direction - @eval begin - function $plan_f(X::StridedArray{T,N}, region; - flags::Integer=ESTIMATE, - timelimit::Real=NO_TIMELIMIT) where {T<:fftwComplex,N} - cFFTWPlan{T,$direction,false,N}(X, fakesimilar(flags, X, T), - region, flags, timelimit) - end - - function $plan_f!(X::StridedArray{T,N}, region; - flags::Integer=ESTIMATE, - timelimit::Real=NO_TIMELIMIT) where {T<:fftwComplex,N} - cFFTWPlan{T,$direction,true,N}(X, X, region, flags, timelimit) - end - $plan_f(X::StridedArray{<:fftwComplex}; kws...) = - $plan_f(X, 1:ndims(X); kws...) - $plan_f!(X::StridedArray{<:fftwComplex}; kws...) = - $plan_f!(X, 1:ndims(X); kws...) - - function plan_inv(p::cFFTWPlan{T,$direction,inplace,N}) where {T<:fftwComplex,N,inplace} - X = Array{T}(p.sz) - Y = inplace ? X : fakesimilar(p.flags, X, T) - ScaledPlan(cFFTWPlan{T,$idirection,inplace,N}(X, Y, p.region, - p.flags, NO_TIMELIMIT), - normalization(X, p.region)) - end - end -end - -function A_mul_B!(y::StridedArray{T}, p::cFFTWPlan{T}, x::StridedArray{T}) where T - assert_applicable(p, x, y) - unsafe_execute!(p, x, y) - return y -end - -function *(p::cFFTWPlan{T,K,false}, x::StridedArray{T,N}) where {T,K,N} - assert_applicable(p, x) - y = Array{T}(p.osz)::Array{T,N} - unsafe_execute!(p, x, y) - return y -end - -function *(p::cFFTWPlan{T,K,true}, x::StridedArray{T}) where {T,K} - assert_applicable(p, x) - unsafe_execute!(p, x, x) - return x -end - -# rfft/brfft and planned variants. No in-place version for now. - -for (Tr,Tc) in ((:Float32,:Complex64),(:Float64,:Complex128)) - # Note: use $FORWARD and $BACKWARD below because of issue #9775 - @eval begin - function plan_rfft(X::StridedArray{$Tr,N}, region; - flags::Integer=ESTIMATE, - timelimit::Real=NO_TIMELIMIT) where N - osize = rfft_output_size(X, region) - Y = flags&ESTIMATE != 0 ? FakeArray($Tc,osize...) : Array{$Tc}(osize...) - rFFTWPlan{$Tr,$FORWARD,false,N}(X, Y, region, flags, timelimit) - end - - function plan_brfft(X::StridedArray{$Tc,N}, d::Integer, region; - flags::Integer=ESTIMATE, - timelimit::Real=NO_TIMELIMIT) where N - osize = brfft_output_size(X, d, region) - Y = flags&ESTIMATE != 0 ? FakeArray($Tr,osize...) : Array{$Tr}(osize...) - - # FFTW currently doesn't support PRESERVE_INPUT for - # multidimensional out-of-place c2r transforms, so - # we have to handle 1d and >1d cases separately with a copy. Ugh. - if length(region) <= 1 - rFFTWPlan{$Tc,$BACKWARD,false,N}(X, Y, region, - flags | PRESERVE_INPUT, - timelimit) - else - rFFTWPlan{$Tc,$BACKWARD,false,N}(copy(X), Y, region, flags, - timelimit) - end - end - - plan_rfft(X::StridedArray{$Tr};kws...)=plan_rfft(X,1:ndims(X);kws...) - plan_brfft(X::StridedArray{$Tr};kws...)=plan_brfft(X,1:ndims(X);kws...) - - function plan_inv(p::rFFTWPlan{$Tr,$FORWARD,false,N}) where N - X = Array{$Tr}(p.sz) - Y = p.flags&ESTIMATE != 0 ? FakeArray($Tc,p.osz) : Array{$Tc}(p.osz) - ScaledPlan(rFFTWPlan{$Tc,$BACKWARD,false,N}(Y, X, p.region, - length(p.region) <= 1 ? - p.flags | PRESERVE_INPUT : - p.flags, NO_TIMELIMIT), - normalization(X, p.region)) - end - - function plan_inv(p::rFFTWPlan{$Tc,$BACKWARD,false,N}) where N - X = Arra{$Tc}(p.sz) - Y = p.flags&ESTIMATE != 0 ? FakeArray($Tr,p.osz) : Array{$Tr}(p.osz) - ScaledPlan(rFFTWPlan{$Tr,$FORWARD,false,N}(Y, X, p.region, - p.flags, NO_TIMELIMIT), - normalization(Y, p.region)) - end - - function A_mul_B!(y::StridedArray{$Tc}, p::rFFTWPlan{$Tr,$FORWARD}, x::StridedArray{$Tr}) - assert_applicable(p, x, y) - unsafe_execute!(p, x, y) - return y - end - function A_mul_B!(y::StridedArray{$Tr}, p::rFFTWPlan{$Tc,$BACKWARD}, x::StridedArray{$Tc}) - assert_applicable(p, x, y) - unsafe_execute!(p, x, y) # note: may overwrite x as well as y! - return y - end - - function *(p::rFFTWPlan{$Tr,$FORWARD,false}, x::StridedArray{$Tr,N}) where N - assert_applicable(p, x) - y = Array{$Tc}(p.osz)::Array{$Tc,N} - unsafe_execute!(p, x, y) - return y - end - - function *(p::rFFTWPlan{$Tc,$BACKWARD,false}, x::StridedArray{$Tc,N}) where N - if p.flags & PRESERVE_INPUT != 0 - assert_applicable(p, x) - y = Array{$Tr}(p.osz)::Array{$Tr,N} - unsafe_execute!(p, x, y) - else # need to make a copy to avoid overwriting x - xc = copy(x) - assert_applicable(p, xc) - y = Array{$Tr}(p.osz)::Array{$Tr,N} - unsafe_execute!(p, xc, y) - end - return y - end - end -end - -# FFTW r2r transforms (low-level interface) - -for f in (:r2r, :r2r!) - pf = Symbol("plan_", f) - @eval begin - $f(x::AbstractArray{<:fftwNumber}, kinds) = $pf(x, kinds) * x - $f(x::AbstractArray{<:fftwNumber}, kinds, region) = $pf(x, kinds, region) * x - $pf(x::AbstractArray, kinds; kws...) = $pf(x, kinds, 1:ndims(x); kws...) - $f(x::AbstractArray{<:Real}, kinds, region=1:ndims(x)) = $f(fftwfloat(x), kinds, region) - $pf(x::AbstractArray{<:Real}, kinds, region; kws...) = $pf(fftwfloat(x), kinds, region; kws...) - $f(x::AbstractArray{<:Complex}, kinds, region=1:ndims(x)) = $f(fftwcomplex(x), kinds, region) - $pf(x::AbstractArray{<:Complex}, kinds, region; kws...) = $pf(fftwcomplex(x), kinds, region; kws...) - end -end - -function plan_r2r(X::StridedArray{T,N}, kinds, region; - flags::Integer=ESTIMATE, - timelimit::Real=NO_TIMELIMIT) where {T<:fftwNumber,N} - r2rFFTWPlan{T,ANY,false,N}(X, fakesimilar(flags, X, T), region, kinds, - flags, timelimit) -end - -function plan_r2r!(X::StridedArray{T,N}, kinds, region; - flags::Integer=ESTIMATE, - timelimit::Real=NO_TIMELIMIT) where {T<:fftwNumber,N} - r2rFFTWPlan{T,ANY,true,N}(X, X, region, kinds, flags, timelimit) -end - -# mapping from r2r kind to the corresponding inverse transform -const inv_kind = Dict{Int,Int}(R2HC => HC2R, HC2R => R2HC, DHT => DHT, - REDFT00 => REDFT00, - REDFT01 => REDFT10, REDFT10 => REDFT01, - REDFT11 => REDFT11, - RODFT00 => RODFT00, - RODFT01 => RODFT10, RODFT10 => RODFT01, - RODFT11 => RODFT11) - -# r2r inverses are normalized to 1/N, where N is a "logical" size -# the transform with length n and kind k: -function logical_size(n::Integer, k::Integer) - k <= DHT && return n - k == REDFT00 && return 2(n-1) - k == RODFT00 && return 2(n+1) - return 2n -end - -function plan_inv(p::r2rFFTWPlan{T,K,inplace,N}) where {T<:fftwNumber,K,inplace,N} - X = Array{T}(p.sz) - iK = fix_kinds(p.region, [inv_kind[k] for k in K]) - Y = inplace ? X : fakesimilar(p.flags, X, T) - ScaledPlan(r2rFFTWPlan{T,ANY,inplace,N}(X, Y, p.region, iK, - p.flags, NO_TIMELIMIT), - normalization(real(T), - map(logical_size, [p.sz...][[p.region...]], iK), - 1:length(iK))) -end - -function A_mul_B!(y::StridedArray{T}, p::r2rFFTWPlan{T}, x::StridedArray{T}) where T - assert_applicable(p, x, y) - unsafe_execute!(p, x, y) - return y -end - -function *(p::r2rFFTWPlan{T,K,false}, x::StridedArray{T,N}) where {T,K,N} - assert_applicable(p, x) - y = Array{T}(p.osz)::Array{T,N} - unsafe_execute!(p, x, y) - return y -end - -function *(p::r2rFFTWPlan{T,K,true}, x::StridedArray{T}) where {T,K} - assert_applicable(p, x) - unsafe_execute!(p, x, x) - return x -end - -include("dct.jl") diff --git a/base/fft/dct.jl b/base/fft/dct.jl deleted file mode 100644 index a3410961a7f89..0000000000000 --- a/base/fft/dct.jl +++ /dev/null @@ -1,103 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -# (This is part of the FFTW module.) - -export dct, idct, dct!, idct!, plan_dct, plan_idct, plan_dct!, plan_idct! - -# Discrete cosine transforms (type II/III) via FFTW's r2r transforms; -# we follow the Matlab convention and adopt a unitary normalization here. -# Unlike Matlab we compute the multidimensional transform by default, -# similar to the Julia fft functions. - -mutable struct DCTPlan{T<:fftwNumber,K,inplace} <: Plan{T} - plan::r2rFFTWPlan{T} - r::Array{UnitRange{Int}} # array of indices for rescaling - nrm::Float64 # normalization factor - region::Dims # dimensions being transformed - pinv::DCTPlan{T} - DCTPlan{T,K,inplace}(plan,r,nrm,region) where {T<:fftwNumber,K,inplace} = new(plan,r,nrm,region) -end - -size(p::DCTPlan) = size(p.plan) - -function show(io::IO, p::DCTPlan{T,K,inplace}) where {T,K,inplace} - print(io, inplace ? "FFTW in-place " : "FFTW ", - K == REDFT10 ? "DCT (DCT-II)" : "IDCT (DCT-III)", " plan for ") - showfftdims(io, p.plan.sz, p.plan.istride, eltype(p)) -end - -for (pf, pfr, K, inplace) in ((:plan_dct, :plan_r2r, REDFT10, false), - (:plan_dct!, :plan_r2r!, REDFT10, true), - (:plan_idct, :plan_r2r, REDFT01, false), - (:plan_idct!, :plan_r2r!, REDFT01, true)) - @eval function $pf(X::StridedArray{T}, region; kws...) where T<:fftwNumber - r = [1:n for n in size(X)] - nrm = sqrt(0.5^length(region) * normalization(X,region)) - DCTPlan{T,$K,$inplace}($pfr(X, $K, region; kws...), r, nrm, - ntuple(i -> Int(region[i]), length(region))) - end -end - -function plan_inv(p::DCTPlan{T,K,inplace}) where {T,K,inplace} - X = Array{T}(p.plan.sz) - iK = inv_kind[K] - DCTPlan{T,iK,inplace}(inplace ? - plan_r2r!(X, iK, p.region, flags=p.plan.flags) : - plan_r2r(X, iK, p.region, flags=p.plan.flags), - p.r, p.nrm, p.region) -end - -for f in (:dct, :dct!, :idct, :idct!) - pf = Symbol("plan_", f) - @eval begin - $f(x::AbstractArray{<:fftwNumber}) = $pf(x) * x - $f(x::AbstractArray{<:fftwNumber}, region) = $pf(x, region) * x - $pf(x::AbstractArray; kws...) = $pf(x, 1:ndims(x); kws...) - $f(x::AbstractArray{<:Real}, region=1:ndims(x)) = $f(fftwfloat(x), region) - $pf(x::AbstractArray{<:Real}, region; kws...) = $pf(fftwfloat(x), region; kws...) - $pf(x::AbstractArray{<:Complex}, region; kws...) = $pf(fftwcomplex(x), region; kws...) - end -end - -const sqrthalf = sqrt(0.5) -const sqrt2 = sqrt(2.0) -const onerange = 1:1 - -function A_mul_B!(y::StridedArray{T}, p::DCTPlan{T,REDFT10}, - x::StridedArray{T}) where T - assert_applicable(p.plan, x, y) - unsafe_execute!(p.plan, x, y) - scale!(y, p.nrm) - r = p.r - for d in p.region - oldr = r[d] - r[d] = onerange - y[r...] *= sqrthalf - r[d] = oldr - end - return y -end - -# note: idct changes input data -function A_mul_B!(y::StridedArray{T}, p::DCTPlan{T,REDFT01}, - x::StridedArray{T}) where T - assert_applicable(p.plan, x, y) - scale!(x, p.nrm) - r = p.r - for d in p.region - oldr = r[d] - r[d] = onerange - x[r...] *= sqrt2 - r[d] = oldr - end - unsafe_execute!(p.plan, x, y) - return y -end - -*(p::DCTPlan{T,REDFT10,false}, x::StridedArray{T}) where {T} = - A_mul_B!(Array{T}(p.plan.osz), p, x) - -*(p::DCTPlan{T,REDFT01,false}, x::StridedArray{T}) where {T} = - A_mul_B!(Array{T}(p.plan.osz), p, copy(x)) # need copy to preserve input - -*(p::DCTPlan{T,K,true}, x::StridedArray{T}) where {T,K} = A_mul_B!(x, p, x) diff --git a/base/sysimg.jl b/base/sysimg.jl index 280d26e4c16b3..b7ce80453a33e 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -382,12 +382,6 @@ const × = cross # statistics include("statistics.jl") -# signal processing -include("dft.jl") -importall .DFT -include("dsp.jl") -importall .DSP - # libgit2 support include("libgit2/libgit2.jl") diff --git a/base/util.jl b/base/util.jl index 1617b3d6c5df1..bcc4efe47637a 100644 --- a/base/util.jl +++ b/base/util.jl @@ -382,14 +382,6 @@ macro timed(ex) end end -function fftw_vendor() - if Base.libfftw_name in ("libmkl_rt", "mkl_rt") - return :mkl - else - return :fftw - end -end - ## printing with color ## diff --git a/contrib/julia.lang b/contrib/julia.lang index 80dff29ce6057..616e635de90af 100644 --- a/contrib/julia.lang +++ b/contrib/julia.lang @@ -219,7 +219,6 @@ Core Main - FFTW Collections Test Pkg diff --git a/contrib/julia.xml b/contrib/julia.xml index 978dc6e0b726e..577fc37de5d62 100644 --- a/contrib/julia.xml +++ b/contrib/julia.xml @@ -263,7 +263,6 @@ TypeError Collections - FFTW Order Sys Test diff --git a/contrib/mac/macports.make b/contrib/mac/macports.make index f99927ea90cfb..c4b32b2157d1b 100644 --- a/contrib/mac/macports.make +++ b/contrib/mac/macports.make @@ -22,7 +22,6 @@ JMAKEFLAGS = USE_SYSTEM_LLVM=1 LLVM_CONFIG=${LLVM_CONFIG} \ USE_SYSTEM_OPENLIBM=0 \ USE_SYSTEM_BLAS=1 USE_BLAS64=0\ USE_SYSTEM_LAPACK=1 \ - USE_SYSTEM_FFTW=1 \ USE_SYSTEM_GMP=1 \ USE_SYSTEM_MPFR=1 \ USE_SYSTEM_ARPACK=1 \ diff --git a/contrib/vagrant/Vagrantfile b/contrib/vagrant/Vagrantfile index 5ce593eb28655..d59ce3ee39a07 100644 --- a/contrib/vagrant/Vagrantfile +++ b/contrib/vagrant/Vagrantfile @@ -5,7 +5,7 @@ $script = <